in xen-acpi-processor.c [51:134]
static int push_cxx_to_hypervisor(struct acpi_processor *_pr)
{
struct xen_platform_op op = {
.cmd = XENPF_set_processor_pminfo,
.interface_version = XENPF_INTERFACE_VERSION,
.u.set_pminfo.id = _pr->acpi_id,
.u.set_pminfo.type = XEN_PM_CX,
};
struct xen_processor_cx *dst_cx, *dst_cx_states = NULL;
struct acpi_processor_cx *cx;
unsigned int i, ok;
int ret = 0;
dst_cx_states = kcalloc(_pr->power.count,
sizeof(struct xen_processor_cx), GFP_KERNEL);
if (!dst_cx_states)
return -ENOMEM;
for (ok = 0, i = 1; i <= _pr->power.count; i++) {
cx = &_pr->power.states[i];
if (!cx->valid)
continue;
dst_cx = &(dst_cx_states[ok++]);
dst_cx->reg.space_id = ACPI_ADR_SPACE_SYSTEM_IO;
if (cx->entry_method == ACPI_CSTATE_SYSTEMIO) {
dst_cx->reg.bit_width = 8;
dst_cx->reg.bit_offset = 0;
dst_cx->reg.access_size = 1;
} else {
dst_cx->reg.space_id = ACPI_ADR_SPACE_FIXED_HARDWARE;
if (cx->entry_method == ACPI_CSTATE_FFH) {
/* NATIVE_CSTATE_BEYOND_HALT */
dst_cx->reg.bit_offset = 2;
dst_cx->reg.bit_width = 1; /* VENDOR_INTEL */
}
dst_cx->reg.access_size = 0;
}
dst_cx->reg.address = cx->address;
dst_cx->type = cx->type;
dst_cx->latency = cx->latency;
dst_cx->dpcnt = 0;
set_xen_guest_handle(dst_cx->dp, NULL);
}
if (!ok) {
pr_debug("No _Cx for ACPI CPU %u\n", _pr->acpi_id);
kfree(dst_cx_states);
return -EINVAL;
}
op.u.set_pminfo.power.count = ok;
op.u.set_pminfo.power.flags.bm_control = _pr->flags.bm_control;
op.u.set_pminfo.power.flags.bm_check = _pr->flags.bm_check;
op.u.set_pminfo.power.flags.has_cst = _pr->flags.has_cst;
op.u.set_pminfo.power.flags.power_setup_done =
_pr->flags.power_setup_done;
set_xen_guest_handle(op.u.set_pminfo.power.states, dst_cx_states);
if (!no_hypercall)
ret = HYPERVISOR_platform_op(&op);
if (!ret) {
pr_debug("ACPI CPU%u - C-states uploaded.\n", _pr->acpi_id);
for (i = 1; i <= _pr->power.count; i++) {
cx = &_pr->power.states[i];
if (!cx->valid)
continue;
pr_debug(" C%d: %s %d uS\n",
cx->type, cx->desc, (u32)cx->latency);
}
} else if ((ret != -EINVAL) && (ret != -ENOSYS))
/* EINVAL means the ACPI ID is incorrect - meaning the ACPI
* table is referencing a non-existing CPU - which can happen
* with broken ACPI tables. */
pr_err("(CX): Hypervisor error (%d) for ACPI CPU%u\n",
ret, _pr->acpi_id);
kfree(dst_cx_states);
return ret;
}