Skip to content

Commit

Permalink
KVM: SVM: Add intercept checks for remaining twobyte instructions
Browse files Browse the repository at this point in the history
This patch adds intercepts checks for the remaining twobyte
instructions to the KVM instruction emulator.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
  • Loading branch information
Joerg Roedel authored and Avi Kivity committed May 11, 2011
1 parent d7eb820 commit 8061252
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 7 deletions.
2 changes: 2 additions & 0 deletions arch/x86/include/asm/kvm_emulate.h
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,8 @@ enum x86_intercept {
x86_intercept_wbinvd,
x86_intercept_monitor,
x86_intercept_mwait,
x86_intercept_rdmsr,
x86_intercept_wrmsr,

nr_x86_intercepts
};
Expand Down
25 changes: 18 additions & 7 deletions arch/x86/kvm/emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -2425,12 +2425,9 @@ static int em_cwd(struct x86_emulate_ctxt *ctxt)

static int em_rdtsc(struct x86_emulate_ctxt *ctxt)
{
unsigned cpl = ctxt->ops->cpl(ctxt->vcpu);
struct decode_cache *c = &ctxt->decode;
u64 tsc = 0;

if (cpl > 0 && (ctxt->ops->get_cr(4, ctxt->vcpu) & X86_CR4_TSD))
return emulate_gp(ctxt, 0);
ctxt->ops->get_msr(ctxt->vcpu, MSR_IA32_TSC, &tsc);
c->regs[VCPU_REGS_RAX] = (u32)tsc;
c->regs[VCPU_REGS_RDX] = tsc >> 32;
Expand Down Expand Up @@ -2614,6 +2611,18 @@ static int check_rdtsc(struct x86_emulate_ctxt *ctxt)
return X86EMUL_CONTINUE;
}

static int check_rdpmc(struct x86_emulate_ctxt *ctxt)
{
u64 cr4 = ctxt->ops->get_cr(4, ctxt->vcpu);
u64 rcx = kvm_register_read(ctxt->vcpu, VCPU_REGS_RCX);

if ((!(cr4 & X86_CR4_PCE) && ctxt->ops->cpl(ctxt->vcpu)) ||
(rcx > 3))
return emulate_gp(ctxt, 0);

return X86EMUL_CONTINUE;
}

#define D(_y) { .flags = (_y) }
#define DI(_y, _i) { .flags = (_y), .intercept = x86_intercept_##_i }
#define DIP(_y, _i, _p) { .flags = (_y), .intercept = x86_intercept_##_i, \
Expand Down Expand Up @@ -2846,8 +2855,10 @@ static struct opcode twobyte_table[256] = {
N, N, N, N,
N, N, N, N, N, N, N, N,
/* 0x30 - 0x3F */
D(ImplicitOps | Priv), II(ImplicitOps, em_rdtsc, rdtsc),
D(ImplicitOps | Priv), N,
DI(ImplicitOps | Priv, wrmsr),
IIP(ImplicitOps, em_rdtsc, rdtsc, check_rdtsc),
DI(ImplicitOps | Priv, rdmsr),
DIP(ImplicitOps | Priv, rdpmc, check_rdpmc),
D(ImplicitOps | VendorSpecific), D(ImplicitOps | Priv | VendorSpecific),
N, N,
N, N, N, N, N, N, N, N,
Expand All @@ -2871,12 +2882,12 @@ static struct opcode twobyte_table[256] = {
X16(D(ByteOp | DstMem | SrcNone | ModRM| Mov)),
/* 0xA0 - 0xA7 */
D(ImplicitOps | Stack), D(ImplicitOps | Stack),
N, D(DstMem | SrcReg | ModRM | BitOp),
DI(ImplicitOps, cpuid), D(DstMem | SrcReg | ModRM | BitOp),
D(DstMem | SrcReg | Src2ImmByte | ModRM),
D(DstMem | SrcReg | Src2CL | ModRM), N, N,
/* 0xA8 - 0xAF */
D(ImplicitOps | Stack), D(ImplicitOps | Stack),
N, D(DstMem | SrcReg | ModRM | BitOp | Lock),
DI(ImplicitOps, rsm), D(DstMem | SrcReg | ModRM | BitOp | Lock),
D(DstMem | SrcReg | Src2ImmByte | ModRM),
D(DstMem | SrcReg | Src2CL | ModRM),
D(ModRM), I(DstReg | SrcMem | ModRM, em_imul),
Expand Down
19 changes: 19 additions & 0 deletions arch/x86/kvm/svm.c
Original file line number Diff line number Diff line change
Expand Up @@ -3868,6 +3868,9 @@ static void svm_fpu_deactivate(struct kvm_vcpu *vcpu)
update_cr0_intercept(svm);
}

#define PRE_EX(exit) { .exit_code = (exit), \
.stage = X86_ICPT_PRE_EXCEPT, \
.valid = true }
#define POST_EX(exit) { .exit_code = (exit), \
.stage = X86_ICPT_POST_EXCEPT, \
.valid = true }
Expand Down Expand Up @@ -3906,8 +3909,18 @@ static struct __x86_intercept {
[x86_intercept_rdtscp] = POST_EX(SVM_EXIT_RDTSCP),
[x86_intercept_monitor] = POST_MEM(SVM_EXIT_MONITOR),
[x86_intercept_mwait] = POST_EX(SVM_EXIT_MWAIT),
[x86_intercept_invlpg] = POST_EX(SVM_EXIT_INVLPG),
[x86_intercept_invd] = POST_EX(SVM_EXIT_INVD),
[x86_intercept_wbinvd] = POST_EX(SVM_EXIT_WBINVD),
[x86_intercept_wrmsr] = POST_EX(SVM_EXIT_MSR),
[x86_intercept_rdtsc] = POST_EX(SVM_EXIT_RDTSC),
[x86_intercept_rdmsr] = POST_EX(SVM_EXIT_MSR),
[x86_intercept_rdpmc] = POST_EX(SVM_EXIT_RDPMC),
[x86_intercept_cpuid] = PRE_EX(SVM_EXIT_CPUID),
[x86_intercept_rsm] = PRE_EX(SVM_EXIT_RSM),
};

#undef PRE_EX
#undef POST_EX
#undef POST_MEM

Expand Down Expand Up @@ -3968,6 +3981,12 @@ static int svm_check_intercept(struct kvm_vcpu *vcpu,
case SVM_EXIT_WRITE_DR0:
icpt_info.exit_code += info->modrm_reg;
break;
case SVM_EXIT_MSR:
if (info->intercept == x86_intercept_wrmsr)
vmcb->control.exit_info_1 = 1;
else
vmcb->control.exit_info_1 = 0;
break;
default:
break;
}
Expand Down

0 comments on commit 8061252

Please sign in to comment.