aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/acpi/piix4.c1
-rw-r--r--hw/i386/acpi-build.c45
-rw-r--r--hw/isa/lpc_ich9.c1
-rw-r--r--include/hw/acpi/acpi_dev_interface.h7
-rw-r--r--include/hw/i386/pc.h5
-rw-r--r--stubs/Makefile.objs1
-rw-r--r--stubs/pc_madt_cpu_entry.c7
7 files changed, 49 insertions, 18 deletions
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 6351d2ebb2..6d24cb535b 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -658,6 +658,7 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data)
hc->unplug = piix4_device_unplug_cb;
adevc->ospm_status = piix4_ospm_status;
adevc->send_event = piix4_send_gpe;
+ adevc->madt_cpu = pc_madt_cpu_entry;
}
static const TypeInfo piix4_pm_info = {
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index b3dc1df25a..e35a446a9d 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -329,12 +329,38 @@ build_fadt(GArray *table_data, BIOSLinker *linker, AcpiPmInfo *pm,
(void *)fadt, "FACP", sizeof(*fadt), 1, oem_id, oem_table_id);
}
+void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
+ CPUArchIdList *apic_ids, GArray *entry)
+{
+ int apic_id;
+ AcpiMadtProcessorApic *apic = acpi_data_push(entry, sizeof *apic);
+
+ apic_id = apic_ids->cpus[uid].arch_id;
+ apic->type = ACPI_APIC_PROCESSOR;
+ apic->length = sizeof(*apic);
+ apic->processor_id = uid;
+ apic->local_apic_id = apic_id;
+ if (apic_ids->cpus[uid].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);
+ }
+}
+
static void
build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
{
MachineClass *mc = MACHINE_GET_CLASS(pcms);
CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(pcms));
int madt_start = table_data->len;
+ AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(pcms->acpi_dev);
+ AcpiDeviceIf *adev = ACPI_DEVICE_IF(pcms->acpi_dev);
AcpiMultipleApicTable *madt;
AcpiMadtIoApic *io_apic;
@@ -347,24 +373,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
madt->flags = cpu_to_le32(1);
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 = 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);
- }
+ adevc->madt_cpu(adev, i, apic_ids, table_data);
}
g_free(apic_ids);
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index 213741bc21..c1a4f1b34c 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -714,6 +714,7 @@ static void ich9_lpc_class_init(ObjectClass *klass, void *data)
hc->unplug = ich9_pm_device_unplug_cb;
adevc->ospm_status = ich9_pm_ospm_status;
adevc->send_event = ich9_send_gpe;
+ adevc->madt_cpu = pc_madt_cpu_entry;
}
static const TypeInfo ich9_lpc_info = {
diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h
index a0c4a336f2..da4ef7fbd3 100644
--- a/include/hw/acpi/acpi_dev_interface.h
+++ b/include/hw/acpi/acpi_dev_interface.h
@@ -3,6 +3,7 @@
#include "qom/object.h"
#include "qapi-types.h"
+#include "hw/boards.h"
/* These values are part of guest ABI, and can not be changed */
typedef enum {
@@ -37,6 +38,10 @@ void acpi_send_event(DeviceState *dev, AcpiEventStatusBits event);
* ospm_status: returns status of ACPI device objects, reported
* via _OST method if device supports it.
* send_event: inject a specified event into guest
+ * madt_cpu: fills @entry with Interrupt Controller Structure
+ * for CPU indexed by @uid in @apic_ids array,
+ * returned structure types are:
+ * 0 - Local APIC, 9 - Local x2APIC, 0xB - GICC
*
* Interface is designed for providing unified interface
* to generic ACPI functionality that could be used without
@@ -50,5 +55,7 @@ typedef struct AcpiDeviceIfClass {
/* <public> */
void (*ospm_status)(AcpiDeviceIf *adev, ACPIOSTInfoList ***list);
void (*send_event)(AcpiDeviceIf *adev, AcpiEventStatusBits ev);
+ void (*madt_cpu)(AcpiDeviceIf *adev, int uid,
+ CPUArchIdList *apic_ids, GArray *entry);
} AcpiDeviceIfClass;
#endif
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 49566c89d4..9e239297e8 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -17,6 +17,7 @@
#include "hw/compat.h"
#include "hw/mem/pc-dimm.h"
#include "hw/mem/nvdimm.h"
+#include "hw/acpi/acpi_dev_interface.h"
#define HPET_INTCAP "hpet-intcap"
@@ -345,6 +346,10 @@ void pc_system_firmware_init(MemoryRegion *rom_memory,
/* pvpanic.c */
uint16_t pvpanic_port(void);
+/* acpi-build.c */
+void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
+ CPUArchIdList *apic_ids, GArray *entry);
+
/* e820 types */
#define E820_RAM 1
#define E820_RESERVED 2
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index b829ee6e1a..7cdcad4fdb 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -43,3 +43,4 @@ stub-obj-y += vhost.o
stub-obj-y += iohandler.o
stub-obj-y += smbios_type_38.o
stub-obj-y += ipmi.o
+stub-obj-y += pc_madt_cpu_entry.o
diff --git a/stubs/pc_madt_cpu_entry.c b/stubs/pc_madt_cpu_entry.c
new file mode 100644
index 0000000000..427e772868
--- /dev/null
+++ b/stubs/pc_madt_cpu_entry.c
@@ -0,0 +1,7 @@
+#include "qemu/osdep.h"
+#include "hw/i386/pc.h"
+
+void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
+ CPUArchIdList *apic_ids, GArray *entry)
+{
+}