Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 6 Dec 2017 21:39:02 +0000 (UTC)
From:      Jung-uk Kim <jkim@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r326637 - stable/11/sys/x86/cpufreq
Message-ID:  <201712062139.vB6Ld23d028032@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jkim
Date: Wed Dec  6 21:39:01 2017
New Revision: 326637
URL: https://svnweb.freebsd.org/changeset/base/326637

Log:
  MFC:	r309361, r322710, r323286, r326378, r326383, r326407
  
  Sync. hwpstate with head.
  
  r309361 (danfe):
  
  - Mention mismatching numbers in MSR vs. ACPI _PSS count warning.
  - Rephrase unsupported AMD CPUs message and wrap as an overly long line.
  - Improve readability when reporting resulted P-state transition (debug).
  
  r322710, r323286 (cem):
  
  - Add support for family 17h pstate info from MSRs.
  - Yield CPU awaiting frequency change.
  
  r326378, r326383, r326407:
  
  - Fix some style(9) nits.
  - Add a tunable "debug.hwpstate_verify" to check P-state after changing it
  and turn it off by default.

Modified:
  stable/11/sys/x86/cpufreq/hwpstate.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/x86/cpufreq/hwpstate.c
==============================================================================
--- stable/11/sys/x86/cpufreq/hwpstate.c	Wed Dec  6 21:18:45 2017	(r326636)
+++ stable/11/sys/x86/cpufreq/hwpstate.c	Wed Dec  6 21:39:01 2017	(r326637)
@@ -83,11 +83,15 @@ __FBSDID("$FreeBSD$");
 #define	AMD_10H_11H_CUR_DID(msr)		(((msr) >> 6) & 0x07)
 #define	AMD_10H_11H_CUR_FID(msr)		((msr) & 0x3F)
 
+#define	AMD_17H_CUR_VID(msr)			(((msr) >> 14) & 0xFF)
+#define	AMD_17H_CUR_DID(msr)			(((msr) >> 8) & 0x3F)
+#define	AMD_17H_CUR_FID(msr)			((msr) & 0xFF)
+
 #define	HWPSTATE_DEBUG(dev, msg...)			\
-	do{						\
-		if(hwpstate_verbose)			\
+	do {						\
+		if (hwpstate_verbose)			\
 			device_printf(dev, msg);	\
-	}while(0)
+	} while (0)
 
 struct hwpstate_setting {
 	int	freq;		/* CPU clock in Mhz or 100ths of a percent. */
@@ -117,10 +121,14 @@ static int	hwpstate_get_info_from_acpi_perf(device_t d
 static int	hwpstate_get_info_from_msr(device_t dev);
 static int	hwpstate_goto_pstate(device_t dev, int pstate_id);
 
-static int	hwpstate_verbose = 0;
+static int	hwpstate_verbose;
 SYSCTL_INT(_debug, OID_AUTO, hwpstate_verbose, CTLFLAG_RWTUN,
-       &hwpstate_verbose, 0, "Debug hwpstate");
+    &hwpstate_verbose, 0, "Debug hwpstate");
 
+static int	hwpstate_verify;
+SYSCTL_INT(_debug, OID_AUTO, hwpstate_verify, CTLFLAG_RWTUN,
+    &hwpstate_verify, 0, "Verify P-state after setting");
+
 static device_method_t hwpstate_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_identify,	hwpstate_identify),
@@ -154,61 +162,69 @@ DRIVER_MODULE(hwpstate, cpu, hwpstate_driver, hwpstate
  * Go to Px-state on all cpus considering the limit.
  */
 static int
-hwpstate_goto_pstate(device_t dev, int pstate)
+hwpstate_goto_pstate(device_t dev, int id)
 {
-	int i;
+	sbintime_t sbt;
 	uint64_t msr;
-	int j;
-	int limit;
-	int id = pstate;
-	int error;
-	
+	int cpu, i, j, limit;
+
 	/* get the current pstate limit */
 	msr = rdmsr(MSR_AMD_10H_11H_LIMIT);
 	limit = AMD_10H_11H_GET_PSTATE_LIMIT(msr);
-	if(limit > id)
+	if (limit > id)
 		id = limit;
 
+	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.
 	 */
-	error = 0;
 	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, PCPU_GET(cpuid));
+		HWPSTATE_DEBUG(dev, "setting P%d-state on cpu%d\n", id, i);
 		/* Go To Px-state */
 		wrmsr(MSR_AMD_10H_11H_CONTROL, id);
 	}
-	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 = 0; j < 100; j++){
-			/* get the result. not assure msr=id */
-			msr = rdmsr(MSR_AMD_10H_11H_STATUS);
-			if(msr == id){
-				break;
+
+	/*
+	 * 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);
 			}
-			DELAY(100);
+			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);
+			}
 		}
-		HWPSTATE_DEBUG(dev, "result  P%d-state on cpu%d\n",
-		    (int)msr, PCPU_GET(cpuid));
-		if (msr != id) {
-			HWPSTATE_DEBUG(dev, "error: loop is not enough.\n");
-			error = ENXIO;
-		}
 	}
-	thread_lock(curthread);
-	sched_unbind(curthread);
-	thread_unlock(curthread);
-	return (error);
+
+	return (0);
 }
 
 static int
@@ -242,7 +258,7 @@ hwpstate_get(device_t dev, struct cf_setting *cf)
 	if (cf == NULL)
 		return (EINVAL);
 	msr = rdmsr(MSR_AMD_10H_11H_STATUS);
-	if(msr >= sc->cfnum)
+	if (msr >= sc->cfnum)
 		return (EINVAL);
 	set = sc->hwpstate_settings[msr];
 
@@ -367,7 +383,8 @@ hwpstate_probe(device_t dev)
 		 */
 		msr = rdmsr(MSR_AMD_10H_11H_LIMIT);
 		if (sc->cfnum != 1 + AMD_10H_11H_GET_PSTATE_MAX_VAL(msr)) {
-			HWPSTATE_DEBUG(dev, "msr and acpi _PSS count mismatch.\n");
+			HWPSTATE_DEBUG(dev, "MSR (%jd) and ACPI _PSS (%d)"
+			    " count mismatch\n", (intmax_t)msr, sc->cfnum);
 			error = TRUE;
 		}
 	}
@@ -416,7 +433,7 @@ hwpstate_get_info_from_msr(device_t dev)
 		fid = AMD_10H_11H_CUR_FID(msr);
 
 		/* Convert fid/did to frequency. */
-		switch(family) {
+		switch (family) {
 		case 0x11:
 			hwpstate_set[i].freq = (100 * (fid + 0x08)) >> did;
 			break;
@@ -426,8 +443,18 @@ hwpstate_get_info_from_msr(device_t dev)
 		case 0x16:
 			hwpstate_set[i].freq = (100 * (fid + 0x10)) >> did;
 			break;
+		case 0x17:
+			did = AMD_17H_CUR_DID(msr);
+			if (did == 0) {
+				HWPSTATE_DEBUG(dev, "unexpected did: 0\n");
+				did = 1;
+			}
+			fid = AMD_17H_CUR_FID(msr);
+			hwpstate_set[i].freq = (200 * fid) / did;
+			break;
 		default:
-			HWPSTATE_DEBUG(dev, "get_info_from_msr: AMD family 0x%02x CPU's are not implemented yet. sorry.\n", family);
+			HWPSTATE_DEBUG(dev, "get_info_from_msr: AMD family"
+			    " 0x%02x CPUs are not supported yet\n", family);
 			return (ENXIO);
 		}
 		hwpstate_set[i].pstate_id = i;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201712062139.vB6Ld23d028032>