Commit c43e853a authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/ehabkost/tags/x86-pull-request' into staging



x86 and CPU queue, 2016-10-24

x2APIC support to APIC code, cpu_exec_init() refactor on all
architectures, and other x86 changes.

# gpg: Signature made Mon 24 Oct 2016 20:51:14 BST
# gpg:                using RSA key 0x2807936F984DC5A6
# gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>"
# Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF  D1AA 2807 936F 984D C5A6

* remotes/ehabkost/tags/x86-pull-request:
  exec: call cpu_exec_exit() from a CPU unrealize common function
  exec: move cpu_exec_init() calls to realize functions
  exec: split cpu_exec_init()
  pc: q35: Bump max_cpus to 288
  pc: Require IRQ remapping and EIM if there could be x2APIC CPUs
  pc: Add 'etc/boot-cpus' fw_cfg file for machine with more than 255 CPUs
  Increase MAX_CPUMASK_BITS from 255 to 288
  pc: Clarify FW_CFG_MAX_CPUS usage comment
  pc: kvm_apic: Pass APIC ID depending on xAPIC/x2APIC mode
  pc: apic_common: Reset APIC ID to initial ID when switching into x2APIC mode
  pc: apic_common: Restore APIC ID to initial ID on reset
  pc: apic_common: Extend APIC ID property to 32bit
  pc: Leave max apic_id_limit only in legacy cpu hotplug code
  acpi: cphp: Force switch to modern cpu hotplug if APIC ID > 254
  pc: acpi: x2APIC support for SRAT table
  pc: acpi: x2APIC support for MADT table and _MAT method

Conflicts:
	target-arm/cpu.c

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents fe4c0407 7bbc124e
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -630,7 +630,7 @@ AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx)
}
#endif

void cpu_exec_exit(CPUState *cpu)
void cpu_exec_unrealizefn(CPUState *cpu)
{
    CPUClass *cc = CPU_GET_CLASS(cpu);

@@ -644,11 +644,8 @@ void cpu_exec_exit(CPUState *cpu)
    }
}

void cpu_exec_init(CPUState *cpu, Error **errp)
void cpu_exec_initfn(CPUState *cpu)
{
    CPUClass *cc ATTRIBUTE_UNUSED = CPU_GET_CLASS(cpu);
    Error *local_err ATTRIBUTE_UNUSED = NULL;

    cpu->as = NULL;
    cpu->num_ases = 0;

@@ -669,6 +666,11 @@ void cpu_exec_init(CPUState *cpu, Error **errp)
    cpu->memory = system_memory;
    object_ref(OBJECT(cpu->memory));
#endif
}

void cpu_exec_realizefn(CPUState *cpu, Error **errp)
{
    CPUClass *cc ATTRIBUTE_UNUSED = CPU_GET_CLASS(cpu);

    cpu_list_add(cpu);

+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);
            }
+12 −5
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include "qapi/error.h"
#include "qom/cpu.h"
#include "hw/i386/pc.h"
#include "qemu/error-report.h"

#define CPU_EJECT_METHOD "CPEJ"
#define CPU_MAT_METHOD "CPMA"
@@ -63,7 +64,8 @@ static void acpi_set_cpu_present_bit(AcpiCpuHotplug *g, CPUState *cpu,

    cpu_id = k->get_arch_id(cpu);
    if ((cpu_id / 8) >= ACPI_GPE_PROC_LEN) {
        error_setg(errp, "acpi: invalid cpu id: %" PRIi64, cpu_id);
        object_property_set_bool(g->device, false, "cpu-hotplug-legacy",
                                 &error_abort);
        return;
    }

@@ -85,13 +87,14 @@ void legacy_acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
{
    CPUState *cpu;

    CPU_FOREACH(cpu) {
        acpi_set_cpu_present_bit(gpe_cpu, cpu, &error_abort);
    }
    memory_region_init_io(&gpe_cpu->io, owner, &AcpiCpuHotplug_ops,
                          gpe_cpu, "acpi-cpu-hotplug", ACPI_GPE_PROC_LEN);
    memory_region_add_subregion(parent, base, &gpe_cpu->io);
    gpe_cpu->device = owner;

    CPU_FOREACH(cpu) {
        acpi_set_cpu_present_bit(gpe_cpu, cpu, &error_abort);
    }
}

void acpi_switch_to_modern_cphp(AcpiCpuHotplug *gpe_cpu,
@@ -234,7 +237,11 @@ void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *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(pcms->apic_id_limit <= ACPI_CPU_HOTPLUG_ID_LIMIT);
    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);
    }

    /* create PCI0.PRES device and its _CRS to reserve CPU hotplug MMIO */
    dev = aml_device("PCI0." stringify(CPU_HOTPLUG_RESOURCE_DEVICE));
+1 −1
Original line number Diff line number Diff line
@@ -1494,7 +1494,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
     * it later in machvirt_init, where we have more information about the
     * configuration of the particular instance.
     */
    mc->max_cpus = MAX_CPUMASK_BITS;
    mc->max_cpus = 255;
    mc->has_dynamic_sysbus = true;
    mc->block_default_type = IF_VIRTIO;
    mc->no_cdrom = 1;
+78 −34
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,14 +358,21 @@ 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
@@ -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",
@@ -2391,7 +2421,6 @@ static void
build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
{
    AcpiSystemResourceAffinityTable *srat;
    AcpiSratProcessorAffinity *core;
    AcpiSratMemoryAffinity *numamem;

    int i;
@@ -2411,7 +2440,10 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)

    for (i = 0; i < apic_ids->len; i++) {
        int j = numa_get_node_for_cpu(i);
        int apic_id = apic_ids->cpus[i].arch_id;
        uint32_t apic_id = apic_ids->cpus[i].arch_id;

        if (apic_id < 255) {
            AcpiSratProcessorAffinity *core;

            core = acpi_data_push(table_data, sizeof *core);
            core->type = ACPI_SRAT_PROCESSOR_APIC;
@@ -2423,6 +2455,18 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
            memset(core->proximity_hi, 0, 3);
            core->local_sapic_eid = 0;
            core->flags = cpu_to_le32(1);
        } else {
            AcpiSratProcessorX2ApicAffinity *core;

            core = acpi_data_push(table_data, sizeof *core);
            core->type = ACPI_SRAT_PROCESSOR_x2APIC;
            core->length = sizeof(*core);
            core->x2apic_id = cpu_to_le32(apic_id);
            if (j < nb_numa_nodes) {
                core->proximity_domain = cpu_to_le32(j);
            }
            core->flags = cpu_to_le32(1);
        }
    }


Loading