/** Copyright 2019-2023, Haiku, Inc. All rights reserved.* Distributed under the terms of the MIT License.** Authors:* Augustin Cavalier <waddlesplash>*/#include <cpu.h>#include <arch_cpu.h>static boolneeds_zenbleed_patch(const uint32 family, const uint32 model, const uint64 microcode){if (family != 0x17)return false;// https://github.com/torvalds/linux/blob/522b1d6921/arch/x86/kernel/cpu/amd.c#L986if (model >= 0x30 && model <= 0x3f)return (microcode < 0x0830107a);if (model >= 0x60 && model <= 0x67)return (microcode < 0x0860010b);if (model >= 0x68 && model <= 0x6f)return (microcode < 0x08608105);if (model >= 0x70 && model <= 0x7f)return (microcode < 0x08701032);if (model >= 0xa0 && model <= 0xaf)return (microcode < 0x08a00008);return false;}static status_tpatch_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;const uint64 microcode = x86_read_msr(IA32_MSR_UCODE_REV);// 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.pdfswitch (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.pdfif (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.pdfif (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));}// Family 17h ("Zen")// Cross-Process Information Leak (aka. "Zenbleed")// https://www.amd.com/en/resources/product-security/bulletin/amd-sb-7008.htmlif (needs_zenbleed_patch(family, model, microcode)) {x86_write_msr(MSR_F10H_DE_CFG, x86_read_msr(MSR_F10H_DE_CFG) | (1 << 9));}return B_OK;}status_t__x86_patch_errata_percpu(int currentCPU){const cpu_ent* cpu = get_cpu_struct();if (cpu->arch.vendor == VENDOR_AMD|| cpu->arch.vendor == VENDOR_HYGON) {return patch_errata_percpu_amd(currentCPU, cpu);}return B_OK;}