|
@@ -25,6 +25,7 @@ static const uint32_t ged_supported_events[] = {
|
|
ACPI_GED_MEM_HOTPLUG_EVT,
|
|
ACPI_GED_MEM_HOTPLUG_EVT,
|
|
ACPI_GED_PWR_DOWN_EVT,
|
|
ACPI_GED_PWR_DOWN_EVT,
|
|
ACPI_GED_NVDIMM_HOTPLUG_EVT,
|
|
ACPI_GED_NVDIMM_HOTPLUG_EVT,
|
|
|
|
+ ACPI_GED_CPU_HOTPLUG_EVT,
|
|
};
|
|
};
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -234,6 +235,8 @@ static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev,
|
|
} else {
|
|
} else {
|
|
acpi_memory_plug_cb(hotplug_dev, &s->memhp_state, dev, errp);
|
|
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 {
|
|
} else {
|
|
error_setg(errp, "virt: device plug request for unsupported device"
|
|
error_setg(errp, "virt: device plug request for unsupported device"
|
|
" type: %s", object_get_typename(OBJECT(dev)));
|
|
" type: %s", object_get_typename(OBJECT(dev)));
|
|
@@ -248,6 +251,8 @@ static void acpi_ged_unplug_request_cb(HotplugHandler *hotplug_dev,
|
|
if ((object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) &&
|
|
if ((object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) &&
|
|
!(object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)))) {
|
|
!(object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)))) {
|
|
acpi_memory_unplug_request_cb(hotplug_dev, &s->memhp_state, dev, errp);
|
|
acpi_memory_unplug_request_cb(hotplug_dev, &s->memhp_state, dev, errp);
|
|
|
|
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
|
|
|
+ acpi_cpu_unplug_request_cb(hotplug_dev, &s->cpuhp_state, dev, errp);
|
|
} else {
|
|
} else {
|
|
error_setg(errp, "acpi: device unplug request for unsupported device"
|
|
error_setg(errp, "acpi: device unplug request for unsupported device"
|
|
" type: %s", object_get_typename(OBJECT(dev)));
|
|
" type: %s", object_get_typename(OBJECT(dev)));
|
|
@@ -261,6 +266,8 @@ static void acpi_ged_unplug_cb(HotplugHandler *hotplug_dev,
|
|
|
|
|
|
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
|
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
|
acpi_memory_unplug_cb(&s->memhp_state, dev, errp);
|
|
acpi_memory_unplug_cb(&s->memhp_state, dev, errp);
|
|
|
|
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
|
|
|
+ acpi_cpu_unplug_cb(&s->cpuhp_state, dev, errp);
|
|
} else {
|
|
} else {
|
|
error_setg(errp, "acpi: device unplug for unsupported device"
|
|
error_setg(errp, "acpi: device unplug for unsupported device"
|
|
" type: %s", object_get_typename(OBJECT(dev)));
|
|
" type: %s", object_get_typename(OBJECT(dev)));
|
|
@@ -272,6 +279,7 @@ static void acpi_ged_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list)
|
|
AcpiGedState *s = ACPI_GED(adev);
|
|
AcpiGedState *s = ACPI_GED(adev);
|
|
|
|
|
|
acpi_memory_ospm_status(&s->memhp_state, list);
|
|
acpi_memory_ospm_status(&s->memhp_state, list);
|
|
|
|
+ acpi_cpu_ospm_status(&s->cpuhp_state, list);
|
|
}
|
|
}
|
|
|
|
|
|
static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
|
|
static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
|
|
@@ -286,6 +294,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
|
|
sel = ACPI_GED_PWR_DOWN_EVT;
|
|
sel = ACPI_GED_PWR_DOWN_EVT;
|
|
} else if (ev & ACPI_NVDIMM_HOTPLUG_STATUS) {
|
|
} else if (ev & ACPI_NVDIMM_HOTPLUG_STATUS) {
|
|
sel = ACPI_GED_NVDIMM_HOTPLUG_EVT;
|
|
sel = ACPI_GED_NVDIMM_HOTPLUG_EVT;
|
|
|
|
+ } else if (ev & ACPI_CPU_HOTPLUG_STATUS) {
|
|
|
|
+ sel = ACPI_GED_CPU_HOTPLUG_EVT;
|
|
} else {
|
|
} else {
|
|
/* Unknown event. Return without generating interrupt. */
|
|
/* Unknown event. Return without generating interrupt. */
|
|
warn_report("GED: Unsupported event %d. No irq injected", ev);
|
|
warn_report("GED: Unsupported event %d. No irq injected", ev);
|
|
@@ -371,6 +381,42 @@ static const VMStateDescription vmstate_acpi_ged = {
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+static void acpi_ged_realize(DeviceState *dev, Error **errp)
|
|
|
|
+{
|
|
|
|
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
|
|
|
+ AcpiGedState *s = ACPI_GED(dev);
|
|
|
|
+ uint32_t ged_events;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ ged_events = ctpop32(s->ged_event_bitmap);
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < ARRAY_SIZE(ged_supported_events) && ged_events; i++) {
|
|
|
|
+ uint32_t event = s->ged_event_bitmap & ged_supported_events[i];
|
|
|
|
+
|
|
|
|
+ if (!event) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ switch (event) {
|
|
|
|
+ case ACPI_GED_CPU_HOTPLUG_EVT:
|
|
|
|
+ /* initialize CPU Hotplug related regions */
|
|
|
|
+ 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);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ ged_events--;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (ged_events) {
|
|
|
|
+ error_report("Unsupported events specified");
|
|
|
|
+ abort();
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
static void acpi_ged_initfn(Object *obj)
|
|
static void acpi_ged_initfn(Object *obj)
|
|
{
|
|
{
|
|
DeviceState *dev = DEVICE(obj);
|
|
DeviceState *dev = DEVICE(obj);
|
|
@@ -411,6 +457,7 @@ static void acpi_ged_class_init(ObjectClass *class, void *data)
|
|
dc->desc = "ACPI Generic Event Device";
|
|
dc->desc = "ACPI Generic Event Device";
|
|
device_class_set_props(dc, acpi_ged_properties);
|
|
device_class_set_props(dc, acpi_ged_properties);
|
|
dc->vmsd = &vmstate_acpi_ged;
|
|
dc->vmsd = &vmstate_acpi_ged;
|
|
|
|
+ dc->realize = acpi_ged_realize;
|
|
|
|
|
|
hc->plug = acpi_ged_device_plug_cb;
|
|
hc->plug = acpi_ged_device_plug_cb;
|
|
hc->unplug_request = acpi_ged_unplug_request_cb;
|
|
hc->unplug_request = acpi_ged_unplug_request_cb;
|