aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/acpi/core.c11
-rw-r--r--hw/acpi/ich9.c2
-rw-r--r--hw/acpi/piix4.c5
-rw-r--r--hw/core/machine.c5
-rw-r--r--hw/i386/acpi-build.c72
-rw-r--r--hw/isa/lpc_ich9.c1
-rw-r--r--hw/isa/vt82c686.c2
-rw-r--r--hw/net/virtio-net.c18
-rw-r--r--hw/pci-host/gpex-acpi.c1
-rw-r--r--hw/pci/pci.c6
-rw-r--r--hw/pci/pcie.c19
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);
}