aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/svm.c
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2009-03-30 09:03:29 -0400
committerAvi Kivity <avi@redhat.com>2009-06-10 04:48:38 -0400
commit64a7ec066813443440bfc9f60a9e76a47cfa6b2b (patch)
treed6d3461ba7667ac2801350d5b3b518e84b5df0f6 /arch/x86/kvm/svm.c
parentb237ac37a149e8b56436fabf093532483bff13b0 (diff)
KVM: Fix unneeded instruction skipping during task switching.
There is no need to skip instruction if the reason for a task switch is a task gate in IDT and access to it is caused by an external even. The problem is currently solved only for VMX since there is no reliable way to skip an instruction in SVM. We should emulate it instead. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/svm.c')
-rw-r--r--arch/x86/kvm/svm.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index de741043c5b1..bba67b70c4b0 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1825,17 +1825,28 @@ static int task_switch_interception(struct vcpu_svm *svm,
1825 struct kvm_run *kvm_run) 1825 struct kvm_run *kvm_run)
1826{ 1826{
1827 u16 tss_selector; 1827 u16 tss_selector;
1828 int reason;
1829 int int_type = svm->vmcb->control.exit_int_info &
1830 SVM_EXITINTINFO_TYPE_MASK;
1828 1831
1829 tss_selector = (u16)svm->vmcb->control.exit_info_1; 1832 tss_selector = (u16)svm->vmcb->control.exit_info_1;
1833
1830 if (svm->vmcb->control.exit_info_2 & 1834 if (svm->vmcb->control.exit_info_2 &
1831 (1ULL << SVM_EXITINFOSHIFT_TS_REASON_IRET)) 1835 (1ULL << SVM_EXITINFOSHIFT_TS_REASON_IRET))
1832 return kvm_task_switch(&svm->vcpu, tss_selector, 1836 reason = TASK_SWITCH_IRET;
1833 TASK_SWITCH_IRET); 1837 else if (svm->vmcb->control.exit_info_2 &
1834 if (svm->vmcb->control.exit_info_2 & 1838 (1ULL << SVM_EXITINFOSHIFT_TS_REASON_JMP))
1835 (1ULL << SVM_EXITINFOSHIFT_TS_REASON_JMP)) 1839 reason = TASK_SWITCH_JMP;
1836 return kvm_task_switch(&svm->vcpu, tss_selector, 1840 else if (svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID)
1837 TASK_SWITCH_JMP); 1841 reason = TASK_SWITCH_GATE;
1838 return kvm_task_switch(&svm->vcpu, tss_selector, TASK_SWITCH_CALL); 1842 else
1843 reason = TASK_SWITCH_CALL;
1844
1845
1846 if (reason != TASK_SWITCH_GATE || int_type == SVM_EXITINTINFO_TYPE_SOFT)
1847 skip_emulated_instruction(&svm->vcpu);
1848
1849 return kvm_task_switch(&svm->vcpu, tss_selector, reason);
1839} 1850}
1840 1851
1841static int cpuid_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) 1852static int cpuid_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)