From 73556a19205d4a9cd2dd98688edbc6d76f6caff3 Mon Sep 17 00:00:00 2001 From: guenther Date: Sat, 11 May 2024 19:21:47 +0000 Subject: [PATCH] Use %b to format cpu flag info in dmesg, so we have the raw values too. This is also much more space efficient. Reduce the cpu flag noise in dmesg by suppressing lines and registers that are identical with the previous CPU and show -/+ info if there are any differences. particular feedback from deraadt@, kettenis@, jsg@, and dv@ ok deraadt@ --- sys/arch/amd64/amd64/identcpu.c | 541 ++++++++++++---------------- sys/arch/amd64/include/specialreg.h | 60 ++- 2 files changed, 297 insertions(+), 304 deletions(-) diff --git a/sys/arch/amd64/amd64/identcpu.c b/sys/arch/amd64/amd64/identcpu.c index 9d8fefa6305..841dd899354 100644 --- a/sys/arch/amd64/amd64/identcpu.c +++ b/sys/arch/amd64/amd64/identcpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: identcpu.c,v 1.140 2024/04/03 02:01:21 guenther Exp $ */ +/* $OpenBSD: identcpu.c,v 1.141 2024/05/11 19:21:47 guenther Exp $ */ /* $NetBSD: identcpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */ /* @@ -73,211 +73,6 @@ int amd64_has_aesni; int has_rdrand; int has_rdseed; -const struct { - u_int32_t bit; - char str[12]; -} cpu_cpuid_features[] = { - { CPUID_FPU, "FPU" }, - { CPUID_VME, "VME" }, - { CPUID_DE, "DE" }, - { CPUID_PSE, "PSE" }, - { CPUID_TSC, "TSC" }, - { CPUID_MSR, "MSR" }, - { CPUID_PAE, "PAE" }, - { CPUID_MCE, "MCE" }, - { CPUID_CX8, "CX8" }, - { CPUID_APIC, "APIC" }, - { CPUID_SEP, "SEP" }, - { CPUID_MTRR, "MTRR" }, - { CPUID_PGE, "PGE" }, - { CPUID_MCA, "MCA" }, - { CPUID_CMOV, "CMOV" }, - { CPUID_PAT, "PAT" }, - { CPUID_PSE36, "PSE36" }, - { CPUID_PSN, "PSN" }, - { CPUID_CFLUSH, "CFLUSH" }, - { CPUID_DS, "DS" }, - { CPUID_ACPI, "ACPI" }, - { CPUID_MMX, "MMX" }, - { CPUID_FXSR, "FXSR" }, - { CPUID_SSE, "SSE" }, - { CPUID_SSE2, "SSE2" }, - { CPUID_SS, "SS" }, - { CPUID_HTT, "HTT" }, - { CPUID_TM, "TM" }, - { CPUID_PBE, "PBE" } -}, cpu_ecpuid_features[] = { - { CPUID_MPC, "MPC" }, - { CPUID_NXE, "NXE" }, - { CPUID_MMXX, "MMXX" }, - { CPUID_FFXSR, "FFXSR" }, - { CPUID_PAGE1GB, "PAGE1GB" }, - { CPUID_RDTSCP, "RDTSCP" }, - { CPUID_LONG, "LONG" }, - { CPUID_3DNOW2, "3DNOW2" }, - { CPUID_3DNOW, "3DNOW" } -}, cpu_cpuid_ecxfeatures[] = { - { CPUIDECX_SSE3, "SSE3" }, - { CPUIDECX_PCLMUL, "PCLMUL" }, - { CPUIDECX_DTES64, "DTES64" }, - { CPUIDECX_MWAIT, "MWAIT" }, - { CPUIDECX_DSCPL, "DS-CPL" }, - { CPUIDECX_VMX, "VMX" }, - { CPUIDECX_SMX, "SMX" }, - { CPUIDECX_EST, "EST" }, - { CPUIDECX_TM2, "TM2" }, - { CPUIDECX_SSSE3, "SSSE3" }, - { CPUIDECX_CNXTID, "CNXT-ID" }, - { CPUIDECX_SDBG, "SDBG" }, - { CPUIDECX_FMA3, "FMA3" }, - { CPUIDECX_CX16, "CX16" }, - { CPUIDECX_XTPR, "xTPR" }, - { CPUIDECX_PDCM, "PDCM" }, - { CPUIDECX_PCID, "PCID" }, - { CPUIDECX_DCA, "DCA" }, - { CPUIDECX_SSE41, "SSE4.1" }, - { CPUIDECX_SSE42, "SSE4.2" }, - { CPUIDECX_X2APIC, "x2APIC" }, - { CPUIDECX_MOVBE, "MOVBE" }, - { CPUIDECX_POPCNT, "POPCNT" }, - { CPUIDECX_DEADLINE, "DEADLINE" }, - { CPUIDECX_AES, "AES" }, - { CPUIDECX_XSAVE, "XSAVE" }, - { CPUIDECX_OSXSAVE, "OSXSAVE" }, - { CPUIDECX_AVX, "AVX" }, - { CPUIDECX_F16C, "F16C" }, - { CPUIDECX_RDRAND, "RDRAND" }, - { CPUIDECX_HV, "HV" }, -}, cpu_ecpuid_ecxfeatures[] = { - { CPUIDECX_LAHF, "LAHF" }, - { CPUIDECX_CMPLEG, "CMPLEG" }, - { CPUIDECX_SVM, "SVM" }, - { CPUIDECX_EAPICSP, "EAPICSP"}, - { CPUIDECX_AMCR8, "AMCR8"}, - { CPUIDECX_ABM, "ABM" }, - { CPUIDECX_SSE4A, "SSE4A" }, - { CPUIDECX_MASSE, "MASSE" }, - { CPUIDECX_3DNOWP, "3DNOWP" }, - { CPUIDECX_OSVW, "OSVW" }, - { CPUIDECX_IBS, "IBS" }, - { CPUIDECX_XOP, "XOP" }, - { CPUIDECX_SKINIT, "SKINIT" }, - { CPUIDECX_LWP, "WDT" }, - { CPUIDECX_FMA4, "FMA4" }, - { CPUIDECX_TCE, "TCE" }, - { CPUIDECX_NODEID, "NODEID" }, - { CPUIDECX_TBM, "TBM" }, - { CPUIDECX_TOPEXT, "TOPEXT" }, - { CPUIDECX_CPCTR, "CPCTR" }, - { CPUIDECX_DBKP, "DBKP" }, - { CPUIDECX_PERFTSC, "PERFTSC" }, - { CPUIDECX_PCTRL3, "PCTRL3" }, - { CPUIDECX_MWAITX, "MWAITX" }, -}, cpu_seff0_ebxfeatures[] = { - { SEFF0EBX_FSGSBASE, "FSGSBASE" }, - { SEFF0EBX_TSC_ADJUST, "TSC_ADJUST" }, - { SEFF0EBX_SGX, "SGX" }, - { SEFF0EBX_BMI1, "BMI1" }, - { SEFF0EBX_HLE, "HLE" }, - { SEFF0EBX_AVX2, "AVX2" }, - { SEFF0EBX_SMEP, "SMEP" }, - { SEFF0EBX_BMI2, "BMI2" }, - { SEFF0EBX_ERMS, "ERMS" }, - { SEFF0EBX_INVPCID, "INVPCID" }, - { SEFF0EBX_RTM, "RTM" }, - { SEFF0EBX_PQM, "PQM" }, - { SEFF0EBX_MPX, "MPX" }, - { SEFF0EBX_AVX512F, "AVX512F" }, - { SEFF0EBX_AVX512DQ, "AVX512DQ" }, - { SEFF0EBX_RDSEED, "RDSEED" }, - { SEFF0EBX_ADX, "ADX" }, - { SEFF0EBX_SMAP, "SMAP" }, - { SEFF0EBX_AVX512IFMA, "AVX512IFMA" }, - { SEFF0EBX_PCOMMIT, "PCOMMIT" }, - { SEFF0EBX_CLFLUSHOPT, "CLFLUSHOPT" }, - { SEFF0EBX_CLWB, "CLWB" }, - { SEFF0EBX_PT, "PT" }, - { SEFF0EBX_AVX512PF, "AVX512PF" }, - { SEFF0EBX_AVX512ER, "AVX512ER" }, - { SEFF0EBX_AVX512CD, "AVX512CD" }, - { SEFF0EBX_SHA, "SHA" }, - { SEFF0EBX_AVX512BW, "AVX512BW" }, - { SEFF0EBX_AVX512VL, "AVX512VL" }, -}, cpu_seff0_ecxfeatures[] = { - { SEFF0ECX_PREFETCHWT1, "PREFETCHWT1" }, - { SEFF0ECX_AVX512VBMI, "AVX512VBMI" }, - { SEFF0ECX_UMIP, "UMIP" }, - { SEFF0ECX_PKU, "PKU" }, - { SEFF0ECX_WAITPKG, "WAITPKG" }, - { SEFF0ECX_PKS, "PKS" }, -}, cpu_seff0_edxfeatures[] = { - { SEFF0EDX_AVX512_4FNNIW, "AVX512FNNIW" }, - { SEFF0EDX_AVX512_4FMAPS, "AVX512FMAPS" }, - { SEFF0EDX_SRBDS_CTRL, "SRBDS_CTRL" }, - { SEFF0EDX_MD_CLEAR, "MD_CLEAR" }, - { SEFF0EDX_TSXFA, "TSXFA" }, - { SEFF0EDX_IBT, "IBT" }, - { SEFF0EDX_IBRS, "IBRS,IBPB" }, - { SEFF0EDX_STIBP, "STIBP" }, - { SEFF0EDX_L1DF, "L1DF" }, - /* SEFF0EDX_ARCH_CAP (not printed) */ - { SEFF0EDX_SSBD, "SSBD" }, -}, cpu_tpm_eaxfeatures[] = { - { TPM_SENSOR, "SENSOR" }, - { TPM_ARAT, "ARAT" }, -}, cpu_cpuid_perf_eax[] = { - { CPUIDEAX_VERID, "PERF" }, -}, cpu_cpuid_apmi_edx[] = { - { CPUIDEDX_HWPSTATE, "HWPSTATE" }, - { CPUIDEDX_ITSC, "ITSC" }, -}, cpu_amdspec_ebxfeatures[] = { - { CPUIDEBX_INVLPGB, "INVLPGB" }, - { CPUIDEBX_IBPB, "IBPB" }, - { CPUIDEBX_IBRS, "IBRS" }, - { CPUIDEBX_STIBP, "STIBP" }, - { CPUIDEBX_IBRS_ALWAYSON, "IBRS_ALL" }, - { CPUIDEBX_STIBP_ALWAYSON, "STIBP_ALL" }, - { CPUIDEBX_IBRS_PREF, "IBRS_PREF" }, - { CPUIDEBX_IBRS_SAME_MODE, "IBRS_SM" }, - { CPUIDEBX_SSBD, "SSBD" }, - { CPUIDEBX_VIRT_SSBD, "VIRTSSBD" }, - { CPUIDEBX_SSBD_NOTREQ, "SSBDNR" }, -}, cpu_xsave_extfeatures[] = { - { XSAVE_XSAVEOPT, "XSAVEOPT" }, - { XSAVE_XSAVEC, "XSAVEC" }, - { XSAVE_XGETBV1, "XGETBV1" }, - { XSAVE_XSAVES, "XSAVES" }, - { XSAVE_XFD, "XFD" }, -}, cpu_arch_cap_features[] = { - /* ARCH_CAP_RDCL_NO (not printed) == !MELTDOWN */ - { ARCH_CAP_IBRS_ALL, "IBRS_ALL" }, - { ARCH_CAP_RSBA, "RSBA" }, - { ARCH_CAP_SKIP_L1DFL_VMENTRY, "SKIP_L1DFL" }, - { ARCH_CAP_SSB_NO, "SSB_NO" }, - { ARCH_CAP_MDS_NO, "MDS_NO" }, - { ARCH_CAP_IF_PSCHANGE_MC_NO, "IF_PSCHANGE" }, - { ARCH_CAP_TSX_CTRL, "TSX_CTRL" }, - { ARCH_CAP_TAA_NO, "TAA_NO" }, - { ARCH_CAP_MCU_CONTROL, "MCU_CONTROL" }, - { ARCH_CAP_MISC_PACKAGE_CTLS, "MISC_PKG_CT" }, - { ARCH_CAP_ENERGY_FILTERING_CTL, "ENERGY_FILT" }, - { ARCH_CAP_DOITM, "DOITM" }, - { ARCH_CAP_SBDR_SSDP_NO, "SBDR_SSDP_N" }, - { ARCH_CAP_FBSDP_NO, "FBSDP_NO" }, - { ARCH_CAP_PSDP_NO, "PSDP_NO" }, - { ARCH_CAP_FB_CLEAR, "FB_CLEAR" }, - { ARCH_CAP_FB_CLEAR_CTRL, "FB_CLEAR_CT" }, - { ARCH_CAP_RRSBA, "RRSBA" }, - { ARCH_CAP_BHI_NO, "BHI_NO" }, - { ARCH_CAP_XAPIC_DISABLE_STATUS, "XAPIC_DIS" }, - { ARCH_CAP_OVERCLOCKING_STATUS, "OVERCLOCK" }, - { ARCH_CAP_PBRSB_NO, "PBRSB_NO" }, - { ARCH_CAP_GDS_CTRL, "GDS_CTRL" }, - { ARCH_CAP_GDS_NO, "GDS_NO" }, - { ARCH_CAP_RFDS_NO, "RFDS_NO" }, - { ARCH_CAP_RFDS_CLEAR, "RFDS_CLEAR" }, -}; - int cpu_amd64speed(int *freq) { @@ -545,28 +340,197 @@ cpu_freq(struct cpu_info *ci) return ((count - last_count) * 10); } +/* print flags from one cpuid for cpu0 */ +static inline void +pcpu0id3(const char *id, char reg1, uint32_t val1, const char *bits1, + char reg2, uint32_t val2, const char *bits2, + char reg3, uint32_t val3, const char *bits3) +{ + if (val1 || val2 || val3) { + printf("\ncpu0: cpuid %s", id); + if (val1) + printf(" e%cx=%b", reg1, val1, bits1); + if (val2) + printf(" e%cx=%b", reg2, val2, bits2); + if (val3) + printf(" e%cx=%b", reg3, val3, bits3); + } +} + +/* print flags from one, 32-bit MSR for cpu0 */ +static inline void +pmsr032(uint32_t msr, uint32_t value, const char *bits) +{ + if (value) + printf("\ncpu0: msr %x=%b", msr, value, bits); +} + +static void +pbitdiff(uint32_t value, uint32_t base_value, const char *bits) +{ + uint32_t minus; + if (value == base_value) + return; + minus = base_value & ~value; + value &= ~base_value; + if (minus) + printf("-%b", minus, bits); + if (value) + printf("+%b", value, bits); +} + +static inline void +pcpuid(struct cpu_info *ci, const char *id, char reg, uint32_t val, + uint32_t prev_val, const char *bits) +{ + if (CPU_IS_PRIMARY(ci)) + pcpu0id3(id, reg, val, bits, 0, 0, NULL, 0, 0, NULL); + else if (val != prev_val) { + printf("\n%s: cpuid %s e%cx=", ci->ci_dev->dv_xname, id, reg); + pbitdiff(val, prev_val, bits); + } +} + +static inline void +pcpuid2(struct cpu_info *ci, const char *id, + char reg1, uint32_t val1, uint32_t prev_val1, const char *bits1, + char reg2, uint32_t val2, uint32_t prev_val2, const char *bits2) +{ + if (CPU_IS_PRIMARY(ci)) + pcpu0id3(id, reg1, val1, bits1, reg2, val2, bits2, 0, 0, + NULL); + else if (val1 != prev_val1 || val2 != prev_val2) { + printf("\n%s: cpuid %s", ci->ci_dev->dv_xname, id); + if (val1 != prev_val1) { + printf(" e%cx=", reg1); + pbitdiff(val1, prev_val1, bits1); + } + if (val2 != prev_val2) { + printf(" e%cx=", reg2); + pbitdiff(val2, prev_val2, bits2); + } + } +} + +static inline void +pcpuid3(struct cpu_info *ci, const char *id, + char reg1, uint32_t val1, uint32_t prev_val1, const char *bits1, + char reg2, uint32_t val2, uint32_t prev_val2, const char *bits2, + char reg3, uint32_t val3, uint32_t prev_val3, const char *bits3) +{ + if (CPU_IS_PRIMARY(ci)) + pcpu0id3(id, reg1, val1, bits1, reg2, val2, bits2, reg3, val3, + bits3); + else if (val1 != prev_val1 || val2 != prev_val2 || val3 != prev_val3) { + printf("\n%s: cpuid %s", ci->ci_dev->dv_xname, id); + if (val1 != prev_val1) { + printf(" e%cx=", reg1); + pbitdiff(val1, prev_val1, bits1); + } + if (val2 != prev_val2) { + printf(" e%cx=", reg2); + pbitdiff(val2, prev_val2, bits2); + } + if (val3 != prev_val3) { + printf(" e%cx=", reg3); + pbitdiff(val3, prev_val3, bits3); + } + } +} + +static inline void +pmsr32(struct cpu_info *ci, uint32_t msr, uint32_t value, uint32_t prev_value, + const char *bits) +{ + if (CPU_IS_PRIMARY(ci)) + pmsr032(msr, value, bits); + else if (value != prev_value) { + printf("\n%s: msr %x=", ci->ci_dev->dv_xname, msr); + pbitdiff(value, prev_value, bits); + } +} + +#ifdef MULTIPROCESSOR +static uint32_t prevcpu_perf_eax; +static uint32_t prevcpu_perf_edx; +#endif + +static inline void +print_perf_cpuid(struct cpu_info *ci) +{ + uint32_t eax, edx, version; + + if (CPU_IS_PRIMARY(ci)) { + eax = cpu_perf_eax; + edx = cpu_perf_edx; + version = eax & CPUIDEAX_VERID; + if (version == 0) + return; + } +#ifdef MULTIPROCESSOR + else { + uint32_t dummy; + CPUID(0xa, eax, dummy, dummy, edx); + /* if no difference on the bits we care about, say nothing */ + if (((eax ^ prevcpu_perf_eax) & 0x00ffffff) == 0 && + ((edx ^ prevcpu_perf_edx) & 0x00001fff) == 0) + return; + version = eax & CPUIDEAX_VERID; + } + prevcpu_perf_eax = eax; + prevcpu_perf_edx = edx; +#endif + + printf("\n%s: cpuid a vers=%d", ci->ci_dev->dv_xname, version); + if (version) { + printf(", gp=%d, gpwidth=%d", CPUIDEAX_NUM_GC(eax), + CPUIDEAX_BIT_GC(eax)); + if (version > 1) { + printf(", ff=%d, ffwidth=%d", CPUIDEDX_NUM_FC(edx), + CPUIDEDX_BIT_FC(edx)); + } + } +} + void identifycpu(struct cpu_info *ci) { + static uint32_t prevcpu_1_ecx, prevcpu_tpm_ecxflags, prevcpu_d_1_eax; + static uint32_t prevcpu_apmi_edx, prevcpu_arch_capa; + static struct cpu_info *prevci = &cpu_info_primary; +#define CPUID_MEMBER(member) ci->member, prevci->member + uint32_t cflushsz, curcpu_1_ecx, curcpu_apmi_edx = 0; + uint32_t curcpu_tpm_ecxflags = 0, curcpu_d_1_eax = 0; uint64_t freq = 0; - u_int32_t dummy, val, cpu_tpm_ecxflags = 0; + u_int32_t dummy; char mycpu_model[48]; - int i; char *brandstr_from, *brandstr_to; int skipspace; - CPUID(1, ci->ci_signature, val, dummy, ci->ci_feature_flags); CPUID(0x80000000, ci->ci_pnfeatset, dummy, dummy, dummy); - if (ci->ci_pnfeatset >= 0x80000001) { - CPUID(0x80000001, ci->ci_efeature_eax, dummy, - ci->ci_efeature_ecx, ci->ci_feature_eflags); - /* Other bits may clash */ - ci->ci_feature_flags |= (ci->ci_feature_eflags & CPUID_NXE); - if (CPU_IS_PRIMARY(ci)) - ecpu_ecxfeature = ci->ci_efeature_ecx; + CPUID(0x80000001, ci->ci_efeature_eax, dummy, ci->ci_efeature_ecx, + ci->ci_feature_eflags); + + if (CPU_IS_PRIMARY(ci)) { + ci->ci_signature = cpu_id; + ci->ci_feature_flags = cpu_feature & ~CPUID_NXE; + cflushsz = cpu_ebxfeature; + curcpu_1_ecx = cpu_ecxfeature; + ecpu_ecxfeature = ci->ci_efeature_ecx; + curcpu_apmi_edx = cpu_apmi_edx; + } else { + CPUID(1, ci->ci_signature, cflushsz, curcpu_1_ecx, + ci->ci_feature_flags); /* Let cpu_feature be the common bits */ - cpu_feature &= ci->ci_feature_flags; + cpu_feature &= ci->ci_feature_flags | + (ci->ci_feature_eflags & CPUID_NXE); + if (ci->ci_pnfeatset >= 0x80000007) { + CPUID(0x80000007, dummy, dummy, dummy, + curcpu_apmi_edx); + } } + /* cflush cacheline size is equal to bits 15-8 of ebx * 8 */ + ci->ci_cflushsz = ((cflushsz >> 8) & 0xff) * 8; CPUID(0x80000002, ci->ci_brand[0], ci->ci_brand[1], ci->ci_brand[2], ci->ci_brand[3]); @@ -641,6 +605,14 @@ identifycpu(struct cpu_info *ci) freq = cpu_freq(ci); + if (ci->ci_cpuid_level >= 0x07) { + /* "Structured Extended Feature Flags" */ + CPUID_LEAF(0x7, 0, dummy, ci->ci_feature_sefflags_ebx, + ci->ci_feature_sefflags_ecx, ci->ci_feature_sefflags_edx); + /* SEFF0ECX_OSPKE is set late on AP */ + ci->ci_feature_sefflags_ecx &= ~SEFF0ECX_OSPKE; + } + printf("%s: %s", ci->ci_dev->dv_xname, mycpu_model); if (freq != 0) @@ -670,90 +642,62 @@ identifycpu(struct cpu_info *ci) printf(", patch %08llx", level); } - printf("\n%s: ", ci->ci_dev->dv_xname); - - for (i = 0; i < nitems(cpu_cpuid_features); i++) - if (ci->ci_feature_flags & cpu_cpuid_features[i].bit) - printf("%s%s", i? "," : "", cpu_cpuid_features[i].str); - for (i = 0; i < nitems(cpu_cpuid_ecxfeatures); i++) - if (cpu_ecxfeature & cpu_cpuid_ecxfeatures[i].bit) - printf(",%s", cpu_cpuid_ecxfeatures[i].str); - for (i = 0; i < nitems(cpu_ecpuid_features); i++) - if (ci->ci_feature_eflags & cpu_ecpuid_features[i].bit) - printf(",%s", cpu_ecpuid_features[i].str); - for (i = 0; i < nitems(cpu_ecpuid_ecxfeatures); i++) - if (ecpu_ecxfeature & cpu_ecpuid_ecxfeatures[i].bit) - printf(",%s", cpu_ecpuid_ecxfeatures[i].str); - for (i = 0; i < nitems(cpu_cpuid_perf_eax); i++) - if (cpu_perf_eax & cpu_cpuid_perf_eax[i].bit) - printf(",%s", cpu_cpuid_perf_eax[i].str); - for (i = 0; i < nitems(cpu_cpuid_apmi_edx); i++) - if (cpu_apmi_edx & cpu_cpuid_apmi_edx[i].bit) - printf(",%s", cpu_cpuid_apmi_edx[i].str); - - if (ci->ci_cpuid_level >= 0x07) { - /* "Structured Extended Feature Flags" */ - CPUID_LEAF(0x7, 0, dummy, ci->ci_feature_sefflags_ebx, - ci->ci_feature_sefflags_ecx, ci->ci_feature_sefflags_edx); - for (i = 0; i < nitems(cpu_seff0_ebxfeatures); i++) - if (ci->ci_feature_sefflags_ebx & - cpu_seff0_ebxfeatures[i].bit) - printf(",%s", cpu_seff0_ebxfeatures[i].str); - for (i = 0; i < nitems(cpu_seff0_ecxfeatures); i++) - if (ci->ci_feature_sefflags_ecx & - cpu_seff0_ecxfeatures[i].bit) - printf(",%s", cpu_seff0_ecxfeatures[i].str); - for (i = 0; i < nitems(cpu_seff0_edxfeatures); i++) - if (ci->ci_feature_sefflags_edx & - cpu_seff0_edxfeatures[i].bit) - printf(",%s", cpu_seff0_edxfeatures[i].str); - } + if (ci->ci_cpuid_level >= 0x06) + CPUID(0x06, ci->ci_feature_tpmflags, dummy, + curcpu_tpm_ecxflags, dummy); + if (ci->ci_vendor == CPUV_AMD && ci->ci_family >= 0x12) + ci->ci_feature_tpmflags |= TPM_ARAT; - if (ci->ci_vendor == CPUV_INTEL && ci->ci_cpuid_level >= 0x06) { - CPUID(0x06, ci->ci_feature_tpmflags, dummy, cpu_tpm_ecxflags, - dummy); - for (i = 0; i < nitems(cpu_tpm_eaxfeatures); i++) - if (ci->ci_feature_tpmflags & - cpu_tpm_eaxfeatures[i].bit) - printf(",%s", cpu_tpm_eaxfeatures[i].str); - } else if (ci->ci_vendor == CPUV_AMD) { - CPUID(0x06, ci->ci_feature_tpmflags, dummy, cpu_tpm_ecxflags, - dummy); - if (ci->ci_family >= 0x12) - ci->ci_feature_tpmflags |= TPM_ARAT; - } + /* xsave subfeatures */ + if (ci->ci_cpuid_level >= 0xd) + CPUID_LEAF(0xd, 1, curcpu_d_1_eax, dummy, dummy, dummy); + + pcpuid2(ci, "1", 'd', CPUID_MEMBER(ci_feature_flags), CPUID_EDX_BITS, + 'c', curcpu_1_ecx, prevcpu_1_ecx, CPUID_ECX_BITS); + pcpuid2(ci, "6", 'a', CPUID_MEMBER(ci_feature_tpmflags), TPM_EAX_BITS, + 'c', curcpu_tpm_ecxflags, prevcpu_tpm_ecxflags, TPM_ECX_BITS); + pcpuid3(ci, "7.0", + 'b', CPUID_MEMBER(ci_feature_sefflags_ebx), SEFF0_EBX_BITS, + 'c', CPUID_MEMBER(ci_feature_sefflags_ecx), SEFF0_ECX_BITS, + 'd', CPUID_MEMBER(ci_feature_sefflags_edx), SEFF0_EDX_BITS); + print_perf_cpuid(ci); + pcpuid(ci, "d.1", 'a', curcpu_d_1_eax, prevcpu_d_1_eax, XSAVE_BITS); + pcpuid2(ci, "80000001", + 'd', CPUID_MEMBER(ci_feature_eflags), CPUIDE_EDX_BITS, + 'c', CPUID_MEMBER(ci_efeature_ecx), CPUIDE_ECX_BITS); + pcpuid(ci, "80000007", 'd', curcpu_apmi_edx, prevcpu_apmi_edx, + CPUID_APMI_EDX_BITS); +#ifdef MULTIPROCESSOR + prevcpu_1_ecx = curcpu_1_ecx; + prevcpu_tpm_ecxflags = curcpu_tpm_ecxflags; + prevcpu_d_1_eax = curcpu_d_1_eax; + prevcpu_apmi_edx = curcpu_apmi_edx; +#endif /* speculation control features */ if (ci->ci_vendor == CPUV_AMD) { if (ci->ci_pnfeatset >= 0x80000008) { CPUID(0x80000008, dummy, ci->ci_feature_amdspec_ebx, dummy, dummy); - for (i = 0; i < nitems(cpu_amdspec_ebxfeatures); i++) - if (ci->ci_feature_amdspec_ebx & - cpu_amdspec_ebxfeatures[i].bit) - printf(",%s", - cpu_amdspec_ebxfeatures[i].str); + pcpuid(ci, "80000008", 'b', + CPUID_MEMBER(ci_feature_amdspec_ebx), + CPUID_AMDSPEC_EBX_BITS); } - } else if (ci->ci_vendor == CPUV_INTEL && - (ci->ci_feature_sefflags_edx & SEFF0EDX_ARCH_CAP)) { - uint64_t msr = rdmsr(MSR_ARCH_CAPABILITIES); - - for (i = 0; i < nitems(cpu_arch_cap_features); i++) - if (msr & cpu_arch_cap_features[i].bit) - printf(",%s", cpu_arch_cap_features[i].str); - } - - /* xsave subfeatures */ - if (ci->ci_cpuid_level >= 0xd) { - CPUID_LEAF(0xd, 1, val, dummy, dummy, dummy); - for (i = 0; i < nitems(cpu_xsave_extfeatures); i++) - if (val & cpu_xsave_extfeatures[i].bit) - printf(",%s", cpu_xsave_extfeatures[i].str); + } else if (ci->ci_vendor == CPUV_INTEL) { + if (ci->ci_feature_sefflags_edx & SEFF0EDX_ARCH_CAP) { + uint32_t msr = rdmsr(MSR_ARCH_CAPABILITIES); + + pmsr32(ci, MSR_ARCH_CAPABILITIES, msr, + prevcpu_arch_capa, ARCH_CAP_MSR_BITS); + prevcpu_arch_capa = msr; + if (!CPU_IS_PRIMARY(ci) && cpu_meltdown && + (msr & ARCH_CAP_RDCL_NO)) + printf("\n%s: -MELTDOWN", ci->ci_dev->dv_xname); + } + if (cpu_meltdown && CPU_IS_PRIMARY(ci)) + printf("\n%s: MELTDOWN", ci->ci_dev->dv_xname); } - if (cpu_meltdown) - printf(",MELTDOWN"); - printf("\n"); replacemeltdown(); @@ -763,9 +707,7 @@ identifycpu(struct cpu_info *ci) #ifndef SMALL_KERNEL if (ci->ci_vendor == CPUV_AMD && ci->ci_pnfeatset >= 0x80000007) { - CPUID(0x80000007, dummy, dummy, dummy, val); - - if (val & 0x06) { + if (curcpu_apmi_edx & 0x06) { if ((ci->ci_signature & 0xF00) == 0xF00) setperf_setup = k8_powernow_init; } @@ -787,14 +729,6 @@ identifycpu(struct cpu_info *ci) replacesmap(); } - if (ci->ci_feature_flags & CPUID_CFLUSH) { - u_int32_t cflushsz; - - CPUID(0x01, dummy, cflushsz, dummy, dummy); - /* cflush cacheline size is equal to bits 15-8 of ebx * 8 */ - ci->ci_cflushsz = ((cflushsz >> 8) & 0xff) * 8; - } - #ifndef SMALL_KERNEL if (CPU_IS_PRIMARY(ci) && (ci->ci_feature_tpmflags & TPM_SENSOR)) { ci->ci_sensor.type = SENSOR_TEMP; @@ -830,13 +764,14 @@ identifycpu(struct cpu_info *ci) #endif /* NVMM > 0 */ /* Check for effective frequency via MPERF, APERF */ - if ((cpu_tpm_ecxflags & TPM_EFFFREQ) && ci->ci_smt_id == 0) { + if ((curcpu_tpm_ecxflags & TPM_EFFFREQ) && ci->ci_smt_id == 0) { #ifndef SMALL_KERNEL ci->ci_hz_sensor.type = SENSOR_FREQ; sensor_task_register(ci, cpu_hz_update_sensor, 1); sensor_attach(&ci->ci_sensordev, &ci->ci_hz_sensor); #endif } + prevci = ci; } #ifndef SMALL_KERNEL diff --git a/sys/arch/amd64/include/specialreg.h b/sys/arch/amd64/include/specialreg.h index 41eb3f21831..834627d8c7d 100644 --- a/sys/arch/amd64/include/specialreg.h +++ b/sys/arch/amd64/include/specialreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: specialreg.h,v 1.111 2024/04/11 23:00:13 jsg Exp $ */ +/* $OpenBSD: specialreg.h,v 1.112 2024/05/11 19:21:47 guenther Exp $ */ /* $NetBSD: specialreg.h,v 1.1 2003/04/26 18:39:48 fvdl Exp $ */ /* $NetBSD: x86/specialreg.h,v 1.2 2003/04/25 21:54:30 fvdl Exp $ */ @@ -166,6 +166,12 @@ #define CPUID_TM 0x20000000 /* thermal monitor (TCC) */ #define CPUID_B30 0x40000000 /* reserved */ #define CPUID_PBE 0x80000000 /* Pending Break Enabled restarts clock */ +#define CPUID_EDX_BITS \ + ("\20" "\01FPU" "\02VME" "\03DE" "\04PSE" "\05TSC" "\06MSR" "\07PAE" \ + "\010MCE" "\011CX8" "\012APIC" "\014SEP" "\015MTRR" "\016PGE" "\017MCA" \ + "\020CMOV" "\021PAT" "\022PSE36" "\023PSN" "\024CFLUSH" "\026DS" \ + "\027ACPI" "\030MMX" "\031FXSR" "\032SSE" "\033SSE2" "\034SS" "\035HTT" \ + "\036TM" "\040PBE" ) #define CPUIDECX_SSE3 0x00000001 /* streaming SIMD extensions #3 */ #define CPUIDECX_PCLMUL 0x00000002 /* Carryless Multiplication */ @@ -198,6 +204,13 @@ #define CPUIDECX_F16C 0x20000000 /* 16bit fp conversion */ #define CPUIDECX_RDRAND 0x40000000 /* RDRAND instruction */ #define CPUIDECX_HV 0x80000000 /* Running on hypervisor */ +#define CPUID_ECX_BITS \ + ("\20" "\01SSE3" "\02PCLMUL" "\03DTES64" "\04MWAIT" "\05DS-CPL" "\06VMX" \ + "\07SMX" "\010EST" "\011TM2" "\012SSSE3" "\013CNXT-ID" "\014SDBG" \ + "\015FMA3" "\016CX16" "\017xTPR" "\020PDCM" "\022PCID" "\023DCA" \ + "\024SSE4.1" "\025SSE4.2" "\026x2APIC" "\027MOVBE" "\030POPCNT" \ + "\031DEADLINE" "\032AES" "\033XSAVE" "\034OSXSAVE" "\035AVX" "\036F16C" \ + "\037RDRAND" "\040HV" ) /* * "Structured Extended Feature Flags Parameters" (CPUID function 0x7, leaf 0) @@ -232,13 +245,26 @@ #define SEFF0EBX_SHA 0x20000000 /* SHA Extensions */ #define SEFF0EBX_AVX512BW 0x40000000 /* AVX-512 byte/word inst */ #define SEFF0EBX_AVX512VL 0x80000000 /* AVX-512 vector len inst */ +#define SEFF0_EBX_BITS \ + ("\20" "\01FSGSBASE" "\02TSC_ADJUST" "\03SGX" "\04BMI1" "\05HLE" \ + "\06AVX2" "\010SMEP" "\011BMI2" "\012ERMS" "\013INVPCID" "\014RTM" \ + "\015PQM" "\017MPX" "\021AVX512F" "\022AVX512DQ" "\023RDSEED" "\024ADX" \ + "\025SMAP" "\026AVX512IFMA" "\027PCOMMIT" "\030CLFLUSHOPT" "\031CLWB" \ + "\032PT" "\033AVX512PF" "\034AVX512ER" "\035AVX512CD" "\036SHA" \ + "\037AVX512BW" "\040AVX512VL" ) + /* SEFF ECX bits */ #define SEFF0ECX_PREFETCHWT1 0x00000001 /* PREFETCHWT1 instruction */ #define SEFF0ECX_AVX512VBMI 0x00000002 /* AVX-512 vector bit inst */ #define SEFF0ECX_UMIP 0x00000004 /* UMIP support */ #define SEFF0ECX_PKU 0x00000008 /* Page prot keys for user mode */ +#define SEFF0ECX_OSPKE 0x00000010 /* OS enabled RD/WRPKRU */ #define SEFF0ECX_WAITPKG 0x00000020 /* UMONITOR/UMWAIT/TPAUSE insns */ #define SEFF0ECX_PKS 0x80000000 /* Page prot keys for sup mode */ +#define SEFF0_ECX_BITS \ + ("\20" "\01PREFETCHWT1" "\02AVX512VBMI" "\03UMIP" "\04PKU" "\06WAITPKG" \ + "\040PKS" ) + /* SEFF EDX bits */ #define SEFF0EDX_AVX512_4FNNIW 0x00000004 /* AVX-512 neural network insns */ #define SEFF0EDX_AVX512_4FMAPS 0x00000008 /* AVX-512 mult accum single prec */ @@ -251,14 +277,21 @@ #define SEFF0EDX_L1DF 0x10000000 /* L1D_FLUSH */ #define SEFF0EDX_ARCH_CAP 0x20000000 /* Has IA32_ARCH_CAPABILITIES MSR */ #define SEFF0EDX_SSBD 0x80000000 /* Spec Store Bypass Disable */ +#define SEFF0_EDX_BITS \ + ("\20" "\03AVX512FNNIW" "\04AVX512FMAPS" "\012SRBDS_CTRL" "\013MD_CLEAR" \ + "\016TSXFA" "\025IBT" "\033IBRS,IBPB" "\034STIBP" "\035L1DF" "\040SSBD" ) /* * Thermal and Power Management (CPUID function 0x6) EAX bits */ #define TPM_SENSOR 0x00000001 /* Digital temp sensor */ #define TPM_ARAT 0x00000004 /* APIC Timer Always Running */ +#define TPM_EAX_BITS \ + ("\20" "\01SENSOR" "\03ARAT" ) /* Thermal and Power Management (CPUID function 0x6) ECX bits */ #define TPM_EFFFREQ 0x00000001 /* APERF & MPERF MSR present */ +#define TPM_ECX_BITS \ + ("\20" "\01EFFFREQ" ) /* * "Architectural Performance Monitoring" bits (CPUID function 0x0a): @@ -295,6 +328,9 @@ #define CPUID_LONG 0x20000000 /* long mode */ #define CPUID_3DNOW2 0x40000000 /* 3DNow! Instruction Extension */ #define CPUID_3DNOW 0x80000000 /* 3DNow! Instructions */ +#define CPUIDE_EDX_BITS \ + ("\20" "\024MPC" "\025NXE" "\027MMXX" "\032FFXSR" "\033PAGE1GB" \ + "\034RDTSCP" "\036LONG" "\0373DNOW2" "\0403DNOW" ) #define CPUIDECX_LAHF 0x00000001 /* LAHF and SAHF instructions */ #define CPUIDECX_CMPLEG 0x00000002 /* Core MP legacy mode */ @@ -324,6 +360,12 @@ #define CPUIDECX_PERFTSC 0x08000000 /* performance time-stamp counter */ #define CPUIDECX_PCTRL3 0x10000000 /* L3 performance counter ext */ #define CPUIDECX_MWAITX 0x20000000 /* MWAITX/MONITORX */ +#define CPUIDE_ECX_BITS \ + ("\20" "\01LAHF" "\02CMPLEG" "\03SVM" "\04EAPICSP" "\05AMCR8" "\06ABM" \ + "\07SSE4A" "\010MASSE" "\0113DNOWP" "\012OSVW" "\013IBS" "\014XOP" \ + "\015SKINIT" "\020WDT" "\021FMA4" "\022TCE" "\024NODEID" "\026TBM" \ + "\027TOPEXT" "\030CPCTR" "\033DBKP" "\034PERFTSC" "\035PCTRL3" \ + "\036MWAITX" ) /* * "Advanced Power Management Information" bits (CPUID function 0x80000007): @@ -331,6 +373,8 @@ */ #define CPUIDEDX_HWPSTATE (1 << 7) /* Hardware P State Control */ #define CPUIDEDX_ITSC (1 << 8) /* Invariant TSC */ +#define CPUID_APMI_EDX_BITS \ + ("\20" "\010HWPSTATE" "\011ITSC" ) /* * AMD CPUID function 0x80000008 EBX bits @@ -346,6 +390,10 @@ #define CPUIDEBX_SSBD (1ULL << 24) /* Speculation Control SSBD */ #define CPUIDEBX_VIRT_SSBD (1ULL << 25) /* Virt Spec Control SSBD */ #define CPUIDEBX_SSBD_NOTREQ (1ULL << 26) /* SSBD not required */ +#define CPUID_AMDSPEC_EBX_BITS \ + ("\20" "\04INVLPGB" "\015IBPB" "\017IBRS" "\020STIBP" "\021IBRS_ALL" \ + "\022STIBP_ALL" "\023IBRS_PREF" "\024IBRS_SM" "\031SSBD" "\032VIRTSSBD" \ + "\033SSBDNR" ) #define CPUID2FAMILY(cpuid) (((cpuid) >> 8) & 15) #define CPUID2MODEL(cpuid) (((cpuid) >> 4) & 15) @@ -430,6 +478,14 @@ #define ARCH_CAP_GDS_NO (1 << 26) /* GDS safe */ #define ARCH_CAP_RFDS_NO (1 << 27) /* RFDS safe */ #define ARCH_CAP_RFDS_CLEAR (1 << 28) /* use VERW for RFDS */ +#define ARCH_CAP_MSR_BITS \ + ("\20" "\02IBRS_ALL" "\03RSBA" "\04SKIP_L1DFL" "\05SSB_NO" "\06MDS_NO" \ + "\07IF_PSCHANGE" "\010TSX_CTRL" "\011TAA_NO" "\012MCU_CONTROL" \ + "\013MISC_PKG_CT" "\014ENERGY_FILT" "\015DOITM" "\016SBDR_SSDP_N" \ + "\017FBSDP_NO" "\020PSDP_NO" "\022FB_CLEAR" "\023FB_CLEAR_CT" \ + "\024RRSBA" "\025BHI_NO" "\026XAPIC_DIS" "\030OVERCLOCK" "\031PBRSB_NO" \ + "\032GDS_CTRL" "\033GDS_NO" "\034RFDS_NO" "\035RFDS_CLEAR" ) + #define MSR_FLUSH_CMD 0x10b #define FLUSH_CMD_L1D_FLUSH 0x1 /* (1ULL << 0) */ #define MSR_BBL_CR_ADDR 0x116 /* PII+ only */ @@ -1510,6 +1566,8 @@ #define XSAVE_XGETBV1 0x04UL #define XSAVE_XSAVES 0x08UL #define XSAVE_XFD 0x10UL +#define XSAVE_BITS \ + ("\20" "\01XSAVEOPT" "\02XSAVEC" "\03XGETBV1" "\04XSAVES" "\05XFD" ) /* * Default cr0 and cr4 flags. -- 2.20.1