Exemple #1
0
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;
    }

}
Exemple #2
0
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;
    }
}