- Rename the ACPI_CAP to ACPI_PDC according to Intel's document.
While I'm here, update the document revision.
- Remove unapplied comment about _OSC and _PDC's revision; Intel's
document states clearly that it should be 1
- Fix the 'Count' argument for _OSC evaluation; the intergers in
'Capabilities buffer' argument is 2
- Fix the buffer length of _OSC's 'Capabilities buffer'; we only
pass 2 intergers.
- Perfer _OSC evaluation, fall back to _PDC evaluation only if _OSC
evaluation fails.
- Add MD cpu features, so MD code could deliver proper settings.
For AMD CPUs, the old configuration just works (AMD actually has
no documents about _PDC and _OSC).
For Intel CPUs w/ EST, it looks like P-State's _PCT will appear
only when bit0 (P-State MSR), bit5 (P-State software coordination)
and bit11 (P-State hardware coordination) are turned on.
# Machine-specific code for P-State
SRCS+= acpi_pstate_machdep.c
+# Machine-specific code for CPU
+SRCS+= acpi_cpu_machdep.c
# Machine-specific code such as sleep/wakeup
SRCS+= acpi_machdep.c acpi_wakecode.h
SRCS+= acpi_wakeup.c
struct acpi_cpux_softc *sc = device_get_softc(dev);
ACPI_HANDLE handle;
device_t child;
- int cpu_id;
+ int cpu_id, cpu_features;
struct acpi_softc *acpi_sc;
handle = acpi_get_handle(dev);
return ENOMEM;
}
+ /*
+ * Before calling any CPU methods, collect child driver feature hints
+ * and notify ACPI of them. We support unified SMP power control
+ * so advertise this ourselves. Note this is not the same as independent
+ * SMP control where each CPU can have different settings.
+ */
+ cpu_features = ACPI_PDC_MP_C1PXTX | ACPI_PDC_MP_C2C3;
+ cpu_features |= acpi_cpu_md_features();
+
+ /*
+ * CPU capabilities are specified as a buffer of 32-bit integers:
+ * revision, count, and one or more capabilities.
+ */
+ if (cpu_features) {
+ ACPI_OBJECT_LIST arglist;
+ uint32_t cap_set[3];
+ ACPI_OBJECT arg[4];
+ ACPI_STATUS status;
+
+ /* UUID needed by _OSC evaluation */
+ static uint8_t cpu_oscuuid[16] = {
+ 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
+ 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
+ };
+
+ arglist.Pointer = arg;
+ arglist.Count = 4;
+ arg[0].Type = ACPI_TYPE_BUFFER;
+ arg[0].Buffer.Length = sizeof(cpu_oscuuid);
+ arg[0].Buffer.Pointer = cpu_oscuuid; /* UUID */
+ arg[1].Type = ACPI_TYPE_INTEGER;
+ arg[1].Integer.Value = 1; /* revision */
+ arg[2].Type = ACPI_TYPE_INTEGER;
+ arg[2].Integer.Value = 2; /* # of capabilities integers */
+ arg[3].Type = ACPI_TYPE_BUFFER;
+ arg[3].Buffer.Length = sizeof(cap_set[0]) * 2; /* capabilities buffer */
+ arg[3].Buffer.Pointer = (uint8_t *)cap_set;
+ cap_set[0] = 0;
+ cap_set[1] = cpu_features;
+ status = AcpiEvaluateObject(handle, "_OSC", &arglist, NULL);
+
+ if (!ACPI_SUCCESS(status)) {
+ if (bootverbose)
+ device_printf(dev, "_OSC failed, use _PDC\n");
+
+ arglist.Pointer = arg;
+ arglist.Count = 1;
+ arg[0].Type = ACPI_TYPE_BUFFER;
+ arg[0].Buffer.Length = sizeof(cap_set);
+ arg[0].Buffer.Pointer = (uint8_t *)cap_set;
+ cap_set[0] = 1; /* revision */
+ cap_set[1] = 1; /* # of capabilities integers */
+ cap_set[2] = cpu_features;
+ AcpiEvaluateObject(handle, "_PDC", &arglist, NULL);
+ }
+ }
+
child = BUS_ADD_CHILD(dev, dev, 0, "cpu_cst", -1);
if (child == NULL)
return ENXIO;
struct sysctl_oid *pcpu_sysctl_tree; /* hw.acpi.cpuX */
};
+uint32_t acpi_cpu_md_features(void);
+
#endif /* !__ACPI_CPU_H__ */
struct acpi_cx cpu_cx_states[MAX_CX_STATES];
int cpu_cx_count; /* Number of valid Cx states. */
int cpu_prev_sleep;/* Last idle sleep duration. */
- int cpu_features; /* Child driver supported features. */
/* Runtime state. */
int cpu_non_c3; /* Index of lowest non-C3 state. */
u_int cpu_cx_stats[MAX_CX_STATES];/* Cx usage history. */
acpi_cpu_cst_attach(device_t dev)
{
ACPI_BUFFER buf;
- ACPI_OBJECT arg[4], *obj;
- ACPI_OBJECT_LIST arglist;
+ ACPI_OBJECT *obj;
struct mdglobaldata *md;
struct acpi_cpu_softc *sc;
ACPI_STATUS status;
- u_int features;
- int cpu_id, drv_count, i;
- driver_t **drivers;
- uint32_t cap_set[3];
-
- /* UUID needed by _OSC evaluation */
- static uint8_t cpu_oscuuid[16] = { 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29,
- 0xBE, 0x47, 0x9E, 0xBD, 0xD8, 0x70,
- 0x58, 0x71, 0x39, 0x53 };
+ int cpu_id;
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cpu_startup, NULL);
}
- /*
- * Before calling any CPU methods, collect child driver feature hints
- * and notify ACPI of them. We support unified SMP power control
- * so advertise this ourselves. Note this is not the same as independent
- * SMP control where each CPU can have different settings.
- */
- sc->cpu_features = ACPI_CAP_SMP_SAME | ACPI_CAP_SMP_SAME_C3;
- if (devclass_get_drivers(acpi_cpu_cst_devclass,
- &drivers, &drv_count) == 0) {
- for (i = 0; i < drv_count; i++) {
- if (ACPI_GET_FEATURES(drivers[i], &features) == 0)
- sc->cpu_features |= features;
- }
- kfree(drivers, M_TEMP);
- }
-
- /*
- * CPU capabilities are specified as a buffer of 32-bit integers:
- * revision, count, and one or more capabilities. The revision of
- * "1" is not specified anywhere but seems to match Linux.
- */
- if (sc->cpu_features) {
- arglist.Pointer = arg;
- arglist.Count = 1;
- arg[0].Type = ACPI_TYPE_BUFFER;
- arg[0].Buffer.Length = sizeof(cap_set);
- arg[0].Buffer.Pointer = (uint8_t *)cap_set;
- cap_set[0] = 1; /* revision */
- cap_set[1] = 1; /* number of capabilities integers */
- cap_set[2] = sc->cpu_features;
- AcpiEvaluateObject(sc->cpu_handle, "_PDC", &arglist, NULL);
-
- /*
- * On some systems we need to evaluate _OSC so that the ASL
- * loads the _PSS and/or _PDC methods at runtime.
- *
- * TODO: evaluate failure of _OSC.
- */
- arglist.Pointer = arg;
- arglist.Count = 4;
- arg[0].Type = ACPI_TYPE_BUFFER;
- arg[0].Buffer.Length = sizeof(cpu_oscuuid);
- arg[0].Buffer.Pointer = cpu_oscuuid; /* UUID */
- arg[1].Type = ACPI_TYPE_INTEGER;
- arg[1].Integer.Value = 1; /* revision */
- arg[2].Type = ACPI_TYPE_INTEGER;
- arg[2].Integer.Value = 1; /* count */
- arg[3].Type = ACPI_TYPE_BUFFER;
- arg[3].Buffer.Length = sizeof(cap_set); /* Capabilities buffer */
- arg[3].Buffer.Pointer = (uint8_t *)cap_set;
- cap_set[0] = 0;
- AcpiEvaluateObject(sc->cpu_handle, "_OSC", &arglist, NULL);
- }
-
/* Probe for Cx state support. */
acpi_cpu_cx_probe(sc);
* Various features and capabilities for the acpi_get_features() method.
* In particular, these are used for the ACPI 3.0 _PDC and _OSC methods.
* See the Intel document titled "Processor Driver Capabilities Bit
- * Definitions", number 302223-002.
+ * Definitions", number 302223-005.
*/
-#define ACPI_CAP_PERF_MSRS (1 << 0) /* Intel SpeedStep PERF_CTL MSRs */
-#define ACPI_CAP_C1_IO_HALT (1 << 1) /* Intel C1 "IO then halt" sequence */
-#define ACPI_CAP_THR_MSRS (1 << 2) /* Intel OnDemand throttling MSRs */
-#define ACPI_CAP_SMP_SAME (1 << 3) /* MP C1, Px, and Tx (all the same) */
-#define ACPI_CAP_SMP_SAME_C3 (1 << 4) /* MP C2 and C3 (all the same) */
-#define ACPI_CAP_SMP_DIFF_PX (1 << 5) /* MP Px (different, using _PSD) */
-#define ACPI_CAP_SMP_DIFF_CX (1 << 6) /* MP Cx (different, using _CSD) */
-#define ACPI_CAP_SMP_DIFF_TX (1 << 7) /* MP Tx (different, using _TSD) */
-#define ACPI_CAP_SMP_C1_NATIVE (1 << 8) /* MP C1 support other than halt */
+#define ACPI_PDC_PX_MSR (1 << 0) /* Intel SpeedStep PERF_CTL MSRs */
+#define ACPI_PDC_MP_C1_IO_HALT (1 << 1) /* Intel C1 "IO then halt" sequence */
+#define ACPI_PDC_TX_MSR (1 << 2) /* Intel OnDemand throttling MSRs */
+#define ACPI_PDC_MP_C1PXTX (1 << 3) /* MP C1, Px, and Tx */
+#define ACPI_PDC_MP_C2C3 (1 << 4) /* MP C2 and C3 */
+#define ACPI_PDC_MP_PX_SWCORD (1 << 5) /* MP Px, using _PSD */
+#define ACPI_PDC_MP_CX_SWCORD (1 << 6) /* MP Cx, using _CSD */
+#define ACPI_PDC_MP_TX_SWCORD (1 << 7) /* MP Tx, using _TSD */
+#define ACPI_PDC_MP_C1_NATIVE (1 << 8) /* MP C1 support other than halt */
+#define ACPI_PDC_MP_C2C3_NATIVE (1 << 9) /* MP C2 and C3 support */
+#define ACPI_PDC_PX_HWCORD (1 << 11)/* Hardware coordination of Px */
/*
* Quirk flags.
--- /dev/null
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+
+#include <machine/cputypes.h>
+#include <machine/md_var.h>
+#include <machine/specialreg.h>
+
+#include "acpi.h"
+#include "acpivar.h"
+#include "acpi_cpu.h"
+
+uint32_t
+acpi_cpu_md_features(void)
+{
+ if (cpu_vendor_id == CPU_VENDOR_INTEL) {
+ if (cpu_feature2 & CPUID2_EST) {
+ return (ACPI_PDC_PX_MSR |
+ ACPI_PDC_MP_PX_SWCORD |
+ ACPI_PDC_PX_HWCORD);
+ }
+ }
+ return 0;
+}
--- /dev/null
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+
+#include <machine/cputypes.h>
+#include <machine/md_var.h>
+#include <machine/specialreg.h>
+
+#include "acpi.h"
+#include "acpivar.h"
+#include "acpi_cpu.h"
+
+uint32_t
+acpi_cpu_md_features(void)
+{
+ if (cpu_vendor_id == CPU_VENDOR_INTEL) {
+ if (cpu_feature2 & CPUID2_EST) {
+ return (ACPI_PDC_PX_MSR |
+ ACPI_PDC_MP_PX_SWCORD |
+ ACPI_PDC_PX_HWCORD);
+ }
+ }
+ return 0;
+}