commit 11554c848e14f5322210c640e4a7ddeabe961282
Author: Yaozu Dong <Eddie.dong@intel.com>
Date:   Wed Apr 25 14:14:17 2007 +0800

    Avoid MSR save/restore for lightweight VM EXIT where no
    task switch nor qemu user mode is entered.

diff --git a/drivers/kvm/kvm_vmx.h b/drivers/kvm/kvm_vmx.h
index d139f73..f1bf7ad 100644
--- a/drivers/kvm/kvm_vmx.h
+++ b/drivers/kvm/kvm_vmx.h
@@ -1,14 +1,6 @@
 #ifndef __KVM_VMX_H
 #define __KVM_VMX_H
 
-#ifdef CONFIG_X86_64
-/*
- * avoid save/load MSR_SYSCALL_MASK and MSR_LSTAR by std vt
- * mechanism (cpu bug AA24)
- */
-#define NR_BAD_MSRS 2
-#else
-#define NR_BAD_MSRS 0
-#endif
+#define NR_HW_SAVE_MSRS  1
 
 #endif
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index fbbf9d6..3d2176f 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -71,10 +71,11 @@ static struct kvm_vmx_segment_field {
 };
 
 static const u32 vmx_msr_index[] = {
+	MSR_K6_STAR,
 #ifdef CONFIG_X86_64
 	MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR, MSR_KERNEL_GS_BASE,
 #endif
-	MSR_EFER, MSR_K6_STAR,
+	MSR_EFER,
 };
 #define NR_VMX_MSR ARRAY_SIZE(vmx_msr_index)
 
@@ -991,7 +992,7 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)
 	struct descriptor_table dt;
 	int i;
 	int ret = 0;
-	int nr_good_msrs;
+	int nr_sw_save_msrs;
 	extern asmlinkage void kvm_vmx_return(void);
 
 	if (!init_rmode_tss(vcpu->kvm)) {
@@ -1140,18 +1141,18 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)
 	}
 	printk(KERN_DEBUG "kvm: msrs: %d\n", vcpu->nmsrs);
 
-	nr_good_msrs = vcpu->nmsrs - NR_BAD_MSRS;
+	nr_sw_save_msrs = vcpu->nmsrs - NR_HW_SAVE_MSRS;
 	vmcs_writel(VM_ENTRY_MSR_LOAD_ADDR,
-		    virt_to_phys(vcpu->guest_msrs + NR_BAD_MSRS));
+		    virt_to_phys(vcpu->guest_msrs + nr_sw_save_msrs));
 	vmcs_writel(VM_EXIT_MSR_STORE_ADDR,
-		    virt_to_phys(vcpu->guest_msrs + NR_BAD_MSRS));
+		    virt_to_phys(vcpu->guest_msrs + nr_sw_save_msrs));
 	vmcs_writel(VM_EXIT_MSR_LOAD_ADDR,
-		    virt_to_phys(vcpu->host_msrs + NR_BAD_MSRS));
+		    virt_to_phys(vcpu->host_msrs + nr_sw_save_msrs));
 	vmcs_write32_fixedbits(MSR_IA32_VMX_EXIT_CTLS, VM_EXIT_CONTROLS,
 		     	       (HOST_IS_64 << 9));  /* 22.2,1, 20.7.1 */
-	vmcs_write32(VM_EXIT_MSR_STORE_COUNT, nr_good_msrs); /* 22.2.2 */
-	vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, nr_good_msrs);  /* 22.2.2 */
-	vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, nr_good_msrs); /* 22.2.2 */
+	vmcs_write32(VM_EXIT_MSR_STORE_COUNT, NR_HW_SAVE_MSRS); /* 22.2.2 */
+	vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, NR_HW_SAVE_MSRS);  /* 22.2.2 */
+	vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, NR_HW_SAVE_MSRS); /* 22.2.2 */
 
 
 	/* 22.2.1, 20.8.1 */
@@ -1732,6 +1733,9 @@ static int vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 	int fs_gs_ldt_reload_needed;
 	int r;
 
+	save_msrs(vcpu->host_msrs, vcpu->nmsrs);
+	load_msrs(vcpu->guest_msrs, vcpu->nmsrs - NR_HW_SAVE_MSRS);
+
 again:
 	/*
 	 * Set host fs and gs selectors.  Unfortunately, 22.2.3 does not
@@ -1766,9 +1770,6 @@ again:
 	fx_save(vcpu->host_fx_image);
 	fx_restore(vcpu->guest_fx_image);
 
-	save_msrs(vcpu->host_msrs, vcpu->nmsrs);
-	load_msrs(vcpu->guest_msrs, NR_BAD_MSRS);
-
 	asm (
 		/* Store host registers */
 		"pushf \n\t"
@@ -1911,9 +1912,6 @@ again:
 	}
 	++kvm_stat.exits;
 
-	save_msrs(vcpu->guest_msrs, NR_BAD_MSRS);
-	load_msrs(vcpu->host_msrs, NR_BAD_MSRS);
-
 	fx_save(vcpu->guest_fx_image);
 	fx_restore(vcpu->host_fx_image);
 	vcpu->interrupt_window_open = (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0;
@@ -1939,14 +1937,14 @@ again:
 			/* Give scheduler a change to reschedule. */
 			if (signal_pending(current)) {
 				++kvm_stat.signal_exits;
-				post_kvm_run_save(vcpu, kvm_run);
-				return -EINTR;
+ 				r = -EINTR;
+ 				goto out;
 			}
 
 			if (dm_request_for_irq_injection(vcpu, kvm_run)) {
 				++kvm_stat.request_irq_exits;
-				post_kvm_run_save(vcpu, kvm_run);
-				return -EINTR;
+ 				r = -EINTR;
+ 				goto out;
 			}
 
 			kvm_resched(vcpu);
@@ -1954,6 +1952,10 @@ again:
 		}
 	}
 
+out:
+	save_msrs(vcpu->guest_msrs, vcpu->nmsrs - NR_HW_SAVE_MSRS);
+	load_msrs(vcpu->host_msrs, vcpu->nmsrs - NR_HW_SAVE_MSRS);
+
 	post_kvm_run_save(vcpu, kvm_run);
 	return r;
 }
