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