diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index dc4b3d1e23..e4ea1e21fb 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -557,6 +557,8 @@ void __x86_setup_system_time(uint32 conversionFactor, uint32 conversionFactorNsecs, bool conversionFactorNsecsShift); #endif +status_t __x86_patch_errata_percpu(int cpu); + void x86_userspace_thread_exit(void); void x86_end_userspace_thread_exit(void); diff --git a/src/system/kernel/arch/x86/32/errata.cpp b/src/system/kernel/arch/x86/32/errata.cpp new file mode 100644 index 0000000000..8b4a80f890 --- /dev/null +++ b/src/system/kernel/arch/x86/32/errata.cpp @@ -0,0 +1,18 @@ +/* + * Copyright 2019, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Augustin Cavalier + */ + +#include +#include + + +status_t +__x86_patch_errata_percpu(int currentCPU) +{ + // TODO. + return B_OK; +} diff --git a/src/system/kernel/arch/x86/64/errata.cpp b/src/system/kernel/arch/x86/64/errata.cpp new file mode 100644 index 0000000000..0ecf7da3fb --- /dev/null +++ b/src/system/kernel/arch/x86/64/errata.cpp @@ -0,0 +1,105 @@ +/* + * Copyright 2019, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Augustin Cavalier + */ + +#include +#include + + +static status_t +patch_errata_percpu_amd(int currentCPU, const cpu_ent* cpu) +{ + // There are no errata to patch on a hypervisor, the host will have + // already taken care of everything for us. + if (x86_check_feature(IA32_FEATURE_EXT_HYPERVISOR, FEATURE_EXT)) + return B_OK; + + const uint32 family = cpu->arch.family + cpu->arch.extended_family, + model = (cpu->arch.extended_model << 4) | cpu->arch.model; + + // Family 10h and 12h, Erratum 721: + // + // "Under a highly specific and detailed set of internal timing conditions, + // the processor may incorrectly update the stack pointer after a long + // series of push and/or near-call instructions, or a long series of pop + // and/or near-return instructions. + // + // https://www.amd.com/system/files/TechDocs/41322_10h_Rev_Gd.pdf + // https://www.amd.com/system/files/TechDocs/44739_12h_Rev_Gd.pdf + switch (family) { + case 0x10: + case 0x12: + x86_write_msr(0xc0011029, x86_read_msr(0xc0011029) | 1); + break; + } + + // Family 16h ("Jaguar"), Erratum 793: + // + // "Under a highly specific and detailed set of internal timing conditions, + // a locked instruction may trigger a timing sequence whereby the write to + // a write combined memory type is not flushed, causing the locked instruction + // to stall indefinitely." + // + // https://www.amd.com/system/files/TechDocs/53072_Rev_Guide_16h_Models_30h-3Fh.pdf + if (family == 0x16 && model <= 0xf) { + x86_write_msr(0xc0011020, x86_read_msr(0xc0011020) | ((uint64)1 << 15)); + } + + // Family 17h ("Zen") Model 1h + // https://www.amd.com/system/files/TechDocs/55449_Fam_17h_M_00h-0Fh_Rev_Guide.pdf + if (family == 0x17 && model == 0x1) { + // Erratum 1021: + // + // "Under a highly specific and detailed set of internal timing + // conditions, a load operation may incorrectly receive stale data + // from an older store operation." + x86_write_msr(0xc0011029, x86_read_msr(0xc0011029) | (1 << 13)); + + // Erratum 1033: + // + // "Under a highly specific and detailed set of internal timing + // conditions, a Lock operation may cause the system to hang." + x86_write_msr(0xc0011020, x86_read_msr(0xc0011020) | (1 << 4)); + + // Erratum 1049: + // + // "Under a highly specific and detailed set of internal timing + // conditions, an FCMOV instruction may yield incorrect data if the + // following sequence of events occurs: + // * An FCOMI instruction + // * A non-FP instruction that modifies RFLAGS + // * An FCMOV instruction." + x86_write_msr(0xc0011028, x86_read_msr(0xc0011028) | (1 << 4)); + + // Erratum 1095: + // + // Under a highly detailed and specific set of internal timing + // conditions, a lock operation may not fence a younger load operation + // correctly when the following conditions are met: + // * SMT (Simultaneous Multithreading) is enabled, and + // * a lock operation on memory location A, followed by a load + // operation on memory location B are executing on one thread while + // * a lock operation on memory location B, followed by a load operation + // on memory location A are executing on the second thread on the + // same core. + // This may result in the load operations on both threads incorrectly + // receiving pre-lock data." + x86_write_msr(0xc0011020, x86_read_msr(0xc0011020) | ((uint64)1 << 57)); + } + + return B_OK; +} + + +status_t +__x86_patch_errata_percpu(int currentCPU) +{ + const cpu_ent* cpu = get_cpu_struct(); + if (cpu->arch.vendor == VENDOR_AMD) + return patch_errata_percpu_amd(currentCPU, cpu); + return B_OK; +} diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index dd068ac875..fee9cbdd4a 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -24,6 +24,7 @@ if $(TARGET_ARCH) = x86_64 { arch.S cpuid.cpp descriptors.cpp + errata.cpp interrupts.S signals.cpp signals_asm.S @@ -49,6 +50,7 @@ if $(TARGET_ARCH) = x86_64 { bios.cpp cpuid.S descriptors.cpp + errata.cpp interrupts.S signals.cpp signals_asm.S diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index 11b6ede26f..653e43dd71 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -1135,7 +1135,7 @@ arch_cpu_init_percpu(kernel_args* args, int cpu) gCpuIdleFunc = halt_idle; } - return B_OK; + return __x86_patch_errata_percpu(cpu); }