Commit e2c95939 authored by Igor Mammedov's avatar Igor Mammedov Committed by Eduardo Habkost
Browse files

pc: acpi: x2APIC support for MADT table and _MAT method

parent a3ae21ec
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -531,6 +531,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
                apic->flags = cpu_to_le32(1);
                break;
            }
            case ACPI_APIC_LOCAL_X2APIC: {
                AcpiMadtProcessorX2Apic *apic = (void *)madt_buf->data;
                apic->flags = cpu_to_le32(1);
                break;
            }
            default:
                assert(0);
            }
+54 −24
Original line number Diff line number Diff line
@@ -340,10 +340,17 @@ build_fadt(GArray *table_data, BIOSLinker *linker, AcpiPmInfo *pm,
void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
                       CPUArchIdList *apic_ids, GArray *entry)
{
    int apic_id;
    uint32_t apic_id = apic_ids->cpus[uid].arch_id;

    /* 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.
     */
    if (apic_id < 255) {
        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;
@@ -351,15 +358,22 @@ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
        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);
        }
    } else {
        AcpiMadtProcessorX2Apic *apic = acpi_data_push(entry, sizeof *apic);

        apic->type = ACPI_APIC_LOCAL_X2APIC;
        apic->length = sizeof(*apic);
        apic->uid = cpu_to_le32(uid);
        apic->x2apic_id = cpu_to_le32(apic_id);
        if (apic_ids->cpus[uid].cpu != NULL) {
            apic->flags = cpu_to_le32(1);
        } else {
            apic->flags = cpu_to_le32(0);
        }
    }
}

static void
build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
@@ -369,11 +383,11 @@ build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *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);
    bool x2apic_mode = false;

    AcpiMultipleApicTable *madt;
    AcpiMadtIoApic *io_apic;
    AcpiMadtIntsrcovr *intsrcovr;
    AcpiMadtLocalNmi *local_nmi;
    int i;

    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++) {
        adevc->madt_cpu(adev, i, apic_ids, table_data);
        if (apic_ids->cpus[i].arch_id > 254) {
            x2apic_mode = true;
        }
    }
    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 */
    }

    if (x2apic_mode) {
        AcpiMadtLocalX2ApicNmi *local_nmi;

        local_nmi = acpi_data_push(table_data, sizeof *local_nmi);
        local_nmi->type   = ACPI_APIC_LOCAL_X2APIC_NMI;
        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,
                 (void *)(table_data->data + madt_start), "APIC",
+18 −0
Original line number Diff line number Diff line
@@ -343,6 +343,24 @@ struct AcpiMadtLocalNmi {
} QEMU_PACKED;
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 {
    ACPI_SUB_HEADER_DEF
    uint16_t reserved;