205 lines
6.9 KiB
Diff
205 lines
6.9 KiB
Diff
|
|
From 05d22b55133db1a2526cfe305102e075e883b5e2 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 911a98255b..deb481555d 100644
|
||
|
|
--- a/docs/specs/acpi_hw_reduced_hotplug.rst
|
||
|
|
+++ b/docs/specs/acpi_hw_reduced_hotplug.rst
|
||
|
|
@@ -63,7 +63,8 @@ GED IO interface (4 byte access)
|
||
|
|
bits:
|
||
|
|
0: Memory hotplug event
|
||
|
|
1: System power down event
|
||
|
|
- 2-31: Reserved
|
||
|
|
+ 2: CPU hotplug event
|
||
|
|
+ 3-31: Reserved
|
||
|
|
|
||
|
|
**write_access:**
|
||
|
|
|
||
|
|
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
|
||
|
|
index 72ad1fcff2..cb6bb67f3c 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 82139b4314..478a4ee87c 100644
|
||
|
|
--- a/hw/acpi/generic_event_device.c
|
||
|
|
+++ b/hw/acpi/generic_event_device.c
|
||
|
|
@@ -23,6 +23,7 @@
|
||
|
|
static const uint32_t ged_supported_events[] = {
|
||
|
|
ACPI_GED_MEM_HOTPLUG_EVT,
|
||
|
|
ACPI_GED_PWR_DOWN_EVT,
|
||
|
|
+ ACPI_GED_CPU_HOTPLUG_EVT,
|
||
|
|
};
|
||
|
|
|
||
|
|
/*
|
||
|
|
@@ -110,6 +111,9 @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev,
|
||
|
|
aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE),
|
||
|
|
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[]
|
||
|
|
@@ -176,6 +180,8 @@ static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev,
|
||
|
|
|
||
|
|
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
||
|
|
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)));
|
||
|
|
@@ -192,6 +198,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
|
||
|
|
sel = ACPI_GED_MEM_HOTPLUG_EVT;
|
||
|
|
} else if (ev & ACPI_POWER_DOWN_STATUS) {
|
||
|
|
sel = ACPI_GED_PWR_DOWN_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);
|
||
|
|
@@ -224,6 +232,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,
|
||
|
|
@@ -244,6 +262,7 @@ static const VMStateDescription vmstate_acpi_ged = {
|
||
|
|
},
|
||
|
|
.subsections = (const VMStateDescription * []) {
|
||
|
|
&vmstate_memhp_state,
|
||
|
|
+ &vmstate_cpuhp_state,
|
||
|
|
NULL
|
||
|
|
}
|
||
|
|
};
|
||
|
|
@@ -254,6 +273,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->io, obj, &ged_ops, ged_st,
|
||
|
|
TYPE_ACPI_GED, ACPI_GED_EVT_SEL_LEN);
|
||
|
|
@@ -273,6 +293,21 @@ static void acpi_ged_initfn(Object *obj)
|
||
|
|
sysbus_init_mmio(sbd, &s->container_memhp);
|
||
|
|
acpi_memory_hotplug_init(&s->container_memhp, OBJECT(dev),
|
||
|
|
&s->memhp_state, 0);
|
||
|
|
+
|
||
|
|
+ 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 ad7f7c089b..15e18b0a48 100644
|
||
|
|
--- a/hw/arm/Kconfig
|
||
|
|
+++ b/hw/arm/Kconfig
|
||
|
|
@@ -24,6 +24,7 @@ config ARM_VIRT
|
||
|
|
select DIMM
|
||
|
|
select ACPI_MEMORY_HOTPLUG
|
||
|
|
select ACPI_HW_REDUCED
|
||
|
|
+ select ACPI_CPU_HOTPLUG
|
||
|
|
|
||
|
|
config CHEETAH
|
||
|
|
bool
|
||
|
|
diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h
|
||
|
|
index a30ec84a4f..e726414459 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 f99efad7a3..e702ff1e18 100644
|
||
|
|
--- a/include/hw/acpi/generic_event_device.h
|
||
|
|
+++ b/include/hw/acpi/generic_event_device.h
|
||
|
|
@@ -62,6 +62,7 @@
|
||
|
|
#include "hw/sysbus.h"
|
||
|
|
#include "hw/acpi/memory_hotplug.h"
|
||
|
|
#include "hw/arm/virt.h"
|
||
|
|
+#include "hw/acpi/cpu.h"
|
||
|
|
|
||
|
|
#define ACPI_POWER_BUTTON_DEVICE "PWRB"
|
||
|
|
|
||
|
|
@@ -83,6 +84,7 @@
|
||
|
|
*/
|
||
|
|
#define ACPI_GED_MEM_HOTPLUG_EVT 0x1
|
||
|
|
#define ACPI_GED_PWR_DOWN_EVT 0x2
|
||
|
|
+#define ACPI_GED_CPU_HOTPLUG_EVT 0x4
|
||
|
|
|
||
|
|
typedef struct GEDState {
|
||
|
|
MemoryRegion io;
|
||
|
|
@@ -93,6 +95,8 @@ typedef 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.19.1
|