Commit 0bacd1300dbcd7f56bdbf1ca73438b6a68c31b8f
1 parent
6f484e73
Handle suspend in qemu (Gleb Natapov)
Reset a PC and tell BIOS that resume from ram is required on the next boot. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6080 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
32 additions
and
0 deletions
hw/acpi.c
... | ... | @@ -53,6 +53,8 @@ typedef struct PIIX4PMState { |
53 | 53 | qemu_irq irq; |
54 | 54 | } PIIX4PMState; |
55 | 55 | |
56 | +#define RSM_STS (1 << 15) | |
57 | +#define PWRBTN_STS (1 << 8) | |
56 | 58 | #define RTC_EN (1 << 10) |
57 | 59 | #define PWRBTN_EN (1 << 8) |
58 | 60 | #define GBL_EN (1 << 5) |
... | ... | @@ -151,6 +153,14 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) |
151 | 153 | case 0: /* soft power off */ |
152 | 154 | qemu_system_shutdown_request(); |
153 | 155 | break; |
156 | + case 1: | |
157 | + /* RSM_STS should be set on resume. Pretend that resume | |
158 | + was caused by power button */ | |
159 | + s->pmsts |= (RSM_STS | PWRBTN_STS); | |
160 | + qemu_system_reset_request(); | |
161 | +#if defined(TARGET_I386) | |
162 | + cmos_set_s3_resume(); | |
163 | +#endif | |
154 | 164 | default: |
155 | 165 | break; |
156 | 166 | } |
... | ... | @@ -471,6 +481,17 @@ static int pm_load(QEMUFile* f,void* opaque,int version_id) |
471 | 481 | return 0; |
472 | 482 | } |
473 | 483 | |
484 | +static void piix4_reset(void *opaque) | |
485 | +{ | |
486 | + PIIX4PMState *s = opaque; | |
487 | + uint8_t *pci_conf = s->dev.config; | |
488 | + | |
489 | + pci_conf[0x58] = 0; | |
490 | + pci_conf[0x59] = 0; | |
491 | + pci_conf[0x5a] = 0; | |
492 | + pci_conf[0x5b] = 0; | |
493 | +} | |
494 | + | |
474 | 495 | i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, |
475 | 496 | qemu_irq sci_irq) |
476 | 497 | { |
... | ... | @@ -527,6 +548,8 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, |
527 | 548 | |
528 | 549 | s->smbus = i2c_init_bus(); |
529 | 550 | s->irq = sci_irq; |
551 | + qemu_register_reset(piix4_reset, s); | |
552 | + | |
530 | 553 | return s->smbus; |
531 | 554 | } |
532 | 555 | ... | ... |
hw/pc.c
... | ... | @@ -1135,6 +1135,14 @@ static void pc_init_isa(ram_addr_t ram_size, int vga_ram_size, |
1135 | 1135 | initrd_filename, 0, cpu_model); |
1136 | 1136 | } |
1137 | 1137 | |
1138 | +/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE) | |
1139 | + BIOS will read it and start S3 resume at POST Entry */ | |
1140 | +void cmos_set_s3_resume(void) | |
1141 | +{ | |
1142 | + if (rtc_state) | |
1143 | + rtc_set_memory(rtc_state, 0xF, 0xFE); | |
1144 | +} | |
1145 | + | |
1138 | 1146 | QEMUMachine pc_machine = { |
1139 | 1147 | .name = "pc", |
1140 | 1148 | .desc = "Standard PC", | ... | ... |
hw/pc.h
... | ... | @@ -82,6 +82,7 @@ RTCState *rtc_init(int base, qemu_irq irq); |
82 | 82 | RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq); |
83 | 83 | void rtc_set_memory(RTCState *s, int addr, int val); |
84 | 84 | void rtc_set_date(RTCState *s, const struct tm *tm); |
85 | +void cmos_set_s3_resume(void); | |
85 | 86 | |
86 | 87 | /* pc.c */ |
87 | 88 | extern int fd_bootchk; | ... | ... |