/root/src/xen/xen/arch/x86/cpu/amd.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include <xen/init.h> |
2 | | #include <xen/bitops.h> |
3 | | #include <xen/mm.h> |
4 | | #include <xen/smp.h> |
5 | | #include <xen/pci.h> |
6 | | #include <asm/io.h> |
7 | | #include <asm/msr.h> |
8 | | #include <asm/processor.h> |
9 | | #include <asm/amd.h> |
10 | | #include <asm/hvm/support.h> |
11 | | #include <asm/setup.h> /* amd_init_cpu */ |
12 | | #include <asm/acpi.h> |
13 | | #include <asm/apic.h> |
14 | | |
15 | | #include "cpu.h" |
16 | | |
17 | | /* |
18 | | * Pre-canned values for overriding the CPUID features |
19 | | * and extended features masks. |
20 | | * |
21 | | * Currently supported processors: |
22 | | * |
23 | | * "fam_0f_rev_c" |
24 | | * "fam_0f_rev_d" |
25 | | * "fam_0f_rev_e" |
26 | | * "fam_0f_rev_f" |
27 | | * "fam_0f_rev_g" |
28 | | * "fam_10_rev_b" |
29 | | * "fam_10_rev_c" |
30 | | * "fam_11_rev_b" |
31 | | */ |
32 | | static char __initdata opt_famrev[14]; |
33 | | string_param("cpuid_mask_cpu", opt_famrev); |
34 | | |
35 | | static unsigned int __initdata opt_cpuid_mask_l7s0_eax = ~0u; |
36 | | integer_param("cpuid_mask_l7s0_eax", opt_cpuid_mask_l7s0_eax); |
37 | | static unsigned int __initdata opt_cpuid_mask_l7s0_ebx = ~0u; |
38 | | integer_param("cpuid_mask_l7s0_ebx", opt_cpuid_mask_l7s0_ebx); |
39 | | |
40 | | static unsigned int __initdata opt_cpuid_mask_thermal_ecx = ~0u; |
41 | | integer_param("cpuid_mask_thermal_ecx", opt_cpuid_mask_thermal_ecx); |
42 | | |
43 | | /* 1 = allow, 0 = don't allow guest creation, -1 = don't allow boot */ |
44 | | s8 __read_mostly opt_allow_unsafe; |
45 | | boolean_param("allow_unsafe", opt_allow_unsafe); |
46 | | |
47 | | static inline int rdmsr_amd_safe(unsigned int msr, unsigned int *lo, |
48 | | unsigned int *hi) |
49 | 0 | { |
50 | 0 | int err; |
51 | 0 |
|
52 | 0 | asm volatile("1: rdmsr\n2:\n" |
53 | 0 | ".section .fixup,\"ax\"\n" |
54 | 0 | "3: movl %6,%2\n" |
55 | 0 | " jmp 2b\n" |
56 | 0 | ".previous\n" |
57 | 0 | _ASM_EXTABLE(1b, 3b) |
58 | 0 | : "=a" (*lo), "=d" (*hi), "=r" (err) |
59 | 0 | : "c" (msr), "D" (0x9c5a203a), "2" (0), "i" (-EFAULT)); |
60 | 0 |
|
61 | 0 | return err; |
62 | 0 | } |
63 | | |
64 | | static inline int wrmsr_amd_safe(unsigned int msr, unsigned int lo, |
65 | | unsigned int hi) |
66 | 0 | { |
67 | 0 | int err; |
68 | 0 |
|
69 | 0 | asm volatile("1: wrmsr\n2:\n" |
70 | 0 | ".section .fixup,\"ax\"\n" |
71 | 0 | "3: movl %6,%0\n" |
72 | 0 | " jmp 2b\n" |
73 | 0 | ".previous\n" |
74 | 0 | _ASM_EXTABLE(1b, 3b) |
75 | 0 | : "=r" (err) |
76 | 0 | : "c" (msr), "a" (lo), "d" (hi), "D" (0x9c5a203a), |
77 | 0 | "0" (0), "i" (-EFAULT)); |
78 | 0 |
|
79 | 0 | return err; |
80 | 0 | } |
81 | | |
82 | | static void wrmsr_amd(unsigned int msr, uint64_t val) |
83 | 0 | { |
84 | 0 | asm volatile("wrmsr" :: |
85 | 0 | "c" (msr), "a" ((uint32_t)val), |
86 | 0 | "d" (val >> 32), "D" (0x9c5a203a)); |
87 | 0 | } |
88 | | |
89 | | static const struct cpuidmask { |
90 | | uint16_t fam; |
91 | | char rev[2]; |
92 | | unsigned int ecx, edx, ext_ecx, ext_edx; |
93 | | } pre_canned[] __initconst = { |
94 | | #define CAN(fam, id, rev) { \ |
95 | | fam, #rev, \ |
96 | | AMD_FEATURES_##id##_REV_##rev##_ECX, \ |
97 | | AMD_FEATURES_##id##_REV_##rev##_EDX, \ |
98 | | AMD_EXTFEATURES_##id##_REV_##rev##_ECX, \ |
99 | | AMD_EXTFEATURES_##id##_REV_##rev##_EDX \ |
100 | | } |
101 | | #define CAN_FAM(fam, rev) CAN(0x##fam, FAM##fam##h, rev) |
102 | | #define CAN_K8(rev) CAN(0x0f, K8, rev) |
103 | | CAN_FAM(11, B), |
104 | | CAN_FAM(10, C), |
105 | | CAN_FAM(10, B), |
106 | | CAN_K8(G), |
107 | | CAN_K8(F), |
108 | | CAN_K8(E), |
109 | | CAN_K8(D), |
110 | | CAN_K8(C) |
111 | | #undef CAN |
112 | | }; |
113 | | |
114 | | static const struct cpuidmask *__init noinline get_cpuidmask(const char *opt) |
115 | 0 | { |
116 | 0 | unsigned long fam; |
117 | 0 | char rev; |
118 | 0 | unsigned int i; |
119 | 0 |
|
120 | 0 | if (strncmp(opt, "fam_", 4)) |
121 | 0 | return NULL; |
122 | 0 | fam = simple_strtoul(opt + 4, &opt, 16); |
123 | 0 | if (strncmp(opt, "_rev_", 5) || !opt[5] || opt[6]) |
124 | 0 | return NULL; |
125 | 0 | rev = toupper(opt[5]); |
126 | 0 |
|
127 | 0 | for (i = 0; i < ARRAY_SIZE(pre_canned); ++i) |
128 | 0 | if (fam == pre_canned[i].fam && rev == *pre_canned[i].rev) |
129 | 0 | return &pre_canned[i]; |
130 | 0 |
|
131 | 0 | return NULL; |
132 | 0 | } |
133 | | |
134 | | /* |
135 | | * Sets caps in expected_levelling_cap, probes for the specified mask MSR, and |
136 | | * set caps in levelling_caps if it is found. Processors prior to Fam 10h |
137 | | * required a 32-bit password for masking MSRs. Returns the default value. |
138 | | */ |
139 | | static uint64_t __init _probe_mask_msr(unsigned int msr, uint64_t caps) |
140 | 0 | { |
141 | 0 | unsigned int hi, lo; |
142 | 0 |
|
143 | 0 | expected_levelling_cap |= caps; |
144 | 0 |
|
145 | 0 | if ((rdmsr_amd_safe(msr, &lo, &hi) == 0) && |
146 | 0 | (wrmsr_amd_safe(msr, lo, hi) == 0)) |
147 | 0 | levelling_caps |= caps; |
148 | 0 |
|
149 | 0 | return ((uint64_t)hi << 32) | lo; |
150 | 0 | } |
151 | | |
152 | | /* |
153 | | * Probe for the existance of the expected masking MSRs. They might easily |
154 | | * not be available if Xen is running virtualised. |
155 | | */ |
156 | | static void __init noinline probe_masking_msrs(void) |
157 | 0 | { |
158 | 0 | const struct cpuinfo_x86 *c = &boot_cpu_data; |
159 | 0 |
|
160 | 0 | /* |
161 | 0 | * First, work out which masking MSRs we should have, based on |
162 | 0 | * revision and cpuid. |
163 | 0 | */ |
164 | 0 |
|
165 | 0 | /* Fam11 doesn't support masking at all. */ |
166 | 0 | if (c->x86 == 0x11) |
167 | 0 | return; |
168 | 0 |
|
169 | 0 | cpuidmask_defaults._1cd = |
170 | 0 | _probe_mask_msr(MSR_K8_FEATURE_MASK, LCAP_1cd); |
171 | 0 | cpuidmask_defaults.e1cd = |
172 | 0 | _probe_mask_msr(MSR_K8_EXT_FEATURE_MASK, LCAP_e1cd); |
173 | 0 |
|
174 | 0 | if (c->cpuid_level >= 7) |
175 | 0 | cpuidmask_defaults._7ab0 = |
176 | 0 | _probe_mask_msr(MSR_AMD_L7S0_FEATURE_MASK, LCAP_7ab0); |
177 | 0 |
|
178 | 0 | if (c->x86 == 0x15 && c->cpuid_level >= 6 && cpuid_ecx(6)) |
179 | 0 | cpuidmask_defaults._6c = |
180 | 0 | _probe_mask_msr(MSR_AMD_THRM_FEATURE_MASK, LCAP_6c); |
181 | 0 |
|
182 | 0 | /* |
183 | 0 | * Don't bother warning about a mismatch if virtualised. These MSRs |
184 | 0 | * are not architectural and almost never virtualised. |
185 | 0 | */ |
186 | 0 | if ((expected_levelling_cap == levelling_caps) || |
187 | 0 | cpu_has_hypervisor) |
188 | 0 | return; |
189 | 0 |
|
190 | 0 | printk(XENLOG_WARNING "Mismatch between expected (%#x) " |
191 | 0 | "and real (%#x) levelling caps: missing %#x\n", |
192 | 0 | expected_levelling_cap, levelling_caps, |
193 | 0 | (expected_levelling_cap ^ levelling_caps) & levelling_caps); |
194 | 0 | printk(XENLOG_WARNING "Fam %#x, model %#x level %#x\n", |
195 | 0 | c->x86, c->x86_model, c->cpuid_level); |
196 | 0 | printk(XENLOG_WARNING |
197 | 0 | "If not running virtualised, please report a bug\n"); |
198 | 0 | } |
199 | | |
200 | | /* |
201 | | * Context switch levelling state to the next domain. A parameter of NULL is |
202 | | * used to context switch to the default host state (by the cpu bringup-code, |
203 | | * crash path, etc). |
204 | | */ |
205 | | static void amd_ctxt_switch_levelling(const struct vcpu *next) |
206 | 0 | { |
207 | 0 | struct cpuidmasks *these_masks = &this_cpu(cpuidmasks); |
208 | 0 | const struct domain *nextd = next ? next->domain : NULL; |
209 | 0 | const struct cpuidmasks *masks = |
210 | 0 | (nextd && is_pv_domain(nextd) && nextd->arch.pv_domain.cpuidmasks) |
211 | 0 | ? nextd->arch.pv_domain.cpuidmasks : &cpuidmask_defaults; |
212 | 0 |
|
213 | 0 | if ((levelling_caps & LCAP_1cd) == LCAP_1cd) { |
214 | 0 | uint64_t val = masks->_1cd; |
215 | 0 |
|
216 | 0 | /* |
217 | 0 | * OSXSAVE defaults to 1, which causes fast-forwarding of |
218 | 0 | * Xen's real setting. Clobber it if disabled by the guest |
219 | 0 | * kernel. |
220 | 0 | */ |
221 | 0 | if (next && is_pv_vcpu(next) && !is_idle_vcpu(next) && |
222 | 0 | !(next->arch.pv_vcpu.ctrlreg[4] & X86_CR4_OSXSAVE)) |
223 | 0 | val &= ~((uint64_t)cpufeat_mask(X86_FEATURE_OSXSAVE) << 32); |
224 | 0 |
|
225 | 0 | if (unlikely(these_masks->_1cd != val)) { |
226 | 0 | wrmsr_amd(MSR_K8_FEATURE_MASK, val); |
227 | 0 | these_masks->_1cd = val; |
228 | 0 | } |
229 | 0 | } |
230 | 0 |
|
231 | 0 | #define LAZY(cap, msr, field) \ |
232 | 0 | ({ \ |
233 | 0 | if (unlikely(these_masks->field != masks->field) && \ |
234 | 0 | ((levelling_caps & cap) == cap)) \ |
235 | 0 | { \ |
236 | 0 | wrmsr_amd(msr, masks->field); \ |
237 | 0 | these_masks->field = masks->field; \ |
238 | 0 | } \ |
239 | 0 | }) |
240 | 0 |
|
241 | 0 | LAZY(LCAP_e1cd, MSR_K8_EXT_FEATURE_MASK, e1cd); |
242 | 0 | LAZY(LCAP_7ab0, MSR_AMD_L7S0_FEATURE_MASK, _7ab0); |
243 | 0 | LAZY(LCAP_6c, MSR_AMD_THRM_FEATURE_MASK, _6c); |
244 | 0 |
|
245 | 0 | #undef LAZY |
246 | 0 | } |
247 | | |
248 | | /* |
249 | | * Mask the features and extended features returned by CPUID. Parameters are |
250 | | * set from the boot line via two methods: |
251 | | * |
252 | | * 1) Specific processor revision string |
253 | | * 2) User-defined masks |
254 | | * |
255 | | * The user-defined masks take precedence. |
256 | | * |
257 | | * AMD "masking msrs" are actually overrides, making it possible to advertise |
258 | | * features which are not supported by the hardware. Care must be taken to |
259 | | * avoid this, as the accidentally-advertised features will not actually |
260 | | * function. |
261 | | */ |
262 | | static void __init noinline amd_init_levelling(void) |
263 | 0 | { |
264 | 0 | const struct cpuidmask *m = NULL; |
265 | 0 |
|
266 | 0 | probe_masking_msrs(); |
267 | 0 |
|
268 | 0 | if (*opt_famrev != '\0') { |
269 | 0 | m = get_cpuidmask(opt_famrev); |
270 | 0 |
|
271 | 0 | if (!m) |
272 | 0 | printk("Invalid processor string: %s\n", opt_famrev); |
273 | 0 | } |
274 | 0 |
|
275 | 0 | if ((levelling_caps & LCAP_1cd) == LCAP_1cd) { |
276 | 0 | uint32_t ecx, edx, tmp; |
277 | 0 |
|
278 | 0 | cpuid(0x00000001, &tmp, &tmp, &ecx, &edx); |
279 | 0 |
|
280 | 0 | if (~(opt_cpuid_mask_ecx & opt_cpuid_mask_edx)) { |
281 | 0 | ecx &= opt_cpuid_mask_ecx; |
282 | 0 | edx &= opt_cpuid_mask_edx; |
283 | 0 | } else if (m) { |
284 | 0 | ecx &= m->ecx; |
285 | 0 | edx &= m->edx; |
286 | 0 | } |
287 | 0 |
|
288 | 0 | /* Fast-forward bits - Must be set. */ |
289 | 0 | if (ecx & cpufeat_mask(X86_FEATURE_XSAVE)) |
290 | 0 | ecx |= cpufeat_mask(X86_FEATURE_OSXSAVE); |
291 | 0 | edx |= cpufeat_mask(X86_FEATURE_APIC); |
292 | 0 |
|
293 | 0 | /* Allow the HYPERVISOR bit to be set via guest policy. */ |
294 | 0 | ecx |= cpufeat_mask(X86_FEATURE_HYPERVISOR); |
295 | 0 |
|
296 | 0 | cpuidmask_defaults._1cd = ((uint64_t)ecx << 32) | edx; |
297 | 0 | } |
298 | 0 |
|
299 | 0 | if ((levelling_caps & LCAP_e1cd) == LCAP_e1cd) { |
300 | 0 | uint32_t ecx, edx, tmp; |
301 | 0 |
|
302 | 0 | cpuid(0x80000001, &tmp, &tmp, &ecx, &edx); |
303 | 0 |
|
304 | 0 | if (~(opt_cpuid_mask_ext_ecx & opt_cpuid_mask_ext_edx)) { |
305 | 0 | ecx &= opt_cpuid_mask_ext_ecx; |
306 | 0 | edx &= opt_cpuid_mask_ext_edx; |
307 | 0 | } else if (m) { |
308 | 0 | ecx &= m->ext_ecx; |
309 | 0 | edx &= m->ext_edx; |
310 | 0 | } |
311 | 0 |
|
312 | 0 | /* Fast-forward bits - Must be set. */ |
313 | 0 | edx |= cpufeat_mask(X86_FEATURE_APIC); |
314 | 0 |
|
315 | 0 | cpuidmask_defaults.e1cd = ((uint64_t)ecx << 32) | edx; |
316 | 0 | } |
317 | 0 |
|
318 | 0 | if ((levelling_caps & LCAP_7ab0) == LCAP_7ab0) { |
319 | 0 | uint32_t eax, ebx, tmp; |
320 | 0 |
|
321 | 0 | cpuid(0x00000007, &eax, &ebx, &tmp, &tmp); |
322 | 0 |
|
323 | 0 | if (~(opt_cpuid_mask_l7s0_eax & opt_cpuid_mask_l7s0_ebx)) { |
324 | 0 | eax &= opt_cpuid_mask_l7s0_eax; |
325 | 0 | ebx &= opt_cpuid_mask_l7s0_ebx; |
326 | 0 | } |
327 | 0 |
|
328 | 0 | cpuidmask_defaults._7ab0 &= ((uint64_t)eax << 32) | ebx; |
329 | 0 | } |
330 | 0 |
|
331 | 0 | if ((levelling_caps & LCAP_6c) == LCAP_6c) { |
332 | 0 | uint32_t ecx = cpuid_ecx(6); |
333 | 0 |
|
334 | 0 | if (~opt_cpuid_mask_thermal_ecx) |
335 | 0 | ecx &= opt_cpuid_mask_thermal_ecx; |
336 | 0 |
|
337 | 0 | cpuidmask_defaults._6c &= (~0ULL << 32) | ecx; |
338 | 0 | } |
339 | 0 |
|
340 | 0 | if (opt_cpu_info) { |
341 | 0 | printk(XENLOG_INFO "Levelling caps: %#x\n", levelling_caps); |
342 | 0 | printk(XENLOG_INFO |
343 | 0 | "MSR defaults: 1d 0x%08x, 1c 0x%08x, e1d 0x%08x, " |
344 | 0 | "e1c 0x%08x, 7a0 0x%08x, 7b0 0x%08x, 6c 0x%08x\n", |
345 | 0 | (uint32_t)cpuidmask_defaults._1cd, |
346 | 0 | (uint32_t)(cpuidmask_defaults._1cd >> 32), |
347 | 0 | (uint32_t)cpuidmask_defaults.e1cd, |
348 | 0 | (uint32_t)(cpuidmask_defaults.e1cd >> 32), |
349 | 0 | (uint32_t)(cpuidmask_defaults._7ab0 >> 32), |
350 | 0 | (uint32_t)cpuidmask_defaults._7ab0, |
351 | 0 | (uint32_t)cpuidmask_defaults._6c); |
352 | 0 | } |
353 | 0 |
|
354 | 0 | if (levelling_caps) |
355 | 0 | ctxt_switch_levelling = amd_ctxt_switch_levelling; |
356 | 0 | } |
357 | | |
358 | | /* |
359 | | * Check for the presence of an AMD erratum. Arguments are defined in amd.h |
360 | | * for each known erratum. Return 1 if erratum is found. |
361 | | */ |
362 | | int cpu_has_amd_erratum(const struct cpuinfo_x86 *cpu, int osvw_id, ...) |
363 | 0 | { |
364 | 0 | va_list ap; |
365 | 0 | u32 range; |
366 | 0 | u32 ms; |
367 | 0 | |
368 | 0 | if (cpu->x86_vendor != X86_VENDOR_AMD) |
369 | 0 | return 0; |
370 | 0 |
|
371 | 0 | if (osvw_id >= 0 && cpu_has(cpu, X86_FEATURE_OSVW)) { |
372 | 0 | u64 osvw_len; |
373 | 0 |
|
374 | 0 | rdmsrl(MSR_AMD_OSVW_ID_LENGTH, osvw_len); |
375 | 0 |
|
376 | 0 | if (osvw_id < osvw_len) { |
377 | 0 | u64 osvw_bits; |
378 | 0 |
|
379 | 0 | rdmsrl(MSR_AMD_OSVW_STATUS + (osvw_id >> 6), |
380 | 0 | osvw_bits); |
381 | 0 |
|
382 | 0 | return (osvw_bits >> (osvw_id & 0x3f)) & 1; |
383 | 0 | } |
384 | 0 | } |
385 | 0 |
|
386 | 0 | /* OSVW unavailable or ID unknown, match family-model-stepping range */ |
387 | 0 | va_start(ap, osvw_id); |
388 | 0 |
|
389 | 0 | ms = (cpu->x86_model << 4) | cpu->x86_mask; |
390 | 0 | while ((range = va_arg(ap, int))) { |
391 | 0 | if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) && |
392 | 0 | (ms >= AMD_MODEL_RANGE_START(range)) && |
393 | 0 | (ms <= AMD_MODEL_RANGE_END(range))) { |
394 | 0 | va_end(ap); |
395 | 0 | return 1; |
396 | 0 | } |
397 | 0 | } |
398 | 0 |
|
399 | 0 | va_end(ap); |
400 | 0 | return 0; |
401 | 0 | } |
402 | | |
403 | | /* |
404 | | * Disable C1-Clock ramping if enabled in PMM7.CpuLowPwrEnh on 8th-generation |
405 | | * cores only. Assume BIOS has setup all Northbridges equivalently. |
406 | | */ |
407 | | static void disable_c1_ramping(void) |
408 | 0 | { |
409 | 0 | u8 pmm7; |
410 | 0 | int node, nr_nodes; |
411 | 0 |
|
412 | 0 | /* Read the number of nodes from the first Northbridge. */ |
413 | 0 | nr_nodes = ((pci_conf_read32(0, 0, 0x18, 0x0, 0x60)>>4)&0x07)+1; |
414 | 0 | for (node = 0; node < nr_nodes; node++) { |
415 | 0 | /* PMM7: bus=0, dev=0x18+node, function=0x3, register=0x87. */ |
416 | 0 | pmm7 = pci_conf_read8(0, 0, 0x18+node, 0x3, 0x87); |
417 | 0 | /* Invalid read means we've updated every Northbridge. */ |
418 | 0 | if (pmm7 == 0xFF) |
419 | 0 | break; |
420 | 0 | pmm7 &= 0xFC; /* clear pmm7[1:0] */ |
421 | 0 | pci_conf_write8(0, 0, 0x18+node, 0x3, 0x87, pmm7); |
422 | 0 | printk ("AMD: Disabling C1 Clock Ramping Node #%x\n", node); |
423 | 0 | } |
424 | 0 | } |
425 | | |
426 | | static void disable_c1e(void *unused) |
427 | 0 | { |
428 | 0 | uint64_t msr_content; |
429 | 0 |
|
430 | 0 | /* |
431 | 0 | * Disable C1E mode, as the APIC timer stops in that mode. |
432 | 0 | * The MSR does not exist in all FamilyF CPUs (only Rev F and above), |
433 | 0 | * but we safely catch the #GP in that case. |
434 | 0 | */ |
435 | 0 | if ((rdmsr_safe(MSR_K8_ENABLE_C1E, msr_content) == 0) && |
436 | 0 | (msr_content & (3ULL << 27)) && |
437 | 0 | (wrmsr_safe(MSR_K8_ENABLE_C1E, msr_content & ~(3ULL << 27)) != 0)) |
438 | 0 | printk(KERN_ERR "Failed to disable C1E on CPU#%u (%16"PRIx64")\n", |
439 | 0 | smp_processor_id(), msr_content); |
440 | 0 | } |
441 | | |
442 | | static void check_disable_c1e(unsigned int port, u8 value) |
443 | 0 | { |
444 | 0 | /* C1E is sometimes enabled during entry to ACPI mode. */ |
445 | 0 | if ((port == acpi_smi_cmd) && (value == acpi_enable_value)) |
446 | 0 | on_each_cpu(disable_c1e, NULL, 1); |
447 | 0 | } |
448 | | |
449 | | /* |
450 | | * BIOS is expected to clear MtrrFixDramModEn bit. According to AMD BKDG : |
451 | | * "The MtrrFixDramModEn bit should be set to 1 during BIOS initalization of |
452 | | * the fixed MTRRs, then cleared to 0 for operation." |
453 | | */ |
454 | | static void check_syscfg_dram_mod_en(void) |
455 | 0 | { |
456 | 0 | uint64_t syscfg; |
457 | 0 | static bool_t printed = 0; |
458 | 0 |
|
459 | 0 | if (!((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && |
460 | 0 | (boot_cpu_data.x86 >= 0x0f))) |
461 | 0 | return; |
462 | 0 |
|
463 | 0 | rdmsrl(MSR_K8_SYSCFG, syscfg); |
464 | 0 | if (!(syscfg & K8_MTRRFIXRANGE_DRAM_MODIFY)) |
465 | 0 | return; |
466 | 0 |
|
467 | 0 | if (!test_and_set_bool(printed)) |
468 | 0 | printk(KERN_ERR "MTRR: SYSCFG[MtrrFixDramModEn] not " |
469 | 0 | "cleared by BIOS, clearing this bit\n"); |
470 | 0 |
|
471 | 0 | syscfg &= ~K8_MTRRFIXRANGE_DRAM_MODIFY; |
472 | 0 | wrmsrl(MSR_K8_SYSCFG, syscfg); |
473 | 0 | } |
474 | | |
475 | | static void amd_get_topology(struct cpuinfo_x86 *c) |
476 | 0 | { |
477 | 0 | int cpu; |
478 | 0 | unsigned bits; |
479 | 0 |
|
480 | 0 | if (c->x86_max_cores <= 1) |
481 | 0 | return; |
482 | 0 | /* |
483 | 0 | * On a AMD multi core setup the lower bits of the APIC id |
484 | 0 | * distingush the cores. |
485 | 0 | */ |
486 | 0 | cpu = smp_processor_id(); |
487 | 0 | bits = (cpuid_ecx(0x80000008) >> 12) & 0xf; |
488 | 0 |
|
489 | 0 | if (bits == 0) { |
490 | 0 | while ((1 << bits) < c->x86_max_cores) |
491 | 0 | bits++; |
492 | 0 | } |
493 | 0 |
|
494 | 0 | /* Low order bits define the core id */ |
495 | 0 | c->cpu_core_id = c->phys_proc_id & ((1<<bits)-1); |
496 | 0 | /* Convert local APIC ID into the socket ID */ |
497 | 0 | c->phys_proc_id >>= bits; |
498 | 0 | /* Collect compute unit ID if available */ |
499 | 0 | if (cpu_has(c, X86_FEATURE_TOPOEXT)) { |
500 | 0 | u32 eax, ebx, ecx, edx; |
501 | 0 |
|
502 | 0 | cpuid(0x8000001e, &eax, &ebx, &ecx, &edx); |
503 | 0 | c->compute_unit_id = ebx & 0xFF; |
504 | 0 | c->x86_num_siblings = ((ebx >> 8) & 0x3) + 1; |
505 | 0 | } |
506 | 0 | |
507 | 0 | if (opt_cpu_info) |
508 | 0 | printk("CPU %d(%d) -> Processor %d, %s %d\n", |
509 | 0 | cpu, c->x86_max_cores, c->phys_proc_id, |
510 | 0 | cpu_has(c, X86_FEATURE_TOPOEXT) ? "Compute Unit" : |
511 | 0 | "Core", |
512 | 0 | cpu_has(c, X86_FEATURE_TOPOEXT) ? c->compute_unit_id : |
513 | 0 | c->cpu_core_id); |
514 | 0 | } |
515 | | |
516 | | static void early_init_amd(struct cpuinfo_x86 *c) |
517 | 0 | { |
518 | 0 | if (c == &boot_cpu_data) |
519 | 0 | amd_init_levelling(); |
520 | 0 |
|
521 | 0 | amd_ctxt_switch_levelling(NULL); |
522 | 0 | } |
523 | | |
524 | | static void init_amd(struct cpuinfo_x86 *c) |
525 | 0 | { |
526 | 0 | u32 l, h; |
527 | 0 |
|
528 | 0 | unsigned long long value; |
529 | 0 |
|
530 | 0 | /* Disable TLB flush filter by setting HWCR.FFDIS on K8 |
531 | 0 | * bit 6 of msr C001_0015 |
532 | 0 | * |
533 | 0 | * Errata 63 for SH-B3 steppings |
534 | 0 | * Errata 122 for all steppings (F+ have it disabled by default) |
535 | 0 | */ |
536 | 0 | if (c->x86 == 15) { |
537 | 0 | rdmsrl(MSR_K7_HWCR, value); |
538 | 0 | value |= 1 << 6; |
539 | 0 | wrmsrl(MSR_K7_HWCR, value); |
540 | 0 | } |
541 | 0 |
|
542 | 0 | /* |
543 | 0 | * Some AMD CPUs duplicate the 3DNow bit in base and extended CPUID |
544 | 0 | * leaves. Unfortunately, this aliases PBE on Intel CPUs. Clobber the |
545 | 0 | * alias, leaving 3DNow in the extended leaf. |
546 | 0 | */ |
547 | 0 | __clear_bit(X86_FEATURE_PBE, c->x86_capability); |
548 | 0 | |
549 | 0 | if (c->x86 == 0xf && c->x86_model < 0x14 |
550 | 0 | && cpu_has(c, X86_FEATURE_LAHF_LM)) { |
551 | 0 | /* |
552 | 0 | * Some BIOSes incorrectly force this feature, but only K8 |
553 | 0 | * revision D (model = 0x14) and later actually support it. |
554 | 0 | * (AMD Erratum #110, docId: 25759). |
555 | 0 | */ |
556 | 0 | __clear_bit(X86_FEATURE_LAHF_LM, c->x86_capability); |
557 | 0 | if (!rdmsr_amd_safe(0xc001100d, &l, &h)) |
558 | 0 | wrmsr_amd_safe(0xc001100d, l, h & ~1); |
559 | 0 | } |
560 | 0 |
|
561 | 0 | /* MFENCE stops RDTSC speculation */ |
562 | 0 | __set_bit(X86_FEATURE_MFENCE_RDTSC, c->x86_capability); |
563 | 0 |
|
564 | 0 | switch(c->x86) |
565 | 0 | { |
566 | 0 | case 0xf ... 0x17: |
567 | 0 | disable_c1e(NULL); |
568 | 0 | if (acpi_smi_cmd && (acpi_enable_value | acpi_disable_value)) |
569 | 0 | pv_post_outb_hook = check_disable_c1e; |
570 | 0 | break; |
571 | 0 | } |
572 | 0 |
|
573 | 0 | display_cacheinfo(c); |
574 | 0 |
|
575 | 0 | if (c->extended_cpuid_level >= 0x80000008) { |
576 | 0 | c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; |
577 | 0 | } |
578 | 0 |
|
579 | 0 | if (c->extended_cpuid_level >= 0x80000007) { |
580 | 0 | if (cpu_has(c, X86_FEATURE_ITSC)) { |
581 | 0 | __set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability); |
582 | 0 | __set_bit(X86_FEATURE_NONSTOP_TSC, c->x86_capability); |
583 | 0 | if (c->x86 != 0x11) |
584 | 0 | __set_bit(X86_FEATURE_TSC_RELIABLE, |
585 | 0 | c->x86_capability); |
586 | 0 | } |
587 | 0 | } |
588 | 0 |
|
589 | 0 | /* re-enable TopologyExtensions if switched off by BIOS */ |
590 | 0 | if ((c->x86 == 0x15) && |
591 | 0 | (c->x86_model >= 0x10) && (c->x86_model <= 0x1f) && |
592 | 0 | !cpu_has(c, X86_FEATURE_TOPOEXT) && |
593 | 0 | !rdmsr_safe(MSR_K8_EXT_FEATURE_MASK, value)) { |
594 | 0 | value |= 1ULL << 54; |
595 | 0 | wrmsr_safe(MSR_K8_EXT_FEATURE_MASK, value); |
596 | 0 | rdmsrl(MSR_K8_EXT_FEATURE_MASK, value); |
597 | 0 | if (value & (1ULL << 54)) { |
598 | 0 | __set_bit(X86_FEATURE_TOPOEXT, c->x86_capability); |
599 | 0 | printk(KERN_INFO "CPU: Re-enabling disabled " |
600 | 0 | "Topology Extensions Support\n"); |
601 | 0 | } |
602 | 0 | } |
603 | 0 |
|
604 | 0 | /* |
605 | 0 | * The way access filter has a performance penalty on some workloads. |
606 | 0 | * Disable it on the affected CPUs. |
607 | 0 | */ |
608 | 0 | if (c->x86 == 0x15 && c->x86_model >= 0x02 && c->x86_model < 0x20 && |
609 | 0 | !rdmsr_safe(MSR_AMD64_IC_CFG, value) && (value & 0x1e) != 0x1e) |
610 | 0 | wrmsr_safe(MSR_AMD64_IC_CFG, value | 0x1e); |
611 | 0 |
|
612 | 0 | amd_get_topology(c); |
613 | 0 |
|
614 | 0 | /* Pointless to use MWAIT on Family10 as it does not deep sleep. */ |
615 | 0 | if (c->x86 == 0x10) |
616 | 0 | __clear_bit(X86_FEATURE_MONITOR, c->x86_capability); |
617 | 0 |
|
618 | 0 | if (!cpu_has_amd_erratum(c, AMD_ERRATUM_121)) |
619 | 0 | opt_allow_unsafe = 1; |
620 | 0 | else if (opt_allow_unsafe < 0) |
621 | 0 | panic("Xen will not boot on this CPU for security reasons" |
622 | 0 | "Pass \"allow_unsafe\" if you're trusting all your" |
623 | 0 | " (PV) guest kernels.\n"); |
624 | 0 | else if (!opt_allow_unsafe && c == &boot_cpu_data) |
625 | 0 | printk(KERN_WARNING |
626 | 0 | "*** Xen will not allow creation of DomU-s on" |
627 | 0 | " this CPU for security reasons. ***\n" |
628 | 0 | KERN_WARNING |
629 | 0 | "*** Pass \"allow_unsafe\" if you're trusting" |
630 | 0 | " all your (PV) guest kernels. ***\n"); |
631 | 0 |
|
632 | 0 | if (c->x86 == 0x16 && c->x86_model <= 0xf) { |
633 | 0 | if (c == &boot_cpu_data) { |
634 | 0 | l = pci_conf_read32(0, 0, 0x18, 0x3, 0x58); |
635 | 0 | h = pci_conf_read32(0, 0, 0x18, 0x3, 0x5c); |
636 | 0 | if ((l & 0x1f) | (h & 0x1)) |
637 | 0 | printk(KERN_WARNING |
638 | 0 | "Applying workaround for erratum 792: %s%s%s\n", |
639 | 0 | (l & 0x1f) ? "clearing D18F3x58[4:0]" : "", |
640 | 0 | ((l & 0x1f) && (h & 0x1)) ? " and " : "", |
641 | 0 | (h & 0x1) ? "clearing D18F3x5C[0]" : ""); |
642 | 0 |
|
643 | 0 | if (l & 0x1f) |
644 | 0 | pci_conf_write32(0, 0, 0x18, 0x3, 0x58, |
645 | 0 | l & ~0x1f); |
646 | 0 |
|
647 | 0 | if (h & 0x1) |
648 | 0 | pci_conf_write32(0, 0, 0x18, 0x3, 0x5c, |
649 | 0 | h & ~0x1); |
650 | 0 | } |
651 | 0 |
|
652 | 0 | rdmsrl(MSR_AMD64_LS_CFG, value); |
653 | 0 | if (!(value & (1 << 15))) { |
654 | 0 | static bool_t warned; |
655 | 0 |
|
656 | 0 | if (c == &boot_cpu_data || opt_cpu_info || |
657 | 0 | !test_and_set_bool(warned)) |
658 | 0 | printk(KERN_WARNING |
659 | 0 | "CPU%u: Applying workaround for erratum 793\n", |
660 | 0 | smp_processor_id()); |
661 | 0 | wrmsrl(MSR_AMD64_LS_CFG, value | (1 << 15)); |
662 | 0 | } |
663 | 0 | } else if (c->x86 == 0x12) { |
664 | 0 | rdmsrl(MSR_AMD64_DE_CFG, value); |
665 | 0 | if (!(value & (1U << 31))) { |
666 | 0 | static bool warned; |
667 | 0 |
|
668 | 0 | if (c == &boot_cpu_data || opt_cpu_info || |
669 | 0 | !test_and_set_bool(warned)) |
670 | 0 | printk(KERN_WARNING |
671 | 0 | "CPU%u: Applying workaround for erratum 665\n", |
672 | 0 | smp_processor_id()); |
673 | 0 | wrmsrl(MSR_AMD64_DE_CFG, value | (1U << 31)); |
674 | 0 | } |
675 | 0 | } |
676 | 0 |
|
677 | 0 | /* AMD CPUs do not support SYSENTER outside of legacy mode. */ |
678 | 0 | __clear_bit(X86_FEATURE_SEP, c->x86_capability); |
679 | 0 |
|
680 | 0 | if (c->x86 == 0x10) { |
681 | 0 | /* do this for boot cpu */ |
682 | 0 | if (c == &boot_cpu_data) |
683 | 0 | check_enable_amd_mmconf_dmi(); |
684 | 0 |
|
685 | 0 | fam10h_check_enable_mmcfg(); |
686 | 0 |
|
687 | 0 | /* |
688 | 0 | * On family 10h BIOS may not have properly enabled WC+ |
689 | 0 | * support, causing it to be converted to CD memtype. This may |
690 | 0 | * result in performance degradation for certain nested-paging |
691 | 0 | * guests. Prevent this conversion by clearing bit 24 in |
692 | 0 | * MSR_F10_BU_CFG2. |
693 | 0 | */ |
694 | 0 | rdmsrl(MSR_F10_BU_CFG2, value); |
695 | 0 | value &= ~(1ULL << 24); |
696 | 0 | wrmsrl(MSR_F10_BU_CFG2, value); |
697 | 0 | } |
698 | 0 |
|
699 | 0 | /* |
700 | 0 | * Family 0x12 and above processors have APIC timer |
701 | 0 | * running in deep C states. |
702 | 0 | */ |
703 | 0 | if ( opt_arat && c->x86 > 0x11 ) |
704 | 0 | __set_bit(X86_FEATURE_ARAT, c->x86_capability); |
705 | 0 |
|
706 | 0 | /* |
707 | 0 | * Prior to Family 0x14, perf counters are not reset during warm reboot. |
708 | 0 | * We have to reset them manually. |
709 | 0 | */ |
710 | 0 | if (nmi_watchdog != NMI_LOCAL_APIC && c->x86 < 0x14) { |
711 | 0 | wrmsrl(MSR_K7_PERFCTR0, 0); |
712 | 0 | wrmsrl(MSR_K7_PERFCTR1, 0); |
713 | 0 | wrmsrl(MSR_K7_PERFCTR2, 0); |
714 | 0 | wrmsrl(MSR_K7_PERFCTR3, 0); |
715 | 0 | } |
716 | 0 |
|
717 | 0 | if (cpu_has(c, X86_FEATURE_EFRO)) { |
718 | 0 | rdmsr(MSR_K7_HWCR, l, h); |
719 | 0 | l |= (1 << 27); /* Enable read-only APERF/MPERF bit */ |
720 | 0 | wrmsr(MSR_K7_HWCR, l, h); |
721 | 0 | } |
722 | 0 |
|
723 | 0 | /* Prevent TSC drift in non single-processor, single-core platforms. */ |
724 | 0 | if ((smp_processor_id() == 1) && !cpu_has(c, X86_FEATURE_ITSC)) |
725 | 0 | disable_c1_ramping(); |
726 | 0 |
|
727 | 0 | check_syscfg_dram_mod_en(); |
728 | 0 | } |
729 | | |
730 | | static const struct cpu_dev amd_cpu_dev = { |
731 | | .c_vendor = "AMD", |
732 | | .c_ident = { "AuthenticAMD" }, |
733 | | .c_early_init = early_init_amd, |
734 | | .c_init = init_amd, |
735 | | }; |
736 | | |
737 | | int __init amd_init_cpu(void) |
738 | 1 | { |
739 | 1 | cpu_devs[X86_VENDOR_AMD] = &amd_cpu_dev; |
740 | 1 | return 0; |
741 | 1 | } |