From 6ac0d8d44c0966225b200cc25f8c5270f1191ec0 Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Mon, 12 Jan 2015 17:30:14 +0530 Subject: [PATCH 01/16] ich9: add disable_s3, disable_s4, s4_val properties PIIX4 has disable_s3 and disable_s4 properties to enable or disable PM functions. Add such properties to the ICH9 chipset as well for the Q35 machine type. S3 / S4 are not guaranteed to always work (needs work in the guest as well as QEMU for things to work properly), and disabling advertising of these features ensures guests don't go into zombie state if something isn't working right. The defaults are kept the same as in PIIX4: both S3 and S4 are enabled by default. These can be disabled via the cmdline: ... -global ICH9-LPC.disable_s3=1 -global ICH9-LPC.disable_s4=1 Note: some guests can fake hibernation by writing a hibernate image and doing a shutdown instead of S4 if S4 isn't available; there's nothing we can do guests to stop doing this, and this patch can't affect that functionality. Signed-off-by: Amit Shah Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Marcel Apfelbaum --- hw/acpi/ich9.c | 98 +++++++++++++++++++++++++++++++++++++++++- include/hw/acpi/ich9.h | 4 ++ 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c index ea991a3c65..e4195ea42c 100644 --- a/hw/acpi/ich9.c +++ b/hw/acpi/ich9.c @@ -219,7 +219,7 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io); acpi_pm1_evt_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io); - acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io, 2); + acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io, pm->s4_val); acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN); memory_region_init_io(&pm->io_gpe, OBJECT(lpc_pci), &ich9_gpe_ops, pm, @@ -269,10 +269,94 @@ static void ich9_pm_set_memory_hotplug_support(Object *obj, bool value, s->pm.acpi_memory_hotplug.is_enabled = value; } +static void ich9_pm_get_disable_s3(Object *obj, Visitor *v, + void *opaque, const char *name, + Error **errp) +{ + ICH9LPCPMRegs *pm = opaque; + uint8_t value = pm->disable_s3; + + visit_type_uint8(v, &value, name, errp); +} + +static void ich9_pm_set_disable_s3(Object *obj, Visitor *v, + void *opaque, const char *name, + Error **errp) +{ + ICH9LPCPMRegs *pm = opaque; + Error *local_err = NULL; + uint8_t value; + + visit_type_uint8(v, &value, name, &local_err); + if (local_err) { + goto out; + } + pm->disable_s3 = value; +out: + error_propagate(errp, local_err); +} + +static void ich9_pm_get_disable_s4(Object *obj, Visitor *v, + void *opaque, const char *name, + Error **errp) +{ + ICH9LPCPMRegs *pm = opaque; + uint8_t value = pm->disable_s4; + + visit_type_uint8(v, &value, name, errp); +} + +static void ich9_pm_set_disable_s4(Object *obj, Visitor *v, + void *opaque, const char *name, + Error **errp) +{ + ICH9LPCPMRegs *pm = opaque; + Error *local_err = NULL; + uint8_t value; + + visit_type_uint8(v, &value, name, &local_err); + if (local_err) { + goto out; + } + pm->disable_s4 = value; +out: + error_propagate(errp, local_err); +} + +static void ich9_pm_get_s4_val(Object *obj, Visitor *v, + void *opaque, const char *name, + Error **errp) +{ + ICH9LPCPMRegs *pm = opaque; + uint8_t value = pm->s4_val; + + visit_type_uint8(v, &value, name, errp); +} + +static void ich9_pm_set_s4_val(Object *obj, Visitor *v, + void *opaque, const char *name, + Error **errp) +{ + ICH9LPCPMRegs *pm = opaque; + Error *local_err = NULL; + uint8_t value; + + visit_type_uint8(v, &value, name, &local_err); + if (local_err) { + goto out; + } + pm->s4_val = value; +out: + error_propagate(errp, local_err); +} + void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp) { static const uint32_t gpe0_len = ICH9_PMIO_GPE0_LEN; pm->acpi_memory_hotplug.is_enabled = true; + pm->disable_s3 = 0; + pm->disable_s4 = 0; + pm->s4_val = 2; object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE, &pm->pm_io_base, errp); @@ -285,6 +369,18 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp) ich9_pm_get_memory_hotplug_support, ich9_pm_set_memory_hotplug_support, NULL); + object_property_add(obj, ACPI_PM_PROP_S3_DISABLED, "uint8", + ich9_pm_get_disable_s3, + ich9_pm_set_disable_s3, + NULL, pm, NULL); + object_property_add(obj, ACPI_PM_PROP_S4_DISABLED, "uint8", + ich9_pm_get_disable_s4, + ich9_pm_set_disable_s4, + NULL, pm, NULL); + object_property_add(obj, ACPI_PM_PROP_S4_VAL, "uint8", + ich9_pm_get_s4_val, + ich9_pm_set_s4_val, + NULL, pm, NULL); } void ich9_pm_device_plug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp) diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h index fe975e6624..12d7a7af5f 100644 --- a/include/hw/acpi/ich9.h +++ b/include/hw/acpi/ich9.h @@ -49,6 +49,10 @@ typedef struct ICH9LPCPMRegs { AcpiCpuHotplug gpe_cpu; MemHotplugState acpi_memory_hotplug; + + uint8_t disable_s3; + uint8_t disable_s4; + uint8_t s4_val; } ICH9LPCPMRegs; void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, From 7828d75045380ac659f2ad85fb5fec9bbb0746ac Mon Sep 17 00:00:00 2001 From: Don Koch Date: Fri, 16 Jan 2015 14:20:51 -0500 Subject: [PATCH 02/16] Add some trace calls to pci.c. Signed-off-by: Don Koch Acked-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/pci/pci.c | 9 +++++++++ trace-events | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 371699cf86..d5e0e419c2 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -32,6 +32,7 @@ #include "hw/loader.h" #include "qemu/range.h" #include "qmp-commands.h" +#include "trace.h" #include "hw/pci/msi.h" #include "hw/pci/msix.h" #include "exec/address-spaces.h" @@ -1106,10 +1107,18 @@ static void pci_update_mappings(PCIDevice *d) /* now do the real mapping */ if (r->addr != PCI_BAR_UNMAPPED) { + trace_pci_update_mappings_del(d, pci_bus_num(d->bus), + PCI_FUNC(d->devfn), + PCI_SLOT(d->devfn), + i, r->addr, r->size); memory_region_del_subregion(r->address_space, r->memory); } r->addr = new_addr; if (r->addr != PCI_BAR_UNMAPPED) { + trace_pci_update_mappings_add(d, pci_bus_num(d->bus), + PCI_FUNC(d->devfn), + PCI_SLOT(d->devfn), + i, r->addr, r->size); memory_region_add_subregion_overlap(r->address_space, r->addr, r->memory, 1); } diff --git a/trace-events b/trace-events index 8acbcce0f0..3db2f0ccea 100644 --- a/trace-events +++ b/trace-events @@ -1238,6 +1238,10 @@ spapr_pci_msi_write(uint64_t addr, uint64_t data, uint32_t dt_irq) "@%"PRIx64"<= spapr_pci_lsi_set(const char *busname, int pin, uint32_t irq) "%s PIN%d IRQ %u" spapr_pci_msi_retry(unsigned config_addr, unsigned req_num, unsigned max_irqs) "Guest device at %x asked %u, have only %u" +# hw/pci/pci.c +pci_update_mappings_del(void *d, uint32_t bus, uint32_t func, uint32_t slot, int bar, uint64_t addr, uint64_t size) "d=%p %02x:%02x.%x %d,%#"PRIx64"+%#"PRIx64 +pci_update_mappings_add(void *d, uint32_t bus, uint32_t func, uint32_t slot, int bar, uint64_t addr, uint64_t size) "d=%p %02x:%02x.%x %d,%#"PRIx64"+%#"PRIx64 + # hw/intc/xics.c xics_icp_check_ipi(int server, uint8_t mfrr) "CPU %d can take IPI mfrr=%#x" xics_icp_accept(uint32_t old_xirr, uint32_t new_xirr) "icp_accept: XIRR %#"PRIx32"->%#"PRIx32 From 27fb9688f9162515901ebf29e3879788fd326ea7 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 6 Jan 2015 17:03:08 +0100 Subject: [PATCH 03/16] pci: Split pcie_host_mmcfg_map() The mmcfg space is a memory region that allows access to PCI config space in the PCIe world. To maintain abstraction layers, I would like to expose the mmcfg space as a sysbus mmio region rather than have it mapped straight into the system's memory address space though. So this patch splits the initialization of the mmcfg space from the actual mapping, allowing us to only have an mmfg memory region without the map. Signed-off-by: Alexander Graf Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Claudio Fontana --- hw/pci/pcie_host.c | 9 +++++++-- include/hw/pci/pcie_host.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/hw/pci/pcie_host.c b/hw/pci/pcie_host.c index 3db038fc7f..dfb4a2b505 100644 --- a/hw/pci/pcie_host.c +++ b/hw/pci/pcie_host.c @@ -98,8 +98,7 @@ void pcie_host_mmcfg_unmap(PCIExpressHost *e) } } -void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr, - uint32_t size) +void pcie_host_mmcfg_init(PCIExpressHost *e, uint32_t size) { assert(!(size & (size - 1))); /* power of 2 */ assert(size >= PCIE_MMCFG_SIZE_MIN); @@ -107,6 +106,12 @@ void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr, e->size = size; memory_region_init_io(&e->mmio, OBJECT(e), &pcie_mmcfg_ops, e, "pcie-mmcfg", e->size); +} + +void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr, + uint32_t size) +{ + pcie_host_mmcfg_init(e, size); e->base_addr = addr; memory_region_add_subregion(get_system_memory(), e->base_addr, &e->mmio); } diff --git a/include/hw/pci/pcie_host.h b/include/hw/pci/pcie_host.h index ff44ef6fca..4d23c80759 100644 --- a/include/hw/pci/pcie_host.h +++ b/include/hw/pci/pcie_host.h @@ -50,6 +50,7 @@ struct PCIExpressHost { }; void pcie_host_mmcfg_unmap(PCIExpressHost *e); +void pcie_host_mmcfg_init(PCIExpressHost *e, uint32_t size); void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr, uint32_t size); void pcie_host_mmcfg_update(PCIExpressHost *e, int enable, From 6d4e4cb9985e24557abcf3932a0e7f8f6ab3c1d2 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 19 Dec 2014 11:46:57 +0000 Subject: [PATCH 04/16] pc: acpi: fix WindowsXP BSOD when memory hotplug is enabled ACPI parser in XP considers PNP0A06 devices of CPU and memory hotplug as duplicates. Adding unique _UID to CPU hotplug device fixes BSOD. Cc: qemu-stable@nongnu.org Signed-off-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-dsdt-cpu-hotplug.dsl | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl index 34aab5af43..268d870990 100644 --- a/hw/i386/acpi-dsdt-cpu-hotplug.dsl +++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl @@ -94,6 +94,7 @@ Scope(\_SB) { Device(CPU_HOTPLUG_RESOURCE_DEVICE) { Name(_HID, EisaId("PNP0A06")) + Name(_UID, "CPU hotplug resources") Name(_CRS, ResourceTemplate() { IO(Decode16, CPU_STATUS_BASE, CPU_STATUS_BASE, 0, CPU_STATUS_LEN) From 215d8d130be605c1927c764b027047c0ae0c6122 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 27 Jan 2015 14:40:44 +0200 Subject: [PATCH 05/16] acpi-test: update expected DSDT Previous patch pc: acpi: fix WindowsXP BSOD when memory hotplug is enabled changed DSDT, update expected test files. Signed-off-by: Michael S. Tsirkin --- tests/acpi-test-data/pc/DSDT | Bin 3592 -> 3621 bytes tests/acpi-test-data/q35/DSDT | Bin 8182 -> 8211 bytes tests/acpi-test-data/q35/SSDT | Bin 560 -> 560 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/acpi-test-data/pc/DSDT b/tests/acpi-test-data/pc/DSDT index ee9cc6781cea3a9515b9a176eea3459f8e4d8655..010d74603f09430d65fae1ce2a0d867c1964a1a8 100644 GIT binary patch delta 76 zcmeB>St`Tj66_M9%E!RKxMw35D<_k`&}2c*=Q?gI0YR?89Pu8WEs<66_Mf!N)t@Y@1cM7+C=S C=n9Ph diff --git a/tests/acpi-test-data/q35/DSDT b/tests/acpi-test-data/q35/DSDT index ef0c75f4236de3e6f727e21991533f2bf8279dee..8ac32efc0316daeed23e9002aa8bb05fb0fe483f 100644 GIT binary patch delta 76 zcmexnKiPrHCD3oF>oW7nlzKY&}1X&=Q?gI0YR?89Pu8WE+&p)W8W&{9RLk7

Date: Tue, 27 Jan 2015 14:40:44 +0200 Subject: [PATCH 06/16] acpi: update generated hex files Previous patch pc: acpi: fix WindowsXP BSOD when memory hotplug is enabled changed DSDT, update hex files for non-iasl builds. Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-dsdt.hex.generated | 43 ++++++++++++++++++++++----- hw/i386/q35-acpi-dsdt.hex.generated | 45 ++++++++++++++++++++++++----- 2 files changed, 73 insertions(+), 15 deletions(-) diff --git a/hw/i386/acpi-dsdt.hex.generated b/hw/i386/acpi-dsdt.hex.generated index 875570e5b1..498b194a0c 100644 --- a/hw/i386/acpi-dsdt.hex.generated +++ b/hw/i386/acpi-dsdt.hex.generated @@ -3,12 +3,12 @@ static unsigned char AcpiDsdtAmlCode[] = { 0x53, 0x44, 0x54, -0x8, +0x25, 0xe, 0x0, 0x0, 0x1, -0xfc, +0x6c, 0x42, 0x58, 0x50, @@ -31,8 +31,8 @@ static unsigned char AcpiDsdtAmlCode[] = { 0x4e, 0x54, 0x4c, -0x28, -0x8, +0x7, +0x11, 0x14, 0x20, 0x10, @@ -2318,8 +2318,8 @@ static unsigned char AcpiDsdtAmlCode[] = { 0x53, 0x1, 0x10, -0x42, -0x11, +0x4f, +0x12, 0x5f, 0x53, 0x42, @@ -2551,7 +2551,8 @@ static unsigned char AcpiDsdtAmlCode[] = { 0x60, 0x5b, 0x82, -0x29, +0x46, +0x4, 0x50, 0x52, 0x45, @@ -2568,6 +2569,34 @@ static unsigned char AcpiDsdtAmlCode[] = { 0x6, 0x8, 0x5f, +0x55, +0x49, +0x44, +0xd, +0x43, +0x50, +0x55, +0x20, +0x68, +0x6f, +0x74, +0x70, +0x6c, +0x75, +0x67, +0x20, +0x72, +0x65, +0x73, +0x6f, +0x75, +0x72, +0x63, +0x65, +0x73, +0x0, +0x8, +0x5f, 0x43, 0x52, 0x53, diff --git a/hw/i386/q35-acpi-dsdt.hex.generated b/hw/i386/q35-acpi-dsdt.hex.generated index 4807bdf484..0d5b133150 100644 --- a/hw/i386/q35-acpi-dsdt.hex.generated +++ b/hw/i386/q35-acpi-dsdt.hex.generated @@ -3,12 +3,12 @@ static unsigned char Q35AcpiDsdtAmlCode[] = { 0x53, 0x44, 0x54, -0xf6, -0x1f, +0x13, +0x20, 0x0, 0x0, 0x1, -0x91, +0x0, 0x42, 0x58, 0x50, @@ -31,8 +31,8 @@ static unsigned char Q35AcpiDsdtAmlCode[] = { 0x4e, 0x54, 0x4c, -0x28, -0x8, +0x7, +0x11, 0x14, 0x20, 0x10, @@ -6959,8 +6959,8 @@ static unsigned char Q35AcpiDsdtAmlCode[] = { 0x53, 0x1, 0x10, -0x42, -0x11, +0x4f, +0x12, 0x5f, 0x53, 0x42, @@ -7192,7 +7192,8 @@ static unsigned char Q35AcpiDsdtAmlCode[] = { 0x60, 0x5b, 0x82, -0x29, +0x46, +0x4, 0x50, 0x52, 0x45, @@ -7209,6 +7210,34 @@ static unsigned char Q35AcpiDsdtAmlCode[] = { 0x6, 0x8, 0x5f, +0x55, +0x49, +0x44, +0xd, +0x43, +0x50, +0x55, +0x20, +0x68, +0x6f, +0x74, +0x70, +0x6c, +0x75, +0x67, +0x20, +0x72, +0x65, +0x73, +0x6f, +0x75, +0x72, +0x63, +0x65, +0x73, +0x0, +0x8, +0x5f, 0x43, 0x52, 0x53, From 6d848641b7a4da92840fb2f5c240d1668f5a9281 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 19 Dec 2014 11:47:00 +0000 Subject: [PATCH 07/16] acpi: build_append_nameseg(): add padding if necessary According to ACPI spec NameSeg shorter than 4 characters must be padded up to 4 characters with "_" symbol. ACPI 5.0: 20.2.2 "Name Objects Encoding" Do it in build_append_nameseg() so that caller shouldn't know or care about it. Signed-off-by: Igor Mammedov Reviewed-by: Claudio Fontana Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 6a2e9c52bc..2f1daf701c 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -305,6 +305,8 @@ static inline void build_append_array(GArray *array, GArray *val) g_array_append_vals(array, val->data, val->len); } +#define ACPI_NAMESEG_LEN 4 + static void GCC_FMT_ATTR(2, 3) build_append_nameseg(GArray *array, const char *format, ...) { @@ -317,8 +319,11 @@ build_append_nameseg(GArray *array, const char *format, ...) len = vsnprintf(s, sizeof s, format, args); va_end(args); - assert(len == 4); + assert(len <= ACPI_NAMESEG_LEN); + g_array_append_vals(array, s, len); + /* Pad up to ACPI_NAMESEG_LEN characters if necessary. */ + g_array_append_vals(array, "____", ACPI_NAMESEG_LEN - len); } /* 5.4 Definition Block Encoding */ @@ -859,7 +864,7 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state) if (bus->parent_dev) { op = 0x82; /* DeviceOp */ - build_append_nameseg(bus_table, "S%.02X_", + build_append_nameseg(bus_table, "S%.02X", bus->parent_dev->devfn); build_append_byte(bus_table, 0x08); /* NameOp */ build_append_nameseg(bus_table, "_SUN"); @@ -979,7 +984,7 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state) build_append_int(notify, 0x1U << i); build_append_byte(notify, 0x00); /* NullName */ build_append_byte(notify, 0x86); /* NotifyOp */ - build_append_nameseg(notify, "S%.02X_", PCI_DEVFN(i, 0)); + build_append_nameseg(notify, "S%.02X", PCI_DEVFN(i, 0)); build_append_byte(notify, 0x69); /* Arg1Op */ /* Pack it up */ @@ -1036,7 +1041,7 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state) if (bus->parent_dev) { build_append_byte(parent->notify_table, '^'); /* ParentPrefixChar */ build_append_byte(parent->notify_table, 0x2E); /* DualNamePrefix */ - build_append_nameseg(parent->notify_table, "S%.02X_", + build_append_nameseg(parent->notify_table, "S%.02X", bus->parent_dev->devfn); build_append_nameseg(parent->notify_table, "PCNT"); } @@ -1106,7 +1111,7 @@ build_ssdt(GArray *table_data, GArray *linker, GArray *sb_scope = build_alloc_array(); uint8_t op = 0x10; /* ScopeOp */ - build_append_nameseg(sb_scope, "_SB_"); + build_append_nameseg(sb_scope, "_SB"); /* build Processor object for each processor */ for (i = 0; i < acpi_cpus; i++) { From 71f4be25d476c2865688da1e568257313cc2e511 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 19 Jan 2015 17:50:38 +0100 Subject: [PATCH 08/16] bios-tables-test: split piix4 and q35 tests This makes it clear which one is failing. Signed-off-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: John Snow --- tests/bios-tables-test.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c index 2519f7d0e2..4d0fa848b1 100644 --- a/tests/bios-tables-test.c +++ b/tests/bios-tables-test.c @@ -765,7 +765,7 @@ static void test_acpi_one(const char *params, test_data *data) g_free(args); } -static void test_acpi_tcg(void) +static void test_acpi_piix4_tcg(void) { test_data data; @@ -776,6 +776,11 @@ static void test_acpi_tcg(void) data.machine = MACHINE_PC; test_acpi_one("-machine accel=tcg", &data); free_test_data(&data); +} + +static void test_acpi_q35_tcg(void) +{ + test_data data; memset(&data, 0, sizeof(data)); data.machine = MACHINE_Q35; @@ -799,7 +804,8 @@ int main(int argc, char *argv[]) g_test_init(&argc, &argv, NULL); if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { - qtest_add_func("acpi/tcg", test_acpi_tcg); + qtest_add_func("acpi/piix4/tcg", test_acpi_piix4_tcg); + qtest_add_func("acpi/q35/tcg", test_acpi_q35_tcg); } ret = g_test_run(); unlink(disk); From 91d5c57a2e98845c02cda026f3f6a88cb5e14225 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 12 Dec 2014 10:01:46 +0100 Subject: [PATCH 09/16] virtio: fix feature bit checks Several places check against the feature bit number instead of against the feature bit. Fix them. Cc: qemu-stable@nongnu.org Reported-by: Thomas Huth Signed-off-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/scsi/virtio-scsi.c | 2 +- hw/virtio/dataplane/vring.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index b06dd390d2..9e2c718be7 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -144,7 +144,7 @@ static int virtio_scsi_parse_req(VirtIOSCSIReq *req, * * TODO: always disable this workaround for virtio 1.0 devices. */ - if ((vdev->guest_features & VIRTIO_F_ANY_LAYOUT) == 0) { + if ((vdev->guest_features & (1 << VIRTIO_F_ANY_LAYOUT)) == 0) { req_size = req->elem.out_sg[0].iov_len; resp_size = req->elem.in_sg[0].iov_len; } diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c index 61f6d83686..78c6f45a07 100644 --- a/hw/virtio/dataplane/vring.c +++ b/hw/virtio/dataplane/vring.c @@ -133,12 +133,12 @@ bool vring_should_notify(VirtIODevice *vdev, Vring *vring) * interrupts. */ smp_mb(); - if ((vdev->guest_features & VIRTIO_F_NOTIFY_ON_EMPTY) && + if ((vdev->guest_features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) && unlikely(vring->vr.avail->idx == vring->last_avail_idx)) { return true; } - if (!(vdev->guest_features & VIRTIO_RING_F_EVENT_IDX)) { + if (!(vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX))) { return !(vring->vr.avail->flags & VRING_AVAIL_F_NO_INTERRUPT); } old = vring->signalled_used; From 0058ae1d9483f5f96c7798e2ae51cce42c69abfb Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 19 Jan 2015 23:58:55 +0200 Subject: [PATCH 10/16] bios-linker-loader: move header to common location Will be usable by MIPS, ARM. Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 2 +- hw/i386/bios-linker-loader.c | 2 +- {hw/i386 => include/hw/acpi}/bios-linker-loader.h | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename {hw/i386 => include/hw/acpi}/bios-linker-loader.h (100%) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 2f1daf701c..4944249b84 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -36,7 +36,7 @@ #include "hw/i386/acpi-defs.h" #include "hw/acpi/acpi.h" #include "hw/nvram/fw_cfg.h" -#include "bios-linker-loader.h" +#include "hw/acpi/bios-linker-loader.h" #include "hw/loader.h" #include "hw/isa/isa.h" #include "hw/acpi/memory_hotplug.h" diff --git a/hw/i386/bios-linker-loader.c b/hw/i386/bios-linker-loader.c index aa56184e9a..5cc4d90c16 100644 --- a/hw/i386/bios-linker-loader.c +++ b/hw/i386/bios-linker-loader.c @@ -19,7 +19,7 @@ */ #include "qemu-common.h" -#include "bios-linker-loader.h" +#include "hw/acpi/bios-linker-loader.h" #include "hw/nvram/fw_cfg.h" #include "qemu/bswap.h" diff --git a/hw/i386/bios-linker-loader.h b/include/hw/acpi/bios-linker-loader.h similarity index 100% rename from hw/i386/bios-linker-loader.h rename to include/hw/acpi/bios-linker-loader.h From 09852232ee131d0bfa5bdf7f44a806158a5c8711 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 19 Jan 2015 23:58:55 +0200 Subject: [PATCH 11/16] bios-linker-loader: move source to common location There are plans to use bios linker by MIPS, ARM. It's only used by ACPI ATM, so put it in hw/acpi and make it depend on CONFIG_ACPI. Signed-off-by: Michael S. Tsirkin --- hw/acpi/Makefile.objs | 1 + hw/{i386 => acpi}/bios-linker-loader.c | 0 hw/i386/Makefile.objs | 1 - 3 files changed, 1 insertion(+), 1 deletion(-) rename hw/{i386 => acpi}/bios-linker-loader.c (100%) diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs index acd2389431..ee82073338 100644 --- a/hw/acpi/Makefile.objs +++ b/hw/acpi/Makefile.objs @@ -1,3 +1,4 @@ common-obj-$(CONFIG_ACPI) += core.o piix4.o ich9.o pcihp.o cpu_hotplug.o common-obj-$(CONFIG_ACPI) += memory_hotplug.o common-obj-$(CONFIG_ACPI) += acpi_interface.o +common-obj-$(CONFIG_ACPI) += bios-linker-loader.o diff --git a/hw/i386/bios-linker-loader.c b/hw/acpi/bios-linker-loader.c similarity index 100% rename from hw/i386/bios-linker-loader.c rename to hw/acpi/bios-linker-loader.c diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs index 9d419addb4..2b678ef2a6 100644 --- a/hw/i386/Makefile.objs +++ b/hw/i386/Makefile.objs @@ -7,7 +7,6 @@ obj-$(CONFIG_XEN) += ../xenpv/ xen/ obj-y += kvmvapic.o obj-y += acpi-build.o -obj-y += bios-linker-loader.o hw/i386/acpi-build.o: hw/i386/acpi-build.c hw/i386/acpi-dsdt.hex \ hw/i386/ssdt-proc.hex hw/i386/ssdt-pcihp.hex hw/i386/ssdt-misc.hex \ hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex \ From 744c6d474791ff3ad5c2f08edc732564199fd146 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 7 Jan 2015 15:36:33 -0200 Subject: [PATCH 12/16] smbios: Fix dimm size calculation when RAM is multiple of 16GB The Memory Device size calculation logic is broken when the RAM size is a multiple of 16GB, making the size of the last entry be 0 instead of 16GB. Fix the logic to handle that case correctly. Signed-off-by: Eduardo Habkost Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Paolo Bonzini --- hw/i386/smbios.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c index 024e59445b..ae7032adda 100644 --- a/hw/i386/smbios.c +++ b/hw/i386/smbios.c @@ -850,7 +850,8 @@ void smbios_get_tables(uint8_t **tables, size_t *tables_len, } #define MAX_DIMM_SZ (16ll * ONE_GB) -#define GET_DIMM_SZ ((i < dimm_cnt - 1) ? MAX_DIMM_SZ : ram_size % MAX_DIMM_SZ) +#define GET_DIMM_SZ ((i < dimm_cnt - 1) ? MAX_DIMM_SZ \ + : ((ram_size - 1) % MAX_DIMM_SZ) + 1) dimm_cnt = QEMU_ALIGN_UP(ram_size, MAX_DIMM_SZ) / MAX_DIMM_SZ; From 07d01c9c1929e43216005fcc8eccea75776ee0d2 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 7 Jan 2015 15:36:34 -0200 Subject: [PATCH 13/16] smbios: Don't report unknown CPU speed (fix SVVP regression) SVVP requires processor speed on Type 4 structures to not be unknown. This was fixed in SeaBIOS 0.5.0 (in 2009), but the bug was reintroduced in QEMU 2.1. Revert to old behavior and report CPU speed as 2000 MHz instead of unknown. Signed-off-by: Eduardo Habkost Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Paolo Bonzini --- hw/i386/smbios.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c index ae7032adda..12d213769d 100644 --- a/hw/i386/smbios.c +++ b/hw/i386/smbios.c @@ -618,8 +618,9 @@ static void smbios_build_type_4_table(unsigned instance) SMBIOS_TABLE_SET_STR(4, processor_version_str, type4.version); t->voltage = 0; t->external_clock = cpu_to_le16(0); /* Unknown */ - t->max_speed = cpu_to_le16(0); /* Unknown */ - t->current_speed = cpu_to_le16(0); /* Unknown */ + /* SVVP requires max_speed and current_speed to not be unknown. */ + t->max_speed = cpu_to_le16(2000); /* 2000 MHz */ + t->current_speed = cpu_to_le16(2000); /* 2000 MHz */ t->status = 0x41; /* Socket populated, CPU enabled */ t->processor_upgrade = 0x01; /* Other */ t->l1_cache_handle = cpu_to_le16(0xFFFF); /* N/A */ From 759048ac20174b34fa7a593f4da2e7fed34e599c Mon Sep 17 00:00:00 2001 From: Bharata B Rao Date: Tue, 27 Jan 2015 09:35:00 +0530 Subject: [PATCH 14/16] pc: Fix DIMMs capacity calculation pc_existing_dimms_capacity() is returning DIMMs count rather than capacity. Fix this to return the capacity. Also consider only realized devices for capacity calculation. Signed-off-by: Bharata B Rao Reviewed-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/pc.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index e07f1fac56..125cf0ad7c 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1552,25 +1552,18 @@ void qemu_register_pc_machine(QEMUMachine *m) g_free(name); } -static int pc_dimm_count(Object *obj, void *opaque) -{ - int *count = opaque; - - if (object_dynamic_cast(obj, TYPE_PC_DIMM)) { - (*count)++; - } - - object_child_foreach(obj, pc_dimm_count, opaque); - return 0; -} - static int pc_existing_dimms_capacity(Object *obj, void *opaque) { Error *local_err = NULL; uint64_t *size = opaque; if (object_dynamic_cast(obj, TYPE_PC_DIMM)) { - (*size) += object_property_get_int(obj, PC_DIMM_SIZE_PROP, &local_err); + DeviceState *dev = DEVICE(obj); + + if (dev->realized) { + (*size) += object_property_get_int(obj, PC_DIMM_SIZE_PROP, + &local_err); + } if (local_err) { qerror_report_err(local_err); @@ -1579,7 +1572,7 @@ static int pc_existing_dimms_capacity(Object *obj, void *opaque) } } - object_child_foreach(obj, pc_dimm_count, opaque); + object_child_foreach(obj, pc_existing_dimms_capacity, opaque); return 0; } @@ -1623,8 +1616,9 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev, if (existing_dimms_capacity + memory_region_size(mr) > machine->maxram_size - machine->ram_size) { error_setg(&local_err, "not enough space, currently 0x%" PRIx64 - " in use of total 0x" RAM_ADDR_FMT, - existing_dimms_capacity, machine->maxram_size); + " in use of total hot pluggable 0x" RAM_ADDR_FMT, + existing_dimms_capacity, + machine->maxram_size - machine->ram_size); goto out; } From 9967c94957f60c2d1cadbe0bfd4373a13fb1a226 Mon Sep 17 00:00:00 2001 From: Bharata B Rao Date: Tue, 27 Jan 2015 09:35:01 +0530 Subject: [PATCH 15/16] pc-dimm: Make pc_existing_dimms_capacity global Move pc_existing_dimms_capacity() to pc-dimm.c since it would be needed by PowerPC memory hotplug code too. Signed-off-by: Bharata B Rao Reviewed-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/pc.c | 24 ------------------------ hw/mem/pc-dimm.c | 25 +++++++++++++++++++++++++ include/hw/mem/pc-dimm.h | 1 + 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 125cf0ad7c..2ec45a4be0 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1552,30 +1552,6 @@ void qemu_register_pc_machine(QEMUMachine *m) g_free(name); } -static int pc_existing_dimms_capacity(Object *obj, void *opaque) -{ - Error *local_err = NULL; - uint64_t *size = opaque; - - if (object_dynamic_cast(obj, TYPE_PC_DIMM)) { - DeviceState *dev = DEVICE(obj); - - if (dev->realized) { - (*size) += object_property_get_int(obj, PC_DIMM_SIZE_PROP, - &local_err); - } - - if (local_err) { - qerror_report_err(local_err); - error_free(local_err); - return 1; - } - } - - object_child_foreach(obj, pc_existing_dimms_capacity, opaque); - return 0; -} - static void pc_dimm_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c index d431834030..f02ce6e04c 100644 --- a/hw/mem/pc-dimm.c +++ b/hw/mem/pc-dimm.c @@ -22,6 +22,31 @@ #include "qemu/config-file.h" #include "qapi/visitor.h" #include "qemu/range.h" +#include "qapi/qmp/qerror.h" + +int pc_existing_dimms_capacity(Object *obj, void *opaque) +{ + Error *local_err = NULL; + uint64_t *size = opaque; + + if (object_dynamic_cast(obj, TYPE_PC_DIMM)) { + DeviceState *dev = DEVICE(obj); + + if (dev->realized) { + (*size) += object_property_get_int(obj, PC_DIMM_SIZE_PROP, + &local_err); + } + + if (local_err) { + qerror_report_err(local_err); + error_free(local_err); + return 1; + } + } + + object_child_foreach(obj, pc_existing_dimms_capacity, opaque); + return 0; +} int qmp_pc_dimm_device_list(Object *obj, void *opaque) { diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h index e1dcbbcd58..bbfa53f3a4 100644 --- a/include/hw/mem/pc-dimm.h +++ b/include/hw/mem/pc-dimm.h @@ -78,4 +78,5 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start, int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp); int qmp_pc_dimm_device_list(Object *obj, void *opaque); +int pc_existing_dimms_capacity(Object *obj, void *opaque); #endif From 37153450436f58449ce7e41d13a23821611e889e Mon Sep 17 00:00:00 2001 From: Bharata B Rao Date: Tue, 27 Jan 2015 09:35:02 +0530 Subject: [PATCH 16/16] pc-dimm: Add Error argument to pc_existing_dimms_capacity Now that pc_existing_dimms_capacity() is an API, include Error pointer as an argument and modify the caller appropriately. Suggested-by: Igor Mammedov Signed-off-by: Bharata B Rao Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Igor Mammedov --- hw/i386/pc.c | 4 ++-- hw/mem/pc-dimm.c | 32 ++++++++++++++++++++++---------- include/hw/mem/pc-dimm.h | 2 +- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 2ec45a4be0..c7af6aae01 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1584,8 +1584,8 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev, goto out; } - if (pc_existing_dimms_capacity(OBJECT(machine), &existing_dimms_capacity)) { - error_setg(&local_err, "failed to get total size of existing DIMMs"); + existing_dimms_capacity = pc_existing_dimms_capacity(&local_err); + if (local_err) { goto out; } diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c index f02ce6e04c..18cdc54bf9 100644 --- a/hw/mem/pc-dimm.c +++ b/hw/mem/pc-dimm.c @@ -22,32 +22,44 @@ #include "qemu/config-file.h" #include "qapi/visitor.h" #include "qemu/range.h" -#include "qapi/qmp/qerror.h" -int pc_existing_dimms_capacity(Object *obj, void *opaque) +typedef struct pc_dimms_capacity { + uint64_t size; + Error **errp; +} pc_dimms_capacity; + +static int pc_existing_dimms_capacity_internal(Object *obj, void *opaque) { - Error *local_err = NULL; - uint64_t *size = opaque; + pc_dimms_capacity *cap = opaque; + uint64_t *size = &cap->size; if (object_dynamic_cast(obj, TYPE_PC_DIMM)) { DeviceState *dev = DEVICE(obj); if (dev->realized) { (*size) += object_property_get_int(obj, PC_DIMM_SIZE_PROP, - &local_err); + cap->errp); } - if (local_err) { - qerror_report_err(local_err); - error_free(local_err); + if (cap->errp && *cap->errp) { return 1; } } - - object_child_foreach(obj, pc_existing_dimms_capacity, opaque); + object_child_foreach(obj, pc_existing_dimms_capacity_internal, opaque); return 0; } +uint64_t pc_existing_dimms_capacity(Error **errp) +{ + pc_dimms_capacity cap; + + cap.size = 0; + cap.errp = errp; + + pc_existing_dimms_capacity_internal(qdev_get_machine(), &cap); + return cap.size; +} + int qmp_pc_dimm_device_list(Object *obj, void *opaque) { MemoryDeviceInfoList ***prev = opaque; diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h index bbfa53f3a4..f7b80b44b7 100644 --- a/include/hw/mem/pc-dimm.h +++ b/include/hw/mem/pc-dimm.h @@ -78,5 +78,5 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start, int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp); int qmp_pc_dimm_device_list(Object *obj, void *opaque); -int pc_existing_dimms_capacity(Object *obj, void *opaque); +uint64_t pc_existing_dimms_capacity(Error **errp); #endif