xref: /haiku/src/system/kernel/arch/x86/64/errata.cpp (revision 68ea01249e1e2088933cb12f9c28d4e5c5d1c9ef)
1 /*
2  * Copyright 2019, Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Augustin Cavalier <waddlesplash>
7  */
8 
9 #include <cpu.h>
10 #include <arch_cpu.h>
11 
12 
13 static status_t
14 patch_errata_percpu_amd(int currentCPU, const cpu_ent* cpu)
15 {
16 	// There are no errata to patch on a hypervisor, the host will have
17 	// already taken care of everything for us.
18 	if (x86_check_feature(IA32_FEATURE_EXT_HYPERVISOR, FEATURE_EXT))
19 		return B_OK;
20 
21 	const uint32 family = cpu->arch.family + cpu->arch.extended_family,
22 		model = (cpu->arch.extended_model << 4) | cpu->arch.model;
23 
24 	// Family 10h and 12h, Erratum 721:
25 	//
26 	// "Under a highly specific and detailed set of internal timing conditions,
27 	// the processor may incorrectly update the stack pointer after a long
28 	// series of push and/or near-call instructions, or a long series of pop
29 	// and/or near-return instructions.
30 	//
31 	// https://www.amd.com/system/files/TechDocs/41322_10h_Rev_Gd.pdf
32 	// https://www.amd.com/system/files/TechDocs/44739_12h_Rev_Gd.pdf
33 	switch (family) {
34 	case 0x10:
35 	case 0x12:
36 		x86_write_msr(0xc0011029, x86_read_msr(0xc0011029) | 1);
37 		break;
38 	}
39 
40 	// Family 16h ("Jaguar"), Erratum 793:
41 	//
42 	// "Under a highly specific and detailed set of internal timing conditions,
43 	// a locked instruction may trigger a timing sequence whereby the write to
44 	// a write combined memory type is not flushed, causing the locked instruction
45 	// to stall indefinitely."
46 	//
47 	// https://www.amd.com/system/files/TechDocs/53072_Rev_Guide_16h_Models_30h-3Fh.pdf
48 	if (family == 0x16 && model <= 0xf) {
49 		x86_write_msr(0xc0011020, x86_read_msr(0xc0011020) | ((uint64)1 << 15));
50 	}
51 
52 	// Family 17h ("Zen") Model 1h
53 	// https://www.amd.com/system/files/TechDocs/55449_Fam_17h_M_00h-0Fh_Rev_Guide.pdf
54 	if (family == 0x17 && model == 0x1) {
55 		// Erratum 1021:
56 		//
57 		// "Under a highly specific and detailed set of internal timing
58 		// conditions, a load operation may incorrectly receive stale data
59 		// from an older store operation."
60 		x86_write_msr(0xc0011029, x86_read_msr(0xc0011029) | (1 << 13));
61 
62 		// Erratum 1033:
63 		//
64 		// "Under a highly specific and detailed set of internal timing
65 		// conditions, a Lock operation may cause the system to hang."
66 		x86_write_msr(0xc0011020, x86_read_msr(0xc0011020) | (1 << 4));
67 
68 		// Erratum 1049:
69 		//
70 		// "Under a highly specific and detailed set of internal timing
71 		// conditions, an FCMOV instruction may yield incorrect data if the
72 		// following sequence of events occurs:
73 		//  * An FCOMI instruction
74 		//  * A non-FP instruction that modifies RFLAGS
75 		//  * An FCMOV instruction."
76 		x86_write_msr(0xc0011028, x86_read_msr(0xc0011028) | (1 << 4));
77 
78 		// Erratum 1095:
79 		//
80 		// Under a highly detailed and specific set of internal timing
81 		// conditions, a lock operation may not fence a younger load operation
82 		// correctly when the following conditions are met:
83 		//  * SMT (Simultaneous Multithreading) is enabled, and
84 		//  * a lock operation on memory location A, followed by a load
85 		//    operation on memory location B are executing on one thread while
86 		//  * a lock operation on memory location B, followed by a load operation
87 		//    on memory location A are executing on the second thread on the
88 		//    same core.
89 		// This may result in the load operations on both threads incorrectly
90 		// receiving pre-lock data."
91 		x86_write_msr(0xc0011020, x86_read_msr(0xc0011020) | ((uint64)1 << 57));
92 	}
93 
94 	return B_OK;
95 }
96 
97 
98 status_t
99 __x86_patch_errata_percpu(int currentCPU)
100 {
101 	const cpu_ent* cpu = get_cpu_struct();
102 	if (cpu->arch.vendor == VENDOR_AMD)
103 		return patch_errata_percpu_amd(currentCPU, cpu);
104 	return B_OK;
105 }
106