Page MenuHomeFreeBSD

D55606.id.diff
No OneTemporary

D55606.id.diff

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
@@ -588,6 +588,18 @@
return (val);
}
+static int
+hwpstate_pstate_read_limit(device_t dev)
+{
+ int cpu;
+ uint64_t msr;
+
+ cpu = cpu_get_pcpu(dev)->pc_cpuid;
+ x86_msr_op(MSR_AMD_10H_11H_LIMIT,
+ MSR_OP_READ | MSR_OP_RENDEZVOUS_ONE | MSR_OP_CPUID(cpu), 0, &msr);
+ return (msr);
+}
+
/*
* Go to Px-state on all cpus, considering the limit register (if so
* configured).
@@ -597,11 +609,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);
+ msr = hwpstate_pstate_read_limit(dev);
limit = AMD_10H_11H_GET_PSTATE_LIMIT(msr);
if (limit > id) {
HWPSTATE_DEBUG(dev, "Restricting requested P%d to P%d "
@@ -610,53 +624,34 @@
}
}
- 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 */
+ x86_msr_op(MSR_AMD_10H_11H_CONTROL,
+ MSR_OP_READ | MSR_OP_RENDEZVOUS_ONE |
+ MSR_OP_CPUID(cpu),
+ 0, &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);
}
}
@@ -723,7 +718,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)))
@@ -738,13 +732,15 @@
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;
+ x86_msr_op(MSR_AMD_10H_11H_STATUS,
+ MSR_OP_READ | MSR_OP_RENDEZVOUS_ONE | MSR_OP_CPUID(cpu), 0, &msr);
if (msr >= sc->cfnum)
return (EINVAL);
set = sc->hwpstate_settings[msr];
-
cf->freq = set.freq;
cf->volts = set.volts;
cf->power = set.power;
@@ -1095,7 +1091,7 @@
* Now we get _PSS info from acpi_perf without error.
* Let's check it.
*/
- msr = rdmsr(MSR_AMD_10H_11H_LIMIT);
+ msr = hwpstate_pstate_read_limit(dev);
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);
@@ -1133,15 +1129,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) {
@@ -1230,22 +1219,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)
+ 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 msrs[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);
+ msr = hwpstate_pstate_read_limit(dev);
sc->cfnum = 1 + AMD_10H_11H_GET_PSTATE_MAX_VAL(msr);
hwpstate_set = sc->hwpstate_settings;
+ hwpstate_pstate_read_settings(sc, msrs);
for (i = 0; i < sc->cfnum; i++) {
- msr = rdmsr(MSR_AMD_10H_11H_CONFIG + i);
+ msr = msrs[i];
if ((msr & ((uint64_t)1 << 63)) == 0) {
HWPSTATE_DEBUG(dev, "msr is not valid.\n");
return (ENXIO);

File Metadata

Mime Type
text/plain
Expires
Tue, Mar 3, 2:36 AM (18 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29166764
Default Alt Text
D55606.id.diff (5 KB)

Event Timeline