diff --git a/share/man/man7/security.7 b/share/man/man7/security.7 index a3895fb8a607..71ecf1e682e6 100644 --- a/share/man/man7/security.7 +++ b/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 @@ page table format used by hypervisors on Intel CPUs to map the guest 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. diff --git a/sys/amd64/amd64/initcpu.c b/sys/amd64/amd64/initcpu.c index 33db37eda8d6..b584273aff6c 100644 --- a/sys/amd64/amd64/initcpu.c +++ b/sys/amd64/amd64/initcpu.c @@ -270,6 +270,7 @@ initializecpu(void) 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: diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 239b4baaca60..b2944089e6d9 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -1791,6 +1791,9 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) 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 */ diff --git a/sys/dev/cpuctl/cpuctl.c b/sys/dev/cpuctl/cpuctl.c index 878e430b473e..67f710f52ec6 100644 --- a/sys/dev/cpuctl/cpuctl.c +++ b/sys/dev/cpuctl/cpuctl.c @@ -547,6 +547,7 @@ cpuctl_do_eval_cpu_features(int cpu, struct thread *td) #endif hw_mds_recalculate(); x86_taa_recalculate(); + x86_rngds_mitg_recalculate(true); printcpuinfo(); return (0); } diff --git a/sys/x86/include/x86_var.h b/sys/x86/include/x86_var.h index b064f2f77c2e..3b908068bff3 100644 --- a/sys/x86/include/x86_var.h +++ b/sys/x86/include/x86_var.h @@ -95,6 +95,7 @@ extern int hw_mds_disable; 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_ibrs_recalculate(bool all_cpus); 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); diff --git a/sys/x86/x86/cpu_machdep.c b/sys/x86/x86/cpu_machdep.c index 33dd19d28fbd..74a5261f9112 100644 --- a/sys/x86/x86/cpu_machdep.c +++ b/sys/x86/x86/cpu_machdep.c @@ -1402,6 +1402,60 @@ SYSCTL_INT(_machdep_mitigations, OID_AUTO, flush_rsb_ctxsw, 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