staticint no_hypercall;
MODULE_PARM_DESC(off, "Inhibit the hypercall.");
module_param_named(off, no_hypercall, int, 0400);
/* *Note:Donotconverttheacpi_id*belowtocpumask_var_torusecpumask_bit *-asthoseshrinktonr_cpu_bits(whichisdependentonpossible_cpu),which *canbelessthanwhatwewanttoputin.Insteadusethe'nr_acpi_bits' *whichisdynamicallycomputedbasedontheMADTorx2APICtable.
*/ staticunsignedint nr_acpi_bits; /* Mutex to protect the acpi_ids_done - for CPU hotplug use. */ static DEFINE_MUTEX(acpi_ids_mutex); /* Which ACPI ID we have processed from 'struct acpi_processor'. */ staticunsignedlong *acpi_ids_done; /* Which ACPI ID exist in the SSDT/DSDT processor definitions. */ staticunsignedlong *acpi_id_present; /* And if there is an _CST definition (or a PBLK) for the ACPI IDs */ staticunsignedlong *acpi_id_cst_present; /* Which ACPI P-State dependencies for a enumerated processor */ staticstruct acpi_psd_package *acpi_psd;
staticint 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; unsignedint 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_states = kcalloc(_pr->performance->state_count, sizeof(struct xen_processor_px), GFP_KERNEL); if (!dst_states) return ERR_PTR(-ENOMEM);
dst_perf->state_count = _pr->performance->state_count; for (i = 0; i < _pr->performance->state_count; i++) { /* Fortunatly for us, they are both the same size */
memcpy(&(dst_states[i]), &(_pr->performance->states[i]), sizeof(struct acpi_processor_px));
} return dst_states;
} staticint xen_copy_psd_data(struct acpi_processor *_pr, struct xen_processor_performance *dst)
{ struct acpi_psd_package *pdomain;
mutex_lock(&acpi_ids_mutex); if (__test_and_set_bit(_pr->acpi_id, acpi_ids_done)) {
mutex_unlock(&acpi_ids_mutex); return -EBUSY;
} if (_pr->flags.power)
err = push_cxx_to_hypervisor(_pr);
if (_pr->performance && _pr->performance->states)
err |= push_pxx_to_hypervisor(_pr);
mutex_unlock(&acpi_ids_mutex); return err;
} staticunsignedint __init get_max_acpi_id(void)
{ struct xenpf_pcpuinfo *info; struct xen_platform_op op = {
.cmd = XENPF_get_cpuinfo,
.interface_version = XENPF_INTERFACE_VERSION,
}; int ret = 0; unsignedint i, last_cpu, max_acpi_id = 0;
info = &op.u.pcpu_info;
info->xen_cpuid = 0;
ret = HYPERVISOR_platform_op(&op); if (ret) return NR_CPUS;
/* The max_present is the same irregardless of the xen_cpuid */
last_cpu = op.u.pcpu_info.max_present; for (i = 0; i <= last_cpu; i++) {
info->xen_cpuid = i;
ret = HYPERVISOR_platform_op(&op); if (ret) continue;
max_acpi_id = max(info->acpi_id, max_acpi_id);
}
max_acpi_id *= 2; /* Slack for CPU hotplug support. */
pr_debug("Max ACPI ID: %u\n", max_acpi_id); return max_acpi_id;
} /* *Theread_acpi_idandcheck_acpi_idsaretheretosupporttheXen *oddityofvirtualCPUs!=physicalCPUsintheinitialdomain. *Theusercansupply'xen_max_vcpus=X'ontheXenhypervisorline *whichwillbandtheamountofCPUstheinitialdomaincansee. *IngeneralthatisOK,exceptitplayshavocwithanyofthe *for_each_[present|online]_cpumacroswhicharebandedtothevirtual *CPUamount.
*/ static acpi_status
read_acpi_id(acpi_handle handle, u32 lvl, void *context, void **rv)
{
u32 acpi_id;
acpi_status status;
acpi_object_type acpi_type; unsignedlonglong tmp; union acpi_object object = { 0 }; struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
acpi_io_address pblk = 0;
status = acpi_get_type(handle, &acpi_type); if (ACPI_FAILURE(status)) return AE_OK;
switch (acpi_type) { case ACPI_TYPE_PROCESSOR:
status = acpi_evaluate_object(handle, NULL, NULL, &buffer); if (ACPI_FAILURE(status)) return AE_OK;
acpi_id = object.processor.proc_id;
pblk = object.processor.pblk_address; break; case ACPI_TYPE_DEVICE:
status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp); if (ACPI_FAILURE(status)) return AE_OK;
acpi_id = tmp; break; default: return AE_OK;
} if (invalid_phys_cpuid(acpi_get_phys_id(handle,
acpi_type == ACPI_TYPE_DEVICE,
acpi_id))) {
pr_debug("CPU with ACPI ID %u is unavailable\n", acpi_id); return AE_OK;
} /* There are more ACPI Processor objects than in x2APIC or MADT.
* This can happen with incorrect ACPI SSDT declerations. */ if (acpi_id >= nr_acpi_bits) {
pr_debug("max acpi id %u, trying to set %u\n",
nr_acpi_bits - 1, acpi_id); return AE_OK;
} /* OK, There is a ACPI Processor object */
__set_bit(acpi_id, acpi_id_present);
/* It has P-state dependencies */ if (!acpi_processor_get_psd(handle, &acpi_psd[acpi_id])) {
pr_debug("ACPI CPU%u w/ PST:coord_type = %llu domain = %llu\n",
acpi_id, acpi_psd[acpi_id].coord_type,
acpi_psd[acpi_id].domain);
}
status = acpi_evaluate_object(handle, "_CST", NULL, &buffer); if (ACPI_FAILURE(status)) { if (!pblk) return AE_OK;
} /* .. and it has a C-state */
__set_bit(acpi_id, acpi_id_cst_present);
if (acpi_id_present && acpi_id_cst_present) /* OK, done this once .. skip to uploading */ goto upload;
/* All online CPUs have been processed at this stage. Now verify *whetherinfact"onlineCPUs"==physicalCPUs.
*/
acpi_id_present = bitmap_zalloc(nr_acpi_bits, GFP_KERNEL); if (!acpi_id_present) return -ENOMEM;
upload: if (!bitmap_equal(acpi_id_present, acpi_ids_done, nr_acpi_bits)) { unsignedint i;
for_each_set_bit(i, acpi_id_present, nr_acpi_bits) {
pr_backup->acpi_id = i; /* Mask out C-states if there are no _CST or PBLK */
pr_backup->flags.power = test_bit(i, acpi_id_cst_present); /* num_entries is non-zero if we evaluated _PSD */ if (acpi_psd[i].num_entries) {
memcpy(&pr_backup->performance->domain_info,
&acpi_psd[i], sizeof(struct acpi_psd_package));
}
(void)upload_pm_data(pr_backup);
}
}
return0;
}
/* acpi_perf_data is a pointer to percpu data. */ staticstruct acpi_processor_performance __percpu *acpi_perf_data;
staticvoid free_acpi_perf_data(void)
{ int i;
/* Freeing a NULL pointer is OK, and alloc_percpu zeroes. */
for_each_possible_cpu(i)
free_cpumask_var(per_cpu_ptr(acpi_perf_data, i)
->shared_cpu_map);
free_percpu(acpi_perf_data);
}
staticint xen_upload_processor_pm_data(void)
{ struct acpi_processor *pr_backup = NULL; int i; int rc = 0;
pr_info("Uploading Xen processor PM info\n");
for_each_possible_cpu(i) { struct acpi_processor *_pr;
_pr = per_cpu(processors, i /* APIC ID */); if (!_pr) continue;
if (!pr_backup)
pr_backup = kmemdup(_pr, sizeof(*_pr), GFP_KERNEL);
(void)upload_pm_data(_pr);
}
rc = check_acpi_ids(pr_backup);
kfree(pr_backup);
return rc;
}
staticvoid xen_acpi_processor_resume_worker(struct work_struct *dummy)
{ int rc;
bitmap_zero(acpi_ids_done, nr_acpi_bits);
rc = xen_upload_processor_pm_data(); if (rc != 0)
pr_info("ACPI data upload failed, error = %d\n", rc);
}
MODULE_AUTHOR("Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>");
MODULE_DESCRIPTION("Xen ACPI Processor P-states (and Cx) driver which uploads PM data to Xen hypervisor");
MODULE_LICENSE("GPL");
/* We want to be loaded before the CPU freq scaling drivers are loaded.
* They are loaded in late_initcall. */
device_initcall(xen_acpi_processor_init);
module_exit(xen_acpi_processor_exit);
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.