aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/emulate.c
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2011-04-04 06:39:29 -0400
committerAvi Kivity <avi@redhat.com>2011-05-11 07:57:01 -0400
commit3b88e41a41344846ee28007ebfe1bb0defa7f86a (patch)
tree9c08334297bd05def6d3dffb1b947dd9b26b1ac5 /arch/x86/kvm/emulate.c
parentcfec82cb7d313ae5b2c2dbb974401d7c214c7b09 (diff)
KVM: SVM: Add intercept check for accessing dr registers
This patch adds the intercept checks for instruction accessing the debug registers. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r--arch/x86/kvm/emulate.c63
1 files changed, 48 insertions, 15 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index d2e77755efe8..cd9ed9f45275 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -509,6 +509,11 @@ static int emulate_exception(struct x86_emulate_ctxt *ctxt, int vec,
509 return X86EMUL_PROPAGATE_FAULT; 509 return X86EMUL_PROPAGATE_FAULT;
510} 510}
511 511
512static int emulate_db(struct x86_emulate_ctxt *ctxt)
513{
514 return emulate_exception(ctxt, DB_VECTOR, 0, false);
515}
516
512static int emulate_gp(struct x86_emulate_ctxt *ctxt, int err) 517static int emulate_gp(struct x86_emulate_ctxt *ctxt, int err)
513{ 518{
514 return emulate_exception(ctxt, GP_VECTOR, err, true); 519 return emulate_exception(ctxt, GP_VECTOR, err, true);
@@ -2534,6 +2539,47 @@ static int check_cr_write(struct x86_emulate_ctxt *ctxt)
2534 return X86EMUL_CONTINUE; 2539 return X86EMUL_CONTINUE;
2535} 2540}
2536 2541
2542static int check_dr7_gd(struct x86_emulate_ctxt *ctxt)
2543{
2544 unsigned long dr7;
2545
2546 ctxt->ops->get_dr(7, &dr7, ctxt->vcpu);
2547
2548 /* Check if DR7.Global_Enable is set */
2549 return dr7 & (1 << 13);
2550}
2551
2552static int check_dr_read(struct x86_emulate_ctxt *ctxt)
2553{
2554 struct decode_cache *c = &ctxt->decode;
2555 int dr = c->modrm_reg;
2556 u64 cr4;
2557
2558 if (dr > 7)
2559 return emulate_ud(ctxt);
2560
2561 cr4 = ctxt->ops->get_cr(4, ctxt->vcpu);
2562 if ((cr4 & X86_CR4_DE) && (dr == 4 || dr == 5))
2563 return emulate_ud(ctxt);
2564
2565 if (check_dr7_gd(ctxt))
2566 return emulate_db(ctxt);
2567
2568 return X86EMUL_CONTINUE;
2569}
2570
2571static int check_dr_write(struct x86_emulate_ctxt *ctxt)
2572{
2573 struct decode_cache *c = &ctxt->decode;
2574 u64 new_val = c->src.val64;
2575 int dr = c->modrm_reg;
2576
2577 if ((dr == 6 || dr == 7) && (new_val & 0xffffffff00000000ULL))
2578 return emulate_gp(ctxt, 0);
2579
2580 return check_dr_read(ctxt);
2581}
2582
2537#define D(_y) { .flags = (_y) } 2583#define D(_y) { .flags = (_y) }
2538#define DI(_y, _i) { .flags = (_y), .intercept = x86_intercept_##_i } 2584#define DI(_y, _i) { .flags = (_y), .intercept = x86_intercept_##_i }
2539#define DIP(_y, _i, _p) { .flags = (_y), .intercept = x86_intercept_##_i, \ 2585#define DIP(_y, _i, _p) { .flags = (_y), .intercept = x86_intercept_##_i, \
@@ -2728,9 +2774,9 @@ static struct opcode twobyte_table[256] = {
2728 N, N, N, N, N, N, N, N, D(ImplicitOps | ModRM), N, N, N, N, N, N, N, 2774 N, N, N, N, N, N, N, N, D(ImplicitOps | ModRM), N, N, N, N, N, N, N,
2729 /* 0x20 - 0x2F */ 2775 /* 0x20 - 0x2F */
2730 DIP(ModRM | DstMem | Priv | Op3264, cr_read, check_cr_read), 2776 DIP(ModRM | DstMem | Priv | Op3264, cr_read, check_cr_read),
2731 D(ModRM | DstMem | Priv | Op3264), 2777 DIP(ModRM | DstMem | Priv | Op3264, dr_read, check_dr_read),
2732 DIP(ModRM | SrcMem | Priv | Op3264, cr_write, check_cr_write), 2778 DIP(ModRM | SrcMem | Priv | Op3264, cr_write, check_cr_write),
2733 D(ModRM | SrcMem | Priv | Op3264), 2779 DIP(ModRM | SrcMem | Priv | Op3264, dr_write, check_dr_write),
2734 N, N, N, N, 2780 N, N, N, N,
2735 N, N, N, N, N, N, N, N, 2781 N, N, N, N, N, N, N, N,
2736 /* 0x30 - 0x3F */ 2782 /* 0x30 - 0x3F */
@@ -3818,12 +3864,6 @@ twobyte_insn:
3818 c->dst.val = ops->get_cr(c->modrm_reg, ctxt->vcpu); 3864 c->dst.val = ops->get_cr(c->modrm_reg, ctxt->vcpu);
3819 break; 3865 break;
3820 case 0x21: /* mov from dr to reg */ 3866 case 0x21: /* mov from dr to reg */
3821 if ((ops->get_cr(4, ctxt->vcpu) & X86_CR4_DE) &&
3822 (c->modrm_reg == 4 || c->modrm_reg == 5)) {
3823 emulate_ud(ctxt);
3824 rc = X86EMUL_PROPAGATE_FAULT;
3825 goto done;
3826 }
3827 ops->get_dr(c->modrm_reg, &c->dst.val, ctxt->vcpu); 3867 ops->get_dr(c->modrm_reg, &c->dst.val, ctxt->vcpu);
3828 break; 3868 break;
3829 case 0x22: /* mov reg, cr */ 3869 case 0x22: /* mov reg, cr */
@@ -3835,13 +3875,6 @@ twobyte_insn:
3835 c->dst.type = OP_NONE; 3875 c->dst.type = OP_NONE;
3836 break; 3876 break;
3837 case 0x23: /* mov from reg to dr */ 3877 case 0x23: /* mov from reg to dr */
3838 if ((ops->get_cr(4, ctxt->vcpu) & X86_CR4_DE) &&
3839 (c->modrm_reg == 4 || c->modrm_reg == 5)) {
3840 emulate_ud(ctxt);
3841 rc = X86EMUL_PROPAGATE_FAULT;
3842 goto done;
3843 }
3844
3845 if (ops->set_dr(c->modrm_reg, c->src.val & 3878 if (ops->set_dr(c->modrm_reg, c->src.val &
3846 ((ctxt->mode == X86EMUL_MODE_PROT64) ? 3879 ((ctxt->mode == X86EMUL_MODE_PROT64) ?
3847 ~0ULL : ~0U), ctxt->vcpu) < 0) { 3880 ~0ULL : ~0U), ctxt->vcpu) < 0) {