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