diff options
author | Jan Kiszka <jan.kiszka@siemens.com> | 2010-04-14 09:51:09 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-05-17 05:17:46 -0400 |
commit | e269fb2189fb86d79d64c0ca74c6c1a549ad4aa3 (patch) | |
tree | 627c658efaec155d1f295d1fc7b8abded9d4f861 /arch/x86/kvm/vmx.c | |
parent | 0760d44868f351ba30fc9a08cf1830e46aa72466 (diff) |
KVM: x86: Push potential exception error code on task switches
When a fault triggers a task switch, the error code, if existent, has to
be pushed on the new task's stack. Implement the missing bits.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r-- | arch/x86/kvm/vmx.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index fb4a8869bb99..1b38d8a88cf7 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -3271,6 +3271,8 @@ static int handle_task_switch(struct kvm_vcpu *vcpu) | |||
3271 | { | 3271 | { |
3272 | struct vcpu_vmx *vmx = to_vmx(vcpu); | 3272 | struct vcpu_vmx *vmx = to_vmx(vcpu); |
3273 | unsigned long exit_qualification; | 3273 | unsigned long exit_qualification; |
3274 | bool has_error_code = false; | ||
3275 | u32 error_code = 0; | ||
3274 | u16 tss_selector; | 3276 | u16 tss_selector; |
3275 | int reason, type, idt_v; | 3277 | int reason, type, idt_v; |
3276 | 3278 | ||
@@ -3293,6 +3295,13 @@ static int handle_task_switch(struct kvm_vcpu *vcpu) | |||
3293 | kvm_clear_interrupt_queue(vcpu); | 3295 | kvm_clear_interrupt_queue(vcpu); |
3294 | break; | 3296 | break; |
3295 | case INTR_TYPE_HARD_EXCEPTION: | 3297 | case INTR_TYPE_HARD_EXCEPTION: |
3298 | if (vmx->idt_vectoring_info & | ||
3299 | VECTORING_INFO_DELIVER_CODE_MASK) { | ||
3300 | has_error_code = true; | ||
3301 | error_code = | ||
3302 | vmcs_read32(IDT_VECTORING_ERROR_CODE); | ||
3303 | } | ||
3304 | /* fall through */ | ||
3296 | case INTR_TYPE_SOFT_EXCEPTION: | 3305 | case INTR_TYPE_SOFT_EXCEPTION: |
3297 | kvm_clear_exception_queue(vcpu); | 3306 | kvm_clear_exception_queue(vcpu); |
3298 | break; | 3307 | break; |
@@ -3307,7 +3316,8 @@ static int handle_task_switch(struct kvm_vcpu *vcpu) | |||
3307 | type != INTR_TYPE_NMI_INTR)) | 3316 | type != INTR_TYPE_NMI_INTR)) |
3308 | skip_emulated_instruction(vcpu); | 3317 | skip_emulated_instruction(vcpu); |
3309 | 3318 | ||
3310 | if (!kvm_task_switch(vcpu, tss_selector, reason)) | 3319 | if (!kvm_task_switch(vcpu, tss_selector, reason, has_error_code, |
3320 | error_code)) | ||
3311 | return 0; | 3321 | return 0; |
3312 | 3322 | ||
3313 | /* clear all local breakpoint enable flags */ | 3323 | /* clear all local breakpoint enable flags */ |