From patchwork Mon May 14 12:34:18 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gleb Natapov X-Patchwork-Id: 158990 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id C2047B7040 for ; Mon, 14 May 2012 22:34:55 +1000 (EST) Received: from localhost ([::1]:38866 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1STuUH-0003OG-BB for incoming@patchwork.ozlabs.org; Mon, 14 May 2012 08:34:53 -0400 Received: from eggs.gnu.org ([208.118.235.92]:36998) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1STuU6-0003O9-Md for qemu-devel@nongnu.org; Mon, 14 May 2012 08:34:44 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1STuU3-0004M3-GX for qemu-devel@nongnu.org; Mon, 14 May 2012 08:34:42 -0400 Received: from mx1.redhat.com ([209.132.183.28]:8595) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1STuU3-0004Ly-83 for qemu-devel@nongnu.org; Mon, 14 May 2012 08:34:39 -0400 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q4ECYbHF031004 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 14 May 2012 08:34:37 -0400 Received: from dhcp-1-237.tlv.redhat.com (dhcp-4-26.tlv.redhat.com [10.35.4.26]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q4ECYaOu029991 for ; Mon, 14 May 2012 08:34:37 -0400 Received: by dhcp-1-237.tlv.redhat.com (Postfix, from userid 13519) id A443D18D477; Mon, 14 May 2012 15:34:36 +0300 (IDT) From: Gleb Natapov To: qemu-devel@nongnu.org Date: Mon, 14 May 2012 15:34:18 +0300 Message-Id: <1336998858-30055-2-git-send-email-gleb@redhat.com> In-Reply-To: <1336998858-30055-1-git-send-email-gleb@redhat.com> References: <1336998858-30055-1-git-send-email-gleb@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 2/2] Add PIIX4 properties to control PM system states. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This patch adds two things. First it allows QEMU to distinguish between regular powerdown and S4 powerdown. Later separate QMP notification will be added for S4 powerdown. Second it allows S3/S4 states to be disabled from QEMU command line. Some guests known to be broken with regards to power management, but allow to use it anyway. Using new properties management will be able to disable S3/S4 for such guests. Supported system state are passed to a firmware using new fw_cfg entry. The entry contains 6 byte array. Each byte represents one system state. If byte at offset X has its MSB set it means that system state X is supported and to enter it guest should use the value from lowest 7 bits. Signed-off-by: Gleb Natapov --- hw/acpi.c | 5 ++++- hw/acpi.h | 2 +- hw/acpi_piix4.c | 21 +++++++++++++++++++-- hw/mips_malta.c | 3 ++- hw/pc.c | 6 ------ hw/pc.h | 10 +++++++++- hw/pc_piix.c | 2 +- hw/vt82c686.c | 2 +- 8 files changed, 37 insertions(+), 14 deletions(-) diff --git a/hw/acpi.c b/hw/acpi.c index 5d521e5..effc7ec 100644 --- a/hw/acpi.c +++ b/hw/acpi.c @@ -370,7 +370,7 @@ void acpi_pm1_cnt_init(ACPIREGS *ar) qemu_register_wakeup_notifier(&ar->wakeup); } -void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val) +void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val, char s4) { ar->pm1.cnt.cnt = val & ~(ACPI_BITMASK_SLEEP_ENABLE); @@ -385,6 +385,9 @@ void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val) qemu_system_suspend_request(); break; default: + if (sus_typ == s4) { /* S4 request */ + qemu_system_shutdown_request(); + } break; } } diff --git a/hw/acpi.h b/hw/acpi.h index fe8cdb4..7337f41 100644 --- a/hw/acpi.h +++ b/hw/acpi.h @@ -139,7 +139,7 @@ void acpi_pm1_evt_reset(ACPIREGS *ar); /* PM1a_CNT: piix and ich9 don't implement PM1b CNT. */ void acpi_pm1_cnt_init(ACPIREGS *ar); -void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val); +void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val, char s4); void acpi_pm1_cnt_update(ACPIREGS *ar, bool sci_enable, bool sci_disable); void acpi_pm1_cnt_reset(ACPIREGS *ar); diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 585da4e..ce1f5af 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -27,6 +27,7 @@ #include "sysemu.h" #include "range.h" #include "ioport.h" +#include "fw_cfg.h" //#define DEBUG @@ -71,6 +72,10 @@ typedef struct PIIX4PMState { struct pci_status pci0_status; uint32_t pci0_hotplug_enable; uint32_t pci0_slot_device_present; + + uint8_t disable_s3; + uint8_t disable_s4; + uint8_t s4_val; } PIIX4PMState; static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s); @@ -123,7 +128,7 @@ static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width, pm_update_sci(s); break; case 0x04: - acpi_pm1_cnt_write(&s->ar, val); + acpi_pm1_cnt_write(&s->ar, val, s->s4_val); break; default: break; @@ -421,7 +426,7 @@ static int piix4_pm_initfn(PCIDevice *dev) i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qemu_irq sci_irq, qemu_irq smi_irq, - int kvm_enabled) + int kvm_enabled, uint16_t fw_cfg_key) { PCIDevice *dev; PIIX4PMState *s; @@ -437,11 +442,23 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qdev_init_nofail(&dev->qdev); + if (fw_cfg_key != FW_CFG_INVALID) { + uint8_t suspend[6] = {128, 0, 0, 129, 128, 128}; + + suspend[3] = 1 | ((!s->disable_s3) << 7); + suspend[4] = s->s4_val | ((!s->disable_s4) << 7); + + fw_cfg_add_bytes(fw_cfg_key, g_memdup(suspend, 6), 6); + } + return s->smb.smbus; } static Property piix4_pm_properties[] = { DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0), + DEFINE_PROP_UINT8("disable_s3", PIIX4PMState, disable_s3, 0), + DEFINE_PROP_UINT8("disable_s4", PIIX4PMState, disable_s4, 0), + DEFINE_PROP_UINT8("s4_val", PIIX4PMState, s4_val, 2), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/mips_malta.c b/hw/mips_malta.c index 4752bb2..5f0f5b6 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -48,6 +48,7 @@ #include "blockdev.h" #include "exec-memory.h" #include "sysbus.h" /* SysBusDevice */ +#include "fw_cfg.h" //#define DEBUG_BOARD_INIT @@ -954,7 +955,7 @@ void mips_malta_init (ram_addr_t ram_size, pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1); pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci"); smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, - isa_get_irq(NULL, 9), NULL, 0); + isa_get_irq(NULL, 9), NULL, 0, FW_CFG_INVALID); /* TODO: Populate SPD eeprom data. */ smbus_eeprom_init(smbus, 8, NULL, 0); pit = pit_init(isa_bus, 0x40, 0, NULL); diff --git a/hw/pc.c b/hw/pc.c index 5d28d3b..3a2c2d2 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -29,7 +29,6 @@ #include "pci.h" #include "vmware_vga.h" #include "monitor.h" -#include "fw_cfg.h" #include "hpet_emul.h" #include "smbios.h" #include "loader.h" @@ -64,11 +63,6 @@ /* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables. */ #define ACPI_DATA_SIZE 0x10000 #define BIOS_CFG_IOPORT 0x510 -#define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0) -#define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1) -#define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2) -#define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3) -#define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4) #define MSI_ADDR_BASE 0xfee00000 diff --git a/hw/pc.h b/hw/pc.h index 74d3369..4d23712 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -9,6 +9,7 @@ #include "net.h" #include "memory.h" #include "ioapic.h" +#include "fw_cfg.h" /* PC-style peripherals (also used by other machines). */ @@ -142,7 +143,7 @@ int acpi_table_add(const char *table_desc); i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qemu_irq sci_irq, qemu_irq smi_irq, - int kvm_enabled); + int kvm_enabled, uint16_t fw_cfg_key); void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr); /* hpet.c */ @@ -227,4 +228,11 @@ void pc_system_firmware_init(MemoryRegion *rom_memory); int e820_add_entry(uint64_t, uint64_t, uint32_t); +#define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0) +#define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1) +#define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2) +#define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3) +#define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4) +#define FW_CFG_SYSTEM_STATES (FW_CFG_ARCH_LOCAL + 5) + #endif diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 6a75718..6bd2791 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -280,7 +280,7 @@ static void pc_init1(MemoryRegion *system_memory, /* TODO: Populate SPD eeprom data. */ smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, gsi[9], *smi_irq, - kvm_enabled()); + kvm_enabled(), FW_CFG_SYSTEM_STATES); smbus_eeprom_init(smbus, 8, NULL, 0); } diff --git a/hw/vt82c686.c b/hw/vt82c686.c index 6fb7950..5d7c00c 100644 --- a/hw/vt82c686.c +++ b/hw/vt82c686.c @@ -210,7 +210,7 @@ static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val) pm_update_sci(s); break; case 0x04: - acpi_pm1_cnt_write(&s->ar, val); + acpi_pm1_cnt_write(&s->ar, val, 0); break; default: break;