206 lines
7.1 KiB
Diff
206 lines
7.1 KiB
Diff
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
|
|
|