1 /* 2 * 3 * Copyright (c) 2018 Intel Corporation 4 * Copyright (c) 2019 Huawei Technologies R & D (UK) Ltd 5 * Written by Samuel Ortiz, Shameer Kolothum 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms and conditions of the GNU General Public License, 9 * version 2 or later, as published by the Free Software Foundation. 10 */ 11 12 #include "qemu/osdep.h" 13 #include "qapi/error.h" 14 #include "hw/acpi/acpi.h" 15 #include "hw/acpi/generic_event_device.h" 16 #include "hw/irq.h" 17 #include "hw/mem/pc-dimm.h" 18 #include "hw/mem/nvdimm.h" 19 #include "hw/qdev-properties.h" 20 #include "migration/vmstate.h" 21 #include "qemu/error-report.h" 22 #include "sysemu/runstate.h" 23 24 static const uint32_t ged_supported_events[] = { 25 ACPI_GED_MEM_HOTPLUG_EVT, 26 ACPI_GED_PWR_DOWN_EVT, 27 ACPI_GED_NVDIMM_HOTPLUG_EVT, 28 ACPI_GED_CPU_HOTPLUG_EVT, 29 }; 30 31 /* 32 * The ACPI Generic Event Device (GED) is a hardware-reduced specific 33 * device[ACPI v6.1 Section 5.6.9] that handles all platform events, 34 * including the hotplug ones. Platforms need to specify their own 35 * GED Event bitmap to describe what kind of events they want to support 36 * through GED. This routine uses a single interrupt for the GED device, 37 * relying on IO memory region to communicate the type of device 38 * affected by the interrupt. This way, we can support up to 32 events 39 * with a unique interrupt. 40 */ 41 void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev, 42 uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base) 43 { 44 AcpiGedState *s = ACPI_GED(hotplug_dev); 45 Aml *crs = aml_resource_template(); 46 Aml *evt, *field; 47 Aml *dev = aml_device("%s", name); 48 Aml *evt_sel = aml_local(0); 49 Aml *esel = aml_name(AML_GED_EVT_SEL); 50 51 /* _CRS interrupt */ 52 aml_append(crs, aml_interrupt(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH, 53 AML_EXCLUSIVE, &ged_irq, 1)); 54 55 aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0013"))); 56 aml_append(dev, aml_name_decl("_UID", aml_string(GED_DEVICE))); 57 aml_append(dev, aml_name_decl("_CRS", crs)); 58 59 /* Append IO region */ 60 aml_append(dev, aml_operation_region(AML_GED_EVT_REG, rs, 61 aml_int(ged_base + ACPI_GED_EVT_SEL_OFFSET), 62 ACPI_GED_EVT_SEL_LEN)); 63 field = aml_field(AML_GED_EVT_REG, AML_DWORD_ACC, AML_NOLOCK, 64 AML_WRITE_AS_ZEROS); 65 aml_append(field, aml_named_field(AML_GED_EVT_SEL, 66 ACPI_GED_EVT_SEL_LEN * BITS_PER_BYTE)); 67 aml_append(dev, field); 68 69 /* 70 * For each GED event we: 71 * - Add a conditional block for each event, inside a loop. 72 * - Call a method for each supported GED event type. 73 * 74 * The resulting ASL code looks like: 75 * 76 * Local0 = ESEL 77 * If ((Local0 & One) == One) 78 * { 79 * MethodEvent0() 80 * } 81 * 82 * If ((Local0 & 0x2) == 0x2) 83 * { 84 * MethodEvent1() 85 * } 86 * ... 87 */ 88 evt = aml_method("_EVT", 1, AML_SERIALIZED); 89 { 90 Aml *if_ctx; 91 uint32_t i; 92 uint32_t ged_events = ctpop32(s->ged_event_bitmap); 93 94 /* Local0 = ESEL */ 95 aml_append(evt, aml_store(esel, evt_sel)); 96 97 for (i = 0; i < ARRAY_SIZE(ged_supported_events) && ged_events; i++) { 98 uint32_t event = s->ged_event_bitmap & ged_supported_events[i]; 99 100 if (!event) { 101 continue; 102 } 103 104 if_ctx = aml_if(aml_equal(aml_and(evt_sel, aml_int(event), NULL), 105 aml_int(event))); 106 switch (event) { 107 case ACPI_GED_MEM_HOTPLUG_EVT: 108 aml_append(if_ctx, aml_call0(MEMORY_DEVICES_CONTAINER "." 109 MEMORY_SLOT_SCAN_METHOD)); 110 break; 111 case ACPI_GED_CPU_HOTPLUG_EVT: 112 aml_append(if_ctx, aml_call0(AML_GED_EVT_CPU_SCAN_METHOD)); 113 break; 114 case ACPI_GED_PWR_DOWN_EVT: 115 aml_append(if_ctx, 116 aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE), 117 aml_int(0x80))); 118 break; 119 case ACPI_GED_NVDIMM_HOTPLUG_EVT: 120 aml_append(if_ctx, 121 aml_notify(aml_name("\\_SB.NVDR"), 122 aml_int(0x80))); 123 break; 124 default: 125 /* 126 * Please make sure all the events in ged_supported_events[] 127 * are handled above. 128 */ 129 g_assert_not_reached(); 130 } 131 132 aml_append(evt, if_ctx); 133 ged_events--; 134 } 135 136 if (ged_events) { 137 error_report("Unsupported events specified"); 138 abort(); 139 } 140 } 141 142 /* Append _EVT method */ 143 aml_append(dev, evt); 144 145 aml_append(table, dev); 146 } 147 148 void acpi_dsdt_add_power_button(Aml *scope) 149 { 150 Aml *dev = aml_device(ACPI_POWER_BUTTON_DEVICE); 151 aml_append(dev, aml_name_decl("_HID", aml_string("PNP0C0C"))); 152 aml_append(dev, aml_name_decl("_UID", aml_int(0))); 153 aml_append(scope, dev); 154 } 155 156 /* Memory read by the GED _EVT AML dynamic method */ 157 static uint64_t ged_evt_read(void *opaque, hwaddr addr, unsigned size) 158 { 159 uint64_t val = 0; 160 GEDState *ged_st = opaque; 161 162 switch (addr) { 163 case ACPI_GED_EVT_SEL_OFFSET: 164 /* Read the selector value and reset it */ 165 val = ged_st->sel; 166 ged_st->sel = 0; 167 break; 168 default: 169 break; 170 } 171 172 return val; 173 } 174 175 /* Nothing is expected to be written to the GED memory region */ 176 static void ged_evt_write(void *opaque, hwaddr addr, uint64_t data, 177 unsigned int size) 178 { 179 } 180 181 static const MemoryRegionOps ged_evt_ops = { 182 .read = ged_evt_read, 183 .write = ged_evt_write, 184 .endianness = DEVICE_LITTLE_ENDIAN, 185 .valid = { 186 .min_access_size = 4, 187 .max_access_size = 4, 188 }, 189 }; 190 191 static uint64_t ged_regs_read(void *opaque, hwaddr addr, unsigned size) 192 { 193 return 0; 194 } 195 196 static void ged_regs_write(void *opaque, hwaddr addr, uint64_t data, 197 unsigned int size) 198 { 199 bool slp_en; 200 int slp_typ; 201 202 switch (addr) { 203 case ACPI_GED_REG_SLEEP_CTL: 204 slp_typ = (data >> 2) & 0x07; 205 slp_en = (data >> 5) & 0x01; 206 if (slp_en && slp_typ == 5) { 207 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); 208 } 209 return; 210 case ACPI_GED_REG_SLEEP_STS: 211 return; 212 case ACPI_GED_REG_RESET: 213 if (data == ACPI_GED_RESET_VALUE) { 214 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 215 } 216 return; 217 } 218 } 219 220 static const MemoryRegionOps ged_regs_ops = { 221 .read = ged_regs_read, 222 .write = ged_regs_write, 223 .endianness = DEVICE_LITTLE_ENDIAN, 224 .valid = { 225 .min_access_size = 1, 226 .max_access_size = 1, 227 }, 228 }; 229 230 static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev, 231 DeviceState *dev, Error **errp) 232 { 233 AcpiGedState *s = ACPI_GED(hotplug_dev); 234 235 if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 236 if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { 237 nvdimm_acpi_plug_cb(hotplug_dev, dev); 238 } else { 239 acpi_memory_plug_cb(hotplug_dev, &s->memhp_state, dev, errp); 240 } 241 } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { 242 acpi_cpu_plug_cb(hotplug_dev, &s->cpuhp_state, dev, errp); 243 } else { 244 error_setg(errp, "virt: device plug request for unsupported device" 245 " type: %s", object_get_typename(OBJECT(dev))); 246 } 247 } 248 249 static void acpi_ged_unplug_request_cb(HotplugHandler *hotplug_dev, 250 DeviceState *dev, Error **errp) 251 { 252 AcpiGedState *s = ACPI_GED(hotplug_dev); 253 254 if ((object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) && 255 !(object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)))) { 256 acpi_memory_unplug_request_cb(hotplug_dev, &s->memhp_state, dev, errp); 257 } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { 258 acpi_cpu_unplug_request_cb(hotplug_dev, &s->cpuhp_state, dev, errp); 259 } else { 260 error_setg(errp, "acpi: device unplug request for unsupported device" 261 " type: %s", object_get_typename(OBJECT(dev))); 262 } 263 } 264 265 static void acpi_ged_unplug_cb(HotplugHandler *hotplug_dev, 266 DeviceState *dev, Error **errp) 267 { 268 AcpiGedState *s = ACPI_GED(hotplug_dev); 269 270 if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 271 acpi_memory_unplug_cb(&s->memhp_state, dev, errp); 272 } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { 273 acpi_cpu_unplug_cb(&s->cpuhp_state, dev, errp); 274 } else { 275 error_setg(errp, "acpi: device unplug for unsupported device" 276 " type: %s", object_get_typename(OBJECT(dev))); 277 } 278 } 279 280 static void acpi_ged_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list) 281 { 282 AcpiGedState *s = ACPI_GED(adev); 283 284 acpi_memory_ospm_status(&s->memhp_state, list); 285 acpi_cpu_ospm_status(&s->cpuhp_state, list); 286 } 287 288 static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) 289 { 290 AcpiGedState *s = ACPI_GED(adev); 291 GEDState *ged_st = &s->ged_state; 292 uint32_t sel; 293 294 if (ev & ACPI_MEMORY_HOTPLUG_STATUS) { 295 sel = ACPI_GED_MEM_HOTPLUG_EVT; 296 } else if (ev & ACPI_POWER_DOWN_STATUS) { 297 sel = ACPI_GED_PWR_DOWN_EVT; 298 } else if (ev & ACPI_NVDIMM_HOTPLUG_STATUS) { 299 sel = ACPI_GED_NVDIMM_HOTPLUG_EVT; 300 } else if (ev & ACPI_CPU_HOTPLUG_STATUS) { 301 sel = ACPI_GED_CPU_HOTPLUG_EVT; 302 } else { 303 /* Unknown event. Return without generating interrupt. */ 304 warn_report("GED: Unsupported event %d. No irq injected", ev); 305 return; 306 } 307 308 /* 309 * Set the GED selector field to communicate the event type. 310 * This will be read by GED aml code to select the appropriate 311 * event method. 312 */ 313 ged_st->sel |= sel; 314 315 /* Trigger the event by sending an interrupt to the guest. */ 316 qemu_irq_pulse(s->irq); 317 } 318 319 static Property acpi_ged_properties[] = { 320 DEFINE_PROP_UINT32("ged-event", AcpiGedState, ged_event_bitmap, 0), 321 DEFINE_PROP_END_OF_LIST(), 322 }; 323 324 static const VMStateDescription vmstate_memhp_state = { 325 .name = "acpi-ged/memhp", 326 .version_id = 1, 327 .minimum_version_id = 1, 328 .fields = (const VMStateField[]) { 329 VMSTATE_MEMORY_HOTPLUG(memhp_state, AcpiGedState), 330 VMSTATE_END_OF_LIST() 331 } 332 }; 333 334 static const VMStateDescription vmstate_ged_state = { 335 .name = "acpi-ged-state", 336 .version_id = 1, 337 .minimum_version_id = 1, 338 .fields = (const VMStateField[]) { 339 VMSTATE_UINT32(sel, GEDState), 340 VMSTATE_END_OF_LIST() 341 } 342 }; 343 344 static const VMStateDescription vmstate_ghes = { 345 .name = "acpi-ghes", 346 .version_id = 1, 347 .minimum_version_id = 1, 348 .fields = (const VMStateField[]) { 349 VMSTATE_UINT64(ghes_addr_le, AcpiGhesState), 350 VMSTATE_END_OF_LIST() 351 }, 352 }; 353 354 static bool ghes_needed(void *opaque) 355 { 356 AcpiGedState *s = opaque; 357 return s->ghes_state.ghes_addr_le; 358 } 359 360 static const VMStateDescription vmstate_ghes_state = { 361 .name = "acpi-ged/ghes", 362 .version_id = 1, 363 .minimum_version_id = 1, 364 .needed = ghes_needed, 365 .fields = (const VMStateField[]) { 366 VMSTATE_STRUCT(ghes_state, AcpiGedState, 1, 367 vmstate_ghes, AcpiGhesState), 368 VMSTATE_END_OF_LIST() 369 } 370 }; 371 372 static const VMStateDescription vmstate_acpi_ged = { 373 .name = "acpi-ged", 374 .version_id = 1, 375 .minimum_version_id = 1, 376 .fields = (const VMStateField[]) { 377 VMSTATE_STRUCT(ged_state, AcpiGedState, 1, vmstate_ged_state, GEDState), 378 VMSTATE_END_OF_LIST(), 379 }, 380 .subsections = (const VMStateDescription * const []) { 381 &vmstate_memhp_state, 382 &vmstate_ghes_state, 383 NULL 384 } 385 }; 386 387 static void acpi_ged_realize(DeviceState *dev, Error **errp) 388 { 389 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 390 AcpiGedState *s = ACPI_GED(dev); 391 uint32_t ged_events; 392 int i; 393 394 ged_events = ctpop32(s->ged_event_bitmap); 395 396 for (i = 0; i < ARRAY_SIZE(ged_supported_events) && ged_events; i++) { 397 uint32_t event = s->ged_event_bitmap & ged_supported_events[i]; 398 399 if (!event) { 400 continue; 401 } 402 403 switch (event) { 404 case ACPI_GED_CPU_HOTPLUG_EVT: 405 /* initialize CPU Hotplug related regions */ 406 memory_region_init(&s->container_cpuhp, OBJECT(dev), 407 "cpuhp container", 408 ACPI_CPU_HOTPLUG_REG_LEN); 409 sysbus_init_mmio(sbd, &s->container_cpuhp); 410 cpu_hotplug_hw_init(&s->container_cpuhp, OBJECT(dev), 411 &s->cpuhp_state, 0); 412 break; 413 } 414 ged_events--; 415 } 416 417 if (ged_events) { 418 error_report("Unsupported events specified"); 419 abort(); 420 } 421 } 422 423 static void acpi_ged_initfn(Object *obj) 424 { 425 DeviceState *dev = DEVICE(obj); 426 AcpiGedState *s = ACPI_GED(dev); 427 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 428 GEDState *ged_st = &s->ged_state; 429 430 memory_region_init_io(&ged_st->evt, obj, &ged_evt_ops, ged_st, 431 TYPE_ACPI_GED, ACPI_GED_EVT_SEL_LEN); 432 sysbus_init_mmio(sbd, &ged_st->evt); 433 434 sysbus_init_irq(sbd, &s->irq); 435 436 s->memhp_state.is_enabled = true; 437 /* 438 * GED handles memory hotplug event and acpi-mem-hotplug 439 * memory region gets initialized here. Create an exclusive 440 * container for memory hotplug IO and expose it as GED sysbus 441 * MMIO so that boards can map it separately. 442 */ 443 memory_region_init(&s->container_memhp, OBJECT(dev), "memhp container", 444 MEMORY_HOTPLUG_IO_LEN); 445 sysbus_init_mmio(sbd, &s->container_memhp); 446 acpi_memory_hotplug_init(&s->container_memhp, OBJECT(dev), 447 &s->memhp_state, 0); 448 449 memory_region_init_io(&ged_st->regs, obj, &ged_regs_ops, ged_st, 450 TYPE_ACPI_GED "-regs", ACPI_GED_REG_COUNT); 451 sysbus_init_mmio(sbd, &ged_st->regs); 452 } 453 454 static void acpi_ged_class_init(ObjectClass *class, void *data) 455 { 456 DeviceClass *dc = DEVICE_CLASS(class); 457 HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(class); 458 AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(class); 459 460 dc->desc = "ACPI Generic Event Device"; 461 device_class_set_props(dc, acpi_ged_properties); 462 dc->vmsd = &vmstate_acpi_ged; 463 dc->realize = acpi_ged_realize; 464 465 hc->plug = acpi_ged_device_plug_cb; 466 hc->unplug_request = acpi_ged_unplug_request_cb; 467 hc->unplug = acpi_ged_unplug_cb; 468 469 adevc->ospm_status = acpi_ged_ospm_status; 470 adevc->send_event = acpi_ged_send_event; 471 } 472 473 static const TypeInfo acpi_ged_info = { 474 .name = TYPE_ACPI_GED, 475 .parent = TYPE_SYS_BUS_DEVICE, 476 .instance_size = sizeof(AcpiGedState), 477 .instance_init = acpi_ged_initfn, 478 .class_init = acpi_ged_class_init, 479 .interfaces = (InterfaceInfo[]) { 480 { TYPE_HOTPLUG_HANDLER }, 481 { TYPE_ACPI_DEVICE_IF }, 482 { } 483 } 484 }; 485 486 static void acpi_ged_register_types(void) 487 { 488 type_register_static(&acpi_ged_info); 489 } 490 491 type_init(acpi_ged_register_types) 492