aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/emulate.c
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@siemens.com>2010-04-14 09:51:09 -0400
committerAvi Kivity <avi@redhat.com>2010-05-17 05:17:46 -0400
commite269fb2189fb86d79d64c0ca74c6c1a549ad4aa3 (patch)
tree627c658efaec155d1f295d1fc7b8abded9d4f861 /arch/x86/kvm/emulate.c
parent0760d44868f351ba30fc9a08cf1830e46aa72466 (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/emulate.c')
-rw-r--r--arch/x86/kvm/emulate.c22
1 files changed, 18 insertions, 4 deletions
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;