Esempio n. 1
0
/*
 * Original comment/code:
 *  "DFE: Measures the Max Performance Frequency in Hz (64-bit)"
 *
 * Measures the Actual Performance Frequency in Hz (64-bit)
 *  (just a naming change, mperf --> aperf )
 */
static uint64_t measure_aperf_frequency(void)
{
    uint64_t aperfStart;
    uint64_t aperfEnd;
    uint64_t aperfDelta = 0xffffffffffffffffULL;
    unsigned long pollCount;
    uint64_t retval = 0;
    int i;

    /* Time how many APERF ticks elapse in 30 msec using the 8254 PIT
     * counter 2. We run this loop 3 times to make sure the cache
     * is hot and we take the minimum delta from all of the runs.
     * That is to say that we're biased towards measuring the minimum
     * number of APERF ticks that occur while waiting for the timer to
     * expire.
     */
    for(i = 0; i < 10; ++i)
    {
        enable_PIT2();
        set_PIT2_mode0(CALIBRATE_LATCH);
        aperfStart = rdmsr64(MSR_AMD_APERF);
        pollCount = poll_PIT2_gate();
        aperfEnd = rdmsr64(MSR_AMD_APERF);
        /* The poll loop must have run at least a few times for accuracy */
        if (pollCount <= 1)
        {
            continue;
        }
        /* The TSC must increment at LEAST once every millisecond.
         * We should have waited exactly 30 msec so the APERF delta should
         * be >= 30. Anything less and the processor is way too slow.
         */
        if ((aperfEnd - aperfStart) <= CALIBRATE_TIME_MSEC)
        {
            continue;
        }
        // tscDelta = MIN(tscDelta, (tscEnd - tscStart))
        if ( (aperfEnd - aperfStart) < aperfDelta )
        {
            aperfDelta = aperfEnd - aperfStart;
        }
    }
    /* mperfDelta is now the least number of MPERF ticks the processor made in
     * a timespan of 0.03 s (e.g. 30 milliseconds)
     */

    if (aperfDelta > (1ULL<<32))
    {
        retval = 0;
    }
    else
    {
        retval = aperfDelta * 1000 / 30;
    }
    disable_PIT2();
    return retval;
}
Esempio n. 2
0
static void
mca_get_availability(void)
{
	uint64_t	features = cpuid_info()->cpuid_features;
	uint32_t	family =  cpuid_info()->cpuid_family;

	mca_MCE_present = (features & CPUID_FEATURE_MCE) != 0;
	mca_MCA_present = (features & CPUID_FEATURE_MCA) != 0;
	mca_family = family;
	
	/*
	 * If MCA, the number of banks etc is reported by the IA32_MCG_CAP MSR.
	 */
	if (mca_MCA_present) {
		ia32_mcg_cap.u64 = rdmsr64(IA32_MCG_CAP);
		mca_error_bank_count = ia32_mcg_cap.bits.count;
		mca_control_MSR_present = ia32_mcg_cap.bits.mcg_ctl_p;
		mca_threshold_status_present = ia32_mcg_cap.bits.mcg_tes_p;
		mca_sw_error_recovery_present = ia32_mcg_cap.bits.mcg_ser_p;
		mca_cmci_present = ia32_mcg_cap.bits.mcg_ext_corr_err_p;
		if (family == 0x0F) {
			mca_extended_MSRs_present = ia32_mcg_cap.bits.mcg_ext_p;
			mca_extended_MSRs_count = ia32_mcg_cap.bits.mcg_ext_cnt;
		}
	}
}
Esempio n. 3
0
void
panic(const char *errormsg, ...) {
    va_list list;
    kprintf("\nKERNEL PANIC: ");
    if (can_use_serial) {
        bool early = false;
        if (rdmsr64(MSR_IA32_GS_BASE) == 0 && enable == false) {
            early = true;
        }
        if (early) {
            va_start(list, errormsg);
            _doprnt_log(errormsg, &list, serial_putc, 16);
            va_end(list);
            goto panicing;
        } else {
        normal_print:
            va_start(list, errormsg);
            _doprnt(errormsg, &list, putc, 16);
            va_end(list);
            goto panicing;
        }
    } else {
        goto normal_print;
    }
panicing:
    kprintf("\nCPU Halted");
    pal_stop_cpu(true);
}
Esempio n. 4
0
void scan_cpu_intel()
{
	uint32_t	cpuid_reg[4];

	// Get Number of cores per package
	/*
	 Initially set the EAX register to 4 and the ECX register to 0 prior to executing the CPUID instruction.
	 After executing the CPUID instruction, (EAX[31:26] + 1) contains the number of cores.
	 */
	cpuid_reg[2]=1;
	do_cpuid(4, cpuid_reg);
	do_cpuid(4, cpuid_reg); // FIXME: why does this only work the 2nd time ?
	Platform.CPU.NoCores = bitfield(cpuid_reg[0], 31, 26) + 1;
	
	// Find Number of Concurrent Threads Processed (HyperThreading) 
	do_cpuid(1,cpuid_reg);
	if(bitfield(cpuid_reg[1], 23, 16) > 1)
		Platform.CPU.NoThreads=Platform.CPU.NoCores;
	else
		Platform.CPU.NoThreads=Platform.CPU.NoCores * 2;
	
	// Mobile CPU ?
	if (rdmsr64(0x17) & (1<<28))
		Platform.CPU.Mobile = 1;
	else
		Platform.CPU.Mobile = 0;
}
Esempio n. 5
0
static void
mca_get_availability(void)
{
	uint64_t	features = cpuid_info()->cpuid_features;
	uint32_t	family =   cpuid_info()->cpuid_family;
	uint32_t	model =    cpuid_info()->cpuid_model;
	uint32_t	stepping = cpuid_info()->cpuid_stepping;

	mca_MCE_present = (features & CPUID_FEATURE_MCE) != 0;
	mca_MCA_present = (features & CPUID_FEATURE_MCA) != 0;
	mca_family = family;

	if ((model == CPUID_MODEL_HASWELL     && stepping < 3) ||
	    (model == CPUID_MODEL_HASWELL_ULT && stepping < 1) ||
	    (model == CPUID_MODEL_CRYSTALWELL && stepping < 1))
		panic("Haswell pre-C0 steppings are not supported");

	/*
	 * If MCA, the number of banks etc is reported by the IA32_MCG_CAP MSR.
	 */
	if (mca_MCA_present) {
		ia32_mcg_cap.u64 = rdmsr64(IA32_MCG_CAP);
		mca_error_bank_count = ia32_mcg_cap.bits.count;
		mca_control_MSR_present = ia32_mcg_cap.bits.mcg_ctl_p;
		mca_threshold_status_present = ia32_mcg_cap.bits.mcg_tes_p;
		mca_sw_error_recovery_present = ia32_mcg_cap.bits.mcg_ser_p;
		mca_cmci_present = ia32_mcg_cap.bits.mcg_ext_corr_err_p;
		if (family == 0x0F) {
			mca_extended_MSRs_present = ia32_mcg_cap.bits.mcg_ext_p;
			mca_extended_MSRs_count = ia32_mcg_cap.bits.mcg_ext_cnt;
		}
	}
}
Esempio n. 6
0
/*
 * 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);
}
Esempio n. 7
0
inline void read_cpu_thermal(void* cpu_index)
{
    UInt8 * cpn = (UInt8 *)cpu_index;
    
	*cpn = get_cpu_number();
    
	if(*cpn < kCPUSensorsMaxCpus) {
		UInt64 msr = rdmsr64(MSR_IA32_THERM_STS);
		if (msr & 0x80000000) cpu_thermal[*cpn] = (msr >> 16) & 0x7F;
	}
Esempio n. 8
0
static inline void read_cpu_thermal(void *magic)
{
    UInt32 number = get_cpu_number();
    
    if (number < kCPUSensorsMaxCpus) {
        UInt64 msr = rdmsr64(MSR_IA32_THERM_STS);
        if (msr & 0x80000000) {
            cpu_thermal[number] = (msr >> 16) & 0x7F;
            cpu_thermal_updated[number] = true;
        }
Esempio n. 9
0
// Real timer filter
bool driver::perfTimerEvent(IOTimerEventSource *src, int count) {
 uint64_t msr;
 uint32_t vid;
 
 uint32_t next_check_delay;
 uint32_t wantspeed,wantstep;
 long i,idle,used,total;

 if (driverStatus != driverDrive) return(false);

 //ok, so we're using adaptive mode..
 if (get_cpu_ticks(&idle, &total)) fail("get_cpu_load");

 // Used = % used x 10
 used = ((total-idle)*1000)/total;

 // If used > 95% we can't really guess how much is needed, so step to highest speed
 if (used>=950) wantspeed=speedstep_cpu_setting[num_speeds-1].cpuMhz;
		
 // Otherwise wantspeed is the ideal frequency to maintain idle % target
 else wantspeed = (speedstep_cpu_setting[stepCurrent].cpuMhz * (used+1)) / TARGET_CPULOAD;

 if (wantspeed>=speedstep_cpu_setting[num_speeds-1].cpuMhz)	wantstep = num_speeds-1;	// We want something higher than our highest
 else if (wantspeed<=speedstep_cpu_setting[0].cpuMhz)			wantstep = 0;				// We want something lower than our lowest
 
 // Otherwise, find the best step
 else for (i = 0; i < (num_speeds-1); i++) if ((wantspeed >= speedstep_cpu_setting[i].cpuMhz) && (wantspeed < speedstep_cpu_setting[i+1].cpuMhz)) wantstep=i;
 //dbg("pctused=%u idle=%u total=%u wantspeed=%u wantstep=%u\n",used,idle,total,wantspeed,wantstep);

 if (wantstep == stepCurrent) goto check_soon;

 stepCurrent = wantstep; // Assume we got the one we wanted

 eist_update_all_cpus(speedstep_cpu_setting[wantstep].VID);
// IOSleep(1);
 msr = rdmsr64(MSR_PERF_CTL);
 vid = msr & 0xFFFF;
 dbg("Stepping to %u pctused=%u VID=0x%04x\n",speedstep_cpu_setting[wantstep].cpuMhz,used,vid);
 
 perfTimer->setTimeoutMS(512 * (wantstep+1)); // Make the delay until the next check proportional to the speed we picked
 return(true);
 

 perfTimer->setTimeoutMS(1024);
 success:
 return(true);

 check_soon:
 perfTimer->setTimeoutMS(512);
 return(true);

 fail:
 return(false);
}
Esempio n. 10
0
static void
mca_save_state(mca_state_t *mca_state)
{
	mca_mci_bank_t  *bank;
	unsigned int	i;

	assert(!ml_get_interrupts_enabled() || get_preemption_level() > 0);

	if  (mca_state == NULL)
		return;

	mca_state->mca_mcg_ctl = mca_control_MSR_present ?
					rdmsr64(IA32_MCG_CTL) : 0ULL;	
	mca_state->mca_mcg_status.u64 = rdmsr64(IA32_MCG_STATUS);

 	bank = (mca_mci_bank_t *) &mca_state->mca_error_bank[0];
	for (i = 0; i < mca_error_bank_count; i++, bank++) {
		bank->mca_mci_ctl        = rdmsr64(IA32_MCi_CTL(i));	
		bank->mca_mci_status.u64 = rdmsr64(IA32_MCi_STATUS(i));	
		if (!bank->mca_mci_status.bits.val)
			continue;
		bank->mca_mci_misc = (bank->mca_mci_status.bits.miscv)?
					rdmsr64(IA32_MCi_MISC(i)) : 0ULL;	
		bank->mca_mci_addr = (bank->mca_mci_status.bits.addrv)?
					rdmsr64(IA32_MCi_ADDR(i)) : 0ULL;	
	} 

	/*
	 * If we're the first thread with MCA state, point our package to it
	 * and don't care about races
	 */
	if (x86_package()->mca_state == NULL)
		x86_package()->mca_state = mca_state;
}
Esempio n. 11
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
}
Esempio n. 12
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);
}
Esempio n. 13
0
void kprintf(const char *fmt, ...)
{
	va_list   listp;
	boolean_t state;

	if (!disable_serial_output) {
		boolean_t early = FALSE;
		if (rdmsr64(MSR_IA32_GS_BASE) == 0) {
			early = TRUE;
		}
		/* If PE_kputc has not yet been initialized, don't
		 * take any locks, just dump to serial */
		if (!PE_kputc || early) {
			va_start(listp, fmt);
			_doprnt(fmt, &listp, pal_serial_putc, 16);
			va_end(listp);
			return;
		}

		/*
		 * Spin to get kprintf lock but re-enable interrupts while
		 * failing.
		 * This allows interrupts to be handled while waiting but
		 * interrupts are disabled once we have the lock.
		 */
		state = ml_set_interrupts_enabled(FALSE);

		pal_preemption_assert();

		while (!simple_lock_try(&kprintf_lock)) {
			ml_set_interrupts_enabled(state);
			ml_set_interrupts_enabled(FALSE);
		}

		if (cpu_number() != cpu_last_locked) {
			MP_DEBUG_KPRINTF("[cpu%d...]\n", cpu_number());
			cpu_last_locked = cpu_number();
		}

		va_start(listp, fmt);
		_doprnt(fmt, &listp, PE_kputc, 16);
		va_end(listp);

		simple_unlock(&kprintf_lock);
		ml_set_interrupts_enabled(state);
	}
}
Esempio n. 14
0
static inline void cpu_check(void *magic)
{
    int number = cpu_number();
    
    if (number < kCPUSensorsMaxCpus) {
        
        
        cpu_enabled[number] = true;
        
        uint32_t cpuid_reg[4];
        
        do_cpuid(0x0b, cpuid_reg);
        
        cpu_lapic[number] = cpuid_reg[edx];
        cpu_check_value[number] = rdmsr64(MSR_IA32_PACKAGE_THERM_STATUS);
    }
}
Esempio n. 15
0
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));
}
bool AutoThrottler::perfTimerEvent(IOTimerEventSource* src, int count) {
	uint32_t wantspeed,wantstep;
	long idle, used, total;
	uint64_t msr;
	
	msr = rdmsr64(INTEL_MSR_PERF_STS); // read current MSR
	// For clock recalibration
	
	if (!enabled || !setupDone) return false;
	
	// gather stats
	PStates[currentPState].TimesChosen++;
	totalTimerEvents++;
	
	GetCPUTicks(&idle, &total);
	
	// Used = % used x 10
	used = ((total - idle) * 1000) / total;
	dbg( "used %ld ", used );
  
	// If used > 95% we can't really guess how much is needed, so step to highest speed
//	if (used >= 950)
//        wantspeed = PStates[0].AcpiFreq;
//	else // Otherwise wantspeed is the ideal frequency to maintain idle % target
		wantspeed = (PStates[currentPState].AcpiFreq * (used + 1)) / targetCPULoad;

	wantstep = FindClosestPState(wantspeed);

// 20110802 WTF?
//	if (VID(msr) == 975) goto check_soon;	
	currentPState = wantstep; // Assume we got the one we wanted

	
	throttleAllCPUs(&PStates[currentPState]);
	
	perfTimer->setTimeoutMS(throttleQuantum * (NumberOfPStates - wantstep)); // Make the delay until the next check proportional to the speed we picked
	return true;
	
check_soon:
	perfTimer->setTimeoutMS(throttleQuantum);
	return true;
}
Esempio n. 17
0
void
kprintf(const char *fmt, ...) {
    va_list     listp;
    //bool      state;
    if (can_use_serial) {
        bool early = false;
        if (rdmsr64(MSR_IA32_GS_BASE) == 0&&enable==false) {
            early = true;
        }
        if (early) {
            va_start(listp, fmt);
            _doprnt_log(fmt, &listp, serial_putc, 16);
            va_end(listp);
            return;
        }
        
        /*
         * Spin to get kprintf lock but poll for incoming signals
         * while interrupts are masked.
         */
        /*state = ml_set_interrupts_enabled(FALSE);
        
        pal_preemption_assert();
        
        while (!simple_lock_try(&kprintf_lock)) {
            (void) cpu_signal_handler(NULL);
        }
        
        if (cpu_number() != cpu_last_locked) {
            MP_DEBUG_KPRINTF("[cpu%d...]\n", cpu_number());
            cpu_last_locked = cpu_number();
        }*/
        
        va_start(listp, fmt);
        _doprnt(fmt, &listp, putc, 16);
        va_end(listp);
        
        /*simple_unlock(&kprintf_lock);
        ml_set_interrupts_enabled(state);*/
    }
}
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);
}
Esempio n. 19
0
static uint32_t rdmsr32(uint32_t msr)
{
	return (uint32_t) rdmsr64(msr);
}
Esempio n. 20
0
static void mca_dump_64bit_state(void)
{
	kdb_printf("Extended Machine Check State:\n");
	kdb_printf("  IA32_MCG_RAX:    0x%016qx\n", rdmsr64(IA32_MCG_RAX));
	kdb_printf("  IA32_MCG_RBX:    0x%016qx\n", rdmsr64(IA32_MCG_RBX));
	kdb_printf("  IA32_MCG_RCX:    0x%016qx\n", rdmsr64(IA32_MCG_RCX));
	kdb_printf("  IA32_MCG_RDX:    0x%016qx\n", rdmsr64(IA32_MCG_RDX));
	kdb_printf("  IA32_MCG_RSI:    0x%016qx\n", rdmsr64(IA32_MCG_RSI));
	kdb_printf("  IA32_MCG_RDI:    0x%016qx\n", rdmsr64(IA32_MCG_RDI));
	kdb_printf("  IA32_MCG_RBP:    0x%016qx\n", rdmsr64(IA32_MCG_RBP));
	kdb_printf("  IA32_MCG_RSP:    0x%016qx\n", rdmsr64(IA32_MCG_RSP));
	kdb_printf("  IA32_MCG_RFLAGS: 0x%016qx\n", rdmsr64(IA32_MCG_RFLAGS));
	kdb_printf("  IA32_MCG_RIP:    0x%016qx\n", rdmsr64(IA32_MCG_RIP));
	kdb_printf("  IA32_MCG_MISC:   0x%016qx\n", rdmsr64(IA32_MCG_MISC));
	kdb_printf("  IA32_MCG_R8:     0x%016qx\n", rdmsr64(IA32_MCG_R8));
	kdb_printf("  IA32_MCG_R9:     0x%016qx\n", rdmsr64(IA32_MCG_R9));
	kdb_printf("  IA32_MCG_R10:    0x%016qx\n", rdmsr64(IA32_MCG_R10));
	kdb_printf("  IA32_MCG_R11:    0x%016qx\n", rdmsr64(IA32_MCG_R11));
	kdb_printf("  IA32_MCG_R12:    0x%016qx\n", rdmsr64(IA32_MCG_R12));
	kdb_printf("  IA32_MCG_R13:    0x%016qx\n", rdmsr64(IA32_MCG_R13));
	kdb_printf("  IA32_MCG_R14:    0x%016qx\n", rdmsr64(IA32_MCG_R14));
	kdb_printf("  IA32_MCG_R15:    0x%016qx\n", rdmsr64(IA32_MCG_R15));
}
Esempio n. 21
0
File: cpu.c Progetto: 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
}
Esempio n. 22
0
/*
 * 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
}
Esempio n. 23
0
static void
commpage_init_cpu_capabilities( void )
{
	uint64_t bits;
	int cpus;
	ml_cpu_info_t cpu_info;

	bits = 0;
	ml_cpu_get_info(&cpu_info);
	
	switch (cpu_info.vector_unit) {
		case 9:
			bits |= kHasAVX1_0;
			/* fall thru */
		case 8:
			bits |= kHasSSE4_2;
			/* fall thru */
		case 7:
			bits |= kHasSSE4_1;
			/* fall thru */
		case 6:
			bits |= kHasSupplementalSSE3;
			/* fall thru */
		case 5:
			bits |= kHasSSE3;
			/* fall thru */
		case 4:
			bits |= kHasSSE2;
			/* fall thru */
		case 3:
			bits |= kHasSSE;
			/* fall thru */
		case 2:
			bits |= kHasMMX;
		default:
			break;
	}
	switch (cpu_info.cache_line_size) {
		case 128:
			bits |= kCache128;
			break;
		case 64:
			bits |= kCache64;
			break;
		case 32:
			bits |= kCache32;
			break;
		default:
			break;
	}
	cpus = commpage_cpus();			// how many CPUs do we have

	bits |= (cpus << kNumCPUsShift);

	bits |= kFastThreadLocalStorage;	// we use %gs for TLS

#define setif(_bits, _bit, _condition) \
	if (_condition) _bits |= _bit

	setif(bits, kUP,         cpus == 1);
	setif(bits, k64Bit,      cpu_mode_is64bit());
	setif(bits, kSlow,       tscFreq <= SLOW_TSC_THRESHOLD);

	setif(bits, kHasAES,     cpuid_features() &
					CPUID_FEATURE_AES);
	setif(bits, kHasF16C,    cpuid_features() &
					CPUID_FEATURE_F16C);
	setif(bits, kHasRDRAND,  cpuid_features() &
					CPUID_FEATURE_RDRAND);
	setif(bits, kHasFMA,     cpuid_features() &
					CPUID_FEATURE_FMA);

	setif(bits, kHasBMI1,    cpuid_leaf7_features() &
					CPUID_LEAF7_FEATURE_BMI1);
	setif(bits, kHasBMI2,    cpuid_leaf7_features() &
					CPUID_LEAF7_FEATURE_BMI2);
	setif(bits, kHasRTM,     cpuid_leaf7_features() &
					CPUID_LEAF7_FEATURE_RTM);
	setif(bits, kHasHLE,     cpuid_leaf7_features() &
					CPUID_LEAF7_FEATURE_HLE);
	setif(bits, kHasAVX2_0,  cpuid_leaf7_features() &
					CPUID_LEAF7_FEATURE_AVX2);
	setif(bits, kHasRDSEED,  cpuid_features() &
					CPUID_LEAF7_FEATURE_RDSEED);
	setif(bits, kHasADX,     cpuid_features() &
					CPUID_LEAF7_FEATURE_ADX);
	
	setif(bits, kHasMPX,     cpuid_leaf7_features() &
					CPUID_LEAF7_FEATURE_MPX);
	setif(bits, kHasSGX,     cpuid_leaf7_features() &
					CPUID_LEAF7_FEATURE_SGX);
	uint64_t misc_enable = rdmsr64(MSR_IA32_MISC_ENABLE);
	setif(bits, kHasENFSTRG, (misc_enable & 1ULL) &&
				 (cpuid_leaf7_features() &
					CPUID_LEAF7_FEATURE_ERMS));
	
	_cpu_capabilities = bits;		// set kernel version for use by drivers etc
}
bool SMBIOSResolver::start(IOService * provider)
{
	if( super::start(provider) != true ) return false;	// Oh no	
	if( IOService::getResourceService()->getProperty("SMBIOS-Resolver") ) return false;	// We should exist only once	
	if( !IOService::getResourceService()->getProperty("SMBIOS") ) return false;	// AppleSMBIOS.kext didn´t start we bail out
	
	IOService * iosRoot = getServiceRoot();
	if( !iosRoot ) return false;	// Unable to get IOServiceRoot
	
	int doVerbose = 0;
	// PE_parse_boot_arg("smbios", &doVerbose);	// bootarg SMBIOS=1 will give a verbose output to log (when I find something verbose worth outputting)
	
	// Dictionary from plist
	OSDictionary * hwDict = OSDynamicCast( OSDictionary, getProperty("Override"));
	
	//	/rom/version
	IORegistryEntry * dtROMNode = fromPath("/rom", gIODTPlane);
	if( dtROMNode )
	{
		OSString * romVersion = OSDynamicCast( OSString, hwDict->getObject("rom-version"));
		if(romVersion->getLength() > 0) dtROMNode->setProperty("version", OSData::withBytes(romVersion->getCStringNoCopy(), romVersion->getLength() + 1) );
		dtROMNode->release();
	}
	else
	{
		return false;	// No /rom node in IODeviceTree plane
	}
	
	// root entries
	OSObject * dictString = 0;
	
	dictString = hwDict->getObject("manufacturer");
	if(dictString)
	{
		OSString * rootManufacturer = OSDynamicCast( OSString, dictString);
		if(rootManufacturer->getLength() > 1) iosRoot->setProperty("manufacturer", OSData::withBytes(rootManufacturer->getCStringNoCopy(), rootManufacturer->getLength() + 1) );
	}
	
	dictString = hwDict->getObject("system-type");
	if(dictString)
	{
		OSData * systemType = OSDynamicCast( OSData, dictString);
		if(systemType) iosRoot->setProperty("system-type", systemType );
	}
	
	dictString = hwDict->getObject("compatible");
	if(dictString) 
	{
		OSString * rootCompatible = OSDynamicCast( OSString, dictString);
		if(rootCompatible->getLength() > 1) iosRoot->setProperty("compatible", OSData::withBytes(rootCompatible->getCStringNoCopy(), rootCompatible->getLength() + 1) );
	}
	
	dictString = hwDict->getObject("product-name");
	if(dictString) 
	{
		OSString * rootProductName = OSDynamicCast( OSString, dictString);
		if(rootProductName->getLength() > 1) iosRoot->setProperty("product-name", OSData::withBytes(rootProductName->getCStringNoCopy(), rootProductName->getLength() + 1) );
	}
	
	dictString = hwDict->getObject("model");
	if(dictString) 
	{
		OSString * rootModel = OSDynamicCast( OSString, dictString);
		if(rootModel->getLength() > 1)
		{
			iosRoot->setProperty("model", OSData::withBytes(rootModel->getCStringNoCopy(), rootModel->getLength() + 1) );
			iosRoot->setName(rootModel->getCStringNoCopy());
		}
	}
	
	dictString = hwDict->getObject("version");
	if(dictString) 
	{
		OSString * rootVersion = OSDynamicCast( OSString, dictString);
		if(rootVersion->getLength() > 1) iosRoot->setProperty("version", OSData::withBytes(rootVersion->getCStringNoCopy(), rootVersion->getLength() + 1) );
	}
	
	dictString = hwDict->getObject("board-id");
	if(dictString) 
	{
		OSString * rootBoardId = OSDynamicCast( OSString, dictString);
		if(rootBoardId->getLength() > 1) iosRoot->setProperty("board-id", OSData::withBytes(rootBoardId->getCStringNoCopy(), rootBoardId->getLength() + 1) );
	}
	
	dictString = hwDict->getObject("serial-number");
	if(dictString) 
	{
		OSString * rootSerial = OSDynamicCast( OSString, dictString);
		if(rootSerial->getLength() > 1)
		{
			UInt8 length = rootSerial->getLength();
			const char *serialNumberString = rootSerial->getCStringNoCopy();
			
			// The serial-number property in the IORegistry is a 43-byte data object.
			// Bytes 0 through 2 are the last three bytes of the serial number string.
			// Bytes 11 through 20, inclusive, are the serial number string itself.
			// All other bytes are '\0'.
			OSData * data = OSData::withCapacity(43);
			if (data)
			{
				data->appendBytes(serialNumberString + (length - 3), 3);
				data->appendBytes(NULL, 10);
				data->appendBytes(serialNumberString, length);
				data->appendBytes(NULL, 43 - length - 10 - 3);
				iosRoot->setProperty("serial-number", data);
				data->release();
			}
			
			iosRoot->setProperty(kIOPlatformSerialNumberKey, rootSerial);
		}
	}
	
	dictString = hwDict->getObject("UUID-key");
	if(dictString) 
	{
		OSString * rootUUIDKey = OSDynamicCast( OSString, hwDict->getObject("UUID-key"));
		iosRoot->setProperty(kIOPlatformUUIDKey, rootUUIDKey);
		publishResource(kIOPlatformUUIDKey, rootUUIDKey);
	}
	
	bool useEfiBus = false;
	UInt64 fsbFrequency = 0;
	UInt64 msr;
	dictString = hwDict->getObject("use-efi-bus");
	if (dictString) useEfiBus = (OSDynamicCast(OSBoolean, dictString))->getValue(); 
	IORegistryEntry * efiPlatform = fromPath("/efi/platform", gIODTPlane);
	if (efiPlatform && useEfiBus)
	{
		OSData * efiFSBFreq = OSDynamicCast(OSData, efiPlatform->getProperty("FSBFrequency"));
		bcopy(efiFSBFreq->getBytesNoCopy(), &fsbFrequency, efiFSBFreq->getLength());
		efiPlatform->release();
	}
	else
	{	// No /efi/platform found
		fsbFrequency = gPEClockFrequencyInfo.bus_frequency_hz;	// Value previously set by AppleSMBIOS 
		if (!strncmp(cpuid_info()->cpuid_vendor, CPUID_VID_INTEL, sizeof(CPUID_VID_INTEL)) && (cpuid_info()->cpuid_features & CPUID_FEATURE_SSE2)) fsbFrequency /= 4;
	}

	dictString = hwDict->getObject("hardcode-bus");
	if(dictString) 
	{
		fsbFrequency = (OSDynamicCast(OSNumber, dictString))->unsigned64BitValue();
		if (fsbFrequency)
		{
			if (fsbFrequency <= 10000) fsbFrequency *= 1000000;
		}
		else
		{
			if (!strncmp(cpuid_info()->cpuid_vendor, CPUID_VID_INTEL, sizeof(CPUID_VID_INTEL)))
			{
				if ((cpuid_info()->cpuid_family == 0x0f) && (cpuid_info()->cpuid_model >= 2))
				{
					msr = rdmsr64(0x0000002C);
					switch ((msr >> 16) & 0x7) {
						case 0:
							if (cpuid_info()->cpuid_model == 2) fsbFrequency = 100 * 1000000;
							else 
							{
								fsbFrequency = (800 * 1000000) / 3;	// 266
								fsbFrequency++;
							}
							break;
						case 1:
							fsbFrequency = (400 * 1000000) / 3;	//	133
							break;
						case 2:
							fsbFrequency = (600 * 1000000) / 3;	// 200
							break;
						case 3:
							fsbFrequency = (500 * 1000000) / 3;	//	166
							fsbFrequency++;
							break;
						case 4:
							fsbFrequency = (1000 * 1000000) / 3;	//	333
							break;
						default:
							break;
					}
				}
				else
				{
					fsbFrequency = 100 * 1000000;
				}
				
				if (cpuid_info()->cpuid_family == 0x06)
				{
					msr = rdmsr64(0x000000CD);
					switch (msr & 0x7) {
						case 0:
							fsbFrequency = (800 * 1000000) / 3;	//	266
							fsbFrequency++;
							break;
						case 1:
							fsbFrequency = (400 * 1000000) / 3;	//	133
							break;
						case 2:
							fsbFrequency = (600 * 1000000) / 3;	//	200
							break;
						case 3:
							fsbFrequency = (500 * 1000000) / 3;	//	166
							fsbFrequency++;
							break;
						case 4:
							fsbFrequency = (1000 * 1000000) / 3;//	333
							break;
						case 5:
							fsbFrequency = (300 * 1000000) / 3;	//	100
							break;
						case 6:
							fsbFrequency = (1200 * 1000000) / 3;//	400
							break;
						case 7:		// should check
							fsbFrequency = (1400 * 1000000) / 3;//	466
							fsbFrequency++;
							break;
						default:
							break;
					}
				}
				 
			}
		}
Esempio n. 25
0
static void
commpage_init_cpu_capabilities( void )
{
	uint64_t bits;
	int cpus;
	ml_cpu_info_t cpu_info;

	bits = 0;
	ml_cpu_get_info(&cpu_info);

	switch (cpu_info.vector_unit) {
		case 9:
			bits |= kHasAVX1_0;
			/* fall thru */
		case 8:
			bits |= kHasSSE4_2;
			/* fall thru */
		case 7:
			bits |= kHasSSE4_1;
			/* fall thru */
		case 6:
			bits |= kHasSupplementalSSE3;
			/* fall thru */
		case 5:
			bits |= kHasSSE3;
			/* fall thru */
		case 4:
			bits |= kHasSSE2;
			/* fall thru */
		case 3:
			bits |= kHasSSE;
			/* fall thru */
		case 2:
			bits |= kHasMMX;
		default:
			break;
	}
	switch (cpu_info.cache_line_size) {
		case 128:
			bits |= kCache128;
			break;
		case 64:
			bits |= kCache64;
			break;
		case 32:
			bits |= kCache32;
			break;
		default:
			break;
	}
	cpus = commpage_cpus();			// how many CPUs do we have

	/** Sinetek: by default we'd like some reasonable values,
	 **  so that the userspace runs correctly.
	 **
	 ** On Mountain Lion, kHasSSE4_2 provides vanilla SSE2 routines.
	 ** On Mavericks, we need a bit more support: SSE3, SSE3X.
	 **/
	if (IsAmdCPU()) {
		bits |= kHasSSE4_2;
		bits &= ~kHasSupplementalSSE3;
#define MAVERICKS_AMD
#ifdef MAVERICKS_AMD
		bits |= kHasSSE3;
	//	bits |= kHasSupplementalSSE3;
		bits &= ~kHasSSE4_2;
#endif
	}

	bits |= (cpus << kNumCPUsShift);

	bits |= kFastThreadLocalStorage;	// we use %gs for TLS

#define setif(_bits, _bit, _condition) \
	if (_condition) _bits |= _bit

	setif(bits, kUP,         cpus == 1);
	setif(bits, k64Bit,      cpu_mode_is64bit());
	setif(bits, kSlow,       tscFreq <= SLOW_TSC_THRESHOLD);

	setif(bits, kHasAES,     cpuid_features() &
					CPUID_FEATURE_AES);
	setif(bits, kHasF16C,    cpuid_features() &
					CPUID_FEATURE_F16C);
	setif(bits, kHasRDRAND,  cpuid_features() &
					CPUID_FEATURE_RDRAND);
	setif(bits, kHasFMA,     cpuid_features() &
					CPUID_FEATURE_FMA);

	setif(bits, kHasBMI1,    cpuid_leaf7_features() &
					CPUID_LEAF7_FEATURE_BMI1);
	setif(bits, kHasBMI2,    cpuid_leaf7_features() &
					CPUID_LEAF7_FEATURE_BMI2);
	setif(bits, kHasRTM,     cpuid_leaf7_features() &
					CPUID_LEAF7_FEATURE_RTM);
	setif(bits, kHasHLE,     cpuid_leaf7_features() &
					CPUID_LEAF7_FEATURE_HLE);
	setif(bits, kHasAVX2_0,  cpuid_leaf7_features() &
					CPUID_LEAF7_FEATURE_AVX2);
	
	uint64_t misc_enable = rdmsr64(MSR_IA32_MISC_ENABLE);
	setif(bits, kHasENFSTRG, (misc_enable & 1ULL) &&
				 (cpuid_leaf7_features() &
					CPUID_LEAF7_FEATURE_ENFSTRG));
	
	_cpu_capabilities = bits;		// set kernel version for use by drivers etc
}
void checkForNby2Ratio() {
	uint64_t sts;
	sts = rdmsr64(INTEL_MSR_PERF_STS);
	Nby2Ratio = (sts & (1ULL << 46)); // bit 46 is set
}
Esempio n. 27
0
void
mca_dump(void)
{
	ia32_mcg_status_t	status;
	mca_state_t		*mca_state = current_cpu_datap()->cpu_mca_state;

	/*
	 * Capture local MCA registers to per-cpu data.
	 */
	mca_save_state(mca_state);

	/*
	 * Serialize in case of multiple simultaneous machine-checks.
	 * Only the first caller is allowed to dump MCA registers,
	 * other threads spin meantime.
	 */
	simple_lock(&mca_lock);
	if (mca_dump_state > CLEAR) {
		simple_unlock(&mca_lock);
		while (mca_dump_state == DUMPING)
			cpu_pause();
		return;
	}
	mca_dump_state = DUMPING;
	simple_unlock(&mca_lock);

	/*
	 * Report machine-check capabilities:
	 */
	kdb_printf(
		"Machine-check capabilities (cpu %d) 0x%016qx:\n",
		cpu_number(), ia32_mcg_cap.u64);

	mca_report_cpu_info();

	kdb_printf(
		" %d error-reporting banks\n%s%s%s", mca_error_bank_count,
		IF(mca_control_MSR_present,
		   " control MSR present\n"),
		IF(mca_threshold_status_present,
		   " threshold-based error status present\n"),
		IF(mca_cmci_present,
		   " extended corrected memory error handling present\n"));
	if (mca_extended_MSRs_present)
		kdb_printf(
			" %d extended MSRs present\n", mca_extended_MSRs_count);
 
	/*
	 * Report machine-check status:
	 */
	status.u64 = rdmsr64(IA32_MCG_STATUS);
	kdb_printf(
		"Machine-check status 0x%016qx:\n%s%s%s", status.u64,
		IF(status.bits.ripv, " restart IP valid\n"),
		IF(status.bits.eipv, " error IP valid\n"),
		IF(status.bits.mcip, " machine-check in progress\n"));

	/*
	 * Dump error-reporting registers:
	 */
	mca_dump_error_banks(mca_state);

	/*
	 * Dump any extended machine state:
	 */
	if (mca_extended_MSRs_present) {
		if (cpu_mode_is64bit())
			mca_dump_64bit_state();
		else
			mca_dump_32bit_state();
	}

	/* Update state to release any other threads. */
	mca_dump_state = DUMPED;
}
uint16_t getCurrentVoltage() {
	// Apple recommends not to return cached value, but to read it from the processor
	uint64_t msr = rdmsr64(INTEL_MSR_PERF_STS);
	return VID_to_mV(VID(msr));
}
uint16_t getCurrentFrequency() {
	uint64_t msr = rdmsr64(INTEL_MSR_PERF_STS);
	return FID_to_MHz(FID(msr));
}
Esempio n. 30
0
/*
 * 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
}