diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/acpi/core.c | 11 | ||||
-rw-r--r-- | hw/acpi/ich9.c | 2 | ||||
-rw-r--r-- | hw/acpi/piix4.c | 5 | ||||
-rw-r--r-- | hw/core/machine.c | 5 | ||||
-rw-r--r-- | hw/i386/acpi-build.c | 72 | ||||
-rw-r--r-- | hw/isa/lpc_ich9.c | 1 | ||||
-rw-r--r-- | hw/isa/vt82c686.c | 2 | ||||
-rw-r--r-- | hw/net/virtio-net.c | 18 | ||||
-rw-r--r-- | hw/pci-host/gpex-acpi.c | 1 | ||||
-rw-r--r-- | hw/pci/pci.c | 6 | ||||
-rw-r--r-- | hw/pci/pcie.c | 19 |
11 files changed, 108 insertions, 34 deletions
diff --git a/hw/acpi/core.c b/hw/acpi/core.c index 7170bff..1e004d0 100644 --- a/hw/acpi/core.c +++ b/hw/acpi/core.c @@ -579,6 +579,10 @@ void acpi_pm1_cnt_update(ACPIREGS *ar, bool sci_enable, bool sci_disable) { /* ACPI specs 3.0, 4.7.2.5 */ + if (ar->pm1.cnt.acpi_only) { + return; + } + if (sci_enable) { ar->pm1.cnt.cnt |= ACPI_BITMASK_SCI_ENABLE; } else if (sci_disable) { @@ -608,11 +612,13 @@ static const MemoryRegionOps acpi_pm_cnt_ops = { }; void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, - bool disable_s3, bool disable_s4, uint8_t s4_val) + bool disable_s3, bool disable_s4, uint8_t s4_val, + bool acpi_only) { FWCfgState *fw_cfg; ar->pm1.cnt.s4_val = s4_val; + ar->pm1.cnt.acpi_only = acpi_only; ar->wakeup.notify = acpi_notify_wakeup; qemu_register_wakeup_notifier(&ar->wakeup); @@ -638,6 +644,9 @@ void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, void acpi_pm1_cnt_reset(ACPIREGS *ar) { ar->pm1.cnt.cnt = 0; + if (ar->pm1.cnt.acpi_only) { + ar->pm1.cnt.cnt |= ACPI_BITMASK_SCI_ENABLE; + } } /* ACPI GPE */ diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c index 5ff4e01..853447c 100644 --- a/hw/acpi/ich9.c +++ b/hw/acpi/ich9.c @@ -282,7 +282,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, pm->disable_s3, pm->disable_s4, - pm->s4_val); + pm->s4_val, !pm->smm_compat && !smm_enabled); acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN); memory_region_init_io(&pm->io_gpe, OBJECT(lpc_pci), &ich9_gpe_ops, pm, diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 669be5b..1efc0de 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -74,6 +74,7 @@ struct PIIX4PMState { qemu_irq irq; qemu_irq smi_irq; int smm_enabled; + bool smm_compat; Notifier machine_ready; Notifier powerdown_notifier; @@ -496,7 +497,8 @@ static void piix4_pm_realize(PCIDevice *dev, Error **errp) acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io); acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io); - acpi_pm1_cnt_init(&s->ar, &s->io, s->disable_s3, s->disable_s4, s->s4_val); + acpi_pm1_cnt_init(&s->ar, &s->io, s->disable_s3, s->disable_s4, s->s4_val, + !s->smm_compat && !s->smm_enabled); acpi_gpe_init(&s->ar, GPE_LEN); s->powerdown_notifier.notify = piix4_pm_powerdown_req; @@ -642,6 +644,7 @@ static Property piix4_pm_properties[] = { use_acpi_root_pci_hotplug, true), DEFINE_PROP_BOOL("memory-hotplug-support", PIIX4PMState, acpi_memory_hotplug.is_enabled, true), + DEFINE_PROP_BOOL("smm-compat", PIIX4PMState, smm_compat, false), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/core/machine.c b/hw/core/machine.c index 970046f..4386f57 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -36,7 +36,10 @@ #include "hw/virtio/virtio.h" #include "hw/virtio/virtio-pci.h" -GlobalProperty hw_compat_5_2[] = {}; +GlobalProperty hw_compat_5_2[] = { + { "ICH9-LPC", "smm-compat", "on"}, + { "PIIX4_PM", "smm-compat", "on"}, +}; const size_t hw_compat_5_2_len = G_N_ELEMENTS(hw_compat_5_2); GlobalProperty hw_compat_5_1[] = { diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index b9190b9..31a5f6f 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -139,6 +139,14 @@ const struct AcpiGenericAddress x86_nvdimm_acpi_dsmio = { static void init_common_fadt_data(MachineState *ms, Object *o, AcpiFadtData *data) { + X86MachineState *x86ms = X86_MACHINE(ms); + /* + * "ICH9-LPC" or "PIIX4_PM" has "smm-compat" property to keep the old + * behavior for compatibility irrelevant to smm_enabled, which doesn't + * comforms to ACPI spec. + */ + bool smm_enabled = object_property_get_bool(o, "smm-compat", NULL) ? + true : x86_machine_is_smm_enabled(x86ms); uint32_t io = object_property_get_uint(o, ACPI_PM_PROP_PM_IO_BASE, NULL); AmlAddressSpace as = AML_AS_SYSTEM_IO; AcpiFadtData fadt = { @@ -159,12 +167,16 @@ static void init_common_fadt_data(MachineState *ms, Object *o, .rtc_century = RTC_CENTURY, .plvl2_lat = 0xfff /* C2 state not supported */, .plvl3_lat = 0xfff /* C3 state not supported */, - .smi_cmd = ACPI_PORT_SMI_CMD, + .smi_cmd = smm_enabled ? ACPI_PORT_SMI_CMD : 0, .sci_int = object_property_get_uint(o, ACPI_PM_PROP_SCI_INT, NULL), .acpi_enable_cmd = - object_property_get_uint(o, ACPI_PM_PROP_ACPI_ENABLE_CMD, NULL), + smm_enabled ? + object_property_get_uint(o, ACPI_PM_PROP_ACPI_ENABLE_CMD, NULL) : + 0, .acpi_disable_cmd = - object_property_get_uint(o, ACPI_PM_PROP_ACPI_DISABLE_CMD, NULL), + smm_enabled ? + object_property_get_uint(o, ACPI_PM_PROP_ACPI_DISABLE_CMD, NULL) : + 0, .pm1a_evt = { .space_id = as, .bit_width = 4 * 8, .address = io }, .pm1a_cnt = { .space_id = as, .bit_width = 2 * 8, .address = io + 0x04 }, @@ -1060,6 +1072,46 @@ static void build_q35_pci0_int(Aml *table) aml_append(table, sb_scope); } +static Aml *build_q35_dram_controller(const AcpiMcfgInfo *mcfg) +{ + Aml *dev; + Aml *resource_template; + + /* DRAM controller */ + dev = aml_device("DRAC"); + aml_append(dev, aml_name_decl("_HID", aml_string("PNP0C01"))); + + resource_template = aml_resource_template(); + if (mcfg->base + mcfg->size - 1 >= (1ULL << 32)) { + aml_append(resource_template, + aml_qword_memory(AML_POS_DECODE, + AML_MIN_FIXED, + AML_MAX_FIXED, + AML_NON_CACHEABLE, + AML_READ_WRITE, + 0x0000000000000000, + mcfg->base, + mcfg->base + mcfg->size - 1, + 0x0000000000000000, + mcfg->size)); + } else { + aml_append(resource_template, + aml_dword_memory(AML_POS_DECODE, + AML_MIN_FIXED, + AML_MAX_FIXED, + AML_NON_CACHEABLE, + AML_READ_WRITE, + 0x0000000000000000, + mcfg->base, + mcfg->base + mcfg->size - 1, + 0x0000000000000000, + mcfg->size)); + } + aml_append(dev, aml_name_decl("_CRS", resource_template)); + + return dev; +} + static void build_q35_isa_bridge(Aml *table) { Aml *dev; @@ -1206,6 +1258,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(machine); X86MachineState *x86ms = X86_MACHINE(machine); AcpiMcfgInfo mcfg; + bool mcfg_valid = !!acpi_get_mcfg(&mcfg); uint32_t nr_mem = machine->ram_slots; int root_bus_limit = 0xFF; PCIBus *bus = NULL; @@ -1228,7 +1281,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(sb_scope, dev); aml_append(dsdt, sb_scope); - build_hpet_aml(dsdt); + if (misc->has_hpet) { + build_hpet_aml(dsdt); + } build_piix4_isa_bridge(dsdt); build_isa_devices_aml(dsdt); if (pm->pcihp_bridge_en || pm->pcihp_root_en) { @@ -1244,6 +1299,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(dev, aml_name_decl("_UID", aml_int(0))); aml_append(dev, build_q35_osc_method()); aml_append(sb_scope, dev); + if (mcfg_valid) { + aml_append(sb_scope, build_q35_dram_controller(&mcfg)); + } if (pm->smi_on_cpuhp) { /* reserve SMI block resources, IO ports 0xB2, 0xB3 */ @@ -1272,7 +1330,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(dsdt, sb_scope); - build_hpet_aml(dsdt); + if (misc->has_hpet) { + build_hpet_aml(dsdt); + } build_q35_isa_bridge(dsdt); build_isa_devices_aml(dsdt); build_q35_pci0_int(dsdt); @@ -1374,7 +1434,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, * the PCI0._CRS. Add mmconfig to the set so it will be excluded * too. */ - if (acpi_get_mcfg(&mcfg)) { + if (mcfg_valid) { crs_range_insert(crs_range_set.mem_ranges, mcfg.base, mcfg.base + mcfg.size - 1); } diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index d3145bf..3963b73 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -775,6 +775,7 @@ static const VMStateDescription vmstate_ich9_lpc = { static Property ich9_lpc_properties[] = { DEFINE_PROP_BOOL("noreboot", ICH9LPCState, pin_strap.spkr_hi, true), + DEFINE_PROP_BOOL("smm-compat", ICH9LPCState, pm.smm_compat, false), DEFINE_PROP_BIT64("x-smi-broadcast", ICH9LPCState, smi_host_features, ICH9_LPC_SMI_F_BROADCAST_BIT, true), DEFINE_PROP_BIT64("x-smi-cpu-hotplug", ICH9LPCState, smi_host_features, diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 5db9b17..05d084f 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -190,7 +190,7 @@ static void via_pm_realize(PCIDevice *dev, Error **errp) acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io); acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io); - acpi_pm1_cnt_init(&s->ar, &s->io, false, false, 2); + acpi_pm1_cnt_init(&s->ar, &s->io, false, false, 2, false); } typedef struct via_pm_init_info { diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 5150f29..439f823 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -855,19 +855,19 @@ static void failover_add_primary(VirtIONet *n, Error **errp) id = failover_find_primary_device_id(n); if (!id) { + error_setg(errp, "Primary device not found"); + error_append_hint(errp, "Virtio-net failover will not work. Make " + "sure primary device has parameter" + " failover_pair_id=%s\n", n->netclient_name); return; } opts = qemu_opts_find(qemu_find_opts("device"), id); - if (opts) { - dev = qdev_device_add(opts, &err); - if (err) { - qemu_opts_del(opts); - } + g_assert(opts); /* cannot be NULL because id was found using opts list */ + dev = qdev_device_add(opts, &err); + if (err) { + qemu_opts_del(opts); } else { - error_setg(errp, "Primary device not found"); - error_append_hint(errp, "Virtio-net failover will not work. Make " - "sure primary device has parameter" - " failover_pair_id=<virtio-net-id>\n"); + object_unref(OBJECT(dev)); } error_propagate(errp, err); } diff --git a/hw/pci-host/gpex-acpi.c b/hw/pci-host/gpex-acpi.c index 446912d..0f01f13 100644 --- a/hw/pci-host/gpex-acpi.c +++ b/hw/pci-host/gpex-acpi.c @@ -175,6 +175,7 @@ void acpi_dsdt_add_gpex(Aml *scope, struct GPEXConfig *cfg) aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num))); aml_append(dev, aml_name_decl("_UID", aml_int(bus_num))); aml_append(dev, aml_name_decl("_STR", aml_unicode("pxb Device"))); + aml_append(dev, aml_name_decl("_CCA", aml_int(1))); if (numa_node != NUMA_NODE_UNASSIGNED) { aml_append(dev, aml_name_decl("_PXM", aml_int(numa_node))); } diff --git a/hw/pci/pci.c b/hw/pci/pci.c index a9ebef8..fa97a67 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -2127,10 +2127,8 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp) pci_qdev_unrealize(DEVICE(pci_dev)); return; } - if (!(pci_dev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) - && (PCI_FUNC(pci_dev->devfn) == 0)) { - qdev->allow_unplug_during_migration = true; - } else { + if ((pci_dev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) + || (PCI_FUNC(pci_dev->devfn) != 0)) { error_setg(errp, "failover: primary device must be in its own " "PCI slot"); pci_qdev_unrealize(DEVICE(pci_dev)); diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index d4010cf..a733e2f 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -75,11 +75,6 @@ pcie_cap_v1_fill(PCIDevice *dev, uint8_t port, uint8_t type, uint8_t version) QEMU_PCI_EXP_LNKSTA_NLW(QEMU_PCI_EXP_LNK_X1) | QEMU_PCI_EXP_LNKSTA_CLS(QEMU_PCI_EXP_LNK_2_5GT)); - if (dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA) { - pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, - PCI_EXP_LNKSTA_DLLLA); - } - /* We changed link status bits over time, and changing them across * migrations is generally fine as hardware changes them too. * Let's not bother checking. @@ -125,8 +120,7 @@ static void pcie_cap_fill_slot_lnk(PCIDevice *dev) */ pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP, PCI_EXP_LNKCAP_DLLLARC); - pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, - PCI_EXP_LNKSTA_DLLLA); + /* the PCI_EXP_LNKSTA_DLLLA will be set in the hotplug function */ /* * Target Link Speed defaults to the highest link speed supported by @@ -427,6 +421,7 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev); uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap; PCIDevice *pci_dev = PCI_DEVICE(dev); + uint32_t lnkcap = pci_get_long(exp_cap + PCI_EXP_LNKCAP); /* Don't send event when device is enabled during qemu machine creation: * it is present on boot, no hotplug event is necessary. We do send an @@ -434,7 +429,8 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, if (!dev->hotplugged) { pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_PDS); - if (pci_dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA) { + if (pci_dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA || + (lnkcap & PCI_EXP_LNKCAP_DLLLARC)) { pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, PCI_EXP_LNKSTA_DLLLA); } @@ -448,7 +444,8 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, if (pci_get_function_0(pci_dev)) { pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_PDS); - if (pci_dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA) { + if (pci_dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA || + (lnkcap & PCI_EXP_LNKCAP_DLLLARC)) { pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, PCI_EXP_LNKSTA_DLLLA); } @@ -640,6 +637,7 @@ void pcie_cap_slot_write_config(PCIDevice *dev, uint32_t pos = dev->exp.exp_cap; uint8_t *exp_cap = dev->config + pos; uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA); + uint32_t lnkcap = pci_get_long(exp_cap + PCI_EXP_LNKCAP); if (ranges_overlap(addr, len, pos + PCI_EXP_SLTSTA, 2)) { /* @@ -695,7 +693,8 @@ void pcie_cap_slot_write_config(PCIDevice *dev, pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_PDS); - if (dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA) { + if (dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA || + (lnkcap & PCI_EXP_LNKCAP_DLLLARC)) { pci_word_test_and_clear_mask(exp_cap + PCI_EXP_LNKSTA, PCI_EXP_LNKSTA_DLLLA); } |