static void pcie_unplug_device(PCIBus *bus, PCIDevice *dev, void *opaque) { HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(DEVICE(dev)); hotplug_handler_unplug(hotplug_ctrl, DEVICE(dev), &error_abort); object_unparent(OBJECT(dev)); }
static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data, unsigned int size) { MemHotplugState *mem_st = opaque; MemStatus *mdev; ACPIOSTInfo *info; DeviceState *dev = NULL; HotplugHandler *hotplug_ctrl = NULL; Error *local_err = NULL; if (!mem_st->dev_count) { return; } if (addr) { if (mem_st->selector >= mem_st->dev_count) { trace_mhp_acpi_invalid_slot_selected(mem_st->selector); return; } } switch (addr) { case 0x0: /* DIMM slot selector */ mem_st->selector = data; trace_mhp_acpi_write_slot(mem_st->selector); break; case 0x4: /* _OST event */ mdev = &mem_st->devs[mem_st->selector]; if (data == 1) { /* TODO: handle device insert OST event */ } else if (data == 3) { /* TODO: handle device remove OST event */ } mdev->ost_event = data; trace_mhp_acpi_write_ost_ev(mem_st->selector, mdev->ost_event); break; case 0x8: /* _OST status */ mdev = &mem_st->devs[mem_st->selector]; mdev->ost_status = data; trace_mhp_acpi_write_ost_status(mem_st->selector, mdev->ost_status); /* TODO: implement memory removal on guest signal */ info = acpi_memory_device_status(mem_st->selector, mdev); qapi_event_send_acpi_device_ost(info, &error_abort); qapi_free_ACPIOSTInfo(info); break; case 0x14: /* set is_* fields */ mdev = &mem_st->devs[mem_st->selector]; if (data & 2) { /* clear insert event */ mdev->is_inserting = false; trace_mhp_acpi_clear_insert_evt(mem_st->selector); } else if (data & 4) { mdev->is_removing = false; trace_mhp_acpi_clear_remove_evt(mem_st->selector); } else if (data & 8) { if (!mdev->is_enabled) { trace_mhp_acpi_ejecting_invalid_slot(mem_st->selector); break; } dev = DEVICE(mdev->dimm); hotplug_ctrl = qdev_get_hotplug_handler(dev); /* call pc-dimm unplug cb */ hotplug_handler_unplug(hotplug_ctrl, dev, &local_err); if (local_err) { trace_mhp_acpi_pc_dimm_delete_failed(mem_st->selector); qapi_event_send_mem_unplug_error(dev->id, error_get_pretty(local_err), &error_abort); error_free(local_err); break; } trace_mhp_acpi_pc_dimm_deleted(mem_st->selector); } break; default: break; } }
static void cpu_hotplug_wr(void *opaque, hwaddr addr, uint64_t data, unsigned int size) { CPUHotplugState *cpu_st = opaque; AcpiCpuStatus *cdev; ACPIOSTInfo *info; assert(cpu_st->dev_count); if (addr) { if (cpu_st->selector >= cpu_st->dev_count) { trace_cpuhp_acpi_invalid_idx_selected(cpu_st->selector); return; } } switch (addr) { case ACPI_CPU_SELECTOR_OFFSET_WR: /* current CPU selector */ cpu_st->selector = data; trace_cpuhp_acpi_write_idx(cpu_st->selector); break; case ACPI_CPU_FLAGS_OFFSET_RW: /* set is_* fields */ cdev = &cpu_st->devs[cpu_st->selector]; if (data & 2) { /* clear insert event */ cdev->is_inserting = false; trace_cpuhp_acpi_clear_inserting_evt(cpu_st->selector); } else if (data & 4) { /* clear remove event */ cdev->is_removing = false; trace_cpuhp_acpi_clear_remove_evt(cpu_st->selector); } else if (data & 8) { DeviceState *dev = NULL; HotplugHandler *hotplug_ctrl = NULL; if (!cdev->cpu || cdev->cpu == first_cpu) { trace_cpuhp_acpi_ejecting_invalid_cpu(cpu_st->selector); break; } trace_cpuhp_acpi_ejecting_cpu(cpu_st->selector); dev = DEVICE(cdev->cpu); hotplug_ctrl = qdev_get_hotplug_handler(dev); hotplug_handler_unplug(hotplug_ctrl, dev, NULL); } break; case ACPI_CPU_CMD_OFFSET_WR: trace_cpuhp_acpi_write_cmd(cpu_st->selector, data); if (data < CPHP_CMD_MAX) { cpu_st->command = data; if (cpu_st->command == CPHP_GET_NEXT_CPU_WITH_EVENT_CMD) { uint32_t iter = cpu_st->selector; do { cdev = &cpu_st->devs[iter]; if (cdev->is_inserting || cdev->is_removing) { cpu_st->selector = iter; trace_cpuhp_acpi_cpu_has_events(cpu_st->selector, cdev->is_inserting, cdev->is_removing); break; } iter = iter + 1 < cpu_st->dev_count ? iter + 1 : 0; } while (iter != cpu_st->selector); } } break; case ACPI_CPU_CMD_DATA_OFFSET_RW: switch (cpu_st->command) { case CPHP_OST_EVENT_CMD: { cdev = &cpu_st->devs[cpu_st->selector]; cdev->ost_event = data; trace_cpuhp_acpi_write_ost_ev(cpu_st->selector, cdev->ost_event); break; } case CPHP_OST_STATUS_CMD: { cdev = &cpu_st->devs[cpu_st->selector]; cdev->ost_status = data; info = acpi_cpu_device_status(cpu_st->selector, cdev); qapi_event_send_acpi_device_ost(info); qapi_free_ACPIOSTInfo(info); trace_cpuhp_acpi_write_ost_status(cpu_st->selector, cdev->ost_status); break; } default: break; } break; default: break; } }