From 6069484d92dcff002e6303b253506d6ea46c600c Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Mon, 13 Jan 2020 19:02:20 +0800 Subject: [PATCH 01/28] acpi/madt: Factor out the building of MADT GICC struct To realize CPU hotplug, the cpus aml within ACPI DSDT should contain _MAT mathod, which is equal to the GICC struct in ACPI MADT. Factor out the GICC building code from ACPI MADT and reuse it in build_cpus_aml. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta (cherry picked from commit f2b68e8adc98f8db20b1edc84b8f485975ed987c) --- ...-out-the-building-of-MADT-GICC-struc.patch | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 acpi-madt-Factor-out-the-building-of-MADT-GICC-struc.patch diff --git a/acpi-madt-Factor-out-the-building-of-MADT-GICC-struc.patch b/acpi-madt-Factor-out-the-building-of-MADT-GICC-struc.patch new file mode 100644 index 00000000..d322c8d1 --- /dev/null +++ b/acpi-madt-Factor-out-the-building-of-MADT-GICC-struc.patch @@ -0,0 +1,136 @@ +From 4f50ed900713acc14c971c07165fa83670d3f2b8 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Mon, 13 Jan 2020 19:02:20 +0800 +Subject: [PATCH] acpi/madt: Factor out the building of MADT GICC struct + +To realize CPU hotplug, the cpus aml within ACPI DSDT should contain +_MAT mathod, which is equal to the GICC struct in ACPI MADT. Factor +out the GICC building code from ACPI MADT and reuse it in build_cpus_aml. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt-acpi-build.c | 77 ++++++++++++++++++++++------------------ + include/hw/arm/virt.h | 4 +++ + 2 files changed, 47 insertions(+), 34 deletions(-) + +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index 1ca705654b..64b1ed8672 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -771,6 +771,48 @@ static void build_append_gicr(GArray *table_data, uint64_t base, uint32_t size) + build_append_int_noprefix(table_data, size, 4); /* Discovery Range Length */ + } + ++void virt_madt_cpu_entry(AcpiDeviceIf *adev, int i, ++ const CPUArchIdList *possible_cpus, GArray *table_data, ++ bool force_enabled) ++{ ++ VirtMachineState *vms = VIRT_MACHINE(qdev_get_machine()); ++ const MemMapEntry *memmap = vms->memmap; ++ ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i)); ++ uint64_t physical_base_address = 0, gich = 0, gicv = 0; ++ uint32_t vgic_interrupt = vms->virt ? PPI(ARCH_GIC_MAINT_IRQ) : 0; ++ uint32_t pmu_interrupt = arm_feature(&armcpu->env, ARM_FEATURE_PMU) ? ++ PPI(VIRTUAL_PMU_IRQ) : 0; ++ ++ if (vms->gic_version == 2) { ++ physical_base_address = memmap[VIRT_GIC_CPU].base; ++ gicv = memmap[VIRT_GIC_VCPU].base; ++ gich = memmap[VIRT_GIC_HYP].base; ++ } ++ ++ /* 5.2.12.14 GIC Structure */ ++ build_append_int_noprefix(table_data, 0xB, 1); /* Type */ ++ build_append_int_noprefix(table_data, 76, 1); /* Length */ ++ build_append_int_noprefix(table_data, 0, 2); /* Reserved */ ++ build_append_int_noprefix(table_data, i, 4); /* GIC ID */ ++ build_append_int_noprefix(table_data, i, 4); /* ACPI Processor UID */ ++ /* Flags */ ++ build_append_int_noprefix(table_data, 1, 4); /* Enabled */ ++ /* Parking Protocol Version */ ++ build_append_int_noprefix(table_data, 0, 4); ++ /* Performance Interrupt GSIV */ ++ build_append_int_noprefix(table_data, pmu_interrupt, 4); ++ build_append_int_noprefix(table_data, 0, 8); /* Parked Address */ ++ /* Physical Base Address */ ++ build_append_int_noprefix(table_data, physical_base_address, 8); ++ build_append_int_noprefix(table_data, gicv, 8); /* GICV */ ++ build_append_int_noprefix(table_data, gich, 8); /* GICH */ ++ /* VGIC Maintenance interrupt */ ++ build_append_int_noprefix(table_data, vgic_interrupt, 4); ++ build_append_int_noprefix(table_data, 0, 8); /* GICR Base Address*/ ++ /* MPIDR */ ++ build_append_int_noprefix(table_data, armcpu->mp_affinity, 8); ++} ++ + static void + build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + { +@@ -798,40 +840,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + build_append_int_noprefix(table_data, 0, 3); /* Reserved */ + + for (i = 0; i < MACHINE(vms)->smp.cpus; i++) { +- ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i)); +- uint64_t physical_base_address = 0, gich = 0, gicv = 0; +- uint32_t vgic_interrupt = vms->virt ? PPI(ARCH_GIC_MAINT_IRQ) : 0; +- uint32_t pmu_interrupt = arm_feature(&armcpu->env, ARM_FEATURE_PMU) ? +- PPI(VIRTUAL_PMU_IRQ) : 0; +- +- if (vms->gic_version == 2) { +- physical_base_address = memmap[VIRT_GIC_CPU].base; +- gicv = memmap[VIRT_GIC_VCPU].base; +- gich = memmap[VIRT_GIC_HYP].base; +- } +- +- /* 5.2.12.14 GIC Structure */ +- build_append_int_noprefix(table_data, 0xB, 1); /* Type */ +- build_append_int_noprefix(table_data, 76, 1); /* Length */ +- build_append_int_noprefix(table_data, 0, 2); /* Reserved */ +- build_append_int_noprefix(table_data, i, 4); /* GIC ID */ +- build_append_int_noprefix(table_data, i, 4); /* ACPI Processor UID */ +- /* Flags */ +- build_append_int_noprefix(table_data, 1, 4); /* Enabled */ +- /* Parking Protocol Version */ +- build_append_int_noprefix(table_data, 0, 4); +- /* Performance Interrupt GSIV */ +- build_append_int_noprefix(table_data, pmu_interrupt, 4); +- build_append_int_noprefix(table_data, 0, 8); /* Parked Address */ +- /* Physical Base Address */ +- build_append_int_noprefix(table_data, physical_base_address, 8); +- build_append_int_noprefix(table_data, gicv, 8); /* GICV */ +- build_append_int_noprefix(table_data, gich, 8); /* GICH */ +- /* VGIC Maintenance interrupt */ +- build_append_int_noprefix(table_data, vgic_interrupt, 4); +- build_append_int_noprefix(table_data, 0, 8); /* GICR Base Address*/ +- /* MPIDR */ +- build_append_int_noprefix(table_data, armcpu->mp_affinity, 8); ++ virt_madt_cpu_entry(NULL, i, NULL, table_data, false); + } + + if (vms->gic_version == 3) { +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index a4356cf736..36639e8d3e 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -38,6 +38,7 @@ + #include "sysemu/kvm.h" + #include "hw/intc/arm_gicv3_common.h" + #include "qom/object.h" ++#include "hw/acpi/acpi_dev_interface.h" + + #define NUM_GICV2M_SPIS 64 + #define NUM_VIRTIO_TRANSPORTS 32 +@@ -181,6 +182,9 @@ OBJECT_DECLARE_TYPE(VirtMachineState, VirtMachineClass, VIRT_MACHINE) + + void virt_acpi_setup(VirtMachineState *vms); + bool virt_is_acpi_enabled(VirtMachineState *vms); ++void virt_madt_cpu_entry(AcpiDeviceIf *adev, int uid, ++ const CPUArchIdList *cpu_list, GArray *entry, ++ bool force_enabled); + + /* Return the number of used redistributor regions */ + static inline int virt_gicv3_redist_region_count(VirtMachineState *vms) +-- +2.27.0 + -- Gitee From 16b188e9c2743c4e5028b92d0a4302b3304a2cfd Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 10 Apr 2020 10:05:54 +0800 Subject: [PATCH 02/28] hw/arm/virt: Assign virt_madt_cpu_entry to acpi_ged madt_cpu hook In build_cpus_aml, we will invoke this hook to build _MAT aml mehtod for cpus. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta (cherry picked from commit 80bcd0313ba67d5c4439030c96c26aee1d9288f9) --- ...gn-virt_madt_cpu_entry-to-acpi_ged-m.patch | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 hw-arm-virt-Assign-virt_madt_cpu_entry-to-acpi_ged-m.patch diff --git a/hw-arm-virt-Assign-virt_madt_cpu_entry-to-acpi_ged-m.patch b/hw-arm-virt-Assign-virt_madt_cpu_entry-to-acpi_ged-m.patch new file mode 100644 index 00000000..71aea393 --- /dev/null +++ b/hw-arm-virt-Assign-virt_madt_cpu_entry-to-acpi_ged-m.patch @@ -0,0 +1,40 @@ +From ae74dda87e172ce82a8180d1a2e9c62904390f91 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 10:05:54 +0800 +Subject: [PATCH] hw/arm/virt: Assign virt_madt_cpu_entry to acpi_ged madt_cpu + hook + +In build_cpus_aml, we will invoke this hook to build _MAT +aml mehtod for cpus. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 47e98f09e8..44c29070c4 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -684,6 +684,7 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms) + static inline DeviceState *create_acpi_ged(VirtMachineState *vms) + { + DeviceState *dev; ++ AcpiDeviceIfClass *adevc; + MachineState *ms = MACHINE(vms); + int irq = vms->irqmap[VIRT_ACPI_GED]; + uint32_t event = ACPI_GED_PWR_DOWN_EVT; +@@ -699,6 +700,9 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms) + dev = qdev_new(TYPE_ACPI_GED); + qdev_prop_set_uint32(dev, "ged-event", event); + ++ adevc = ACPI_DEVICE_IF_GET_CLASS(dev); ++ adevc->madt_cpu = virt_madt_cpu_entry; ++ + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(vms->gic, irq)); +-- +2.27.0 + -- Gitee From 2363e5e3a7374cfaba965adbc9135397c864d462 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 22 Apr 2020 15:58:27 +0800 Subject: [PATCH 03/28] arm/virt/acpi: Factor out CPPC building from DSDT CPU aml When CPU hotplug is enabled, we will use build_cpus_aml instead of acpi_dsdt_add_cpus, so factor out CPPC building and we can reuse it in build_cpus_aml. Signed-off-by: Keqian Zhu (cherry picked from commit c6b2e91699e31e3473e94d86d9c8db767f0ebb59) --- ...ctor-out-CPPC-building-from-DSDT-CPU.patch | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 arm-virt-acpi-Factor-out-CPPC-building-from-DSDT-CPU.patch diff --git a/arm-virt-acpi-Factor-out-CPPC-building-from-DSDT-CPU.patch b/arm-virt-acpi-Factor-out-CPPC-building-from-DSDT-CPU.patch new file mode 100644 index 00000000..fe171fe8 --- /dev/null +++ b/arm-virt-acpi-Factor-out-CPPC-building-from-DSDT-CPU.patch @@ -0,0 +1,122 @@ +From 06837491e2ece2fdd6fe6cc8572aaab52fbdcb3e Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Wed, 22 Apr 2020 15:58:27 +0800 +Subject: [PATCH] arm/virt/acpi: Factor out CPPC building from DSDT CPU aml + +When CPU hotplug is enabled, we will use build_cpus_aml instead of +acpi_dsdt_add_cpus, so factor out CPPC building and we can reuse it +in build_cpus_aml. + +Signed-off-by: Keqian Zhu +--- + hw/arm/virt-acpi-build.c | 33 +++++++++++++++++----------- + hw/arm/virt.c | 1 + + include/hw/acpi/acpi_dev_interface.h | 2 ++ + include/hw/arm/virt.h | 2 ++ + 4 files changed, 25 insertions(+), 13 deletions(-) + +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index 64b1ed8672..a93d223879 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -120,8 +120,24 @@ static void acpi_dsdt_add_cppc(Aml *dev, uint64_t cpu_base, int *regs_offset) + aml_append(dev, aml_name_decl("_CPC", cpc)); + } + +-static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms, +- const MemMapEntry *cppc_memmap) ++void virt_acpi_dsdt_cpu_cppc(AcpiDeviceIf *adev, int ncpu, int num_cpu, Aml *dev) ++{ ++ VirtMachineState *vms = VIRT_MACHINE(qdev_get_machine()); ++ const MemMapEntry *cppc_memmap = &vms->memmap[VIRT_CPUFREQ]; ++ ++ /* ++ * Append _CPC and _PSD to support CPU frequence show ++ * Check CPPC available by DESIRED_PERF register ++ */ ++ if (cppc_regs_offset[DESIRED_PERF] != -1) { ++ acpi_dsdt_add_cppc(dev, ++ cppc_memmap->base + ncpu * CPPC_REG_PER_CPU_STRIDE, ++ cppc_regs_offset); ++ acpi_dsdt_add_psd(dev, num_cpu); ++ } ++} ++ ++static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms) + { + MachineState *ms = MACHINE(vms); + uint16_t i; +@@ -131,16 +147,7 @@ static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms, + aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007"))); + aml_append(dev, aml_name_decl("_UID", aml_int(i))); + +- /* +- * Append _CPC and _PSD to support CPU frequence show +- * Check CPPC available by DESIRED_PERF register +- */ +- if (cppc_regs_offset[DESIRED_PERF] != -1) { +- acpi_dsdt_add_cppc(dev, +- cppc_memmap->base + i * CPPC_REG_PER_CPU_STRIDE, +- cppc_regs_offset); +- acpi_dsdt_add_psd(dev, ms->smp.cpus); +- } ++ virt_acpi_dsdt_cpu_cppc(NULL, i, ms->smp.cpus, dev); + + aml_append(scope, dev); + } +@@ -940,7 +947,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + * the RTC ACPI device at all when using UEFI. + */ + scope = aml_scope("\\_SB"); +- acpi_dsdt_add_cpus(scope, vms, &memmap[VIRT_CPUFREQ]); ++ acpi_dsdt_add_cpus(scope, vms); + acpi_dsdt_add_uart(scope, &memmap[VIRT_UART], + (irqmap[VIRT_UART] + ARM_SPI_BASE)); + if (vmc->acpi_expose_flash) { +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 44c29070c4..3299d674c8 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -702,6 +702,7 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms) + + adevc = ACPI_DEVICE_IF_GET_CLASS(dev); + adevc->madt_cpu = virt_madt_cpu_entry; ++ adevc->cpu_cppc = virt_acpi_dsdt_cpu_cppc; + + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base); +diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h +index ea6056ab92..601931433a 100644 +--- a/include/hw/acpi/acpi_dev_interface.h ++++ b/include/hw/acpi/acpi_dev_interface.h +@@ -5,6 +5,7 @@ + #include "qom/object.h" + #include "hw/boards.h" + #include "hw/qdev-core.h" ++#include "hw/acpi/aml-build.h" + + /* These values are part of guest ABI, and can not be changed */ + typedef enum { +@@ -55,5 +56,6 @@ struct AcpiDeviceIfClass { + void (*madt_cpu)(AcpiDeviceIf *adev, int uid, + const CPUArchIdList *apic_ids, GArray *entry, + bool force_enabled); ++ void (*cpu_cppc)(AcpiDeviceIf *adev, int uid, int num_cpu, Aml *dev); + }; + #endif +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index 36639e8d3e..fe26709e1a 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -185,6 +185,8 @@ bool virt_is_acpi_enabled(VirtMachineState *vms); + void virt_madt_cpu_entry(AcpiDeviceIf *adev, int uid, + const CPUArchIdList *cpu_list, GArray *entry, + bool force_enabled); ++void virt_acpi_dsdt_cpu_cppc(AcpiDeviceIf *adev, int uid, ++ int num_cpu, Aml *dev); + + /* Return the number of used redistributor regions */ + static inline int virt_gicv3_redist_region_count(VirtMachineState *vms) +-- +2.27.0 + -- Gitee From 296e467191d159e6915048effa48eb5e8474928c Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 22 Apr 2020 16:11:13 +0800 Subject: [PATCH 04/28] acpi/cpu: Prepare build_cpus_aml for arm virt We will reuse build_cpus_aml to build DSDT cpus aml in arm/virt ACPI to realize cpu hotplug. Three points are added. 1. Make ACPI IO address space configurable, because ARM64 platforms don't use port IO for ACPI IO space. 2. Add GICC struct building support in _MAT of cpu aml. 3. Let the hotplug method parameter can be NULL, because ACPI GED will realize it. Besides, CPU CPPC building is injected. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta (cherry picked from commit 4d7c437b4d1a8ac175e7b9224a9e402b619d6cd3) --- ...-Prepare-build_cpus_aml-for-arm-virt.patch | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 acpi-cpu-Prepare-build_cpus_aml-for-arm-virt.patch diff --git a/acpi-cpu-Prepare-build_cpus_aml-for-arm-virt.patch b/acpi-cpu-Prepare-build_cpus_aml-for-arm-virt.patch new file mode 100644 index 00000000..49477add --- /dev/null +++ b/acpi-cpu-Prepare-build_cpus_aml-for-arm-virt.patch @@ -0,0 +1,117 @@ +From 1ab75151c0a486ebdbe50d29c9677c7bc1f05929 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Wed, 22 Apr 2020 16:11:13 +0800 +Subject: [PATCH] acpi/cpu: Prepare build_cpus_aml for arm virt + +We will reuse build_cpus_aml to build DSDT cpus aml in arm/virt +ACPI to realize cpu hotplug. Three points are added. + +1. Make ACPI IO address space configurable, because ARM64 platforms + don't use port IO for ACPI IO space. +2. Add GICC struct building support in _MAT of cpu aml. +3. Let the hotplug method parameter can be NULL, because ACPI GED + will realize it. + +Besides, CPU CPPC building is injected. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/acpi/cpu.c | 27 ++++++++++++++++++++------- + hw/i386/acpi-build.c | 2 +- + include/hw/acpi/cpu.h | 3 ++- + 3 files changed, 23 insertions(+), 9 deletions(-) + +diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c +index b20903ea30..a9c2ee952a 100644 +--- a/hw/acpi/cpu.c ++++ b/hw/acpi/cpu.c +@@ -343,7 +343,8 @@ const VMStateDescription vmstate_cpu_hotplug = { + void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, + hwaddr io_base, + const char *res_root, +- const char *event_handler_method) ++ const char *event_handler_method, ++ AmlRegionSpace rs) + { + Aml *ifctx; + Aml *field; +@@ -371,13 +372,18 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, + aml_append(cpu_ctrl_dev, aml_mutex(CPU_LOCK, 0)); + + crs = aml_resource_template(); +- aml_append(crs, aml_io(AML_DECODE16, io_base, io_base, 1, +- ACPI_CPU_HOTPLUG_REG_LEN)); ++ if (rs == AML_SYSTEM_IO) { ++ aml_append(crs, aml_io(AML_DECODE16, io_base, io_base, 1, ++ ACPI_CPU_HOTPLUG_REG_LEN)); ++ } else { ++ aml_append(crs, aml_memory32_fixed(io_base, ++ ACPI_CPU_HOTPLUG_REG_LEN, AML_READ_WRITE)); ++ } + aml_append(cpu_ctrl_dev, aml_name_decl("_CRS", crs)); + + /* declare CPU hotplug MMIO region with related access fields */ + aml_append(cpu_ctrl_dev, +- aml_operation_region("PRST", AML_SYSTEM_IO, aml_int(io_base), ++ aml_operation_region("PRST", rs, aml_int(io_base), + ACPI_CPU_HOTPLUG_REG_LEN)); + + field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK, +@@ -663,6 +669,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, + aml_append(dev, aml_name_decl("_UID", uid)); + } + ++ assert(adevc); ++ if (adevc->cpu_cppc) { ++ adevc->cpu_cppc(adev, i, arch_ids->len, dev); ++ } ++ + method = aml_method("_STA", 0, AML_SERIALIZED); + aml_append(method, aml_return(aml_call1(CPU_STS_METHOD, uid))); + aml_append(dev, method); +@@ -703,9 +714,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, + aml_append(sb_scope, cpus_dev); + aml_append(table, sb_scope); + +- method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED); +- aml_append(method, aml_call0("\\_SB.CPUS." CPU_SCAN_METHOD)); +- aml_append(table, method); ++ if (event_handler_method) { ++ method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED); ++ aml_append(method, aml_call0("\\_SB.CPUS." CPU_SCAN_METHOD)); ++ aml_append(table, method); ++ } + + g_free(cphp_res_path); + } +diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c +index a99c6e4fe3..1ce2d67c2e 100644 +--- a/hw/i386/acpi-build.c ++++ b/hw/i386/acpi-build.c +@@ -1513,7 +1513,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, + .fw_unplugs_cpu = pm->smi_on_cpu_unplug, + }; + build_cpus_aml(dsdt, machine, opts, pm->cpu_hp_io_base, +- "\\_SB.PCI0", "\\_GPE._E02"); ++ "\\_SB.PCI0", "\\_GPE._E02", AML_SYSTEM_IO); + } + + if (pcms->memhp_io_base && nr_mem) { +diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h +index 999caaf510..a0fdc44bdd 100644 +--- a/include/hw/acpi/cpu.h ++++ b/include/hw/acpi/cpu.h +@@ -58,7 +58,8 @@ typedef struct CPUHotplugFeatures { + void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, + hwaddr io_base, + const char *res_root, +- const char *event_handler_method); ++ const char *event_handler_method, ++ AmlRegionSpace rs); + + void acpi_cpu_ospm_status(CPUHotplugState *cpu_st, ACPIOSTInfoList ***list); + +-- +2.27.0 + -- Gitee From 9a529f4d5d3df17b2fae2b9f44fe2b37801e935c Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 3 Apr 2020 15:41:01 +0800 Subject: [PATCH 05/28] acpi/ged: Extend ACPI GED to support CPU hotplug This adds a new GED event called ACPI_GED_CPU_HOTPLUG_EVT. The basic workflow is that: GED sends this event to guest, then ACPI driver in guest will call _EVT method of GED aml, then _EVT will call CSCN method in cpus aml to get status of all cpus. The status of cpus is maintained by CPUHotplugState in GED and is made accessable to guest through memory region. This also adds migration support to CPUHotplugState. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta (cherry picked from commit a072cbe5beab53e9328c2fe6576e755e88b2c40a) --- ...tend-ACPI-GED-to-support-CPU-hotplug.patch | 205 ++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 acpi-ged-Extend-ACPI-GED-to-support-CPU-hotplug.patch diff --git a/acpi-ged-Extend-ACPI-GED-to-support-CPU-hotplug.patch b/acpi-ged-Extend-ACPI-GED-to-support-CPU-hotplug.patch new file mode 100644 index 00000000..12a279ea --- /dev/null +++ b/acpi-ged-Extend-ACPI-GED-to-support-CPU-hotplug.patch @@ -0,0 +1,205 @@ +From 603cbcc5efdd35f518a5bd0a5067d40c2c4eb8d6 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 3 Apr 2020 15:41:01 +0800 +Subject: [PATCH] acpi/ged: Extend ACPI GED to support CPU hotplug + +This adds a new GED event called ACPI_GED_CPU_HOTPLUG_EVT. +The basic workflow is that: GED sends this event to guest, +then ACPI driver in guest will call _EVT method of GED aml, +then _EVT will call CSCN method in cpus aml to get status of +all cpus. + +The status of cpus is maintained by CPUHotplugState in GED and +is made accessable to guest through memory region. + +This also adds migration support to CPUHotplugState. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + docs/specs/acpi_hw_reduced_hotplug.rst | 3 ++- + hw/acpi/cpu.c | 1 - + hw/acpi/generic_event_device.c | 35 ++++++++++++++++++++++++++ + hw/arm/Kconfig | 1 + + include/hw/acpi/cpu.h | 2 ++ + include/hw/acpi/generic_event_device.h | 4 +++ + 6 files changed, 44 insertions(+), 2 deletions(-) + +diff --git a/docs/specs/acpi_hw_reduced_hotplug.rst b/docs/specs/acpi_hw_reduced_hotplug.rst +index 0bd3f9399f..3acd6fcd8b 100644 +--- a/docs/specs/acpi_hw_reduced_hotplug.rst ++++ b/docs/specs/acpi_hw_reduced_hotplug.rst +@@ -64,7 +64,8 @@ GED IO interface (4 byte access) + 0: Memory hotplug event + 1: System power down event + 2: NVDIMM hotplug event +- 3-31: Reserved ++ 3: CPU hotplug event ++ 4-31: Reserved + + **write_access:** + +diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c +index a9c2ee952a..f9ce0a7f41 100644 +--- a/hw/acpi/cpu.c ++++ b/hw/acpi/cpu.c +@@ -6,7 +6,6 @@ + #include "trace.h" + #include "sysemu/numa.h" + +-#define ACPI_CPU_HOTPLUG_REG_LEN 12 + #define ACPI_CPU_SELECTOR_OFFSET_WR 0 + #define ACPI_CPU_FLAGS_OFFSET_RW 4 + #define ACPI_CPU_CMD_OFFSET_WR 5 +diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c +index e28457a7d1..042a8ef8a5 100644 +--- a/hw/acpi/generic_event_device.c ++++ b/hw/acpi/generic_event_device.c +@@ -25,6 +25,7 @@ static const uint32_t ged_supported_events[] = { + ACPI_GED_MEM_HOTPLUG_EVT, + ACPI_GED_PWR_DOWN_EVT, + ACPI_GED_NVDIMM_HOTPLUG_EVT, ++ ACPI_GED_CPU_HOTPLUG_EVT, + }; + + /* +@@ -117,6 +118,9 @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev, + aml_notify(aml_name("\\_SB.NVDR"), + aml_int(0x80))); + break; ++ case ACPI_GED_CPU_HOTPLUG_EVT: ++ aml_append(if_ctx, aml_call0("\\_SB.CPUS.CSCN")); ++ break; + default: + /* + * Please make sure all the events in ged_supported_events[] +@@ -234,6 +238,8 @@ static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev, + } else { + acpi_memory_plug_cb(hotplug_dev, &s->memhp_state, dev, errp); + } ++ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { ++ acpi_cpu_plug_cb(hotplug_dev, &s->cpuhp_state, dev, errp); + } else { + error_setg(errp, "virt: device plug request for unsupported device" + " type: %s", object_get_typename(OBJECT(dev))); +@@ -279,6 +285,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) + sel = ACPI_GED_PWR_DOWN_EVT; + } else if (ev & ACPI_NVDIMM_HOTPLUG_STATUS) { + sel = ACPI_GED_NVDIMM_HOTPLUG_EVT; ++ } else if (ev & ACPI_CPU_HOTPLUG_STATUS) { ++ sel = ACPI_GED_CPU_HOTPLUG_EVT; + } else { + /* Unknown event. Return without generating interrupt. */ + warn_report("GED: Unsupported event %d. No irq injected", ev); +@@ -311,6 +319,16 @@ static const VMStateDescription vmstate_memhp_state = { + } + }; + ++static const VMStateDescription vmstate_cpuhp_state = { ++ .name = "acpi-ged/cpuhp", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_CPU_HOTPLUG(cpuhp_state, AcpiGedState), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ + static const VMStateDescription vmstate_ged_state = { + .name = "acpi-ged-state", + .version_id = 1, +@@ -360,6 +378,7 @@ static const VMStateDescription vmstate_acpi_ged = { + .subsections = (const VMStateDescription * []) { + &vmstate_memhp_state, + &vmstate_ghes_state, ++ &vmstate_cpuhp_state, + NULL + } + }; +@@ -370,6 +389,7 @@ static void acpi_ged_initfn(Object *obj) + AcpiGedState *s = ACPI_GED(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + GEDState *ged_st = &s->ged_state; ++ MachineClass *mc; + + memory_region_init_io(&ged_st->evt, obj, &ged_evt_ops, ged_st, + TYPE_ACPI_GED, ACPI_GED_EVT_SEL_LEN); +@@ -393,6 +413,21 @@ static void acpi_ged_initfn(Object *obj) + memory_region_init_io(&ged_st->regs, obj, &ged_regs_ops, ged_st, + TYPE_ACPI_GED "-regs", ACPI_GED_REG_COUNT); + sysbus_init_mmio(sbd, &ged_st->regs); ++ ++ mc = MACHINE_GET_CLASS(qdev_get_machine()); ++ if (!mc->possible_cpu_arch_ids) { ++ /* ++ * MachineClass should support possible_cpu_arch_ids in ++ * cpu_hotplug_hw_init below. ++ */ ++ return; ++ } ++ ++ memory_region_init(&s->container_cpuhp, OBJECT(dev), "cpuhp container", ++ ACPI_CPU_HOTPLUG_REG_LEN); ++ sysbus_init_mmio(sbd, &s->container_cpuhp); ++ cpu_hotplug_hw_init(&s->container_cpuhp, OBJECT(dev), ++ &s->cpuhp_state, 0); + } + + static void acpi_ged_class_init(ObjectClass *class, void *data) +diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig +index 2d37d29f02..006a4b4c4b 100644 +--- a/hw/arm/Kconfig ++++ b/hw/arm/Kconfig +@@ -27,6 +27,7 @@ config ARM_VIRT + select DIMM + select ACPI_HW_REDUCED + select ACPI_APEI ++ select ACPI_CPU_HOTPLUG + + config CHEETAH + bool +diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h +index a0fdc44bdd..d521025830 100644 +--- a/include/hw/acpi/cpu.h ++++ b/include/hw/acpi/cpu.h +@@ -17,6 +17,8 @@ + #include "hw/acpi/aml-build.h" + #include "hw/hotplug.h" + ++#define ACPI_CPU_HOTPLUG_REG_LEN 12 ++ + typedef struct AcpiCpuStatus { + struct CPUState *cpu; + uint64_t arch_id; +diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h +index d49217c445..6bb2ade385 100644 +--- a/include/hw/acpi/generic_event_device.h ++++ b/include/hw/acpi/generic_event_device.h +@@ -63,6 +63,7 @@ + #include "hw/acpi/memory_hotplug.h" + #include "hw/acpi/ghes.h" + #include "qom/object.h" ++#include "hw/acpi/cpu.h" + + #define ACPI_POWER_BUTTON_DEVICE "PWRB" + +@@ -97,6 +98,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED) + #define ACPI_GED_MEM_HOTPLUG_EVT 0x1 + #define ACPI_GED_PWR_DOWN_EVT 0x2 + #define ACPI_GED_NVDIMM_HOTPLUG_EVT 0x4 ++#define ACPI_GED_CPU_HOTPLUG_EVT 0x8 + + typedef struct GEDState { + MemoryRegion evt; +@@ -108,6 +110,8 @@ struct AcpiGedState { + SysBusDevice parent_obj; + MemHotplugState memhp_state; + MemoryRegion container_memhp; ++ CPUHotplugState cpuhp_state; ++ MemoryRegion container_cpuhp; + GEDState ged_state; + uint32_t ged_event_bitmap; + qemu_irq irq; +-- +2.27.0 + -- Gitee From 267b813a65799baf4895f5e713ea3f50de90707c Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 10 Apr 2020 10:17:27 +0800 Subject: [PATCH 06/28] arm/cpu: assign arm_get_arch_id handler to get_arch_id hook This hook will be called in get_cpu_status, which is called during cpu hotplug. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta (cherry picked from commit dc4b675a897d6094b60ef462482e03b2905e1737) --- ...rm_get_arch_id-handler-to-get_arch_i.patch | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 arm-cpu-assign-arm_get_arch_id-handler-to-get_arch_i.patch diff --git a/arm-cpu-assign-arm_get_arch_id-handler-to-get_arch_i.patch b/arm-cpu-assign-arm_get_arch_id-handler-to-get_arch_i.patch new file mode 100644 index 00000000..91c7181e --- /dev/null +++ b/arm-cpu-assign-arm_get_arch_id-handler-to-get_arch_i.patch @@ -0,0 +1,43 @@ +From 42072fd4b33125959d825a0c5cee0d1122072f71 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 10:17:27 +0800 +Subject: [PATCH] arm/cpu: assign arm_get_arch_id handler to get_arch_id hook + +This hook will be called in get_cpu_status, which is called +during cpu hotplug. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + target/arm/cpu.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 65163f5135..f06ba29885 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -2557,6 +2557,13 @@ static const struct TCGCPUOps arm_tcg_ops = { + }; + #endif /* CONFIG_TCG */ + ++static int64_t arm_cpu_get_arch_id(CPUState *cs) ++{ ++ ARMCPU *cpu = ARM_CPU(cs); ++ ++ return cpu->mp_affinity; ++} ++ + static void arm_cpu_class_init(ObjectClass *oc, void *data) + { + ARMCPUClass *acc = ARM_CPU_CLASS(oc); +@@ -2575,6 +2582,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) + cc->set_pc = arm_cpu_set_pc; + cc->gdb_read_register = arm_cpu_gdb_read_register; + cc->gdb_write_register = arm_cpu_gdb_write_register; ++ cc->get_arch_id = arm_cpu_get_arch_id; + #ifndef CONFIG_USER_ONLY + cc->sysemu_ops = &arm_sysemu_ops; + #endif +-- +2.27.0 + -- Gitee From 3137876cb9bee285421c210f18a471f8d1e533b0 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 11 Feb 2022 15:48:16 +0800 Subject: [PATCH 07/28] tests/acpi/bios-tables-test: Allow changes to virt/DSDT file Let virt/DSDT as the expected file allowed to be changed. Signed-off-by: Keqian Zhu (cherry picked from commit d160f3e1e3737c47558c1f7908ddbd6cf188b3ff) --- ...tables-test-Allow-changes-to-virt-DS.patch | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 tests-acpi-bios-tables-test-Allow-changes-to-virt-DS.patch diff --git a/tests-acpi-bios-tables-test-Allow-changes-to-virt-DS.patch b/tests-acpi-bios-tables-test-Allow-changes-to-virt-DS.patch new file mode 100644 index 00000000..585df22e --- /dev/null +++ b/tests-acpi-bios-tables-test-Allow-changes-to-virt-DS.patch @@ -0,0 +1,22 @@ +From d215714b9ab38f6c9e0aacf2120b44888936a1ed Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 11 Feb 2022 15:48:16 +0800 +Subject: [PATCH] tests/acpi/bios-tables-test: Allow changes to virt/DSDT file + +Let virt/DSDT as the expected file allowed to be changed. + +Signed-off-by: Keqian Zhu +--- + tests/qtest/bios-tables-test-allowed-diff.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h +index dfb8523c8b..7b4adbc822 100644 +--- a/tests/qtest/bios-tables-test-allowed-diff.h ++++ b/tests/qtest/bios-tables-test-allowed-diff.h +@@ -1 +1,2 @@ + /* List of comma-separated changed AML files to ignore */ ++"tests/data/acpi/virt/DSDT", +-- +2.27.0 + -- Gitee From e290842121d36963f2531286ef1bd830fe2e9932 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Sun, 5 Apr 2020 16:03:15 +0800 Subject: [PATCH 08/28] arm/virt: Attach ACPI CPU hotplug support to virt Attach cpus aml building and GED support for CPU hotplug to arm/virt, but currently we make it diabled by not add CPU hotplug event to GED. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta (cherry picked from commit dc9cea17499b378bde70f3854786ba56daf6a09a) --- ...ach-ACPI-CPU-hotplug-support-to-virt.patch | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 arm-virt-Attach-ACPI-CPU-hotplug-support-to-virt.patch diff --git a/arm-virt-Attach-ACPI-CPU-hotplug-support-to-virt.patch b/arm-virt-Attach-ACPI-CPU-hotplug-support-to-virt.patch new file mode 100644 index 00000000..174c3de0 --- /dev/null +++ b/arm-virt-Attach-ACPI-CPU-hotplug-support-to-virt.patch @@ -0,0 +1,103 @@ +From 6b0f94aee82c7558d79e5ec28437483c4873dc65 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Sun, 5 Apr 2020 16:03:15 +0800 +Subject: [PATCH] arm/virt: Attach ACPI CPU hotplug support to virt + +Attach cpus aml building and GED support for CPU hotplug to +arm/virt, but currently we make it diabled by not add CPU +hotplug event to GED. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt-acpi-build.c | 15 ++++++++++++++- + hw/arm/virt.c | 6 ++++++ + include/hw/arm/virt.h | 1 + + 3 files changed, 21 insertions(+), 1 deletion(-) + +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index a93d223879..7cb320d9f2 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -937,6 +937,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + const int *irqmap = vms->irqmap; + AcpiTable table = { .sig = "DSDT", .rev = 2, .oem_id = vms->oem_id, + .oem_table_id = vms->oem_table_id }; ++ bool cpu_aml_built = false; + + acpi_table_begin(&table, table_data); + dsdt = init_aml_allocator(); +@@ -947,7 +948,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + * the RTC ACPI device at all when using UEFI. + */ + scope = aml_scope("\\_SB"); +- acpi_dsdt_add_cpus(scope, vms); + acpi_dsdt_add_uart(scope, &memmap[VIRT_UART], + (irqmap[VIRT_UART] + ARM_SPI_BASE)); + if (vmc->acpi_expose_flash) { +@@ -977,6 +977,19 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + AML_SYSTEM_MEMORY, + memmap[VIRT_PCDIMM_ACPI].base); + } ++ ++ if (event & ACPI_GED_CPU_HOTPLUG_EVT) { ++ CPUHotplugFeatures opts = { ++ .acpi_1_compatible = false, .has_legacy_cphp = false ++ }; ++ build_cpus_aml(dsdt, ms, opts, memmap[VIRT_CPU_ACPI].base, ++ "\\_SB", NULL, AML_SYSTEM_MEMORY); ++ cpu_aml_built = true; ++ } ++ } ++ ++ if (!cpu_aml_built) { ++ acpi_dsdt_add_cpus(scope, vms); + } + + acpi_dsdt_add_power_button(scope); +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 3299d674c8..9b73c479c4 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -154,6 +154,7 @@ static const MemMapEntry base_memmap[] = { + [VIRT_NVDIMM_ACPI] = { 0x09090000, NVDIMM_ACPI_IO_LEN}, + [VIRT_PVTIME] = { 0x090a0000, 0x00010000 }, + [VIRT_SECURE_GPIO] = { 0x090b0000, 0x00001000 }, ++ [VIRT_CPU_ACPI] = { 0x090c0000, ACPI_CPU_HOTPLUG_REG_LEN }, + [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, + [VIRT_CPUFREQ] = { 0x0b000000, 0x00010000 }, + /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ +@@ -697,6 +698,10 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms) + event |= ACPI_GED_NVDIMM_HOTPLUG_EVT; + } + ++ /* event |= ACPI_GED_CPU_HOTPLUG_EVT; ++ * Currently CPU hotplug is not enabled. ++ */ ++ + dev = qdev_new(TYPE_ACPI_GED); + qdev_prop_set_uint32(dev, "ged-event", event); + +@@ -706,6 +711,7 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms) + + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base); ++ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 3, vms->memmap[VIRT_CPU_ACPI].base); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(vms->gic, irq)); + + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index fe26709e1a..2a838620d8 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -88,6 +88,7 @@ enum { + VIRT_ACPI_GED, + VIRT_NVDIMM_ACPI, + VIRT_PVTIME, ++ VIRT_CPU_ACPI, + VIRT_LOWMEMMAP_LAST, + }; + +-- +2.27.0 + -- Gitee From 2f5a5868f61606c1614b82a84d89a8bc04be7434 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 11 Feb 2022 16:07:31 +0800 Subject: [PATCH 09/28] tests/acpi/bios-table-test: Update expected virt/DSDT file Update DSDT binary and empty bios-tables-test-allowd-diff.h Signed-off-by: Keqian Zhu (cherry picked from commit 3a8ad66a61be0eb162e34929698c3a040b515f51) --- BinDir.tar.gz | Bin 3433 -> 3440 bytes ...table-test-Update-expected-virt-DSDT.patch | 26 ++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests-acpi-bios-table-test-Update-expected-virt-DSDT.patch diff --git a/BinDir.tar.gz b/BinDir.tar.gz index 3800e9d831a8166f7d9fbffa7f59fffb394dd0e6..313f1fe4ec24d08eb57204d497834eb9262f9787 100644 GIT binary patch delta 3363 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 E1N=3g)Bpeg delta 3325 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 diff --git a/tests-acpi-bios-table-test-Update-expected-virt-DSDT.patch b/tests-acpi-bios-table-test-Update-expected-virt-DSDT.patch new file mode 100644 index 00000000..22b88989 --- /dev/null +++ b/tests-acpi-bios-table-test-Update-expected-virt-DSDT.patch @@ -0,0 +1,26 @@ +From d3d158cbf6b236022794e867ac395f75fb4f6436 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 11 Feb 2022 16:07:31 +0800 +Subject: [PATCH] tests/acpi/bios-table-test: Update expected virt/DSDT file + +Update DSDT binary and empty bios-tables-test-allowd-diff.h + +Signed-off-by: Keqian Zhu +--- + tests/data/acpi/virt/DSDT | Bin 5669 -> 5669 bytes + tests/data/acpi/virt/DSDT.memhp | Bin 7030 -> 7030 bytes + tests/data/acpi/virt/DSDT.numamem | Bin 5669 -> 5669 bytes + tests/data/acpi/virt/DSDT.pxb | Bin 8152 -> 8152 bytes + tests/qtest/bios-tables-test-allowed-diff.h | 1 - + 5 files changed, 1 deletion(-) + +diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h +index 7b4adbc822..dfb8523c8b 100644 +--- a/tests/qtest/bios-tables-test-allowed-diff.h ++++ b/tests/qtest/bios-tables-test-allowed-diff.h +@@ -1,2 +1 @@ + /* List of comma-separated changed AML files to ignore */ +-"tests/data/acpi/virt/DSDT", +-- +2.27.0 + -- Gitee From c8668035f6482fe68fa52626596cf3eb849cf051 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 3 Apr 2020 16:16:18 +0800 Subject: [PATCH 10/28] arm/virt: Add CPU hotplug framework Establish the CPU hotplug framework for arm/virt, we will add necessary code legs to this framework gradually to realize CPU hotplug finally. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta (cherry picked from commit 9dfe0cc4e9970f93b817068efd0bd6e0d98ca0b2) --- arm-virt-Add-CPU-hotplug-framework.patch | 69 ++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 arm-virt-Add-CPU-hotplug-framework.patch diff --git a/arm-virt-Add-CPU-hotplug-framework.patch b/arm-virt-Add-CPU-hotplug-framework.patch new file mode 100644 index 00000000..4fdcf9f0 --- /dev/null +++ b/arm-virt-Add-CPU-hotplug-framework.patch @@ -0,0 +1,69 @@ +From 209b3e4e522b8f7f41e495feaade96ee9a91e46a Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 3 Apr 2020 16:16:18 +0800 +Subject: [PATCH] arm/virt: Add CPU hotplug framework + +Establish the CPU hotplug framework for arm/virt, we will add +necessary code legs to this framework gradually to realize CPU +hotplug finally. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 9b73c479c4..11155fcb70 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -2586,6 +2586,18 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev, + dev, &error_abort); + } + ++static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ /* Currently nothing to do */ ++} ++ ++static void virt_cpu_plug(HotplugHandler *hotplug_dev, ++ DeviceState *dev, Error **errp) ++{ ++ /* Currently nothing to do */ ++} ++ + static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) + { +@@ -2619,6 +2631,8 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, + qdev_prop_set_uint32(dev, "len-reserved-regions", 1); + qdev_prop_set_string(dev, "reserved-regions[0]", resv_prop_str); + g_free(resv_prop_str); ++ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { ++ virt_cpu_pre_plug(hotplug_dev, dev, errp); + } + } + +@@ -2637,6 +2651,8 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev, + } + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + virt_memory_plug(hotplug_dev, dev, errp); ++ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { ++ virt_cpu_plug(hotplug_dev, dev, errp); + } + if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { + PCIDevice *pdev = PCI_DEVICE(dev); +@@ -2717,7 +2733,8 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, + MachineClass *mc = MACHINE_GET_CLASS(machine); + + if (device_is_dynamic_sysbus(mc, dev) || +- (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM))) { ++ (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) || ++ (object_dynamic_cast(OBJECT(dev), TYPE_CPU))) { + return HOTPLUG_HANDLER(machine); + } + if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { +-- +2.27.0 + -- Gitee From 8a4141881a490db8efb2f3e9b6d668912ce1bad3 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Mon, 6 Apr 2020 10:54:35 +0800 Subject: [PATCH 11/28] arm/virt: Add CPU topology support The CPU topology specified by user (through -smp options) is used in ACPI PPTT. Now we will use this information to locate which CPU to plug or unplug. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta (cherry picked from commit f53ccf3efe6b1894a4a38dd5acae724b9036cbda) --- arm-virt-Add-CPU-topology-support.patch | 269 ++++++++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 arm-virt-Add-CPU-topology-support.patch diff --git a/arm-virt-Add-CPU-topology-support.patch b/arm-virt-Add-CPU-topology-support.patch new file mode 100644 index 00000000..016b3ed6 --- /dev/null +++ b/arm-virt-Add-CPU-topology-support.patch @@ -0,0 +1,269 @@ +From 5454c00908236dcabcbf9ae246ccb69e1fcea72e Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Mon, 6 Apr 2020 10:54:35 +0800 +Subject: [PATCH] arm/virt: Add CPU topology support + +The CPU topology specified by user (through -smp options) is used in +ACPI PPTT. Now we will use this information to locate which CPU to +plug or unplug. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt.c | 87 ++++++++++++++++++++++++++++++++++++++- + include/hw/arm/topology.h | 68 ++++++++++++++++++++++++++++++ + qapi/machine.json | 2 + + target/arm/cpu.c | 4 ++ + target/arm/cpu.h | 4 ++ + 5 files changed, 163 insertions(+), 2 deletions(-) + create mode 100644 include/hw/arm/topology.h + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 11155fcb70..a12e718686 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -39,6 +39,7 @@ + #include "hw/sysbus.h" + #include "hw/arm/boot.h" + #include "hw/arm/primecell.h" ++#include "hw/arm/topology.h" + #include "hw/arm/virt.h" + #include "hw/block/flash.h" + #include "hw/vfio/vfio-calxeda-xgmac.h" +@@ -2524,6 +2525,7 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms) + int n; + unsigned int max_cpus = ms->smp.max_cpus; + VirtMachineState *vms = VIRT_MACHINE(ms); ++ ARMCPUTopoInfo topo; + + if (ms->possible_cpus) { + assert(ms->possible_cpus->len == max_cpus); +@@ -2535,10 +2537,19 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms) + ms->possible_cpus->len = max_cpus; + for (n = 0; n < ms->possible_cpus->len; n++) { + ms->possible_cpus->cpus[n].type = ms->cpu_type; ++ ms->possible_cpus->cpus[n].vcpus_count = 1; + ms->possible_cpus->cpus[n].arch_id = + virt_cpu_mp_affinity(vms, n); ++ ++ topo_ids_from_idx(n, ms->smp.clusters, ms->smp.cores, ms->smp.threads, &topo); ++ ms->possible_cpus->cpus[n].props.has_socket_id = true; ++ ms->possible_cpus->cpus[n].props.socket_id = topo.pkg_id; ++ ms->possible_cpus->cpus[n].props.has_cluster_id = true; ++ ms->possible_cpus->cpus[n].props.cluster_id = topo.cluster_id; ++ ms->possible_cpus->cpus[n].props.has_core_id = true; ++ ms->possible_cpus->cpus[n].props.core_id = topo.core_id; + ms->possible_cpus->cpus[n].props.has_thread_id = true; +- ms->possible_cpus->cpus[n].props.thread_id = n; ++ ms->possible_cpus->cpus[n].props.thread_id = topo.smt_id; + } + return ms->possible_cpus; + } +@@ -2589,7 +2600,79 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev, + static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) + { +- /* Currently nothing to do */ ++ CPUState *cs = CPU(dev); ++ ARMCPUTopoInfo topo; ++ ARMCPU *cpu = ARM_CPU(dev); ++ MachineState *ms = MACHINE(hotplug_dev); ++ int smp_clusters = ms->smp.clusters; ++ int smp_cores = ms->smp.cores; ++ int smp_threads = ms->smp.threads; ++ ++ /* if cpu idx is not set, set it based on socket/cluster/core/thread ++ * properties ++ */ ++ if (cs->cpu_index == UNASSIGNED_CPU_INDEX) { ++ int max_socket = ms->smp.max_cpus / smp_threads / smp_cores / smp_clusters; ++ if (cpu->socket_id < 0 || cpu->socket_id >= max_socket) { ++ error_setg(errp, "Invalid CPU socket-id: %u must be in range 0:%u", ++ cpu->socket_id, max_socket - 1); ++ return; ++ } ++ if (cpu->cluster_id < 0 || cpu->cluster_id >= smp_clusters) { ++ error_setg(errp, "Invalid CPU cluster-id: %u must be in range 0:%u", ++ cpu->cluster_id, smp_clusters - 1); ++ return; ++ } ++ if (cpu->core_id < 0 || cpu->core_id >= smp_cores) { ++ error_setg(errp, "Invalid CPU core-id: %u must be in range 0:%u", ++ cpu->core_id, smp_cores - 1); ++ return; ++ } ++ if (cpu->thread_id < 0 || cpu->thread_id >= smp_threads) { ++ error_setg(errp, "Invalid CPU thread-id: %u must be in range 0:%u", ++ cpu->thread_id, smp_threads - 1); ++ return; ++ } ++ ++ topo.pkg_id = cpu->socket_id; ++ topo.cluster_id = cpu->cluster_id; ++ topo.core_id = cpu->core_id; ++ topo.smt_id = cpu->thread_id; ++ cs->cpu_index = idx_from_topo_ids(smp_clusters, smp_cores, smp_threads, &topo); ++ } ++ ++ /* if 'address' properties socket-id/cluster-id/core-id/thread-id are not ++ * set, set them so that machine_query_hotpluggable_cpus would show correct ++ * values ++ */ ++ topo_ids_from_idx(cs->cpu_index, smp_clusters, smp_cores, smp_threads, &topo); ++ if (cpu->socket_id != -1 && cpu->socket_id != topo.pkg_id) { ++ error_setg(errp, "property socket-id: %u doesn't match set idx:" ++ " 0x%x (socket-id: %u)", cpu->socket_id, cs->cpu_index, topo.pkg_id); ++ return; ++ } ++ cpu->socket_id = topo.pkg_id; ++ ++ if (cpu->cluster_id != -1 && cpu->cluster_id != topo.cluster_id) { ++ error_setg(errp, "property cluster-id: %u doesn't match set idx:" ++ " 0x%x (cluster-id: %u)", cpu->cluster_id, cs->cpu_index, topo.cluster_id); ++ return; ++ } ++ cpu->cluster_id = topo.cluster_id; ++ ++ if (cpu->core_id != -1 && cpu->core_id != topo.core_id) { ++ error_setg(errp, "property core-id: %u doesn't match set idx:" ++ " 0x%x (core-id: %u)", cpu->core_id, cs->cpu_index, topo.core_id); ++ return; ++ } ++ cpu->core_id = topo.core_id; ++ ++ if (cpu->thread_id != -1 && cpu->thread_id != topo.smt_id) { ++ error_setg(errp, "property thread-id: %u doesn't match set idx:" ++ " 0x%x (thread-id: %u)", cpu->thread_id, cs->cpu_index, topo.smt_id); ++ return; ++ } ++ cpu->thread_id = topo.smt_id; + } + + static void virt_cpu_plug(HotplugHandler *hotplug_dev, +diff --git a/include/hw/arm/topology.h b/include/hw/arm/topology.h +new file mode 100644 +index 0000000000..d0dad1a9a3 +--- /dev/null ++++ b/include/hw/arm/topology.h +@@ -0,0 +1,68 @@ ++/* ++ * ARM CPU topology data structures and functions ++ * ++ * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO.,LTD. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, see . ++ */ ++ ++#ifndef HW_ARM_TOPOLOGY_H ++#define HW_ARM_TOPOLOGY_H ++ ++typedef struct ARMCPUTopoInfo { ++ unsigned pkg_id; ++ unsigned cluster_id; ++ unsigned core_id; ++ unsigned smt_id; ++} ARMCPUTopoInfo; ++ ++/* Calculate (contiguous) CPU index based on topology */ ++static inline unsigned idx_from_topo_ids(unsigned nr_clusters, ++ unsigned nr_cores, ++ unsigned nr_threads, ++ const ARMCPUTopoInfo *topo) ++{ ++ assert(nr_clusters > 0); ++ assert(nr_cores > 0); ++ assert(nr_threads > 0); ++ assert(topo != NULL); ++ ++ return topo->pkg_id * nr_clusters * nr_cores * nr_threads + ++ topo->cluster_id * nr_cores + ++ topo->core_id * nr_threads + ++ topo->smt_id; ++} ++ ++/* Calculate thread/core/cluster/package topology ++ * based on (contiguous) CPU index ++ */ ++static inline void topo_ids_from_idx(unsigned cpu_index, ++ unsigned nr_clusters, ++ unsigned nr_cores, ++ unsigned nr_threads, ++ ARMCPUTopoInfo *topo) ++{ ++ assert(nr_clusters > 0); ++ assert(nr_cores > 0); ++ assert(nr_threads > 0); ++ assert(topo != NULL); ++ ++ topo->smt_id = cpu_index % nr_threads; ++ topo->core_id = cpu_index / nr_threads % nr_cores; ++ topo->cluster_id = cpu_index / nr_threads / nr_cores % nr_clusters; ++ topo->pkg_id = cpu_index / nr_threads / nr_cores / nr_clusters; ++} ++ ++#endif /* HW_ARM_TOPOLOGY_H */ ++ +diff --git a/qapi/machine.json b/qapi/machine.json +index 8faa51074e..6822cafe2e 100644 +--- a/qapi/machine.json ++++ b/qapi/machine.json +@@ -868,6 +868,7 @@ + # @node-id: NUMA node ID the CPU belongs to + # @socket-id: socket number within node/board the CPU belongs to + # @die-id: die number within socket the CPU belongs to (since 4.1) ++# @cluster-id: cluster number within die the CPU belongs to (since 6.2) + # @core-id: core number within die the CPU belongs to + # @thread-id: thread number within core the CPU belongs to + # +@@ -883,6 +884,7 @@ + 'data': { '*node-id': 'int', + '*socket-id': 'int', + '*die-id': 'int', ++ '*cluster-id': 'int', + '*core-id': 'int', + '*thread-id': 'int' + } +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index f06ba29885..9fd8e57971 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -2507,6 +2507,10 @@ static Property arm_cpu_properties[] = { + DEFINE_PROP_UINT64("mp-affinity", ARMCPU, + mp_affinity, ARM64_AFFINITY_INVALID), + DEFINE_PROP_INT32("node-id", ARMCPU, node_id, CPU_UNSET_NUMA_NODE_ID), ++ DEFINE_PROP_INT32("socket-id", ARMCPU, socket_id, -1), ++ DEFINE_PROP_INT32("cluster-id", ARMCPU, cluster_id, -1), ++ DEFINE_PROP_INT32("core-id", ARMCPU, core_id, -1), ++ DEFINE_PROP_INT32("thread-id", ARMCPU, thread_id, -1), + DEFINE_PROP_INT32("core-count", ARMCPU, core_count, -1), + DEFINE_PROP_END_OF_LIST() + }; +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index 947897d5ac..eb804dffaa 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -1006,6 +1006,10 @@ struct ARMCPU { + QLIST_HEAD(, ARMELChangeHook) el_change_hooks; + + int32_t node_id; /* NUMA node this CPU belongs to */ ++ int32_t socket_id; ++ int32_t cluster_id; ++ int32_t core_id; ++ int32_t thread_id; + + /* Used to synchronize KVM and QEMU in-kernel device levels */ + uint8_t device_irq_level; +-- +2.27.0 + -- Gitee From ced81a56f3ef1ff018ad1cbe997306ccf38cac3c Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 23 Apr 2020 20:54:18 +0800 Subject: [PATCH 12/28] test/numa: Adjust aarch64 numa test We have supported topology for arm/virt in previous patch, which changes the meaning of "thread-id", so we must modify test case. Signed-off-by: Keqian Zhu (cherry picked from commit 61bc7026130c63f054fa97f59b48e068f0210b79) --- test-numa-Adjust-aarch64-numa-test.patch | 59 ++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 test-numa-Adjust-aarch64-numa-test.patch diff --git a/test-numa-Adjust-aarch64-numa-test.patch b/test-numa-Adjust-aarch64-numa-test.patch new file mode 100644 index 00000000..cb333143 --- /dev/null +++ b/test-numa-Adjust-aarch64-numa-test.patch @@ -0,0 +1,59 @@ +From 1a347bf3f8e7e31cdaed265af22853d66c202090 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Thu, 23 Apr 2020 20:54:18 +0800 +Subject: [PATCH] test/numa: Adjust aarch64 numa test + +We have supported topology for arm/virt in previous patch, which +changes the meaning of "thread-id", so we must modify test case. + +Signed-off-by: Keqian Zhu +--- + tests/qtest/numa-test.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/tests/qtest/numa-test.c b/tests/qtest/numa-test.c +index 90bf68a5b3..08f28012c8 100644 +--- a/tests/qtest/numa-test.c ++++ b/tests/qtest/numa-test.c +@@ -223,17 +223,17 @@ static void aarch64_numa_cpu(const void *data) + QTestState *qts; + g_autofree char *cli = NULL; + +- cli = make_cli(data, "-machine smp.cpus=2 " ++ cli = make_cli(data, "-machine smp.cpus=2,smp.cores=2 " + "-numa node,nodeid=0,memdev=ram -numa node,nodeid=1 " +- "-numa cpu,node-id=1,thread-id=0 " +- "-numa cpu,node-id=0,thread-id=1"); ++ "-numa cpu,node-id=1,core-id=0 " ++ "-numa cpu,node-id=0,core-id=1"); + qts = qtest_init(cli); + cpus = get_cpus(qts, &resp); + g_assert(cpus); + + while ((e = qlist_pop(cpus))) { + QDict *cpu, *props; +- int64_t thread, node; ++ int64_t core, node; + + cpu = qobject_to(QDict, e); + g_assert(qdict_haskey(cpu, "props")); +@@ -241,12 +241,12 @@ static void aarch64_numa_cpu(const void *data) + + g_assert(qdict_haskey(props, "node-id")); + node = qdict_get_int(props, "node-id"); +- g_assert(qdict_haskey(props, "thread-id")); +- thread = qdict_get_int(props, "thread-id"); ++ g_assert(qdict_haskey(props, "core-id")); ++ core = qdict_get_int(props, "core-id"); + +- if (thread == 0) { ++ if (core == 0) { + g_assert_cmpint(node, ==, 1); +- } else if (thread == 1) { ++ } else if (core == 1) { + g_assert_cmpint(node, ==, 0); + } else { + g_assert(false); +-- +2.27.0 + -- Gitee From e6b9178be20e6afbe6ba38fc0acbf2e446446f35 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Mon, 6 Apr 2020 12:50:54 +0800 Subject: [PATCH 13/28] hw/arm/virt: Factor out some CPU init codes to pre_plug hook The init path of hotplugged CPU is pre_plug/realize/plug, so we must move these init code in machvirt_init to pre_plug hook, to let them be shared by all CPUs. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta (cherry picked from commit 3587e6e0654962090fdfbae30485c0355f1a9faf) --- ...or-out-some-CPU-init-codes-to-pre_pl.patch | 261 ++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 hw-arm-virt-Factor-out-some-CPU-init-codes-to-pre_pl.patch diff --git a/hw-arm-virt-Factor-out-some-CPU-init-codes-to-pre_pl.patch b/hw-arm-virt-Factor-out-some-CPU-init-codes-to-pre_pl.patch new file mode 100644 index 00000000..fe733c62 --- /dev/null +++ b/hw-arm-virt-Factor-out-some-CPU-init-codes-to-pre_pl.patch @@ -0,0 +1,261 @@ +From 7838609e9a7743af03c58ae46afd26070b2feea6 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Mon, 6 Apr 2020 12:50:54 +0800 +Subject: [PATCH] hw/arm/virt: Factor out some CPU init codes to pre_plug hook + +The init path of hotplugged CPU is pre_plug/realize/plug, so we +must move these init code in machvirt_init to pre_plug hook, to +let them be shared by all CPUs. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt.c | 197 ++++++++++++++++++++++++++------------------------ + 1 file changed, 103 insertions(+), 94 deletions(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index a12e718686..149e0245d7 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -213,6 +213,10 @@ static const char *valid_cpus[] = { + ARM_CPU_TYPE_NAME("max"), + }; + ++static MemoryRegion *secure_sysmem; ++static MemoryRegion *tag_sysmem; ++static MemoryRegion *secure_tag_sysmem; ++ + static bool cpu_type_valid(const char *cpu) + { + int i; +@@ -1990,9 +1994,6 @@ static void machvirt_init(MachineState *machine) + MachineClass *mc = MACHINE_GET_CLASS(machine); + const CPUArchIdList *possible_cpus; + MemoryRegion *sysmem = get_system_memory(); +- MemoryRegion *secure_sysmem = NULL; +- MemoryRegion *tag_sysmem = NULL; +- MemoryRegion *secure_tag_sysmem = NULL; + int n, virt_max_cpus; + bool firmware_loaded; + bool aarch64 = true; +@@ -2099,100 +2100,11 @@ static void machvirt_init(MachineState *machine) + } + + cpuobj = object_new(possible_cpus->cpus[n].type); +- object_property_set_int(cpuobj, "mp-affinity", +- possible_cpus->cpus[n].arch_id, NULL); ++ aarch64 &= object_property_get_bool(cpuobj, "aarch64", NULL); + + cs = CPU(cpuobj); + cs->cpu_index = n; + +- numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj), +- &error_fatal); +- +- aarch64 &= object_property_get_bool(cpuobj, "aarch64", NULL); +- +- if (!vms->secure) { +- object_property_set_bool(cpuobj, "has_el3", false, NULL); +- } +- +- if (!vms->virt && object_property_find(cpuobj, "has_el2")) { +- object_property_set_bool(cpuobj, "has_el2", false, NULL); +- } +- +- if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) { +- object_property_set_int(cpuobj, "psci-conduit", vms->psci_conduit, +- NULL); +- +- /* Secondary CPUs start in PSCI powered-down state */ +- if (n > 0) { +- object_property_set_bool(cpuobj, "start-powered-off", true, +- NULL); +- } +- } +- +- if (vmc->kvm_no_adjvtime && +- object_property_find(cpuobj, "kvm-no-adjvtime")) { +- object_property_set_bool(cpuobj, "kvm-no-adjvtime", true, NULL); +- } +- +- if (vmc->no_kvm_steal_time && +- object_property_find(cpuobj, "kvm-steal-time")) { +- object_property_set_bool(cpuobj, "kvm-steal-time", false, NULL); +- } +- +- if (vmc->no_pmu && object_property_find(cpuobj, "pmu")) { +- object_property_set_bool(cpuobj, "pmu", false, NULL); +- } +- +- if (object_property_find(cpuobj, "reset-cbar")) { +- object_property_set_int(cpuobj, "reset-cbar", +- vms->memmap[VIRT_CPUPERIPHS].base, +- &error_abort); +- } +- +- object_property_set_link(cpuobj, "memory", OBJECT(sysmem), +- &error_abort); +- if (vms->secure) { +- object_property_set_link(cpuobj, "secure-memory", +- OBJECT(secure_sysmem), &error_abort); +- } +- +- if (vms->mte) { +- /* Create the memory region only once, but link to all cpus. */ +- if (!tag_sysmem) { +- /* +- * The property exists only if MemTag is supported. +- * If it is, we must allocate the ram to back that up. +- */ +- if (!object_property_find(cpuobj, "tag-memory")) { +- error_report("MTE requested, but not supported " +- "by the guest CPU"); +- exit(1); +- } +- +- tag_sysmem = g_new(MemoryRegion, 1); +- memory_region_init(tag_sysmem, OBJECT(machine), +- "tag-memory", UINT64_MAX / 32); +- +- if (vms->secure) { +- secure_tag_sysmem = g_new(MemoryRegion, 1); +- memory_region_init(secure_tag_sysmem, OBJECT(machine), +- "secure-tag-memory", UINT64_MAX / 32); +- +- /* As with ram, secure-tag takes precedence over tag. */ +- memory_region_add_subregion_overlap(secure_tag_sysmem, 0, +- tag_sysmem, -1); +- } +- } +- +- object_property_set_link(cpuobj, "tag-memory", OBJECT(tag_sysmem), +- &error_abort); +- if (vms->secure) { +- object_property_set_link(cpuobj, "secure-tag-memory", +- OBJECT(secure_tag_sysmem), +- &error_abort); +- } +- } +- + qdev_realize(DEVICE(cpuobj), NULL, &error_fatal); + object_unref(cpuobj); + } +@@ -2600,10 +2512,16 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev, + static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) + { +- CPUState *cs = CPU(dev); + ARMCPUTopoInfo topo; ++ Object *cpuobj = OBJECT(dev); ++ CPUState *cs = CPU(dev); + ARMCPU *cpu = ARM_CPU(dev); + MachineState *ms = MACHINE(hotplug_dev); ++ MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); ++ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); ++ VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(hotplug_dev); ++ const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); ++ MemoryRegion *sysmem = get_system_memory(); + int smp_clusters = ms->smp.clusters; + int smp_cores = ms->smp.cores; + int smp_threads = ms->smp.threads; +@@ -2673,6 +2591,97 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, + return; + } + cpu->thread_id = topo.smt_id; ++ ++ /* Init some properties */ ++ ++ object_property_set_int(cpuobj, "mp-affinity", ++ possible_cpus->cpus[cs->cpu_index].arch_id, NULL); ++ ++ numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj), ++ &error_fatal); ++ ++ if (!vms->secure) { ++ object_property_set_bool(cpuobj, "has_el3", false, NULL); ++ } ++ ++ if (!vms->virt && object_property_find(cpuobj, "has_el2")) { ++ object_property_set_bool(cpuobj, "has_el2", false, NULL); ++ } ++ ++ if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) { ++ object_property_set_int(cpuobj, "psci-conduit", vms->psci_conduit, ++ NULL); ++ ++ /* Secondary CPUs start in PSCI powered-down state */ ++ if (cs->cpu_index > 0) { ++ object_property_set_bool(cpuobj, "start-powered-off", true, ++ NULL); ++ } ++ } ++ ++ if (vmc->kvm_no_adjvtime && ++ object_property_find(cpuobj, "kvm-no-adjvtime")) { ++ object_property_set_bool(cpuobj, "kvm-no-adjvtime", true, NULL); ++ } ++ ++ if (vmc->no_kvm_steal_time && ++ object_property_find(cpuobj, "kvm-steal-time")) { ++ object_property_set_bool(cpuobj, "kvm-steal-time", false, NULL); ++ } ++ ++ if (vmc->no_pmu && object_property_find(cpuobj, "pmu")) { ++ object_property_set_bool(cpuobj, "pmu", false, NULL); ++ } ++ ++ if (object_property_find(cpuobj, "reset-cbar")) { ++ object_property_set_int(cpuobj, "reset-cbar", ++ vms->memmap[VIRT_CPUPERIPHS].base, ++ &error_abort); ++ } ++ ++ object_property_set_link(cpuobj, "memory", OBJECT(sysmem), ++ &error_abort); ++ if (vms->secure) { ++ object_property_set_link(cpuobj, "secure-memory", ++ OBJECT(secure_sysmem), &error_abort); ++ } ++ ++ if (vms->mte) { ++ /* Create the memory region only once, but link to all cpus. */ ++ if (!tag_sysmem) { ++ /* ++ * The property exists only if MemTag is supported. ++ * If it is, we must allocate the ram to back that up. ++ */ ++ if (!object_property_find(cpuobj, "tag-memory")) { ++ error_report("MTE requested, but not supported " ++ "by the guest CPU"); ++ exit(1); ++ } ++ ++ tag_sysmem = g_new(MemoryRegion, 1); ++ memory_region_init(tag_sysmem, OBJECT(ms), ++ "tag-memory", UINT64_MAX / 32); ++ ++ if (vms->secure) { ++ secure_tag_sysmem = g_new(MemoryRegion, 1); ++ memory_region_init(secure_tag_sysmem, OBJECT(ms), ++ "secure-tag-memory", UINT64_MAX / 32); ++ ++ /* As with ram, secure-tag takes precedence over tag. */ ++ memory_region_add_subregion_overlap(secure_tag_sysmem, 0, ++ tag_sysmem, -1); ++ } ++ } ++ ++ object_property_set_link(cpuobj, "tag-memory", OBJECT(tag_sysmem), ++ &error_abort); ++ if (vms->secure) { ++ object_property_set_link(cpuobj, "secure-tag-memory", ++ OBJECT(secure_tag_sysmem), ++ &error_abort); ++ } ++ } + } + + static void virt_cpu_plug(HotplugHandler *hotplug_dev, +-- +2.27.0 + -- Gitee From 33d00cea883f208b9b702c9ea9a456924d14fcfa Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Thu, 9 Apr 2020 09:31:22 +0800 Subject: [PATCH 14/28] hw/arm/boot: Add manually register and trigger of CPU reset We need to register and trigger CPU reset manually for hotplugged CPU. Besides, we gather CPU reset handlers of all CPUs because CPU reset should happen before GIC reset. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta (cherry picked from commit e38ab50a87d6f581d282e606ac12db5e8238c1e1) --- ...manually-register-and-trigger-of-CPU.patch | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 hw-arm-boot-Add-manually-register-and-trigger-of-CPU.patch diff --git a/hw-arm-boot-Add-manually-register-and-trigger-of-CPU.patch b/hw-arm-boot-Add-manually-register-and-trigger-of-CPU.patch new file mode 100644 index 00000000..0055d3b3 --- /dev/null +++ b/hw-arm-boot-Add-manually-register-and-trigger-of-CPU.patch @@ -0,0 +1,116 @@ +From 9dc22ff87eb61a8b2bcc5892961ec432986893c9 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Thu, 9 Apr 2020 09:31:22 +0800 +Subject: [PATCH] hw/arm/boot: Add manually register and trigger of CPU reset + +We need to register and trigger CPU reset manually for hotplugged +CPU. Besides, we gather CPU reset handlers of all CPUs because CPU +reset should happen before GIC reset. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/boot.c | 18 ++++++++++++++++++ + hw/core/reset.c | 25 +++++++++++++++++++++++++ + include/hw/arm/boot.h | 3 +++ + include/sysemu/reset.h | 4 ++++ + 4 files changed, 50 insertions(+) + +diff --git a/hw/arm/boot.c b/hw/arm/boot.c +index 21024f7999..3d45de1772 100644 +--- a/hw/arm/boot.c ++++ b/hw/arm/boot.c +@@ -814,6 +814,24 @@ static void do_cpu_reset(void *opaque) + } + } + ++void cpu_hotplug_register_reset(int ncpu) ++{ ++ CPUState *cpu_0 = qemu_get_cpu(0); ++ CPUState *cpu = qemu_get_cpu(ncpu); ++ QEMUResetEntry *entry = qemu_get_reset_entry(do_cpu_reset, cpu_0); ++ ++ assert(entry); ++ /* Gather the reset handlers of all CPUs */ ++ qemu_register_reset_after(entry, do_cpu_reset, cpu); ++} ++ ++void cpu_hotplug_reset_manually(int ncpu) ++{ ++ CPUState *cpu = qemu_get_cpu(ncpu); ++ ++ do_cpu_reset(cpu); ++} ++ + /** + * load_image_to_fw_cfg() - Load an image file into an fw_cfg entry identified + * by key. +diff --git a/hw/core/reset.c b/hw/core/reset.c +index e923723d38..314d332111 100644 +--- a/hw/core/reset.c ++++ b/hw/core/reset.c +@@ -48,6 +48,31 @@ void qemu_register_reset(QEMUResetHandler *func, void *opaque) + QTAILQ_INSERT_TAIL(&reset_handlers, re, entry); + } + ++QEMUResetEntry *qemu_get_reset_entry(QEMUResetHandler *func, ++ void *opaque) ++{ ++ QEMUResetEntry *re; ++ ++ QTAILQ_FOREACH(re, &reset_handlers, entry) { ++ if (re->func == func && re->opaque == opaque) { ++ return re; ++ } ++ } ++ ++ return NULL; ++} ++ ++void qemu_register_reset_after(QEMUResetEntry *entry, ++ QEMUResetHandler *func, ++ void *opaque) ++{ ++ QEMUResetEntry *re = g_malloc0(sizeof(QEMUResetEntry)); ++ ++ re->func = func; ++ re->opaque = opaque; ++ QTAILQ_INSERT_AFTER(&reset_handlers, entry, re, entry); ++} ++ + void qemu_unregister_reset(QEMUResetHandler *func, void *opaque) + { + QEMUResetEntry *re; +diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h +index ce2b48b88b..c3c4d3ea79 100644 +--- a/include/hw/arm/boot.h ++++ b/include/hw/arm/boot.h +@@ -119,6 +119,9 @@ struct arm_boot_info { + arm_endianness endianness; + }; + ++void cpu_hotplug_register_reset(int ncpu); ++void cpu_hotplug_reset_manually(int ncpu); ++ + /** + * arm_load_kernel - Loads memory with everything needed to boot + * +diff --git a/include/sysemu/reset.h b/include/sysemu/reset.h +index 0b0d6d7598..f3ff26c637 100644 +--- a/include/sysemu/reset.h ++++ b/include/sysemu/reset.h +@@ -2,7 +2,11 @@ + #define QEMU_SYSEMU_RESET_H + + typedef void QEMUResetHandler(void *opaque); ++typedef struct QEMUResetEntry QEMUResetEntry; + ++QEMUResetEntry *qemu_get_reset_entry(QEMUResetHandler *func, void *opaque); ++void qemu_register_reset_after(QEMUResetEntry *entry, ++ QEMUResetHandler *func, void *opaque); + void qemu_register_reset(QEMUResetHandler *func, void *opaque); + void qemu_unregister_reset(QEMUResetHandler *func, void *opaque); + void qemu_devices_reset(void); +-- +2.27.0 + -- Gitee From 4a4c8273fc4bf7fb496369d0681301271be73222 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Sun, 5 Apr 2020 15:29:16 +0800 Subject: [PATCH 15/28] arm/virt/gic: Construct irqs connection from create_gic Make the irqs can be connected to for individual CPU. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta (cherry picked from commit 6161210e01ad1c757e44b0a31c3424f770c9281a) --- ...struct-irqs-connection-from-create_g.patch | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 arm-virt-gic-Construct-irqs-connection-from-create_g.patch diff --git a/arm-virt-gic-Construct-irqs-connection-from-create_g.patch b/arm-virt-gic-Construct-irqs-connection-from-create_g.patch new file mode 100644 index 00000000..c16cb0ec --- /dev/null +++ b/arm-virt-gic-Construct-irqs-connection-from-create_g.patch @@ -0,0 +1,124 @@ +From 03e050611d6dc9909166fd31dd11abf6fd5012ea Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Sun, 5 Apr 2020 15:29:16 +0800 +Subject: [PATCH] arm/virt/gic: Construct irqs connection from create_gic + +Make the irqs can be connected to for individual CPU. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt.c | 90 ++++++++++++++++++++++++++++----------------------- + 1 file changed, 49 insertions(+), 41 deletions(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 149e0245d7..0af0a996a1 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -772,6 +772,54 @@ static void create_v2m(VirtMachineState *vms) + vms->msi_controller = VIRT_MSI_CTRL_GICV2M; + } + ++static void connect_gic_cpu_irqs(VirtMachineState *vms, int i) ++{ ++ DeviceState *cpudev = DEVICE(qemu_get_cpu(i)); ++ SysBusDevice *gicbusdev = SYS_BUS_DEVICE(vms->gic); ++ int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS; ++ int num_cpus = object_property_get_uint(OBJECT(vms->gic), "num-cpu", NULL); ++ int gic_type = vms->gic_version; ++ int irq; ++ /* Mapping from the output timer irq lines from the CPU to the ++ * GIC PPI inputs we use for the virt board. ++ */ ++ const int timer_irq[] = { ++ [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ, ++ [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ, ++ [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ, ++ [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ, ++ }; ++ ++ for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) { ++ qdev_connect_gpio_out(cpudev, irq, ++ qdev_get_gpio_in(vms->gic, ++ ppibase + timer_irq[irq])); ++ } ++ ++ if (gic_type == 3) { ++ qemu_irq irq = qdev_get_gpio_in(vms->gic, ++ ppibase + ARCH_GIC_MAINT_IRQ); ++ qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", ++ 0, irq); ++ } else if (vms->virt) { ++ qemu_irq irq = qdev_get_gpio_in(vms->gic, ++ ppibase + ARCH_GIC_MAINT_IRQ); ++ sysbus_connect_irq(gicbusdev, i + 4 * num_cpus, irq); ++ } ++ ++ qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0, ++ qdev_get_gpio_in(vms->gic, ppibase ++ + VIRTUAL_PMU_IRQ)); ++ ++ sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ)); ++ sysbus_connect_irq(gicbusdev, i + num_cpus, ++ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ)); ++ sysbus_connect_irq(gicbusdev, i + 2 * num_cpus, ++ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ)); ++ sysbus_connect_irq(gicbusdev, i + 3 * num_cpus, ++ qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ)); ++} ++ + static void create_gic(VirtMachineState *vms, MemoryRegion *mem) + { + MachineState *ms = MACHINE(vms); +@@ -849,47 +897,7 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem) + * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs. + */ + for (i = 0; i < smp_cpus; i++) { +- DeviceState *cpudev = DEVICE(qemu_get_cpu(i)); +- int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS; +- int irq; +- /* Mapping from the output timer irq lines from the CPU to the +- * GIC PPI inputs we use for the virt board. +- */ +- const int timer_irq[] = { +- [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ, +- [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ, +- [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ, +- [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ, +- }; +- +- for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) { +- qdev_connect_gpio_out(cpudev, irq, +- qdev_get_gpio_in(vms->gic, +- ppibase + timer_irq[irq])); +- } +- +- if (type == 3) { +- qemu_irq irq = qdev_get_gpio_in(vms->gic, +- ppibase + ARCH_GIC_MAINT_IRQ); +- qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", +- 0, irq); +- } else if (vms->virt) { +- qemu_irq irq = qdev_get_gpio_in(vms->gic, +- ppibase + ARCH_GIC_MAINT_IRQ); +- sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus, irq); +- } +- +- qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0, +- qdev_get_gpio_in(vms->gic, ppibase +- + VIRTUAL_PMU_IRQ)); +- +- sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ)); +- sysbus_connect_irq(gicbusdev, i + smp_cpus, +- qdev_get_gpio_in(cpudev, ARM_CPU_FIQ)); +- sysbus_connect_irq(gicbusdev, i + 2 * smp_cpus, +- qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ)); +- sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus, +- qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ)); ++ connect_gic_cpu_irqs(vms, i); + } + + fdt_add_gic_node(vms); +-- +2.27.0 + -- Gitee From 494cd1482180526bc9b1c16740ad4e05e680523f Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 10 Apr 2020 12:55:17 +0800 Subject: [PATCH 16/28] intc/gicv3_common: Factor out arm_gicv3_common_cpu_realize The CPU object of hotplugged CPU will be defer-created (during hotplug session), so we must factor out realization code to let it can be applied to individual CPU. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta (cherry picked from commit 7e5f5b7ff26bc48205f47d8f29477a8587c71446) --- ...n-Factor-out-arm_gicv3_common_cpu_re.patch | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 intc-gicv3_common-Factor-out-arm_gicv3_common_cpu_re.patch diff --git a/intc-gicv3_common-Factor-out-arm_gicv3_common_cpu_re.patch b/intc-gicv3_common-Factor-out-arm_gicv3_common_cpu_re.patch new file mode 100644 index 00000000..043573e8 --- /dev/null +++ b/intc-gicv3_common-Factor-out-arm_gicv3_common_cpu_re.patch @@ -0,0 +1,51 @@ +From 06cb0756a01796352861b4d47d59db1bde84ec6f Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 12:55:17 +0800 +Subject: [PATCH] intc/gicv3_common: Factor out arm_gicv3_common_cpu_realize + +The CPU object of hotplugged CPU will be defer-created (during +hotplug session), so we must factor out realization code to let +it can be applied to individual CPU. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/intc/arm_gicv3_common.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c +index 9884d2e39b..1a11d1986d 100644 +--- a/hw/intc/arm_gicv3_common.c ++++ b/hw/intc/arm_gicv3_common.c +@@ -301,6 +301,16 @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler, + } + } + ++static void arm_gicv3_common_cpu_realize(GICv3State *s, int ncpu) ++{ ++ CPUState *cpu = qemu_get_cpu(ncpu); ++ ++ s->cpu[ncpu].cpu = cpu; ++ s->cpu[ncpu].gic = s; ++ /* Store GICv3CPUState in CPUARMState gicv3state pointer */ ++ gicv3_set_gicv3state(cpu, &s->cpu[ncpu]); ++} ++ + static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) + { + GICv3State *s = ARM_GICV3_COMMON(dev); +@@ -363,10 +373,7 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) + CPUState *cpu = qemu_get_cpu(i); + uint64_t cpu_affid; + +- s->cpu[i].cpu = cpu; +- s->cpu[i].gic = s; +- /* Store GICv3CPUState in CPUARMState gicv3state pointer */ +- gicv3_set_gicv3state(cpu, &s->cpu[i]); ++ arm_gicv3_common_cpu_realize(s, i); + + /* Pre-construct the GICR_TYPER: + * For our implementation: +-- +2.27.0 + -- Gitee From 4f562e8fa1ef7ad0cbf370034f840b3a38affd42 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 10 Apr 2020 10:59:55 +0800 Subject: [PATCH 17/28] intc/gicv3_cpuif: Factor out gicv3_init_one_cpuif The CPU object of hotplugged CPU will be defer-created (during hotplug session), so we must factor out some code to let it can be applied to individual CPU. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta (cherry picked from commit 0583d886a2bfa994a8be64d678a54c333cc5377d) --- ...puif-Factor-out-gicv3_init_one_cpuif.patch | 196 ++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 intc-gicv3_cpuif-Factor-out-gicv3_init_one_cpuif.patch diff --git a/intc-gicv3_cpuif-Factor-out-gicv3_init_one_cpuif.patch b/intc-gicv3_cpuif-Factor-out-gicv3_init_one_cpuif.patch new file mode 100644 index 00000000..87c93443 --- /dev/null +++ b/intc-gicv3_cpuif-Factor-out-gicv3_init_one_cpuif.patch @@ -0,0 +1,196 @@ +From 62b5c897e367c3db477a680b7557662347677433 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 10:59:55 +0800 +Subject: [PATCH] intc/gicv3_cpuif: Factor out gicv3_init_one_cpuif + +The CPU object of hotplugged CPU will be defer-created (during +hotplug session), so we must factor out some code to let it can +be applied to individual CPU. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/intc/arm_gicv3.c | 5 +- + hw/intc/arm_gicv3_cpuif.c | 122 ++++++++++++++++++-------------------- + hw/intc/gicv3_internal.h | 2 +- + 3 files changed, 64 insertions(+), 65 deletions(-) + +diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c +index 9f5f815db9..40016cb84a 100644 +--- a/hw/intc/arm_gicv3.c ++++ b/hw/intc/arm_gicv3.c +@@ -382,6 +382,7 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) + GICv3State *s = ARM_GICV3(dev); + ARMGICv3Class *agc = ARM_GICV3_GET_CLASS(s); + Error *local_err = NULL; ++ int i; + + agc->parent_realize(dev, &local_err); + if (local_err) { +@@ -391,7 +392,9 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) + + gicv3_init_irqs_and_mmio(s, gicv3_set_irq, gic_ops); + +- gicv3_init_cpuif(s); ++ for (i = 0; i < s->num_cpu; i++) { ++ gicv3_init_one_cpuif(s, i); ++ } + } + + static void arm_gicv3_class_init(ObjectClass *klass, void *data) +diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c +index 85fc369e55..70809bcddd 100644 +--- a/hw/intc/arm_gicv3_cpuif.c ++++ b/hw/intc/arm_gicv3_cpuif.c +@@ -2625,76 +2625,72 @@ static void gicv3_cpuif_el_change_hook(ARMCPU *cpu, void *opaque) + gicv3_cpuif_update(cs); + } + +-void gicv3_init_cpuif(GICv3State *s) ++void gicv3_init_one_cpuif(GICv3State *s, int ncpu) + { + /* Called from the GICv3 realize function; register our system + * registers with the CPU + */ +- int i; +- +- for (i = 0; i < s->num_cpu; i++) { +- ARMCPU *cpu = ARM_CPU(qemu_get_cpu(i)); +- GICv3CPUState *cs = &s->cpu[i]; +- +- /* Note that we can't just use the GICv3CPUState as an opaque pointer +- * in define_arm_cp_regs_with_opaque(), because when we're called back +- * it might be with code translated by CPU 0 but run by CPU 1, in +- * which case we'd get the wrong value. +- * So instead we define the regs with no ri->opaque info, and +- * get back to the GICv3CPUState from the CPUARMState. ++ ARMCPU *cpu = ARM_CPU(qemu_get_cpu(ncpu)); ++ GICv3CPUState *cs = &s->cpu[ncpu]; ++ ++ /* Note that we can't just use the GICv3CPUState as an opaque pointer ++ * in define_arm_cp_regs_with_opaque(), because when we're called back ++ * it might be with code translated by CPU 0 but run by CPU 1, in ++ * which case we'd get the wrong value. ++ * So instead we define the regs with no ri->opaque info, and ++ * get back to the GICv3CPUState from the CPUARMState. ++ */ ++ define_arm_cp_regs(cpu, gicv3_cpuif_reginfo); ++ if (arm_feature(&cpu->env, ARM_FEATURE_EL2) ++ && cpu->gic_num_lrs) { ++ int j; ++ ++ cs->num_list_regs = cpu->gic_num_lrs; ++ cs->vpribits = cpu->gic_vpribits; ++ cs->vprebits = cpu->gic_vprebits; ++ ++ /* Check against architectural constraints: getting these ++ * wrong would be a bug in the CPU code defining these, ++ * and the implementation relies on them holding. + */ +- define_arm_cp_regs(cpu, gicv3_cpuif_reginfo); +- if (arm_feature(&cpu->env, ARM_FEATURE_EL2) +- && cpu->gic_num_lrs) { +- int j; +- +- cs->num_list_regs = cpu->gic_num_lrs; +- cs->vpribits = cpu->gic_vpribits; +- cs->vprebits = cpu->gic_vprebits; +- +- /* Check against architectural constraints: getting these +- * wrong would be a bug in the CPU code defining these, +- * and the implementation relies on them holding. +- */ +- g_assert(cs->vprebits <= cs->vpribits); +- g_assert(cs->vprebits >= 5 && cs->vprebits <= 7); +- g_assert(cs->vpribits >= 5 && cs->vpribits <= 8); ++ g_assert(cs->vprebits <= cs->vpribits); ++ g_assert(cs->vprebits >= 5 && cs->vprebits <= 7); ++ g_assert(cs->vpribits >= 5 && cs->vpribits <= 8); + +- define_arm_cp_regs(cpu, gicv3_cpuif_hcr_reginfo); ++ define_arm_cp_regs(cpu, gicv3_cpuif_hcr_reginfo); + +- for (j = 0; j < cs->num_list_regs; j++) { +- /* Note that the AArch64 LRs are 64-bit; the AArch32 LRs +- * are split into two cp15 regs, LR (the low part, with the +- * same encoding as the AArch64 LR) and LRC (the high part). +- */ +- ARMCPRegInfo lr_regset[] = { +- { .name = "ICH_LRn_EL2", .state = ARM_CP_STATE_BOTH, +- .opc0 = 3, .opc1 = 4, .crn = 12, +- .crm = 12 + (j >> 3), .opc2 = j & 7, +- .type = ARM_CP_IO | ARM_CP_NO_RAW, +- .access = PL2_RW, +- .readfn = ich_lr_read, +- .writefn = ich_lr_write, +- }, +- { .name = "ICH_LRCn_EL2", .state = ARM_CP_STATE_AA32, +- .cp = 15, .opc1 = 4, .crn = 12, +- .crm = 14 + (j >> 3), .opc2 = j & 7, +- .type = ARM_CP_IO | ARM_CP_NO_RAW, +- .access = PL2_RW, +- .readfn = ich_lr_read, +- .writefn = ich_lr_write, +- }, +- REGINFO_SENTINEL +- }; +- define_arm_cp_regs(cpu, lr_regset); +- } +- if (cs->vprebits >= 6) { +- define_arm_cp_regs(cpu, gicv3_cpuif_ich_apxr1_reginfo); +- } +- if (cs->vprebits == 7) { +- define_arm_cp_regs(cpu, gicv3_cpuif_ich_apxr23_reginfo); +- } ++ for (j = 0; j < cs->num_list_regs; j++) { ++ /* Note that the AArch64 LRs are 64-bit; the AArch32 LRs ++ * are split into two cp15 regs, LR (the low part, with the ++ * same encoding as the AArch64 LR) and LRC (the high part). ++ */ ++ ARMCPRegInfo lr_regset[] = { ++ { .name = "ICH_LRn_EL2", .state = ARM_CP_STATE_BOTH, ++ .opc0 = 3, .opc1 = 4, .crn = 12, ++ .crm = 12 + (j >> 3), .opc2 = j & 7, ++ .type = ARM_CP_IO | ARM_CP_NO_RAW, ++ .access = PL2_RW, ++ .readfn = ich_lr_read, ++ .writefn = ich_lr_write, ++ }, ++ { .name = "ICH_LRCn_EL2", .state = ARM_CP_STATE_AA32, ++ .cp = 15, .opc1 = 4, .crn = 12, ++ .crm = 14 + (j >> 3), .opc2 = j & 7, ++ .type = ARM_CP_IO | ARM_CP_NO_RAW, ++ .access = PL2_RW, ++ .readfn = ich_lr_read, ++ .writefn = ich_lr_write, ++ }, ++ REGINFO_SENTINEL ++ }; ++ define_arm_cp_regs(cpu, lr_regset); ++ } ++ if (cs->vprebits >= 6) { ++ define_arm_cp_regs(cpu, gicv3_cpuif_ich_apxr1_reginfo); ++ } ++ if (cs->vprebits == 7) { ++ define_arm_cp_regs(cpu, gicv3_cpuif_ich_apxr23_reginfo); + } +- arm_register_el_change_hook(cpu, gicv3_cpuif_el_change_hook, cs); + } ++ arm_register_el_change_hook(cpu, gicv3_cpuif_el_change_hook, cs); + } +diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h +index b9c37453b0..65db012600 100644 +--- a/hw/intc/gicv3_internal.h ++++ b/hw/intc/gicv3_internal.h +@@ -495,7 +495,7 @@ void gicv3_redist_update_lpi(GICv3CPUState *cs); + */ + void gicv3_redist_update_lpi_only(GICv3CPUState *cs); + void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns); +-void gicv3_init_cpuif(GICv3State *s); ++void gicv3_init_one_cpuif(GICv3State *s, int ncpu); + + /** + * gicv3_cpuif_update: +-- +2.27.0 + -- Gitee From 971729d5fbc430030a95da4b87858e866c8aeb35 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 10 Apr 2020 12:49:12 +0800 Subject: [PATCH 18/28] intc/kvm_gicv3: Factor out kvm_arm_gicv3_cpu_realize The CPU object of hotplugged CPU will be defer-created (during hotplug session), so we must factor out realization code to let it can be applied to individual CPU. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta (cherry picked from commit 7b0dc0a49e5ea43bd4b4d85d3630db2efcbb493b) --- ...Factor-out-kvm_arm_gicv3_cpu_realize.patch | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 intc-kvm_gicv3-Factor-out-kvm_arm_gicv3_cpu_realize.patch diff --git a/intc-kvm_gicv3-Factor-out-kvm_arm_gicv3_cpu_realize.patch b/intc-kvm_gicv3-Factor-out-kvm_arm_gicv3_cpu_realize.patch new file mode 100644 index 00000000..f9f4b940 --- /dev/null +++ b/intc-kvm_gicv3-Factor-out-kvm_arm_gicv3_cpu_realize.patch @@ -0,0 +1,46 @@ +From dd03bc60712bd41a9606742ea4b769aa8e360655 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 12:49:12 +0800 +Subject: [PATCH] intc/kvm_gicv3: Factor out kvm_arm_gicv3_cpu_realize + +The CPU object of hotplugged CPU will be defer-created (during +hotplug session), so we must factor out realization code to let +it can be applied to individual CPU. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/intc/arm_gicv3_kvm.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c +index 5ec5ff9ef6..596b31998b 100644 +--- a/hw/intc/arm_gicv3_kvm.c ++++ b/hw/intc/arm_gicv3_kvm.c +@@ -764,6 +764,12 @@ static void vm_change_state_handler(void *opaque, bool running, + } + } + ++static void kvm_arm_gicv3_cpu_realize(GICv3State *s, int ncpu) ++{ ++ ARMCPU *cpu = ARM_CPU(qemu_get_cpu(ncpu)); ++ ++ define_arm_cp_regs(cpu, gicv3_cpuif_reginfo); ++} + + static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp) + { +@@ -790,9 +796,7 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp) + gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL); + + for (i = 0; i < s->num_cpu; i++) { +- ARMCPU *cpu = ARM_CPU(qemu_get_cpu(i)); +- +- define_arm_cp_regs(cpu, gicv3_cpuif_reginfo); ++ kvm_arm_gicv3_cpu_realize(s, i); + } + + /* Try to create the device via the device control API */ +-- +2.27.0 + -- Gitee From be00fe0fe370119d5b507c3b6f6b393dd39f99b2 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Mon, 6 Apr 2020 11:26:35 +0800 Subject: [PATCH 19/28] hw/intc/gicv3: Add CPU hotplug realize hook GICv3 exposes individual CPU realization capability through this hook. It will be used for hotplugged CPU. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta (cherry picked from commit e376844ee4fefdb6ffabb751d4d08363bc1a4faf) --- ...c-gicv3-Add-CPU-hotplug-realize-hook.patch | 171 ++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 hw-intc-gicv3-Add-CPU-hotplug-realize-hook.patch diff --git a/hw-intc-gicv3-Add-CPU-hotplug-realize-hook.patch b/hw-intc-gicv3-Add-CPU-hotplug-realize-hook.patch new file mode 100644 index 00000000..926a6191 --- /dev/null +++ b/hw-intc-gicv3-Add-CPU-hotplug-realize-hook.patch @@ -0,0 +1,171 @@ +From e94b8dc43d416b3ebf316faf14309fe4c4d0b4f0 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Mon, 6 Apr 2020 11:26:35 +0800 +Subject: [PATCH] hw/intc/gicv3: Add CPU hotplug realize hook + +GICv3 exposes individual CPU realization capability through +this hook. It will be used for hotplugged CPU. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/intc/arm_gicv3.c | 17 ++++++++++++++++- + hw/intc/arm_gicv3_common.c | 8 ++++++++ + hw/intc/arm_gicv3_kvm.c | 11 +++++++++++ + include/hw/intc/arm_gicv3.h | 2 ++ + include/hw/intc/arm_gicv3_common.h | 4 ++++ + 5 files changed, 41 insertions(+), 1 deletion(-) + +diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c +index 40016cb84a..9591cfbcc0 100644 +--- a/hw/intc/arm_gicv3.c ++++ b/hw/intc/arm_gicv3.c +@@ -376,6 +376,19 @@ static const MemoryRegionOps gic_ops[] = { + } + }; + ++static void gicv3_cpu_realize(GICv3State *s, int i) ++{ ++ gicv3_init_one_cpuif(s, i); ++} ++ ++static void arm_gicv3_cpu_hotplug_realize(GICv3State *s, int ncpu) ++{ ++ ARMGICv3Class *agc = ARM_GICV3_GET_CLASS(s); ++ ++ agc->parent_cpu_hotplug_realize(s, ncpu); ++ gicv3_cpu_realize(s, ncpu); ++} ++ + static void arm_gic_realize(DeviceState *dev, Error **errp) + { + /* Device instance realize function for the GIC sysbus device */ +@@ -393,7 +406,7 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) + gicv3_init_irqs_and_mmio(s, gicv3_set_irq, gic_ops); + + for (i = 0; i < s->num_cpu; i++) { +- gicv3_init_one_cpuif(s, i); ++ gicv3_cpu_realize(s, i); + } + } + +@@ -403,6 +416,8 @@ static void arm_gicv3_class_init(ObjectClass *klass, void *data) + ARMGICv3CommonClass *agcc = ARM_GICV3_COMMON_CLASS(klass); + ARMGICv3Class *agc = ARM_GICV3_CLASS(klass); + ++ agc->parent_cpu_hotplug_realize = agcc->cpu_hotplug_realize; ++ agcc->cpu_hotplug_realize = arm_gicv3_cpu_hotplug_realize; + agcc->post_load = arm_gicv3_post_load; + device_class_set_parent_realize(dc, arm_gic_realize, &agc->parent_realize); + } +diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c +index 1a11d1986d..f8ef6817a4 100644 +--- a/hw/intc/arm_gicv3_common.c ++++ b/hw/intc/arm_gicv3_common.c +@@ -311,6 +311,11 @@ static void arm_gicv3_common_cpu_realize(GICv3State *s, int ncpu) + gicv3_set_gicv3state(cpu, &s->cpu[ncpu]); + } + ++static void arm_gicv3_common_cpu_hotplug_realize(GICv3State *s, int ncpu) ++{ ++ arm_gicv3_common_cpu_realize(s, ncpu); ++} ++ + static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) + { + GICv3State *s = ARM_GICV3_COMMON(dev); +@@ -371,6 +376,7 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) + + for (i = 0; i < s->num_cpu; i++) { + CPUState *cpu = qemu_get_cpu(i); ++ + uint64_t cpu_affid; + + arm_gicv3_common_cpu_realize(s, i); +@@ -537,12 +543,14 @@ static Property arm_gicv3_common_properties[] = { + static void arm_gicv3_common_class_init(ObjectClass *klass, void *data) + { + DeviceClass *dc = DEVICE_CLASS(klass); ++ ARMGICv3CommonClass *agcc = ARM_GICV3_COMMON_CLASS(klass); + ARMLinuxBootIfClass *albifc = ARM_LINUX_BOOT_IF_CLASS(klass); + + dc->reset = arm_gicv3_common_reset; + dc->realize = arm_gicv3_common_realize; + device_class_set_props(dc, arm_gicv3_common_properties); + dc->vmsd = &vmstate_gicv3; ++ agcc->cpu_hotplug_realize = arm_gicv3_common_cpu_hotplug_realize; + albifc->arm_linux_init = arm_gic_common_linux_init; + } + +diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c +index 596b31998b..95271e754b 100644 +--- a/hw/intc/arm_gicv3_kvm.c ++++ b/hw/intc/arm_gicv3_kvm.c +@@ -76,6 +76,7 @@ struct KVMARMGICv3Class { + ARMGICv3CommonClass parent_class; + DeviceRealize parent_realize; + void (*parent_reset)(DeviceState *dev); ++ CPUHotplugRealize parent_cpu_hotplug_realize; + }; + + static void kvm_arm_gicv3_set_irq(void *opaque, int irq, int level) +@@ -771,6 +772,14 @@ static void kvm_arm_gicv3_cpu_realize(GICv3State *s, int ncpu) + define_arm_cp_regs(cpu, gicv3_cpuif_reginfo); + } + ++static void kvm_arm_gicv3_cpu_hotplug_realize(GICv3State *s, int ncpu) ++{ ++ KVMARMGICv3Class *kagcc = KVM_ARM_GICV3_GET_CLASS(s); ++ ++ kagcc->parent_cpu_hotplug_realize(s, ncpu); ++ kvm_arm_gicv3_cpu_realize(s, ncpu); ++} ++ + static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp) + { + GICv3State *s = KVM_ARM_GICV3(dev); +@@ -881,6 +890,8 @@ static void kvm_arm_gicv3_class_init(ObjectClass *klass, void *data) + ARMGICv3CommonClass *agcc = ARM_GICV3_COMMON_CLASS(klass); + KVMARMGICv3Class *kgc = KVM_ARM_GICV3_CLASS(klass); + ++ kgc->parent_cpu_hotplug_realize = agcc->cpu_hotplug_realize; ++ agcc->cpu_hotplug_realize = kvm_arm_gicv3_cpu_hotplug_realize; + agcc->pre_save = kvm_arm_gicv3_get; + agcc->post_load = kvm_arm_gicv3_put; + device_class_set_parent_realize(dc, kvm_arm_gicv3_realize, +diff --git a/include/hw/intc/arm_gicv3.h b/include/hw/intc/arm_gicv3.h +index a81a6ae7ec..e360556bd5 100644 +--- a/include/hw/intc/arm_gicv3.h ++++ b/include/hw/intc/arm_gicv3.h +@@ -26,6 +26,8 @@ struct ARMGICv3Class { + ARMGICv3CommonClass parent_class; + /*< public >*/ + ++ CPUHotplugRealize parent_cpu_hotplug_realize; ++ + DeviceRealize parent_realize; + }; + +diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h +index fc38e4b7dc..c208a191ff 100644 +--- a/include/hw/intc/arm_gicv3_common.h ++++ b/include/hw/intc/arm_gicv3_common.h +@@ -306,11 +306,15 @@ typedef struct ARMGICv3CommonClass ARMGICv3CommonClass; + DECLARE_OBJ_CHECKERS(GICv3State, ARMGICv3CommonClass, + ARM_GICV3_COMMON, TYPE_ARM_GICV3_COMMON) + ++typedef void (*CPUHotplugRealize)(GICv3State *s, int ncpu); ++ + struct ARMGICv3CommonClass { + /*< private >*/ + SysBusDeviceClass parent_class; + /*< public >*/ + ++ CPUHotplugRealize cpu_hotplug_realize; ++ + void (*pre_save)(GICv3State *s); + void (*post_load)(GICv3State *s); + }; +-- +2.27.0 + -- Gitee From cb290972f18cbdc2e31877092c9555aa9bf36acd Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 10 Apr 2020 13:04:40 +0800 Subject: [PATCH 20/28] accel/kvm: Add pre-park vCPU support For that KVM do not support dynamic adjustment of vCPU count, we must pre-park all possible vCPU at start. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta (cherry picked from commit 000c4a3d545146ee38ea4334fee3a93669c11b28) --- accel-kvm-Add-pre-park-vCPU-support.patch | 64 +++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 accel-kvm-Add-pre-park-vCPU-support.patch diff --git a/accel-kvm-Add-pre-park-vCPU-support.patch b/accel-kvm-Add-pre-park-vCPU-support.patch new file mode 100644 index 00000000..e3433842 --- /dev/null +++ b/accel-kvm-Add-pre-park-vCPU-support.patch @@ -0,0 +1,64 @@ +From c950cda47386360e37a89dfa7029d83e33888a40 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 13:04:40 +0800 +Subject: [PATCH] accel/kvm: Add pre-park vCPU support + +For that KVM do not support dynamic adjustment of vCPU count, +we must pre-park all possible vCPU at start. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + accel/kvm/kvm-all.c | 23 +++++++++++++++++++++++ + include/sysemu/kvm.h | 1 + + 2 files changed, 24 insertions(+) + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index 8a98446b7c..f2ce5cd45a 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -433,6 +433,29 @@ void kvm_destroy_vcpu(CPUState *cpu) + } + } + ++int kvm_create_parked_vcpu(unsigned long vcpu_id) ++{ ++ KVMState *s = kvm_state; ++ struct KVMParkedVcpu *vcpu = NULL; ++ int ret; ++ ++ DPRINTF("kvm_create_parked_vcpu\n"); ++ ++ ret = kvm_vm_ioctl(s, KVM_CREATE_VCPU, (void *)vcpu_id); ++ if (ret < 0) { ++ DPRINTF("kvm_create_vcpu failed\n"); ++ goto err; ++ } ++ ++ vcpu = g_malloc0(sizeof(*vcpu)); ++ vcpu->vcpu_id = vcpu_id; ++ vcpu->kvm_fd = ret; ++ QLIST_INSERT_HEAD(&s->kvm_parked_vcpus, vcpu, node); ++ ++err: ++ return ret; ++} ++ + static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id) + { + struct KVMParkedVcpu *cpu; +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index 7b22aeb6ae..2623775c27 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -221,6 +221,7 @@ int kvm_has_pit_state2(void); + int kvm_has_many_ioeventfds(void); + int kvm_has_gsi_routing(void); + int kvm_has_intx_set_mask(void); ++int kvm_create_parked_vcpu(unsigned long vcpu_id); + + /** + * kvm_arm_supports_user_irq +-- +2.27.0 + -- Gitee From 4d7cf3008702d8f5286109251dd31545b69a4b36 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 10 Apr 2020 13:15:35 +0800 Subject: [PATCH 21/28] intc/gicv3: Add pre-sizing capability to GICv3 Currently GICv3 supports fixed smp_cpus CPUs, and all CPUs are present always. Now we want to pre-sizing GICv3 to support max_cpus CPUs and not all of them are present always, so some sizing codes should be concerned. GIC irqs, GICR and GICC are pre-created for all possible CPUs at start, but only smp_cpus CPUs are realize and irqs of smp_cpus CPUs are connected. Other code changes are mainly for arm_gicv3, and we do little about kvm_arm_gicv3 becasue KVM will deal with the sizing information properly. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta (cherry picked from commit cd6ddaa7a22579bd3caaaf323201cad55e1d1407) --- ...3-Add-pre-sizing-capability-to-GICv3.patch | 358 ++++++++++++++++++ 1 file changed, 358 insertions(+) create mode 100644 intc-gicv3-Add-pre-sizing-capability-to-GICv3.patch diff --git a/intc-gicv3-Add-pre-sizing-capability-to-GICv3.patch b/intc-gicv3-Add-pre-sizing-capability-to-GICv3.patch new file mode 100644 index 00000000..a68cdcbe --- /dev/null +++ b/intc-gicv3-Add-pre-sizing-capability-to-GICv3.patch @@ -0,0 +1,358 @@ +From 3ed7dcc4a8ccf443d125e7908d8293b562c68d4b Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 13:15:35 +0800 +Subject: [PATCH] intc/gicv3: Add pre-sizing capability to GICv3 + +Currently GICv3 supports fixed smp_cpus CPUs, and all CPUs are +present always. Now we want to pre-sizing GICv3 to support max_cpus +CPUs and not all of them are present always, so some sizing codes +should be concerned. + +GIC irqs, GICR and GICC are pre-created for all possible CPUs at +start, but only smp_cpus CPUs are realize and irqs of smp_cpus CPUs +are connected. + +Other code changes are mainly for arm_gicv3, and we do little about +kvm_arm_gicv3 becasue KVM will deal with the sizing information properly. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt.c | 17 +++++++++++---- + hw/intc/arm_gicv3.c | 43 +++++++++++++++++++++++++------------- + hw/intc/arm_gicv3_common.c | 22 +++++++++++++++++-- + hw/intc/arm_gicv3_cpuif.c | 4 ++++ + hw/intc/arm_gicv3_kvm.c | 28 ++++++++++++++++++++++++- + include/hw/arm/virt.h | 3 ++- + 6 files changed, 95 insertions(+), 22 deletions(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 0af0a996a1..b1224fb1e4 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -827,14 +827,19 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem) + SysBusDevice *gicbusdev; + const char *gictype; + int type = vms->gic_version, i; ++ /* The max number of CPUs suppored by GIC */ ++ unsigned int num_cpus = ms->smp.cpus; ++ /* The number of CPUs present before boot */ + unsigned int smp_cpus = ms->smp.cpus; + uint32_t nb_redist_regions = 0; + ++ assert(num_cpus >= smp_cpus); ++ + gictype = (type == 3) ? gicv3_class_name() : gic_class_name(); + + vms->gic = qdev_new(gictype); + qdev_prop_set_uint32(vms->gic, "revision", type); +- qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus); ++ qdev_prop_set_uint32(vms->gic, "num-cpu", num_cpus); + /* Note that the num-irq property counts both internal and external + * interrupts; there are always 32 of the former (mandated by GIC spec). + */ +@@ -846,7 +851,7 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem) + if (type == 3) { + uint32_t redist0_capacity = + vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE; +- uint32_t redist0_count = MIN(smp_cpus, redist0_capacity); ++ uint32_t redist0_count = MIN(num_cpus, redist0_capacity); + + nb_redist_regions = virt_gicv3_redist_region_count(vms); + +@@ -867,7 +872,7 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem) + vms->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE; + + qdev_prop_set_uint32(vms->gic, "redist-region-count[1]", +- MIN(smp_cpus - redist0_count, redist1_capacity)); ++ MIN(num_cpus - redist0_count, redist1_capacity)); + } + } else { + if (!kvm_irqchip_in_kernel()) { +@@ -894,7 +899,11 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem) + + /* Wire the outputs from each CPU's generic timer and the GICv3 + * maintenance interrupt signal to the appropriate GIC PPI inputs, +- * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs. ++ * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's ++ * inputs. ++ * ++ * The irqs of remaining CPUs (if we has) will be connected during ++ * hotplugging. + */ + for (i = 0; i < smp_cpus; i++) { + connect_gic_cpu_irqs(vms, i); +diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c +index 9591cfbcc0..864d4e4034 100644 +--- a/hw/intc/arm_gicv3.c ++++ b/hw/intc/arm_gicv3.c +@@ -19,6 +19,7 @@ + #include "qapi/error.h" + #include "qemu/module.h" + #include "hw/intc/arm_gicv3.h" ++#include "hw/core/cpu.h" + #include "gicv3_internal.h" + + static bool irqbetter(GICv3CPUState *cs, int irq, uint8_t prio) +@@ -217,7 +218,9 @@ static void gicv3_update_noirqset(GICv3State *s, int start, int len) + assert(len > 0); + + for (i = 0; i < s->num_cpu; i++) { +- s->cpu[i].seenbetter = false; ++ if (qemu_get_cpu(i)) { ++ s->cpu[i].seenbetter = false; ++ } + } + + /* Find the highest priority pending interrupt in this range. */ +@@ -259,16 +262,18 @@ static void gicv3_update_noirqset(GICv3State *s, int start, int len) + * now be the new best one). + */ + for (i = 0; i < s->num_cpu; i++) { +- GICv3CPUState *cs = &s->cpu[i]; ++ if (qemu_get_cpu(i)) { ++ GICv3CPUState *cs = &s->cpu[i]; + +- if (cs->seenbetter) { +- cs->hppi.grp = gicv3_irq_group(cs->gic, cs, cs->hppi.irq); +- } ++ if (cs->seenbetter) { ++ cs->hppi.grp = gicv3_irq_group(cs->gic, cs, cs->hppi.irq); ++ } + +- if (!cs->seenbetter && cs->hppi.prio != 0xff && +- cs->hppi.irq >= start && cs->hppi.irq < start + len) { +- gicv3_full_update_noirqset(s); +- break; ++ if (!cs->seenbetter && cs->hppi.prio != 0xff && ++ cs->hppi.irq >= start && cs->hppi.irq < start + len) { ++ gicv3_full_update_noirqset(s); ++ break; ++ } + } + } + } +@@ -279,7 +284,9 @@ void gicv3_update(GICv3State *s, int start, int len) + + gicv3_update_noirqset(s, start, len); + for (i = 0; i < s->num_cpu; i++) { +- gicv3_cpuif_update(&s->cpu[i]); ++ if (qemu_get_cpu(i)) { ++ gicv3_cpuif_update(&s->cpu[i]); ++ } + } + } + +@@ -291,7 +298,9 @@ void gicv3_full_update_noirqset(GICv3State *s) + int i; + + for (i = 0; i < s->num_cpu; i++) { +- s->cpu[i].hppi.prio = 0xff; ++ if (qemu_get_cpu(i)) { ++ s->cpu[i].hppi.prio = 0xff; ++ } + } + + /* Note that we can guarantee that these functions will not +@@ -302,7 +311,9 @@ void gicv3_full_update_noirqset(GICv3State *s) + gicv3_update_noirqset(s, GIC_INTERNAL, s->num_irq - GIC_INTERNAL); + + for (i = 0; i < s->num_cpu; i++) { +- gicv3_redist_update_noirqset(&s->cpu[i]); ++ if (qemu_get_cpu(i)) { ++ gicv3_redist_update_noirqset(&s->cpu[i]); ++ } + } + } + +@@ -315,7 +326,9 @@ void gicv3_full_update(GICv3State *s) + + gicv3_full_update_noirqset(s); + for (i = 0; i < s->num_cpu; i++) { +- gicv3_cpuif_update(&s->cpu[i]); ++ if (qemu_get_cpu(i)) { ++ gicv3_cpuif_update(&s->cpu[i]); ++ } + } + } + +@@ -406,7 +419,9 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) + gicv3_init_irqs_and_mmio(s, gicv3_set_irq, gic_ops); + + for (i = 0; i < s->num_cpu; i++) { +- gicv3_cpu_realize(s, i); ++ if (qemu_get_cpu(i)) { ++ gicv3_cpu_realize(s, i); ++ } + } + } + +diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c +index f8ef6817a4..a4976b2ba0 100644 +--- a/hw/intc/arm_gicv3_common.c ++++ b/hw/intc/arm_gicv3_common.c +@@ -24,12 +24,14 @@ + #include "qemu/osdep.h" + #include "qapi/error.h" + #include "qemu/module.h" ++#include "qemu/error-report.h" + #include "hw/core/cpu.h" + #include "hw/intc/arm_gicv3_common.h" + #include "hw/qdev-properties.h" + #include "migration/vmstate.h" + #include "gicv3_internal.h" + #include "hw/arm/linux-boot-if.h" ++#include "hw/boards.h" + #include "sysemu/kvm.h" + + +@@ -377,9 +379,14 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) + for (i = 0; i < s->num_cpu; i++) { + CPUState *cpu = qemu_get_cpu(i); + ++ MachineState *ms = MACHINE(qdev_get_machine()); ++ MachineClass *mc = MACHINE_GET_CLASS(ms); ++ const CPUArchIdList *possible_cpus = NULL; + uint64_t cpu_affid; + +- arm_gicv3_common_cpu_realize(s, i); ++ if (cpu) { ++ arm_gicv3_common_cpu_realize(s, i); ++ } + + /* Pre-construct the GICR_TYPER: + * For our implementation: +@@ -393,7 +400,18 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) + * VLPIS == 0 (virtual LPIs not supported) + * PLPIS == 0 (physical LPIs not supported) + */ +- cpu_affid = object_property_get_uint(OBJECT(cpu), "mp-affinity", NULL); ++ if (cpu) { ++ cpu_affid = object_property_get_uint(OBJECT(cpu), "mp-affinity", NULL); ++ } else { ++ if (!mc->possible_cpu_arch_ids) { ++ error_report("MachineClass must implement possible_cpu_arch_ids " ++ "hook to support pre-sizing GICv3"); ++ exit(1); ++ } ++ ++ possible_cpus = mc->possible_cpu_arch_ids(ms); ++ cpu_affid = possible_cpus->cpus[i].arch_id; ++ } + + /* The CPU mp-affinity property is in MPIDR register format; squash + * the affinity bytes into 32 bits as the GICR_TYPER has them. +diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c +index 70809bcddd..274a40a40c 100644 +--- a/hw/intc/arm_gicv3_cpuif.c ++++ b/hw/intc/arm_gicv3_cpuif.c +@@ -1676,6 +1676,10 @@ static void icc_generate_sgi(CPUARMState *env, GICv3CPUState *cs, + aff, targetlist); + + for (i = 0; i < s->num_cpu; i++) { ++ if (!qemu_get_cpu(i)) { ++ continue; ++ } ++ + GICv3CPUState *ocs = &s->cpu[i]; + + if (irm) { +diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c +index 95271e754b..2e2b08e31f 100644 +--- a/hw/intc/arm_gicv3_kvm.c ++++ b/hw/intc/arm_gicv3_kvm.c +@@ -342,6 +342,10 @@ static void kvm_arm_gicv3_put(GICv3State *s) + for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { + GICv3CPUState *c = &s->cpu[ncpu]; + ++ if (!qemu_get_cpu(ncpu)) { ++ continue; ++ } ++ + reg64 = c->gicr_propbaser; + regl = (uint32_t)reg64; + kvm_gicr_access(s, GICR_PROPBASER, ncpu, ®l, true); +@@ -361,6 +365,10 @@ static void kvm_arm_gicv3_put(GICv3State *s) + for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { + GICv3CPUState *c = &s->cpu[ncpu]; + ++ if (!qemu_get_cpu(ncpu)) { ++ continue; ++ } ++ + reg = c->gicr_ctlr; + kvm_gicr_access(s, GICR_CTLR, ncpu, ®, true); + +@@ -457,6 +465,10 @@ static void kvm_arm_gicv3_put(GICv3State *s) + GICv3CPUState *c = &s->cpu[ncpu]; + int num_pri_bits; + ++ if (!qemu_get_cpu(ncpu)) { ++ continue; ++ } ++ + kvm_gicc_access(s, ICC_SRE_EL1, ncpu, &c->icc_sre_el1, true); + kvm_gicc_access(s, ICC_CTLR_EL1, ncpu, + &c->icc_ctlr_el1[GICV3_NS], true); +@@ -524,6 +536,10 @@ static void kvm_arm_gicv3_get(GICv3State *s) + /* Redistributor state (one per CPU) */ + + for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { ++ if (!qemu_get_cpu(ncpu)) { ++ continue; ++ } ++ + GICv3CPUState *c = &s->cpu[ncpu]; + + kvm_gicr_access(s, GICR_CTLR, ncpu, ®, false); +@@ -559,6 +575,10 @@ static void kvm_arm_gicv3_get(GICv3State *s) + + if (redist_typer & GICR_TYPER_PLPIS) { + for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { ++ if (!qemu_get_cpu(ncpu)) { ++ continue; ++ } ++ + GICv3CPUState *c = &s->cpu[ncpu]; + + kvm_gicr_access(s, GICR_PROPBASER, ncpu, ®l, false); +@@ -612,6 +632,10 @@ static void kvm_arm_gicv3_get(GICv3State *s) + */ + + for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { ++ if (!qemu_get_cpu(ncpu)) { ++ continue; ++ } ++ + GICv3CPUState *c = &s->cpu[ncpu]; + int num_pri_bits; + +@@ -805,7 +829,9 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp) + gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL); + + for (i = 0; i < s->num_cpu; i++) { +- kvm_arm_gicv3_cpu_realize(s, i); ++ if (qemu_get_cpu(i)) { ++ kvm_arm_gicv3_cpu_realize(s, i); ++ } + } + + /* Try to create the device via the device control API */ +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index 2a838620d8..947d41f767 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -196,8 +196,9 @@ static inline int virt_gicv3_redist_region_count(VirtMachineState *vms) + vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE; + + assert(vms->gic_version == VIRT_GIC_VERSION_3); ++ GICv3State *s = ARM_GICV3_COMMON(vms->gic); + +- return MACHINE(vms)->smp.cpus > redist0_capacity ? 2 : 1; ++ return s->num_cpu > redist0_capacity ? 2 : 1; + } + + #endif /* QEMU_ARM_VIRT_H */ +-- +2.27.0 + -- Gitee From 4486897ff7f3e6288360e6e2a02d75d9371f5652 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 10 Apr 2020 13:40:44 +0800 Subject: [PATCH 22/28] acpi/madt: Add pre-sizing capability to MADT GICC struct The count of possible CPUs is exposed to guest through the count of MADT GICC struct, so we should pre-sizing MADT GICC too. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta (cherry picked from commit 101bb4ff32325cdc374719f006b6c5b24ff63d0d) --- ...e-sizing-capability-to-MADT-GICC-str.patch | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 acpi-madt-Add-pre-sizing-capability-to-MADT-GICC-str.patch diff --git a/acpi-madt-Add-pre-sizing-capability-to-MADT-GICC-str.patch b/acpi-madt-Add-pre-sizing-capability-to-MADT-GICC-str.patch new file mode 100644 index 00000000..47d18ea6 --- /dev/null +++ b/acpi-madt-Add-pre-sizing-capability-to-MADT-GICC-str.patch @@ -0,0 +1,84 @@ +From 8bd05cdb811e868c54ef28ac558c7efb7cf610b9 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 13:40:44 +0800 +Subject: [PATCH] acpi/madt: Add pre-sizing capability to MADT GICC struct + +The count of possible CPUs is exposed to guest through the count +of MADT GICC struct, so we should pre-sizing MADT GICC too. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt-acpi-build.c | 25 +++++++++++++++++++------ + 1 file changed, 19 insertions(+), 6 deletions(-) + +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index 7cb320d9f2..a16b54086e 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -787,8 +787,16 @@ void virt_madt_cpu_entry(AcpiDeviceIf *adev, int i, + ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i)); + uint64_t physical_base_address = 0, gich = 0, gicv = 0; + uint32_t vgic_interrupt = vms->virt ? PPI(ARCH_GIC_MAINT_IRQ) : 0; +- uint32_t pmu_interrupt = arm_feature(&armcpu->env, ARM_FEATURE_PMU) ? +- PPI(VIRTUAL_PMU_IRQ) : 0; ++ uint32_t pmu_interrupt, enabled; ++ static bool pmu; ++ ++ if (i == 0) { ++ pmu = arm_feature(&armcpu->env, ARM_FEATURE_PMU); ++ } ++ /* FEATURE_PMU should be all enabled or disabled for CPUs */ ++ assert(!armcpu || arm_feature(&armcpu->env, ARM_FEATURE_PMU) == pmu); ++ pmu_interrupt = pmu ? PPI(VIRTUAL_PMU_IRQ) : 0; ++ enabled = armcpu || force_enabled ? 1 /* Enabled */ : 0 /* Disabled */; + + if (vms->gic_version == 2) { + physical_base_address = memmap[VIRT_GIC_CPU].base; +@@ -803,7 +811,7 @@ void virt_madt_cpu_entry(AcpiDeviceIf *adev, int i, + build_append_int_noprefix(table_data, i, 4); /* GIC ID */ + build_append_int_noprefix(table_data, i, 4); /* ACPI Processor UID */ + /* Flags */ +- build_append_int_noprefix(table_data, 1, 4); /* Enabled */ ++ build_append_int_noprefix(table_data, enabled, 4); /* Enabled */ + /* Parking Protocol Version */ + build_append_int_noprefix(table_data, 0, 4); + /* Performance Interrupt GSIV */ +@@ -817,7 +825,7 @@ void virt_madt_cpu_entry(AcpiDeviceIf *adev, int i, + build_append_int_noprefix(table_data, vgic_interrupt, 4); + build_append_int_noprefix(table_data, 0, 8); /* GICR Base Address*/ + /* MPIDR */ +- build_append_int_noprefix(table_data, armcpu->mp_affinity, 8); ++ build_append_int_noprefix(table_data, possible_cpus->cpus[i].arch_id, 8); + } + + static void +@@ -825,9 +833,14 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + { + int i; + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); ++ MachineClass *mc = MACHINE_GET_CLASS(vms); ++ MachineState *ms = MACHINE(vms); ++ const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); + const MemMapEntry *memmap = vms->memmap; + AcpiTable table = { .sig = "APIC", .rev = 3, .oem_id = vms->oem_id, + .oem_table_id = vms->oem_table_id }; ++ /* The MADT GICC numbers */ ++ int num_cpu = ms->smp.cpus; + + acpi_table_begin(&table, table_data); + /* Local Interrupt Controller Address */ +@@ -846,8 +859,8 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + build_append_int_noprefix(table_data, vms->gic_version, 1); + build_append_int_noprefix(table_data, 0, 3); /* Reserved */ + +- for (i = 0; i < MACHINE(vms)->smp.cpus; i++) { +- virt_madt_cpu_entry(NULL, i, NULL, table_data, false); ++ for (i = 0; i < num_cpu; i++) { ++ virt_madt_cpu_entry(NULL, i, possible_cpus, table_data, false); + } + + if (vms->gic_version == 3) { +-- +2.27.0 + -- Gitee From 73903a3ef83ad3b44a895ecf7ae8032166e37518 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 10 Apr 2020 13:50:40 +0800 Subject: [PATCH 23/28] arm/virt: Add cpu_hotplug_enabled field Some conditions must be satisfied to support CPU hotplug, including ACPI, GED, 64bit CPU, GICv3. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta (cherry picked from commit 7550d4ab290a6c114a528b867aacdf80207e211d) --- arm-virt-Add-cpu_hotplug_enabled-field.patch | 62 ++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 arm-virt-Add-cpu_hotplug_enabled-field.patch diff --git a/arm-virt-Add-cpu_hotplug_enabled-field.patch b/arm-virt-Add-cpu_hotplug_enabled-field.patch new file mode 100644 index 00000000..0ae840c7 --- /dev/null +++ b/arm-virt-Add-cpu_hotplug_enabled-field.patch @@ -0,0 +1,62 @@ +From 965eb25b03f6977a7656dce3ac5cdb4c95bfe003 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 13:50:40 +0800 +Subject: [PATCH] arm/virt: Add cpu_hotplug_enabled field + +Some conditions must be satisfied to support CPU hotplug, including +ACPI, GED, 64bit CPU, GICv3. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt.c | 7 +++++++ + include/hw/arm/virt.h | 1 + + 2 files changed, 8 insertions(+) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index b1224fb1e4..45a0a045b1 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -2008,6 +2008,7 @@ static void machvirt_init(MachineState *machine) + { + VirtMachineState *vms = VIRT_MACHINE(machine); + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(machine); ++ MachineState *ms = MACHINE(machine); + MachineClass *mc = MACHINE_GET_CLASS(machine); + const CPUArchIdList *possible_cpus; + MemoryRegion *sysmem = get_system_memory(); +@@ -2017,6 +2018,7 @@ static void machvirt_init(MachineState *machine) + bool has_ged = !vmc->no_ged; + unsigned int smp_cpus = machine->smp.cpus; + unsigned int max_cpus = machine->smp.max_cpus; ++ ObjectClass *cpu_class; + + /* + * In accelerated mode, the memory map is computed earlier in kvm_type() +@@ -2106,6 +2108,11 @@ static void machvirt_init(MachineState *machine) + create_fdt(vms); + qemu_log("cpu init start\n"); + ++ cpu_class = object_class_by_name(ms->cpu_type); ++ vms->cpu_hotplug_enabled = has_ged && firmware_loaded && ++ virt_is_acpi_enabled(vms) && vms->gic_version == 3 && ++ !!object_class_dynamic_cast(cpu_class, TYPE_AARCH64_CPU); ++ + possible_cpus = mc->possible_cpu_arch_ids(machine); + assert(possible_cpus->len == max_cpus); + for (n = 0; n < possible_cpus->len; n++) { +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index 947d41f767..c371d377e0 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -149,6 +149,7 @@ struct VirtMachineState { + bool its; + bool tcg_its; + bool virt; ++ bool cpu_hotplug_enabled; + bool ras; + bool mte; + OnOffAuto acpi; +-- +2.27.0 + -- Gitee From 4bb917100903d71f3bf645b194ea61476c1c69de Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 22 Apr 2020 19:52:58 +0800 Subject: [PATCH 24/28] arm/virt/acpi: Extend cpufreq to support max_cpus We will support CPU hotplug soon, so extend memory region size to allow hotplugged CPU access cpufreq space. Signed-off-by: Keqian Zhu (cherry picked from commit 53c60486a60b76be9e2afe04e53759cf5475dd57) --- ...i-Extend-cpufreq-to-support-max_cpus.patch | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 arm-virt-acpi-Extend-cpufreq-to-support-max_cpus.patch diff --git a/arm-virt-acpi-Extend-cpufreq-to-support-max_cpus.patch b/arm-virt-acpi-Extend-cpufreq-to-support-max_cpus.patch new file mode 100644 index 00000000..501573c5 --- /dev/null +++ b/arm-virt-acpi-Extend-cpufreq-to-support-max_cpus.patch @@ -0,0 +1,66 @@ +From e3522e63a2f14c3c7d8cd603099b6bb51087f43b Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Wed, 22 Apr 2020 19:52:58 +0800 +Subject: [PATCH] arm/virt/acpi: Extend cpufreq to support max_cpus + +We will support CPU hotplug soon, so extend memory region size to +allow hotplugged CPU access cpufreq space. + +Signed-off-by: Keqian Zhu +--- + hw/acpi/cpufreq.c | 15 ++++++--------- + 1 file changed, 6 insertions(+), 9 deletions(-) + +diff --git a/hw/acpi/cpufreq.c b/hw/acpi/cpufreq.c +index a84db490b3..a76f7b8fa2 100644 +--- a/hw/acpi/cpufreq.c ++++ b/hw/acpi/cpufreq.c +@@ -83,6 +83,7 @@ typedef struct CpuhzState { + uint32_t PerformanceLimited; + uint32_t LowestFreq; + uint32_t NominalFreq; ++ uint32_t num_cpu; + uint32_t reg_size; + } CpuhzState; + +@@ -93,10 +94,7 @@ static uint64_t cpufreq_read(void *opaque, hwaddr offset, unsigned size) + uint64_t r; + uint64_t n; + +- MachineState *ms = MACHINE(qdev_get_machine()); +- unsigned int smp_cpus = ms->smp.cpus; +- +- if (offset >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) { ++ if (offset >= s->num_cpu * CPPC_REG_PER_CPU_STRIDE) { + warn_report("cpufreq_read: offset 0x%lx out of range", offset); + return 0; + } +@@ -163,11 +161,10 @@ static uint64_t cpufreq_read(void *opaque, hwaddr offset, unsigned size) + static void cpufreq_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) + { ++ CpuhzState *s = CPUFREQ(opaque); + uint64_t n; +- MachineState *ms = MACHINE(qdev_get_machine()); +- unsigned int smp_cpus = ms->smp.cpus; + +- if (offset >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) { ++ if (offset >= s->num_cpu * CPPC_REG_PER_CPU_STRIDE) { + error_printf("cpufreq_write: offset 0x%lx out of range", offset); + return; + } +@@ -248,9 +245,9 @@ static void cpufreq_init(Object *obj) + CpuhzState *s = CPUFREQ(obj); + + MachineState *ms = MACHINE(qdev_get_machine()); +- unsigned int smp_cpus = ms->smp.cpus; ++ s->num_cpu = ms->smp.max_cpus; + +- s->reg_size = smp_cpus * CPPC_REG_PER_CPU_STRIDE; ++ s->reg_size = s->num_cpu * CPPC_REG_PER_CPU_STRIDE; + if (s->reg_size > MAX_SUPPORT_SPACE) { + error_report("Required space 0x%x excesses the max support 0x%x", + s->reg_size, MAX_SUPPORT_SPACE); +-- +2.27.0 + -- Gitee From 26277fa76762efe66f47c4083a9dd7609777e192 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 10 Apr 2020 13:55:11 +0800 Subject: [PATCH 25/28] arm/virt: Pre-sizing MADT-GICC GICv3 and Pre-park KVM vCPU Establish all pre-sizing facilities based on cpu_hotplug_enabled field. Note: PPTT is constructed for possible_cpus, so it does not need to pre-sizing it. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta (cherry picked from commit c01cf3e56182eea0b0a469a91ccbfcaf37c4c5e6) --- ...ing-MADT-GICC-GICv3-and-Pre-park-KVM.patch | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 arm-virt-Pre-sizing-MADT-GICC-GICv3-and-Pre-park-KVM.patch diff --git a/arm-virt-Pre-sizing-MADT-GICC-GICv3-and-Pre-park-KVM.patch b/arm-virt-Pre-sizing-MADT-GICC-GICv3-and-Pre-park-KVM.patch new file mode 100644 index 00000000..134cdbe2 --- /dev/null +++ b/arm-virt-Pre-sizing-MADT-GICC-GICv3-and-Pre-park-KVM.patch @@ -0,0 +1,92 @@ +From 3063d421cd68937ece290bc02151cc15b7ec33d0 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 13:55:11 +0800 +Subject: [PATCH] arm/virt: Pre-sizing MADT-GICC GICv3 and Pre-park KVM vCPU + +Establish all pre-sizing facilities based on cpu_hotplug_enabled +field. + +Note: PPTT is constructed for possible_cpus, so it does not need +to pre-sizing it. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt-acpi-build.c | 3 +++ + hw/arm/virt.c | 14 ++++++++++++-- + target/arm/kvm.c | 4 ++-- + 3 files changed, 17 insertions(+), 4 deletions(-) + +diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c +index a16b54086e..1101161d70 100644 +--- a/hw/arm/virt-acpi-build.c ++++ b/hw/arm/virt-acpi-build.c +@@ -859,6 +859,9 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + build_append_int_noprefix(table_data, vms->gic_version, 1); + build_append_int_noprefix(table_data, 0, 3); /* Reserved */ + ++ if (vms->cpu_hotplug_enabled) { ++ num_cpu = ms->smp.max_cpus; ++ } + for (i = 0; i < num_cpu; i++) { + virt_madt_cpu_entry(NULL, i, possible_cpus, table_data, false); + } +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 45a0a045b1..4eb1b44729 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -833,6 +833,9 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem) + unsigned int smp_cpus = ms->smp.cpus; + uint32_t nb_redist_regions = 0; + ++ if (vms->cpu_hotplug_enabled) { ++ num_cpus = ms->smp.max_cpus; ++ } + assert(num_cpus >= smp_cpus); + + gictype = (type == 3) ? gicv3_class_name() : gic_class_name(); +@@ -2119,8 +2122,15 @@ static void machvirt_init(MachineState *machine) + Object *cpuobj; + CPUState *cs; + ++ if (kvm_enabled() && vms->cpu_hotplug_enabled) { ++ if (kvm_create_parked_vcpu(n) < 0) { ++ error_report("mach-virt: Create KVM parked vCPU failed"); ++ exit(1); ++ } ++ } ++ + if (n >= smp_cpus) { +- break; ++ continue; + } + + cpuobj = object_new(possible_cpus->cpus[n].type); +@@ -2208,7 +2218,7 @@ static void machvirt_init(MachineState *machine) + } + + vms->bootinfo.ram_size = machine->ram_size; +- vms->bootinfo.nb_cpus = smp_cpus; ++ vms->bootinfo.nb_cpus = vms->cpu_hotplug_enabled ? max_cpus : smp_cpus; + vms->bootinfo.board_id = -1; + vms->bootinfo.loader_start = vms->memmap[VIRT_MEM].base; + vms->bootinfo.get_dtb = machvirt_dtb; +diff --git a/target/arm/kvm.c b/target/arm/kvm.c +index 59d556724f..29ac3f40e0 100644 +--- a/target/arm/kvm.c ++++ b/target/arm/kvm.c +@@ -262,9 +262,9 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + + cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE); + +- if (ms->smp.cpus > 256 && ++ if (ms->smp.max_cpus > 256 && + !kvm_check_extension(s, KVM_CAP_ARM_IRQ_LINE_LAYOUT_2)) { +- error_report("Using more than 256 vcpus requires a host kernel " ++ error_report("Using more than max 256 vcpus requires a host kernel " + "with KVM_CAP_ARM_IRQ_LINE_LAYOUT_2"); + ret = -EINVAL; + } +-- +2.27.0 + -- Gitee From 860179a5439483b213e7aab2b78f7e5cfa0f0dad Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Fri, 10 Apr 2020 14:16:40 +0800 Subject: [PATCH 26/28] arm/virt: Start up CPU hot-plug and cold-plug All the CPU hotplug facilities are ready. Assemble them to start up CPU hot-plug capability for arm/virt. This also adds CPU cold plug support to arm virt machine board. CPU cold plug means adding CPU by using "-device xx-arm-cpu" when we bring up Qemu. Signed-off-by: Salil Mehta Signed-off-by: Keqian Zhu (cherry picked from commit d5d118431a64c4202cb28c27bdea0f8667beb5dd) --- ...-Start-up-CPU-hot-plug-and-cold-plug.patch | 237 ++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 arm-virt-Start-up-CPU-hot-plug-and-cold-plug.patch diff --git a/arm-virt-Start-up-CPU-hot-plug-and-cold-plug.patch b/arm-virt-Start-up-CPU-hot-plug-and-cold-plug.patch new file mode 100644 index 00000000..d4970f16 --- /dev/null +++ b/arm-virt-Start-up-CPU-hot-plug-and-cold-plug.patch @@ -0,0 +1,237 @@ +From a2d8cf86a379bb161cdae850824c9e80fb370599 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 14:16:40 +0800 +Subject: [PATCH] arm/virt: Start up CPU hot-plug and cold-plug + +All the CPU hotplug facilities are ready. Assemble them +to start up CPU hot-plug capability for arm/virt. + +This also adds CPU cold plug support to arm virt machine +board. CPU cold plug means adding CPU by using "-device +xx-arm-cpu" when we bring up Qemu. + +Signed-off-by: Salil Mehta +Signed-off-by: Keqian Zhu +--- + hw/arm/virt.c | 110 ++++++++++++++++++++++++++++++++++++++++-- + hw/core/cpu-common.c | 4 ++ + include/hw/arm/virt.h | 1 + + target/arm/cpu.c | 2 + + 4 files changed, 113 insertions(+), 4 deletions(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 4eb1b44729..b81d22d68f 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -52,6 +52,8 @@ + #include "sysemu/tpm.h" + #include "sysemu/kvm.h" + #include "sysemu/hvf.h" ++#include "sysemu/cpus.h" ++#include "sysemu/hw_accel.h" + #include "hw/loader.h" + #include "qapi/error.h" + #include "qemu/bitops.h" +@@ -703,9 +705,9 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms) + event |= ACPI_GED_NVDIMM_HOTPLUG_EVT; + } + +- /* event |= ACPI_GED_CPU_HOTPLUG_EVT; +- * Currently CPU hotplug is not enabled. +- */ ++ if (vms->cpu_hotplug_enabled) { ++ event |= ACPI_GED_CPU_HOTPLUG_EVT; ++ } + + dev = qdev_new(TYPE_ACPI_GED); + qdev_prop_set_uint32(dev, "ged-event", event); +@@ -2555,11 +2557,18 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, + VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(hotplug_dev); + const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); ++ const CPUArchId *cpu_slot = NULL; + MemoryRegion *sysmem = get_system_memory(); + int smp_clusters = ms->smp.clusters; + int smp_cores = ms->smp.cores; + int smp_threads = ms->smp.threads; + ++ if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) { ++ error_setg(errp, "Invalid CPU type, expected cpu type: '%s'", ++ ms->cpu_type); ++ return; ++ } ++ + /* if cpu idx is not set, set it based on socket/cluster/core/thread + * properties + */ +@@ -2593,6 +2602,20 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, + cs->cpu_index = idx_from_topo_ids(smp_clusters, smp_cores, smp_threads, &topo); + } + ++ /* Some hotplug capability checks */ ++ if (cs->cpu_index >= ms->smp.cpus) { ++ if (!vms->acpi_dev) { ++ error_setg(errp, "CPU cold/hot plug is disabled: " ++ "missing acpi device."); ++ return; ++ } ++ if (!vms->cpu_hotplug_enabled) { ++ error_setg(errp, "CPU cold/hot plug is disabled: " ++ "should use AArch64 CPU and GICv3."); ++ return; ++ } ++ } ++ + /* if 'address' properties socket-id/cluster-id/core-id/thread-id are not + * set, set them so that machine_query_hotpluggable_cpus would show correct + * values +@@ -2631,6 +2654,13 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, + object_property_set_int(cpuobj, "mp-affinity", + possible_cpus->cpus[cs->cpu_index].arch_id, NULL); + ++ cpu_slot = &possible_cpus->cpus[cs->cpu_index]; ++ if (cpu_slot->cpu) { ++ error_setg(errp, "CPU[%d] with mp_affinity %" PRIu64 " exists", ++ cs->cpu_index, cpu->mp_affinity); ++ return; ++ } ++ + numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj), + &error_fatal); + +@@ -2716,12 +2746,83 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, + &error_abort); + } + } ++ ++ /* If we use KVM accel, we should pause all vcpus to ++ * allow hot access of vcpu registers. ++ */ ++ if (dev->hotplugged && kvm_enabled()) { ++ pause_all_vcpus(); ++ } + } + + static void virt_cpu_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) + { +- /* Currently nothing to do */ ++ CPUArchId *cpu_slot; ++ CPUState *cs = CPU(dev); ++ int ncpu = cs->cpu_index; ++ MachineState *ms = MACHINE(hotplug_dev); ++ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); ++ bool pmu = object_property_get_bool(OBJECT(first_cpu), "pmu", NULL); ++ bool steal_time = object_property_get_bool(OBJECT(first_cpu), ++ "kvm-steal-time", NULL); ++ GICv3State *gicv3; ++ ARMGICv3CommonClass *agcc; ++ Error *local_err = NULL; ++ ++ /* For CPU that is cold/hot plugged */ ++ if (ncpu >= ms->smp.cpus) { ++ /* Realize GIC related parts of CPU */ ++ assert(vms->gic_version == 3); ++ gicv3 = ARM_GICV3_COMMON(vms->gic); ++ agcc = ARM_GICV3_COMMON_GET_CLASS(gicv3); ++ agcc->cpu_hotplug_realize(gicv3, ncpu); ++ connect_gic_cpu_irqs(vms, ncpu); ++ ++ /* Init PMU and steal_time part */ ++ if (kvm_enabled()) { ++ hwaddr pvtime_reg_base = vms->memmap[VIRT_PVTIME].base; ++ ++ if (pmu) { ++ assert(arm_feature(&ARM_CPU(cs)->env, ARM_FEATURE_PMU)); ++ if (kvm_irqchip_in_kernel()) { ++ kvm_arm_pmu_set_irq(cs, PPI(VIRTUAL_PMU_IRQ)); ++ } ++ kvm_arm_pmu_init(cs); ++ } ++ if (steal_time) { ++ kvm_arm_pvtime_init(cs, pvtime_reg_base + ++ ncpu * PVTIME_SIZE_PER_CPU); ++ } ++ } ++ ++ /* Register CPU reset and trigger it manually */ ++ cpu_synchronize_state(cs); ++ cpu_hotplug_register_reset(ncpu); ++ cpu_hotplug_reset_manually(ncpu); ++ cpu_synchronize_post_reset(cs); ++ } ++ ++ if (dev->hotplugged && kvm_enabled()) { ++ resume_all_vcpus(); ++ } ++ ++ if (vms->acpi_dev) { ++ hotplug_handler_plug(HOTPLUG_HANDLER(vms->acpi_dev), dev, &local_err); ++ if (local_err) { ++ goto out; ++ } ++ } ++ ++ vms->boot_cpus++; ++ if (vms->fw_cfg) { ++ fw_cfg_modify_i16(vms->fw_cfg, FW_CFG_NB_CPUS, vms->boot_cpus); ++ } ++ ++ cpu_slot = &ms->possible_cpus->cpus[ncpu]; ++ cpu_slot->cpu = OBJECT(dev); ++out: ++ error_propagate(errp, local_err); + } + + static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, +@@ -2940,6 +3041,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) + mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15"); + mc->get_default_cpu_node_id = virt_get_default_cpu_node_id; + mc->kvm_type = virt_kvm_type; ++ mc->has_hotpluggable_cpus = true; + assert(!mc->get_hotplug_handler); + mc->get_hotplug_handler = virt_machine_get_hotplug_handler; + hc->pre_plug = virt_machine_device_pre_plug_cb; +diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c +index 9e3241b430..b8d1d820cb 100644 +--- a/hw/core/cpu-common.c ++++ b/hw/core/cpu-common.c +@@ -208,6 +208,10 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp) + + if (dev->hotplugged) { + cpu_synchronize_post_init(cpu); ++ ++#ifdef __aarch64__ ++ if (!kvm_enabled()) ++#endif + cpu_resume(cpu); + } + +diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h +index c371d377e0..4ddee19b18 100644 +--- a/include/hw/arm/virt.h ++++ b/include/hw/arm/virt.h +@@ -168,6 +168,7 @@ struct VirtMachineState { + uint32_t msi_phandle; + uint32_t iommu_phandle; + int psci_conduit; ++ uint32_t boot_cpus; + hwaddr highest_gpa; + DeviceState *gic; + DeviceState *acpi_dev; +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 9fd8e57971..d550022f18 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -2580,6 +2580,8 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) + device_class_set_props(dc, arm_cpu_properties); + device_class_set_parent_reset(dc, arm_cpu_reset, &acc->parent_reset); + ++ dc->user_creatable = true; ++ + cc->class_by_name = arm_cpu_class_by_name; + cc->has_work = arm_cpu_has_work; + cc->dump_state = arm_cpu_dump_state; +-- +2.27.0 + -- Gitee From d4adf19f8c376e993b4a7de2a3aafdb44c79ddc7 Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 23 Feb 2022 09:09:12 +0800 Subject: [PATCH 27/28] spec: Update patch and changelog with !257 add vcpu hotplug feature from 4.1 to 6.2 !257 acpi/madt: Factor out the building of MADT GICC struct hw/arm/virt: Assign virt_madt_cpu_entry to acpi_ged madt_cpu hook arm/virt/acpi: Factor out CPPC building from DSDT CPU aml acpi/cpu: Prepare build_cpus_aml for arm virt acpi/ged: Extend ACPI GED to support CPU hotplug arm/cpu: assign arm_get_arch_id handler to get_arch_id hook tests/acpi/bios-tables-test: Allow changes to virt/DSDT file arm/virt: Attach ACPI CPU hotplug support to virt tests/acpi/bios-table-test: Update expected virt/DSDT file arm/virt: Add CPU hotplug framework arm/virt: Add CPU topology support test/numa: Adjust aarch64 numa test hw/arm/virt: Factor out some CPU init codes to pre_plug hook hw/arm/boot: Add manually register and trigger of CPU reset arm/virt/gic: Construct irqs connection from create_gic intc/gicv3_common: Factor out arm_gicv3_common_cpu_realize intc/gicv3_cpuif: Factor out gicv3_init_one_cpuif intc/kvm_gicv3: Factor out kvm_arm_gicv3_cpu_realize hw/intc/gicv3: Add CPU hotplug realize hook accel/kvm: Add pre-park vCPU support intc/gicv3: Add pre-sizing capability to GICv3 acpi/madt: Add pre-sizing capability to MADT GICC struct arm/virt: Add cpu_hotplug_enabled field arm/virt/acpi: Extend cpufreq to support max_cpus arm/virt: Pre-sizing MADT-GICC GICv3 and Pre-park KVM vCPU arm/virt: Start up CPU hot-plug and cold-plug Signed-off-by: Chen Qun (cherry picked from commit 9390aa07e450024769ceb3bb3ab481af8911a77b) --- qemu.spec | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/qemu.spec b/qemu.spec index fb5e2f1b..3db28fcd 100644 --- a/qemu.spec +++ b/qemu.spec @@ -201,6 +201,32 @@ Patch0187: Revert-qmp-add-command-to-query-used-memslots-of-vho.patch Patch0188: target-arm-Fix-some-compile-errors.patch Patch0189: pl031-support-rtc-timer-property-for-pl031.patch Patch0190: i386-cpu-fix-compile-error-in-all-target-configure.patch +Patch0191: acpi-madt-Factor-out-the-building-of-MADT-GICC-struc.patch +Patch0192: hw-arm-virt-Assign-virt_madt_cpu_entry-to-acpi_ged-m.patch +Patch0193: arm-virt-acpi-Factor-out-CPPC-building-from-DSDT-CPU.patch +Patch0194: acpi-cpu-Prepare-build_cpus_aml-for-arm-virt.patch +Patch0195: acpi-ged-Extend-ACPI-GED-to-support-CPU-hotplug.patch +Patch0196: arm-cpu-assign-arm_get_arch_id-handler-to-get_arch_i.patch +Patch0197: tests-acpi-bios-tables-test-Allow-changes-to-virt-DS.patch +Patch0198: arm-virt-Attach-ACPI-CPU-hotplug-support-to-virt.patch +Patch0199: tests-acpi-bios-table-test-Update-expected-virt-DSDT.patch +Patch0200: arm-virt-Add-CPU-hotplug-framework.patch +Patch0201: arm-virt-Add-CPU-topology-support.patch +Patch0202: test-numa-Adjust-aarch64-numa-test.patch +Patch0203: hw-arm-virt-Factor-out-some-CPU-init-codes-to-pre_pl.patch +Patch0204: hw-arm-boot-Add-manually-register-and-trigger-of-CPU.patch +Patch0205: arm-virt-gic-Construct-irqs-connection-from-create_g.patch +Patch0206: intc-gicv3_common-Factor-out-arm_gicv3_common_cpu_re.patch +Patch0207: intc-gicv3_cpuif-Factor-out-gicv3_init_one_cpuif.patch +Patch0208: intc-kvm_gicv3-Factor-out-kvm_arm_gicv3_cpu_realize.patch +Patch0209: hw-intc-gicv3-Add-CPU-hotplug-realize-hook.patch +Patch0210: accel-kvm-Add-pre-park-vCPU-support.patch +Patch0211: intc-gicv3-Add-pre-sizing-capability-to-GICv3.patch +Patch0212: acpi-madt-Add-pre-sizing-capability-to-MADT-GICC-str.patch +Patch0213: arm-virt-Add-cpu_hotplug_enabled-field.patch +Patch0214: arm-virt-acpi-Extend-cpufreq-to-support-max_cpus.patch +Patch0215: arm-virt-Pre-sizing-MADT-GICC-GICv3-and-Pre-park-KVM.patch +Patch0216: arm-virt-Start-up-CPU-hot-plug-and-cold-plug.patch BuildRequires: flex BuildRequires: gcc @@ -648,6 +674,34 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Wed Feb 23 2022 Chen Qun +- acpi/madt: Factor out the building of MADT GICC struct +- hw/arm/virt: Assign virt_madt_cpu_entry to acpi_ged madt_cpu hook +- arm/virt/acpi: Factor out CPPC building from DSDT CPU aml +- acpi/cpu: Prepare build_cpus_aml for arm virt +- acpi/ged: Extend ACPI GED to support CPU hotplug +- arm/cpu: assign arm_get_arch_id handler to get_arch_id hook +- tests/acpi/bios-tables-test: Allow changes to virt/DSDT file +- arm/virt: Attach ACPI CPU hotplug support to virt +- tests/acpi/bios-table-test: Update expected virt/DSDT file +- arm/virt: Add CPU hotplug framework +- arm/virt: Add CPU topology support +- test/numa: Adjust aarch64 numa test +- hw/arm/virt: Factor out some CPU init codes to pre_plug hook +- hw/arm/boot: Add manually register and trigger of CPU reset +- arm/virt/gic: Construct irqs connection from create_gic +- intc/gicv3_common: Factor out arm_gicv3_common_cpu_realize +- intc/gicv3_cpuif: Factor out gicv3_init_one_cpuif +- intc/kvm_gicv3: Factor out kvm_arm_gicv3_cpu_realize +- hw/intc/gicv3: Add CPU hotplug realize hook +- accel/kvm: Add pre-park vCPU support +- intc/gicv3: Add pre-sizing capability to GICv3 +- acpi/madt: Add pre-sizing capability to MADT GICC struct +- arm/virt: Add cpu_hotplug_enabled field +- arm/virt/acpi: Extend cpufreq to support max_cpus +- arm/virt: Pre-sizing MADT-GICC GICv3 and Pre-park KVM vCPU +- arm/virt: Start up CPU hot-plug and cold-plug + * Mon Feb 21 2022 Chen Qun - i386/cpu: fix compile error in all target configure -- Gitee From 1ce6e87ae153eec9b8d32aad85bb651a4909d17d Mon Sep 17 00:00:00 2001 From: Chen Qun Date: Wed, 23 Feb 2022 09:09:22 +0800 Subject: [PATCH 28/28] spec: Update release version with !257 increase release verison by one Signed-off-by: Chen Qun (cherry picked from commit 185b204119d6955d15deaba8f441880eacfa3f8f) --- qemu.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu.spec b/qemu.spec index 3db28fcd..c18d51a4 100644 --- a/qemu.spec +++ b/qemu.spec @@ -1,6 +1,6 @@ Name: qemu Version: 6.2.0 -Release: 20 +Release: 21 Epoch: 2 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 -- Gitee