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,6 +53,8 @@ typedef struct PIIX4PMState { | ||
| 53 | qemu_irq irq; | 53 | qemu_irq irq; |
| 54 | } PIIX4PMState; | 54 | } PIIX4PMState; |
| 55 | 55 | ||
| 56 | +#define RSM_STS (1 << 15) | ||
| 57 | +#define PWRBTN_STS (1 << 8) | ||
| 56 | #define RTC_EN (1 << 10) | 58 | #define RTC_EN (1 << 10) |
| 57 | #define PWRBTN_EN (1 << 8) | 59 | #define PWRBTN_EN (1 << 8) |
| 58 | #define GBL_EN (1 << 5) | 60 | #define GBL_EN (1 << 5) |
| @@ -151,6 +153,14 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) | @@ -151,6 +153,14 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) | ||
| 151 | case 0: /* soft power off */ | 153 | case 0: /* soft power off */ |
| 152 | qemu_system_shutdown_request(); | 154 | qemu_system_shutdown_request(); |
| 153 | break; | 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 | default: | 164 | default: |
| 155 | break; | 165 | break; |
| 156 | } | 166 | } |
| @@ -471,6 +481,17 @@ static int pm_load(QEMUFile* f,void* opaque,int version_id) | @@ -471,6 +481,17 @@ static int pm_load(QEMUFile* f,void* opaque,int version_id) | ||
| 471 | return 0; | 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 | i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, | 495 | i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, |
| 475 | qemu_irq sci_irq) | 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,6 +548,8 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, | ||
| 527 | 548 | ||
| 528 | s->smbus = i2c_init_bus(); | 549 | s->smbus = i2c_init_bus(); |
| 529 | s->irq = sci_irq; | 550 | s->irq = sci_irq; |
| 551 | + qemu_register_reset(piix4_reset, s); | ||
| 552 | + | ||
| 530 | return s->smbus; | 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,6 +1135,14 @@ static void pc_init_isa(ram_addr_t ram_size, int vga_ram_size, | ||
| 1135 | initrd_filename, 0, cpu_model); | 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 | QEMUMachine pc_machine = { | 1146 | QEMUMachine pc_machine = { |
| 1139 | .name = "pc", | 1147 | .name = "pc", |
| 1140 | .desc = "Standard PC", | 1148 | .desc = "Standard PC", |
hw/pc.h
| @@ -82,6 +82,7 @@ RTCState *rtc_init(int base, qemu_irq irq); | @@ -82,6 +82,7 @@ RTCState *rtc_init(int base, qemu_irq irq); | ||
| 82 | RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq); | 82 | RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq); |
| 83 | void rtc_set_memory(RTCState *s, int addr, int val); | 83 | void rtc_set_memory(RTCState *s, int addr, int val); |
| 84 | void rtc_set_date(RTCState *s, const struct tm *tm); | 84 | void rtc_set_date(RTCState *s, const struct tm *tm); |
| 85 | +void cmos_set_s3_resume(void); | ||
| 85 | 86 | ||
| 86 | /* pc.c */ | 87 | /* pc.c */ |
| 87 | extern int fd_bootchk; | 88 | extern int fd_bootchk; |