On Sun, Aug 22, 2010 at 09:19:59PM +0300, Gleb Natapov wrote:
On Sun, Aug 22, 2010 at 01:25:10PM -0400, Kevin O'Connor wrote:
Anyone know of a way to reliably hard reset qemu?
kbd controller and triple fault should do hard reset on qemu. All devices and cpu are reset. Why do you think you see soft reset?
The reset did not reset the ram at 0xc0000-0xfffff, and so it just infinitely loops. (The code I used is below.)
-Kevin
diff --git a/src/ioport.h b/src/ioport.h index ba099a7..5bd7f28 100644 --- a/src/ioport.h +++ b/src/ioport.h @@ -50,6 +50,7 @@ #define PORT_FD_DIR 0x03f7 #define PORT_SERIAL1 0x03f8 #define PORT_PCI_CMD 0x0cf8 +#define PORT_PCI_REBOOT 0x0cf9 #define PORT_PCI_DATA 0x0cfc #define PORT_BIOS_DEBUG 0x0402 #define PORT_QEMU_CFG_CTL 0x0510 diff --git a/src/pci.c b/src/pci.c index 611d0e2..115689d 100644 --- a/src/pci.c +++ b/src/pci.c @@ -215,3 +215,13 @@ int pci_find_init_device(const struct pci_device_id *ids, void *arg) } return -1; } + +void +pci_reboot(void) +{ + u8 v = inb(PORT_PCI_REBOOT) & ~6; + outb(v|2, PORT_PCI_REBOOT); /* Request hard reset */ + udelay(50); + outb(v|6, PORT_PCI_REBOOT); /* Actually do the reset */ + udelay(50); +} diff --git a/src/pci.h b/src/pci.h index 9c3108c..64bd43b 100644 --- a/src/pci.h +++ b/src/pci.h @@ -94,6 +94,7 @@ struct pci_device_id {
int pci_init_device(const struct pci_device_id *table, u16 bdf, void *arg); int pci_find_init_device(const struct pci_device_id *ids, void *arg); +void pci_reboot(void);
// pirtable.c void create_pirtable(void); diff --git a/src/post.c b/src/post.c index 56e5eb5..eb7bdcb 100644 --- a/src/post.c +++ b/src/post.c @@ -244,6 +244,8 @@ post(void) memmap_finalize(); }
+int HaveRunPost; + // 32-bit entry point. void VISIBLE32FLAT _start(void) @@ -253,9 +255,27 @@ _start(void) debug_serial_setup(); dprintf(1, "Start bios (version %s)\n", VERSION);
+ if (HaveRunPost) { + // This is a soft reboot - invoke a hard reboot. + dprintf(1, "Attempting a hard reboot\n"); + + // Try PCI 0xcf9 reboot + pci_reboot(); + + // Try keyboard controller reboot. + i8042_reboot(); + + // Try triple fault + asm volatile("int3"); + + panic("Could not reboot"); + } + // Allow writes to modify bios area (0xf0000) make_bios_writable();
+ HaveRunPost = 1; + // Perform main setup code. post();
diff --git a/src/ps2port.c b/src/ps2port.c index ccbd2f6..d1e6d48 100644 --- a/src/ps2port.c +++ b/src/ps2port.c @@ -51,7 +51,7 @@ i8042_wait_write(void) return -1; }
-int +static int i8042_flush(void) { dprintf(7, "i8042_flush\n"); @@ -102,7 +102,7 @@ __i8042_command(int command, u8 *param) return 0; }
-int +static int i8042_command(int command, u8 *param) { dprintf(7, "i8042_command cmd=%x\n", command); @@ -128,6 +128,18 @@ i8042_aux_write(u8 c) return i8042_command(I8042_CMD_AUX_SEND, &c); }
+void +i8042_reboot(void) +{ + int i; + for (i=0; i<10; i++) { + i8042_wait_write(); + udelay(50); + outb(0xfe, PORT_PS2_STATUS); /* pulse reset low */ + udelay(50); + } +} +
/**************************************************************** * Device commands. diff --git a/src/ps2port.h b/src/ps2port.h index afb0e78..dcae391 100644 --- a/src/ps2port.h +++ b/src/ps2port.h @@ -55,8 +55,7 @@ #define I8042_CTR_XLATE 0x40
// functions -int i8042_flush(void); -int i8042_command(int command, u8 *param); +void i8042_reboot(void); int ps2_kbd_command(int command, u8 *param); int ps2_mouse_command(int command, u8 *param); void ps2port_setup(void);