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
17EXPORT_NO_SYMBOLS;
18
19MODULE_PARM(force_rtc, "i");
20MODULE_PARM_DESC(force_rtc, "force RTC mode.");
21static 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 */
29static 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 */
53static 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 */
74static 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
114op_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