Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F162635725
D55606.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D55606.diff
View Options
diff --git a/sys/x86/cpufreq/hwpstate_amd.c b/sys/x86/cpufreq/hwpstate_amd.c
--- a/sys/x86/cpufreq/hwpstate_amd.c
+++ b/sys/x86/cpufreq/hwpstate_amd.c
@@ -552,6 +552,20 @@
return (val);
}
+static void
+hwpstate_pstate_read_limit(int cpu, uint64_t *msr)
+{
+ (void)x86_msr_op(MSR_AMD_10H_11H_LIMIT,
+ MSR_OP_READ | MSR_OP_RENDEZVOUS_ONE | MSR_OP_CPUID(cpu), 0, msr);
+}
+
+static void
+hwpstate_pstate_read_status(int cpu, uint64_t *msr)
+{
+ (void)x86_msr_op(MSR_AMD_10H_11H_STATUS,
+ MSR_OP_READ | MSR_OP_RENDEZVOUS_ONE | MSR_OP_CPUID(cpu), 0, msr);
+}
+
/*
* Go to Px-state on all cpus, considering the limit register (if so
* configured).
@@ -561,11 +575,13 @@
{
sbintime_t sbt;
uint64_t msr;
- int cpu, i, j, limit;
+ int cpu, j, limit;
+
+ cpu = cpu_get_pcpu(dev)->pc_cpuid;
if (hwpstate_pstate_limit) {
/* get the current pstate limit */
- msr = rdmsr(MSR_AMD_10H_11H_LIMIT);
+ hwpstate_pstate_read_limit(cpu, &msr);
limit = AMD_10H_11H_GET_PSTATE_LIMIT(msr);
if (limit > id) {
HWPSTATE_DEBUG(dev, "Restricting requested P%d to P%d "
@@ -574,53 +590,31 @@
}
}
- cpu = curcpu;
HWPSTATE_DEBUG(dev, "setting P%d-state on cpu%d\n", id, cpu);
/* Go To Px-state */
- wrmsr(MSR_AMD_10H_11H_CONTROL, id);
-
- /*
- * We are going to the same Px-state on all cpus.
- * Probably should take _PSD into account.
- */
- CPU_FOREACH(i) {
- if (i == cpu)
- continue;
-
- /* Bind to each cpu. */
- thread_lock(curthread);
- sched_bind(curthread, i);
- thread_unlock(curthread);
- HWPSTATE_DEBUG(dev, "setting P%d-state on cpu%d\n", id, i);
- /* Go To Px-state */
- wrmsr(MSR_AMD_10H_11H_CONTROL, id);
- }
+ x86_msr_op(MSR_AMD_10H_11H_CONTROL,
+ MSR_OP_WRITE | MSR_OP_RENDEZVOUS_ONE | MSR_OP_CPUID(cpu), id, NULL);
/*
* Verify whether each core is in the requested P-state.
*/
if (hwpstate_verify) {
- CPU_FOREACH(i) {
- thread_lock(curthread);
- sched_bind(curthread, i);
- thread_unlock(curthread);
- /* wait loop (100*100 usec is enough ?) */
- for (j = 0; j < 100; j++) {
- /* get the result. not assure msr=id */
- msr = rdmsr(MSR_AMD_10H_11H_STATUS);
- if (msr == id)
- break;
- sbt = SBT_1MS / 10;
- tsleep_sbt(dev, PZERO, "pstate_goto", sbt,
- sbt >> tc_precexp, 0);
- }
- HWPSTATE_DEBUG(dev, "result: P%d-state on cpu%d\n",
- (int)msr, i);
- if (msr != id) {
- HWPSTATE_DEBUG(dev,
- "error: loop is not enough.\n");
- return (ENXIO);
- }
+ /* wait loop (100*100 usec is enough ?) */
+ for (j = 0; j < 100; j++) {
+ /* get the result. not assure msr=id */
+
+ hwpstate_pstate_read_status(cpu, &msr);
+ if (msr == id)
+ break;
+ sbt = SBT_1MS / 10;
+ tsleep_sbt(dev, PZERO, "pstate_goto", sbt,
+ sbt >> tc_precexp, 0);
+ }
+ HWPSTATE_DEBUG(dev, "result: P%d-state on cpu%d\n", (int)msr,
+ cpu);
+ if (msr != id) {
+ HWPSTATE_DEBUG(dev, "error: loop is not enough.\n");
+ return (ENXIO);
}
}
@@ -670,7 +664,6 @@
pc = cpu_get_pcpu(dev);
if (pc == NULL)
return (ENXIO);
-
memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
cf->dev = dev;
if ((ret = cpu_est_clockrate(pc->pc_cpuid, &rate)))
@@ -685,13 +678,14 @@
struct hwpstate_softc *sc;
struct hwpstate_setting set;
uint64_t msr;
+ int cpu;
sc = device_get_softc(dev);
- msr = rdmsr(MSR_AMD_10H_11H_STATUS);
+ cpu = cpu_get_pcpu(dev)->pc_cpuid;
+ hwpstate_pstate_read_status(cpu, &msr);
if (msr >= sc->cfnum)
return (EINVAL);
set = sc->hwpstate_settings[msr];
-
cf->freq = set.freq;
cf->volts = set.volts;
cf->power = set.power;
@@ -967,8 +961,10 @@
device_t perf_dev;
int error, type;
uint64_t msr;
+ int cpu;
sc = device_get_softc(dev);
+ cpu = cpu_get_pcpu(dev)->pc_cpuid;
/*
* Check if acpi_perf has INFO only flag.
*/
@@ -985,15 +981,15 @@
*/
HWPSTATE_DEBUG(dev, "acpi_perf will take care of pstate transitions.\n");
return (ENXIO);
- } else {
- /*
- * If acpi_perf has INFO_ONLY flag, (_PCT has FFixedHW)
- * we can get _PSS info from acpi_perf
- * without going into ACPI.
- */
- HWPSTATE_DEBUG(dev, "going to fetch info from acpi_perf\n");
- error = hwpstate_get_info_from_acpi_perf(dev, perf_dev);
}
+ /*
+ * If acpi_perf has INFO_ONLY flag, (_PCT has FFixedHW)
+ * we can get _PSS info from acpi_perf
+ * without going into ACPI.
+ */
+ HWPSTATE_DEBUG(dev,
+ "going to fetch info from acpi_perf\n");
+ error = hwpstate_get_info_from_acpi_perf(dev, perf_dev);
}
}
@@ -1002,7 +998,7 @@
* Now we get _PSS info from acpi_perf without error.
* Let's check it.
*/
- msr = rdmsr(MSR_AMD_10H_11H_LIMIT);
+ hwpstate_pstate_read_limit(cpu, &msr);
if (sc->cfnum != 1 + AMD_10H_11H_GET_PSTATE_MAX_VAL(msr)) {
HWPSTATE_DEBUG(dev, "MSR (%jd) and ACPI _PSS (%d)"
" count mismatch\n", (intmax_t)msr, sc->cfnum);
@@ -1042,15 +1038,8 @@
sc->flags |= HWPFL_USE_CPPC;
device_set_desc(dev,
"AMD Collaborative Processor Performance Control (CPPC)");
- } else {
- /*
- * No CPPC support. Only keep hwpstate0, it goes well with
- * acpi_throttle.
- */
- if (device_get_unit(dev) != 0)
- return (ENXIO);
+ } else
device_set_desc(dev, "Cool`n'Quiet 2.0");
- }
sc->dev = dev;
if ((sc->flags & HWPFL_USE_CPPC) != 0) {
@@ -1119,22 +1108,59 @@
return (cpufreq_register(dev));
}
+struct hwpstate_pstate_read_settings_cb {
+ struct hwpstate_softc *sc;
+ uint64_t *vals;
+ int err;
+};
+
+static void
+hwpstate_pstate_read_settings_cb(void *args)
+{
+ struct hwpstate_pstate_read_settings_cb *req = args;
+ int i;
+
+ req->err = 0;
+ for (i = 0; i < req->sc->cfnum; i++) {
+ req->err = rdmsr_safe(MSR_AMD_10H_11H_CONFIG + i,
+ &req->vals[i]);
+ if (req->err != 0)
+ return;
+ }
+}
+
+static int
+hwpstate_pstate_read_settings(struct hwpstate_softc *sc, uint64_t vals[])
+{
+ struct hwpstate_pstate_read_settings_cb req;
+ device_t dev;
+
+ req.sc = sc;
+ req.vals = vals;
+ dev = sc->dev;
+ smp_rendezvous_cpu(cpu_get_pcpu(dev)->pc_cpuid,
+ smp_no_rendezvous_barrier, hwpstate_pstate_read_settings_cb,
+ smp_no_rendezvous_barrier, &req);
+ return (req.err);
+}
+
static int
hwpstate_get_info_from_msr(device_t dev)
{
struct hwpstate_softc *sc;
struct hwpstate_setting *hwpstate_set;
- uint64_t msr;
+ uint64_t state_settings[AMD_10H_11H_MAX_STATES], msr;
int family, i, fid, did;
family = CPUID_TO_FAMILY(cpu_id);
sc = device_get_softc(dev);
/* Get pstate count */
- msr = rdmsr(MSR_AMD_10H_11H_LIMIT);
+ hwpstate_pstate_read_limit(cpu_get_pcpu(dev)->pc_cpuid, &msr);
sc->cfnum = 1 + AMD_10H_11H_GET_PSTATE_MAX_VAL(msr);
hwpstate_set = sc->hwpstate_settings;
+ hwpstate_pstate_read_settings(sc, state_settings);
for (i = 0; i < sc->cfnum; i++) {
- msr = rdmsr(MSR_AMD_10H_11H_CONFIG + i);
+ msr = state_settings[i];
if ((msr & ((uint64_t)1 << 63)) == 0) {
HWPSTATE_DEBUG(dev, "msr is not valid.\n");
return (ENXIO);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jul 16, 7:10 AM (18 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35128699
Default Alt Text
D55606.diff (6 KB)
Attached To
Mode
D55606: hwpstate_amd: Expose node as much as possible
Attached
Detach File
Event Timeline
Log In to Comment