Module Name: src Committed By: martin Date: Thu Oct 3 12:00:57 UTC 2024
Modified Files: src/sys/arch/x86/include [netbsd-10]: specialreg.h src/sys/arch/x86/x86 [netbsd-10]: errata.c src/usr.sbin/cpuctl/arch [netbsd-10]: i386.c Log Message: Pull up following revision(s) (requested by rin in ticket #919): sys/arch/x86/x86/errata.c: revision 1.28 sys/arch/x86/x86/errata.c: revision 1.29 sys/arch/x86/include/specialreg.h: revision 1.209 usr.sbin/cpuctl/arch/i386.c: revision 1.144 sys/arch/x86/x86/errata.c: revision 1.30 sys/arch/x86/x86/errata.c: revision 1.33 sys/arch/x86/x86/errata.c: revision 1.34 sys/arch/x86/x86/errata.c: revision 1.35 sys/arch/x86/include/specialreg.h: revision 1.210 sys/arch/x86/include/specialreg.h: revision 1.211 x86/errata.c: Link to original AMD errata guide. This one is no longer updated; need to link to newer ones for individual families too. That's where all the cryptic nomenclature comes from here. x86/errata.c: Say what revision we're searching for. x86/errata.c: Only say the errata revision search for cpu0. x86: make the CPUID list for errata be far less confusing the 0x80000001 CPUID result needs some parsing to match against actual family/model/stepping values. 4-bit 'family' values of 15 or 6 change how to parse the 4-bit extended model and 8-bit extended family value - for family 6 or 15, the extended model bits (4) are concatenated with the base 4-bits to create an 8-bit value, and for family 15, the family value is addition of the family value and the 8-bit extended-family value, giving a range of 0 to 15 + 0xff aka 270. use a CPUREV(family, model, stepping) macro that builds the relevant bit-representation of a CPUID, making it far easier to understand what each entry means, and to add new ones too. i have confirmed that the emitted cpurevs[] array has the same values before/after this change, ie, NFCI or observed. x86: add names for errata that don't have actual numbers zenbleed is reported as "erratum 65535" currently, this adds a name for it, and enables the name for any others as well. pull logging into a function with a tag message. x86: handle AMD errata 1474: A CPU core may hang after about 1044 days from the new comment: * This requires disabling CC6 power level, which can be a performance * issue since it stops full turbo in some implementations (eg, half the * cores must be in CC6 to achieve the highest boost level.) Set a timer * to fire in 1000 days -- except NetBSD timers end up having a signed * 32-bit hz-based value, which rolls over in under 25 days with HZ=1000, * and doing xcall(9) or kthread(9) from a callout is not allowed anyway, * so just have a kthread wait 1 day for 1000 times. documented in: https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/revision-guides/56323-PUB_1_01.pdf add MSR stuff for AMD errata 1474. cpuctl: fix i386 bit descriptions for CPUID_SEF_FLAGS1 warning: non-printing character '\31' in description 'BUS_LOCK_DETECT""b\31' [363] s/RPMQUERY/RMPQUERY/ To generate a diff of this commit: cvs rdiff -u -r1.198.2.5 -r1.198.2.6 src/sys/arch/x86/include/specialreg.h cvs rdiff -u -r1.27.4.2 -r1.27.4.3 src/sys/arch/x86/x86/errata.c cvs rdiff -u -r1.133.2.3 -r1.133.2.4 src/usr.sbin/cpuctl/arch/i386.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/x86/include/specialreg.h diff -u src/sys/arch/x86/include/specialreg.h:1.198.2.5 src/sys/arch/x86/include/specialreg.h:1.198.2.6 --- src/sys/arch/x86/include/specialreg.h:1.198.2.5 Sat Jul 20 14:19:31 2024 +++ src/sys/arch/x86/include/specialreg.h Thu Oct 3 12:00:57 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: specialreg.h,v 1.198.2.5 2024/07/20 14:19:31 martin Exp $ */ +/* $NetBSD: specialreg.h,v 1.198.2.6 2024/10/03 12:00:57 martin Exp $ */ /* * Copyright (c) 2014-2020 The NetBSD Foundation, Inc. @@ -481,7 +481,7 @@ "b\14AVX512_BITALG\0" "b\15TME_EN\0" "b\16AVX512_VPOPCNTDQ\0" \ "b\20LA57\0" \ "f\21\5MAWAU\0" "b\26RDPID\0" "b\27KL\0" \ - "b\30BUS_LOCK_DETECT" "b\31CLDEMOTE\0" "b\33MOVDIRI\0" \ + "b\30BUS_LOCK_DETECT\0" "b\31CLDEMOTE\0" "b\33MOVDIRI\0" \ "b\34MOVDIR64B\0" "b\35ENQCMD\0" "b\36SGXLC\0" "b\37PKS\0" /* %ecx = 0, %edx */ @@ -1021,7 +1021,7 @@ #define CPUID_AMD_ENCMEM_SEVES __BIT(3) /* SEV Encrypted State */ #define CPUID_AMD_ENCMEM_SEV_SNP __BIT(4) /* Secure Nested Paging */ #define CPUID_AMD_ENCMEM_VMPL __BIT(5) /* Virtual Machine Privilege Lvl */ -#define CPUID_AMD_ENCMEM_RPMQUERY __BIT(6) /* RMPQUERY instruction */ +#define CPUID_AMD_ENCMEM_RMPQUERY __BIT(6) /* RMPQUERY instruction */ #define CPUID_AMD_ENCMEM_VMPLSSS __BIT(7) /* VMPL Secure Shadow Stack */ #define CPUID_AMD_ENCMEM_SECTSC __BIT(8) /* Secure TSC */ #define CPUID_AMD_ENCMEM_TSCAUX_V __BIT(9) /* TSC AUX Virtualization */ @@ -1362,6 +1362,10 @@ #define NB_CFG_DISDATMSK 0x0000001000000000ULL #define NB_CFG_INITAPICCPUIDLO (1ULL << 54) +/* AMD Errata 1474. */ +#define MSR_CC6_CFG 0xc0010296 +#define CC6_CFG_DISABLE_BITS (__BIT(22) | __BIT(14) | __BIT(6)) + #define MSR_LS_CFG 0xc0011020 #define LS_CFG_ERRATA_1033 __BIT(4) #define LS_CFG_ERRATA_793 __BIT(15) Index: src/sys/arch/x86/x86/errata.c diff -u src/sys/arch/x86/x86/errata.c:1.27.4.2 src/sys/arch/x86/x86/errata.c:1.27.4.3 --- src/sys/arch/x86/x86/errata.c:1.27.4.2 Thu Jul 27 16:39:40 2023 +++ src/sys/arch/x86/x86/errata.c Thu Oct 3 12:00:57 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: errata.c,v 1.27.4.2 2023/07/27 16:39:40 martin Exp $ */ +/* $NetBSD: errata.c,v 1.27.4.3 2024/10/03 12:00:57 martin Exp $ */ /*- * Copyright (c) 2007 The NetBSD Foundation, Inc. @@ -41,14 +41,19 @@ * AMD Opteron Processors, Publication #25759, Revision: 3.69, * Issue Date: September 2006 * + * https://www.amd.com/system/files/TechDocs/25759.pdf + * * XXX This should perhaps be integrated with the identcpu code. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: errata.c,v 1.27.4.2 2023/07/27 16:39:40 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: errata.c,v 1.27.4.3 2024/10/03 12:00:57 martin Exp $"); -#include <sys/types.h> +#include <sys/param.h> #include <sys/systm.h> +#include <sys/xcall.h> +#include <sys/kthread.h> +#include <sys/clock.h> #include <machine/cpu.h> #include <machine/cpufunc.h> @@ -64,42 +69,121 @@ typedef struct errata { const uint8_t *e_set; bool (*e_act)(struct cpu_info *, struct errata *); uint64_t e_data2; + const char *e_name; /* use if e_num == 0 */ } errata_t; +/* These names match names from various AMD Errata/Revision Guides. */ typedef enum cpurev { + /* K8 / Family 0Fh */ BH_E4, CH_CG, CH_D0, DH_CG, DH_D0, DH_E3, DH_E6, JH_E1, JH_E6, SH_B0, SH_B3, SH_C0, SH_CG, SH_D0, SH_E4, SH_E5, + + /* K10 / Family 10h */ DR_BA, DR_B2, DR_B3, RB_C2, RB_C3, BL_C2, BL_C3, DA_C2, - DA_C3, HY_D0, HY_D1, HY_D1_G34R1, PH_E0, LN_B0, KB_A1, - ML_A1, ZP_B1, ZP_B2, PiR_B2, Rome_B0, Z2_XB, Z2_Ren, - Z2_Luc, Z2_Mat, Z2_VG, Z2_Men, Milan_B1, Milan_B2, Genoa_B1, + DA_C3, HY_D0, HY_D1, HY_D1_G34R1, PH_E0, + + /* Llano / Family 12h */ + LN_B0, + + /* Jaguar / Family 16h */ + KB_A1, ML_A1, + + /* Zen/Zen+/Zen2 / Family 17h */ + ZP_B1, ZP_B2, PiR_B2, Rome_B0, + + /* XXX client Zen2 names aren't known yet. */ + Z2_XB, Z2_Ren, Z2_Luc, Z2_Mat, Z2_VG, Z2_Men, + + /* Zen3/Zen4 / Family 19h */ + Milan_B1, Milan_B2, Genoa_B1, OINK } cpurev_t; -/* These names match names from various AMD Errata/Revision Guides. */ +/* + * The bit-layout in the 0x80000001 CPUID result is, with bit-size + * as the final number here: + * + * resv1_4 extfam_8 extmodel_4 resv2_4 fam_4 model_4 stepping_4 + * + * The CPUREV(family,model,stepping) macro handles the mapping for + * family 6 and family 15 in the "fam_4" nybble, if 6 or 15, the + * extended model is present and is bit-concatenated, and if 15, + * the extended family is additional (ie, family 0x10 is 0xF in + * fam_4 and 0x01 in extfam_8.) + */ +#define CPUREV(fam,mod,step) \ + (((fam) > 0xf ? \ + (0xf << 8) | ((fam) - 0xf) << 20 : \ + (fam) << 8) | \ + (((mod) & 0xf) << 4) | \ + (((fam) == 6 || ((fam) >= 0xf)) ? \ + ((mod) & 0xf0) << 12 : 0) | \ + ((step) & 0xf)) static const u_int cpurevs[] = { - BH_E4, 0x0020fb1, CH_CG, 0x0000f82, CH_CG, 0x0000fb2, - CH_D0, 0x0010f80, CH_D0, 0x0010fb0, DH_CG, 0x0000fc0, - DH_CG, 0x0000fe0, DH_CG, 0x0000ff0, DH_D0, 0x0010fc0, - DH_D0, 0x0010ff0, DH_E3, 0x0020fc0, DH_E3, 0x0020ff0, - DH_E6, 0x0020fc2, DH_E6, 0x0020ff2, JH_E1, 0x0020f10, - JH_E6, 0x0020f12, JH_E6, 0x0020f32, SH_B0, 0x0000f40, - SH_B3, 0x0000f51, SH_C0, 0x0000f48, SH_C0, 0x0000f58, - SH_CG, 0x0000f4a, SH_CG, 0x0000f5a, SH_CG, 0x0000f7a, - SH_D0, 0x0010f40, SH_D0, 0x0010f50, SH_D0, 0x0010f70, - SH_E4, 0x0020f51, SH_E4, 0x0020f71, SH_E5, 0x0020f42, - DR_BA, 0x0100f2a, DR_B2, 0x0100f22, DR_B3, 0x0100f23, - RB_C2, 0x0100f42, RB_C3, 0x0100f43, BL_C2, 0x0100f52, - BL_C3, 0x0100f53, DA_C2, 0x0100f62, DA_C3, 0x0100f63, - HY_D0, 0x0100f80, HY_D1, 0x0100f81, HY_D1_G34R1, 0x0100f91, - PH_E0, 0x0100fa0, LN_B0, 0x0300f10, KB_A1, 0x0700F01, - ML_A1, 0x0730F01, ZP_B1, 0x0800F11, ZP_B2, 0x0800F12, - PiR_B2, 0x0800F82, Rome_B0, 0x0830F10, - /* XXX client Zen2 names aren't known yet. */ - Z2_XB, 0x0840F70, Z2_Ren, 0x0860F01, Z2_Luc, 0x0860F81, - Z2_Mat, 0x0870F10, Z2_VG, 0x0890F02, Z2_Men, 0x08A0F00, - Milan_B1, 0x0A00F11, Milan_B2, 0x0A00F12, - Genoa_B1, 0x0A10F11, + BH_E4, CPUREV(0x0F, 0x2B, 0x1), + CH_CG, CPUREV(0x0F, 0x08, 0x2), + CH_CG, CPUREV(0x0F, 0x0B, 0x2), + CH_D0, CPUREV(0x0F, 0x18, 0x0), + CH_D0, CPUREV(0x0F, 0x1B, 0x0), + DH_CG, CPUREV(0x0F, 0x0C, 0x0), + DH_CG, CPUREV(0x0F, 0x0E, 0x0), + DH_CG, CPUREV(0x0F, 0x0F, 0x0), + DH_D0, CPUREV(0x0F, 0x1C, 0x0), + DH_D0, CPUREV(0x0F, 0x1F, 0x0), + DH_E3, CPUREV(0x0F, 0x2C, 0x0), + DH_E3, CPUREV(0x0F, 0x2F, 0x0), + DH_E6, CPUREV(0x0F, 0x2C, 0x2), + DH_E6, CPUREV(0x0F, 0x2F, 0x2), + JH_E1, CPUREV(0x0F, 0x21, 0x0), + JH_E6, CPUREV(0x0F, 0x21, 0x2), + JH_E6, CPUREV(0x0F, 0x23, 0x2), + SH_B0, CPUREV(0x0F, 0x04, 0x0), + SH_B3, CPUREV(0x0F, 0x05, 0x1), + SH_C0, CPUREV(0x0F, 0x04, 0x8), + SH_C0, CPUREV(0x0F, 0x05, 0x8), + SH_CG, CPUREV(0x0F, 0x04, 0xA), + SH_CG, CPUREV(0x0F, 0x05, 0xA), + SH_CG, CPUREV(0x0F, 0x07, 0xA), + SH_D0, CPUREV(0x0F, 0x14, 0x0), + SH_D0, CPUREV(0x0F, 0x15, 0x0), + SH_D0, CPUREV(0x0F, 0x17, 0x0), + SH_E4, CPUREV(0x0F, 0x25, 0x1), + SH_E4, CPUREV(0x0F, 0x27, 0x1), + SH_E5, CPUREV(0x0F, 0x24, 0x2), + + DR_BA, CPUREV(0x10, 0x02, 0xA), + DR_B2, CPUREV(0x10, 0x02, 0x2), + DR_B3, CPUREV(0x10, 0x02, 0x3), + RB_C2, CPUREV(0x10, 0x04, 0x2), + RB_C3, CPUREV(0x10, 0x04, 0x3), + BL_C2, CPUREV(0x10, 0x05, 0x2), + BL_C3, CPUREV(0x10, 0x05, 0x3), + DA_C2, CPUREV(0x10, 0x06, 0x2), + DA_C3, CPUREV(0x10, 0x06, 0x3), + HY_D0, CPUREV(0x10, 0x08, 0x0), + HY_D1, CPUREV(0x10, 0x08, 0x1), + HY_D1_G34R1, CPUREV(0x10, 0x09, 0x1), + PH_E0, CPUREV(0x10, 0x0A, 0x0), + + LN_B0, CPUREV(0x12, 0x01, 0x0), + + KB_A1, CPUREV(0x16, 0x00, 0x1), + ML_A1, CPUREV(0x16, 0x30, 0x1), + + ZP_B1, CPUREV(0x17, 0x01, 0x1), + ZP_B2, CPUREV(0x17, 0x01, 0x2), + PiR_B2, CPUREV(0x17, 0x08, 0x2), + Rome_B0, CPUREV(0x17, 0x31, 0x0), + Z2_XB, CPUREV(0x17, 0x47, 0x0), + Z2_Ren, CPUREV(0x17, 0x60, 0x1), + Z2_Luc, CPUREV(0x17, 0x68, 0x1), + Z2_Mat, CPUREV(0x17, 0x71, 0x0), + Z2_VG, CPUREV(0x17, 0x90, 0x2), + Z2_Men, CPUREV(0x17, 0xA0, 0x0), + + Milan_B1, CPUREV(0x19, 0x01, 0x1), + Milan_B2, CPUREV(0x19, 0x01, 0x2), + Genoa_B1, CPUREV(0x19, 0x11, 0x1), OINK }; @@ -168,12 +252,13 @@ static const uint8_t x86_errata_set15[] KB_A1, ML_A1, OINK }; -static const uint8_t x86_errata_set16[] = { +static const uint8_t x86_errata_zen2[] = { Rome_B0, Z2_XB, Z2_Ren, Z2_Luc, Z2_Mat, Z2_VG, Z2_Men, OINK }; static bool x86_errata_setmsr(struct cpu_info *, errata_t *); static bool x86_errata_testmsr(struct cpu_info *, errata_t *); +static bool x86_errata_amd_1474(struct cpu_info *, errata_t *); static errata_t errata[] = { /* @@ -182,21 +267,21 @@ static errata_t errata[] = { */ { 81, FALSE, MSR_DC_CFG, x86_errata_set5, - x86_errata_testmsr, DC_CFG_DIS_SMC_CHK_BUF + x86_errata_testmsr, DC_CFG_DIS_SMC_CHK_BUF, NULL }, /* * 86: DRAM Data Masking Feature Can Cause ECC Failures */ { 86, FALSE, MSR_NB_CFG, x86_errata_set1, - x86_errata_testmsr, NB_CFG_DISDATMSK + x86_errata_testmsr, NB_CFG_DISDATMSK, NULL }, /* * 89: Potential Deadlock With Locked Transactions */ { 89, FALSE, MSR_NB_CFG, x86_errata_set8, - x86_errata_testmsr, NB_CFG_DISIOREQLOCK + x86_errata_testmsr, NB_CFG_DISIOREQLOCK, NULL }, /* * 94: Sequential Prefetch Feature May Cause Incorrect @@ -204,7 +289,7 @@ static errata_t errata[] = { */ { 94, FALSE, MSR_IC_CFG, x86_errata_set1, - x86_errata_testmsr, IC_CFG_DIS_SEQ_PREFETCH + x86_errata_testmsr, IC_CFG_DIS_SEQ_PREFETCH, NULL }, /* * 97: 128-Bit Streaming Stores May Cause Coherency @@ -216,7 +301,7 @@ static errata_t errata[] = { */ { 97, FALSE, MSR_DC_CFG, x86_errata_set6, - x86_errata_testmsr, DC_CFG_DIS_CNV_WC_SSO + x86_errata_testmsr, DC_CFG_DIS_CNV_WC_SSO, NULL }, /* * 104: DRAM Data Masking Feature Causes ChipKill ECC @@ -224,14 +309,14 @@ static errata_t errata[] = { */ { 104, FALSE, MSR_NB_CFG, x86_errata_set7, - x86_errata_testmsr, NB_CFG_DISDATMSK + x86_errata_testmsr, NB_CFG_DISDATMSK, NULL }, /* * 113: Enhanced Write-Combining Feature Causes System Hang */ { 113, FALSE, MSR_BU_CFG, x86_errata_set3, - x86_errata_setmsr, BU_CFG_WBENHWSBDIS + x86_errata_setmsr, BU_CFG_WBENHWSBDIS, NULL }, /* * 69: Multiprocessor Coherency Problem with Hardware @@ -239,7 +324,7 @@ static errata_t errata[] = { */ { 69, FALSE, MSR_BU_CFG, x86_errata_set5, - x86_errata_setmsr, BU_CFG_WBPFSMCCHKDIS + x86_errata_setmsr, BU_CFG_WBPFSMCCHKDIS, NULL }, /* * 101: DRAM Scrubber May Cause Data Corruption When Using @@ -247,7 +332,7 @@ static errata_t errata[] = { */ { 101, FALSE, 0, x86_errata_set2, - NULL, 0 + NULL, 0, NULL }, /* * 106: Potential Deadlock with Tightly Coupled Semaphores @@ -255,7 +340,7 @@ static errata_t errata[] = { */ { 106, FALSE, MSR_LS_CFG, x86_errata_set2, - x86_errata_testmsr, LS_CFG_DIS_LS2_SQUISH + x86_errata_testmsr, LS_CFG_DIS_LS2_SQUISH, NULL }, /* * 107: Possible Multiprocessor Coherency Problem with @@ -263,7 +348,7 @@ static errata_t errata[] = { */ { 107, FALSE, MSR_BU_CFG, x86_errata_set2, - x86_errata_testmsr, BU_CFG_THRL2IDXCMPDIS + x86_errata_testmsr, BU_CFG_THRL2IDXCMPDIS, NULL }, /* * 122: TLB Flush Filter May Cause Coherency Problem in @@ -271,14 +356,14 @@ static errata_t errata[] = { */ { 122, FALSE, MSR_HWCR, x86_errata_set4, - x86_errata_setmsr, HWCR_FFDIS + x86_errata_setmsr, HWCR_FFDIS, NULL }, /* * 254: Internal Resource Livelock Involving Cached TLB Reload */ { 254, FALSE, MSR_BU_CFG, x86_errata_set9, - x86_errata_testmsr, BU_CFG_ERRATA_254 + x86_errata_testmsr, BU_CFG_ERRATA_254, NULL }, /* * 261: Processor May Stall Entering Stop-Grant Due to Pending Data @@ -286,7 +371,7 @@ static errata_t errata[] = { */ { 261, FALSE, MSR_DC_CFG, x86_errata_set10, - x86_errata_testmsr, DC_CFG_ERRATA_261 + x86_errata_testmsr, DC_CFG_ERRATA_261, NULL }, /* * 298: L2 Eviction May Occur During Processor Operation To Set @@ -294,11 +379,11 @@ static errata_t errata[] = { */ { 298, FALSE, MSR_HWCR, x86_errata_set9, - x86_errata_testmsr, HWCR_TLBCACHEDIS + x86_errata_testmsr, HWCR_TLBCACHEDIS, NULL }, { 298, FALSE, MSR_BU_CFG, x86_errata_set9, - x86_errata_testmsr, BU_CFG_ERRATA_298 + x86_errata_testmsr, BU_CFG_ERRATA_298, NULL }, /* * 309: Processor Core May Execute Incorrect Instructions on @@ -306,14 +391,14 @@ static errata_t errata[] = { */ { 309, FALSE, MSR_BU_CFG, x86_errata_set9, - x86_errata_testmsr, BU_CFG_ERRATA_309 + x86_errata_testmsr, BU_CFG_ERRATA_309, NULL }, /* * 721: Processor May Incorrectly Update Stack Pointer */ { 721, FALSE, MSR_DE_CFG, x86_errata_set11, - x86_errata_setmsr, DE_CFG_ERRATA_721 + x86_errata_setmsr, DE_CFG_ERRATA_721, NULL }, /* * 776: Incorrect Processor Branch Prediction for Two Consecutive @@ -321,7 +406,7 @@ static errata_t errata[] = { */ { 776, FALSE, MSR_IC_CFG, x86_errata_set12, - x86_errata_setmsr, IC_CFG_ERRATA_776 + x86_errata_setmsr, IC_CFG_ERRATA_776, NULL }, /* * 793: Specific Combination of Writes to Write Combined Memory @@ -329,7 +414,7 @@ static errata_t errata[] = { */ { 793, FALSE, MSR_LS_CFG, x86_errata_set15, - x86_errata_setmsr, LS_CFG_ERRATA_793 + x86_errata_setmsr, LS_CFG_ERRATA_793, NULL }, /* * 1021: Load Operation May Receive Stale Data From Older Store @@ -337,21 +422,21 @@ static errata_t errata[] = { */ { 1021, FALSE, MSR_DE_CFG, x86_errata_set13, - x86_errata_setmsr, DE_CFG_ERRATA_1021 + x86_errata_setmsr, DE_CFG_ERRATA_1021, NULL }, /* * 1033: A Lock Operation May Cause the System to Hang */ { 1033, FALSE, MSR_LS_CFG, x86_errata_set14, - x86_errata_setmsr, LS_CFG_ERRATA_1033 + x86_errata_setmsr, LS_CFG_ERRATA_1033, NULL }, /* * 1049: FCMOV Instruction May Not Execute Correctly */ { 1049, FALSE, MSR_FP_CFG, x86_errata_set13, - x86_errata_setmsr, FP_CFG_ERRATA_1049 + x86_errata_setmsr, FP_CFG_ERRATA_1049, NULL }, #if 0 /* Should we apply this errata? The other OSes don't. */ /* @@ -360,7 +445,7 @@ static errata_t errata[] = { */ { 1091, FALSE, MSR_LS_CFG2, x86_errata_set13, - x86_errata_setmsr, LS_CFG2_ERRATA_1091 + x86_errata_setmsr, LS_CFG2_ERRATA_1091, NULL }, #endif /* @@ -369,7 +454,14 @@ static errata_t errata[] = { */ { 1095, FALSE, MSR_LS_CFG, x86_errata_set13, - x86_errata_setmsr, LS_CFG_ERRATA_1095 + x86_errata_setmsr, LS_CFG_ERRATA_1095, NULL + }, + /* + * 1474: A CPU core may hang after about 1044 days + */ + { + 1474, FALSE, MSR_CC6_CFG, x86_errata_zen2, + x86_errata_amd_1474, CC6_CFG_DISABLE_BITS, NULL }, /* * Zenbleed: @@ -378,11 +470,112 @@ static errata_t errata[] = { * https://lock.cmpxchg8b.com/zenbleed.html */ { - -1, FALSE, MSR_DE_CFG, x86_errata_set16, + 0, FALSE, MSR_DE_CFG, x86_errata_zen2, x86_errata_setmsr, DE_CFG_ERRATA_ZENBLEED, + "ZenBleed" }, }; +/* + * 1474: A CPU core may hang after about 1044 days + * + * This requires disabling CC6 power level, which can be a performance + * issue since it stops full turbo in some implementations (eg, half the + * cores must be in CC6 to achieve the highest boost level.) Set a timer + * to fire in 1000 days -- except NetBSD timers end up having a signed + * 32-bit hz-based value, which rolls over in under 25 days with HZ=1000, + * and doing xcall(9) or kthread(9) from a callout is not allowed anyway, + * so just have a kthread wait 1 day for 1000 times. + */ + +#define AMD_ERRATA_1474_WARN_DAYS 950 +#define AMD_ERRATA_1474_BAD_DAYS 1000 + +static void +amd_errata_1474_disable_cc6(void *a1, void *a2) +{ + errata_t *e = a1; + uint64_t val; + + val = rdmsr_locked(e->e_data1); + if ((val & e->e_data2) == 0) + return; + wrmsr_locked(e->e_data1, val & ~e->e_data2); + aprint_debug_dev(curcpu()->ci_dev, "erratum %u patched\n", + e->e_num); +} + +static void +amd_errata_1474_thread(void *arg) +{ + int loops = 0; + int ticks; + + ticks = hz * SECS_PER_DAY; +#ifdef X86_ERRATA_TEST_AMD_1474 + /* + * Make this trigger warning after 50 seconds, and workaround + * at 100 seconds, for easy testing. + */ + ticks = hz; + loops = 900; +#endif + + while (loops++ < AMD_ERRATA_1474_BAD_DAYS) { + if (loops == AMD_ERRATA_1474_WARN_DAYS) { + printf("warning: AMD Errata 1474 workaround scheduled " + "for %u days.\n", AMD_ERRATA_1474_BAD_DAYS - + AMD_ERRATA_1474_WARN_DAYS); + printf("warning: reboot required to avoid.\n"); + } + kpause("amd1474", false, ticks, NULL); + } + + /* Been 1000 days, disable CC6 and warn about it. */ + uint64_t xc = xc_broadcast(0, amd_errata_1474_disable_cc6, arg, NULL); + xc_wait(xc); + + printf("warning: AMD CC6 disabled due to errata 1474.\n"); + printf("warning: reboot required to restore full turbo speeds.\n"); + + kthread_exit(0); +} + +static bool +x86_errata_amd_1474(struct cpu_info *ci, errata_t *e) +{ + int error; + + /* Don't do anything on non-primary CPUs. */ + if (!CPU_IS_PRIMARY(ci)) + return FALSE; + + error = kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, + amd_errata_1474_thread, e, NULL, "amd1474"); + if (error) { + printf("WARNING: Unable to disable AMD errata 1474!\n"); + printf("WARNING: reboot system after %u days to avoid CPU " + "hangs.\n", AMD_ERRATA_1474_BAD_DAYS); + } else { + aprint_debug_dev(ci->ci_dev, "workaround for erratum %u " + "scheduled for %u days\n", e->e_num, + AMD_ERRATA_1474_BAD_DAYS); + } + + /* Do own warning here, it's not like most others. */ + return FALSE; +} + +static void +x86_errata_log(device_t dev, errata_t *e, const char *msg) +{ + + if (e->e_num == 0) + aprint_debug_dev(dev, "erratum '%s' %s\n", e->e_name, msg); + else + aprint_debug_dev(dev, "erratum %u %s\n", e->e_num, msg); +} + static bool x86_errata_testmsr(struct cpu_info *ci, errata_t *e) { @@ -409,8 +602,7 @@ x86_errata_setmsr(struct cpu_info *ci, e if ((val & e->e_data2) != 0) return FALSE; wrmsr_locked(e->e_data1, val | e->e_data2); - aprint_debug_dev(ci->ci_dev, "erratum %d patched\n", - e->e_num); + x86_errata_log(ci->ci_dev, e, "patched"); return FALSE; } @@ -436,6 +628,11 @@ x86_errata(void) ci = curcpu(); x86_cpuid(0x80000001, descs); + if (CPU_IS_PRIMARY(ci)) { + aprint_verbose_dev(ci->ci_dev, + "searching errata for cpu revision 0x%08"PRIx32"\n", + descs[0]); + } for (i = 0;; i += 2) { if ((rev = cpurevs[i]) == OINK) @@ -456,16 +653,14 @@ x86_errata(void) continue; } - aprint_debug_dev(ci->ci_dev, "testing for erratum %d\n", - e->e_num); + x86_errata_log(ci->ci_dev, e, "testing"); if (e->e_act == NULL) e->e_reported = TRUE; else if ((*e->e_act)(ci, e) == FALSE) continue; - aprint_verbose_dev(ci->ci_dev, "erratum %d present\n", - e->e_num); + x86_errata_log(ci->ci_dev, e, "present"); upgrade = 1; } Index: src/usr.sbin/cpuctl/arch/i386.c diff -u src/usr.sbin/cpuctl/arch/i386.c:1.133.2.3 src/usr.sbin/cpuctl/arch/i386.c:1.133.2.4 --- src/usr.sbin/cpuctl/arch/i386.c:1.133.2.3 Sat Jul 29 10:07:59 2023 +++ src/usr.sbin/cpuctl/arch/i386.c Thu Oct 3 12:00:57 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: i386.c,v 1.133.2.3 2023/07/29 10:07:59 martin Exp $ */ +/* $NetBSD: i386.c,v 1.133.2.4 2024/10/03 12:00:57 martin Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -57,7 +57,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: i386.c,v 1.133.2.3 2023/07/29 10:07:59 martin Exp $"); +__RCSID("$NetBSD: i386.c,v 1.133.2.4 2024/10/03 12:00:57 martin Exp $"); #endif /* not lint */ #include <sys/types.h> @@ -1726,6 +1726,13 @@ print_bits(const char *cpuname, const ch bp += strlen(bp) + 1; } } +#ifdef lint +#define print_bits(cpuname, hdr, fmt, val) \ + do { \ + print_bits(cpuname, hdr, fmt, val); \ + snprintb(NULL, 0, fmt, val); \ + } while (0) +#endif static void dump_descs(uint32_t leafstart, uint32_t leafend, const char *cpuname,