Fix issues with flexcat file paths
[AROS.git] / arch / x86-all / processor / processor_frequency.c
blob796c01c0e47bb54c4bdcbb1e014838f7e60dd24a
1 /*
2 Copyright © 2010-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define DEBUG 0
8 #include <aros/config.h>
9 #include <aros/debug.h>
10 #include <proto/exec.h>
11 #include <resources/processor.h>
13 #include "processor_arch_intern.h"
16 * This code can't work on hosted because rdmsr instruction requires supervisor privilege.
17 * Hosted ports could have host-specific version of this code which would utilize host OS services.
19 #if (AROS_FLAVOUR & AROS_FLAVOUR_STANDALONE)
21 #define MSR_IA32_MPERF 0xE7
22 #define MSR_IA32_APERF 0xE8
23 #define MSR_P4_EBC_FREQUENCY_ID 0x2C
24 #define MSR_CORE_FSB_FREQ 0xCD
25 #define MSR_CORE_EBL_CR_POWERON 0x2A
26 #define MSR_NAHALEM_PLATFORM_INFO 0xCE
27 #define MSR_K10_PSTATE_P0 0xC0010064
28 #define MSR_K8_FIDVID_STATUS 0xC0010042
30 #define FSB_100 100000000ULL
31 #define FSB_133 133330000ULL
32 #define FSB_166 166670000ULL
33 #define FSB_200 200000000ULL
34 #define FSB_266 266670000ULL
35 #define FSB_333 333330000ULL
36 #define FSB_400 400000000ULL
38 static VOID ReadIntelMaxFrequencyInformation(struct X86ProcessorInformation * info)
40 APTR ssp;
42 D(bug("[processor.x86] :%s()\n", __PRETTY_FUNCTION__));
44 ssp = SuperState();
46 /* Procedure for Pentium 4 family (NetBurst) */
47 if ((info->Family == CPUFAMILY_INTEL_PENTIUM4) && (info->Model >= 2))
49 ULONG eax, edx;
50 UQUAD fsb = 0;
51 ULONG mult = 0;
53 /* This procedure calculates the maximum frequency */
55 rdmsr(MSR_P4_EBC_FREQUENCY_ID, &eax, &edx);
57 /*Intel 64 and IA-32 Architectures
58 Software Developer's Manual
59 Volume 3B:System Programming Guide, Part 2
60 Table B-12 */
61 switch((eax >> 16) & 0x07)
63 case(0):
64 if (info->Model == 2)
65 fsb = FSB_100;
66 else
67 fsb = FSB_266;
68 break;
69 case(1): fsb = FSB_133; break;
70 case(2): fsb = FSB_200; break;
71 case(3): fsb = FSB_166; break;
72 case(4): fsb = FSB_333; break;
73 default: fsb = 0; break;
76 /* Getting multiplier at reset time */
77 mult = eax >> 24;
79 info->MaxCPUFrequency = fsb * mult;
80 info->MaxFSBFrequency = fsb * 4;
83 /* Procedure for Pentium M (part of Pentium Pro) family */
84 if ((info->Family == CPUFAMILY_INTEL_PENTIUM_PRO) &&
86 (info->Model == 0x09) || /* Pentium M */
87 (info->Model == 0x0D) /* Pentium M */
91 ULONG eax, edx;
92 ULONG mult = 0;
94 /*Intel 64 and IA-32 Architectures
95 Software Developer's Manual
96 Volume 3B:System Programming Guide, Part 2
97 Table B-16 */
99 rdmsr(MSR_CORE_EBL_CR_POWERON, &eax, &edx);
101 mult = (eax >> 22) & 0x1F;
103 info->MaxCPUFrequency = FSB_100 * mult;
104 info->MaxFSBFrequency = FSB_100 * 4;
107 /* Procedure for Core (part of Pentium Pro) family (ATOM, Core, Core Duo) */
108 if ((info->Family == CPUFAMILY_INTEL_PENTIUM_PRO) &&
110 (info->Model == 0x0E) || /* Core Duo */
111 (info->Model == 0x0F) || /* Core 2 Duo */
112 (info->Model == 0x16) || /* Core Celeron */
113 (info->Model == 0x17) || /* Core 2 Extreme */
114 (info->Model == 0x1C) /* ATOM */
118 ULONG eax, edx;
119 UQUAD fsb = 0;
120 ULONG mult = 0;
122 /* This procedure calculates the maximum frequency */
124 rdmsr(MSR_CORE_FSB_FREQ, &eax, &edx);
126 /*Intel 64 and IA-32 Architectures
127 Software Developer's Manual
128 Volume 3B:System Programming Guide, Part 2
129 Table B-3 */
130 switch(eax & 0x07)
132 case(5): fsb = FSB_100; break;
133 case(1): fsb = FSB_133; break;
134 case(3): fsb = FSB_166; break;
135 case(2): fsb = FSB_200; break;
136 case(0): fsb = FSB_266; break;
137 case(4): fsb = FSB_333; break;
138 case(6): fsb = FSB_400; break;
139 default: fsb = 0; break;
142 rdmsr(MSR_CORE_EBL_CR_POWERON, &eax, &edx);
143 /* Getting multiplier at reset time */
144 mult = (eax >> 22) & 0x1F;
146 info->MaxCPUFrequency = fsb * mult;
147 info->MaxFSBFrequency = fsb * 4;
150 /* Procedure for Nahalem (part of Pentium Pro) family (i7, i5, i3) */
151 if ((info->Family == CPUFAMILY_INTEL_PENTIUM_PRO) &&
153 (info->Model == 0x1A) || /* Core i7 */
154 (info->Model == 0x1E) || /* ? */
155 (info->Model == 0x1F) || /* ? */
156 (info->Model == 0x2E) /* ? */
160 ULONG eax, edx;
161 ULONG mult = 0;
163 /* This procedure calculates the maximum frequency */
165 rdmsr(MSR_NAHALEM_PLATFORM_INFO, &eax, &edx);
167 /*Intel 64 and IA-32 Architectures
168 Software Developer's Manual
169 Volume 3B:System Programming Guide, Part 2
170 Table B-5 */
171 mult = (eax >> 8) & 0xFF;
173 info->MaxCPUFrequency = FSB_133 * mult;
174 /* Note: FSB is not a valid concept with iX (Nahalem) processors */
175 info->MaxFSBFrequency = 0;
178 UserState(ssp);
181 static VOID ReadAMDMaxFrequencyInformation(struct X86ProcessorInformation * info)
183 APTR ssp;
185 D(bug("[processor.x86] :%s()\n", __PRETTY_FUNCTION__));
187 ssp = SuperState();
189 if (info->Family == CPUFAMILY_AMD_K10)
191 ULONG eax, edx;
192 ULONG cpufid = 0, cpudid = 0;
194 /* AMD Family 10h Processor BKDG, page 425 */
195 rdmsr(MSR_K10_PSTATE_P0, &eax, &edx);
197 cpufid = eax & 0x1F;
198 cpudid = (eax >> 6) & 0x07;
200 info->MaxCPUFrequency = FSB_100 * (cpufid + 0x10) / (1 << cpudid);
201 /* Note: FSB is not a valid concept with K10 processors */
202 info->MaxFSBFrequency = 0;
205 if ((info->Family == CPUFAMILY_AMD_K9)
206 || (info->Family == CPUFAMILY_AMD_K8))
208 ULONG eax, ebx, ecx, edx;
209 ULONG cpufid = 0;
210 BOOL success = TRUE;
212 /* BIOS and Kernel Developer's Guide for the AMD AthlonTM 64 and
213 AMD OpteronTM Processors, page 382 */
215 /* Check for power management features */
216 if (info->CPUIDHighestExtendedFunction < 0x80000007)
217 success = FALSE;
219 if (success)
221 cpuid(0x80000007);
223 /* Check avalability of FID */
224 if ((edx & 0x02) == 0)
225 success = FALSE;
228 if (success)
230 /* It should be safe to read MSR_K8_FIDVID_STATUS */
231 rdmsr(MSR_K8_FIDVID_STATUS, &eax, &edx);
233 cpufid = (eax >> 16) & 0x3F;
235 /* Note: K8 has only even multipliers, but they match K9 ones */
236 info->MaxCPUFrequency = FSB_200 * (4 * 2 + cpufid) / 2;
238 /* Note: FSB is not a valid concept with K8, K9 processors */
239 info->MaxFSBFrequency = 0;
243 UserState(ssp);
246 #endif /* AROS_FLAVOUR_STANDALONE */
248 VOID ReadMaxFrequencyInformation(struct X86ProcessorInformation * info)
250 D(bug("[processor.x86] :%s()\n", __PRETTY_FUNCTION__));
252 info->MaxCPUFrequency = 0;
253 info->MaxFSBFrequency = 0;
255 #if (AROS_FLAVOUR & AROS_FLAVOUR_STANDALONE)
257 switch(info->Vendor)
259 case(VENDOR_INTEL):
260 ReadIntelMaxFrequencyInformation(info);
261 break;
262 case(VENDOR_AMD):
263 ReadAMDMaxFrequencyInformation(info);
264 break;
265 default:
266 break;
269 #endif
272 /* Currently the only method of calculating CPU Frequency is based on
273 using performance counter. Other methods might include reading power state
274 and checking with ACPI power tables or hardcoded power tables */
276 UQUAD GetCurrentProcessorFrequency(struct X86ProcessorInformation * info)
278 UQUAD retFreq = info->MaxCPUFrequency;
280 D(bug("[processor.x86] :%s()\n", __PRETTY_FUNCTION__));
282 #if (AROS_FLAVOUR & AROS_FLAVOUR_STANDALONE)
285 Check if APERF/MPERF is available
286 Notes: K10, K9 - rdmsr can be used to read current PState/cpufid/cpudid
288 if (info->APERFMPERF)
290 APTR ssp;
291 ULONG eax, edx;
292 UQUAD startaperf, endaperf, diffaperf = 0;
293 UQUAD startmperf, endmperf, diffmperf = 0;
294 LONG i;
296 ssp = SuperState();
298 for(i = 0; i < 10; i++)
300 rdmsr(MSR_IA32_MPERF, &eax, &edx);
301 startmperf = (UQUAD)edx << 32 | eax;
302 rdmsr(MSR_IA32_APERF, &eax, &edx);
303 startaperf = (UQUAD)edx << 32 | eax;
305 rdmsr(MSR_IA32_MPERF, &eax, &edx);
306 endmperf = (UQUAD)edx << 32 | eax;
307 rdmsr(MSR_IA32_APERF, &eax, &edx);
308 endaperf = (UQUAD)edx << 32 | eax;
310 if ((startmperf > endmperf) || (startaperf > endaperf))
311 continue; /* Overflow error. Skip */
313 diffmperf += endmperf - startmperf;
314 diffaperf += endaperf - startaperf;
317 UserState(ssp);
319 D(bug("[processor.x86] %s: max: %x, diffa: %x, diffm %x\n", __PRETTY_FUNCTION__, info->MaxCPUFrequency, diffaperf, diffmperf));
321 /* Use ratio between MPERF and APERF */
322 if (diffmperf)
323 retFreq = info->MaxCPUFrequency * diffaperf / diffmperf;
324 else
325 retFreq = info->MaxCPUFrequency;
327 else
329 /* use PStates? */
332 #endif
334 return retFreq;