aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/vmx.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-04-30 09:07:54 -0400
committerAvi Kivity <avi@qumranet.com>2007-07-16 05:05:38 -0400
commite6adf28365b2fca0b5235cabff00c9f3d1e7bdf4 (patch)
tree75cdf0f0635a32e9337a4c2e3e5f332cf932f902 /drivers/kvm/vmx.c
parente925c5ba9380dad5fdf1d0a9d9199ac43be74c6a (diff)
KVM: Avoid saving and restoring some host CPU state on lightweight vmexit
Many msrs and the like will only be used by the host if we schedule() or return to userspace. Therefore, we avoid saving them if we handle the exit within the kernel, and if a reschedule is not requested. Based on a patch from Eddie Dong <eddie.dong@intel.com> with a couple of fixes by me. Signed-off-by: Yaozu(Eddie) Dong <eddie.dong@intel.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/vmx.c')
-rw-r--r--drivers/kvm/vmx.c105
1 files changed, 60 insertions, 45 deletions
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 52bd5f079df1..84ce0c0930a0 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -483,6 +483,13 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
483 case MSR_GS_BASE: 483 case MSR_GS_BASE:
484 vmcs_writel(GUEST_GS_BASE, data); 484 vmcs_writel(GUEST_GS_BASE, data);
485 break; 485 break;
486 case MSR_LSTAR:
487 case MSR_SYSCALL_MASK:
488 msr = find_msr_entry(vcpu, msr_index);
489 if (msr)
490 msr->data = data;
491 load_msrs(vcpu->guest_msrs, NR_BAD_MSRS);
492 break;
486#endif 493#endif
487 case MSR_IA32_SYSENTER_CS: 494 case MSR_IA32_SYSENTER_CS:
488 vmcs_write32(GUEST_SYSENTER_CS, data); 495 vmcs_write32(GUEST_SYSENTER_CS, data);
@@ -1820,7 +1827,7 @@ static int vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
1820 int fs_gs_ldt_reload_needed; 1827 int fs_gs_ldt_reload_needed;
1821 int r; 1828 int r;
1822 1829
1823again: 1830preempted:
1824 /* 1831 /*
1825 * Set host fs and gs selectors. Unfortunately, 22.2.3 does not 1832 * Set host fs and gs selectors. Unfortunately, 22.2.3 does not
1826 * allow segment selectors with cpl > 0 or ti == 1. 1833 * allow segment selectors with cpl > 0 or ti == 1.
@@ -1851,13 +1858,6 @@ again:
1851 if (vcpu->guest_debug.enabled) 1858 if (vcpu->guest_debug.enabled)
1852 kvm_guest_debug_pre(vcpu); 1859 kvm_guest_debug_pre(vcpu);
1853 1860
1854 kvm_load_guest_fpu(vcpu);
1855
1856 /*
1857 * Loading guest fpu may have cleared host cr0.ts
1858 */
1859 vmcs_writel(HOST_CR0, read_cr0());
1860
1861#ifdef CONFIG_X86_64 1861#ifdef CONFIG_X86_64
1862 if (is_long_mode(vcpu)) { 1862 if (is_long_mode(vcpu)) {
1863 save_msrs(vcpu->host_msrs + msr_offset_kernel_gs_base, 1); 1863 save_msrs(vcpu->host_msrs + msr_offset_kernel_gs_base, 1);
@@ -1865,6 +1865,14 @@ again:
1865 } 1865 }
1866#endif 1866#endif
1867 1867
1868again:
1869 kvm_load_guest_fpu(vcpu);
1870
1871 /*
1872 * Loading guest fpu may have cleared host cr0.ts
1873 */
1874 vmcs_writel(HOST_CR0, read_cr0());
1875
1868 asm ( 1876 asm (
1869 /* Store host registers */ 1877 /* Store host registers */
1870 "pushf \n\t" 1878 "pushf \n\t"
@@ -1984,36 +1992,8 @@ again:
1984 [cr2]"i"(offsetof(struct kvm_vcpu, cr2)) 1992 [cr2]"i"(offsetof(struct kvm_vcpu, cr2))
1985 : "cc", "memory" ); 1993 : "cc", "memory" );
1986 1994
1987 /*
1988 * Reload segment selectors ASAP. (it's needed for a functional
1989 * kernel: x86 relies on having __KERNEL_PDA in %fs and x86_64
1990 * relies on having 0 in %gs for the CPU PDA to work.)
1991 */
1992 if (fs_gs_ldt_reload_needed) {
1993 load_ldt(ldt_sel);
1994 load_fs(fs_sel);
1995 /*
1996 * If we have to reload gs, we must take care to
1997 * preserve our gs base.
1998 */
1999 local_irq_disable();
2000 load_gs(gs_sel);
2001#ifdef CONFIG_X86_64
2002 wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE));
2003#endif
2004 local_irq_enable();
2005
2006 reload_tss();
2007 }
2008 ++vcpu->stat.exits; 1995 ++vcpu->stat.exits;
2009 1996
2010#ifdef CONFIG_X86_64
2011 if (is_long_mode(vcpu)) {
2012 save_msrs(vcpu->guest_msrs, NR_BAD_MSRS);
2013 load_msrs(vcpu->host_msrs, NR_BAD_MSRS);
2014 }
2015#endif
2016
2017 vcpu->interrupt_window_open = (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0; 1997 vcpu->interrupt_window_open = (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0;
2018 1998
2019 asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS)); 1999 asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
@@ -2035,24 +2015,59 @@ again:
2035 if (r > 0) { 2015 if (r > 0) {
2036 /* Give scheduler a change to reschedule. */ 2016 /* Give scheduler a change to reschedule. */
2037 if (signal_pending(current)) { 2017 if (signal_pending(current)) {
2038 ++vcpu->stat.signal_exits; 2018 r = -EINTR;
2039 post_kvm_run_save(vcpu, kvm_run);
2040 kvm_run->exit_reason = KVM_EXIT_INTR; 2019 kvm_run->exit_reason = KVM_EXIT_INTR;
2041 return -EINTR; 2020 ++vcpu->stat.signal_exits;
2021 goto out;
2042 } 2022 }
2043 2023
2044 if (dm_request_for_irq_injection(vcpu, kvm_run)) { 2024 if (dm_request_for_irq_injection(vcpu, kvm_run)) {
2045 ++vcpu->stat.request_irq_exits; 2025 r = -EINTR;
2046 post_kvm_run_save(vcpu, kvm_run);
2047 kvm_run->exit_reason = KVM_EXIT_INTR; 2026 kvm_run->exit_reason = KVM_EXIT_INTR;
2048 return -EINTR; 2027 ++vcpu->stat.request_irq_exits;
2028 goto out;
2029 }
2030 if (!need_resched()) {
2031 ++vcpu->stat.light_exits;
2032 goto again;
2049 } 2033 }
2050
2051 kvm_resched(vcpu);
2052 goto again;
2053 } 2034 }
2054 } 2035 }
2055 2036
2037out:
2038 /*
2039 * Reload segment selectors ASAP. (it's needed for a functional
2040 * kernel: x86 relies on having __KERNEL_PDA in %fs and x86_64
2041 * relies on having 0 in %gs for the CPU PDA to work.)
2042 */
2043 if (fs_gs_ldt_reload_needed) {
2044 load_ldt(ldt_sel);
2045 load_fs(fs_sel);
2046 /*
2047 * If we have to reload gs, we must take care to
2048 * preserve our gs base.
2049 */
2050 local_irq_disable();
2051 load_gs(gs_sel);
2052#ifdef CONFIG_X86_64
2053 wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE));
2054#endif
2055 local_irq_enable();
2056
2057 reload_tss();
2058 }
2059#ifdef CONFIG_X86_64
2060 if (is_long_mode(vcpu)) {
2061 save_msrs(vcpu->guest_msrs, NR_BAD_MSRS);
2062 load_msrs(vcpu->host_msrs, NR_BAD_MSRS);
2063 }
2064#endif
2065
2066 if (r > 0) {
2067 kvm_resched(vcpu);
2068 goto preempted;
2069 }
2070
2056 post_kvm_run_save(vcpu, kvm_run); 2071 post_kvm_run_save(vcpu, kvm_run);
2057 return r; 2072 return r;
2058} 2073}