Date: Tue, 14 Aug 2018 17:29:41 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r337785 - head/sys/amd64/vmm/intel Message-ID: <201808141729.w7EHTfrd017107@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Tue Aug 14 17:29:41 2018 New Revision: 337785 URL: https://svnweb.freebsd.org/changeset/base/337785 Log: Provide part of the mitigation for L1TF-VMM. On the guest entry in bhyve, flush L1 data cache, using either L1D flush command MSR if available, or by reading enough uninteresting data to fill whole cache. Flush is automatically enabled on CPUs which do not report RDCL_NO, and can be disabled with the hw.vmm.l1d_flush tunable/kenv. Security: CVE-2018-3646 Reviewed by: emaste. jhb, Tony Luck <tony.luck@intel.com> Sponsored by: The FreeBSD Foundation Modified: head/sys/amd64/vmm/intel/vmx.c head/sys/amd64/vmm/intel/vmx_genassym.c head/sys/amd64/vmm/intel/vmx_support.S Modified: head/sys/amd64/vmm/intel/vmx.c ============================================================================== --- head/sys/amd64/vmm/intel/vmx.c Tue Aug 14 17:29:22 2018 (r337784) +++ head/sys/amd64/vmm/intel/vmx.c Tue Aug 14 17:29:41 2018 (r337785) @@ -188,6 +188,12 @@ static u_int vpid_alloc_failed; SYSCTL_UINT(_hw_vmm_vmx, OID_AUTO, vpid_alloc_failed, CTLFLAG_RD, &vpid_alloc_failed, 0, NULL); +static int guest_l1d_flush; +SYSCTL_INT(_hw_vmm_vmx, OID_AUTO, l1d_flush, CTLFLAG_RD, + &guest_l1d_flush, 0, NULL); + +uint64_t vmx_msr_flush_cmd; + /* * The definitions of SDT probes for VMX. */ @@ -798,6 +804,12 @@ vmx_init(int ipinum) printf("vmx_init: ept initialization failed (%d)\n", error); return (error); } + + guest_l1d_flush = (cpu_ia32_arch_caps & IA32_ARCH_CAP_RDCL_NO) == 0; + TUNABLE_INT_FETCH("hw.vmm.l1d_flush", &guest_l1d_flush); + if (guest_l1d_flush && + (cpu_stdext_feature3 & CPUID_STDEXT3_L1D_FLUSH) != 0) + vmx_msr_flush_cmd = IA32_FLUSH_CMD_L1D; /* * Stash the cr0 and cr4 bits that must be fixed to 0 or 1 Modified: head/sys/amd64/vmm/intel/vmx_genassym.c ============================================================================== --- head/sys/amd64/vmm/intel/vmx_genassym.c Tue Aug 14 17:29:22 2018 (r337784) +++ head/sys/amd64/vmm/intel/vmx_genassym.c Tue Aug 14 17:29:41 2018 (r337785) @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/pmap.h> +#include <vm/vm_param.h> #include <machine/vmm.h> #include "vmx_cpufunc.h" @@ -88,3 +89,6 @@ ASSYM(PM_EPTGEN, offsetof(struct pmap, pm_eptgen)); ASSYM(KERNEL_SS, GSEL(GDATA_SEL, SEL_KPL)); ASSYM(KERNEL_CS, GSEL(GCODE_SEL, SEL_KPL)); + +ASSYM(PAGE_SIZE, PAGE_SIZE); +ASSYM(KERNBASE, KERNBASE); Modified: head/sys/amd64/vmm/intel/vmx_support.S ============================================================================== --- head/sys/amd64/vmm/intel/vmx_support.S Tue Aug 14 17:29:22 2018 (r337784) +++ head/sys/amd64/vmm/intel/vmx_support.S Tue Aug 14 17:29:41 2018 (r337785) @@ -30,6 +30,7 @@ */ #include <machine/asmacros.h> +#include <machine/specialreg.h> #include "vmx_assym.h" @@ -175,9 +176,47 @@ ENTRY(vmx_enter_guest) jbe invept_error /* Check invept instruction error */ guest_restore: - cmpl $0, %edx - je do_launch + /* + * Flush L1D cache if requested. Use IA32_FLUSH_CMD MSR if available, + * otherwise load enough of the data from the zero_region to flush + * existing L1D content. + */ +#define L1D_FLUSH_SIZE (64 * 1024) + movl %edx, %r8d + cmpb $0, guest_l1d_flush(%rip) + je after_l1d + movq vmx_msr_flush_cmd(%rip), %rax + testq %rax, %rax + jz 1f + movq %rax, %rdx + shrq $32, %rdx + movl $MSR_IA32_FLUSH_CMD, %ecx + wrmsr + jmp after_l1d +1: movq $KERNBASE, %r9 + movq $-L1D_FLUSH_SIZE, %rcx + /* + * pass 1: Preload TLB. + * Kernel text is mapped using superpages. TLB preload is + * done for the benefit of older CPUs which split 2M page + * into 4k TLB entries. + */ +2: movb L1D_FLUSH_SIZE(%r9, %rcx), %al + addq $PAGE_SIZE, %rcx + jne 2b + xorl %eax, %eax + cpuid + movq $-L1D_FLUSH_SIZE, %rcx + /* pass 2: Read each cache line */ +3: movb L1D_FLUSH_SIZE(%r9, %rcx), %al + addq $64, %rcx + jne 3b + lfence +#undef L1D_FLUSH_SIZE +after_l1d: + cmpl $0, %r8d + je do_launch VMX_GUEST_RESTORE vmresume /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201808141729.w7EHTfrd017107>