# HG changeset patch # User Robert Ransom # Date 1578147960 18000 # Node ID 48a158c0731b26c142a404cc3fdd04e679a3bca1 # Parent 939ab197463703d4835622103bde410bd0a2acd7 Add minimal CPU frequency support for AMD family 10h and later This uses the 'hardware P-state control' present through the current family 17h processors. Family 10h also has the registers for the older software COF/VID control mechanism required by family 0fh (and earlier?), so this really ought to be generalized to support more than one type of CPU frequency control on the same system. diff --git a/sys/src/9/pc/cpufreq.c b/sys/src/9/pc/cpufreq.c new file mode 100644 --- /dev/null +++ b/sys/src/9/pc/cpufreq.c @@ -0,0 +1,97 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" + +enum { + CMpowersave, +}; + +static Cmdtab amdpstatectlmsg[] = { + CMpowersave, "powersave", 1, +}; + +static int +amdpstatecpufreqok(void) +{ + ulong regs[4]; + + if(strcmp(m->cpuidid, "AuthenticAMD") == 0){ + cpuid(0x80000007, regs); + return (regs[3] & (1 << 7)) != 0; + } + return 0; +} + +static void +amdpstateset(ulong pst) +{ + vlong cmdmsr; + long i; + Mach *w; + + w = up->wired; + cmdmsr = pst & 15; + for(i = 0; i < conf.nmach; ++i){ + procwired(up, i); + sched(); + if(wrmsr(0xC0010062, cmdmsr) < 0) + print("error setting P-state %uld on mach %ld\n", pst, i); + } + up->wired = w; + sched(); +} + +static void +amdpstatectl(Cmdbuf *cb) +{ + Cmdtab *ct; + vlong limmsr; + ulong PstateMaxVal; + + ct = lookupcmd(cb, amdpstatectlmsg, nelem(amdpstatectlmsg)); + switch(ct->index){ + case CMpowersave: + if(rdmsr(0xC0010061, &limmsr) < 0){ + cmderror(cb, "MSRC001_0061 unsupported?!"); + return; + } + PstateMaxVal = (limmsr >> 4) & 15; + print("PStateMaxVal: %uld\n", PstateMaxVal); + + amdpstateset(PstateMaxVal); + + return; + } + + cmderror(cb, "bad cpufreq control message"); +} + +static long +amdpstatectlwrite(Chan *c, void *a, long n, vlong off) +{ + Cmdbuf *cb; + + if(off || n >= READSTR) + error(Ebadarg); + + cb = parsecmd(a, n); + if(waserror()){ + free(cb); + nexterror(); + } + amdpstatectl(cb); + poperror(); + free(cb); + return n; +} + +void +cpufreqlink(void) +{ + if(amdpstatecpufreqok()) + addarchfile("cpufreqctl", 0664, nil, amdpstatectlwrite); +} diff --git a/sys/src/9/pc/pc b/sys/src/9/pc/pc --- a/sys/src/9/pc/pc +++ b/sys/src/9/pc/pc @@ -48,6 +48,7 @@ devpccard devi82365 cputemp + cpufreq apm apmjump ether2000 ether8390 ether2114x pci diff --git a/sys/src/9/pc64/pc64 b/sys/src/9/pc64/pc64 --- a/sys/src/9/pc64/pc64 +++ b/sys/src/9/pc64/pc64 @@ -47,6 +47,7 @@ # devpccard # devi82365 cputemp + cpufreq # ether2000 ether8390 # ether2114x pci # ether589 etherelnk3