예제 #1
0
파일: machine_check.c 프로젝트: DiogoPC/xnu
void
mca_cpu_init(void)
{
	unsigned int	i;

	/*
	 * The first (boot) processor is responsible for discovering the
	 * machine check architecture present on this machine.
	 */
	if (!mca_initialized) {
		mca_get_availability();
		mca_initialized = TRUE;
		simple_lock_init(&mca_lock, 0);
	}

	if (mca_MCA_present) {

		/* Enable all MCA features */
		if (mca_control_MSR_present)
			wrmsr64(IA32_MCG_CTL, IA32_MCG_CTL_ENABLE);
	
		switch (mca_family) {
		case 0x06:
			/* Enable all but mc0 */
			for (i = 1; i < mca_error_bank_count; i++)
				wrmsr64(IA32_MCi_CTL(i),0xFFFFFFFFFFFFFFFFULL); 
			
			/* Clear all errors */
			for (i = 0; i < mca_error_bank_count; i++)
				wrmsr64(IA32_MCi_STATUS(i), 0ULL);
			break;
		case 0x0F:
			/* Enable all banks */
			for (i = 0; i < mca_error_bank_count; i++)
				wrmsr64(IA32_MCi_CTL(i),0xFFFFFFFFFFFFFFFFULL); 
			
			/* Clear all errors */
			for (i = 0; i < mca_error_bank_count; i++)
				wrmsr64(IA32_MCi_STATUS(i), 0ULL);
			break;
		}
	}

	/* Enable machine check exception handling if available */
	if (mca_MCE_present) {
		set_cr4(get_cr4()|CR4_MCE);
	}
}
예제 #2
0
파일: Diagnostics.c 프로젝트: Bitesher/xnu
void cpu_pmc_control(void *enablep) {
	boolean_t enable = *(boolean_t *)enablep;
	cpu_data_t	*cdp = current_cpu_datap();

	if (enable) {
		wrmsr64(0x38F, 0x70000000FULL);
		wrmsr64(0x38D, 0x333);
		set_cr4(get_cr4() | CR4_PCE);

	} else {
		wrmsr64(0x38F, 0);
		wrmsr64(0x38D, 0);
		set_cr4((get_cr4() & ~CR4_PCE));
	}
	cdp->cpu_fixed_pmcs_enabled = enable;
}
예제 #3
0
파일: bsd_i386.c 프로젝트: SbIm/xnu-env
/*
 * thread_fast_set_cthread_self: Sets the machine kernel thread ID of the
 * current thread to the given thread ID; fast version for 32-bit processes
 *
 * Parameters:    self                    Thread ID to set
 *                
 * Returns:        0                      Success
 *                !0                      Not success
 */
kern_return_t
thread_fast_set_cthread_self(uint32_t self)
{
	thread_t thread = current_thread();
	pcb_t pcb = thread->machine.pcb;
	struct real_descriptor desc = {
		.limit_low = 1,
		.limit_high = 0,
		.base_low = self & 0xffff,
		.base_med = (self >> 16) & 0xff,
		.base_high = (self >> 24) & 0xff,
		.access = ACC_P|ACC_PL_U|ACC_DATA_W,
		.granularity = SZ_32|SZ_G,
	};

	current_thread()->machine.pcb->cthread_self = (uint64_t) self;	/* preserve old func too */

	/* assign descriptor */
	mp_disable_preemption();
	pcb->cthread_desc = desc;
	*ldt_desc_p(USER_CTHREAD) = desc;
	saved_state32(pcb->iss)->gs = USER_CTHREAD;
	mp_enable_preemption();

	return (USER_CTHREAD);
}

/*
 * thread_fast_set_cthread_self64: Sets the machine kernel thread ID of the
 * current thread to the given thread ID; fast version for 64-bit processes 
 *
 * Parameters:    self                    Thread ID
 *                
 * Returns:        0                      Success
 *                !0                      Not success
 */
kern_return_t
thread_fast_set_cthread_self64(uint64_t self)
{
	pcb_t pcb = current_thread()->machine.pcb;
	cpu_data_t              *cdp;

	/* check for canonical address, set 0 otherwise  */
	if (!IS_USERADDR64_CANONICAL(self))
		self = 0ULL;

	pcb->cthread_self = self;
	mp_disable_preemption();
	cdp = current_cpu_datap();
#if defined(__x86_64__)
	if ((cdp->cpu_uber.cu_user_gs_base != pcb->cthread_self) ||
	    (pcb->cthread_self != rdmsr64(MSR_IA32_KERNEL_GS_BASE)))
		wrmsr64(MSR_IA32_KERNEL_GS_BASE, self);
#endif
	cdp->cpu_uber.cu_user_gs_base = self;
	mp_enable_preemption();
	return (USER_CTHREAD);
}
예제 #4
0
파일: ucode.c 프로젝트: JackieXie168/xnu
/* Exceute the actual update! */
static void
update_microcode(void)
{
	/* SDM Example 9-8 code shows that we load the
	 * address of the UpdateData within the microcode blob,
	 * not the address of the header.
	 */
	wrmsr64(IA32_BIOS_UPDT_TRIG, (uint64_t)(uintptr_t)&global_update->data);
}
예제 #5
0
static void eist_update_action(void *t) {
 uint64_t msr;
 uint16_t vid;
 uint64_t v64;

 bcopy(t,&vid,2);

 v64=vid;
 
 msr = rdmsr64(MSR_PERF_CTL);
 msr = (msr & ~(uint64_t)(0xffff)) | v64;
 wrmsr64(MSR_PERF_CTL, msr);

 //intdbg("CPU%d: %s vid=%d\n", get_cpu_number(), __FUNCTION__,vid);
}
예제 #6
0
파일: vmx_cpu.c 프로젝트: SbIm/xnu-env
static void
vmx_init(void)
{
	uint64_t msr_image;

	if (!vmx_is_available())
		return;

	/*
	 * We don't count on EFI initializing MSR_IA32_FEATURE_CONTROL
	 * and turning VMXON on and locking the bit, so we do that now.
	 */
	msr_image = rdmsr64(MSR_IA32_FEATURE_CONTROL);
	if (0 == ((msr_image & MSR_IA32_FEATCTL_LOCK)))
		wrmsr64(MSR_IA32_FEATURE_CONTROL,
			(msr_image |
			 MSR_IA32_FEATCTL_VMXON |
			 MSR_IA32_FEATCTL_LOCK));
}
예제 #7
0
/*
 * Set MSRs for sysenter/sysexit for 64-bit.
 */
static void
fast_syscall_init64(void)
{
	wrmsr64(MSR_IA32_SYSENTER_CS, SYSENTER_CS); 
	wrmsr64(MSR_IA32_SYSENTER_EIP, UBER64(hi64_sysenter));
	wrmsr64(MSR_IA32_SYSENTER_ESP, UBER64(current_sstk()));

	/* Enable syscall/sysret */
	wrmsr64(MSR_IA32_EFER, rdmsr64(MSR_IA32_EFER) | MSR_IA32_EFER_SCE);

	/*
	 * MSRs for 64-bit syscall/sysret
	 * Note USER_CS because sysret uses this + 16 when returning to
	 * 64-bit code.
	 */
	wrmsr64(MSR_IA32_LSTAR, UBER64(hi64_syscall));
	wrmsr64(MSR_IA32_STAR, (((uint64_t)USER_CS)     << 48) |
			       (((uint64_t)KERNEL64_CS) << 32));
	/*
	 * Emulate eflags cleared by sysenter but note that
	 * we also clear the trace trap to avoid the complications
	 * of single-stepping into a syscall. The nested task bit
	 * is also cleared to avoid a spurious "task switch"
	 * should we choose to return via an IRET.
	 */
	wrmsr64(MSR_IA32_FMASK, EFL_DF|EFL_IF|EFL_TF|EFL_NT);

	/*
	 * Set the Kernel GS base MSR to point to per-cpu data in uber-space.
	 * The uber-space handler (hi64_syscall) uses the swapgs instruction.
	 */
	wrmsr64(MSR_IA32_KERNEL_GS_BASE,
		UBER64((unsigned long)current_cpu_datap()));

#if ONLY_SAFE_FOR_LINDA_SERIAL
	kprintf("fast_syscall_init64() KERNEL_GS_BASE=0x%016llx\n",
		rdmsr64(MSR_IA32_KERNEL_GS_BASE));
#endif
}
void throttleCPU(void *t) {
	uint64_t msr;
	PState p;
	uint32_t newfreq, oldfreq;

	bcopy(t,&p,sizeof(PState)); // get the ctl we want
	
	msr = rdmsr64(INTEL_MSR_PERF_STS); // read current MSR
	
	// For clock recalibration
	oldfreq = FID_to_Hz(FID(msr));
	// blank out last 32 bits and put our ctl there
	msr = (msr & 0xffffffffffff0000ULL) | CTL(p.Frequency, p.Voltage);
	newfreq = FID_to_Hz(FID(msr)); // after setting ctl in msr
	
	//if (RtcFixKernel && !ConstantTSC) {
		//rtc_clock_stepping(newfreq, oldfreq);
	//}
	
	wrmsr64(INTEL_MSR_PERF_CTL, msr); // and write it to the processor
	
	//if (RtcFixKernel && !ConstantTSC)
		//rtc_clock_stepped(newfreq, oldfreq);
}
예제 #9
0
파일: cpu.c 프로젝트: svn2github/chameleon
/*
 * Calculates the FSB and CPU frequencies using specific MSRs for each CPU
 * - multi. is read from a specific MSR. In the case of Intel, there is:
 *	   a max multi. (used to calculate the FSB freq.),
 *	   and a current multi. (used to calculate the CPU freq.)
 * - fsbFrequency = tscFrequency / multi
 * - cpuFrequency = fsbFrequency * multi
 */
void scan_cpu(PlatformInfo_t *p)
{
	uint64_t	tscFrequency = 0;
	uint64_t	fsbFrequency = 0;
	uint64_t	cpuFrequency =0;
	uint64_t	msr = 0;
	uint64_t	flex_ratio = 0;
	uint32_t	max_ratio = 0;
	uint32_t	min_ratio = 0;
	uint8_t		bus_ratio_max = 0;
	uint8_t		bus_ratio_min = 0;
	uint8_t		currdiv = 0;
	uint8_t		currcoef = 0;
	uint8_t		maxdiv = 0;
	uint8_t		maxcoef = 0;

	const char	*newratio;
	int		len = 0;
	
	/* get cpuid values */
	do_cpuid(0x00000000, p->CPU.CPUID[CPUID_0]);
	do_cpuid(0x00000001, p->CPU.CPUID[CPUID_1]);
	do_cpuid(0x00000002, p->CPU.CPUID[CPUID_2]);
	do_cpuid(0x00000003, p->CPU.CPUID[CPUID_3]);
	do_cpuid2(0x00000004, 0, p->CPU.CPUID[CPUID_4]);
	do_cpuid(0x80000000, p->CPU.CPUID[CPUID_80]);
	if (p->CPU.CPUID[CPUID_0][0] >= 0x5) {		
		do_cpuid(5,  p->CPU.CPUID[CPUID_5]);        	
	}	
	if (p->CPU.CPUID[CPUID_0][0] >= 6) {
		do_cpuid(6, p->CPU.CPUID[CPUID_6]);		
	}
	if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 8) {
		do_cpuid(0x80000008, p->CPU.CPUID[CPUID_88]);
		do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]);
	} else if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 1) {
		do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]);
	}
	
#if DEBUG_CPU
	{
		int		i;
		printf("CPUID Raw Values:\n");
		for (i=0; i<CPUID_MAX; i++) {
			printf("%02d: %08x-%08x-%08x-%08x\n", i,
				   p->CPU.CPUID[i][0], p->CPU.CPUID[i][1],
				   p->CPU.CPUID[i][2], p->CPU.CPUID[i][3]);
		}
	}
#endif
    
/*
    EAX (Intel):
    31    28 27            20 19    16 1514 1312 11     8 7      4 3      0
    +--------+----------------+--------+----+----+--------+--------+--------+
    |########|Extended family |Extmodel|####|type|familyid|  model |stepping|
    +--------+----------------+--------+----+----+--------+--------+--------+
     
    EAX (AMD):
    31    28 27            20 19    16 1514 1312 11     8 7      4 3      0
    +--------+----------------+--------+----+----+--------+--------+--------+
    |########|Extended family |Extmodel|####|####|familyid|  model |stepping|
   +--------+----------------+--------+----+----+--------+--------+--------+
*/
	
	p->CPU.Vendor		= p->CPU.CPUID[CPUID_0][1];
	p->CPU.Signature	= p->CPU.CPUID[CPUID_1][0];
    // stepping = cpu_feat_eax & 0xF;
	p->CPU.Stepping		= bitfield(p->CPU.CPUID[CPUID_1][0], 3, 0);
    // model = (cpu_feat_eax >> 4) & 0xF;
	p->CPU.Model		= bitfield(p->CPU.CPUID[CPUID_1][0], 7, 4);
    // family = (cpu_feat_eax >> 8) & 0xF;
	p->CPU.Family		= bitfield(p->CPU.CPUID[CPUID_1][0], 11, 8);
    // type = (cpu_feat_eax >> 12) & 0x3;
	//p->CPU.Type		= bitfield(p->CPU.CPUID[CPUID_1][0], 13, 12);
    // ext_model = (cpu_feat_eax >> 16) & 0xF;
	p->CPU.ExtModel		= bitfield(p->CPU.CPUID[CPUID_1][0], 19, 16);
    // ext_family = (cpu_feat_eax >> 20) & 0xFF;
	p->CPU.ExtFamily	= bitfield(p->CPU.CPUID[CPUID_1][0], 27, 20);
	
	p->CPU.Model += (p->CPU.ExtModel << 4);
	
	if (p->CPU.Vendor == CPUID_VENDOR_INTEL &&
		p->CPU.Family == 0x06 &&
		p->CPU.Model >= CPU_MODEL_NEHALEM &&
		p->CPU.Model != CPU_MODEL_ATOM		// MSR is *NOT* available on the Intel Atom CPU
		) {
		msr = rdmsr64(MSR_CORE_THREAD_COUNT);					// MacMan: Undocumented MSR in Nehalem and newer CPUs
		p->CPU.NoCores		= bitfield((uint32_t)msr, 31, 16);	// MacMan: Using undocumented MSR to get actual values
		p->CPU.NoThreads	= bitfield((uint32_t)msr, 15,  0);	// MacMan: Using undocumented MSR to get actual values
	} else if (p->CPU.Vendor == CPUID_VENDOR_AMD) {
		p->CPU.NoThreads	= bitfield(p->CPU.CPUID[CPUID_1][1], 23, 16);
		p->CPU.NoCores		= bitfield(p->CPU.CPUID[CPUID_88][2], 7, 0) + 1;
	} else {
		// Use previous method for Cores and Threads
		p->CPU.NoThreads	= bitfield(p->CPU.CPUID[CPUID_1][1], 23, 16);
		p->CPU.NoCores		= bitfield(p->CPU.CPUID[CPUID_4][0], 31, 26) + 1;
	}
	
	/* get brand string (if supported) */
	/* Copyright: from Apple's XNU cpuid.c */
	if (p->CPU.CPUID[CPUID_80][0] > 0x80000004) {
		uint32_t	reg[4];
		char		str[128], *s;
		/*
		 * The brand string 48 bytes (max), guaranteed to
		 * be NULL terminated.
		 */
		do_cpuid(0x80000002, reg);
		bcopy((char *)reg, &str[0], 16);
		do_cpuid(0x80000003, reg);
		bcopy((char *)reg, &str[16], 16);
		do_cpuid(0x80000004, reg);
		bcopy((char *)reg, &str[32], 16);
		for (s = str; *s != '\0'; s++) {
			if (*s != ' ') {
                break;
            }
		}
		
		strlcpy(p->CPU.BrandString, s, sizeof(p->CPU.BrandString));
		
		if (!strncmp(p->CPU.BrandString, CPU_STRING_UNKNOWN, MIN(sizeof(p->CPU.BrandString), strlen(CPU_STRING_UNKNOWN) + 1))) {
			/*
			 * This string means we have a firmware-programmable brand string,
			 * and the firmware couldn't figure out what sort of CPU we have.
			 */
			p->CPU.BrandString[0] = '\0';
		}
	}
	
	/* setup features */
	if ((bit(23) & p->CPU.CPUID[CPUID_1][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_MMX;
	}
	if ((bit(25) & p->CPU.CPUID[CPUID_1][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE;
	}
	if ((bit(26) & p->CPU.CPUID[CPUID_1][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE2;
	}
	if ((bit(0) & p->CPU.CPUID[CPUID_1][2]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE3;
	}
	if ((bit(19) & p->CPU.CPUID[CPUID_1][2]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE41;
	}
	if ((bit(20) & p->CPU.CPUID[CPUID_1][2]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE42;
	}
	if ((bit(29) & p->CPU.CPUID[CPUID_81][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_EM64T;
	}
	if ((bit(5) & p->CPU.CPUID[CPUID_1][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_MSR;
	}
	//if ((bit(28) & p->CPU.CPUID[CPUID_1][3]) != 0) {
	if (p->CPU.NoThreads > p->CPU.NoCores) {
		p->CPU.Features |= CPU_FEATURE_HTT;
	}
	
	tscFrequency = measure_tsc_frequency();
	/* if usual method failed */
	if ( tscFrequency < 1000 ) { //TEST
	tscFrequency = timeRDTSC() * 20;
	}
	fsbFrequency = 0;
	cpuFrequency = 0;
	
	if ((p->CPU.Vendor == CPUID_VENDOR_INTEL) && ((p->CPU.Family == 0x06) || (p->CPU.Family == 0x0f))) {
		int intelCPU = p->CPU.Model;
		if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0c) || (p->CPU.Family == 0x0f && p->CPU.Model >= 0x03)) {
			/* Nehalem CPU model */
			if (p->CPU.Family == 0x06 && (
                    p->CPU.Model == CPU_MODEL_NEHALEM       ||
					p->CPU.Model == CPU_MODEL_FIELDS        ||
					p->CPU.Model == CPU_MODEL_DALES         ||
					p->CPU.Model == CPU_MODEL_DALES_32NM    ||
					p->CPU.Model == CPU_MODEL_WESTMERE      ||
					p->CPU.Model == CPU_MODEL_NEHALEM_EX    ||
					p->CPU.Model == CPU_MODEL_WESTMERE_EX   ||
					p->CPU.Model == CPU_MODEL_SANDYBRIDGE   ||
					p->CPU.Model == CPU_MODEL_JAKETOWN      ||
					p->CPU.Model == CPU_MODEL_IVYBRIDGE     ||
                    p->CPU.Model == CPU_MODEL_IVYBRIDGE_XEON||
                    p->CPU.Model == CPU_MODEL_HASWELL       ||
					p->CPU.Model == CPU_MODEL_HASWELL_SVR   ||
					p->CPU.Model == CPU_MODEL_HASWELL_ULT   ||
					p->CPU.Model == CPU_MODEL_CRYSTALWELL )){
				msr = rdmsr64(MSR_PLATFORM_INFO);
//				DBG("msr(%d): platform_info %08x\n", __LINE__, bitfield(msr, 31, 0));
				bus_ratio_max = bitfield(msr, 15, 8);	//MacMan: Changed bitfield to match Apple tsc.c
 				bus_ratio_min = bitfield(msr, 47, 40);	//MacMan: Changed bitfield to match Apple tsc.c
				msr = rdmsr64(MSR_FLEX_RATIO);
//				DBG("msr(%d): flex_ratio %08x\n", __LINE__, bitfield(msr, 31, 0));
				if (bitfield(msr, 16, 16)) {
					flex_ratio = bitfield(msr, 15, 8);	//MacMan: Changed bitfield to match Apple tsc.c
					if (flex_ratio == 0) {
						/* Clear bit 16 (evidently the presence bit) */
						wrmsr64(MSR_FLEX_RATIO, (msr & 0xFFFFFFFFFFFEFFFFULL));
						msr = rdmsr64(MSR_FLEX_RATIO);
//						verbose("Unusable flex ratio detected. Patched MSR now %08x\n", bitfield(msr, 31, 0));
					} else {
						if (bus_ratio_max > flex_ratio) {
							bus_ratio_max = flex_ratio;
						}
					}
				}
				
				if (bus_ratio_max) {
					fsbFrequency = (tscFrequency / bus_ratio_max);
				}
				//MacMan: Turbo Ratio Limit
				switch (intelCPU) 
				{
					case CPU_MODEL_WESTMERE_EX:     // Intel Xeon E7
					case CPU_MODEL_NEHALEM_EX:      // Intel Xeon X75xx, Xeon X65xx, Xeon E75xx, Xeon E65xx
					{
						cpuFrequency = tscFrequency;
						DBG("cpu.c (%d)CPU_MODEL_NEHALEM_EX or CPU_MODEL_WESTMERE_EX Found\n", __LINE__);
						break;
					}
					case CPU_MODEL_SANDYBRIDGE:     // Intel Core i3, i5, i7 LGA1155 (32nm)
					case CPU_MODEL_IVYBRIDGE:       // Intel Core i3, i5, i7 LGA1155 (22nm)
					case CPU_MODEL_JAKETOWN:        // Intel Core i7, Xeon E5 LGA2011 (32nm)
                    case CPU_MODEL_IVYBRIDGE_XEON:  // Intel Core i7, Xeon E5 LGA2011 (22nm)
                    case CPU_MODEL_HASWELL:         // Intel Core i3, i5, i7, Xeon E3 LGA1050 (22nm)
                    case CPU_MODEL_HASWELL_ULT:
                    case CPU_MODEL_CRYSTALWELL:
					{
						msr = rdmsr64(MSR_IA32_PERF_STATUS);
						currcoef = bitfield(msr, 15, 8);
						cpuFrequency = currcoef * fsbFrequency;
						maxcoef = bus_ratio_max;
						break;
					}
					default:
					{
						msr = rdmsr64(MSR_IA32_PERF_STATUS);
						currcoef = bitfield(msr, 7, 0);
						cpuFrequency = currcoef * fsbFrequency;
						maxcoef = bus_ratio_max;
						break;
					}
				}

				if ((getValueForKey(kbusratio, &newratio, &len, &bootInfo->chameleonConfig)) && (len <= 4)) {
					max_ratio = atoi(newratio);
					max_ratio = (max_ratio * 10);
					if (len >= 3) {
                        max_ratio = (max_ratio + 5);
                    }
                    
					verbose("Bus-Ratio: min=%d, max=%s\n", bus_ratio_min, newratio);
					
					// extreme overclockers may love 320 ;)
					if ((max_ratio >= min_ratio) && (max_ratio <= 320)) {
						cpuFrequency = (fsbFrequency * max_ratio) / 10;
						if (len >= 3) {
                            maxdiv = 1;
                        } else {
                            maxdiv = 0;
                        }
					} else {
						max_ratio = (bus_ratio_max * 10);
					}
				}
				p->CPU.MaxRatio = bus_ratio_max;
				p->CPU.MinRatio = bus_ratio_min;
			} else {
				msr = rdmsr64(MSR_IA32_PERF_STATUS);
				DBG("msr(%d): ia32_perf_stat 0x%08x\n", __LINE__, bitfield(msr, 31, 0));
				currcoef = bitfield(msr, 15, 8);                //MacMan: Fixed bitfield to Intel documentation
				/* Non-integer bus ratio for the max-multi*/
				maxdiv = bitfield(msr, 46, 46);
				/* Non-integer bus ratio for the current-multi (undocumented)*/
				currdiv = bitfield(msr, 14, 14);
				
				// This will always be model >= 3
				if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0e) || (p->CPU.Family == 0x0f)) {
					/* On these models, maxcoef defines TSC freq */
					maxcoef = bitfield(msr, 44, 40);
				} else {
					/* On lower models, currcoef defines TSC freq */
					/* XXX */
					maxcoef = currcoef;
				}
				
				if (maxcoef) {
					if (maxdiv) {
						fsbFrequency = ((tscFrequency * 2) / ((maxcoef * 2) + 1));
					} else {
						fsbFrequency = (tscFrequency / maxcoef);
					}
					if (currdiv) {
						cpuFrequency = (fsbFrequency * ((currcoef * 2) + 1) / 2);
					} else {
						cpuFrequency = (fsbFrequency * currcoef);
					}
					DBG("max: %d%s current: %d%s\n", maxcoef, maxdiv ? ".5" : "",currcoef, currdiv ? ".5" : "");
				}
			}
		}
		/* Mobile CPU */
		if (rdmsr64(MSR_IA32_PLATFORM_ID) & (1<<28)) {
			p->CPU.Features |= CPU_FEATURE_MOBILE;
		}
	} else if ((p->CPU.Vendor == CPUID_VENDOR_AMD) && (p->CPU.Family == 0x0f)) {
		switch(p->CPU.ExtFamily) {
			case 0x00: /* K8 */
				msr = rdmsr64(K8_FIDVID_STATUS);
				maxcoef = bitfield(msr, 21, 16) / 2 + 4;
				currcoef = bitfield(msr, 5, 0) / 2 + 4;
				break;
				
			case 0x01: /* K10 */
				msr = rdmsr64(K10_COFVID_STATUS);
				do_cpuid2(0x00000006, 0, p->CPU.CPUID[CPUID_6]);
				// EffFreq: effective frequency interface
				if (bitfield(p->CPU.CPUID[CPUID_6][2], 0, 0) == 1) {
					//uint64_t mperf = measure_mperf_frequency();
					uint64_t aperf = measure_aperf_frequency();
					cpuFrequency = aperf;
				}
				// NOTE: tsc runs at the maccoeff (non turbo)
				//			*not* at the turbo frequency.
				maxcoef	 = bitfield(msr, 54, 49) / 2 + 4;
				currcoef = bitfield(msr, 5, 0) + 0x10;
				currdiv = 2 << bitfield(msr, 8, 6);
				
				break;
				
			case 0x05: /* K14 */
				msr = rdmsr64(K10_COFVID_STATUS);
				currcoef  = (bitfield(msr, 54, 49) + 0x10) << 2;
				currdiv = (bitfield(msr, 8, 4) + 1) << 2;
				currdiv += bitfield(msr, 3, 0);
				
				break;
				
			case 0x02: /* K11 */
				// not implimented
				break;
		}
		
		if (maxcoef) {
			if (currdiv) {
				if (!currcoef) {
                    currcoef = maxcoef;
                }
                
				if (!cpuFrequency) {
					fsbFrequency = ((tscFrequency * currdiv) / currcoef);
				} else {
					fsbFrequency = ((cpuFrequency * currdiv) / currcoef);
				}
				DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv);
			} else {
				if (!cpuFrequency) {
					fsbFrequency = (tscFrequency / maxcoef);
				} else {
					fsbFrequency = (cpuFrequency / maxcoef);
                }
				DBG("%d\n", currcoef);
			}
		} else if (currcoef) {
			if (currdiv) {
				fsbFrequency = ((tscFrequency * currdiv) / currcoef);
				DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv);
			} else {
				fsbFrequency = (tscFrequency / currcoef);
				DBG("%d\n", currcoef);
			}
		}
		if (!cpuFrequency) cpuFrequency = tscFrequency;
	}
	
#if 0
	if (!fsbFrequency) {
		fsbFrequency = (DEFAULT_FSB * 1000);
		cpuFrequency = tscFrequency;
		DBG("0 ! using the default value for FSB !\n");
	}
#endif
	
	p->CPU.MaxCoef = maxcoef;
	if (maxdiv == 0){
		p->CPU.MaxDiv = bus_ratio_max;
	} else {
		p->CPU.MaxDiv = maxdiv;
	}
	p->CPU.CurrCoef = currcoef;
	if (currdiv == 0){
		p->CPU.CurrDiv = currcoef;
	} else {
		p->CPU.CurrDiv = currdiv;
	}
	p->CPU.TSCFrequency = tscFrequency;
	p->CPU.FSBFrequency = fsbFrequency;
	p->CPU.CPUFrequency = cpuFrequency;
	
	// keep formatted with spaces instead of tabs
	DBG("CPU: Brand String:                %s\n",                 p->CPU.BrandString);
	DBG("CPU: Vendor:                      0x%x\n",				  p->CPU.Vendor);
	DBG("CPU: Family / ExtFamily:          0x%x / 0x%x\n",		  p->CPU.Family, p->CPU.ExtFamily);
	DBG("CPU: Model / ExtModel / Stepping: 0x%x / 0x%x / 0x%x\n", p->CPU.Model, p->CPU.ExtModel, p->CPU.Stepping);
	DBG("CPU: Number of Cores / Threads:   %d / %d\n",            p->CPU.NoCores, p->CPU.NoThreads);
	DBG("CPU: Features:                    0x%08x\n",             p->CPU.Features);
	DBG("CPU: TSC Frequency:               %d MHz\n",             p->CPU.TSCFrequency / 1000000);
	DBG("CPU: FSB Frequency:               %d MHz\n",             p->CPU.FSBFrequency / 1000000);
	DBG("CPU: CPU Frequency:               %d MHz\n",             p->CPU.CPUFrequency / 1000000);
	DBG("CPU: Minimum Bus Ratio:           %d\n",                 p->CPU.MinRatio);
	DBG("CPU: Maximum Bus Ratio:           %d\n",                 p->CPU.MaxRatio);
	DBG("CPU: Current Bus Ratio:           %d\n",                 p->CPU.CurrCoef);
//	DBG("CPU: Maximum Multiplier:          %d\n",				  p->CPU.MaxCoef);
//	DBG("CPU: Maximum Divider:             %d\n",				  p->CPU.MaxDiv);
//	DBG("CPU: Current Divider:             %d\n",				  p->CPU.CurrDiv);

#if DEBUG_CPU
	pause();
#endif
}
예제 #10
0
파일: cpu.c 프로젝트: svn2github/chameleon
/*
 * Calculates the FSB and CPU frequencies using specific MSRs for each CPU
 * - multi. is read from a specific MSR. In the case of Intel, there is:
 *	   a max multi. (used to calculate the FSB freq.),
 *	   and a current multi. (used to calculate the CPU freq.)
 * - fsbFrequency = tscFrequency / multi
 * - cpuFrequency = fsbFrequency * multi
 */
void scan_cpu(PlatformInfo_t *p)
{
	uint64_t	tscFrequency = 0;
	uint64_t	fsbFrequency = 0;
	uint64_t	cpuFrequency = 0;
	uint64_t	msr = 0;
	uint64_t	flex_ratio = 0;
	uint32_t	max_ratio = 0;
	uint32_t	min_ratio = 0;
	uint8_t		bus_ratio_max = 0;
	uint8_t		currdiv = 0;
	uint8_t		currcoef = 0;
	uint8_t		maxdiv = 0;
	uint8_t		maxcoef = 0;
	const char	*newratio;
	int		len = 0;
	int		myfsb = 0;
	uint8_t		bus_ratio_min = 0;
	uint32_t	reg[4];
	char		str[128];

	/* get cpuid values */
	do_cpuid(0x00000000, p->CPU.CPUID[CPUID_0]);
	do_cpuid(0x00000001, p->CPU.CPUID[CPUID_1]);

	do_cpuid(0x00000002, p->CPU.CPUID[CPUID_2]);
	do_cpuid(0x00000003, p->CPU.CPUID[CPUID_3]);
	do_cpuid2(0x00000004, 0, p->CPU.CPUID[CPUID_4]);

	do_cpuid(0x80000000, p->CPU.CPUID[CPUID_80]);
	if (p->CPU.CPUID[CPUID_0][0] >= 0x5) {
		do_cpuid(5,  p->CPU.CPUID[CPUID_5]);
	}
	if (p->CPU.CPUID[CPUID_0][0] >= 6) {
		do_cpuid(6, p->CPU.CPUID[CPUID_6]);
	}
	if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 8) {
		do_cpuid(0x80000008, p->CPU.CPUID[CPUID_88]);
		do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]);
	} else if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 1) {
		do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]);
	}

// #if DEBUG_CPU
	{
		int		i;
		DBG("CPUID Raw Values:\n");
		for (i = 0; i < CPUID_MAX; i++) {
			DBG("%02d: %08x-%08x-%08x-%08x\n", i,
				   p->CPU.CPUID[i][0], p->CPU.CPUID[i][1],
				   p->CPU.CPUID[i][2], p->CPU.CPUID[i][3]);
		}
	}
// #endif

/*
    EAX (Intel):
    31    28 27            20 19    16 1514 1312 11     8 7      4 3      0
    +--------+----------------+--------+----+----+--------+--------+--------+
    |########|Extended family |Extmodel|####|type|familyid|  model |stepping|
    +--------+----------------+--------+----+----+--------+--------+--------+

    EAX (AMD):
    31    28 27            20 19    16 1514 1312 11     8 7      4 3      0
    +--------+----------------+--------+----+----+--------+--------+--------+
    |########|Extended family |Extmodel|####|####|familyid|  model |stepping|
    +--------+----------------+--------+----+----+--------+--------+--------+
*/

	p->CPU.Vendor		= p->CPU.CPUID[CPUID_0][1];
	p->CPU.Signature	= p->CPU.CPUID[CPUID_1][0];
	p->CPU.Stepping		= (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 3, 0);	// stepping = cpu_feat_eax & 0xF;
	p->CPU.Model		= (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 7, 4);	// model = (cpu_feat_eax >> 4) & 0xF;
	p->CPU.Family		= (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 11, 8);	// family = (cpu_feat_eax >> 8) & 0xF;
	//p->CPU.Type		= (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 13, 12);	// type = (cpu_feat_eax >> 12) & 0x3;
	p->CPU.ExtModel		= (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 19, 16);	// ext_model = (cpu_feat_eax >> 16) & 0xF;
	p->CPU.ExtFamily	= (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 27, 20);	// ext_family = (cpu_feat_eax >> 20) & 0xFF;

	p->CPU.Model += (p->CPU.ExtModel << 4);

	if (p->CPU.Vendor == CPUID_VENDOR_INTEL)
	{
		/*
		 * Find the number of enabled cores and threads
		 * (which determines whether SMT/Hyperthreading is active).
		 */
		switch (p->CPU.Model)
		{
			case CPU_MODEL_NEHALEM:
			case CPU_MODEL_FIELDS:
			case CPU_MODEL_DALES:
			case CPU_MODEL_NEHALEM_EX:
			case CPU_MODEL_JAKETOWN:
			case CPU_MODEL_SANDYBRIDGE:
			case CPU_MODEL_IVYBRIDGE:
			case CPU_MODEL_HASWELL:
			case CPU_MODEL_HASWELL_SVR:
			//case CPU_MODEL_HASWELL_H:
			case CPU_MODEL_HASWELL_ULT:
			case CPU_MODEL_CRYSTALWELL:
				msr = rdmsr64(MSR_CORE_THREAD_COUNT);
				p->CPU.NoCores		= (uint8_t)bitfield((uint32_t)msr, 31, 16);
				p->CPU.NoThreads	= (uint8_t)bitfield((uint32_t)msr, 15,  0);
				break;

			case CPU_MODEL_DALES_32NM:
			case CPU_MODEL_WESTMERE:
			case CPU_MODEL_WESTMERE_EX:
				msr = rdmsr64(MSR_CORE_THREAD_COUNT);
				p->CPU.NoCores		= (uint8_t)bitfield((uint32_t)msr, 19, 16);
				p->CPU.NoThreads	= (uint8_t)bitfield((uint32_t)msr, 15,  0);
				break;

			default:
				p->CPU.NoCores = 0;
				break;
		} // end switch
	}

	if (p->CPU.NoCores == 0)
	{
		p->CPU.NoCores		= (uint8_t)(p->CPU.CoresPerPackage & 0xff);
		p->CPU.NoThreads	= (uint8_t)(p->CPU.LogicalPerPackage & 0xff);
	}

	/* get BrandString (if supported) */
	/* Copyright: from Apple's XNU cpuid.c */
	if (p->CPU.CPUID[CPUID_80][0] > 0x80000004)
	{
		char	 *s;
		bzero(str, 128);
		/*
		 * The BrandString 48 bytes (max), guaranteed to
		 * be NULL terminated.
		 */
		do_cpuid(0x80000002, reg);
		memcpy(&str[0], (char *)reg, 16);
		do_cpuid(0x80000003, reg);
		memcpy(&str[16], (char *)reg, 16);
		do_cpuid(0x80000004, reg);
		memcpy(&str[32], (char *)reg, 16);
		for (s = str; *s != '\0'; s++)
		{
			if (*s != ' ')
			{
				break;
			}
		}
		strlcpy(p->CPU.BrandString, s, 48);

		if (!strncmp(p->CPU.BrandString, CPU_STRING_UNKNOWN, MIN(sizeof(p->CPU.BrandString), strlen(CPU_STRING_UNKNOWN) + 1)))
		{
			/*
			 * This string means we have a firmware-programmable brand string,
			 * and the firmware couldn't figure out what sort of CPU we have.
			 */
			p->CPU.BrandString[0] = '\0';
		}
		p->CPU.BrandString[47] = '\0';
//		DBG("Brandstring = %s\n", p->CPU.BrandString);
	}

	//workaround for N270. I don't know why it detected wrong
	// MSR is *NOT* available on the Intel Atom CPU
	if ((p->CPU.Model == CPU_MODEL_ATOM) && (strstr(p->CPU.BrandString, "270")))
	{
		p->CPU.NoCores		= 1;
		p->CPU.NoThreads	= 2;
	}

	if (p->CPU.Vendor == CPUID_VENDOR_AMD)
	{
		p->CPU.NoThreads	= (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][1], 23, 16);
		p->CPU.NoCores		= (uint8_t)bitfield(p->CPU.CPUID[CPUID_88][2], 7, 0) + 1;
	}

	/* setup features */
	if ((bit(23) & p->CPU.CPUID[CPUID_1][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_MMX;
	}
	if ((bit(25) & p->CPU.CPUID[CPUID_1][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE;
	}
	if ((bit(26) & p->CPU.CPUID[CPUID_1][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE2;
	}
	if ((bit(0) & p->CPU.CPUID[CPUID_1][2]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE3;
	}
	if ((bit(19) & p->CPU.CPUID[CPUID_1][2]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE41;
	}
	if ((bit(20) & p->CPU.CPUID[CPUID_1][2]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE42;
	}
	if ((bit(29) & p->CPU.CPUID[CPUID_81][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_EM64T;
	}
	if ((bit(5) & p->CPU.CPUID[CPUID_1][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_MSR;
	}
	//if ((bit(28) & p->CPU.CPUID[CPUID_1][3]) != 0) {
	if (p->CPU.NoThreads > p->CPU.NoCores) {
		p->CPU.Features |= CPU_FEATURE_HTT;
	}

	tscFrequency = measure_tsc_frequency();
	DBG("cpu freq classic = 0x%016llx\n", tscFrequency);
	/* if usual method failed */
	if ( tscFrequency < 1000 )	//TEST
	{
		tscFrequency = timeRDTSC() * 20;//measure_tsc_frequency();
		// DBG("cpu freq timeRDTSC = 0x%016llx\n", tscFrequency);
	} else {
		// DBG("cpu freq timeRDTSC = 0x%016llxn", timeRDTSC() * 20);
	}

	fsbFrequency = 0;
	cpuFrequency = 0;

	if (p->CPU.Vendor == CPUID_VENDOR_INTEL && ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0c) || (p->CPU.Family == 0x0f && p->CPU.Model >= 0x03))) {
		int intelCPU = p->CPU.Model;
		if (p->CPU.Family == 0x06) {
			/* Nehalem CPU model */
			switch (p->CPU.Model) {
				case CPU_MODEL_NEHALEM:
				case CPU_MODEL_FIELDS:
				case CPU_MODEL_DALES:
				case CPU_MODEL_DALES_32NM:
				case CPU_MODEL_WESTMERE:
				case CPU_MODEL_NEHALEM_EX:
				case CPU_MODEL_WESTMERE_EX:
/* --------------------------------------------------------- */
				case CPU_MODEL_SANDYBRIDGE:
				case CPU_MODEL_JAKETOWN:
				case CPU_MODEL_IVYBRIDGE_XEON:
				case CPU_MODEL_IVYBRIDGE:
				case CPU_MODEL_HASWELL:
				case CPU_MODEL_HASWELL_SVR:

				case CPU_MODEL_HASWELL_ULT:
				case CPU_MODEL_CRYSTALWELL:
/* --------------------------------------------------------- */
					msr = rdmsr64(MSR_PLATFORM_INFO);
					DBG("msr(%d): platform_info %08x\n", __LINE__, bitfield(msr, 31, 0));
					bus_ratio_max = bitfield(msr, 15, 8);
					bus_ratio_min = bitfield(msr, 47, 40); //valv: not sure about this one (Remarq.1)
					msr = rdmsr64(MSR_FLEX_RATIO);
					DBG("msr(%d): flex_ratio %08x\n", __LINE__, bitfield(msr, 31, 0));
					if (bitfield(msr, 16, 16))
					{
						flex_ratio = bitfield(msr, 15, 8);
						/* bcc9: at least on the gigabyte h67ma-ud2h,
						 where the cpu multipler can't be changed to
						 allow overclocking, the flex_ratio msr has unexpected (to OSX)
						 contents.	These contents cause mach_kernel to
						 fail to compute the bus ratio correctly, instead
						 causing the system to crash since tscGranularity
						 is inadvertently set to 0.
						 */
						if (flex_ratio == 0)
						{
							/* Clear bit 16 (evidently the presence bit) */
							wrmsr64(MSR_FLEX_RATIO, (msr & 0xFFFFFFFFFFFEFFFFULL));
							msr = rdmsr64(MSR_FLEX_RATIO);
							DBG("Unusable flex ratio detected. Patched MSR now %08x\n", bitfield(msr, 31, 0));
						}
						else
						{
							if (bus_ratio_max > flex_ratio)
							{
								bus_ratio_max = flex_ratio;
							}
						}
					}

					if (bus_ratio_max)
					{
						fsbFrequency = (tscFrequency / bus_ratio_max);
					}

					//valv: Turbo Ratio Limit
					if ((intelCPU != 0x2e) && (intelCPU != 0x2f))
					{
						msr = rdmsr64(MSR_TURBO_RATIO_LIMIT);

						cpuFrequency = bus_ratio_max * fsbFrequency;
						max_ratio = bus_ratio_max * 10;
					}
					else
					{
						cpuFrequency = tscFrequency;
					}
					if ((getValueForKey(kbusratio, &newratio, &len, &bootInfo->chameleonConfig)) && (len <= 4))
					{
						max_ratio = atoi(newratio);
						max_ratio = (max_ratio * 10);
						if (len >= 3)
						{
							max_ratio = (max_ratio + 5);
						}

						verbose("Bus-Ratio: min=%d, max=%s\n", bus_ratio_min, newratio);

						// extreme overclockers may love 320 ;)
						if ((max_ratio >= min_ratio) && (max_ratio <= 320))
						{
							cpuFrequency = (fsbFrequency * max_ratio) / 10;
							if (len >= 3)
							{
								maxdiv = 1;
							}
							else
							{
								maxdiv = 0;
							}
						}
						else
						{
							max_ratio = (bus_ratio_max * 10);
						}
					}
					//valv: to be uncommented if Remarq.1 didn't stick
					/*if (bus_ratio_max > 0) bus_ratio = flex_ratio;*/
					p->CPU.MaxRatio = max_ratio;
					p->CPU.MinRatio = min_ratio;

				myfsb = fsbFrequency / 1000000;
				verbose("Sticking with [BCLK: %dMhz, Bus-Ratio: %d]\n", myfsb, max_ratio/10);  // Bungo: fixed wrong Bus-Ratio readout
				currcoef = bus_ratio_max;

				break;

			default:
				msr = rdmsr64(MSR_IA32_PERF_STATUS);
				DBG("msr(%d): ia32_perf_stat 0x%08x\n", __LINE__, bitfield(msr, 31, 0));
				currcoef = bitfield(msr, 12, 8);  // Bungo: reverted to 2263 state because of wrong old CPUs freq. calculating
				/* Non-integer bus ratio for the max-multi*/
				maxdiv = bitfield(msr, 46, 46);
				/* Non-integer bus ratio for the current-multi (undocumented)*/
				currdiv = bitfield(msr, 14, 14);

				// This will always be model >= 3
				if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0e) || (p->CPU.Family == 0x0f)) {
					/* On these models, maxcoef defines TSC freq */
					maxcoef = bitfield(msr, 44, 40);
				} else {
					/* On lower models, currcoef defines TSC freq */
					/* XXX */
					maxcoef = currcoef;
				}

				if (maxcoef) {
					if (maxdiv) {
						fsbFrequency = ((tscFrequency * 2) / ((maxcoef * 2) + 1));
					} else {
						fsbFrequency = (tscFrequency / maxcoef);
					}
					if (currdiv) {
						cpuFrequency = (fsbFrequency * ((currcoef * 2) + 1) / 2);
					} else {
						cpuFrequency = (fsbFrequency * currcoef);
					}
					DBG("max: %d%s current: %d%s\n", maxcoef, maxdiv ? ".5" : "",currcoef, currdiv ? ".5" : "");
				}
				break;
			}
		}
		/* Mobile CPU */
		if (rdmsr64(MSR_IA32_PLATFORM_ID) & (1<<28)) {
			p->CPU.Features |= CPU_FEATURE_MOBILE;
		}
	} else if ((p->CPU.Vendor == CPUID_VENDOR_AMD) && (p->CPU.Family == 0x0f)) {
		switch(p->CPU.ExtFamily) {
			case 0x00: /* K8 */
				msr = rdmsr64(K8_FIDVID_STATUS);
				maxcoef = bitfield(msr, 21, 16) / 2 + 4;
				currcoef = bitfield(msr, 5, 0) / 2 + 4;
				break;

			case 0x01: /* K10 */
				msr = rdmsr64(K10_COFVID_STATUS);
				do_cpuid2(0x00000006, 0, p->CPU.CPUID[CPUID_6]);
				// EffFreq: effective frequency interface
				if (bitfield(p->CPU.CPUID[CPUID_6][2], 0, 0) == 1) {
					//uint64_t mperf = measure_mperf_frequency();
					uint64_t aperf = measure_aperf_frequency();
					cpuFrequency = aperf;
				}
				// NOTE: tsc runs at the maccoeff (non turbo)
				//			*not* at the turbo frequency.
				maxcoef	 = bitfield(msr, 54, 49) / 2 + 4;
				currcoef = bitfield(msr, 5, 0) + 0x10;
				currdiv = 2 << bitfield(msr, 8, 6);

				break;

			case 0x05: /* K14 */
				msr = rdmsr64(K10_COFVID_STATUS);
				currcoef  = (bitfield(msr, 54, 49) + 0x10) << 2;
				currdiv = (bitfield(msr, 8, 4) + 1) << 2;
				currdiv += bitfield(msr, 3, 0);

				break;

			case 0x02: /* K11 */
				// not implimented
				break;
		}

		if (maxcoef) {
			if (currdiv) {
				if (!currcoef) {
					currcoef = maxcoef;
				}

				if (!cpuFrequency) {
					fsbFrequency = ((tscFrequency * currdiv) / currcoef);
				} else {
					fsbFrequency = ((cpuFrequency * currdiv) / currcoef);
				}
				DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv);
			} else {
				if (!cpuFrequency) {
					fsbFrequency = (tscFrequency / maxcoef);
				} else {
					fsbFrequency = (cpuFrequency / maxcoef);
				}
				DBG("%d\n", currcoef);
			}
		} else if (currcoef) {
			if (currdiv) {
				fsbFrequency = ((tscFrequency * currdiv) / currcoef);
				DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv);
			} else {
				fsbFrequency = (tscFrequency / currcoef);
				DBG("%d\n", currcoef);
			}
		}
		if (!cpuFrequency) cpuFrequency = tscFrequency;
	}
	
#if 0
	if (!fsbFrequency) {
		fsbFrequency = (DEFAULT_FSB * 1000);
		cpuFrequency = tscFrequency;
		DBG("0 ! using the default value for FSB !\n");
	}

	DBG("cpu freq = 0x%016llxn", timeRDTSC() * 20);

#endif

	p->CPU.MaxCoef = maxcoef;
	p->CPU.MaxDiv = maxdiv;
	p->CPU.CurrCoef = currcoef;
	p->CPU.CurrDiv = currdiv;
	p->CPU.TSCFrequency = tscFrequency;
	p->CPU.FSBFrequency = fsbFrequency;
	p->CPU.CPUFrequency = cpuFrequency;

	// keep formatted with spaces instead of tabs
	DBG("\n---------------------------------------------\n");
   	DBG("------------------ CPU INFO -----------------\n");
	DBG("---------------------------------------------\n");
	DBG("Brand String:            %s\n",                 p->CPU.BrandString); // Processor name (BIOS)
	DBG("Vendor:                  0x%x\n",               p->CPU.Vendor); // Vendor ex: GenuineIntel
	DBG("Family:                  0x%x\n",               p->CPU.Family); // Family ex: 6 (06h)
	DBG("ExtFamily:               0x%x\n",               p->CPU.ExtFamily);
	DBG("Signature:               %x\n",                 p->CPU.Signature); // CPUID signature
	DBG("Model:                   0x%x\n",               p->CPU.Model); // Model ex: 37 (025h)
	DBG("ExtModel:                0x%x\n",               p->CPU.ExtModel);
	DBG("Stepping:                0x%x\n",               p->CPU.Stepping); // Stepping ex: 5 (05h)
	DBG("MaxCoef:                 0x%x\n",               p->CPU.MaxCoef);
	DBG("CurrCoef:                0x%x\n",               p->CPU.CurrCoef);
	DBG("MaxDiv:                  0x%x\n",               p->CPU.MaxDiv);
	DBG("CurrDiv:                 0x%x\n",               p->CPU.CurrDiv);
	DBG("TSCFreq:                 %dMHz\n",              p->CPU.TSCFrequency / 1000000);
	DBG("FSBFreq:                 %dMHz\n",              p->CPU.FSBFrequency / 1000000);
	DBG("CPUFreq:                 %dMHz\n",              p->CPU.CPUFrequency / 1000000);
	DBG("Cores:                   %d\n",                 p->CPU.NoCores); // Cores
	DBG("Logical processor:       %d\n",                 p->CPU.NoThreads); // Logical procesor
	DBG("Features:                0x%08x\n",             p->CPU.Features);

	DBG("\n---------------------------------------------\n");
#if DEBUG_CPU
	pause();
#endif
}
예제 #11
0
파일: cpu.c 프로젝트: RemC/Chameleon
/*
 * Calculates the FSB and CPU frequencies using specific MSRs for each CPU
 * - multi. is read from a specific MSR. In the case of Intel, there is:
 *	   a max multi. (used to calculate the FSB freq.),
 *	   and a current multi. (used to calculate the CPU freq.)
 * - fsbFrequency = tscFrequency / multi
 * - cpuFrequency = fsbFrequency * multi
 */
void scan_cpu(PlatformInfo_t *p)
{
	uint64_t	tscFrequency, fsbFrequency, cpuFrequency;
	uint64_t	msr, flex_ratio;
	uint8_t		maxcoef, maxdiv, currcoef, bus_ratio_max, currdiv;
	const char	*newratio;
	int			len, myfsb;
	uint8_t		bus_ratio_min;
	uint32_t	max_ratio, min_ratio;
	
	max_ratio = min_ratio = myfsb = bus_ratio_min = 0;
	maxcoef = maxdiv = bus_ratio_max = currcoef = currdiv = 0;
	
	/* get cpuid values */
	do_cpuid(0x00000000, p->CPU.CPUID[CPUID_0]);
	do_cpuid(0x00000001, p->CPU.CPUID[CPUID_1]);
	do_cpuid(0x00000002, p->CPU.CPUID[CPUID_2]);
	do_cpuid(0x00000003, p->CPU.CPUID[CPUID_3]);
	do_cpuid2(0x00000004, 0, p->CPU.CPUID[CPUID_4]);
	do_cpuid(0x80000000, p->CPU.CPUID[CPUID_80]);
	if (p->CPU.CPUID[CPUID_0][0] >= 0x5) {		
		do_cpuid(5,  p->CPU.CPUID[CPUID_5]);        	
	}	
	if (p->CPU.CPUID[CPUID_0][0] >= 6) {
		do_cpuid(6, p->CPU.CPUID[CPUID_6]);		
	}
	if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 8) {
		do_cpuid(0x80000008, p->CPU.CPUID[CPUID_88]);
		do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]);
	}
	else if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 1) {
		do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]);
	}
	
#if DEBUG_CPU
	{
		int		i;
		printf("CPUID Raw Values:\n");
		for (i=0; i<CPUID_MAX; i++) {
			printf("%02d: %08x-%08x-%08x-%08x\n", i,
				   p->CPU.CPUID[i][0], p->CPU.CPUID[i][1],
				   p->CPU.CPUID[i][2], p->CPU.CPUID[i][3]);
		}
	}
#endif
	
	p->CPU.Vendor		= p->CPU.CPUID[CPUID_0][1];
	p->CPU.Signature	= p->CPU.CPUID[CPUID_1][0];
	p->CPU.Stepping		= bitfield(p->CPU.CPUID[CPUID_1][0], 3, 0);
	p->CPU.Model		= bitfield(p->CPU.CPUID[CPUID_1][0], 7, 4);
	p->CPU.Family		= bitfield(p->CPU.CPUID[CPUID_1][0], 11, 8);
	p->CPU.ExtModel		= bitfield(p->CPU.CPUID[CPUID_1][0], 19, 16);
	p->CPU.ExtFamily	= bitfield(p->CPU.CPUID[CPUID_1][0], 27, 20);
	
	p->CPU.Model += (p->CPU.ExtModel << 4);
	
	if (p->CPU.Vendor == CPUID_VENDOR_INTEL &&
		p->CPU.Family == 0x06 &&
		p->CPU.Model >= CPUID_MODEL_NEHALEM &&
		p->CPU.Model != CPUID_MODEL_ATOM		// MSR is *NOT* available on the Intel Atom CPU
		)
	{
		msr = rdmsr64(MSR_CORE_THREAD_COUNT);					// Undocumented MSR in Nehalem and newer CPUs
		p->CPU.NoCores		= bitfield((uint32_t)msr, 31, 16);	// Using undocumented MSR to get actual values
		p->CPU.NoThreads	= bitfield((uint32_t)msr, 15,  0);	// Using undocumented MSR to get actual values
	}
	else if (p->CPU.Vendor == CPUID_VENDOR_AMD)
	{
		p->CPU.NoThreads	= bitfield(p->CPU.CPUID[CPUID_1][1], 23, 16);
		p->CPU.NoCores		= bitfield(p->CPU.CPUID[CPUID_88][2], 7, 0) + 1;
	}
	else
	{
		// Use previous method for Cores and Threads
		p->CPU.NoThreads	= bitfield(p->CPU.CPUID[CPUID_1][1], 23, 16);
		p->CPU.NoCores		= bitfield(p->CPU.CPUID[CPUID_4][0], 31, 26) + 1;
	}
	
	/* get brand string (if supported) */
	/* Copyright: from Apple's XNU cpuid.c */
	if (p->CPU.CPUID[CPUID_80][0] > 0x80000004) {
		uint32_t	reg[4];
		char		str[128], *s;
		/*
		 * The brand string 48 bytes (max), guaranteed to
		 * be NULL terminated.
		 */
		do_cpuid(0x80000002, reg);
		bcopy((char *)reg, &str[0], 16);
		do_cpuid(0x80000003, reg);
		bcopy((char *)reg, &str[16], 16);
		do_cpuid(0x80000004, reg);
		bcopy((char *)reg, &str[32], 16);
		for (s = str; *s != '\0'; s++) {
			if (*s != ' ') break;
		}
		
		strlcpy(p->CPU.BrandString, s, sizeof(p->CPU.BrandString));
		
		if (!strncmp(p->CPU.BrandString, CPU_STRING_UNKNOWN, MIN(sizeof(p->CPU.BrandString), strlen(CPU_STRING_UNKNOWN) + 1))) {
			/*
			 * This string means we have a firmware-programmable brand string,
			 * and the firmware couldn't figure out what sort of CPU we have.
			 */
			p->CPU.BrandString[0] = '\0';
		}
	}
	
	/* setup features */
	if ((bit(23) & p->CPU.CPUID[CPUID_1][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_MMX;
	}
	if ((bit(25) & p->CPU.CPUID[CPUID_1][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE;
	}
	if ((bit(26) & p->CPU.CPUID[CPUID_1][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE2;
	}
	if ((bit(0) & p->CPU.CPUID[CPUID_1][2]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE3;
	}
	if ((bit(19) & p->CPU.CPUID[CPUID_1][2]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE41;
	}
	if ((bit(20) & p->CPU.CPUID[CPUID_1][2]) != 0) {
		p->CPU.Features |= CPU_FEATURE_SSE42;
	}
	if ((bit(29) & p->CPU.CPUID[CPUID_81][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_EM64T;
	}
	if ((bit(5) & p->CPU.CPUID[CPUID_1][3]) != 0) {
		p->CPU.Features |= CPU_FEATURE_MSR;
	}
	//if ((bit(28) & p->CPU.CPUID[CPUID_1][3]) != 0) {
	if (p->CPU.NoThreads > p->CPU.NoCores) {
		p->CPU.Features |= CPU_FEATURE_HTT;
	}
	
	tscFrequency = measure_tsc_frequency();
	/* if usual method failed */
	if ( tscFrequency < 1000 )
	{
	tscFrequency = timeRDTSC() * 20;
	}
	fsbFrequency = 0;
	cpuFrequency = 0;
	
	if ((p->CPU.Vendor == CPUID_VENDOR_INTEL) && ((p->CPU.Family == 0x06) || (p->CPU.Family == 0x0f))) {
		int intelCPU = p->CPU.Model;
		if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0c) || (p->CPU.Family == 0x0f && p->CPU.Model >= 0x03)) {
			/* Nehalem CPU model */
			if (p->CPU.Family == 0x06 && (p->CPU.Model == CPU_MODEL_NEHALEM ||
										  p->CPU.Model == CPU_MODEL_FIELDS ||
										  p->CPU.Model == CPU_MODEL_DALES ||
										  p->CPU.Model == CPU_MODEL_DALES_32NM ||
										  p->CPU.Model == CPU_MODEL_WESTMERE ||
										  p->CPU.Model == CPU_MODEL_NEHALEM_EX ||
										  p->CPU.Model == CPU_MODEL_WESTMERE_EX ||
										  p->CPU.Model == CPU_MODEL_SANDYBRIDGE ||
										  p->CPU.Model == CPU_MODEL_JAKETOWN ||
										  p->CPU.Model == CPU_MODEL_IVYBRIDGE)) {
				msr = rdmsr64(MSR_PLATFORM_INFO);
				DBG("msr(%d): platform_info %08x\n", __LINE__, bitfield(msr, 31, 0));
				bus_ratio_max = bitfield(msr, 14, 8);
				bus_ratio_min = bitfield(msr, 46, 40); //valv: not sure about this one (Remarq.1)
				msr = rdmsr64(MSR_FLEX_RATIO);
				DBG("msr(%d): flex_ratio %08x\n", __LINE__, bitfield(msr, 31, 0));
				if (bitfield(msr, 16, 16)) {
					flex_ratio = bitfield(msr, 14, 8);
					/* bcc9: at least on the gigabyte h67ma-ud2h,
					 where the cpu multipler can't be changed to
					 allow overclocking, the flex_ratio msr has unexpected (to OSX)
					 contents.	These contents cause mach_kernel to
					 fail to compute the bus ratio correctly, instead
					 causing the system to crash since tscGranularity
					 is inadvertently set to 0.
					 */
					if (flex_ratio == 0) {
						/* Clear bit 16 (evidently the presence bit) */
						wrmsr64(MSR_FLEX_RATIO, (msr & 0xFFFFFFFFFFFEFFFFULL));
						msr = rdmsr64(MSR_FLEX_RATIO);
						verbose("Unusable flex ratio detected. Patched MSR now %08x\n", bitfield(msr, 31, 0));
					} else {
						if (bus_ratio_max > flex_ratio) {
							bus_ratio_max = flex_ratio;
						}
					}
				}
				
				if (bus_ratio_max) {
					fsbFrequency = (tscFrequency / bus_ratio_max);
				}
				//valv: Turbo Ratio Limit
				if ((intelCPU != 0x2e) && (intelCPU != 0x2f)) {
					msr = rdmsr64(MSR_TURBO_RATIO_LIMIT);
					cpuFrequency = bus_ratio_max * fsbFrequency;
					max_ratio = bus_ratio_max * 10;
				} else {
					cpuFrequency = tscFrequency;
				}
				if ((getValueForKey(kbusratio, &newratio, &len, &bootInfo->chameleonConfig)) && (len <= 4)) {
					max_ratio = atoi(newratio);
					max_ratio = (max_ratio * 10);
					if (len >= 3) max_ratio = (max_ratio + 5);
					
					verbose("Bus-Ratio: min=%d, max=%s\n", bus_ratio_min, newratio);
					
					// extreme overclockers may love 320 ;)
					if ((max_ratio >= min_ratio) && (max_ratio <= 320)) {
						cpuFrequency = (fsbFrequency * max_ratio) / 10;
						if (len >= 3) maxdiv = 1;
						else maxdiv = 0;
					} else {
						max_ratio = (bus_ratio_max * 10);
					}
				}
				//valv: to be uncommented if Remarq.1 didn't stick
				/*if (bus_ratio_max > 0) bus_ratio = flex_ratio;*/
				p->CPU.MaxRatio = max_ratio;
				p->CPU.MinRatio = min_ratio;
				
				myfsb = fsbFrequency / 1000000;
				verbose("Sticking with [BCLK: %dMhz, Bus-Ratio: %d]\n", myfsb, max_ratio);
				currcoef = bus_ratio_max;
			} else {
				msr = rdmsr64(MSR_IA32_PERF_STATUS);
				DBG("msr(%d): ia32_perf_stat 0x%08x\n", __LINE__, bitfield(msr, 31, 0));
				currcoef = bitfield(msr, 12, 8);
				/* Non-integer bus ratio for the max-multi*/
				maxdiv = bitfield(msr, 46, 46);
				/* Non-integer bus ratio for the current-multi (undocumented)*/
				currdiv = bitfield(msr, 14, 14);
				
				// This will always be model >= 3
				if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0e) || (p->CPU.Family == 0x0f))
				{
					/* On these models, maxcoef defines TSC freq */
					maxcoef = bitfield(msr, 44, 40);
				} else {
					/* On lower models, currcoef defines TSC freq */
					/* XXX */
					maxcoef = currcoef;
				}
				
				if (maxcoef) {
					if (maxdiv) {
						fsbFrequency = ((tscFrequency * 2) / ((maxcoef * 2) + 1));
					} else {
						fsbFrequency = (tscFrequency / maxcoef);
					}
					if (currdiv) {
						cpuFrequency = (fsbFrequency * ((currcoef * 2) + 1) / 2);
					} else {
						cpuFrequency = (fsbFrequency * currcoef);
					}
					DBG("max: %d%s current: %d%s\n", maxcoef, maxdiv ? ".5" : "",currcoef, currdiv ? ".5" : "");
				}
			}
		}
		/* Mobile CPU */
		if (rdmsr64(MSR_IA32_PLATFORM_ID) & (1<<28)) {
			p->CPU.Features |= CPU_FEATURE_MOBILE;
		}
	}
	else if ((p->CPU.Vendor == CPUID_VENDOR_AMD) && (p->CPU.Family == 0x0f))
	{
		switch(p->CPU.ExtFamily)
		{
			case 0x00: /* K8 */
				msr = rdmsr64(K8_FIDVID_STATUS);
				maxcoef = bitfield(msr, 21, 16) / 2 + 4;
				currcoef = bitfield(msr, 5, 0) / 2 + 4;
				break;
				
			case 0x01: /* K10 */
				msr = rdmsr64(K10_COFVID_STATUS);
				do_cpuid2(0x00000006, 0, p->CPU.CPUID[CPUID_6]);
				// EffFreq: effective frequency interface
				if (bitfield(p->CPU.CPUID[CPUID_6][2], 0, 0) == 1)
				{
					//uint64_t mperf = measure_mperf_frequency();
					uint64_t aperf = measure_aperf_frequency();
					cpuFrequency = aperf;
				}
				// NOTE: tsc runs at the maccoeff (non turbo)
				//			*not* at the turbo frequency.
				maxcoef	 = bitfield(msr, 54, 49) / 2 + 4;
				currcoef = bitfield(msr, 5, 0) + 0x10;
				currdiv = 2 << bitfield(msr, 8, 6);
				
				break;
				
			case 0x05: /* K14 */
				msr = rdmsr64(K10_COFVID_STATUS);
				currcoef  = (bitfield(msr, 54, 49) + 0x10) << 2;
				currdiv = (bitfield(msr, 8, 4) + 1) << 2;
				currdiv += bitfield(msr, 3, 0);
				
				break;
				
			case 0x02: /* K11 */
				// not implimented
				break;
		}
		
		if (maxcoef)
		{
			if (currdiv)
			{
				if (!currcoef) currcoef = maxcoef;
				if (!cpuFrequency)
					fsbFrequency = ((tscFrequency * currdiv) / currcoef);
				else
					fsbFrequency = ((cpuFrequency * currdiv) / currcoef);
				
				DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv);
			} else {
				if (!cpuFrequency)
					fsbFrequency = (tscFrequency / maxcoef);
				else 
					fsbFrequency = (cpuFrequency / maxcoef);
				DBG("%d\n", currcoef);
			}
		}
		else if (currcoef)
		{
			if (currdiv)
			{
				fsbFrequency = ((tscFrequency * currdiv) / currcoef);
				DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv);
			} else {
				fsbFrequency = (tscFrequency / currcoef);
				DBG("%d\n", currcoef);
			}
		}
		if (!cpuFrequency) cpuFrequency = tscFrequency;
	}
	
#if 0
	if (!fsbFrequency) {
		fsbFrequency = (DEFAULT_FSB * 1000);
		cpuFrequency = tscFrequency;
		DBG("0 ! using the default value for FSB !\n");
	}
#endif
	
	p->CPU.MaxCoef = maxcoef;
	p->CPU.MaxDiv = maxdiv;
	p->CPU.CurrCoef = currcoef;
	p->CPU.CurrDiv = currdiv;
	p->CPU.TSCFrequency = tscFrequency;
	p->CPU.FSBFrequency = fsbFrequency;
	p->CPU.CPUFrequency = cpuFrequency;
	
	// keep formatted with spaces instead of tabs
	DBG("CPU: Brand String:             %s\n",              p->CPU.BrandString);
    DBG("CPU: Vendor/Family/ExtFamily:  0x%x/0x%x/0x%x\n",  p->CPU.Vendor, p->CPU.Family, p->CPU.ExtFamily);
    DBG("CPU: Model/ExtModel/Stepping:  0x%x/0x%x/0x%x\n",  p->CPU.Model, p->CPU.ExtModel, p->CPU.Stepping);
    DBG("CPU: MaxCoef/CurrCoef:         0x%x/0x%x\n",       p->CPU.MaxCoef, p->CPU.CurrCoef);
    DBG("CPU: MaxDiv/CurrDiv:           0x%x/0x%x\n",       p->CPU.MaxDiv, p->CPU.CurrDiv);
    DBG("CPU: TSCFreq:                  %dMHz\n",           p->CPU.TSCFrequency / 1000000);
    DBG("CPU: FSBFreq:                  %dMHz\n",           p->CPU.FSBFrequency / 1000000);
    DBG("CPU: CPUFreq:                  %dMHz\n",           p->CPU.CPUFrequency / 1000000);
    DBG("CPU: NoCores/NoThreads:        %d/%d\n",           p->CPU.NoCores, p->CPU.NoThreads);
    DBG("CPU: Features:                 0x%08x\n",          p->CPU.Features);
#if DEBUG_CPU
	pause();
#endif
}
예제 #12
0
kern_return_t
pal_efi_call_in_32bit_mode(uint32_t func,
                           struct pal_efi_registers *efi_reg,
                           void *stack_contents,
                           size_t stack_contents_size, /* 16-byte multiple */
                           uint32_t *efi_status)
{
    DBG("pal_efi_call_in_32bit_mode(0x%08x, %p, %p, %lu, %p)\n",
	func, efi_reg, stack_contents, stack_contents_size, efi_status);

    if (func == 0) {
        return KERN_INVALID_ADDRESS;
    }

    if ((efi_reg == NULL)
        || (stack_contents == NULL)
        || (stack_contents_size % 16 != 0)) {
        return KERN_INVALID_ARGUMENT;
    }

    if (!gPEEFISystemTable || !gPEEFIRuntimeServices) {
        return KERN_NOT_SUPPORTED;
    }

    DBG("pal_efi_call_in_32bit_mode() efi_reg:\n");
    DBG("  rcx: 0x%016llx\n", efi_reg->rcx);
    DBG("  rdx: 0x%016llx\n", efi_reg->rdx);
    DBG("   r8: 0x%016llx\n", efi_reg->r8);
    DBG("   r9: 0x%016llx\n", efi_reg->r9);
    DBG("  rax: 0x%016llx\n", efi_reg->rax);

    DBG("pal_efi_call_in_32bit_mode() stack:\n");
#if PAL_DEBUG
    size_t i;
    for (i = 0; i < stack_contents_size; i += sizeof(uint32_t)) {
	uint32_t *p = (uint32_t *) ((uintptr_t)stack_contents + i);
	DBG("  %p: 0x%08x\n", p, *p);
    } 
#endif

#ifdef __x86_64__
    /*
     * Ensure no interruptions.
     * Taking a spinlock for serialization is technically unnecessary
     * because the EFIRuntime kext should serialize.
     */
    boolean_t istate = ml_set_interrupts_enabled(FALSE);
    simple_lock(&pal_efi_lock);

    /*
     * Switch to special page tables with the entire high kernel space
     * double-mapped into the bottom 4GB.
     *
     * NB: We assume that all data passed exchanged with RuntimeServices is
     * located in the 4GB of KVA based at VM_MIN_ADDRESS. In particular, kexts
     * loaded the basement (below VM_MIN_ADDRESS) cannot pass static data.
     * Kernel stack and heap space is OK.
     */
    MARK_CPU_IDLE(cpu_number());
    pal_efi_saved_cr3 = get_cr3_raw();
    pal_efi_saved_cr0 = get_cr0();
    IDPML4[KERNEL_PML4_INDEX] = IdlePML4[KERNEL_PML4_INDEX];
    IDPML4[0]		      = IdlePML4[KERNEL_PML4_INDEX];
    clear_ts();
    set_cr3_raw((uint64_t) ID_MAP_VTOP(IDPML4));
    
    swapgs();			/* Save kernel's GS base */

    /* Set segment state ready for compatibility mode */
    set_gs(NULL_SEG);
    set_fs(NULL_SEG);
    set_es(KERNEL_DS);
    set_ds(KERNEL_DS);
    set_ss(KERNEL_DS);

    _pal_efi_call_in_32bit_mode_asm(func,
                                    efi_reg,
                                    stack_contents,
                                    stack_contents_size);
    
    /* Restore NULL segment state */
    set_ss(NULL_SEG);
    set_es(NULL_SEG);
    set_ds(NULL_SEG);

    swapgs();			/* Restore kernel's GS base */

    /* Restore the 64-bit user GS base we just destroyed */
    wrmsr64(MSR_IA32_KERNEL_GS_BASE,
	    current_cpu_datap()->cpu_uber.cu_user_gs_base);

    /* End of mapping games */
    set_cr3_raw(pal_efi_saved_cr3);
    set_cr0(pal_efi_saved_cr0);
    MARK_CPU_ACTIVE(cpu_number());
    
    simple_unlock(&pal_efi_lock);
    ml_set_interrupts_enabled(istate);
#else
    _pal_efi_call_in_32bit_mode_asm(func,
                                    efi_reg,
                                    stack_contents,
                                    stack_contents_size);
#endif

    *efi_status = (uint32_t)efi_reg->rax;
    DBG("pal_efi_call_in_32bit_mode() efi_status: 0x%x\n", *efi_status);

    return KERN_SUCCESS;
}