Skip to content

Commit f6577a5

Browse files
amlutobonzini
authored andcommitted
x86, kvm, vmx: Always use LOAD_IA32_EFER if available
At least on Sandy Bridge, letting the CPU switch IA32_EFER is much faster than switching it manually. I benchmarked this using the vmexit kvm-unit-test (single run, but GOAL multiplied by 5 to do more iterations): Test Before After Change cpuid 2000 1932 -3.40% vmcall 1914 1817 -5.07% mov_from_cr8 13 13 0.00% mov_to_cr8 19 19 0.00% inl_from_pmtimer 19164 10619 -44.59% inl_from_qemu 15662 10302 -34.22% inl_from_kernel 3916 3802 -2.91% outl_to_kernel 2230 2194 -1.61% mov_dr 172 176 2.33% ipi (skipped) (skipped) ipi+halt (skipped) (skipped) ple-round-robin 13 13 0.00% wr_tsc_adjust_msr 1920 1845 -3.91% rd_tsc_adjust_msr 1892 1814 -4.12% mmio-no-eventfd:pci-mem 16394 11165 -31.90% mmio-wildcard-eventfd:pci-mem 4607 4645 0.82% mmio-datamatch-eventfd:pci-mem 4601 4610 0.20% portio-no-eventfd:pci-io 11507 7942 -30.98% portio-wildcard-eventfd:pci-io 2239 2225 -0.63% portio-datamatch-eventfd:pci-io 2250 2234 -0.71% I haven't explicitly computed the significance of these numbers, but this isn't subtle. Signed-off-by: Andy Lutomirski <[email protected]> [The results were reproducible on all of Nehalem, Sandy Bridge and Ivy Bridge. The slowness of manual switching is because writing to EFER with WRMSR triggers a TLB flush, even if the only bit you're touching is SCE (so the page table format is not affected). Doing the write as part of vmentry/vmexit, instead, does not flush the TLB, probably because all processors that have EPT also have VPID. - Paolo] Signed-off-by: Paolo Bonzini <[email protected]>
1 parent ac14623 commit f6577a5

File tree

1 file changed

+8
-2
lines changed

1 file changed

+8
-2
lines changed

arch/x86/kvm/vmx.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1662,8 +1662,14 @@ static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset)
16621662
vmx->guest_msrs[efer_offset].mask = ~ignore_bits;
16631663

16641664
clear_atomic_switch_msr(vmx, MSR_EFER);
1665-
/* On ept, can't emulate nx, and must switch nx atomically */
1666-
if (enable_ept && ((vmx->vcpu.arch.efer ^ host_efer) & EFER_NX)) {
1665+
1666+
/*
1667+
* On EPT, we can't emulate NX, so we must switch EFER atomically.
1668+
* On CPUs that support "load IA32_EFER", always switch EFER
1669+
* atomically, since it's faster than switching it manually.
1670+
*/
1671+
if (cpu_has_load_ia32_efer ||
1672+
(enable_ept && ((vmx->vcpu.arch.efer ^ host_efer) & EFER_NX))) {
16671673
guest_efer = vmx->vcpu.arch.efer;
16681674
if (!(guest_efer & EFER_LMA))
16691675
guest_efer &= ~EFER_LME;

0 commit comments

Comments
 (0)