1 | /*␊ |
2 | * Copyright 2010,2011 valv, cparm <armelcadetpetit@gmail.com>. All rights reserved.␊ |
3 | */␊ |
4 | #include "boot.h"␊ |
5 | #include "bootstruct.h"␊ |
6 | #include "libsaio.h"␊ |
7 | #include "modules.h"␊ |
8 | #include "Platform.h"␊ |
9 | #include "cpu.h"␊ |
10 | ␊ |
11 | #define kFixFSB␉␉ "FixFSB"␊ |
12 | #define MSR_FSB_FREQ␉␉0x000000cd␊ |
13 | #define AMD_10H_11H_CONFIG 0xc0010064␊ |
14 | #define kEnableCPUfreq␉"EnableCPUfreqModule"␊ |
15 | ␊ |
16 | void CPUfreq_hook(void* arg1, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6)␊ |
17 | {␉␊ |
18 | ␉int bus_ratio;␉␉␉␉ ␊ |
19 | ␉uint64_t␉msr , fsbFrequency , cpuFrequency , minfsb , maxfsb ;␊ |
20 | ␉␊ |
21 | ␉if ((Platform->CPU.Vendor == 0x756E6547 /* Intel */) && ((Platform->CPU.Family == 0x06) || (Platform->CPU.Family == 0x0f))) {␊ |
22 | ␉␉if ((Platform->CPU.Family == 0x06 && Platform->CPU.Model >= 0x0c) || (Platform->CPU.Family == 0x0f && Platform->CPU.Model >= 0x03)) {␊ |
23 | ␉␉␉␊ |
24 | ␉␉␉if (Platform->CPU.Family == 0x06) {␊ |
25 | ␉␉␉␉␊ |
26 | ␉␉␉␉bus_ratio = 0; ␉␉␉␉␉␉␉␉ ␊ |
27 | ␉␉␉␉msr = rdmsr64(MSR_FSB_FREQ); ␊ |
28 | ␉␉␉␉fsbFrequency = 0;␊ |
29 | ␉␉␉␉cpuFrequency = 0; ␊ |
30 | ␉␉␉␉minfsb = 183000000; ␊ |
31 | ␉␉␉␉maxfsb = 185000000;␊ |
32 | ␉␉␉␉␊ |
33 | ␉␉␉␉bool␉␉fix_fsb = false;␉␉␉␉␊ |
34 | ␉␉␉␉uint16_t idlo;␊ |
35 | ␉␉␉␉uint8_t crlo, crhi = 0;␉␉␉␉␊ |
36 | ␉␉␉␉␊ |
37 | ␉␉␉␉switch (Platform->CPU.Model) {␊ |
38 | ␉␉␉␉␉case CPUID_MODEL_YONAH:␉␉// Core Duo/Solo, Pentium M DC␊ |
39 | ␉␉␉␉␉case CPUID_MODEL_MEROM:␉␉// Core Xeon, Core 2 DC, 65nm␊ |
40 | ␉␉␉␉␉case 0x16:␉␉␉␉␉// Celeron, Core 2 SC, 65nm␊ |
41 | ␉␉␉␉␉case CPUID_MODEL_PENRYN:␉␉// Core 2 Duo/Extreme, Xeon, 45nm␊ |
42 | ␉␉␉␉␉case CPUID_MODEL_ATOM:␉␉// Atom :)␊ |
43 | ␉␉␉␉␉case 0x27:␉␉␉␉␉// Atom Lincroft, 45nm ␊ |
44 | ␉␉␉␉␉␉␊ |
45 | ␉␉␉␉␉␉getBoolForKey(kFixFSB, &fix_fsb, &bootInfo->bootConfig); ␊ |
46 | ␉␉␉␉␉␉␊ |
47 | ␉␉␉␉␉␉if (fix_fsb) {␊ |
48 | ␉␉␉␉␉␉␉␊ |
49 | ␉␉␉␉␉␉␉int bus = (msr >> 0) & 0x7; ␊ |
50 | ␉␉␉␉␉␉␉switch (bus) {␊ |
51 | ␉␉␉␉␉␉␉␉case 0:␊ |
52 | ␉␉␉␉␉␉␉␉␉fsbFrequency = 266666667;␊ |
53 | ␉␉␉␉␉␉␉␉␉break;␊ |
54 | ␉␉␉␉␉␉␉␉case 1:␊ |
55 | ␉␉␉␉␉␉␉␉␉fsbFrequency = 133333333;␊ |
56 | ␉␉␉␉␉␉␉␉␉break;␊ |
57 | ␉␉␉␉␉␉␉␉case 2:␊ |
58 | ␉␉␉␉␉␉␉␉␉fsbFrequency = 200000000;␊ |
59 | ␉␉␉␉␉␉␉␉␉break;␊ |
60 | ␉␉␉␉␉␉␉␉case 3:␊ |
61 | ␉␉␉␉␉␉␉␉␉fsbFrequency = 166666667;␊ |
62 | ␉␉␉␉␉␉␉␉␉break;␊ |
63 | ␉␉␉␉␉␉␉␉case 4:␊ |
64 | ␉␉␉␉␉␉␉␉␉fsbFrequency = 333333333;␊ |
65 | ␉␉␉␉␉␉␉␉␉break;␊ |
66 | ␉␉␉␉␉␉␉␉case 5:␊ |
67 | ␉␉␉␉␉␉␉␉␉fsbFrequency = 100000000;␊ |
68 | ␉␉␉␉␉␉␉␉␉break;␊ |
69 | ␉␉␉␉␉␉␉␉case 6:␊ |
70 | ␉␉␉␉␉␉␉␉␉fsbFrequency = 400000000;␊ |
71 | ␉␉␉␉␉␉␉␉␉break;␊ |
72 | ␉␉␉␉␉␉␉␉default:␊ |
73 | ␉␉␉␉␉␉␉␉␉fsbFrequency = 200000000;␉␉␉␉␉␉␉␉␉␊ |
74 | ␉␉␉␉␉␉␉␉␉break;␊ |
75 | ␉␉␉␉␉␉␉}␊ |
76 | ␉␉␉␉␉␉␉␊ |
77 | ␉␉␉␉␉␉␉␊ |
78 | ␉␉␉␉␉␉␉if (((fsbFrequency) > (minfsb) && (fsbFrequency) < (maxfsb)) || (!fsbFrequency)) {␊ |
79 | ␉␉␉␉␉␉␉␉fsbFrequency = 200000000;␊ |
80 | ␉␉␉␉␉␉␉}␊ |
81 | ␉␉␉␉␉␉␉Platform->CPU.FSBFrequency = fsbFrequency;␊ |
82 | ␉␉␉␉␉␉}␊ |
83 | ␉␉␉␉␉␉␉␊ |
84 | ␉␉␉␉␉␉if (getIntForKey("MaxBusRatio", &bus_ratio, &bootInfo->bootConfig)) ␊ |
85 | ␉␉␉␉␉␉{ ␊ |
86 | ␉␉␉␉␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_STATUS);␊ |
87 | ␉␉␉␉␉␉␉␉idlo = (msr >> 48) & 0xffff;␉␉␉␉␉␉␉␉␊ |
88 | ␉␉␉␉␉␉␉␉crlo = (idlo >> 8) & 0xff;␊ |
89 | ␉␉␉␉␉␉␉␉␊ |
90 | ␉␉␉␉␉␉␉␉//printf("CPUfreq: MinCoef: 0x%x\n",crlo);␊ |
91 | ␉␉␉␉␉␉␉␉␊ |
92 | ␉␉␉␉␉␉␉␉if (Platform->CPU.MaxCoef) ␊ |
93 | ␉␉␉␉␉␉␉␉{␊ |
94 | ␉␉␉␉␉␉␉␉␉if (Platform->CPU.MaxDiv) ␊ |
95 | ␉␉␉␉␉␉␉␉␉{␊ |
96 | ␉␉␉␉␉␉␉␉␉␉crhi = (Platform->CPU.MaxCoef * 10) + 5;␊ |
97 | ␉␉␉␉␉␉␉␉␉}␊ |
98 | ␉␉␉␉␉␉␉␉␉else ␊ |
99 | ␉␉␉␉␉␉␉␉␉{␊ |
100 | ␉␉␉␉␉␉␉␉␉␉crhi = Platform->CPU.MaxCoef * 10;␊ |
101 | ␉␉␉␉␉␉␉␉␉}␊ |
102 | ␉␉␉␉␉␉␉␉}␊ |
103 | ␉␉␉␉␉␉␉␉if (crlo == 0 || crhi == crlo) goto out;␉␉␉␉␉␉␉␉␊ |
104 | ␉␉␉␉␉␉␉␉␊ |
105 | ␉␉␉␉␉␉␉␉if ((bus_ratio >= (crlo *10)) && (crhi >= bus_ratio) ) ␊ |
106 | ␉␉␉␉␉␉␉␉//if (bus_ratio >= 60) ␊ |
107 | ␉␉␉␉␉␉␉␉{␉␉␉␉␉␉␉␉␊ |
108 | ␉␉␉␉␉␉␉␉␉uint8_t currdiv = 0, currcoef = 0;␊ |
109 | ␉␉␉␉␉␉␉␉␉␊ |
110 | ␉␉␉␉␉␉␉␉␉currcoef = (int)(bus_ratio / 10);␊ |
111 | ␉␉␉␉␉␉␉␉␉␊ |
112 | ␉␉␉␉␉␉␉␉␉uint8_t fdiv = bus_ratio - (currcoef * 10);␊ |
113 | ␉␉␉␉␉␉␉␉␉if (fdiv > 0)␊ |
114 | ␉␉␉␉␉␉␉␉␉␉currdiv = 1;␊ |
115 | ␉␉␉␉␉␉␉␉␉␊ |
116 | ␉␉␉␉␉␉␉␉␉Platform->CPU.CurrCoef = currcoef;␊ |
117 | ␉␉␉␉␉␉␉␉␉Platform->CPU.CurrDiv = currdiv;␉␉␉␉␉␉␉␉␉␊ |
118 | ␉␉␉␉␉␉␉␉}␊ |
119 | ␉␉␉␉␉␉␉␉␊ |
120 | ␉␉␉␉␉␉␉␉␊ |
121 | ␉␉␉␉␉␉}␉␉␉␉␉␉␉␉␊ |
122 | ␉␉␉␉␉␉␉␊ |
123 | out:␊ |
124 | ␉␉␉␉␉␉␉if (Platform->CPU.CurrDiv) ␊ |
125 | ␉␉␉␉␉␉␉{␊ |
126 | ␉␉␉␉␉␉␉␉cpuFrequency = (Platform->CPU.FSBFrequency * ((Platform->CPU.CurrCoef * 2) + 1) / 2);␊ |
127 | ␉␉␉␉␉␉␉}␊ |
128 | ␉␉␉␉␉␉␉else ␊ |
129 | ␉␉␉␉␉␉␉{␊ |
130 | ␉␉␉␉␉␉␉␉cpuFrequency = (Platform->CPU.FSBFrequency * Platform->CPU.CurrCoef);␊ |
131 | ␉␉␉␉␉␉␉}␉␉␉␉␉␉␉␊ |
132 | ␉␉␉␉␉␉␉␊ |
133 | ␉␉␉␉␉␉␉Platform->CPU.CPUFrequency = cpuFrequency;␊ |
134 | ␉␉␉␉␉␉␉verbose("CPU: FSBFreq changed to: %dMHz\n", Platform->CPU.FSBFrequency / 1000000);␊ |
135 | ␉␉␉␉␉␉␉verbose("CPU: CPUFreq changed to: %dMHz\n", Platform->CPU.CPUFrequency / 1000000);␊ |
136 | ␉␉␉␉␉␉␉//verbose("CPUfreq: FSB Fix applied !\n");␉␉␉␉␉␉␉␊ |
137 | ␉␉␉␉␉␉ ␉␉␉␉␉␉␊ |
138 | ␉␉␉␉␉␉break;␊ |
139 | ␉␉␉␉␉case 0x1d:␉␉// Xeon MP MP 7400␊ |
140 | ␉␉␉␉␉default:␉␉␉␉␉␉␊ |
141 | ␉␉␉␉␉␉break;␊ |
142 | ␉␉␉␉}␊ |
143 | ␉␉␉}␊ |
144 | ␉␉}␊ |
145 | ␉}␊ |
146 | ␉else if(Platform->CPU.Vendor == 0x68747541 /* AMD */ && Platform->CPU.Family == 0x0f) // valv: work in progress␊ |
147 | ␉␉ {␊ |
148 | ␉␉␉ verbose("CPU: ");␊ |
149 | ␉␉␉ // valv: mobility check␉␉␉ ␊ |
150 | ␉␉␉ if ((strstr(Platform->CPU.BrandString, "obile") == 0) || (strstr(Platform->CPU.BrandString, "Atom") == 0))␊ |
151 | ␉␉␉␉␉{␊ |
152 | ␉␉␉␉␉␉ Platform->CPU.isMobile = true;␊ |
153 | ␉␉␉␉␉}␊ |
154 | ␉␉␉␉␉␊ |
155 | ␉␉␉ verbose("%s\n", Platform->CPU.BrandString);␊ |
156 | ␉␉␉␉␉uint8_t bus_ratio_current = 0;␊ |
157 | ␉␉␉␉␊ |
158 | ␉␉␉ if(Platform->CPU.ExtFamily == 0x00 /* K8 */)␊ |
159 | ␉␉␉␉ {␊ |
160 | ␉␉␉␉␉␉␉␊ |
161 | ␉␉␉␉␉ msr = rdmsr64(K8_FIDVID_STATUS);␊ |
162 | ␉␉␉␉␉␉␉␉bus_ratio_current = (msr & 0x3f) / 2 + 4; ␊ |
163 | ␉␉␉␉␉␉␉␉Platform->CPU.CurrDiv = (msr & 0x01) * 2;␉␉␉␉␉ ␊ |
164 | ␉␉␉␉␉ if (bus_ratio_current)␊ |
165 | ␉␉␉␉␉␉ {␊ |
166 | ␉␉␉␉␉␉␉ if (Platform->CPU.CurrDiv)␊ |
167 | ␉␉␉␉␉␉␉␉ {␊ |
168 | ␉␉␉␉␉␉␉␉␉ Platform->CPU.FSBFrequency = ((Platform->CPU.TSCFrequency * Platform->CPU.CurrDiv) / bus_ratio_current); // ?␊ |
169 | ␉␉␉␉␉␉␉␉␉ }␊ |
170 | ␉␉␉␉␉␉␉ else␊ |
171 | ␉␉␉␉␉␉␉␉ {␊ |
172 | ␉␉␉␉␉␉␉␉␉ Platform->CPU.FSBFrequency = (Platform->CPU.TSCFrequency / bus_ratio_current);␊ |
173 | ␉␉␉␉␉␉␉␉␉ }␊ |
174 | ␉␉␉␉␉␉␉ //fsbFrequency = (tscFrequency / bus_ratio_max); // ?␊ |
175 | ␉␉␉␉␉␉␉ }␊ |
176 | ␉␉␉␉␉ }␊ |
177 | ␉␉␉ else if(Platform->CPU.ExtFamily >= 0x01 /* K10+ */)␊ |
178 | ␉␉␉␉ {␊ |
179 | ␉␉␉␉␉␉␉␉␊ |
180 | ␉␉␉␉␉ msr = rdmsr64(AMD_10H_11H_CONFIG);␊ |
181 | ␉␉␉␉␉␉␉ bus_ratio_current = ((msr) & 0x3F);␊ |
182 | ␉␉␉␉␉␉␉␉Platform->CPU.CurrDiv = (2 << ((msr >> 6) & 0x07)) / 2;␊ |
183 | ␉␉␉␉␉ Platform->CPU.FSBFrequency = (Platform->CPU.CPUFrequency / bus_ratio_current);␊ |
184 | ␉␉␉␉␉␉␉␉␊ |
185 | ␊ |
186 | ␉␉␉␉␉ }␉␊ |
187 | ␉␉␉␉␊ |
188 | ␉␉␉␉␉if (!Platform->CPU.FSBFrequency) ␊ |
189 | ␉␉␉␉␉{␊ |
190 | ␉␉␉␉␉␉Platform->CPU.FSBFrequency = (DEFAULT_FSB * 1000);␊ |
191 | ␉␉␉␉␉␉verbose("0 ! using the default value for FSB !\n");␊ |
192 | ␉␉␉␉␉}␊ |
193 | ␉␉␉␉␉Platform->CPU.CurrCoef = bus_ratio_current / 10;␊ |
194 | ␉␉␉␉␉Platform->CPU.CPUFrequency = Platform->CPU.TSCFrequency;␊ |
195 | ␉␉␉␉␉␊ |
196 | ␉␉␉␉␉verbose("CPU (AMD): FSBFreq: %dMHz\n", Platform->CPU.FSBFrequency / 1000000);␊ |
197 | ␉␉␉␉␉verbose("CPU (AMD): CPUFreq: %dMHz\n", Platform->CPU.CPUFrequency / 1000000);␊ |
198 | ␉␉␉␉␉verbose("CPU (AMD): CurrCoef:␉␉␉ 0x%x\n", Platform->CPU.CurrCoef);␊ |
199 | ␉␉␉␉␉verbose("CPU (AMD): CurrDiv: 0x%x\n", Platform->CPU.CurrDiv);␉␊ |
200 | ␉␉␉ }␊ |
201 | ␊ |
202 | }␊ |
203 | ␊ |
204 | void CPUfreq_start()␊ |
205 | {␉␊ |
206 | ␉bool enable = true;␊ |
207 | ␉getBoolForKey(kEnableCPUfreq, &enable, &bootInfo->bootConfig) ;␊ |
208 | ␉␊ |
209 | ␉if (enable) {␊ |
210 | ␉␉if (Platform->CPU.Features & CPUID_FEATURE_MSR) {␊ |
211 | ␉␉␉register_hook_callback("PreBoot", &CPUfreq_hook);␉␉␊ |
212 | ␉␉} else {␊ |
213 | ␉␉␉verbose ("Unsupported CPU: CPUfreq disabled !!!\n");␉␉␊ |
214 | ␉␉}␉␊ |
215 | ␉}␊ |
216 | }␊ |
217 | |