From: @openeuler-sync-bot Reviewed-by: @imxcc Signed-off-by: @imxcc
This commit is contained in:
commit
2fd41a5c69
BIN
BinDir.tar.gz
BIN
BinDir.tar.gz
Binary file not shown.
64
accel-kvm-Add-pre-park-vCPU-support.patch
Normal file
64
accel-kvm-Add-pre-park-vCPU-support.patch
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
From c950cda47386360e37a89dfa7029d83e33888a40 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
117
acpi-cpu-Prepare-build_cpus_aml-for-arm-virt.patch
Normal file
117
acpi-cpu-Prepare-build_cpus_aml-for-arm-virt.patch
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
From 1ab75151c0a486ebdbe50d29c9677c7bc1f05929 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
205
acpi-ged-Extend-ACPI-GED-to-support-CPU-hotplug.patch
Normal file
205
acpi-ged-Extend-ACPI-GED-to-support-CPU-hotplug.patch
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
From 603cbcc5efdd35f518a5bd0a5067d40c2c4eb8d6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
84
acpi-madt-Add-pre-sizing-capability-to-MADT-GICC-str.patch
Normal file
84
acpi-madt-Add-pre-sizing-capability-to-MADT-GICC-str.patch
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
From 8bd05cdb811e868c54ef28ac558c7efb7cf610b9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
136
acpi-madt-Factor-out-the-building-of-MADT-GICC-struc.patch
Normal file
136
acpi-madt-Factor-out-the-building-of-MADT-GICC-struc.patch
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
From 4f50ed900713acc14c971c07165fa83670d3f2b8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
43
arm-cpu-assign-arm_get_arch_id-handler-to-get_arch_i.patch
Normal file
43
arm-cpu-assign-arm_get_arch_id-handler-to-get_arch_i.patch
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
From 42072fd4b33125959d825a0c5cee0d1122072f71 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
69
arm-virt-Add-CPU-hotplug-framework.patch
Normal file
69
arm-virt-Add-CPU-hotplug-framework.patch
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
From 209b3e4e522b8f7f41e495feaade96ee9a91e46a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
269
arm-virt-Add-CPU-topology-support.patch
Normal file
269
arm-virt-Add-CPU-topology-support.patch
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
From 5454c00908236dcabcbf9ae246ccb69e1fcea72e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||||
|
---
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#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
|
||||||
|
|
||||||
62
arm-virt-Add-cpu_hotplug_enabled-field.patch
Normal file
62
arm-virt-Add-cpu_hotplug_enabled-field.patch
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
From 965eb25b03f6977a7656dce3ac5cdb4c95bfe003 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
103
arm-virt-Attach-ACPI-CPU-hotplug-support-to-virt.patch
Normal file
103
arm-virt-Attach-ACPI-CPU-hotplug-support-to-virt.patch
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
From 6b0f94aee82c7558d79e5ec28437483c4873dc65 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
92
arm-virt-Pre-sizing-MADT-GICC-GICv3-and-Pre-park-KVM.patch
Normal file
92
arm-virt-Pre-sizing-MADT-GICC-GICv3-and-Pre-park-KVM.patch
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
From 3063d421cd68937ece290bc02151cc15b7ec33d0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
237
arm-virt-Start-up-CPU-hot-plug-and-cold-plug.patch
Normal file
237
arm-virt-Start-up-CPU-hot-plug-and-cold-plug.patch
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
From a2d8cf86a379bb161cdae850824c9e80fb370599 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <salil.mehta@huawei.com>
|
||||||
|
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
66
arm-virt-acpi-Extend-cpufreq-to-support-max_cpus.patch
Normal file
66
arm-virt-acpi-Extend-cpufreq-to-support-max_cpus.patch
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
From e3522e63a2f14c3c7d8cd603099b6bb51087f43b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
122
arm-virt-acpi-Factor-out-CPPC-building-from-DSDT-CPU.patch
Normal file
122
arm-virt-acpi-Factor-out-CPPC-building-from-DSDT-CPU.patch
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
From 06837491e2ece2fdd6fe6cc8572aaab52fbdcb3e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
124
arm-virt-gic-Construct-irqs-connection-from-create_g.patch
Normal file
124
arm-virt-gic-Construct-irqs-connection-from-create_g.patch
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
From 03e050611d6dc9909166fd31dd11abf6fd5012ea Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
116
hw-arm-boot-Add-manually-register-and-trigger-of-CPU.patch
Normal file
116
hw-arm-boot-Add-manually-register-and-trigger-of-CPU.patch
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
From 9dc22ff87eb61a8b2bcc5892961ec432986893c9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
40
hw-arm-virt-Assign-virt_madt_cpu_entry-to-acpi_ged-m.patch
Normal file
40
hw-arm-virt-Assign-virt_madt_cpu_entry-to-acpi_ged-m.patch
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
From ae74dda87e172ce82a8180d1a2e9c62904390f91 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
261
hw-arm-virt-Factor-out-some-CPU-init-codes-to-pre_pl.patch
Normal file
261
hw-arm-virt-Factor-out-some-CPU-init-codes-to-pre_pl.patch
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
From 7838609e9a7743af03c58ae46afd26070b2feea6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
171
hw-intc-gicv3-Add-CPU-hotplug-realize-hook.patch
Normal file
171
hw-intc-gicv3-Add-CPU-hotplug-realize-hook.patch
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
From e94b8dc43d416b3ebf316faf14309fe4c4d0b4f0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
358
intc-gicv3-Add-pre-sizing-capability-to-GICv3.patch
Normal file
358
intc-gicv3-Add-pre-sizing-capability-to-GICv3.patch
Normal file
@ -0,0 +1,358 @@
|
|||||||
|
From 3ed7dcc4a8ccf443d125e7908d8293b562c68d4b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
51
intc-gicv3_common-Factor-out-arm_gicv3_common_cpu_re.patch
Normal file
51
intc-gicv3_common-Factor-out-arm_gicv3_common_cpu_re.patch
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
From 06cb0756a01796352861b4d47d59db1bde84ec6f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
196
intc-gicv3_cpuif-Factor-out-gicv3_init_one_cpuif.patch
Normal file
196
intc-gicv3_cpuif-Factor-out-gicv3_init_one_cpuif.patch
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
From 62b5c897e367c3db477a680b7557662347677433 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
46
intc-kvm_gicv3-Factor-out-kvm_arm_gicv3_cpu_realize.patch
Normal file
46
intc-kvm_gicv3-Factor-out-kvm_arm_gicv3_cpu_realize.patch
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
From dd03bc60712bd41a9606742ea4b769aa8e360655 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
56
qemu.spec
56
qemu.spec
@ -1,6 +1,6 @@
|
|||||||
Name: qemu
|
Name: qemu
|
||||||
Version: 6.2.0
|
Version: 6.2.0
|
||||||
Release: 20
|
Release: 21
|
||||||
Epoch: 2
|
Epoch: 2
|
||||||
Summary: QEMU is a generic and open source machine emulator and virtualizer
|
Summary: QEMU is a generic and open source machine emulator and virtualizer
|
||||||
License: GPLv2 and BSD and MIT and CC-BY-SA-4.0
|
License: GPLv2 and BSD and MIT and CC-BY-SA-4.0
|
||||||
@ -201,6 +201,32 @@ Patch0187: Revert-qmp-add-command-to-query-used-memslots-of-vho.patch
|
|||||||
Patch0188: target-arm-Fix-some-compile-errors.patch
|
Patch0188: target-arm-Fix-some-compile-errors.patch
|
||||||
Patch0189: pl031-support-rtc-timer-property-for-pl031.patch
|
Patch0189: pl031-support-rtc-timer-property-for-pl031.patch
|
||||||
Patch0190: i386-cpu-fix-compile-error-in-all-target-configure.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: flex
|
||||||
BuildRequires: gcc
|
BuildRequires: gcc
|
||||||
@ -648,6 +674,34 @@ getent passwd qemu >/dev/null || \
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed Feb 23 2022 Chen Qun <kuhn.chenqun@huawei.com>
|
||||||
|
- 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 <kuhn.chenqun@huawei.com>
|
* Mon Feb 21 2022 Chen Qun <kuhn.chenqun@huawei.com>
|
||||||
- i386/cpu: fix compile error in all target configure
|
- i386/cpu: fix compile error in all target configure
|
||||||
|
|
||||||
|
|||||||
59
test-numa-Adjust-aarch64-numa-test.patch
Normal file
59
test-numa-Adjust-aarch64-numa-test.patch
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
From 1a347bf3f8e7e31cdaed265af22853d66c202090 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
26
tests-acpi-bios-table-test-Update-expected-virt-DSDT.patch
Normal file
26
tests-acpi-bios-table-test-Update-expected-virt-DSDT.patch
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
From d3d158cbf6b236022794e867ac395f75fb4f6436 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
22
tests-acpi-bios-tables-test-Allow-changes-to-virt-DS.patch
Normal file
22
tests-acpi-bios-tables-test-Allow-changes-to-virt-DS.patch
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
From d215714b9ab38f6c9e0aacf2120b44888936a1ed Mon Sep 17 00:00:00 2001
|
||||||
|
From: Keqian Zhu <zhukeqian1@huawei.com>
|
||||||
|
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 <zhukeqian1@huawei.com>
|
||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user