pc: acpi: x2APIC support for MADT table and _MAT method
Signed-off-by: Igor Mammedov <imammedo@redhat.com> Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
This commit is contained in:
parent
a3ae21ec3f
commit
e2c9593945
@ -531,6 +531,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
|||||||
apic->flags = cpu_to_le32(1);
|
apic->flags = cpu_to_le32(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ACPI_APIC_LOCAL_X2APIC: {
|
||||||
|
AcpiMadtProcessorX2Apic *apic = (void *)madt_buf->data;
|
||||||
|
apic->flags = cpu_to_le32(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
@ -340,24 +340,38 @@ build_fadt(GArray *table_data, BIOSLinker *linker, AcpiPmInfo *pm,
|
|||||||
void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
|
void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
|
||||||
CPUArchIdList *apic_ids, GArray *entry)
|
CPUArchIdList *apic_ids, GArray *entry)
|
||||||
{
|
{
|
||||||
int apic_id;
|
uint32_t apic_id = apic_ids->cpus[uid].arch_id;
|
||||||
AcpiMadtProcessorApic *apic = acpi_data_push(entry, sizeof *apic);
|
|
||||||
|
|
||||||
apic_id = apic_ids->cpus[uid].arch_id;
|
/* ACPI spec says that LAPIC entry for non present
|
||||||
apic->type = ACPI_APIC_PROCESSOR;
|
* CPU may be omitted from MADT or it must be marked
|
||||||
apic->length = sizeof(*apic);
|
* as disabled. However omitting non present CPU from
|
||||||
apic->processor_id = uid;
|
* MADT breaks hotplug on linux. So possible CPUs
|
||||||
apic->local_apic_id = apic_id;
|
* should be put in MADT but kept disabled.
|
||||||
if (apic_ids->cpus[uid].cpu != NULL) {
|
*/
|
||||||
apic->flags = cpu_to_le32(1);
|
if (apic_id < 255) {
|
||||||
|
AcpiMadtProcessorApic *apic = acpi_data_push(entry, sizeof *apic);
|
||||||
|
|
||||||
|
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 {
|
||||||
|
apic->flags = cpu_to_le32(0);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* ACPI spec says that LAPIC entry for non present
|
AcpiMadtProcessorX2Apic *apic = acpi_data_push(entry, sizeof *apic);
|
||||||
* CPU may be omitted from MADT or it must be marked
|
|
||||||
* as disabled. However omitting non present CPU from
|
apic->type = ACPI_APIC_LOCAL_X2APIC;
|
||||||
* MADT breaks hotplug on linux. So possible CPUs
|
apic->length = sizeof(*apic);
|
||||||
* should be put in MADT but kept disabled.
|
apic->uid = cpu_to_le32(uid);
|
||||||
*/
|
apic->x2apic_id = cpu_to_le32(apic_id);
|
||||||
apic->flags = cpu_to_le32(0);
|
if (apic_ids->cpus[uid].cpu != NULL) {
|
||||||
|
apic->flags = cpu_to_le32(1);
|
||||||
|
} else {
|
||||||
|
apic->flags = cpu_to_le32(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,11 +383,11 @@ build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
|
|||||||
int madt_start = table_data->len;
|
int madt_start = table_data->len;
|
||||||
AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(pcms->acpi_dev);
|
AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(pcms->acpi_dev);
|
||||||
AcpiDeviceIf *adev = ACPI_DEVICE_IF(pcms->acpi_dev);
|
AcpiDeviceIf *adev = ACPI_DEVICE_IF(pcms->acpi_dev);
|
||||||
|
bool x2apic_mode = false;
|
||||||
|
|
||||||
AcpiMultipleApicTable *madt;
|
AcpiMultipleApicTable *madt;
|
||||||
AcpiMadtIoApic *io_apic;
|
AcpiMadtIoApic *io_apic;
|
||||||
AcpiMadtIntsrcovr *intsrcovr;
|
AcpiMadtIntsrcovr *intsrcovr;
|
||||||
AcpiMadtLocalNmi *local_nmi;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
madt = acpi_data_push(table_data, sizeof *madt);
|
madt = acpi_data_push(table_data, sizeof *madt);
|
||||||
@ -382,6 +396,9 @@ build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
|
|||||||
|
|
||||||
for (i = 0; i < apic_ids->len; i++) {
|
for (i = 0; i < apic_ids->len; i++) {
|
||||||
adevc->madt_cpu(adev, i, apic_ids, table_data);
|
adevc->madt_cpu(adev, i, apic_ids, table_data);
|
||||||
|
if (apic_ids->cpus[i].arch_id > 254) {
|
||||||
|
x2apic_mode = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
g_free(apic_ids);
|
g_free(apic_ids);
|
||||||
|
|
||||||
@ -414,12 +431,25 @@ build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
|
|||||||
intsrcovr->flags = cpu_to_le16(0xd); /* active high, level triggered */
|
intsrcovr->flags = cpu_to_le16(0xd); /* active high, level triggered */
|
||||||
}
|
}
|
||||||
|
|
||||||
local_nmi = acpi_data_push(table_data, sizeof *local_nmi);
|
if (x2apic_mode) {
|
||||||
local_nmi->type = ACPI_APIC_LOCAL_NMI;
|
AcpiMadtLocalX2ApicNmi *local_nmi;
|
||||||
local_nmi->length = sizeof(*local_nmi);
|
|
||||||
local_nmi->processor_id = 0xff; /* all processors */
|
local_nmi = acpi_data_push(table_data, sizeof *local_nmi);
|
||||||
local_nmi->flags = cpu_to_le16(0);
|
local_nmi->type = ACPI_APIC_LOCAL_X2APIC_NMI;
|
||||||
local_nmi->lint = 1; /* ACPI_LINT1 */
|
local_nmi->length = sizeof(*local_nmi);
|
||||||
|
local_nmi->uid = 0xFFFFFFFF; /* all processors */
|
||||||
|
local_nmi->flags = cpu_to_le16(0);
|
||||||
|
local_nmi->lint = 1; /* ACPI_LINT1 */
|
||||||
|
} else {
|
||||||
|
AcpiMadtLocalNmi *local_nmi;
|
||||||
|
|
||||||
|
local_nmi = acpi_data_push(table_data, sizeof *local_nmi);
|
||||||
|
local_nmi->type = ACPI_APIC_LOCAL_NMI;
|
||||||
|
local_nmi->length = sizeof(*local_nmi);
|
||||||
|
local_nmi->processor_id = 0xff; /* all processors */
|
||||||
|
local_nmi->flags = cpu_to_le16(0);
|
||||||
|
local_nmi->lint = 1; /* ACPI_LINT1 */
|
||||||
|
}
|
||||||
|
|
||||||
build_header(linker, table_data,
|
build_header(linker, table_data,
|
||||||
(void *)(table_data->data + madt_start), "APIC",
|
(void *)(table_data->data + madt_start), "APIC",
|
||||||
|
@ -343,6 +343,24 @@ struct AcpiMadtLocalNmi {
|
|||||||
} QEMU_PACKED;
|
} QEMU_PACKED;
|
||||||
typedef struct AcpiMadtLocalNmi AcpiMadtLocalNmi;
|
typedef struct AcpiMadtLocalNmi AcpiMadtLocalNmi;
|
||||||
|
|
||||||
|
struct AcpiMadtProcessorX2Apic {
|
||||||
|
ACPI_SUB_HEADER_DEF
|
||||||
|
uint16_t reserved;
|
||||||
|
uint32_t x2apic_id; /* Processor's local x2APIC ID */
|
||||||
|
uint32_t flags;
|
||||||
|
uint32_t uid; /* Processor object _UID */
|
||||||
|
} QEMU_PACKED;
|
||||||
|
typedef struct AcpiMadtProcessorX2Apic AcpiMadtProcessorX2Apic;
|
||||||
|
|
||||||
|
struct AcpiMadtLocalX2ApicNmi {
|
||||||
|
ACPI_SUB_HEADER_DEF
|
||||||
|
uint16_t flags; /* MPS INTI flags */
|
||||||
|
uint32_t uid; /* Processor object _UID */
|
||||||
|
uint8_t lint; /* Local APIC LINT# */
|
||||||
|
uint8_t reserved[3]; /* Local APIC LINT# */
|
||||||
|
} QEMU_PACKED;
|
||||||
|
typedef struct AcpiMadtLocalX2ApicNmi AcpiMadtLocalX2ApicNmi;
|
||||||
|
|
||||||
struct AcpiMadtGenericInterrupt {
|
struct AcpiMadtGenericInterrupt {
|
||||||
ACPI_SUB_HEADER_DEF
|
ACPI_SUB_HEADER_DEF
|
||||||
uint16_t reserved;
|
uint16_t reserved;
|
||||||
|
Loading…
Reference in New Issue
Block a user