Home | History | Annotate | Download | only in x86
      1 /**
      2  * @file cpu_type.c
      3  * CPU determination
      4  *
      5  * @remark Copyright 2002 OProfile authors
      6  * @remark Read the file COPYING
      7  *
      8  * @author John Levon
      9  * @author Philippe Elie
     10  */
     11 
     12 #include "oprofile.h"
     13 #include "op_msr.h"
     14 
     15 #include <linux/smp.h>
     16 
     17 EXPORT_NO_SYMBOLS;
     18 
     19 MODULE_PARM(force_rtc, "i");
     20 MODULE_PARM_DESC(force_rtc, "force RTC mode.");
     21 static int force_rtc;
     22 
     23 #ifndef HT_SUPPORT
     24 /**
     25  * p4_threads - determines the number of logical processor threads in a die
     26  *
     27  * returns number of threads in p4 die (1 for non-HT processors)
     28  */
     29 static int p4_threads(void)
     30 {
     31 	int processor_threads = 1;
     32 
     33 #ifdef CONFIG_SMP
     34 	if (test_bit(X86_FEATURE_HT, &current_cpu_data.x86_capability)) {
     35 		/* This it a Pentium 4 with HT, find number of threads */
     36 		int eax, ebx, ecx, edx;
     37 
     38 		cpuid (1, &eax, &ebx, &ecx, &edx);
     39 		processor_threads = (ebx >> 16) & 0xff;
     40 	}
     41 #endif /* CONFIG_SMP */
     42 
     43 	return processor_threads;
     44 }
     45 
     46 #ifdef CONFIG_SMP
     47 /**
     48  * do_cpu_id - Call the cpuid instruction and fill in data at passed address
     49  *
     50  * We expect that data is pointing to an array of unsigned chars as big as there
     51  * are cpus in an smp system.
     52  */
     53 static void do_cpu_id(void * data)
     54 {
     55 	int eax, ebx, ecx, edx;
     56 	unsigned char * ptr = (unsigned char *) data;
     57 
     58 	cpuid(1, &eax, &ebx, &ecx, &edx);
     59 
     60 	/* bits EBX[31:24] define APIC ID */
     61 	ptr[smp_processor_id()] = (unsigned char) ((ebx & 0xff000000) >> 24);
     62 }
     63 #endif
     64 
     65 /**
     66  * p4_ht_enabled - Determines if Hyper Threading is enabled or not.
     67  *
     68  * A P4 can be capable of HT, but not enabled via BIOS.  The check for
     69  * this is unfortunately not simple and involves running cpuid on all
     70  * logical processors and checking for bits in the APIC_ID fields.
     71  * As per Intel docs.  Returns 1 if enabled, 0 otherwise.
     72  *
     73  */
     74 static int p4_ht_enabled(void)
     75 {
     76 #ifndef CONFIG_SMP
     77 	return 0;
     78 #else
     79 	int enabled, threads, i;
     80 	unsigned char mask;
     81 	unsigned char apic_id[smp_num_cpus];
     82 	unsigned int cpu;
     83 
     84 	/* First check for capability */
     85 	threads = p4_threads();
     86 	if (threads == 1) return 0;
     87 	/* Create mask for low order bits */
     88 	mask = 0xff;
     89 	i = 1;
     90 	while (i < threads) {
     91 		i *= 2;
     92 		mask <<= 1;
     93 	}
     94 	/* Get APIC_ID from all logial procs and self */
     95 	smp_call_function(do_cpu_id, apic_id, 1, 1);
     96 	do_cpu_id(apic_id);
     97 	/* If the low order bits are on, then HT is enabled */
     98 	enabled = 0;
     99 	cpu = 0;
    100 	do {
    101 		if (apic_id[cpu] & ~mask) {
    102 			enabled = 1;
    103 			break;
    104 		}
    105 		cpu++;
    106 	} while (cpu < smp_num_cpus);
    107 
    108 	return enabled;
    109 #endif /* CONFIG_SMP */
    110 }
    111 #endif /* !HT_SUPPORT */
    112 
    113 
    114 op_cpu p4_cpu_type(void)
    115 {
    116 	__u8 model = current_cpu_data.x86_model;
    117 	if (model <= 4) {
    118 #ifdef HT_SUPPORT
    119 		if (smp_num_siblings == 1) {
    120 			return CPU_P4;
    121 		} else if (smp_num_siblings == 2) {
    122 			return CPU_P4_HT2;
    123 		} else {
    124 			printk(KERN_INFO
    125 			       "oprofile: P4 HT unsupported number of siblings"
    126 			       "processor, reverting to RTC\n");
    127 			return CPU_RTC;
    128 		}
    129 #else
    130 		/* Cannot handle enabled HT P4 hardware */
    131 		if ((p4_threads() > 1) && p4_ht_enabled()) {
    132 			printk(KERN_INFO
    133 			       "oprofile: P4 HT enabled, reverting to RTC\n");
    134 			return CPU_RTC;
    135 		}
    136 		else
    137 			return CPU_P4;
    138 #endif
    139 	} else
    140 		/* Do not know what it is */
    141 		return CPU_RTC;
    142 }
    143 
    144 
    145 __init op_cpu get_cpu_type(void)
    146 {
    147 	__u8 vendor = current_cpu_data.x86_vendor;
    148 	__u8 family = current_cpu_data.x86;
    149 	__u8 model = current_cpu_data.x86_model;
    150 	__u16 val;
    151 
    152 	if (force_rtc)
    153 		return CPU_RTC;
    154 
    155 	switch (vendor) {
    156 		case X86_VENDOR_AMD:
    157 			if (family == 6) {
    158 				/* certain models of K7 does not have apic.
    159 				 * Check if apic is really present before enabling it.
    160 				 * IA32 V3, 7.4.1 */
    161 				val = cpuid_edx(1);
    162 				if (!(val & (1 << 9)))
    163 					return CPU_RTC;
    164 				return CPU_ATHLON;
    165 			}
    166 			if (family == 15)
    167 				return CPU_HAMMER;
    168 			return CPU_RTC;
    169 
    170 		case X86_VENDOR_INTEL:
    171 			switch (family) {
    172 			default:
    173 				return CPU_RTC;
    174 			case 6:
    175 				/* A P6-class processor */
    176 				if (model == 14)
    177 					return CPU_CORE;
    178 				if (model > 0xd)
    179 					return CPU_RTC;
    180 				if (model > 5)
    181 					return CPU_PIII;
    182 				else if (model > 2)
    183 					return CPU_PII;
    184 				return CPU_PPRO;
    185 			case 0xf:
    186 				return p4_cpu_type();
    187 			}
    188 
    189 		default:
    190 			return CPU_RTC;
    191 	}
    192 }
    193