Date: Fri, 25 Sep 2015 12:58:18 -0400 From: Anthony Jenkins <Scoobi_doo@yahoo.com> To: "freebsd-mobile@freebsd.org" <freebsd-mobile@freebsd.org> Subject: PATCH: cpufreq(4) support for modern AMD processors (git format) Message-ID: <56057D2A.9090505@yahoo.com>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------020102020707080202060604 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable sys/x86/cpufreq/hwpstate.c provides support for AMD CPUs, but only supports families up to 0x11. The latest AMD CPU family is 0x16. This patch adds support for newer AMD CPUs. (The patch to sys/x86/cpufreq/powernow.c is cosmetic/superfluous.) Sources: BIOS and Kernel Developer's Guide for AMD Family (10h|11h|12h|14h Models *|15h Models *|16h Models *) Processors I'm still looking into the occasional 'hwpstate0: set freq failed, err 6' error. hwpstate0 reports "error: loop is not enough" when attempting to set the P-state on my cores. CPU_FOREACH(i) { /* Bind to each cpu. */ thread_lock(curthread); sched_bind(curthread, i); thread_unlock(curthread); /* wait loop (100*100 usec is enough ?) */ for(j =3D 0; j < 100; j++){ /* get the result. not assure msr=3Did */ msr =3D rdmsr(MSR_AMD_10H_11H_STATUS); if(msr =3D=3D id){ break; } DELAY(100); } HWPSTATE_DEBUG(dev, "result P%d-state on cpu%d\n", (int)msr, PCPU_GET(cpuid)); if (msr !=3D id) { HWPSTATE_DEBUG(dev, "error: loop is not enough.\n= "); error =3D ENXIO; } } I haven't figured out a more deterministic way of knowing when to read the MSR after requesting the new P-state...still wading through the AMD CPU manuals. --=20 Anthony Jenkins Software Engineer Zenterio, Inc. USA --------------020102020707080202060604 Content-Type: text/x-patch; name="amd_hwpstate_support.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="amd_hwpstate_support.patch" diff --git a/sys/x86/cpufreq/hwpstate.c b/sys/x86/cpufreq/hwpstate.c index d4c70b7..326d967 100644 --- a/sys/x86/cpufreq/hwpstate.c +++ b/sys/x86/cpufreq/hwpstate.c @@ -408,25 +408,27 @@ hwpstate_get_info_from_msr(device_t dev) hwpstate_set =3D sc->hwpstate_settings; for (i =3D 0; i < sc->cfnum; i++) { msr =3D rdmsr(MSR_AMD_10H_11H_CONFIG + i); - if ((msr & ((uint64_t)1 << 63)) !=3D ((uint64_t)1 << 63)) { + if ((msr & ((uint64_t)1 << 63)) =3D=3D 0) { HWPSTATE_DEBUG(dev, "msr is not valid.\n"); return (ENXIO); } did =3D AMD_10H_11H_CUR_DID(msr); fid =3D AMD_10H_11H_CUR_FID(msr); + /* fid/did to frequency */ switch(family) { case 0x11: - /* fid/did to frequency */ - hwpstate_set[i].freq =3D 100 * (fid + 0x08) / (1 << did); + hwpstate_set[i].freq =3D (100 * (fid + 0x08)) >> did; break; case 0x10: - /* fid/did to frequency */ - hwpstate_set[i].freq =3D 100 * (fid + 0x10) / (1 << did); + case 0x12: + case 0x14: + case 0x15: + case 0x16: + hwpstate_set[i].freq =3D (100 * (fid + 0x10)) >> did; break; default: - HWPSTATE_DEBUG(dev, "get_info_from_msr: AMD family %d CPU's are not i= mplemented yet. sorry.\n", family); + HWPSTATE_DEBUG(dev, "get_info_from_msr: AMD family 0x%02x CPU's are n= ot implemented yet. sorry.\n", family); return (ENXIO); - break; } hwpstate_set[i].pstate_id =3D i; /* There was volts calculation, but deleted it. */ diff --git a/sys/x86/cpufreq/powernow.c b/sys/x86/cpufreq/powernow.c index cc62e87..355bde8 100644 --- a/sys/x86/cpufreq/powernow.c +++ b/sys/x86/cpufreq/powernow.c @@ -866,17 +866,22 @@ static void pn_identify(driver_t *driver, device_t parent) { =20 - if ((amd_pminfo & AMDPM_FID) =3D=3D 0 || (amd_pminfo & AMDPM_VID) =3D=3D= 0) + if ((amd_pminfo & AMDPM_FID) =3D=3D 0 || (amd_pminfo & AMDPM_VID) =3D=3D= 0) { + printf("powernow: pn_identify: amd_pminfo=3D0x%04x .\n", amd_pminfo); return; + } switch (cpu_id & 0xf00) { case 0x600: case 0xf00: break; default: + printf("powernow: pn_identify: cpu_id=3D0x%04x.\n", cpu_id); return; } - if (device_find_child(parent, "powernow", -1) !=3D NULL) + if (device_find_child(parent, "powernow", -1) !=3D NULL) { + printf("powernow: pn_identify: No \"powernow\"device found.\n"); return; + } if (BUS_ADD_CHILD(parent, 10, "powernow", -1) =3D=3D NULL) device_printf(parent, "powernow: add child failed\n"); } @@ -895,8 +900,10 @@ pn_probe(device_t dev) status =3D rdmsr(MSR_AMDK7_FIDVID_STATUS); =20 pc =3D cpu_get_pcpu(dev); - if (pc =3D=3D NULL) + if (pc =3D=3D NULL) { + printf("powernow: cpu_get_pcpu() returned NULL.\n"); return (ENODEV); + } =20 cpu_est_clockrate(pc->pc_cpuid, &rate); =20 @@ -936,6 +943,7 @@ pn_probe(device_t dev) device_set_desc(dev, "Cool`n'Quiet K8"); break; default: + printf("powernow: cpuid 0x%04x & 0xf00 not matched.\n", cpu_id); return (ENODEV); } =20 --------------020102020707080202060604--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?56057D2A.9090505>