aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/kvm_emulate.h3
-rw-r--r--arch/x86/include/asm/kvm_host.h3
-rw-r--r--arch/x86/include/asm/svm.h1
-rw-r--r--arch/x86/kvm/emulate.c22
-rw-r--r--arch/x86/kvm/svm.c11
-rw-r--r--arch/x86/kvm/vmx.c12
-rw-r--r--arch/x86/kvm/x86.c6
7 files changed, 48 insertions, 10 deletions
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index a1319c82050e..0b2729bf2070 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -230,6 +230,7 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt,
230 struct x86_emulate_ops *ops); 230 struct x86_emulate_ops *ops);
231int emulator_task_switch(struct x86_emulate_ctxt *ctxt, 231int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
232 struct x86_emulate_ops *ops, 232 struct x86_emulate_ops *ops,
233 u16 tss_selector, int reason); 233 u16 tss_selector, int reason,
234 bool has_error_code, u32 error_code);
234 235
235#endif /* _ASM_X86_KVM_X86_EMULATE_H */ 236#endif /* _ASM_X86_KVM_X86_EMULATE_H */
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 5d5e0a9afcf2..3602728d54de 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -595,7 +595,8 @@ int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr,
595void kvm_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg); 595void kvm_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
596int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, int seg); 596int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, int seg);
597 597
598int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason); 598int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason,
599 bool has_error_code, u32 error_code);
599 600
600void kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0); 601void kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
601void kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3); 602void kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3);
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index 1d91d05f9368..0e831059ac5a 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -244,6 +244,7 @@ struct __attribute__ ((__packed__)) vmcb {
244 244
245#define SVM_EXITINFOSHIFT_TS_REASON_IRET 36 245#define SVM_EXITINFOSHIFT_TS_REASON_IRET 36
246#define SVM_EXITINFOSHIFT_TS_REASON_JMP 38 246#define SVM_EXITINFOSHIFT_TS_REASON_JMP 38
247#define SVM_EXITINFOSHIFT_TS_HAS_ERROR_CODE 44
247 248
248#define SVM_EXIT_READ_CR0 0x000 249#define SVM_EXIT_READ_CR0 0x000
249#define SVM_EXIT_READ_CR3 0x003 250#define SVM_EXIT_READ_CR3 0x003
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index aace5659bbe0..585d0ef4a5f6 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -2344,8 +2344,9 @@ static int task_switch_32(struct x86_emulate_ctxt *ctxt,
2344} 2344}
2345 2345
2346static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt, 2346static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
2347 struct x86_emulate_ops *ops, 2347 struct x86_emulate_ops *ops,
2348 u16 tss_selector, int reason) 2348 u16 tss_selector, int reason,
2349 bool has_error_code, u32 error_code)
2349{ 2350{
2350 struct desc_struct curr_tss_desc, next_tss_desc; 2351 struct desc_struct curr_tss_desc, next_tss_desc;
2351 int ret; 2352 int ret;
@@ -2418,12 +2419,22 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
2418 ops->set_cached_descriptor(&next_tss_desc, VCPU_SREG_TR, ctxt->vcpu); 2419 ops->set_cached_descriptor(&next_tss_desc, VCPU_SREG_TR, ctxt->vcpu);
2419 ops->set_segment_selector(tss_selector, VCPU_SREG_TR, ctxt->vcpu); 2420 ops->set_segment_selector(tss_selector, VCPU_SREG_TR, ctxt->vcpu);
2420 2421
2422 if (has_error_code) {
2423 struct decode_cache *c = &ctxt->decode;
2424
2425 c->op_bytes = c->ad_bytes = (next_tss_desc.type & 8) ? 4 : 2;
2426 c->lock_prefix = 0;
2427 c->src.val = (unsigned long) error_code;
2428 emulate_push(ctxt);
2429 }
2430
2421 return ret; 2431 return ret;
2422} 2432}
2423 2433
2424int emulator_task_switch(struct x86_emulate_ctxt *ctxt, 2434int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
2425 struct x86_emulate_ops *ops, 2435 struct x86_emulate_ops *ops,
2426 u16 tss_selector, int reason) 2436 u16 tss_selector, int reason,
2437 bool has_error_code, u32 error_code)
2427{ 2438{
2428 struct decode_cache *c = &ctxt->decode; 2439 struct decode_cache *c = &ctxt->decode;
2429 int rc; 2440 int rc;
@@ -2431,12 +2442,15 @@ int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
2431 memset(c, 0, sizeof(struct decode_cache)); 2442 memset(c, 0, sizeof(struct decode_cache));
2432 c->eip = ctxt->eip; 2443 c->eip = ctxt->eip;
2433 memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs); 2444 memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs);
2445 c->dst.type = OP_NONE;
2434 2446
2435 rc = emulator_do_task_switch(ctxt, ops, tss_selector, reason); 2447 rc = emulator_do_task_switch(ctxt, ops, tss_selector, reason,
2448 has_error_code, error_code);
2436 2449
2437 if (rc == X86EMUL_CONTINUE) { 2450 if (rc == X86EMUL_CONTINUE) {
2438 memcpy(ctxt->vcpu->arch.regs, c->regs, sizeof c->regs); 2451 memcpy(ctxt->vcpu->arch.regs, c->regs, sizeof c->regs);
2439 kvm_rip_write(ctxt->vcpu, c->eip); 2452 kvm_rip_write(ctxt->vcpu, c->eip);
2453 rc = writeback(ctxt, ops);
2440 } 2454 }
2441 2455
2442 return rc; 2456 return rc;
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 87b36fbbfec8..78af52222fd2 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2222,6 +2222,8 @@ static int task_switch_interception(struct vcpu_svm *svm)
2222 svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_TYPE_MASK; 2222 svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_TYPE_MASK;
2223 uint32_t idt_v = 2223 uint32_t idt_v =
2224 svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID; 2224 svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID;
2225 bool has_error_code = false;
2226 u32 error_code = 0;
2225 2227
2226 tss_selector = (u16)svm->vmcb->control.exit_info_1; 2228 tss_selector = (u16)svm->vmcb->control.exit_info_1;
2227 2229
@@ -2242,6 +2244,12 @@ static int task_switch_interception(struct vcpu_svm *svm)
2242 svm->vcpu.arch.nmi_injected = false; 2244 svm->vcpu.arch.nmi_injected = false;
2243 break; 2245 break;
2244 case SVM_EXITINTINFO_TYPE_EXEPT: 2246 case SVM_EXITINTINFO_TYPE_EXEPT:
2247 if (svm->vmcb->control.exit_info_2 &
2248 (1ULL << SVM_EXITINFOSHIFT_TS_HAS_ERROR_CODE)) {
2249 has_error_code = true;
2250 error_code =
2251 (u32)svm->vmcb->control.exit_info_2;
2252 }
2245 kvm_clear_exception_queue(&svm->vcpu); 2253 kvm_clear_exception_queue(&svm->vcpu);
2246 break; 2254 break;
2247 case SVM_EXITINTINFO_TYPE_INTR: 2255 case SVM_EXITINTINFO_TYPE_INTR:
@@ -2258,7 +2266,8 @@ static int task_switch_interception(struct vcpu_svm *svm)
2258 (int_vec == OF_VECTOR || int_vec == BP_VECTOR))) 2266 (int_vec == OF_VECTOR || int_vec == BP_VECTOR)))
2259 skip_emulated_instruction(&svm->vcpu); 2267 skip_emulated_instruction(&svm->vcpu);
2260 2268
2261 return kvm_task_switch(&svm->vcpu, tss_selector, reason); 2269 return kvm_task_switch(&svm->vcpu, tss_selector, reason,
2270 has_error_code, error_code);
2262} 2271}
2263 2272
2264static int cpuid_interception(struct vcpu_svm *svm) 2273static int cpuid_interception(struct vcpu_svm *svm)
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 */
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 40991527f54a..58a295c6bf62 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4778,7 +4778,8 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
4778 return 0; 4778 return 0;
4779} 4779}
4780 4780
4781int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason) 4781int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason,
4782 bool has_error_code, u32 error_code)
4782{ 4783{
4783 int cs_db, cs_l, ret; 4784 int cs_db, cs_l, ret;
4784 cache_all_regs(vcpu); 4785 cache_all_regs(vcpu);
@@ -4796,7 +4797,8 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason)
4796 ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; 4797 ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
4797 4798
4798 ret = emulator_task_switch(&vcpu->arch.emulate_ctxt, &emulate_ops, 4799 ret = emulator_task_switch(&vcpu->arch.emulate_ctxt, &emulate_ops,
4799 tss_selector, reason); 4800 tss_selector, reason, has_error_code,
4801 error_code);
4800 4802
4801 if (ret == X86EMUL_CONTINUE) 4803 if (ret == X86EMUL_CONTINUE)
4802 kvm_x86_ops->set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags); 4804 kvm_x86_ops->set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags);