Beispiel #1
0
void scan_platform()
{
	uint32_t	cpuid_reg[4];

	build_pci_dt();

	calculate_freq();
	
	// Copy the values from calculate_freq()
	Platform.CPU.TSCFrequency = tscFrequency;
	Platform.CPU.FSBFrequency = fsbFrequency;
	Platform.CPU.CPUFrequency = cpuFrequency;
	
	do_cpuid(0, cpuid_reg);
	Platform.CPU.Vendor = cpuid_reg[1];
	
	do_cpuid(1, cpuid_reg);
	Platform.CPU.Model = bitfield(cpuid_reg[0], 7, 4);
	Platform.CPU.Family = bitfield(cpuid_reg[0], 11, 8);
	Platform.CPU.ExtModel = bitfield(cpuid_reg[0], 19, 16);
	Platform.CPU.ExtFamily = bitfield(cpuid_reg[0], 27, 20);

	// Get vendor specific cpu data 
	if((Platform.CPU.Vendor == 0x756E6547 /* Intel */) && ((Platform.CPU.Family == 0x06) || (Platform.CPU.Family == 0x0f)))
		scan_cpu_intel();
	else if((Platform.CPU.Vendor == 0x68747541 /* AMD */) && (Platform.CPU.Family == 0x0f))
		scan_cpu_amd();
}
Beispiel #2
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;
}
Beispiel #3
0
static void fields(node_t * sym)
{
    int follow[] = {INT, CONST, '}', IF, 0};
    node_t *sty = SYM_TYPE(sym);

    if (!first_decl(token)) {
        error("expect type name or qualifiers");
        return;
    }

    struct vector *v = vec_new();
    do {
        node_t *basety = specifiers(NULL, NULL);

        for (;;) {
            node_t *field = new_field();
            if (token->id == ':') {
                bitfield(field);
                FIELD_TYPE(field) = basety;
            } else {
                node_t *ty = NULL;
                struct token *id = NULL;
                declarator(&ty, &id, NULL);
                attach_type(&ty, basety);
                if (token->id == ':')
                    bitfield(field);
                FIELD_TYPE(field) = ty;
                if (id) {
                    for (int i = 0; i < vec_len(v); i++) {
                        node_t *f = vec_at(v, i);
                        if (FIELD_NAME(f) &&
                                !strcmp(FIELD_NAME(f), id->name)) {
                            errorf(id->src,
                                   "redefinition of '%s'",
                                   id->name);
                            break;
                        }
                    }
                    FIELD_NAME(field) = id->name;
                    AST_SRC(field) = id->src;
                }
            }

            vec_push(v, field);
            if (token->id != ',')
                break;
            expect(',');
            ensure_field(field, vec_len(v), false);
        }

        match(';', follow);
        ensure_field(vec_tail(v), vec_len(v),
                     isstruct(sty) && !first_decl(token));
    } while (first_decl(token));

    TYPE_FIELDS(sty) = (node_t **) vtoa(v);
    set_typesize(sty);
}
Beispiel #4
0
void dvbcrsc::advance(vector<int>& input)
   {
   fsm::advance(input);
   // ref: ETSI EN 301 790 V1.4.1 (2005-04)
   // ip[0] = A, ip[1] = B
   assert(input(0) != fsm::tail && input(1) != fsm::tail);
   // process input
   bitfield ip = bitfield(vector<bool> (input));
   // compute the shift-register left input
   bitfield lsi = ((ip.extract(0) ^ ip.extract(1)) + reg) * bitfield("1101");
   // do the shift
   reg = lsi >> reg;
   // apply the second input
   reg ^= (bitfield("0") + ip.extract(1) + ip.extract(1));
   }
Beispiel #5
0
vector<int> dvbcrsc::output(const vector<int>& input) const
   {
   // ref: ETSI EN 301 790 V1.4.1 (2005-04)
   // ip[0] = A, ip[1] = B
   assert(input(0) != fsm::tail && input(1) != fsm::tail);
   // process input
   bitfield ip = bitfield(vector<bool> (input));
   // compute the shift-register left input
   bitfield lsi = ((ip.extract(0) ^ ip.extract(1)) + reg) * bitfield("1101");
   // determine output
   // since the code is systematic, the first (low-order) op is the input
   bitfield op = ip;
   // low-order parity is Y
   op = (lsi + reg) * bitfield("1011") + op;
   // next is W
   op = (lsi + reg) * bitfield("1001") + op;
   return vector<int> (op.asvector());
   }
/** \brief Build a random bitfield_t
 */
bitfield_t bitfield_testclass_t::build_random(size_t nb_bit)		const throw()
{
	bitfield_t	bitfield(nb_bit);
	// take nb_bit/2 random idx and set the bit at thos position
	for(size_t i = 0; i < bitfield.size()/2; i++)
		bitfield.set( rand() % bitfield.size(), true);
	// return the just built bitfield_t
	return bitfield;
}
Beispiel #7
0
void ccbfsm::reset(const libbase::vector<int>& state)
   {
   fsm::reset(state);
   assert(state.size() == nu);
   reg = 0;
   int j = 0;
   for (int t = 0; t < nu; t++)
      for (int i = 0; i < k; i++)
         if (reg(i).size() > t)
            reg(i) |= bitfield(state(j++) << t, reg(i).size());
   assert(j == nu);
   }
Beispiel #8
0
void print_bit_dump( unsigned char* one, unsigned char* two, long long size, long long offset, int max_diff){
	long long counter=0;
	char one_buff[9];
	char two_buff[9];
	char diff_buff[9];
	int diff_counter=0;
	printf("Offset (hex)\tWrite\t\t  Read\t\t     XOR\n");
	while(counter<size){
		if(one[counter]!=two[counter]){
			if(diff_counter>=max_diff)
				return;
			diff_counter++;
			bitfield(one_buff,one[counter]);
			bitfield(two_buff,two[counter]);
			bitfield(diff_buff,one[counter]^two[counter]);
			printf("0x%010I64x:\t%s (0x%02X) | %s (0x%02X) | %s\n", offset + counter, one_buff,one[counter],two_buff,two[counter],diff_buff);
		}
		counter++;

	}

}
static inline bool hpetIsInvalid()
{
    hpetInfo_t hpetInfo;
    hpet_get_info(&hpetInfo);
    // The AppleIntelCPUPowerManagement will crash if rcbaArea and/or HPET is NULL
    // Ordinarily this can never happen but modified xnu can allow for this.
    if(hpetInfo.rcbaArea == 0)
    {
        IOLog("Forcing takeover of AppleIntelCPUPowerManagement resource due to lack of RCBA (no LPC?)\n");
        return true;
    }
    // Another case is that the LPC exists but the HPET isn't really valid.
    // That is to say that virtual hardware provides enough to get past xnu startup
    // but not enough to really make the HPET work.

    uint32_t hptc = *(uint32_t*)(hpetInfo.rcbaArea + 0x3404);
    if(!(hptc & hptcAE))
    {
        IOLog("Forcing takeover of AppleIntelCPUPowerManagement resource because HPET is not enabled\n");
        return true;
    }
    // Use the RCBA's HPTC to determine which of the four possible HPET physical addresses is used
    uint32_t hpetAreap = hpetAddr | ((hptc & 3) << 12);
    IOMemoryDescriptor *hpetMemDesc = IOMemoryDescriptor::withPhysicalAddress(hpetAreap, sizeof(hpetReg_t), kIODirectionIn);

    // grab the GCAP_ID (note offset is actually 0)
    uint64_t GCAP_ID;
    hpetMemDesc->readBytes(offsetof(hpetReg_t, GCAP_ID), &GCAP_ID, sizeof(GCAP_ID));

    // We're done with the memory descriptor now, so release it
    hpetMemDesc->release();
    hpetMemDesc = NULL;

    // Extract the VENDOR_ID_CAP field from the GCAP_ID and test it
    uint16_t vendorId = bitfield(GCAP_ID, 31, 16);
    if( (vendorId == 0x0000) || (vendorId == 0xffff))
    {
        IOLog("Forcing takeover of AppleIntelCPUPowerManagement resource due to bad HPET VENDOR_ID_CAP\n");
        return true;
    }
    else if(vendorId != 0x8086)
    {
        IOLog("WARNING: HPET is not Intel.  Going ahead and allowing AppleIntelCPUPowerManagement to start but beware it may behave strangely\n");
    }
    return false;
}
Beispiel #10
0
 // Accessors for current relocation pair
 Kind kind() const {
   return (Kind) bitfield(current(), offset_width, type_width);
 }
Beispiel #11
0
 void update_current() {
   _current_code_offset += 
     sign_extend(bitfield(current(), 0, offset_width), offset_width);
 }
Beispiel #12
0
static int eim_init(void)
{
	int ret = 0;

	const int CSREC = 3;
	const int PSZ = 0;
	const int AUS = 1;
	const int BCS = 0;
	const int BCD = 0;
	const int BL = 3;
	const int WFL = 1;
	const int RFL = 1;
	const int WC = 0;
	const int ADH = 0;
	const int RWSC = 3;
	const int WWSC = 1;
	const int ADVA = 0; /* RADVA and WADVA */
	const int ADVN = 0; /* RADVN and WADVN */
	const int OEA = 0;
	const int CSA = 0; /* RCSA and WCSA */
	const int RL = 0;
	const int BEA = 0;
	const int BE = 1;
	const int WEA = 0;
	const int INTPOL = 1; /* Interrupt polarity */
	const int INTEN = 0; /* Interrupt enable */
	const int GBCD = 0; /* Burst clock divisor */
	const int BCM = 1; /* Burst clock mode (set c ontinuous here) */
  
	u32 GCR1, GCR2, RCR1, RCR2, WCR1, WEIMCR;
	u32 temp_clk;
	const int emi_slow_podf = 7;
  
	iomux_v3_cfg_t iomux_cs2 = MX51_PAD_EIM_CS2__EIM_CS2;
	iomux_v3_cfg_t iomux_dtack = MX51_PAD_EIM_DTACK__GPIO2_31;
	iomux_v3_cfg_t iomux_event = MX51_PAD_GPIO1_5__SDMA_EXT_EVENT;

	mxc_iomux_v3_setup_pad(iomux_cs2);
	mxc_iomux_v3_setup_pad(iomux_dtack);
	mxc_iomux_v3_setup_pad(iomux_event);

	/*
	 * Change the clock divider for EMI bus from divide-by-7 to divide-by-8, so
	 * that the bus frequency is below 90 MHz, in accordance with footnote 4 in
	 * section 4.6.7.3 in the datasheet. This is necessary to prevent bus errors
	 * as the device heats up.
	 */

	temp_clk = __raw_readl( MX51_IO_ADDRESS(MX51_CCM_BASE_ADDR)+ MXC_CCM_CBCDR );

	__raw_writel( (temp_clk & (~0x1c00000)) | bitfield(22, 3, emi_slow_podf),
		      MX51_IO_ADDRESS(MX51_CCM_BASE_ADDR)+ MXC_CCM_CBCDR );

	if (gpio_request(event_gpio_num, "xillybus")) {
		printk(KERN_ERR THIS "GPIO pin %i is already in use\n", event_gpio_num);
		return -ENODEV;
	}

	gpio_direction_input(event_gpio_num);
  
	GCR1 = 0x0111008f |
		bitfield(28, 4, PSZ) |
		bitfield(23, 1, AUS) |
		bitfield(20, 3, CSREC) |
		bitfield(14, 2, BCS) |
		bitfield(12, 2, BCD) |
		bitfield(11, 1, WC) |
		bitfield(8, 3, BL) |
		bitfield(5, 1, RFL) |
		bitfield(4, 1, WFL);
    
	GCR2 = bitfield(0, 2, ADH);

	RCR1 = 
		bitfield(24, 6, RWSC) |
		bitfield(20, 3, ADVA) |
		bitfield(16, 3, ADVN) |
		bitfield(12, 3, OEA) |
		bitfield(4, 3, CSA);

	RCR2 = 
		bitfield(8, 2, RL) |
		bitfield(4, 3, BEA) |
		bitfield(3, 1, BE);

	WCR1 =
		bitfield(30, 1, !BE) |
		bitfield(24, 6, WWSC) |
		bitfield(21, 3, ADVA) |
		bitfield(18, 3, ADVN) |
		bitfield(15, 3, BEA) |
		bitfield(9, 3, WEA) |
		bitfield(3, 3, CSA);

	WEIMCR =
		bitfield(5, 1, INTPOL) |
		bitfield(4, 1, INTEN) |
		bitfield(1, 2, GBCD) |
		bitfield(0, 1, BCM);

	writereg(0x30, GCR1);
	writereg(0x34, GCR2);
	writereg(0x38, RCR1);
	writereg(0x3c, RCR2);
	writereg(0x40, WCR1);
	writereg(0x90, WEIMCR);

	if  (!request_mem_region(MX51_CS2_BASE_ADDR, SZ_64K, "xillybus_sdma")) {
		printk(KERN_ERR THIS "request_mem_region failed. Aborting.\n");
		return -ENODEV;
	}

	cs2_base = ioremap_nocache(MX51_CS2_BASE_ADDR, SZ_64K);

	if (!cs2_base) {
		printk(KERN_WARNING THIS "Failed to obtain I/O space\n");
		ret = -ENODEV;
		goto failed_ioremap;
	}

	return 0;

failed_ioremap:
	release_mem_region(MX51_CS2_BASE_ADDR, SZ_64K);

	return ret;
}
Beispiel #13
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
}
Beispiel #14
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, 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
}
Beispiel #15
0
	friend constexpr inline
	bitfield operator | (bitfield a, bitfield b)
	noexcept
	{
		return bitfield(BF(a._bits)|BF(b._bits));
	}
Beispiel #16
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
}
Beispiel #17
0
/* -----------------------------------------------------------------------------
   vmx_get_specs()
	Obtain VMX facility specifications for this CPU and
	enter them into the vmx_specs_t structure. If VMX is not available or
	disabled on this CPU, set vmx_present to false and return leaving
	the remainder of the vmx_specs_t uninitialized. 
   -------------------------------------------------------------------------- */
void
vmx_get_specs()
{
	vmx_specs_t *specs = &current_cpu_datap()->cpu_vmx.specs;
	uint64_t msr_image;
	
	/* this is called once for every CPU, but the lock doesn't care :-) */
	simple_lock_init(&vmx_use_count_lock, 0);

	vmx_init();

	/*
	 * if we have read the data on boot, we won't read it
	 *  again on wakeup, otherwise *bad* things will happen
	 */
	if (specs->initialized)
		return;
	else
		specs->initialized = TRUE;

	/* See if VMX is present, return if it is not */
	specs->vmx_present = vmx_is_available() && vmxon_is_enabled();
	if (!specs->vmx_present)
		return;

#define bitfield(x,f)	((x >> f##_BIT) & f##_MASK)
	/* Obtain and decode VMX general capabilities */	
	msr_image = rdmsr64(MSR_IA32_VMX_BASIC);
	specs->vmcs_id       = (uint32_t)(msr_image & VMX_VCR_VMCS_REV_ID);
	specs->vmcs_mem_type = bitfield(msr_image, VMX_VCR_VMCS_MEM_TYPE) != 0;
	specs->vmcs_size = bitfield(msr_image, VMX_VCR_VMCS_SIZE);
							  
	/* Obtain allowed settings for pin-based execution controls */
	msr_image = rdmsr64(MSR_IA32_VMXPINBASED_CTLS);
	specs->pin_exctls_0 = (uint32_t)(msr_image & 0xFFFFFFFF);
	specs->pin_exctls_1 = (uint32_t)(msr_image >> 32);
	
	/* Obtain allowed settings for processor-based execution controls */
	msr_image = rdmsr64(MSR_IA32_PROCBASED_CTLS);
	specs->proc_exctls_0 = (uint32_t)(msr_image & 0xFFFFFFFF);
	specs->proc_exctls_1 = (uint32_t)(msr_image >> 32);
	
	/* Obtain allowed settings for VM-exit controls */
	msr_image = rdmsr64(MSR_IA32_VMX_EXIT_CTLS);
	specs->exit_ctls_0 = (uint32_t)(msr_image & 0xFFFFFFFF);
	specs->exit_ctls_1 = (uint32_t)(msr_image >> 32);
	
	/* Obtain allowed settings for VM-entry controls */
	msr_image = rdmsr64(MSR_IA32_VMX_ENTRY_CTLS);
	specs->enter_ctls_0 = (uint32_t)(msr_image & 0xFFFFFFFF);
	specs->enter_ctls_0 = (uint32_t)(msr_image >> 32);
	
	/* Obtain and decode miscellaneous capabilities */
	msr_image = rdmsr64(MSR_IA32_VMX_MISC);
	specs->act_halt     = bitfield(msr_image, VMX_VCR_ACT_HLT) != 0;
	specs->act_shutdown = bitfield(msr_image, VMX_VCR_ACT_SHUTDOWN) != 0;
	specs->act_SIPI     = bitfield(msr_image, VMX_VCR_ACT_SIPI) != 0;
	specs->act_CSTATE   = bitfield(msr_image, VMX_VCR_ACT_CSTATE) != 0;
	specs->cr3_targs    = bitfield(msr_image, VMX_VCR_CR3_TARGS);
	specs->max_msrs     = (uint32_t)(512 * (1 + bitfield(msr_image, VMX_VCR_MAX_MSRS)));
	specs->mseg_id      = (uint32_t)bitfield(msr_image, VMX_VCR_MSEG_ID);
	
	/* Obtain VMX-fixed bits in CR0 */
	specs->cr0_fixed_0 = (uint32_t)rdmsr64(MSR_IA32_VMX_CR0_FIXED0) & 0xFFFFFFFF;
	specs->cr0_fixed_1 = (uint32_t)rdmsr64(MSR_IA32_VMX_CR0_FIXED1) & 0xFFFFFFFF;
	
	/* Obtain VMX-fixed bits in CR4 */
	specs->cr4_fixed_0 = (uint32_t)rdmsr64(MSR_IA32_VMX_CR4_FIXED0) & 0xFFFFFFFF;
	specs->cr4_fixed_1 = (uint32_t)rdmsr64(MSR_IA32_VMX_CR4_FIXED1) & 0xFFFFFFFF;
}