Index: share/man/man7/security.7 =================================================================== --- share/man/man7/security.7 +++ share/man/man7/security.7 @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 16, 2020 +.Dd June 11, 2020 .Dt SECURITY 7 .Os .Sh NAME @@ -1040,6 +1040,13 @@ physical address space to machine physical memory. May be disabled to work around a CPU Erratum called Machine Check Error Avoidance on Page Size Change. +.It Dv machdep.mitigations.rngds.enable +amd64 and i386. +Controls mitigation of Special Register Buffer Data Sampling versus +optimization of the MCU access. +When set to zero, the mitigation is disabled, and the RDSEED and RDRAND +instructions do not incur serialization overhead for shared buffer accesses, +and do not serialize off-core memory accessses. .It Dv kern.elf32.aslr.enable Controls system-global Address Space Layout Randomization (ASLR) for normal non-PIE (Position Independent Executable) 32bit binaries. Index: sys/amd64/amd64/initcpu.c =================================================================== --- sys/amd64/amd64/initcpu.c +++ sys/amd64/amd64/initcpu.c @@ -270,6 +270,7 @@ hw_ibrs_recalculate(false); hw_ssb_recalculate(false); amd64_syscall_ret_flush_l1d_recalc(); + x86_rngds_mitg_recalculate(false); switch (cpu_vendor_id) { case CPU_VENDOR_AMD: case CPU_VENDOR_HYGON: Index: sys/amd64/amd64/machdep.c =================================================================== --- sys/amd64/amd64/machdep.c +++ sys/amd64/amd64/machdep.c @@ -1791,6 +1791,9 @@ TUNABLE_INT_FETCH("machdep.mitigations.taa.enable", &x86_taa_enable); + TUNABLE_INT_FETCH("machdep.mitigations.rndgs.enable", + &x86_rngds_mitg_enable); + finishidentcpu(); /* Final stage of CPU initialization */ initializecpu(); /* Initialize CPU registers */ Index: sys/dev/cpuctl/cpuctl.c =================================================================== --- sys/dev/cpuctl/cpuctl.c +++ sys/dev/cpuctl/cpuctl.c @@ -547,6 +547,7 @@ #endif hw_mds_recalculate(); x86_taa_recalculate(); + x86_rngds_mitg_recalculate(true); printcpuinfo(); return (0); } Index: sys/x86/include/specialreg.h =================================================================== --- sys/x86/include/specialreg.h +++ sys/x86/include/specialreg.h @@ -477,6 +477,7 @@ #define CPUID_STDEXT3_AVX5124FMAPS 0x00000008 #define CPUID_STDEXT3_FSRM 0x00000010 #define CPUID_STDEXT3_AVX512VP2INTERSECT 0x00000100 +#define CPUID_STDEXT3_MCUOPT 0x00000200 #define CPUID_STDEXT3_MD_CLEAR 0x00000400 #define CPUID_STDEXT3_TSXFA 0x00002000 #define CPUID_STDEXT3_PCONFIG 0x00040000 @@ -555,6 +556,7 @@ #define MSR_BBL_CR_BUSY 0x11b #define MSR_BBL_CR_CTL3 0x11e #define MSR_IA32_TSX_CTRL 0x122 +#define MSR_IA32_MCU_OPT_CTRL 0x123 #define MSR_SYSENTER_CS_MSR 0x174 #define MSR_SYSENTER_ESP_MSR 0x175 #define MSR_SYSENTER_EIP_MSR 0x176 @@ -797,6 +799,9 @@ /* MSR IA32_FLUSH_CMD */ #define IA32_FLUSH_CMD_L1D 0x00000001 +/* MSR IA32_MCU_OPT_CTRL */ +#define IA32_RNGDS_MITG_DIS 0x00000001 + /* MSR IA32_HWP_CAPABILITIES */ #define IA32_HWP_CAPABILITIES_HIGHEST_PERFORMANCE(x) (((x) >> 0) & 0xff) #define IA32_HWP_CAPABILITIES_GUARANTEED_PERFORMANCE(x) (((x) >> 8) & 0xff) Index: sys/x86/include/x86_var.h =================================================================== --- sys/x86/include/x86_var.h +++ sys/x86/include/x86_var.h @@ -95,6 +95,7 @@ extern int hw_ssb_active; extern int x86_taa_enable; extern int cpu_flush_rsb_ctxsw; +extern int x86_rngds_mitg_enable; struct pcb; struct thread; @@ -139,6 +140,7 @@ void hw_mds_recalculate(void); void hw_ssb_recalculate(bool all_cpus); void x86_taa_recalculate(void); +void x86_rngds_mitg_recalculate(bool all_cpus); void nmi_call_kdb(u_int cpu, u_int type, struct trapframe *frame); void nmi_call_kdb_smp(u_int type, struct trapframe *frame); void nmi_handle_intr(u_int type, struct trapframe *frame); Index: sys/x86/x86/cpu_machdep.c =================================================================== --- sys/x86/x86/cpu_machdep.c +++ sys/x86/x86/cpu_machdep.c @@ -1402,6 +1402,60 @@ CTLFLAG_RW | CTLFLAG_NOFETCH, &cpu_flush_rsb_ctxsw, 0, "Flush Return Stack Buffer on context switch"); +SYSCTL_NODE(_machdep_mitigations, OID_AUTO, rngds, + CTLFLAG_RW | CTLFLAG_MPSAFE, 0, + "MCU Optimization, disable RDSEED mitigation"); + +int x86_rngds_mitg_enable = 1; +void +x86_rngds_mitg_recalculate(bool all_cpus) +{ + if ((cpu_stdext_feature3 & CPUID_STDEXT3_MCUOPT) == 0) + return; + x86_msr_op(MSR_IA32_MCU_OPT_CTRL, + (x86_rngds_mitg_enable ? MSR_OP_OR : MSR_OP_ANDNOT) | + (all_cpus ? MSR_OP_RENDEZVOUS : MSR_OP_LOCAL), + IA32_RNGDS_MITG_DIS); +} + +static int +sysctl_rngds_mitg_enable_handler(SYSCTL_HANDLER_ARGS) +{ + int error, val; + + val = x86_rngds_mitg_enable; + error = sysctl_handle_int(oidp, &val, 0, req); + if (error != 0 || req->newptr == NULL) + return (error); + x86_rngds_mitg_enable = val; + x86_rngds_mitg_recalculate(true); + return (0); +} +SYSCTL_PROC(_machdep_mitigations_rngds, OID_AUTO, enable, CTLTYPE_INT | + CTLFLAG_RWTUN | CTLFLAG_NOFETCH | CTLFLAG_MPSAFE, NULL, 0, + sysctl_rngds_mitg_enable_handler, "I", + "MCU Optimization, disabling RDSEED mitigation control " + "(0 - mitigation disabled (RDSEED optimized), 1 - mitigation enabled"); + +static int +sysctl_rngds_state_handler(SYSCTL_HANDLER_ARGS) +{ + const char *state; + + if ((cpu_stdext_feature3 & CPUID_STDEXT3_MCUOPT) == 0) { + state = "Not applicable"; + } else if (x86_rngds_mitg_enable == 0) { + state = "RDSEED not serialized"; + } else { + state = "Mitigated"; + } + return (SYSCTL_OUT(req, state, strlen(state))); +} +SYSCTL_PROC(_machdep_mitigations_rngds, OID_AUTO, state, + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, + sysctl_rngds_state_handler, "A", + "MCU Optimization state"); + /* * Enable and restore kernel text write permissions. * Callers must ensure that disable_wp()/restore_wp() are executed Index: sys/x86/x86/identcpu.c =================================================================== --- sys/x86/x86/identcpu.c +++ sys/x86/x86/identcpu.c @@ -1028,6 +1028,7 @@ "\004AVX512_4FMAPS" "\005FSRM" "\011AVX512VP2INTERSECT" + "\012MCUOPT" "\013MD_CLEAR" "\016TSXFA" "\023PCONFIG"