aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/emulate.c
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2011-04-04 06:39:28 -0400
committerAvi Kivity <avi@redhat.com>2011-05-11 07:57:01 -0400
commitcfec82cb7d313ae5b2c2dbb974401d7c214c7b09 (patch)
tree63351befc6b9981127ac8dd2d22149d3ddf75806 /arch/x86/kvm/emulate.c
parent8a76d7f25f8f24fc5a328c8e15e4a7313cf141b9 (diff)
KVM: SVM: Add intercept check for emulated cr accesses
This patch adds all necessary intercept checks for instructions that access the crX 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.c105
1 files changed, 94 insertions, 11 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index e3e96eada6f3..d2e77755efe8 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -2445,6 +2445,95 @@ static int em_movdqu(struct x86_emulate_ctxt *ctxt)
2445 return X86EMUL_CONTINUE; 2445 return X86EMUL_CONTINUE;
2446} 2446}
2447 2447
2448static bool valid_cr(int nr)
2449{
2450 switch (nr) {
2451 case 0:
2452 case 2 ... 4:
2453 case 8:
2454 return true;
2455 default:
2456 return false;
2457 }
2458}
2459
2460static int check_cr_read(struct x86_emulate_ctxt *ctxt)
2461{
2462 struct decode_cache *c = &ctxt->decode;
2463
2464 if (!valid_cr(c->modrm_reg))
2465 return emulate_ud(ctxt);
2466
2467 return X86EMUL_CONTINUE;
2468}
2469
2470static int check_cr_write(struct x86_emulate_ctxt *ctxt)
2471{
2472 struct decode_cache *c = &ctxt->decode;
2473 u64 new_val = c->src.val64;
2474 int cr = c->modrm_reg;
2475
2476 static u64 cr_reserved_bits[] = {
2477 0xffffffff00000000ULL,
2478 0, 0, 0, /* CR3 checked later */
2479 CR4_RESERVED_BITS,
2480 0, 0, 0,
2481 CR8_RESERVED_BITS,
2482 };
2483
2484 if (!valid_cr(cr))
2485 return emulate_ud(ctxt);
2486
2487 if (new_val & cr_reserved_bits[cr])
2488 return emulate_gp(ctxt, 0);
2489
2490 switch (cr) {
2491 case 0: {
2492 u64 cr4, efer;
2493 if (((new_val & X86_CR0_PG) && !(new_val & X86_CR0_PE)) ||
2494 ((new_val & X86_CR0_NW) && !(new_val & X86_CR0_CD)))
2495 return emulate_gp(ctxt, 0);
2496
2497 cr4 = ctxt->ops->get_cr(4, ctxt->vcpu);
2498 ctxt->ops->get_msr(ctxt->vcpu, MSR_EFER, &efer);
2499
2500 if ((new_val & X86_CR0_PG) && (efer & EFER_LME) &&
2501 !(cr4 & X86_CR4_PAE))
2502 return emulate_gp(ctxt, 0);
2503
2504 break;
2505 }
2506 case 3: {
2507 u64 rsvd = 0;
2508
2509 if (is_long_mode(ctxt->vcpu))
2510 rsvd = CR3_L_MODE_RESERVED_BITS;
2511 else if (is_pae(ctxt->vcpu))
2512 rsvd = CR3_PAE_RESERVED_BITS;
2513 else if (is_paging(ctxt->vcpu))
2514 rsvd = CR3_NONPAE_RESERVED_BITS;
2515
2516 if (new_val & rsvd)
2517 return emulate_gp(ctxt, 0);
2518
2519 break;
2520 }
2521 case 4: {
2522 u64 cr4, efer;
2523
2524 cr4 = ctxt->ops->get_cr(4, ctxt->vcpu);
2525 ctxt->ops->get_msr(ctxt->vcpu, MSR_EFER, &efer);
2526
2527 if ((efer & EFER_LMA) && !(new_val & X86_CR4_PAE))
2528 return emulate_gp(ctxt, 0);
2529
2530 break;
2531 }
2532 }
2533
2534 return X86EMUL_CONTINUE;
2535}
2536
2448#define D(_y) { .flags = (_y) } 2537#define D(_y) { .flags = (_y) }
2449#define DI(_y, _i) { .flags = (_y), .intercept = x86_intercept_##_i } 2538#define DI(_y, _i) { .flags = (_y), .intercept = x86_intercept_##_i }
2450#define DIP(_y, _i, _p) { .flags = (_y), .intercept = x86_intercept_##_i, \ 2539#define DIP(_y, _i, _p) { .flags = (_y), .intercept = x86_intercept_##_i, \
@@ -2632,14 +2721,16 @@ static struct opcode opcode_table[256] = {
2632static struct opcode twobyte_table[256] = { 2721static struct opcode twobyte_table[256] = {
2633 /* 0x00 - 0x0F */ 2722 /* 0x00 - 0x0F */
2634 N, GD(0, &group7), N, N, 2723 N, GD(0, &group7), N, N,
2635 N, D(ImplicitOps | VendorSpecific), D(ImplicitOps | Priv), N, 2724 N, D(ImplicitOps | VendorSpecific), DI(ImplicitOps | Priv, clts), N,
2636 DI(ImplicitOps | Priv, invd), DI(ImplicitOps | Priv, wbinvd), N, N, 2725 DI(ImplicitOps | Priv, invd), DI(ImplicitOps | Priv, wbinvd), N, N,
2637 N, D(ImplicitOps | ModRM), N, N, 2726 N, D(ImplicitOps | ModRM), N, N,
2638 /* 0x10 - 0x1F */ 2727 /* 0x10 - 0x1F */
2639 N, N, N, N, N, N, N, N, D(ImplicitOps | ModRM), N, N, N, N, N, N, N, 2728 N, N, N, N, N, N, N, N, D(ImplicitOps | ModRM), N, N, N, N, N, N, N,
2640 /* 0x20 - 0x2F */ 2729 /* 0x20 - 0x2F */
2641 D(ModRM | DstMem | Priv | Op3264), D(ModRM | DstMem | Priv | Op3264), 2730 DIP(ModRM | DstMem | Priv | Op3264, cr_read, check_cr_read),
2642 D(ModRM | SrcMem | Priv | Op3264), D(ModRM | SrcMem | Priv | Op3264), 2731 D(ModRM | DstMem | Priv | Op3264),
2732 DIP(ModRM | SrcMem | Priv | Op3264, cr_write, check_cr_write),
2733 D(ModRM | SrcMem | Priv | Op3264),
2643 N, N, N, N, 2734 N, N, N, N,
2644 N, N, N, N, N, N, N, N, 2735 N, N, N, N, N, N, N, N,
2645 /* 0x30 - 0x3F */ 2736 /* 0x30 - 0x3F */
@@ -3724,14 +3815,6 @@ twobyte_insn:
3724 case 0x18: /* Grp16 (prefetch/nop) */ 3815 case 0x18: /* Grp16 (prefetch/nop) */
3725 break; 3816 break;
3726 case 0x20: /* mov cr, reg */ 3817 case 0x20: /* mov cr, reg */
3727 switch (c->modrm_reg) {
3728 case 1:
3729 case 5 ... 7:
3730 case 9 ... 15:
3731 emulate_ud(ctxt);
3732 rc = X86EMUL_PROPAGATE_FAULT;
3733 goto done;
3734 }
3735 c->dst.val = ops->get_cr(c->modrm_reg, ctxt->vcpu); 3818 c->dst.val = ops->get_cr(c->modrm_reg, ctxt->vcpu);
3736 break; 3819 break;
3737 case 0x21: /* mov from dr to reg */ 3820 case 0x21: /* mov from dr to reg */