diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2016-03-15 16:43:48 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2016-03-15 16:43:48 +0000 |
commit | a58a4cb18725117bf69e6bee0a753c8b73b09667 (patch) | |
tree | 4d6a8eb0a68157cacf380ac121376721b9ff6ad2 /hw/i386 | |
parent | f84d587111cc165f0aa6aa49e434fb3afc897c2d (diff) | |
parent | 6a991e07bb8eeb7d7799a949c0528dffb84b2a98 (diff) |
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
vhost, virtio, pci, pc, acpi
nvdimm work
sparse cpu id rework
ipmi enhancements
fixes all over the place
pxb option to tweak chassis number
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
# gpg: Signature made Tue 15 Mar 2016 14:33:10 GMT using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg: aka "Michael S. Tsirkin <mst@redhat.com>"
* remotes/mst/tags/for_upstream: (51 commits)
hw/acpi: fix GSI links UID
ipmi: add some local variables in ipmi_sdr_init
ipmi: remove the need of an ending record in the SDR table
ipmi: use a function to initialize the SDR table
ipmi: add a realize function to the device class
ipmi: add rsp_buffer_set_error() helper
ipmi: remove IPMI_CHECK_RESERVATION() macro
ipmi: replace IPMI_ADD_RSP_DATA() macro with inline helpers
ipmi: remove IPMI_CHECK_CMD_LEN() macro
MAINTAINERS: machine core
MAINTAINERS: Add an entry for virtio header files
pc: acpi: clarify why possible LAPIC entries must be present in MADT
pc: acpi: drop cpu->found_cpus bitmap
pc: acpi: create Processor and Notify objects only for valid lapics
pc: acpi: create MADT.lapic entries only for valid lapics
pc: acpi: SRAT: create only valid processor lapic entries
pc: acpi: cleanup qdev_get_machine() calls
machine: introduce MachineClass.possible_cpu_arch_ids() hook
pc: init pcms->apic_id_limit once and use it throughout pc.c
pc: acpi: remove NOP assignment
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/i386')
-rw-r--r-- | hw/i386/acpi-build.c | 301 | ||||
-rw-r--r-- | hw/i386/kvm/apic.c | 2 | ||||
-rw-r--r-- | hw/i386/pc.c | 97 | ||||
-rw-r--r-- | hw/i386/pc_piix.c | 5 | ||||
-rw-r--r-- | hw/i386/pc_q35.c | 8 | ||||
-rw-r--r-- | hw/i386/xen/xen_apic.c | 2 |
6 files changed, 245 insertions, 170 deletions
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index b888008839..325d8ce13c 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -37,8 +37,8 @@ #include "hw/acpi/bios-linker-loader.h" #include "hw/loader.h" #include "hw/isa/isa.h" +#include "hw/block/fdc.h" #include "hw/acpi/memory_hotplug.h" -#include "hw/mem/nvdimm.h" #include "sysemu/tpm.h" #include "hw/acpi/tpm.h" #include "sysemu/tpm_backend.h" @@ -76,10 +76,6 @@ #define ACPI_BUILD_DPRINTF(fmt, ...) #endif -typedef struct AcpiCpuInfo { - DECLARE_BITMAP(found_cpus, ACPI_CPU_HOTPLUG_ID_LIMIT); -} AcpiCpuInfo; - typedef struct AcpiMcfgInfo { uint64_t mcfg_base; uint32_t mcfg_size; @@ -121,31 +117,6 @@ typedef struct AcpiBuildPciBusHotplugState { bool pcihp_bridge_en; } AcpiBuildPciBusHotplugState; -static -int acpi_add_cpu_info(Object *o, void *opaque) -{ - AcpiCpuInfo *cpu = opaque; - uint64_t apic_id; - - if (object_dynamic_cast(o, TYPE_CPU)) { - apic_id = object_property_get_int(o, "apic-id", NULL); - assert(apic_id < ACPI_CPU_HOTPLUG_ID_LIMIT); - - set_bit(apic_id, cpu->found_cpus); - } - - object_child_foreach(o, acpi_add_cpu_info, opaque); - return 0; -} - -static void acpi_get_cpu_info(AcpiCpuInfo *cpu) -{ - Object *root = object_get_root(); - - memset(cpu->found_cpus, 0, sizeof cpu->found_cpus); - object_child_foreach(root, acpi_add_cpu_info, cpu); -} - static void acpi_get_pm_info(AcpiPmInfo *pm) { Object *piix = piix4_pm_find(); @@ -362,9 +333,10 @@ build_fadt(GArray *table_data, GArray *linker, AcpiPmInfo *pm, } static void -build_madt(GArray *table_data, GArray *linker, AcpiCpuInfo *cpu) +build_madt(GArray *table_data, GArray *linker, PCMachineState *pcms) { - PCMachineState *pcms = PC_MACHINE(qdev_get_machine()); + MachineClass *mc = MACHINE_GET_CLASS(pcms); + CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(pcms)); int madt_start = table_data->len; AcpiMultipleApicTable *madt; @@ -377,18 +349,28 @@ build_madt(GArray *table_data, GArray *linker, AcpiCpuInfo *cpu) madt->local_apic_address = cpu_to_le32(APIC_DEFAULT_ADDRESS); madt->flags = cpu_to_le32(1); - for (i = 0; i < pcms->apic_id_limit; i++) { + for (i = 0; i < apic_ids->len; i++) { AcpiMadtProcessorApic *apic = acpi_data_push(table_data, sizeof *apic); + int apic_id = apic_ids->cpus[i].arch_id; + apic->type = ACPI_APIC_PROCESSOR; apic->length = sizeof(*apic); - apic->processor_id = i; - apic->local_apic_id = i; - if (test_bit(i, cpu->found_cpus)) { + apic->processor_id = apic_id; + apic->local_apic_id = apic_id; + if (apic_ids->cpus[i].cpu != NULL) { apic->flags = cpu_to_le32(1); } else { + /* ACPI spec says that LAPIC entry for non present + * CPU may be omitted from MADT or it must be marked + * as disabled. However omitting non present CPU from + * MADT breaks hotplug on linux. So possible CPUs + * should be put in MADT but kept disabled. + */ apic->flags = cpu_to_le32(0); } } + g_free(apic_ids); + io_apic = acpi_data_push(table_data, sizeof *io_apic); io_apic->type = ACPI_APIC_IO; io_apic->length = sizeof(*io_apic); @@ -960,21 +942,24 @@ static Aml *build_crs(PCIHostState *host, return crs; } -static void build_processor_devices(Aml *sb_scope, unsigned acpi_cpus, - AcpiCpuInfo *cpu, AcpiPmInfo *pm) +static void build_processor_devices(Aml *sb_scope, MachineState *machine, + AcpiPmInfo *pm) { - int i; + int i, apic_idx; Aml *dev; Aml *crs; Aml *pkg; Aml *field; Aml *ifctx; Aml *method; + MachineClass *mc = MACHINE_GET_CLASS(machine); + CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine); + PCMachineState *pcms = PC_MACHINE(machine); /* The current AML generator can cover the APIC ID range [0..255], * inclusive, for VCPU hotplug. */ QEMU_BUILD_BUG_ON(ACPI_CPU_HOTPLUG_ID_LIMIT > 256); - g_assert(acpi_cpus <= ACPI_CPU_HOTPLUG_ID_LIMIT); + g_assert(pcms->apic_id_limit <= ACPI_CPU_HOTPLUG_ID_LIMIT); /* create PCI0.PRES device and its _CRS to reserve CPU hotplug MMIO */ dev = aml_device("PCI0." stringify(CPU_HOTPLUG_RESOURCE_DEVICE)); @@ -993,28 +978,33 @@ static void build_processor_devices(Aml *sb_scope, unsigned acpi_cpus, aml_append(sb_scope, dev); /* declare CPU hotplug MMIO region and PRS field to access it */ aml_append(sb_scope, aml_operation_region( - "PRST", AML_SYSTEM_IO, pm->cpu_hp_io_base, pm->cpu_hp_io_len)); + "PRST", AML_SYSTEM_IO, aml_int(pm->cpu_hp_io_base), pm->cpu_hp_io_len)); field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE); aml_append(field, aml_named_field("PRS", 256)); aml_append(sb_scope, field); /* build Processor object for each processor */ - for (i = 0; i < acpi_cpus; i++) { - dev = aml_processor(i, 0, 0, "CP%.02X", i); + for (i = 0; i < apic_ids->len; i++) { + int apic_id = apic_ids->cpus[i].arch_id; + + assert(apic_id < ACPI_CPU_HOTPLUG_ID_LIMIT); + + dev = aml_processor(apic_id, 0, 0, "CP%.02X", apic_id); method = aml_method("_MAT", 0, AML_NOTSERIALIZED); aml_append(method, - aml_return(aml_call1(CPU_MAT_METHOD, aml_int(i)))); + aml_return(aml_call1(CPU_MAT_METHOD, aml_int(apic_id)))); aml_append(dev, method); method = aml_method("_STA", 0, AML_NOTSERIALIZED); aml_append(method, - aml_return(aml_call1(CPU_STATUS_METHOD, aml_int(i)))); + aml_return(aml_call1(CPU_STATUS_METHOD, aml_int(apic_id)))); aml_append(dev, method); method = aml_method("_EJ0", 1, AML_NOTSERIALIZED); aml_append(method, - aml_return(aml_call2(CPU_EJECT_METHOD, aml_int(i), aml_arg(0))) + aml_return(aml_call2(CPU_EJECT_METHOD, aml_int(apic_id), + aml_arg(0))) ); aml_append(dev, method); @@ -1026,10 +1016,12 @@ static void build_processor_devices(Aml *sb_scope, unsigned acpi_cpus, */ /* Arg0 = Processor ID = APIC ID */ method = aml_method(AML_NOTIFY_METHOD, 2, AML_NOTSERIALIZED); - for (i = 0; i < acpi_cpus; i++) { - ifctx = aml_if(aml_equal(aml_arg(0), aml_int(i))); + for (i = 0; i < apic_ids->len; i++) { + int apic_id = apic_ids->cpus[i].arch_id; + + ifctx = aml_if(aml_equal(aml_arg(0), aml_int(apic_id))); aml_append(ifctx, - aml_notify(aml_name("CP%.02X", i), aml_arg(1)) + aml_notify(aml_name("CP%.02X", apic_id), aml_arg(1)) ); aml_append(method, ifctx); } @@ -1042,14 +1034,20 @@ static void build_processor_devices(Aml *sb_scope, unsigned acpi_cpus, * ith up to 255 elements. Windows guests up to win2k8 fail when * VarPackageOp is used. */ - pkg = acpi_cpus <= 255 ? aml_package(acpi_cpus) : - aml_varpackage(acpi_cpus); + pkg = pcms->apic_id_limit <= 255 ? aml_package(pcms->apic_id_limit) : + aml_varpackage(pcms->apic_id_limit); + + for (i = 0, apic_idx = 0; i < apic_ids->len; i++) { + int apic_id = apic_ids->cpus[i].arch_id; - for (i = 0; i < acpi_cpus; i++) { - uint8_t b = test_bit(i, cpu->found_cpus) ? 0x01 : 0x00; - aml_append(pkg, aml_int(b)); + for (; apic_idx < apic_id; apic_idx++) { + aml_append(pkg, aml_int(0)); + } + aml_append(pkg, aml_int(apic_ids->cpus[i].cpu ? 1 : 0)); + apic_idx = apic_id + 1; } aml_append(sb_scope, aml_name_decl(CPU_ON_BITMAP, pkg)); + g_free(apic_ids); } static void build_memory_devices(Aml *sb_scope, int nr_mem, @@ -1078,7 +1076,7 @@ static void build_memory_devices(Aml *sb_scope, int nr_mem, aml_append(scope, aml_operation_region( MEMORY_HOTPLUG_IO_REGION, AML_SYSTEM_IO, - io_base, io_len) + aml_int(io_base), io_len) ); field = aml_field(MEMORY_HOTPLUG_IO_REGION, AML_DWORD_ACC, @@ -1192,7 +1190,8 @@ static void build_hpet_aml(Aml *table) aml_append(dev, aml_name_decl("_UID", zero)); aml_append(dev, - aml_operation_region("HPTM", AML_SYSTEM_MEMORY, HPET_BASE, HPET_LEN)); + aml_operation_region("HPTM", AML_SYSTEM_MEMORY, aml_int(HPET_BASE), + HPET_LEN)); field = aml_field("HPTM", AML_DWORD_ACC, AML_LOCK, AML_PRESERVE); aml_append(field, aml_named_field("VEND", 32)); aml_append(field, aml_named_field("PRD", 32)); @@ -1227,33 +1226,63 @@ static void build_hpet_aml(Aml *table) aml_append(table, scope); } -static Aml *build_fdc_device_aml(void) +static Aml *build_fdinfo_aml(int idx, FloppyDriveType type) { + Aml *dev, *fdi; + uint8_t maxc, maxh, maxs; + + isa_fdc_get_drive_max_chs(type, &maxc, &maxh, &maxs); + + dev = aml_device("FLP%c", 'A' + idx); + + aml_append(dev, aml_name_decl("_ADR", aml_int(idx))); + + fdi = aml_package(16); + aml_append(fdi, aml_int(idx)); /* Drive Number */ + aml_append(fdi, + aml_int(cmos_get_fd_drive_type(type))); /* Device Type */ + /* + * the values below are the limits of the drive, and are thus independent + * of the inserted media + */ + aml_append(fdi, aml_int(maxc)); /* Maximum Cylinder Number */ + aml_append(fdi, aml_int(maxs)); /* Maximum Sector Number */ + aml_append(fdi, aml_int(maxh)); /* Maximum Head Number */ + /* + * SeaBIOS returns the below values for int 0x13 func 0x08 regardless of + * the drive type, so shall we + */ + aml_append(fdi, aml_int(0xAF)); /* disk_specify_1 */ + aml_append(fdi, aml_int(0x02)); /* disk_specify_2 */ + aml_append(fdi, aml_int(0x25)); /* disk_motor_wait */ + aml_append(fdi, aml_int(0x02)); /* disk_sector_siz */ + aml_append(fdi, aml_int(0x12)); /* disk_eot */ + aml_append(fdi, aml_int(0x1B)); /* disk_rw_gap */ + aml_append(fdi, aml_int(0xFF)); /* disk_dtl */ + aml_append(fdi, aml_int(0x6C)); /* disk_formt_gap */ + aml_append(fdi, aml_int(0xF6)); /* disk_fill */ + aml_append(fdi, aml_int(0x0F)); /* disk_head_sttl */ + aml_append(fdi, aml_int(0x08)); /* disk_motor_strt */ + + aml_append(dev, aml_name_decl("_FDI", fdi)); + return dev; +} + +static Aml *build_fdc_device_aml(ISADevice *fdc) +{ + int i; Aml *dev; Aml *crs; - Aml *method; - Aml *if_ctx; - Aml *else_ctx; - Aml *zero = aml_int(0); - Aml *is_present = aml_local(0); + +#define ACPI_FDE_MAX_FD 4 + uint32_t fde_buf[5] = { + 0, 0, 0, 0, /* presence of floppy drives #0 - #3 */ + cpu_to_le32(2) /* tape presence (2 == never present) */ + }; dev = aml_device("FDC0"); aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0700"))); - method = aml_method("_STA", 0, AML_NOTSERIALIZED); - aml_append(method, aml_store(aml_name("FDEN"), is_present)); - if_ctx = aml_if(aml_equal(is_present, zero)); - { - aml_append(if_ctx, aml_return(aml_int(0x00))); - } - aml_append(method, if_ctx); - else_ctx = aml_else(); - { - aml_append(else_ctx, aml_return(aml_int(0x0f))); - } - aml_append(method, else_ctx); - aml_append(dev, method); - crs = aml_resource_template(); aml_append(crs, aml_io(AML_DECODE16, 0x03F2, 0x03F2, 0x00, 0x04)); aml_append(crs, aml_io(AML_DECODE16, 0x03F7, 0x03F7, 0x00, 0x01)); @@ -1262,6 +1291,17 @@ static Aml *build_fdc_device_aml(void) aml_dma(AML_COMPATIBILITY, AML_NOTBUSMASTER, AML_TRANSFER8, 2)); aml_append(dev, aml_name_decl("_CRS", crs)); + for (i = 0; i < MIN(MAX_FD, ACPI_FDE_MAX_FD); i++) { + FloppyDriveType type = isa_fdc_get_drive_type(fdc, i); + + if (type < FLOPPY_DRIVE_TYPE_NONE) { + fde_buf[i] = cpu_to_le32(1); /* drive present */ + aml_append(dev, build_fdinfo_aml(i, type)); + } + } + aml_append(dev, aml_name_decl("_FDE", + aml_buffer(sizeof(fde_buf), (uint8_t *)fde_buf))); + return dev; } @@ -1406,12 +1446,16 @@ static Aml *build_com_device_aml(uint8_t uid) static void build_isa_devices_aml(Aml *table) { + ISADevice *fdc = pc_find_fdc0(); + Aml *scope = aml_scope("_SB.PCI0.ISA"); aml_append(scope, build_rtc_device_aml()); aml_append(scope, build_kbd_device_aml()); aml_append(scope, build_mouse_device_aml()); - aml_append(scope, build_fdc_device_aml()); + if (fdc) { + aml_append(scope, build_fdc_device_aml(fdc)); + } aml_append(scope, build_lpt_device_aml()); aml_append(scope, build_com_device_aml(1)); aml_append(scope, build_com_device_aml(2)); @@ -1430,7 +1474,7 @@ static void build_dbg_aml(Aml *table) Aml *idx = aml_local(2); aml_append(scope, - aml_operation_region("DBG", AML_SYSTEM_IO, 0x0402, 0x01)); + aml_operation_region("DBG", AML_SYSTEM_IO, aml_int(0x0402), 0x01)); field = aml_field("DBG", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE); aml_append(field, aml_named_field("DBGB", 8)); aml_append(scope, field); @@ -1509,6 +1553,12 @@ static Aml *build_gsi_link_dev(const char *name, uint8_t uid, uint8_t gsi) aml_append(dev, aml_name_decl("_CRS", crs)); + /* + * _DIS can be no-op because the interrupt cannot be disabled. + */ + method = aml_method("_DIS", 0, AML_NOTSERIALIZED); + aml_append(dev, method); + method = aml_method("_SRS", 1, AML_NOTSERIALIZED); aml_append(dev, method); @@ -1742,18 +1792,14 @@ static void build_q35_pci0_int(Aml *table) aml_append(sb_scope, build_link_dev("LNKG", 6, aml_name("PRQG"))); aml_append(sb_scope, build_link_dev("LNKH", 7, aml_name("PRQH"))); - /* - * TODO: UID probably shouldn't be the same for GSIx devices - * but that's how it was in original ASL so keep it for now - */ - aml_append(sb_scope, build_gsi_link_dev("GSIA", 0, 0x10)); - aml_append(sb_scope, build_gsi_link_dev("GSIB", 0, 0x11)); - aml_append(sb_scope, build_gsi_link_dev("GSIC", 0, 0x12)); - aml_append(sb_scope, build_gsi_link_dev("GSID", 0, 0x13)); - aml_append(sb_scope, build_gsi_link_dev("GSIE", 0, 0x14)); - aml_append(sb_scope, build_gsi_link_dev("GSIF", 0, 0x15)); - aml_append(sb_scope, build_gsi_link_dev("GSIG", 0, 0x16)); - aml_append(sb_scope, build_gsi_link_dev("GSIH", 0, 0x17)); + aml_append(sb_scope, build_gsi_link_dev("GSIA", 0x10, 0x10)); + aml_append(sb_scope, build_gsi_link_dev("GSIB", 0x11, 0x11)); + aml_append(sb_scope, build_gsi_link_dev("GSIC", 0x12, 0x12)); + aml_append(sb_scope, build_gsi_link_dev("GSID", 0x13, 0x13)); + aml_append(sb_scope, build_gsi_link_dev("GSIE", 0x14, 0x14)); + aml_append(sb_scope, build_gsi_link_dev("GSIF", 0x15, 0x15)); + aml_append(sb_scope, build_gsi_link_dev("GSIG", 0x16, 0x16)); + aml_append(sb_scope, build_gsi_link_dev("GSIH", 0x17, 0x17)); aml_append(table, sb_scope); } @@ -1770,28 +1816,25 @@ static void build_q35_isa_bridge(Aml *table) /* ICH9 PCI to ISA irq remapping */ aml_append(dev, aml_operation_region("PIRQ", AML_PCI_CONFIG, - 0x60, 0x0C)); + aml_int(0x60), 0x0C)); aml_append(dev, aml_operation_region("LPCD", AML_PCI_CONFIG, - 0x80, 0x02)); + aml_int(0x80), 0x02)); field = aml_field("LPCD", AML_ANY_ACC, AML_NOLOCK, AML_PRESERVE); aml_append(field, aml_named_field("COMA", 3)); aml_append(field, aml_reserved_field(1)); aml_append(field, aml_named_field("COMB", 3)); aml_append(field, aml_reserved_field(1)); aml_append(field, aml_named_field("LPTD", 2)); - aml_append(field, aml_reserved_field(2)); - aml_append(field, aml_named_field("FDCD", 2)); aml_append(dev, field); aml_append(dev, aml_operation_region("LPCE", AML_PCI_CONFIG, - 0x82, 0x02)); + aml_int(0x82), 0x02)); /* enable bits */ field = aml_field("LPCE", AML_ANY_ACC, AML_NOLOCK, AML_PRESERVE); aml_append(field, aml_named_field("CAEN", 1)); aml_append(field, aml_named_field("CBEN", 1)); aml_append(field, aml_named_field("LPEN", 1)); - aml_append(field, aml_named_field("FDEN", 1)); aml_append(dev, field); aml_append(scope, dev); @@ -1808,7 +1851,7 @@ static void build_piix4_pm(Aml *table) aml_append(dev, aml_name_decl("_ADR", aml_int(0x00010003))); aml_append(dev, aml_operation_region("P13C", AML_PCI_CONFIG, - 0x00, 0xff)); + aml_int(0x00), 0xff)); aml_append(scope, dev); aml_append(table, scope); } @@ -1825,7 +1868,7 @@ static void build_piix4_isa_bridge(Aml *table) /* PIIX PCI to ISA irq remapping */ aml_append(dev, aml_operation_region("P40C", AML_PCI_CONFIG, - 0x60, 0x04)); + aml_int(0x60), 0x04)); /* enable bits */ field = aml_field("^PX13.P13C", AML_ANY_ACC, AML_NOLOCK, AML_PRESERVE); /* Offset(0x5f),, 7, */ @@ -1839,7 +1882,6 @@ static void build_piix4_isa_bridge(Aml *table) aml_append(field, aml_reserved_field(3)); aml_append(field, aml_named_field("CBEN", 1)); aml_append(dev, field); - aml_append(dev, aml_name_decl("FDEN", aml_int(1))); aml_append(scope, dev); aml_append(table, scope); @@ -1854,20 +1896,20 @@ static void build_piix4_pci_hotplug(Aml *table) scope = aml_scope("_SB.PCI0"); aml_append(scope, - aml_operation_region("PCST", AML_SYSTEM_IO, 0xae00, 0x08)); + aml_operation_region("PCST", AML_SYSTEM_IO, aml_int(0xae00), 0x08)); field = aml_field("PCST", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS); aml_append(field, aml_named_field("PCIU", 32)); aml_append(field, aml_named_field("PCID", 32)); aml_append(scope, field); aml_append(scope, - aml_operation_region("SEJ", AML_SYSTEM_IO, 0xae08, 0x04)); + aml_operation_region("SEJ", AML_SYSTEM_IO, aml_int(0xae08), 0x04)); field = aml_field("SEJ", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS); aml_append(field, aml_named_field("B0EJ", 32)); aml_append(scope, field); aml_append(scope, - aml_operation_region("BNMR", AML_SYSTEM_IO, 0xae10, 0x04)); + aml_operation_region("BNMR", AML_SYSTEM_IO, aml_int(0xae10), 0x04)); field = aml_field("BNMR", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS); aml_append(field, aml_named_field("BNUM", 32)); aml_append(scope, field); @@ -1937,14 +1979,13 @@ static Aml *build_q35_osc_method(void) static void build_dsdt(GArray *table_data, GArray *linker, - AcpiCpuInfo *cpu, AcpiPmInfo *pm, AcpiMiscInfo *misc, - PcPciInfo *pci) + AcpiPmInfo *pm, AcpiMiscInfo *misc, + PcPciInfo *pci, MachineState *machine) { CrsRangeEntry *entry; Aml *dsdt, *sb_scope, *scope, *dev, *method, *field, *pkg, *crs; GPtrArray *mem_ranges = g_ptr_array_new_with_free_func(crs_range_free); GPtrArray *io_ranges = g_ptr_array_new_with_free_func(crs_range_free); - MachineState *machine = MACHINE(qdev_get_machine()); PCMachineState *pcms = PC_MACHINE(machine); uint32_t nr_mem = machine->ram_slots; int root_bus_limit = 0xFF; @@ -1975,9 +2016,9 @@ build_dsdt(GArray *table_data, GArray *linker, } else { sb_scope = aml_scope("_SB"); aml_append(sb_scope, - aml_operation_region("PCST", AML_SYSTEM_IO, 0xae00, 0x0c)); + aml_operation_region("PCST", AML_SYSTEM_IO, aml_int(0xae00), 0x0c)); aml_append(sb_scope, - aml_operation_region("PCSB", AML_SYSTEM_IO, 0xae0c, 0x01)); + aml_operation_region("PCSB", AML_SYSTEM_IO, aml_int(0xae0c), 0x01)); field = aml_field("PCSB", AML_ANY_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS); aml_append(field, aml_named_field("PCIB", 8)); aml_append(sb_scope, field); @@ -2252,7 +2293,7 @@ build_dsdt(GArray *table_data, GArray *linker, aml_append(dev, aml_name_decl("_CRS", crs)); aml_append(dev, aml_operation_region("PEOR", AML_SYSTEM_IO, - misc->pvpanic_port, 1)); + aml_int(misc->pvpanic_port), 1)); field = aml_field("PEOR", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE); aml_append(field, aml_named_field("PEPT", 8)); aml_append(dev, field); @@ -2275,7 +2316,7 @@ build_dsdt(GArray *table_data, GArray *linker, sb_scope = aml_scope("\\_SB"); { - build_processor_devices(sb_scope, pcms->apic_id_limit, cpu, pm); + build_processor_devices(sb_scope, machine, pm); build_memory_devices(sb_scope, nr_mem, pm->mem_hp_io_base, pm->mem_hp_io_len); @@ -2396,7 +2437,7 @@ acpi_build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base, } static void -build_srat(GArray *table_data, GArray *linker) +build_srat(GArray *table_data, GArray *linker, MachineState *machine) { AcpiSystemResourceAffinityTable *srat; AcpiSratProcessorAffinity *core; @@ -2406,7 +2447,9 @@ build_srat(GArray *table_data, GArray *linker) uint64_t curnode; int srat_start, numa_start, slots; uint64_t mem_len, mem_base, next_base; - PCMachineState *pcms = PC_MACHINE(qdev_get_machine()); + MachineClass *mc = MACHINE_GET_CLASS(machine); + CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine); + PCMachineState *pcms = PC_MACHINE(machine); ram_addr_t hotplugabble_address_space_size = object_property_get_int(OBJECT(pcms), PC_MACHINE_MEMHP_REGION_SIZE, NULL); @@ -2415,14 +2458,15 @@ build_srat(GArray *table_data, GArray *linker) srat = acpi_data_push(table_data, sizeof *srat); srat->reserved1 = cpu_to_le32(1); - core = (void *)(srat + 1); - for (i = 0; i < pcms->apic_id_limit; ++i) { + for (i = 0; i < apic_ids->len; i++) { + int apic_id = apic_ids->cpus[i].arch_id; + core = acpi_data_push(table_data, sizeof *core); core->type = ACPI_SRAT_PROCESSOR; core->length = sizeof(*core); - core->local_apic_id = i; - curnode = pcms->node_cpu[i]; + core->local_apic_id = apic_id; + curnode = pcms->node_cpu[apic_id]; core->proximity_lo = curnode; memset(core->proximity_hi, 0, 3); core->local_sapic_eid = 0; @@ -2487,6 +2531,7 @@ build_srat(GArray *table_data, GArray *linker) (void *)(table_data->data + srat_start), "SRAT", table_data->len - srat_start, 1, NULL, NULL); + g_free(apic_ids); } static void @@ -2610,21 +2655,13 @@ static bool acpi_has_iommu(void) return intel_iommu && !ambiguous; } -static bool acpi_has_nvdimm(void) -{ - PCMachineState *pcms = PC_MACHINE(qdev_get_machine()); - - return pcms->nvdimm; -} - static -void acpi_build(AcpiBuildTables *tables) +void acpi_build(AcpiBuildTables *tables, MachineState *machine) { - PCMachineState *pcms = PC_MACHINE(qdev_get_machine()); + PCMachineState *pcms = PC_MACHINE(machine); PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); GArray *table_offsets; unsigned facs, dsdt, rsdt, fadt; - AcpiCpuInfo cpu; AcpiPmInfo pm; AcpiMiscInfo misc; AcpiMcfgInfo mcfg; @@ -2634,7 +2671,6 @@ void acpi_build(AcpiBuildTables *tables) GArray *tables_blob = tables->table_data; AcpiSlicOem slic_oem = { .id = NULL, .table_id = NULL }; - acpi_get_cpu_info(&cpu); acpi_get_pm_info(&pm); acpi_get_misc_info(&misc); acpi_get_pci_info(&pci); @@ -2658,7 +2694,7 @@ void acpi_build(AcpiBuildTables *tables) /* DSDT is pointed to by FADT */ dsdt = tables_blob->len; - build_dsdt(tables_blob, tables->linker, &cpu, &pm, &misc, &pci); + build_dsdt(tables_blob, tables->linker, &pm, &misc, &pci, machine); /* Count the size of the DSDT and SSDT, we will need it for legacy * sizing of ACPI tables. @@ -2673,7 +2709,7 @@ void acpi_build(AcpiBuildTables *tables) aml_len += tables_blob->len - fadt; acpi_add_table(table_offsets, tables_blob); - build_madt(tables_blob, tables->linker, &cpu); + build_madt(tables_blob, tables->linker, pcms); if (misc.has_hpet) { acpi_add_table(table_offsets, tables_blob); @@ -2690,7 +2726,7 @@ void acpi_build(AcpiBuildTables *tables) } if (pcms->numa_nodes) { acpi_add_table(table_offsets, tables_blob); - build_srat(tables_blob, tables->linker); + build_srat(tables_blob, tables->linker, machine); } if (acpi_get_mcfg(&mcfg)) { acpi_add_table(table_offsets, tables_blob); @@ -2700,8 +2736,7 @@ void acpi_build(AcpiBuildTables *tables) acpi_add_table(table_offsets, tables_blob); build_dmar_q35(tables_blob, tables->linker); } - - if (acpi_has_nvdimm()) { + if (pcms->acpi_nvdimm_state.is_enabled) { nvdimm_build_acpi(table_offsets, tables_blob, tables->linker); } @@ -2795,7 +2830,7 @@ static void acpi_build_update(void *build_opaque) acpi_build_tables_init(&tables); - acpi_build(&tables); + acpi_build(&tables, MACHINE(qdev_get_machine())); acpi_ram_update(build_state->table_mr, tables.table_data); @@ -2860,7 +2895,7 @@ void acpi_setup(void) acpi_set_pci_info(); acpi_build_tables_init(&tables); - acpi_build(&tables); + acpi_build(&tables, MACHINE(pcms)); /* Now expose it all to Guest */ build_state->table_mr = acpi_add_rom_blob(build_state, tables.table_data, diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c index 694d3989b2..3c7c8fa007 100644 --- a/hw/i386/kvm/apic.c +++ b/hw/i386/kvm/apic.c @@ -186,7 +186,7 @@ static void kvm_apic_realize(DeviceState *dev, Error **errp) APIC_SPACE_SIZE); if (kvm_has_gsi_routing()) { - msi_supported = true; + msi_nonbroken = true; } } diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 56ec6cd6c6..2ac97c4f29 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -199,7 +199,7 @@ static void pic_irq_request(void *opaque, int irq, int level) #define REG_EQUIPMENT_BYTE 0x14 -static int cmos_get_fd_drive_type(FloppyDriveType fd0) +int cmos_get_fd_drive_type(FloppyDriveType fd0) { int val; @@ -699,18 +699,6 @@ static uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index) } } -/* Calculates the limit to CPU APIC ID values - * - * This function returns the limit for the APIC ID value, so that all - * CPU APIC IDs are < pc_apic_id_limit(). - * - * This is used for FW_CFG_MAX_CPUS. See comments on bochs_bios_init(). - */ -static unsigned int pc_apic_id_limit(unsigned int max_cpus) -{ - return x86_cpu_apic_id_from_index(max_cpus - 1) + 1; -} - static void pc_build_smbios(FWCfgState *fw_cfg) { uint8_t *smbios_tables, *smbios_anchor; @@ -748,12 +736,11 @@ static void pc_build_smbios(FWCfgState *fw_cfg) } } -static FWCfgState *bochs_bios_init(AddressSpace *as) +static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms) { FWCfgState *fw_cfg; uint64_t *numa_fw_cfg; int i, j; - unsigned int apic_id_limit = pc_apic_id_limit(max_cpus); fw_cfg = fw_cfg_init_io_dma(FW_CFG_IO_BASE, FW_CFG_IO_BASE + 4, as); @@ -771,7 +758,7 @@ static FWCfgState *bochs_bios_init(AddressSpace *as) * [1] The only kind of "CPU identifier" used between SeaBIOS and QEMU is * the APIC ID, not the "CPU index" */ - fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)apic_id_limit); + fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)pcms->apic_id_limit); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES, acpi_tables, acpi_tables_len); @@ -789,11 +776,11 @@ static FWCfgState *bochs_bios_init(AddressSpace *as) * of nodes, one word for each VCPU->node and one word for each node to * hold the amount of memory. */ - numa_fw_cfg = g_new0(uint64_t, 1 + apic_id_limit + nb_numa_nodes); + numa_fw_cfg = g_new0(uint64_t, 1 + pcms->apic_id_limit + nb_numa_nodes); numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes); for (i = 0; i < max_cpus; i++) { unsigned int apic_id = x86_cpu_apic_id_from_index(i); - assert(apic_id < apic_id_limit); + assert(apic_id < pcms->apic_id_limit); for (j = 0; j < nb_numa_nodes; j++) { if (test_bit(i, numa_info[j].node_cpu)) { numa_fw_cfg[apic_id + 1] = cpu_to_le64(j); @@ -802,10 +789,11 @@ static FWCfgState *bochs_bios_init(AddressSpace *as) } } for (i = 0; i < nb_numa_nodes; i++) { - numa_fw_cfg[apic_id_limit + 1 + i] = cpu_to_le64(numa_info[i].node_mem); + numa_fw_cfg[pcms->apic_id_limit + 1 + i] = + cpu_to_le64(numa_info[i].node_mem); } fw_cfg_add_bytes(fw_cfg, FW_CFG_NUMA, numa_fw_cfg, - (1 + apic_id_limit + nb_numa_nodes) * + (1 + pcms->apic_id_limit + nb_numa_nodes) * sizeof(*numa_fw_cfg)); return fw_cfg; @@ -1119,7 +1107,6 @@ void pc_cpus_init(PCMachineState *pcms) int i; X86CPU *cpu = NULL; MachineState *machine = MACHINE(pcms); - unsigned long apic_id_limit; /* init CPUs */ if (machine->cpu_model == NULL) { @@ -1130,17 +1117,31 @@ void pc_cpus_init(PCMachineState *pcms) #endif } - apic_id_limit = pc_apic_id_limit(max_cpus); - if (apic_id_limit > ACPI_CPU_HOTPLUG_ID_LIMIT) { - error_report("max_cpus is too large. APIC ID of last CPU is %lu", - apic_id_limit - 1); + /* Calculates the limit to CPU APIC ID values + * + * Limit for the APIC ID value, so that all + * CPU APIC IDs are < pcms->apic_id_limit. + * + * This is used for FW_CFG_MAX_CPUS. See comments on bochs_bios_init(). + */ + pcms->apic_id_limit = x86_cpu_apic_id_from_index(max_cpus - 1) + 1; + if (pcms->apic_id_limit > ACPI_CPU_HOTPLUG_ID_LIMIT) { + error_report("max_cpus is too large. APIC ID of last CPU is %u", + pcms->apic_id_limit - 1); exit(1); } - for (i = 0; i < smp_cpus; i++) { - cpu = pc_new_cpu(machine->cpu_model, x86_cpu_apic_id_from_index(i), - &error_fatal); - object_unref(OBJECT(cpu)); + pcms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + + sizeof(CPUArchId) * max_cpus); + for (i = 0; i < max_cpus; i++) { + pcms->possible_cpus->cpus[i].arch_id = x86_cpu_apic_id_from_index(i); + pcms->possible_cpus->len++; + if (i < smp_cpus) { + cpu = pc_new_cpu(machine->cpu_model, x86_cpu_apic_id_from_index(i), + &error_fatal); + pcms->possible_cpus->cpus[i].cpu = CPU(cpu); + object_unref(OBJECT(cpu)); + } } /* tell smbios about cpuid version and features */ @@ -1186,7 +1187,6 @@ void pc_guest_info_init(PCMachineState *pcms) { int i, j; - pcms->apic_id_limit = pc_apic_id_limit(max_cpus); pcms->apic_xrupt_override = kvm_allows_irq0_override(); pcms->numa_nodes = nb_numa_nodes; pcms->node_mem = g_malloc0(pcms->numa_nodes * @@ -1371,7 +1371,7 @@ void pc_memory_init(PCMachineState *pcms, option_rom_mr, 1); - fw_cfg = bochs_bios_init(&address_space_memory); + fw_cfg = bochs_bios_init(&address_space_memory, pcms); rom_set_fw(fw_cfg); @@ -1664,9 +1664,19 @@ static void pc_dimm_unplug(HotplugHandler *hotplug_dev, error_propagate(errp, local_err); } +static int pc_apic_cmp(const void *a, const void *b) +{ + CPUArchId *apic_a = (CPUArchId *)a; + CPUArchId *apic_b = (CPUArchId *)b; + + return apic_a->arch_id - apic_b->arch_id; +} + static void pc_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { + CPUClass *cc = CPU_GET_CLASS(dev); + CPUArchId apic_id, *found_cpu; HotplugHandlerClass *hhc; Error *local_err = NULL; PCMachineState *pcms = PC_MACHINE(hotplug_dev); @@ -1689,6 +1699,13 @@ static void pc_cpu_plug(HotplugHandler *hotplug_dev, /* increment the number of CPUs */ rtc_set_memory(pcms->rtc, 0x5f, rtc_get_memory(pcms->rtc, 0x5f) + 1); + + apic_id.arch_id = cc->get_arch_id(CPU(dev)); + found_cpu = bsearch(&apic_id, pcms->possible_cpus->cpus, + pcms->possible_cpus->len, sizeof(*pcms->possible_cpus->cpus), + pc_apic_cmp); + assert(found_cpu); + found_cpu->cpu = CPU(dev); out: error_propagate(errp, local_err); } @@ -1853,14 +1870,14 @@ static bool pc_machine_get_nvdimm(Object *obj, Error **errp) { PCMachineState *pcms = PC_MACHINE(obj); - return pcms->nvdimm; + return pcms->acpi_nvdimm_state.is_enabled; } static void pc_machine_set_nvdimm(Object *obj, bool value, Error **errp) { PCMachineState *pcms = PC_MACHINE(obj); - pcms->nvdimm = value; + pcms->acpi_nvdimm_state.is_enabled = value; } static void pc_machine_initfn(Object *obj) @@ -1899,7 +1916,7 @@ static void pc_machine_initfn(Object *obj) &error_abort); /* nvdimm is disabled on default. */ - pcms->nvdimm = false; + pcms->acpi_nvdimm_state.is_enabled = false; object_property_add_bool(obj, PC_MACHINE_NVDIMM, pc_machine_get_nvdimm, pc_machine_set_nvdimm, &error_abort); } @@ -1931,6 +1948,17 @@ static unsigned pc_cpu_index_to_socket_id(unsigned cpu_index) return topo.pkg_id; } +static CPUArchIdList *pc_possible_cpu_arch_ids(MachineState *machine) +{ + PCMachineState *pcms = PC_MACHINE(machine); + int len = sizeof(CPUArchIdList) + + sizeof(CPUArchId) * (pcms->possible_cpus->len); + CPUArchIdList *list = g_malloc(len); + + memcpy(list, pcms->possible_cpus, len); + return list; +} + static void pc_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -1953,6 +1981,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) pcmc->save_tsc_khz = true; mc->get_hotplug_handler = pc_get_hotpug_handler; mc->cpu_index_to_socket_id = pc_cpu_index_to_socket_id; + mc->possible_cpu_arch_ids = pc_possible_cpu_arch_ids; mc->default_boot_order = "cad"; mc->hot_add_cpu = pc_hot_add_cpu; mc->max_cpus = 255; diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 6f8c2cd816..6a69b23abc 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -274,6 +274,11 @@ static void pc_init1(MachineState *machine, if (pcmc->pci_enabled) { pc_pci_device_init(pci_bus); } + + if (pcms->acpi_nvdimm_state.is_enabled) { + nvdimm_init_acpi_state(&pcms->acpi_nvdimm_state, system_io, + pcms->fw_cfg, OBJECT(pcms)); + } } /* Looking for a pc_compat_2_4() function? It doesn't exist. diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 46522c90da..17915b05c4 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -61,6 +61,7 @@ static void pc_q35_init(MachineState *machine) PCIDevice *lpc; BusState *idebus[MAX_SATA_PORTS]; ISADevice *rtc_state; + MemoryRegion *system_io = get_system_io(); MemoryRegion *pci_memory; MemoryRegion *rom_memory; MemoryRegion *ram_memory; @@ -160,7 +161,7 @@ static void pc_q35_init(MachineState *machine) q35_host->mch.ram_memory = ram_memory; q35_host->mch.pci_address_space = pci_memory; q35_host->mch.system_memory = get_system_memory(); - q35_host->mch.address_space_io = get_system_io(); + q35_host->mch.address_space_io = system_io; q35_host->mch.below_4g_mem_size = pcms->below_4g_mem_size; q35_host->mch.above_4g_mem_size = pcms->above_4g_mem_size; /* pci */ @@ -251,6 +252,11 @@ static void pc_q35_init(MachineState *machine) if (pcmc->pci_enabled) { pc_pci_device_init(host_bus); } + + if (pcms->acpi_nvdimm_state.is_enabled) { + nvdimm_init_acpi_state(&pcms->acpi_nvdimm_state, system_io, + pcms->fw_cfg, OBJECT(pcms)); + } } #define DEFINE_Q35_MACHINE(suffix, name, compatfn, optionfn) \ diff --git a/hw/i386/xen/xen_apic.c b/hw/i386/xen/xen_apic.c index 2b8d709d4d..21d68ee04b 100644 --- a/hw/i386/xen/xen_apic.c +++ b/hw/i386/xen/xen_apic.c @@ -44,7 +44,7 @@ static void xen_apic_realize(DeviceState *dev, Error **errp) s->vapic_control = 0; memory_region_init_io(&s->io_memory, OBJECT(s), &xen_apic_io_ops, s, "xen-apic-msi", APIC_SPACE_SIZE); - msi_supported = true; + msi_nonbroken = true; } static void xen_apic_set_base(APICCommonState *s, uint64_t val) |