Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F157665401
D34841.id104762.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
17 KB
Referenced Files
None
Subscribers
None
D34841.id104762.diff
View Options
Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -3504,6 +3504,7 @@
dev/xen/bus/xenpv.c optional xenhvm
dev/xen/console/xen_console.c optional xenhvm
dev/xen/control/control.c optional xenhvm
+dev/xen/cpu/xen_acpi_cpu.c optional xenhvm
dev/xen/efi/pvefi.c optional xenhvm efirt
dev/xen/grant_table/grant_table.c optional xenhvm
dev/xen/netback/netback.c optional xenhvm
Index: sys/contrib/xen/platform.h
===================================================================
--- sys/contrib/xen/platform.h
+++ sys/contrib/xen/platform.h
@@ -465,7 +465,11 @@
uint32_t state_count; /* total available performance states */
XEN_GUEST_HANDLE(xen_processor_px_t) states;
struct xen_psd_package domain_info;
- uint32_t shared_type; /* coordination type of this processor */
+ /* Coordination type of this processor */
+#define XEN_CPUPERF_SHARED_TYPE_HW 1 /* HW does needed coordination */
+#define XEN_CPUPERF_SHARED_TYPE_ALL 2 /* All dependent CPUs should set freq */
+#define XEN_CPUPERF_SHARED_TYPE_ANY 3 /* Freq can be set from any dependent CPU */
+ uint32_t shared_type;
};
typedef struct xen_processor_performance xen_processor_performance_t;
DEFINE_XEN_GUEST_HANDLE(xen_processor_performance_t);
Index: sys/dev/acpica/acpi_cpu.c
===================================================================
--- sys/dev/acpica/acpi_cpu.c
+++ sys/dev/acpica/acpi_cpu.c
@@ -300,7 +300,7 @@
device_quiet_children(dev);
}
- return (0);
+ return (BUS_PROBE_DEFAULT);
}
static int
Index: sys/dev/xen/cpu/xen_acpi_cpu.c
===================================================================
--- /dev/null
+++ sys/dev/xen/cpu/xen_acpi_cpu.c
@@ -0,0 +1,589 @@
+/*-
+ * Copyright (c) 2022 Citrix Systems R&D
+ * Copyright (c) 2003-2005 Nate Lawson (SDG)
+ * Copyright (c) 2001 Michael Smith
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_acpi.h"
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/pcpu.h>
+#include <sys/power.h>
+#include <sys/proc.h>
+#include <sys/sched.h>
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
+
+#include <dev/acpica/acpivar.h>
+
+#include <xen/xen-os.h>
+
+#define ACPI_DOMAIN_COORD_TYPE_SW_ALL 0xfc
+#define ACPI_DOMAIN_COORD_TYPE_SW_ANY 0xfd
+#define ACPI_DOMAIN_COORD_TYPE_HW_ALL 0xfe
+
+#define ACPI_NOTIFY_PERF_STATES 0x80 /* _PSS changed. */
+#define ACPI_NOTIFY_CX_STATES 0x81 /* _CST changed. */
+
+static MALLOC_DEFINE(M_XENACPI, "xen_acpi", "Xen CPU ACPI forwarder");
+
+/* Hooks for the ACPI CA debugging infrastructure */
+#define _COMPONENT ACPI_PROCESSOR
+ACPI_MODULE_NAME("PROCESSOR")
+
+struct xen_acpi_cpu_softc {
+ device_t cpu_dev;
+ ACPI_HANDLE cpu_handle;
+ uint32_t cpu_acpi_id;
+ struct xen_processor_cx *cpu_cx_states;
+ unsigned int cpu_cx_count;
+ struct xen_processor_px *cpu_px_states;
+ unsigned int cpu_px_count;
+ struct xen_pct_register control_register;
+ struct xen_pct_register status_register;
+ struct xen_psd_package psd;
+};
+
+#define CPUDEV_DEVICE_ID "ACPI0007"
+
+ACPI_SERIAL_DECL(cpu, "ACPI CPU");
+
+static int
+acpi_get_gas(const ACPI_OBJECT *res, unsigned int idx,
+ ACPI_GENERIC_ADDRESS *gas)
+{
+ ACPI_OBJECT *obj = &res->Package.Elements[idx];
+
+ if (obj == NULL || obj->Type != ACPI_TYPE_BUFFER ||
+ obj->Buffer.Length < sizeof(ACPI_GENERIC_ADDRESS) + 3)
+ return (EINVAL);
+
+ memcpy(gas, obj->Buffer.Pointer + 3, sizeof(*gas));
+
+ return (0);
+}
+
+static int
+acpi_get_pct(const ACPI_OBJECT *res, unsigned int idx,
+ struct xen_pct_register *reg)
+{
+ struct {
+ uint8_t descriptor;
+ uint16_t length;
+ ACPI_GENERIC_ADDRESS gas;
+ } __packed raw;
+ const ACPI_OBJECT *obj = &res->Package.Elements[idx];
+
+ if (obj == NULL || obj->Type != ACPI_TYPE_BUFFER ||
+ obj->Buffer.Length < sizeof(raw))
+ return (EINVAL);
+
+ memcpy(&raw, obj->Buffer.Pointer, sizeof(raw));
+ reg->descriptor = raw.descriptor;
+ reg->length = raw.length;
+ reg->space_id = raw.gas.SpaceId;
+ reg->bit_width = raw.gas.BitWidth;
+ reg->bit_offset = raw.gas.BitOffset;
+ reg->reserved = raw.gas.AccessWidth;
+ reg->address = raw.gas.Address;
+
+ return (0);
+}
+
+static int
+xen_upload_cx(struct xen_acpi_cpu_softc *sc)
+{
+ struct xen_platform_op op = {
+ .cmd = XENPF_set_processor_pminfo,
+ .interface_version = XENPF_INTERFACE_VERSION,
+ .u.set_pminfo.id = sc->cpu_acpi_id,
+ .u.set_pminfo.type = XEN_PM_CX,
+ .u.set_pminfo.u.power.count = sc->cpu_cx_count,
+ .u.set_pminfo.u.power.flags.has_cst = 1,
+ /* Ignore bm_check and bm_control, Xen will set those. */
+ };
+ int error;
+
+ set_xen_guest_handle(op.u.set_pminfo.u.power.states, sc->cpu_cx_states);
+
+ error = HYPERVISOR_platform_op(&op);
+ if (error != 0)
+ device_printf(sc->cpu_dev,
+ "HYPERVISOR_platform_op CX upload failed: %d\n", error);
+ return (error);
+}
+
+static int
+xen_upload_px(struct xen_acpi_cpu_softc *sc)
+{
+ struct xen_platform_op op = {
+ .cmd = XENPF_set_processor_pminfo,
+ .interface_version = XENPF_INTERFACE_VERSION,
+ .u.set_pminfo.id = sc->cpu_acpi_id,
+ .u.set_pminfo.type = XEN_PM_PX,
+ .u.set_pminfo.u.perf.state_count = sc->cpu_px_count,
+ };
+ ACPI_STATUS status;
+ int error;
+
+ status = acpi_GetInteger(sc->cpu_handle, "_PPC",
+ &op.u.set_pminfo.u.perf.platform_limit);
+ if (ACPI_FAILURE(status)) {
+ device_printf(sc->cpu_dev, "missing _PPC object\n");
+ return (ENXIO);
+ }
+ op.u.set_pminfo.u.perf.flags |= XEN_PX_PPC;
+
+ op.u.set_pminfo.u.perf.control_register = sc->control_register;
+ op.u.set_pminfo.u.perf.status_register = sc->status_register;
+ op.u.set_pminfo.u.perf.flags |= XEN_PX_PCT;
+
+ set_xen_guest_handle(op.u.set_pminfo.u.perf.states, sc->cpu_px_states);
+ op.u.set_pminfo.u.perf.flags |= XEN_PX_PSS;
+
+ op.u.set_pminfo.u.perf.domain_info = sc->psd;
+ op.u.set_pminfo.u.perf.flags |= XEN_PX_PSD;
+
+ /*
+ * NB: it's unclear the exact purpose of the shared_type field, or why
+ * it can't be calculated by Xen itself. Naively set it here to allow
+ * the upload to succeed.
+ */
+ switch (sc->psd.coord_type) {
+ case ACPI_DOMAIN_COORD_TYPE_SW_ALL:
+ op.u.set_pminfo.u.perf.shared_type =
+ XEN_CPUPERF_SHARED_TYPE_ALL;
+ break;
+
+ case ACPI_DOMAIN_COORD_TYPE_HW_ALL:
+ op.u.set_pminfo.u.perf.shared_type =
+ XEN_CPUPERF_SHARED_TYPE_HW;
+ break;
+
+ case ACPI_DOMAIN_COORD_TYPE_SW_ANY:
+ op.u.set_pminfo.u.perf.shared_type =
+ XEN_CPUPERF_SHARED_TYPE_ANY;
+ break;
+ default:
+ device_printf(sc->cpu_dev, "unknown coordination type %#lx\n",
+ sc->psd.coord_type);
+ return (EINVAL);
+ }
+
+ error = HYPERVISOR_platform_op(&op);
+ if (error != 0)
+ device_printf(sc->cpu_dev,
+ "HYPERVISOR_platform_op PX upload failed: %d\n", error);
+ return (error);
+}
+
+static int
+acpi_set_pdc(const struct xen_acpi_cpu_softc *sc)
+{
+ struct xen_platform_op op = {
+ .cmd = XENPF_set_processor_pminfo,
+ .interface_version = XENPF_INTERFACE_VERSION,
+ .u.set_pminfo.id = -1,
+ .u.set_pminfo.type = XEN_PM_PDC,
+ };
+ uint32_t pdc[3] = {1, 1};
+ ACPI_OBJECT arg = {
+ .Buffer.Type = ACPI_TYPE_BUFFER,
+ .Buffer.Length = sizeof(pdc),
+ .Buffer.Pointer = (uint8_t *)pdc,
+ };
+ ACPI_OBJECT_LIST arglist = {
+ .Pointer = &arg,
+ .Count = 1,
+ };
+ ACPI_STATUS status;
+ int error;
+
+ set_xen_guest_handle(op.u.set_pminfo.u.pdc, pdc);
+ error = HYPERVISOR_platform_op(&op);
+ if (error != 0) {
+ device_printf(sc->cpu_dev,
+ "unable to get _PDC features from Xen: %d\n", error);
+ return (error);
+ }
+
+ status = AcpiEvaluateObject(sc->cpu_handle, "_PDC", &arglist, NULL);
+ if (ACPI_FAILURE(status)) {
+ device_printf(sc->cpu_dev, "unable to execute _PDC - %s\n",
+ AcpiFormatException(status));
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+/*
+ * Parse a _CST package and set up its Cx states. Since the _CST object
+ * can change dynamically, our notify handler may call this function
+ * to clean up and probe the new _CST package.
+ */
+static int
+acpi_fetch_cx(struct xen_acpi_cpu_softc *sc)
+{
+ ACPI_STATUS status;
+ ACPI_BUFFER buf = {
+ .Length = ACPI_ALLOCATE_BUFFER,
+ };
+ ACPI_OBJECT *top;
+ uint32_t count;
+ unsigned int i;
+
+ status = AcpiEvaluateObject(sc->cpu_handle, "_CST", NULL, &buf);
+ if (ACPI_FAILURE(status)) {
+ device_printf(sc->cpu_dev, "missing _CST object\n");
+ return (ENXIO);
+ }
+
+ /* _CST is a package with a count and at least one Cx package. */
+ top = (ACPI_OBJECT *)buf.Pointer;
+ if (!ACPI_PKG_VALID(top, 2) || acpi_PkgInt32(top, 0, &count) != 0) {
+ device_printf(sc->cpu_dev, "invalid _CST package\n");
+ AcpiOsFree(buf.Pointer);
+ return (ENXIO);
+ }
+ if (count != top->Package.Count - 1) {
+ device_printf(sc->cpu_dev,
+ "invalid _CST state count (%u != %u)\n",
+ count, top->Package.Count - 1);
+ count = top->Package.Count - 1;
+ }
+
+ sc->cpu_cx_states = mallocarray(count, sizeof(struct xen_processor_cx),
+ M_XENACPI, M_WAITOK | M_ZERO);
+
+ sc->cpu_cx_count = 0;
+ for (i = 0; i < count; i++) {
+ uint32_t type;
+ ACPI_GENERIC_ADDRESS gas;
+ ACPI_OBJECT *pkg = &top->Package.Elements[i + 1];
+ struct xen_processor_cx *cx_ptr =
+ &sc->cpu_cx_states[sc->cpu_cx_count];
+
+ if (!ACPI_PKG_VALID(pkg, 4) ||
+ acpi_PkgInt32(pkg, 1, &type) != 0 ||
+ acpi_PkgInt32(pkg, 2, &cx_ptr->latency) != 0 ||
+ acpi_PkgInt32(pkg, 3, &cx_ptr->power) != 0 ||
+ acpi_get_gas(pkg, 0, &gas) != 0) {
+ device_printf(sc->cpu_dev,
+ "skipping invalid _CST %u package\n",
+ i + 1);
+ continue;
+ }
+
+ cx_ptr->type = type;
+ cx_ptr->reg.space_id = gas.SpaceId;
+ cx_ptr->reg.bit_width = gas.BitWidth;
+ cx_ptr->reg.bit_offset = gas.BitOffset;
+ cx_ptr->reg.access_size = gas.AccessWidth;
+ cx_ptr->reg.address = gas.Address;
+ sc->cpu_cx_count++;
+ }
+ AcpiOsFree(buf.Pointer);
+
+ if (sc->cpu_cx_count == 0) {
+ device_printf(sc->cpu_dev, "no valid _CST package found\n");
+ free(sc->cpu_cx_states, M_XENACPI);
+ sc->cpu_cx_states = NULL;
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+/* Probe and setup any valid performance states (Px). */
+static int
+acpi_fetch_px(struct xen_acpi_cpu_softc *sc)
+{
+ ACPI_BUFFER buf = {
+ .Length = ACPI_ALLOCATE_BUFFER,
+ };
+ ACPI_OBJECT *pkg, *res;
+ ACPI_STATUS status;
+ unsigned int count, i;
+ int error;
+ uint64_t *p;
+
+ /* _PSS */
+ status = AcpiEvaluateObject(sc->cpu_handle, "_PSS", NULL, &buf);
+ if (ACPI_FAILURE(status)) {
+ device_printf(sc->cpu_dev, "missing _PSS object\n");
+ return (ENXIO);
+ }
+
+ pkg = (ACPI_OBJECT *)buf.Pointer;
+ if (!ACPI_PKG_VALID(pkg, 1)) {
+ device_printf(sc->cpu_dev, "invalid top level _PSS package\n");
+ goto error;
+ }
+ count = pkg->Package.Count;
+
+ sc->cpu_px_states = mallocarray(count, sizeof(struct xen_processor_px),
+ M_XENACPI, M_WAITOK | M_ZERO);
+
+ /*
+ * Each state is a package of {CoreFreq, Power, TransitionLatency,
+ * BusMasterLatency, ControlVal, StatusVal}, sorted from highest
+ * performance to lowest.
+ */
+ sc->cpu_px_count = 0;
+ for (i = 0; i < count; i++) {
+ unsigned int j;
+
+ res = &pkg->Package.Elements[i];
+ if (!ACPI_PKG_VALID(res, 6)) {
+ device_printf(sc->cpu_dev,
+ "invalid _PSS package idx %u\n", i);
+ continue;
+ }
+
+ /* Parse the rest of the package into the struct. */
+ p = (uint64_t *)&sc->cpu_px_states[sc->cpu_px_count++];
+ for (j = 0; j < 6; j++, p++)
+ acpi_PkgInt(res, j, p);
+ }
+
+ /* No valid Px state found so give up. */
+ if (sc->cpu_px_count == 0) {
+ device_printf(sc->cpu_dev, "no valid _PSS package found\n");
+ goto error;
+ }
+ AcpiOsFree(buf.Pointer);
+
+ /* _PCT */
+ buf.Pointer = NULL;
+ buf.Length = ACPI_ALLOCATE_BUFFER;
+ status = AcpiEvaluateObject(sc->cpu_handle, "_PCT", NULL, &buf);
+ if (ACPI_FAILURE(status)) {
+ device_printf(sc->cpu_dev, "missing _PCT object\n");
+ goto error;
+ }
+
+ /* Check the package of two registers, each a Buffer in GAS format. */
+ pkg = (ACPI_OBJECT *)buf.Pointer;
+ if (!ACPI_PKG_VALID(pkg, 2)) {
+ device_printf(sc->cpu_dev, "invalid top level _PCT package\n");
+ goto error;
+ }
+
+ error = acpi_get_pct(pkg, 0, &sc->control_register);
+ if (error != 0) {
+ device_printf(sc->cpu_dev,
+ "unable to fetch _PCT control register: %d\n", error);
+ goto error;
+ }
+ error = acpi_get_pct(pkg, 1, &sc->status_register);
+ if (error != 0) {
+ device_printf(sc->cpu_dev,
+ "unable to fetch _PCT status register: %d\n", error);
+ goto error;
+ }
+ AcpiOsFree(buf.Pointer);
+
+ /* _PSD */
+ buf.Pointer = NULL;
+ buf.Length = ACPI_ALLOCATE_BUFFER;
+ status = AcpiEvaluateObject(sc->cpu_handle, "_PSD", NULL, &buf);
+ if (ACPI_FAILURE(status)) {
+ device_printf(sc->cpu_dev, "missing _PSD object\n");
+ goto error;
+ }
+
+ pkg = (ACPI_OBJECT *)buf.Pointer;
+ if (!ACPI_PKG_VALID(pkg, 1)) {
+ device_printf(sc->cpu_dev, "invalid top level _PSD package\n");
+ goto error;
+ }
+
+ res = &pkg->Package.Elements[0];
+ if (!ACPI_PKG_VALID(res, 5)) {
+ printf("invalid _PSD package\n");
+ goto error;
+ }
+
+ p = (uint64_t *)&sc->psd;
+ for (i = 0; i < 5; i++, p++)
+ acpi_PkgInt(res, i, p);
+ AcpiOsFree(buf.Pointer);
+
+ return (0);
+
+error:
+ if (buf.Pointer != NULL)
+ AcpiOsFree(buf.Pointer);
+ if (sc->cpu_px_states != NULL) {
+ free(sc->cpu_px_states, M_XENACPI);
+ sc->cpu_px_states = NULL;
+ }
+ return (ENXIO);
+}
+
+static void
+acpi_notify(ACPI_HANDLE h, UINT32 notify, void *context)
+{
+ struct xen_acpi_cpu_softc *sc = context;
+
+ switch (notify) {
+ case ACPI_NOTIFY_PERF_STATES:
+ if (acpi_fetch_px(sc) != 0)
+ break;
+ xen_upload_px(sc);
+ free(sc->cpu_px_states, M_XENACPI);
+ sc->cpu_px_states = NULL;
+ break;
+
+ case ACPI_NOTIFY_CX_STATES:
+ if (acpi_fetch_cx(sc) != 0)
+ break;
+ xen_upload_cx(sc);
+ free(sc->cpu_cx_states, M_XENACPI);
+ sc->cpu_cx_states = NULL;
+ break;
+ }
+}
+
+static int
+xen_acpi_cpu_probe(device_t dev)
+{
+ static char *cpudev_ids[] = { CPUDEV_DEVICE_ID, NULL };
+ ACPI_OBJECT_TYPE type = acpi_get_type(dev);
+
+ if (!xen_initial_domain())
+ return (ENXIO);
+ if (type != ACPI_TYPE_PROCESSOR && type != ACPI_TYPE_DEVICE)
+ return (ENXIO);
+ if (type == ACPI_TYPE_DEVICE &&
+ ACPI_ID_PROBE(device_get_parent(dev), dev, cpudev_ids, NULL) >= 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "XEN ACPI CPU");
+
+ /*
+ * Use SPECIFIC because when running as a Xen dom0 the ACPI PROCESSOR
+ * data is the native one, and needs to be forwarded to Xen but not
+ * used by FreeBSD itself.
+ */
+ return (BUS_PROBE_SPECIFIC);
+}
+
+static int
+xen_acpi_cpu_attach(device_t dev)
+{
+ struct xen_acpi_cpu_softc *sc = device_get_softc(dev);
+ ACPI_STATUS status;
+ int error;
+
+ sc->cpu_dev = dev;
+ sc->cpu_handle = acpi_get_handle(dev);
+
+ if (acpi_get_type(dev) == ACPI_TYPE_PROCESSOR) {
+ ACPI_BUFFER buf = {
+ .Length = ACPI_ALLOCATE_BUFFER,
+ };
+ ACPI_OBJECT *obj;
+
+ status = AcpiEvaluateObject(sc->cpu_handle, NULL, NULL, &buf);
+ if (ACPI_FAILURE(status)) {
+ device_printf(dev,
+ "attach failed to get Processor obj - %s\n",
+ AcpiFormatException(status));
+ return (ENXIO);
+ }
+ obj = (ACPI_OBJECT *)buf.Pointer;
+ sc->cpu_acpi_id = obj->Processor.ProcId;
+ AcpiOsFree(obj);
+ } else {
+ KASSERT(acpi_get_type(dev) == ACPI_TYPE_DEVICE,
+ ("Unexpected ACPI object"));
+ status = acpi_GetInteger(sc->cpu_handle, "_UID",
+ &sc->cpu_acpi_id);
+ if (ACPI_FAILURE(status)) {
+ device_printf(dev, "device object has bad value - %s\n",
+ AcpiFormatException(status));
+ return (ENXIO);
+ }
+ }
+
+ /*
+ * Install the notify handler now: even if we fail to parse or upload
+ * the states here it shouldn't prevent us from attempting to parse
+ * further updates.
+ */
+ AcpiInstallNotifyHandler(sc->cpu_handle, ACPI_DEVICE_NOTIFY,
+ acpi_notify, sc);
+
+ /* Don't return errors, or else the device will keep getting probed. */
+ error = acpi_set_pdc(sc);
+ if (error != 0)
+ return (0);
+
+ error = acpi_fetch_px(sc);
+ if (error != 0)
+ return (0);
+ error = xen_upload_px(sc);
+ free(sc->cpu_px_states, M_XENACPI);
+ sc->cpu_px_states = NULL;
+ if (error != 0)
+ return (0);
+
+ error = acpi_fetch_cx(sc);
+ if (error != 0)
+ return (0);
+ xen_upload_cx(sc);
+ free(sc->cpu_cx_states, M_XENACPI);
+ sc->cpu_cx_states = NULL;
+
+ return (0);
+}
+
+static device_method_t xen_acpi_cpu_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, xen_acpi_cpu_probe),
+ DEVMETHOD(device_attach, xen_acpi_cpu_attach),
+
+ DEVMETHOD_END
+};
+
+static driver_t xen_acpi_cpu_driver = {
+ "xen cpu",
+ xen_acpi_cpu_methods,
+ sizeof(struct xen_acpi_cpu_softc),
+};
+
+static devclass_t xen_acpi_cpu_devclass;
+DRIVER_MODULE(xen_cpu, acpi, xen_acpi_cpu_driver, xen_acpi_cpu_devclass, 0, 0);
+MODULE_DEPEND(xen_cpu, acpi, 1, 1, 1);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, May 24, 9:04 PM (3 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33486876
Default Alt Text
D34841.id104762.diff (17 KB)
Attached To
Mode
D34841: xen/acpi: upload Cx and Px data to Xen
Attached
Detach File
Event Timeline
Log In to Comment