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 || cpu->arch.vendor == VENDOR_HYGON) { 104 return patch_errata_percpu_amd(currentCPU, cpu); 105 } 106 return B_OK; 107 } 108