• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
p4_threads(void)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  */
do_cpu_id(void * data)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  */
p4_ht_enabled(void)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 
p4_cpu_type(void)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 
get_cpu_type(void)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