Source/IntelEnhancedSpeedStep.cpp
author Prashant Vaibhav <voodoo@mercurysquad.com>
Tue Jun 16 00:16:11 2009 +0530 (13 months ago)
changeset 67 980863a83e9e
parent 6374f4d6c9c5cf
permissions -rw-r--r--
Added tag 1.5.0 for changeset 6c420506f042
     1 extern "C" {
     2 #include <pexpert/pexpert.h>
     3 }
     4 
     5 #define super IOService
     6 
     7 #include "IntelEnhancedSpeedStep.h"
     8 #include "Utility.h"
     9 
    10 
    11 OSDefineMetaClassAndStructors(net_mercurysquad_driver_IntelEnhancedSpeedStep, IOService)
    12 OSDefineMetaClassAndStructors(AutoThrottler, OSObject)
    13 
    14 /**********************************************************************************/
    15 /* sysctl interface for compatibility with Niall Douglas' ACPICPUThrottle.kext    */
    16 
    17 static int iess_handle_curfreq SYSCTL_HANDLER_ARGS
    18 {
    19 	int err = 0;
    20 	if (req->newptr) {
    21 		// New freq being set
    22 		int pstate, wantedFreq;
    23 		err = SYSCTL_IN(req, &wantedFreq, sizeof(int));
    24 		if (err) return err;
    25 		
    26 		if (wantedFreq < 16 && wantedFreq < NumberOfPStates) // pstate specified directly
    27 			pstate = wantedFreq;
    28 		else // freq in MHz is given, find closest pstate
    29 			pstate = FindClosestPState(wantedFreq);
    30 		
    31 		dbg("Throttling to PState %d\n", pstate);
    32 		throttleAllCPUs(&PStates[pstate]);
    33 
    34 	} else { // just reading
    35 		int MHz = PStates[FindClosestPState(getCurrentFrequency())].AcpiFreq;
    36 		err = SYSCTL_OUT(req, &MHz, sizeof(int));
    37 	}
    38 	
    39 	return err;
    40 }
    41 
    42 static int iess_handle_curvolt SYSCTL_HANDLER_ARGS
    43 {
    44 	int err = 0;
    45 	if (req->newptr) {
    46 		// New voltage being set
    47 		int wantedvolt;
    48 		err = SYSCTL_IN(req, &wantedvolt, sizeof(int));
    49 		if (err) return err;
    50 		int pstate   = FindClosestPState(getCurrentFrequency());
    51 		int origvolt = VID_to_mV(PStates[pstate].OriginalVoltage);
    52 		if (wantedvolt > origvolt+100) {
    53 			wantedvolt = origvolt;
    54 			warn("Will not set voltage more than 100 mV higher than factory spec %d mV\n", origvolt);
    55 		}
    56 		dbg("Changing voltage of current PState %d to %d mV\n", pstate, wantedvolt);
    57 		PStates[pstate].Voltage = mV_to_VID(wantedvolt);
    58 		throttleAllCPUs(&PStates[pstate]);
    59 	
    60 	} else { // just reading
    61 		int volt = getCurrentVoltage();
    62 		err = SYSCTL_OUT(req, &volt, sizeof(int));
    63 	}
    64 	
    65 	return err;
    66 }
    67 
    68 static int iess_handle_ctl SYSCTL_HANDLER_ARGS
    69 {
    70 	int err = 0;
    71 	if (req->newptr) {
    72 		// new ctl being set
    73 		warn("Use of kern.cputhrottle_ctl is only for debugging."
    74 		     "Use wisely - no validation is done!\n");
    75 		int ctl;
    76 		err = SYSCTL_IN(req, &ctl, sizeof(int));
    77 		if (err) return err;
    78 		dbg("Manual stepping to %xh\n", ctl);
    79 		
    80 		PState p; p.Frequency = FID(ctl); p.Voltage = VID(ctl);
    81 		throttleAllCPUs(&p);
    82 		
    83 	} else {
    84 		int ctl = rdmsr64(INTEL_MSR_PERF_STS);
    85 		ctl &= 0xffff; // only last 32 bits
    86 		err = SYSCTL_OUT(req, &ctl, sizeof(int));
    87 	}
    88 	return err;
    89 }
    90 
    91 static int iess_handle_auto SYSCTL_HANDLER_ARGS
    92 {
    93 	int err = 0;
    94 	if (req->newptr) {
    95 		// new ctl being set
    96 		int whetherOn;
    97 		err = SYSCTL_IN(req, &whetherOn, sizeof(int));
    98 		if (err) return err;
    99 		if (!Throttler) {
   100 			Throttler = new AutoThrottler;
   101 			if (!Throttler) return kIOReturnError;
   102 		}
   103 		// If setup was not done yet, do so.
   104 		if (Throttler->setupDone == false) {
   105 			if (Throttler->setup((OSObject*) Throttler) == false) {
   106 				warn("Auto-throttler could not be setup.\n");
   107 				return kIOReturnError;
   108 			}
   109 		}
   110 		dbg("Setting autothrottle to %d\n", whetherOn);
   111 		Throttler->setEnabled(whetherOn != 0);
   112 		
   113 	} else {
   114 		if (!Throttler) return kIOReturnError;
   115 		int sts = Throttler->getEnabled() ? 1 : 0;
   116 		err = SYSCTL_OUT(req, &sts, sizeof(int));
   117 	}
   118 	return err;
   119 }
   120 
   121 static int iess_handle_usage SYSCTL_HANDLER_ARGS
   122 {
   123 	int err = 0;
   124 	if (!req->newptr) { // reading
   125 		int curpos = 0; uint64_t pc;
   126 		if (totalTimerEvents == 0) return kIOReturnError;
   127 		for (int i = NumberOfPStates - 1; i >= 0; i--) {
   128 			pc = (100 * 100 * PStates[i].TimesChosen) / totalTimerEvents;
   129 			sprintf((frequencyUsage + curpos), "%u.%u%%   ", pc / 100, pc % 100);
   130 			if (pc / 100 < 10)
   131 				curpos += 6;
   132 			else if (pc / 100 < 100)
   133 				curpos += 7;
   134 			else
   135 				curpos += 8;
   136 			if (pc % 10 == 0)
   137 				curpos -= 1; // when it's xx.x% and not xx.xx%
   138 		}
   139 		frequencyUsage[curpos] = '\0';
   140 		err = SYSCTL_OUT(req, frequencyUsage, curpos + 1);
   141 	}
   142 	return err;
   143 }
   144 
   145 static int iess_handle_avgfreq SYSCTL_HANDLER_ARGS
   146 {
   147 	int err = 0;
   148 	if (!req->newptr) { // reading
   149 		if (totalTimerEvents == 0) return kIOReturnError;
   150 		uint64_t sum = 0; int avg = 0;
   151 		for (int i = NumberOfPStates - 1; i >= 0; i--) {
   152 			sum += PStates[i].TimesChosen * FID_to_MHz(PStates[i].Frequency);
   153 		}
   154 		avg = sum / totalTimerEvents;
   155 		err = SYSCTL_OUT(req, &avg, sizeof(avg));
   156 	}
   157 	return err;
   158 }
   159 
   160 SYSCTL_PROC  (_kern, OID_AUTO, cputhrottle_auto,	CTLTYPE_INT | CTLFLAG_RW, 0, 0, &iess_handle_auto,    "I", "Auto-throttle status");
   161 SYSCTL_PROC  (_kern, OID_AUTO, cputhrottle_curfreq,	CTLTYPE_INT | CTLFLAG_RW, 0, 0, &iess_handle_curfreq, "I", "Current CPU frequency");
   162 SYSCTL_PROC  (_kern, OID_AUTO, cputhrottle_curvolt,	CTLTYPE_INT | CTLFLAG_RW, 0, 0, &iess_handle_curvolt, "I", "Current CPU voltage");
   163 SYSCTL_PROC  (_kern, OID_AUTO, cputhrottle_ctl,		CTLTYPE_INT | CTLFLAG_RW, 0, 0, &iess_handle_ctl,     "I", "Current MSR status");
   164 SYSCTL_STRING(_kern, OID_AUTO, cputhrottle_freqs,	CTLFLAG_RD, frequencyList, 0, "CPU frequencies supported");
   165 SYSCTL_PROC  (_kern, OID_AUTO, cputhrottle_usage,	CTLTYPE_STRING | CTLFLAG_RD, 0, 0, &iess_handle_usage,"A", "CPU frequency usage pattern");
   166 SYSCTL_STRING(_kern, OID_AUTO, cputhrottle_factoryvolts,CTLFLAG_RD, originalVoltages, 0, "Factory default voltages for each frequency");
   167 SYSCTL_QUAD  (_kern, OID_AUTO, cputhrottle_totalthrottles, CTLFLAG_RD, &totalThrottles, "Total number of frequency throttles made");
   168 SYSCTL_PROC  (_kern, OID_AUTO, cputhrottle_avgfreq,	CTLTYPE_INT | CTLFLAG_RD, 0, 0, &iess_handle_avgfreq, "I", "Weighted average frequency in MHz at which this computer stays");
   169 /******* Helper functions for sysctl interface *********/
   170 
   171 /* Return null terminated list of frequencies */
   172 char* getFreqList() {
   173 	// Makes a list of space separated frequencies supported by the CPU
   174 	// Each frequency can occupy 4 digits, plus a space
   175 	char* freqs = new char[5 * NumberOfPStates];
   176 	int c = 0;
   177 	for (int i = NumberOfPStates-1; i >= 0; i--) {
   178 		sprintf((freqs + c), "%d ", PStates[i].AcpiFreq);
   179 		// Advance by 5 places if freq was of 4 digits
   180 		if (PStates[i].AcpiFreq >= 1000)
   181 			c += 5;
   182 		else // otherwise 4 places
   183 			c += 4;
   184 	}
   185 	// Set last char (which would be a space) to null
   186 	freqs[c] = '\0';
   187 	return freqs;
   188 }
   189 
   190 /* Return null terminated list of voltages */
   191 char* getVoltageList(bool originals) {
   192 	char* volts = new char[5 * NumberOfPStates];
   193 	int c = 0, svolt = 0;
   194 	for (int i = NumberOfPStates-1; i >= 0; i--) {
   195 		svolt = originals ? VID_to_mV(PStates[i].OriginalVoltage) : VID_to_mV(PStates[i].Voltage);
   196 		sprintf((volts + c), "%d ", svolt);
   197 		// Advance by 5 places if voltage was of 4 digits
   198 		if (svolt >= 1000)
   199 			c += 5;
   200 		else // otherwise 4 places
   201 			c += 4;
   202 	}
   203 	// Set last char (which would be a space) to null
   204 	volts[c] = '\0';
   205 	return volts;
   206 }
   207 
   208 int FindClosestPState(int wantedFreq) {
   209 	// assume P0 is best
   210 	int bestpstate = 0;
   211 	int bestdiff   = abs(PStates[0].AcpiFreq - wantedFreq);
   212 	
   213 	// now iterate over others and find the best
   214 	for (int i = 1; i < NumberOfPStates; i++) {
   215 		if (abs(PStates[i].AcpiFreq - wantedFreq) < bestdiff) {
   216 			bestpstate = i;
   217 			bestdiff = abs(PStates[i].AcpiFreq - wantedFreq);
   218 		}
   219 	}
   220 	
   221 	return bestpstate;
   222 }
   223 
   224 
   225 /***************************************************************************************************/
   226 
   227 bool net_mercurysquad_driver_IntelEnhancedSpeedStep::init(OSDictionary* dict) {
   228 	bool res = super::init(dict);
   229 	info("Initializing version 1.5.0 (C) Prashant Vaibhav <mercurysquad@yahoo.com>\n");
   230 	/* Allocate our spinlock for later use */
   231 	Lock = IOSimpleLockAlloc();
   232 	/* Check for a patched kernel which properly implements rtc_clock_stepped() */
   233 	uint64_t magic = -1; // means autodetect
   234 	
   235 	OSBoolean* debugMsgs = (OSBoolean*) dict->getObject("DebugMessages");
   236 	if (debugMsgs != 0)
   237 		DebugOn = debugMsgs->getValue();
   238 	else
   239 		DebugOn = false;
   240 	
   241 	OSNumber* kernelFeatures = (OSNumber*) dict->getObject("KernelFeatures");
   242 	if (kernelFeatures != 0)
   243 		magic = kernelFeatures->unsigned8BitValue();
   244 	
   245 	if (magic == 255) nanoseconds_to_absolutetime(~(0), &magic); //255uint = -1 int
   246 	
   247 	if (magic == 1) {
   248 		RtcFixKernel = true;
   249 		Below1Ghz	= false;
   250 	} else if (magic == 2) {
   251 		RtcFixKernel = true;
   252 		Below1Ghz	= true;
   253 	} else if (magic == 3) {
   254 		RtcFixKernel = false;
   255 		Below1Ghz = true;
   256 	} else {
   257 		RtcFixKernel = false;
   258 		Below1Ghz	= false;
   259 	}
   260 	
   261 	checkForNby2Ratio(); // check and store in global variable before loading pstate override
   262 	if (getFSB() == false)
   263 		return false;
   264 	
   265 	uint32_t bootarg;
   266 	OSArray* overrideTable = (OSArray*) dict->getObject("PStateTable");
   267 	if (overrideTable != 0 && !PE_parse_boot_arg("-autopstates", &bootarg))
   268 		loadPStateOverride(overrideTable);
   269 	
   270 	OSNumber* defaultState = (OSNumber*) dict->getObject("DefaultPState");
   271 	if (defaultState != 0)
   272 		DefaultPState = defaultState->unsigned8BitValue();
   273 	else
   274 		DefaultPState = -1; // indicate no default state
   275 
   276 	OSNumber* maxLatency = (OSNumber*) dict->getObject("Latency");
   277 	if (maxLatency != 0)
   278 		MaxLatency = maxLatency->unsigned32BitValue();
   279 	else
   280 		MaxLatency = 0;
   281 	
   282 	Throttler = new AutoThrottler;
   283 	if (Throttler) {
   284 		dbg("Throttler instantiated.\n");
   285 		OSNumber* targetload = (OSNumber*) dict->getObject("TargetCPULoad");
   286 		if (targetload != 0)
   287 			Throttler->targetCPULoad = (targetload->unsigned16BitValue()) * 10;
   288 		else
   289 			Throttler->targetCPULoad = 300;
   290 	}
   291 	
   292 	totalThrottles = 0;
   293 	frequencyUsage[0] = '\0';
   294 	
   295 	/* Return whatever the superclass returned */
   296 	return res;
   297 }
   298 
   299 void net_mercurysquad_driver_IntelEnhancedSpeedStep::free(void) {
   300 	dbg("Freeing driver resources\n");
   301 	/* Deallocate the previously allocated spinlock */
   302 	IOSimpleLockFree(Lock);
   303 	super::free();
   304 }
   305 
   306 IOService* net_mercurysquad_driver_IntelEnhancedSpeedStep::probe(IOService* provider, SInt32* score) {
   307 	IOService* res = super::probe(provider, score);
   308 	dbg("Probing for Intel processor...\n");
   309 	
   310 	/* Make preliminary check */
   311 	if ( (strcmp(cpuid_info()->cpuid_vendor, CPUID_VID_INTEL) == 0) // Check it's actually Intel
   312 	&& ( cpuid_info()->cpuid_features & CPUID_FEATURE_EST) ) { // Check it supports EST
   313 		*score += 1000;
   314 		dbg("Supported Intel processor found on your system\n");
   315 		res = this;
   316 	} else {
   317 		warn("No Intel processor found, or your processor does not support SpeedStep."
   318 		     "Kext will not load\n");
   319 		res = NULL;
   320 	}
   321 	
   322 	if (!isConstantTSC()) {
   323 		ConstantTSC = false;
   324 		if (RtcFixKernel)
   325 			dbg("Your processor doesn't support constant_tsc, but you have a kernel which can compensate for it.\n");
   326 		else
   327 			warn("Your processor doesn't support constant_tsc and your kernel doesn't " 
   328 			     "know how to compensate - Expect timing issues or switch to a kernel with RTC fix.\n");
   329 	} else {
   330 		ConstantTSC = true;
   331 		Below1Ghz = true; // blindly, because we're not gonna recalibrate the clock so no fear of panic
   332 	}
   333 	
   334 	return res;
   335 }
   336 
   337 bool net_mercurysquad_driver_IntelEnhancedSpeedStep::start(IOService *provider) {
   338 	bool res = super::start(provider);
   339 	if (!res) return false;
   340 	
   341 	dbg("Starting\n");
   342 	
   343 	/* Create PState tables */
   344 	if (!createPStateTable(PStates, &NumberOfPStates))
   345 		return false;
   346 	
   347 	// Set the frequency list for sysctl
   348 	strcpy(frequencyList, getFreqList());
   349 	strcpy(originalVoltages, getVoltageList(true));
   350 	
   351 	sysctl_register_oid(&sysctl__kern_cputhrottle_curfreq); 
   352 	sysctl_register_oid(&sysctl__kern_cputhrottle_curvolt);
   353 	sysctl_register_oid(&sysctl__kern_cputhrottle_freqs);
   354 	sysctl_register_oid(&sysctl__kern_cputhrottle_usage);
   355 	sysctl_register_oid(&sysctl__kern_cputhrottle_avgfreq);
   356 	sysctl_register_oid(&sysctl__kern_cputhrottle_factoryvolts);
   357 	sysctl_register_oid(&sysctl__kern_cputhrottle_totalthrottles);
   358 	sysctl_register_oid(&sysctl__kern_cputhrottle_ctl);
   359 	
   360 	if (DefaultPState != -1 && DefaultPState < NumberOfPStates) // If a default Pstate was specified in info.plist
   361 	{
   362 		dbg("Throttling to default PState %d as specified in Info.plist\n", DefaultPState);
   363 		throttleAllCPUs(&PStates[DefaultPState]); // then throttle to that value
   364 	}
   365 	
   366 	// Now turn on our auto-throttler
   367 	if (Throttler->setup((OSObject*) Throttler) == false)
   368 		warn("Auto-throttler could not be setup, start it manually later.\n");
   369 	else
   370 		Throttler->setEnabled(true);
   371 	
   372 	return true;
   373 }
   374 
   375 void net_mercurysquad_driver_IntelEnhancedSpeedStep::stop(IOService *provider) {
   376 	dbg("Shutting down\n");
   377 	if (Throttler) {
   378 		Throttler->destruct();
   379 		Throttler->release();
   380 		Throttler = 0;
   381 	}
   382 	sysctl_unregister_oid(&sysctl__kern_cputhrottle_curfreq); 
   383 	sysctl_unregister_oid(&sysctl__kern_cputhrottle_freqs);
   384 	sysctl_unregister_oid(&sysctl__kern_cputhrottle_curvolt);
   385 	sysctl_unregister_oid(&sysctl__kern_cputhrottle_avgfreq);
   386 	sysctl_unregister_oid(&sysctl__kern_cputhrottle_factoryvolts);
   387 	sysctl_unregister_oid(&sysctl__kern_cputhrottle_ctl);
   388 	sysctl_unregister_oid(&sysctl__kern_cputhrottle_usage);
   389 	sysctl_unregister_oid(&sysctl__kern_cputhrottle_totalthrottles);
   390 	
   391 	super::stop(provider);
   392 }
   393 
   394 bool isConstantTSC() {
   395 	/* Check for constant_tsc by getting family, model, stepping */
   396 	/* Ref http://en.wikipedia.org/wiki/CPUID#EAX.3D1:_Processor_Info_and_Feature_Bits 
   397 	 * And http://www.intel.com/assets/pdf/appnote/241618.pdf
   398 	 */
   399 	uint8_t cpumodel = (cpuid_info()->cpuid_extmodel << 4) + cpuid_info()->cpuid_model;
   400 	uint8_t cpufamily = cpuid_info()->cpuid_family;
   401 	dbg("Processor Family %d, Model %d\n", cpufamily, cpumodel);
   402 	if ((cpufamily == 0x6 && cpumodel < 14) // 13 is pentium M, 14+ is core and above
   403 	|| ( cpufamily == 0xf && cpumodel < 3)) // 0xF is pentium 4, less than model 3 dont support constant tsc
   404 		// Ref - http://www.tomshardware.com/forum/128629-28-intel
   405 		return false;
   406 	else
   407 		return true;
   408 }
   409 
   410 void checkForPenryn() {
   411 	uint8_t cpumodel = (cpuid_info()->cpuid_extmodel << 4) + cpuid_info()->cpuid_model;
   412 	Is45nmPenryn = (cpuid_info()->cpuid_family == 6) && (cpumodel >= 0x17);
   413 	if (Is45nmPenryn)
   414 		dbg("On your processor, voltages can be changed in 12.5 mV steps\n");
   415 	else
   416 		dbg("On your processor, voltages can be changed in 16 mV steps\n");
   417 }
   418 
   419 void checkForNby2Ratio() {
   420 	uint64_t sts;
   421 	sts = rdmsr64(INTEL_MSR_PERF_STS);
   422 	Nby2Ratio = (sts & (1ULL << 46)); // bit 46 is set
   423 }
   424 
   425 uint16_t getCurrentVoltage() {
   426 	// Apple recommends not to return cached value, but to read it from the processor
   427 	uint64_t msr = rdmsr64(INTEL_MSR_PERF_STS);
   428 	return VID_to_mV(VID(msr));
   429 }
   430 
   431 uint16_t getCurrentFrequency() {
   432 	uint64_t msr = rdmsr64(INTEL_MSR_PERF_STS);
   433 	return FID_to_MHz(FID(msr));
   434 }
   435 
   436 uint16_t VID_to_mV(uint8_t VID) {
   437 	if (Is45nmPenryn)
   438 		return (((int)VID * 125) + 7125) / 10; // to avoid using float
   439 	else
   440 		return (((int)VID * 16) + 700);
   441 }
   442 
   443 uint8_t mV_to_VID(uint16_t mv) {
   444 	if (Is45nmPenryn)
   445 		return ((mv * 10) - 7125) / 125;
   446 	else
   447 		return (mv - 700) / 16;
   448 }
   449 
   450 inline uint16_t FID_to_MHz(uint8_t x) {
   451 	bool nby2 = x & 0x80;
   452 	uint8_t realfid = x & 0x7f; // removes the bit from 0x80
   453 	if (nby2)
   454 		realfid /= 2;
   455 	return realfid * (FSB / 1000000ULL);
   456 }
   457 
   458 static inline uint32_t FID_to_Hz(uint8_t x) {
   459 	bool nby2 = x & 0x80;
   460 	uint8_t realfid = x & 0x7f;
   461 	if (nby2)
   462 		realfid /= 2;
   463 	return realfid * FSB;
   464 }
   465 
   466 inline uint8_t MHz_to_FID(uint16_t x) {
   467 	uint8_t realfid = x / (FSB / 1000000ULL);
   468 	if (Nby2Ratio && x < 1000) // FIXME: use n/2 for only <1ghz frequencies?
   469 		realfid = (realfid*2) | 0x80;
   470 	return realfid;
   471 }
   472 
   473 void loadPStateOverride(OSArray* dict) {
   474 	/* Here we load the override pstate table from the given array */
   475 	NumberOfPStates = dict->getCount();
   476 	for (int i = 0; i < NumberOfPStates; i++) {
   477 		OSArray* onePstate		= (OSArray*) dict->getObject(i);
   478 		PStates[i].AcpiFreq		= ((OSNumber*) onePstate->getObject(0))->unsigned16BitValue();
   479 		PStates[i].Frequency		= MHz_to_FID(PStates[i].AcpiFreq); // this accounts for N/2 automatically
   480 		PStates[i].OriginalVoltage	= mV_to_VID(((OSNumber*) onePstate->getObject(1))->unsigned16BitValue());
   481 		PStates[i].Voltage		= PStates[i].OriginalVoltage;
   482 		PStates[i].TimesChosen		= 0;
   483 		dbg("P-State %d: %d MHz at %d mV\n", i, PStates[i].AcpiFreq, VID_to_mV(PStates[i].OriginalVoltage));
   484 	}
   485 	info("Loaded %d PStates from Info.plist\n", NumberOfPStates);
   486 }
   487 
   488 bool getFSB() {
   489 	FSB = 0;
   490 	IORegistryEntry* efi = IORegistryEntry::fromPath("/efi/platform", IORegistryEntry::getPlane("IODeviceTree"));
   491 	if (efi == 0) {
   492 		warn("EFI registry entry not found!\n");
   493 		return false;
   494 	}
   495 	OSData* fsb = (OSData*) efi->getProperty("FSBFrequency");
   496 	if (fsb == 0) {
   497 		warn("FSB frequency entry not found!\n");
   498 		return false;
   499 	}
   500 	bcopy(fsb->getBytesNoCopy(), &FSB, 8);
   501 	dbg("FSB = %d MHz\n", FSB/1000000ULL);
   502 	efi = 0; fsb = 0; // in dono ka kaam khatam	
   503 	return true;
   504 }
   505 
   506 bool createPStateTable(PState* pS, unsigned int* numStates) {	
   507 	checkForPenryn(); // early on, so we can display proper mV values
   508 	
   509 	/* If the PState table was specified manually, we dont do the rest. Otherwise autodetect */
   510 	if (NumberOfPStates != 0) {
   511 		dbg("PState table was already created. No autodetection will be performed\n");
   512 		return true;
   513 	}
   514 	
   515 	/* Find CPUs in the IODeviceTree plane */
   516 	IORegistryEntry* ioreg = IORegistryEntry::fromPath("/cpus", IORegistryEntry::getPlane("IODeviceTree"));
   517 	if (ioreg == 0) {
   518 		warn("Holy moly we cannot find your CPU!\n");
   519 		return false;
   520 	}
   521 	
   522 	/* Get the first CPU - we assume all CPUs share the same P-State */
   523 	IOACPIPlatformDevice* cpu = (IOACPIPlatformDevice*) ioreg->getChildEntry(IORegistryEntry::getPlane("IODeviceTree"));
   524 	if (cpu == 0) {
   525 		warn("Um you don't seem to have a CPU o.O\n");
   526 		ioreg = 0;
   527 		return false;
   528 	}
   529 	
   530 	dbg("Using data from %s\n", cpu->getName());
   531 	
   532 	/* Now try to find the performance state table */
   533 	OSObject* PSS; uint32_t bootarg;
   534 	cpu->evaluateObject("_PSS", &PSS);
   535 	if(PSS == 0 || PE_parse_boot_arg("-autopstates", &bootarg)) {
   536 		warn("Auto-creating a PState table.\n");
   537 		int maxFID = MHz_to_FID(getCurrentFrequency());
   538 		int maxVID = mV_to_VID(getCurrentVoltage());
   539 		int minVID = mV_to_VID(984); // For now we'll use hardcoded minvolt, later use table
   540 		int minFID = 6; // No LFM right now
   541 		NumberOfPStates = 1 + ((maxFID - minFID) / 2);
   542 		for (int i = 1; i < NumberOfPStates; i++) {
   543 			PStates[i].Frequency		= minFID + (2*(NumberOfPStates - i - 1));
   544 			PStates[i].AcpiFreq		= FID_to_MHz(PStates[i].Frequency);
   545 			PStates[i].OriginalVoltage	= maxVID - (i*((maxVID - minVID) / NumberOfPStates));
   546 			PStates[i].Voltage		= PStates[i].OriginalVoltage;
   547 			PStates[i].Latency		= 110;
   548 			PStates[i].TimesChosen		= 0;
   549 		}
   550 		
   551 		PStates[0].Frequency		= maxFID;
   552 		PStates[0].AcpiFreq		= FID_to_MHz(maxFID);
   553 		PStates[0].OriginalVoltage	= maxVID;
   554 		PStates[0].Voltage		= PStates[0].OriginalVoltage;
   555 		PStates[0].Latency		= 110;
   556 		PStates[0].TimesChosen		= 0;
   557 		MaxLatency			= PStates[0].Latency;
   558 		info("Using %d PStates (auto-created, may not be optimal).\n", NumberOfPStates);
   559 		ioreg = 0; cpu = 0;
   560 		return true;
   561 	}
   562 	
   563 	OSArray* PSSArray = (OSArray*) PSS;
   564 	NumberOfPStates = PSSArray->getCount();
   565 	dbg("Found %d P-States\n", NumberOfPStates);
   566 	OSArray* onestate; uint16_t ctl, acpifreq; uint32_t power, latency;
   567 	int i = 0, c = 0;
   568 	
   569 	while (c < PSSArray->getCount()) {
   570 		onestate = ( OSArray* )(PSSArray->getObject(c));
   571 		ctl      = ((OSNumber*) onestate->getObject(4))->unsigned32BitValue();
   572 		acpifreq = ((OSNumber*) onestate->getObject(0))->unsigned32BitValue();
   573 		power	 = ((OSNumber*) onestate->getObject(1))->unsigned32BitValue();
   574 		latency	 = ((OSNumber*) onestate->getObject(2))->unsigned32BitValue();
   575 		c++;
   576 		
   577 		if (acpifreq - (10 * (acpifreq / 10)) == 1) {
   578 			// most likely spurious, so skip it
   579 			warn("** Spurious P-State %d: %d MHz at %d mV, consuming %d W, latency %d usec\n", i, acpifreq, VID_to_mV(ctl), power / 1000, latency);
   580 			NumberOfPStates--;
   581 			continue;
   582 		}
   583 		
   584 		if (acpifreq < 1000 && !Below1Ghz) {
   585 			warn("%d MHz disabled because your processor or kernel doesn't support it.\n");
   586 			NumberOfPStates--;
   587 			continue;
   588 		}
   589 		
   590 		PStates[i].AcpiFreq		= acpifreq; // cosmetic only
   591 		PStates[i].Frequency		= FID(ctl);
   592 		PStates[i].OriginalVoltage	= VID(ctl);
   593 		PStates[i].Voltage		= PStates[i].OriginalVoltage; // initially same
   594 		PStates[i].Latency		= latency;
   595 		PStates[i].TimesChosen		= 0;
   596 		
   597 		if (latency > MaxLatency) MaxLatency = latency;
   598 		
   599 		dbg("P-State %d: %d MHz at %d mV, consuming %d W, latency %d usec\n",
   600 		    i, PStates[i].AcpiFreq, VID_to_mV(PStates[i].OriginalVoltage),
   601 		    power / 1000, latency);
   602 		i++;
   603 	}
   604 	
   605 	info("Using %d PStates.\n", NumberOfPStates);
   606 	
   607 	ioreg = 0; cpu = 0; PSS = 0; onestate = 0;
   608 	return true;
   609 }
   610 
   611 /**************************************************************************************************/
   612 /* Throttling functions */
   613 
   614 void throttleAllCPUs(PState* p) {
   615 	dbg("Starting throttle with CTL 0x%x\n", CTL(p->Frequency, p->Voltage));
   616 	IOSimpleLockLock(Lock);
   617 	
   618 	mp_rendezvous(disableInterrupts, throttleCPU, enableInterrupts, p);
   619 	IODelay(p->Latency); // maybe wait longer?
   620 	
   621 	totalThrottles++;
   622 	
   623 	IOSimpleLockUnlock(Lock);
   624 	dbg("Throttle done.\n");
   625 }
   626 
   627 void throttleCPU(void *t) {
   628 	uint64_t msr;
   629 	PState p;
   630 	uint32_t newfreq, oldfreq;
   631 
   632 	bcopy(t,&p,sizeof(PState)); // get the ctl we want
   633 	
   634 	msr = rdmsr64(INTEL_MSR_PERF_STS); // read current MSR
   635 	
   636 	// For clock recalibration
   637 	oldfreq = FID_to_Hz(FID(msr));
   638 	// blank out last 32 bits and put our ctl there
   639 	msr = (msr & 0xffffffffffff0000ULL) | CTL(p.Frequency, p.Voltage);
   640 	newfreq = FID_to_Hz(FID(msr)); // after setting ctl in msr
   641 	
   642 	if (RtcFixKernel && !ConstantTSC) {
   643 		rtc_clock_stepping(newfreq, oldfreq);
   644 	}
   645 	
   646 	wrmsr64(INTEL_MSR_PERF_CTL, msr); // and write it to the processor
   647 	
   648 	if (RtcFixKernel && !ConstantTSC)
   649 		rtc_clock_stepped(newfreq, oldfreq);
   650 }
   651 
   652 void disableInterrupts(__unused void *t) {
   653 	InterruptsEnabled = ml_set_interrupts_enabled(false);
   654 }
   655 
   656 void enableInterrupts(__unused void *t) {
   657 	ml_set_interrupts_enabled(InterruptsEnabled);
   658 }
   659 
   660 
   661 
   662 
   663 /**********************************************************************************************************/
   664 
   665 
   666 static int iess_handle_targetload SYSCTL_HANDLER_ARGS
   667 {
   668 	int err = 0;
   669 	if (req->newptr) {
   670 		// new ctl being set
   671 		int target;
   672 		err = SYSCTL_IN(req, &target, sizeof(int));
   673 		if (err) return err;
   674 		if (!Throttler) return kIOReturnError;
   675 		if (target > 95) return kIOReturnError;
   676 		dbg("Setting autothrottle target to %d\n", target*10);
   677 		Throttler->targetCPULoad = target * 10;
   678 		
   679 	} else {
   680 		if (!Throttler) return kIOReturnError;
   681 		int target = Throttler->targetCPULoad / 10;
   682 		err = SYSCTL_OUT(req, &target, sizeof(int));
   683 	}
   684 	return err;
   685 }
   686 
   687 SYSCTL_PROC  (_kern, OID_AUTO, cputhrottle_targetload,	CTLTYPE_INT | CTLFLAG_RW, 0, 0, &iess_handle_targetload,    "I", "Auto-throttle target CPU load");
   688 
   689 bool AutoThrottler::setup(OSObject* owner) {
   690 	if (setupDone) return true;
   691 	
   692 	workLoop = IOWorkLoop::workLoop();
   693 	if (workLoop == 0) return false;
   694 	
   695 	perfTimer = IOTimerEventSource::timerEventSource(owner, (IOTimerEventSource::Action) &perfTimerWrapper);
   696 	if (perfTimer == 0) return false;
   697 	
   698 	/* from Superhai (modified by mercurysquad) */
   699 	cpu_count = 0; OSDictionary* service;
   700 	mach_timespec_t serviceTimeout = { 60, 0 }; // in seconds
   701 	totalTimerEvents = 0;
   702 	
   703 	IOService* firstCPU = IOService::waitForService(IOService::serviceMatching("IOCPU"), &serviceTimeout);
   704 
   705 	if (!firstCPU) {
   706 		warn("IOKit CPUs not found. Auto-throttle may not work.\n");
   707 		return false;
   708 	} else {
   709 		// we got first cpu, so the others should also be available by now. get them
   710 		service = IOService::serviceMatching("IOCPU");
   711 	}
   712 	
   713 	OSIterator* iterator = IOService::getMatchingServices(service);
   714 	
   715 	if (!iterator) {
   716 		warn("IOKit CPU iterator couldn't be created. Auto-throttle may not work.\n");
   717 		return false;
   718 	}
   719 
   720 	IOCPU * cpu;
   721 	while (cpu = OSDynamicCast(IOCPU, iterator->getNextObject()))
   722 	{
   723 		dbg("Got I/O Kit CPU %d (%d) named %s", cpu_count, cpu->getCPUNumber(), cpu->getCPUName()->getCStringNoCopy());
   724 		mach_cpu[cpu_count] = cpu->getMachProcessor();
   725 		if (cpu_count++ > max_cpus) break;
   726 	}
   727 	selfHost = host_priv_self();
   728 	if (workLoop->addEventSource(perfTimer) != kIOReturnSuccess) return false;
   729 	currentPState = NumberOfPStates - 1;
   730 	perfTimer->setTimeoutMS(throttleQuantum * (1 + currentPState));
   731 	clock_get_uptime(&lastTime);
   732 	if (!targetCPULoad) targetCPULoad = defaultTargetLoad; // % x10
   733 	sysctl_register_oid(&sysctl__kern_cputhrottle_targetload);
   734 	sysctl_register_oid(&sysctl__kern_cputhrottle_auto);
   735 	setupDone = true;
   736 	return true;
   737 }
   738 
   739 
   740 void AutoThrottler::stop() {
   741 	enabled = false;
   742 	perfTimer->cancelTimeout();
   743 	perfTimer->disable();
   744 	// Settle time in case we were just stepping
   745 	IOSleep(1024);
   746 	if (workLoop) workLoop->removeEventSource(perfTimer);	// Remove our event sources
   747 	dbg("Autothrottler stopped.\n");
   748 	setupDone = false;
   749 }
   750 
   751 void AutoThrottler::setEnabled(bool _enabled) {
   752 	if (_enabled) {
   753 		// asked to turn on
   754 		perfTimer->enable();
   755 	} else {
   756 		perfTimer->cancelTimeout();
   757 		perfTimer->disable();
   758 	}
   759 	enabled = _enabled;
   760 }
   761 
   762 bool AutoThrottler::getEnabled() {
   763 	return enabled;
   764 }
   765 
   766 void AutoThrottler::destruct() {
   767 	if (enabled) enabled = false;
   768 	if (setupDone) stop();
   769 	sysctl_unregister_oid(&sysctl__kern_cputhrottle_targetload);
   770 	sysctl_unregister_oid(&sysctl__kern_cputhrottle_auto);
   771 	if (perfTimer) {
   772 		perfTimer->release();
   773 		perfTimer = 0;
   774 	}
   775 	
   776 	if (workLoop) {
   777 		workLoop->release();
   778 		workLoop = 0;
   779 	}
   780 }
   781 
   782 
   783 void AutoThrottler::GetCPUTicks(long* idle, long* total) {
   784 	mach_msg_type_number_t cpu_count_type;
   785 	unsigned int cpu_maxload = 0;
   786 	/* Superhai method */
   787 	unsigned int temp_ticks = 0;
   788 	for (int i = 0; i < cpu_count; i++)
   789 	{
   790 		cpu_count_type = PROCESSOR_CPU_LOAD_INFO_COUNT;
   791 		total_ticks[i] = 0;
   792 		kern_return_t kret = processor_info(mach_cpu[i], PROCESSOR_CPU_LOAD_INFO, &selfHost,
   793 						    (processor_info_t) &cpu_load[i], &cpu_count_type);
   794 		if (kret != KERN_SUCCESS)
   795 		{
   796 			dbg("Error when reading cpu load on cpu %d (%x)", i, kret);
   797 			break;
   798 		}
   799 		cpu_load_temp[i] = cpu_load[i];
   800 		for (int t = 0; t < CPU_STATE_MAX; t++)
   801 		{
   802 			(cpu_load_temp[i].cpu_ticks[t]) -= (cpu_load_last[i].cpu_ticks[t]);
   803 			total_ticks[i] += (cpu_load_temp[i].cpu_ticks[t]);
   804 		}
   805 		load_ticks[i] = total_ticks[i] - cpu_load_temp[i].cpu_ticks[CPU_STATE_IDLE];
   806 		if ((load_ticks[i]) > temp_ticks)
   807 		{
   808 			temp_ticks = load_ticks[i];
   809 			cpu_maxload = i;
   810 		}
   811 		cpu_load_last[i] = cpu_load[i];
   812 	}
   813 	
   814 	*total = total_ticks[cpu_maxload];
   815 	*idle  = *total - load_ticks[cpu_maxload];
   816 	
   817 	dbg("Autothrottle: CPU load %d /10 pc\n", (1000 * (*total - *idle)) / *total);
   818 }
   819 
   820 
   821 
   822 bool perfTimerWrapper(OSObject* owner, IOTimerEventSource* src, int count) {
   823 	register AutoThrottler* objDriver = (AutoThrottler*) owner;
   824 	return (objDriver->perfTimerEvent(src, count));
   825 }
   826 
   827 
   828 bool AutoThrottler::perfTimerEvent(IOTimerEventSource* src, int count) {
   829 	uint32_t wantspeed,wantstep;
   830 	long idle, used, total;
   831 	
   832 	if (!enabled || !setupDone) return false;
   833 	
   834 	// gather stats
   835 	PStates[currentPState].TimesChosen++;
   836 	totalTimerEvents++;
   837 	
   838 	GetCPUTicks(&idle, &total);
   839 	
   840 	// Used = % used x 10
   841 	used = ((total - idle) * 1000) / total;
   842 	
   843 	// If used > 95% we can't really guess how much is needed, so step to highest speed
   844 	if (used >= 950)
   845 		wantspeed = PStates[0].AcpiFreq;
   846 	else // Otherwise wantspeed is the ideal frequency to maintain idle % target
   847 		wantspeed = (PStates[currentPState].AcpiFreq * (used + 1)) / targetCPULoad;
   848 	
   849 	wantstep = FindClosestPState(wantspeed);
   850 	
   851 	if (wantstep == currentPState) goto check_soon;
   852 	
   853 	currentPState = wantstep; // Assume we got the one we wanted
   854 	throttleAllCPUs(&PStates[currentPState]);
   855 	
   856 	perfTimer->setTimeoutMS(throttleQuantum * (NumberOfPStates - wantstep)); // Make the delay until the next check proportional to the speed we picked
   857 	return true;
   858 	
   859 check_soon:
   860 	perfTimer->setTimeoutMS(throttleQuantum);
   861 	return true;
   862 }
   863 
   864