aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2010-11-22 10:53:21 -0500
committerAvi Kivity <avi@redhat.com>2011-01-12 04:29:53 -0500
commitda9cb575b1127f84984b8ad6d973dcc05ac036dd (patch)
treee0269a888731c630c9b64693b21d24b2821da362 /arch
parenta4ee1ca4a36e7857d90ae8c2b85f1bde9a042c10 (diff)
KVM: x86 emulator: introduce struct x86_exception to communicate faults
Introduce a structure that can contain an exception to be passed back to main kvm code. Signed-off-by: Avi Kivity <avi@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/kvm_emulate.h11
-rw-r--r--arch/x86/kvm/emulate.c26
-rw-r--r--arch/x86/kvm/x86.c13
3 files changed, 38 insertions, 12 deletions
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index b48c133c95ab..b7c11270ae8f 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -15,6 +15,12 @@
15 15
16struct x86_emulate_ctxt; 16struct x86_emulate_ctxt;
17 17
18struct x86_exception {
19 u8 vector;
20 bool error_code_valid;
21 u16 error_code;
22};
23
18/* 24/*
19 * x86_emulate_ops: 25 * x86_emulate_ops:
20 * 26 *
@@ -229,9 +235,8 @@ struct x86_emulate_ctxt {
229 235
230 bool perm_ok; /* do not check permissions if true */ 236 bool perm_ok; /* do not check permissions if true */
231 237
232 int exception; /* exception that happens during emulation or -1 */ 238 bool have_exception;
233 u32 error_code; /* error code for exception */ 239 struct x86_exception exception;
234 bool error_code_valid;
235 240
236 /* decode cache */ 241 /* decode cache */
237 struct decode_cache decode; 242 struct decode_cache decode;
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index bdbbb1839e89..18596e6649aa 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -469,9 +469,9 @@ static ulong linear(struct x86_emulate_ctxt *ctxt,
469static void emulate_exception(struct x86_emulate_ctxt *ctxt, int vec, 469static void emulate_exception(struct x86_emulate_ctxt *ctxt, int vec,
470 u32 error, bool valid) 470 u32 error, bool valid)
471{ 471{
472 ctxt->exception = vec; 472 ctxt->exception.vector = vec;
473 ctxt->error_code = error; 473 ctxt->exception.error_code = error;
474 ctxt->error_code_valid = valid; 474 ctxt->exception.error_code_valid = valid;
475} 475}
476 476
477static void emulate_gp(struct x86_emulate_ctxt *ctxt, int err) 477static void emulate_gp(struct x86_emulate_ctxt *ctxt, int err)
@@ -3015,23 +3015,27 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
3015 3015
3016 if (ctxt->mode == X86EMUL_MODE_PROT64 && (c->d & No64)) { 3016 if (ctxt->mode == X86EMUL_MODE_PROT64 && (c->d & No64)) {
3017 emulate_ud(ctxt); 3017 emulate_ud(ctxt);
3018 rc = X86EMUL_PROPAGATE_FAULT;
3018 goto done; 3019 goto done;
3019 } 3020 }
3020 3021
3021 /* LOCK prefix is allowed only with some instructions */ 3022 /* LOCK prefix is allowed only with some instructions */
3022 if (c->lock_prefix && (!(c->d & Lock) || c->dst.type != OP_MEM)) { 3023 if (c->lock_prefix && (!(c->d & Lock) || c->dst.type != OP_MEM)) {
3023 emulate_ud(ctxt); 3024 emulate_ud(ctxt);
3025 rc = X86EMUL_PROPAGATE_FAULT;
3024 goto done; 3026 goto done;
3025 } 3027 }
3026 3028
3027 if ((c->d & SrcMask) == SrcMemFAddr && c->src.type != OP_MEM) { 3029 if ((c->d & SrcMask) == SrcMemFAddr && c->src.type != OP_MEM) {
3028 emulate_ud(ctxt); 3030 emulate_ud(ctxt);
3031 rc = X86EMUL_PROPAGATE_FAULT;
3029 goto done; 3032 goto done;
3030 } 3033 }
3031 3034
3032 /* Privileged instruction can be executed only in CPL=0 */ 3035 /* Privileged instruction can be executed only in CPL=0 */
3033 if ((c->d & Priv) && ops->cpl(ctxt->vcpu)) { 3036 if ((c->d & Priv) && ops->cpl(ctxt->vcpu)) {
3034 emulate_gp(ctxt, 0); 3037 emulate_gp(ctxt, 0);
3038 rc = X86EMUL_PROPAGATE_FAULT;
3035 goto done; 3039 goto done;
3036 } 3040 }
3037 3041
@@ -3210,6 +3214,7 @@ special_insn:
3210 case 0x8c: /* mov r/m, sreg */ 3214 case 0x8c: /* mov r/m, sreg */
3211 if (c->modrm_reg > VCPU_SREG_GS) { 3215 if (c->modrm_reg > VCPU_SREG_GS) {
3212 emulate_ud(ctxt); 3216 emulate_ud(ctxt);
3217 rc = X86EMUL_PROPAGATE_FAULT;
3213 goto done; 3218 goto done;
3214 } 3219 }
3215 c->dst.val = ops->get_segment_selector(c->modrm_reg, ctxt->vcpu); 3220 c->dst.val = ops->get_segment_selector(c->modrm_reg, ctxt->vcpu);
@@ -3225,6 +3230,7 @@ special_insn:
3225 if (c->modrm_reg == VCPU_SREG_CS || 3230 if (c->modrm_reg == VCPU_SREG_CS ||
3226 c->modrm_reg > VCPU_SREG_GS) { 3231 c->modrm_reg > VCPU_SREG_GS) {
3227 emulate_ud(ctxt); 3232 emulate_ud(ctxt);
3233 rc = X86EMUL_PROPAGATE_FAULT;
3228 goto done; 3234 goto done;
3229 } 3235 }
3230 3236
@@ -3357,6 +3363,7 @@ special_insn:
3357 c->dst.bytes = min(c->dst.bytes, 4u); 3363 c->dst.bytes = min(c->dst.bytes, 4u);
3358 if (!emulator_io_permited(ctxt, ops, c->src.val, c->dst.bytes)) { 3364 if (!emulator_io_permited(ctxt, ops, c->src.val, c->dst.bytes)) {
3359 emulate_gp(ctxt, 0); 3365 emulate_gp(ctxt, 0);
3366 rc = X86EMUL_PROPAGATE_FAULT;
3360 goto done; 3367 goto done;
3361 } 3368 }
3362 if (!pio_in_emulated(ctxt, ops, c->dst.bytes, c->src.val, 3369 if (!pio_in_emulated(ctxt, ops, c->dst.bytes, c->src.val,
@@ -3371,6 +3378,7 @@ special_insn:
3371 if (!emulator_io_permited(ctxt, ops, c->dst.val, 3378 if (!emulator_io_permited(ctxt, ops, c->dst.val,
3372 c->src.bytes)) { 3379 c->src.bytes)) {
3373 emulate_gp(ctxt, 0); 3380 emulate_gp(ctxt, 0);
3381 rc = X86EMUL_PROPAGATE_FAULT;
3374 goto done; 3382 goto done;
3375 } 3383 }
3376 ops->pio_out_emulated(c->src.bytes, c->dst.val, 3384 ops->pio_out_emulated(c->src.bytes, c->dst.val,
@@ -3396,6 +3404,7 @@ special_insn:
3396 case 0xfa: /* cli */ 3404 case 0xfa: /* cli */
3397 if (emulator_bad_iopl(ctxt, ops)) { 3405 if (emulator_bad_iopl(ctxt, ops)) {
3398 emulate_gp(ctxt, 0); 3406 emulate_gp(ctxt, 0);
3407 rc = X86EMUL_PROPAGATE_FAULT;
3399 goto done; 3408 goto done;
3400 } else 3409 } else
3401 ctxt->eflags &= ~X86_EFLAGS_IF; 3410 ctxt->eflags &= ~X86_EFLAGS_IF;
@@ -3403,6 +3412,7 @@ special_insn:
3403 case 0xfb: /* sti */ 3412 case 0xfb: /* sti */
3404 if (emulator_bad_iopl(ctxt, ops)) { 3413 if (emulator_bad_iopl(ctxt, ops)) {
3405 emulate_gp(ctxt, 0); 3414 emulate_gp(ctxt, 0);
3415 rc = X86EMUL_PROPAGATE_FAULT;
3406 goto done; 3416 goto done;
3407 } else { 3417 } else {
3408 ctxt->interruptibility = KVM_X86_SHADOW_INT_STI; 3418 ctxt->interruptibility = KVM_X86_SHADOW_INT_STI;
@@ -3475,6 +3485,8 @@ writeback:
3475 ctxt->eip = c->eip; 3485 ctxt->eip = c->eip;
3476 3486
3477done: 3487done:
3488 if (rc == X86EMUL_PROPAGATE_FAULT)
3489 ctxt->have_exception = true;
3478 return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK; 3490 return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK;
3479 3491
3480twobyte_insn: 3492twobyte_insn:
@@ -3537,6 +3549,7 @@ twobyte_insn:
3537 break; 3549 break;
3538 case 5: /* not defined */ 3550 case 5: /* not defined */
3539 emulate_ud(ctxt); 3551 emulate_ud(ctxt);
3552 rc = X86EMUL_PROPAGATE_FAULT;
3540 goto done; 3553 goto done;
3541 case 7: /* invlpg*/ 3554 case 7: /* invlpg*/
3542 emulate_invlpg(ctxt->vcpu, 3555 emulate_invlpg(ctxt->vcpu,
@@ -3567,6 +3580,7 @@ twobyte_insn:
3567 case 5 ... 7: 3580 case 5 ... 7:
3568 case 9 ... 15: 3581 case 9 ... 15:
3569 emulate_ud(ctxt); 3582 emulate_ud(ctxt);
3583 rc = X86EMUL_PROPAGATE_FAULT;
3570 goto done; 3584 goto done;
3571 } 3585 }
3572 c->dst.val = ops->get_cr(c->modrm_reg, ctxt->vcpu); 3586 c->dst.val = ops->get_cr(c->modrm_reg, ctxt->vcpu);
@@ -3575,6 +3589,7 @@ twobyte_insn:
3575 if ((ops->get_cr(4, ctxt->vcpu) & X86_CR4_DE) && 3589 if ((ops->get_cr(4, ctxt->vcpu) & X86_CR4_DE) &&
3576 (c->modrm_reg == 4 || c->modrm_reg == 5)) { 3590 (c->modrm_reg == 4 || c->modrm_reg == 5)) {
3577 emulate_ud(ctxt); 3591 emulate_ud(ctxt);
3592 rc = X86EMUL_PROPAGATE_FAULT;
3578 goto done; 3593 goto done;
3579 } 3594 }
3580 ops->get_dr(c->modrm_reg, &c->dst.val, ctxt->vcpu); 3595 ops->get_dr(c->modrm_reg, &c->dst.val, ctxt->vcpu);
@@ -3582,6 +3597,7 @@ twobyte_insn:
3582 case 0x22: /* mov reg, cr */ 3597 case 0x22: /* mov reg, cr */
3583 if (ops->set_cr(c->modrm_reg, c->src.val, ctxt->vcpu)) { 3598 if (ops->set_cr(c->modrm_reg, c->src.val, ctxt->vcpu)) {
3584 emulate_gp(ctxt, 0); 3599 emulate_gp(ctxt, 0);
3600 rc = X86EMUL_PROPAGATE_FAULT;
3585 goto done; 3601 goto done;
3586 } 3602 }
3587 c->dst.type = OP_NONE; 3603 c->dst.type = OP_NONE;
@@ -3590,6 +3606,7 @@ twobyte_insn:
3590 if ((ops->get_cr(4, ctxt->vcpu) & X86_CR4_DE) && 3606 if ((ops->get_cr(4, ctxt->vcpu) & X86_CR4_DE) &&
3591 (c->modrm_reg == 4 || c->modrm_reg == 5)) { 3607 (c->modrm_reg == 4 || c->modrm_reg == 5)) {
3592 emulate_ud(ctxt); 3608 emulate_ud(ctxt);
3609 rc = X86EMUL_PROPAGATE_FAULT;
3593 goto done; 3610 goto done;
3594 } 3611 }
3595 3612
@@ -3598,6 +3615,7 @@ twobyte_insn:
3598 ~0ULL : ~0U), ctxt->vcpu) < 0) { 3615 ~0ULL : ~0U), ctxt->vcpu) < 0) {
3599 /* #UD condition is already handled by the code above */ 3616 /* #UD condition is already handled by the code above */
3600 emulate_gp(ctxt, 0); 3617 emulate_gp(ctxt, 0);
3618 rc = X86EMUL_PROPAGATE_FAULT;
3601 goto done; 3619 goto done;
3602 } 3620 }
3603 3621
@@ -3609,6 +3627,7 @@ twobyte_insn:
3609 | ((u64)c->regs[VCPU_REGS_RDX] << 32); 3627 | ((u64)c->regs[VCPU_REGS_RDX] << 32);
3610 if (ops->set_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], msr_data)) { 3628 if (ops->set_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], msr_data)) {
3611 emulate_gp(ctxt, 0); 3629 emulate_gp(ctxt, 0);
3630 rc = X86EMUL_PROPAGATE_FAULT;
3612 goto done; 3631 goto done;
3613 } 3632 }
3614 rc = X86EMUL_CONTINUE; 3633 rc = X86EMUL_CONTINUE;
@@ -3617,6 +3636,7 @@ twobyte_insn:
3617 /* rdmsr */ 3636 /* rdmsr */
3618 if (ops->get_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], &msr_data)) { 3637 if (ops->get_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], &msr_data)) {
3619 emulate_gp(ctxt, 0); 3638 emulate_gp(ctxt, 0);
3639 rc = X86EMUL_PROPAGATE_FAULT;
3620 goto done; 3640 goto done;
3621 } else { 3641 } else {
3622 c->regs[VCPU_REGS_RAX] = (u32)msr_data; 3642 c->regs[VCPU_REGS_RAX] = (u32)msr_data;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 651cf9004fbe..0c908321e900 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4254,12 +4254,13 @@ static void toggle_interruptibility(struct kvm_vcpu *vcpu, u32 mask)
4254static void inject_emulated_exception(struct kvm_vcpu *vcpu) 4254static void inject_emulated_exception(struct kvm_vcpu *vcpu)
4255{ 4255{
4256 struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt; 4256 struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
4257 if (ctxt->exception == PF_VECTOR) 4257 if (ctxt->exception.vector == PF_VECTOR)
4258 kvm_propagate_fault(vcpu); 4258 kvm_propagate_fault(vcpu);
4259 else if (ctxt->error_code_valid) 4259 else if (ctxt->exception.error_code_valid)
4260 kvm_queue_exception_e(vcpu, ctxt->exception, ctxt->error_code); 4260 kvm_queue_exception_e(vcpu, ctxt->exception.vector,
4261 ctxt->exception.error_code);
4261 else 4262 else
4262 kvm_queue_exception(vcpu, ctxt->exception); 4263 kvm_queue_exception(vcpu, ctxt->exception.vector);
4263} 4264}
4264 4265
4265static void init_emulate_ctxt(struct kvm_vcpu *vcpu) 4266static void init_emulate_ctxt(struct kvm_vcpu *vcpu)
@@ -4371,7 +4372,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
4371 if (!(emulation_type & EMULTYPE_NO_DECODE)) { 4372 if (!(emulation_type & EMULTYPE_NO_DECODE)) {
4372 init_emulate_ctxt(vcpu); 4373 init_emulate_ctxt(vcpu);
4373 vcpu->arch.emulate_ctxt.interruptibility = 0; 4374 vcpu->arch.emulate_ctxt.interruptibility = 0;
4374 vcpu->arch.emulate_ctxt.exception = -1; 4375 vcpu->arch.emulate_ctxt.have_exception = false;
4375 vcpu->arch.emulate_ctxt.perm_ok = false; 4376 vcpu->arch.emulate_ctxt.perm_ok = false;
4376 4377
4377 r = x86_decode_insn(&vcpu->arch.emulate_ctxt); 4378 r = x86_decode_insn(&vcpu->arch.emulate_ctxt);
@@ -4437,7 +4438,7 @@ restart:
4437 } 4438 }
4438 4439
4439done: 4440done:
4440 if (vcpu->arch.emulate_ctxt.exception >= 0) { 4441 if (vcpu->arch.emulate_ctxt.have_exception) {
4441 inject_emulated_exception(vcpu); 4442 inject_emulated_exception(vcpu);
4442 r = EMULATE_DONE; 4443 r = EMULATE_DONE;
4443 } else if (vcpu->arch.pio.count) { 4444 } else if (vcpu->arch.pio.count) {