diff options
Diffstat (limited to 'hw/i386')
| -rw-r--r-- | hw/i386/acpi-build.c | 72 | ||||
| -rw-r--r-- | hw/i386/pc.c | 31 | ||||
| -rw-r--r-- | hw/i386/pc_piix.c | 1 | ||||
| -rw-r--r-- | hw/i386/pc_q35.c | 2 | ||||
| -rw-r--r-- | hw/i386/x86.c | 11 |
5 files changed, 73 insertions, 44 deletions
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 0e0535d2e3..8d14e4667a 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -95,6 +95,8 @@ typedef struct AcpiPmInfo { bool s3_disabled; bool s4_disabled; bool pcihp_bridge_en; + bool smi_on_cpuhp; + bool pcihp_root_en; uint8_t s4_val; AcpiFadtData fadt; uint16_t cpu_hp_io_base; @@ -194,6 +196,7 @@ static void acpi_get_pm_info(MachineState *machine, AcpiPmInfo *pm) pm->cpu_hp_io_base = 0; pm->pcihp_io_base = 0; pm->pcihp_io_len = 0; + pm->smi_on_cpuhp = false; assert(obj); init_common_fadt_data(machine, obj, &pm->fadt); @@ -207,12 +210,16 @@ static void acpi_get_pm_info(MachineState *machine, AcpiPmInfo *pm) object_property_get_uint(obj, ACPI_PCIHP_IO_LEN_PROP, NULL); } if (lpc) { + uint64_t smi_features = object_property_get_uint(lpc, + ICH9_LPC_SMI_NEGOTIATED_FEAT_PROP, NULL); struct AcpiGenericAddress r = { .space_id = AML_AS_SYSTEM_IO, .bit_width = 8, .address = ICH9_RST_CNT_IOPORT }; pm->fadt.reset_reg = r; pm->fadt.reset_val = 0xf; pm->fadt.flags |= 1 << ACPI_FADT_F_RESET_REG_SUP; pm->cpu_hp_io_base = ICH9_CPU_HOTPLUG_IO_BASE; + pm->smi_on_cpuhp = + !!(smi_features & BIT_ULL(ICH9_LPC_SMI_F_CPU_HOTPLUG_BIT)); } /* The above need not be conditional on machine type because the reset port @@ -245,6 +252,9 @@ static void acpi_get_pm_info(MachineState *machine, AcpiPmInfo *pm) pm->pcihp_bridge_en = object_property_get_bool(obj, "acpi-pci-hotplug-with-bridge-support", NULL); + pm->pcihp_root_en = + object_property_get_bool(obj, "acpi-root-pci-hotplug", + NULL); } static void acpi_get_misc_info(AcpiMiscInfo *info) @@ -359,6 +369,7 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, int slot = PCI_SLOT(i); bool hotplug_enabled_dev; bool bridge_in_acpi; + bool cold_plugged_bridge; if (!pdev) { if (bsel) { /* add hotplug slots for non present devices */ @@ -380,15 +391,14 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, pc = PCI_DEVICE_GET_CLASS(pdev); dc = DEVICE_GET_CLASS(pdev); - /* When hotplug for bridges is enabled, bridges are - * described in ACPI separately (see build_pci_bus_end). - * In this case they aren't themselves hot-pluggable. + /* + * Cold plugged bridges aren't themselves hot-pluggable. * Hotplugged bridges *are* hot-pluggable. */ - bridge_in_acpi = pc->is_bridge && pcihp_bridge_en && - !DEVICE(pdev)->hotplugged; + cold_plugged_bridge = pc->is_bridge && !DEVICE(pdev)->hotplugged; + bridge_in_acpi = cold_plugged_bridge && pcihp_bridge_en; - hotplug_enabled_dev = bsel && dc->hotpluggable && !bridge_in_acpi; + hotplug_enabled_dev = bsel && dc->hotpluggable && !cold_plugged_bridge; if (pc->class_id == PCI_CLASS_BRIDGE_ISA) { continue; @@ -450,10 +460,12 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, } /* Append PCNT method to notify about events on local and child buses. - * Add unconditionally for root since DSDT expects it. + * Add this method for root bus only when hotplug is enabled since DSDT + * expects it. */ - method = aml_method("PCNT", 0, AML_NOTSERIALIZED); - + if (bsel || pcihp_bridge_en) { + method = aml_method("PCNT", 0, AML_NOTSERIALIZED); + } /* If bus supports hotplug select it and notify about local events */ if (bsel) { uint64_t bsel_val = qnum_get_uint(qobject_to(QNum, bsel)); @@ -479,7 +491,10 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, aml_append(method, aml_name("^S%.02X.PCNT", devfn)); } } - aml_append(parent_scope, method); + + if (bsel || pcihp_bridge_en) { + aml_append(parent_scope, method); + } qobject_unref(bsel); } @@ -1504,7 +1519,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, build_hpet_aml(dsdt); build_piix4_isa_bridge(dsdt); build_isa_devices_aml(dsdt); - build_piix4_pci_hotplug(dsdt); + if (pm->pcihp_bridge_en || pm->pcihp_root_en) { + build_piix4_pci_hotplug(dsdt); + } build_piix4_pci0_int(dsdt); } else { sb_scope = aml_scope("_SB"); @@ -1515,6 +1532,32 @@ 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 (pm->smi_on_cpuhp) { + /* reserve SMI block resources, IO ports 0xB2, 0xB3 */ + dev = aml_device("PCI0.SMI0"); + aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A06"))); + aml_append(dev, aml_name_decl("_UID", aml_string("SMI resources"))); + crs = aml_resource_template(); + aml_append(crs, + aml_io( + AML_DECODE16, + ACPI_PORT_SMI_CMD, + ACPI_PORT_SMI_CMD, + 1, + 2) + ); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(dev, aml_operation_region("SMIR", AML_SYSTEM_IO, + aml_int(ACPI_PORT_SMI_CMD), 2)); + field = aml_field("SMIR", AML_BYTE_ACC, AML_NOLOCK, + AML_WRITE_AS_ZEROS); + aml_append(field, aml_named_field("SMIC", 8)); + aml_append(field, aml_reserved_field(8)); + aml_append(dev, field); + aml_append(sb_scope, dev); + } + aml_append(dsdt, sb_scope); build_hpet_aml(dsdt); @@ -1530,7 +1573,8 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, build_legacy_cpu_hotplug_aml(dsdt, machine, pm->cpu_hp_io_base); } else { CPUHotplugFeatures opts = { - .acpi_1_compatible = true, .has_legacy_cphp = true + .acpi_1_compatible = true, .has_legacy_cphp = true, + .smi_path = pm->smi_on_cpuhp ? "\\_SB.PCI0.SMI0.SMIC" : NULL, }; build_cpus_aml(dsdt, machine, opts, pm->cpu_hp_io_base, "\\_SB.PCI0", "\\_GPE._E02"); @@ -1546,7 +1590,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, { aml_append(scope, aml_name_decl("_HID", aml_string("ACPI0006"))); - if (misc->is_piix4) { + if (misc->is_piix4 && (pm->pcihp_bridge_en || pm->pcihp_root_en)) { method = aml_method("_E01", 0, AML_NOTSERIALIZED); aml_append(method, aml_acquire(aml_name("\\_SB.PCI0.BLCK"), 0xFFFF)); @@ -1698,7 +1742,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, crs_range_set_free(&crs_range_set); /* reserve PCIHP resources */ - if (pm->pcihp_io_len) { + if (pm->pcihp_io_len && (pm->pcihp_bridge_en || pm->pcihp_root_en)) { dev = aml_device("PHPR"); aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A06"))); aml_append(dev, diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 1e2ab5ebe7..2c6194e57f 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -97,7 +97,9 @@ #include "trace.h" #include CONFIG_DEVICES -GlobalProperty pc_compat_5_1[] = {}; +GlobalProperty pc_compat_5_1[] = { + { "ICH9-LPC", "x-smi-cpu-hotplug", "off" }, +}; const size_t pc_compat_5_1_len = G_N_ELEMENTS(pc_compat_5_1); GlobalProperty pc_compat_5_0[] = { @@ -769,32 +771,6 @@ void pc_smp_parse(MachineState *ms, QemuOpts *opts) } } -void pc_hot_add_cpu(MachineState *ms, const int64_t id, Error **errp) -{ - X86MachineState *x86ms = X86_MACHINE(ms); - int64_t apic_id = x86_cpu_apic_id_from_index(x86ms, id); - Error *local_err = NULL; - - if (id < 0) { - error_setg(errp, "Invalid CPU id: %" PRIi64, id); - return; - } - - if (apic_id >= ACPI_CPU_HOTPLUG_ID_LIMIT) { - error_setg(errp, "Unable to add CPU: %" PRIi64 - ", resulting APIC ID (%" PRIi64 ") is too large", - id, apic_id); - return; - } - - - x86_cpu_new(X86_MACHINE(ms), apic_id, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } -} - static void pc_machine_done(Notifier *notifier, void *data) { @@ -1691,7 +1667,6 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) mc->auto_enable_numa_with_memdev = true; mc->has_hotpluggable_cpus = true; mc->default_boot_order = "cad"; - mc->hot_add_cpu = pc_hot_add_cpu; mc->smp_parse = pc_smp_parse; mc->block_default_type = IF_IDE; mc->max_cpus = 255; diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 6f3e78bb60..2d8413a0ce 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -752,7 +752,6 @@ static void pc_i440fx_1_4_machine_options(MachineClass *m) { pc_i440fx_1_5_machine_options(m); m->hw_version = "1.4.0"; - m->hot_add_cpu = NULL; compat_props_add(m->compat_props, pc_compat_1_4, pc_compat_1_4_len); } diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 622d039717..e1c415f57d 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -382,7 +382,7 @@ static void pc_q35_5_0_machine_options(MachineClass *m) m->numa_mem_supported = true; compat_props_add(m->compat_props, hw_compat_5_0, hw_compat_5_0_len); compat_props_add(m->compat_props, pc_compat_5_0, pc_compat_5_0_len); - m->auto_enable_numa_with_memhp = false; + m->auto_enable_numa_with_memdev = false; } DEFINE_Q35_MACHINE(v5_0, "pc-q35-5.0", NULL, diff --git a/hw/i386/x86.c b/hw/i386/x86.c index c2ea989579..403c2b1dad 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -279,6 +279,17 @@ void x86_cpu_pre_plug(HotplugHandler *hotplug_dev, return; } + if (x86ms->acpi_dev) { + Error *local_err = NULL; + + hotplug_handler_pre_plug(HOTPLUG_HANDLER(x86ms->acpi_dev), dev, + &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + } + init_topo_info(&topo_info, x86ms); env->nr_dies = x86ms->smp_dies; |