diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2011-04-04 14:39:25 +0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-05-11 15:57:01 +0400 |
commit | d09beabd7cd4cf70d982ff54656dc6431df80fa4 (patch) | |
tree | bfb3d5996f6d2b51d79e0ccc543cbe63d9eaba01 | |
parent | 775fde8648ebc588d07de39457aadc7c2131df2e (diff) | |
download | linux-d09beabd7cd4cf70d982ff54656dc6431df80fa4.tar.xz |
KVM: x86 emulator: Add check_perm callback
This patch adds a check_perm callback for each opcode into
the instruction emulator. This will be used to do all
necessary permission checks on instructions before checking
whether they are intercepted or not.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r-- | arch/x86/include/asm/kvm_emulate.h | 1 | ||||
-rw-r--r-- | arch/x86/kvm/emulate.c | 14 |
2 files changed, 15 insertions, 0 deletions
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h index 1dbd0c736cd1..460c2d8964b7 100644 --- a/arch/x86/include/asm/kvm_emulate.h +++ b/arch/x86/include/asm/kvm_emulate.h @@ -222,6 +222,7 @@ struct decode_cache { u8 seg_override; unsigned int d; int (*execute)(struct x86_emulate_ctxt *ctxt); + int (*check_perm)(struct x86_emulate_ctxt *ctxt); unsigned long regs[NR_VCPU_REGS]; unsigned long eip; /* modrm */ diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index a2c31e527a99..4822824b608b 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -111,6 +111,7 @@ struct opcode { struct group_dual *gdual; struct gprefix *gprefix; } u; + int (*check_perm)(struct x86_emulate_ctxt *ctxt); }; struct group_dual { @@ -2425,12 +2426,17 @@ static int em_movdqu(struct x86_emulate_ctxt *ctxt) #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, \ + .check_perm = (_p) } #define N D(0) #define G(_f, _g) { .flags = ((_f) | Group), .u.group = (_g) } #define GD(_f, _g) { .flags = ((_f) | Group | GroupDual), .u.gdual = (_g) } #define I(_f, _e) { .flags = (_f), .u.execute = (_e) } #define II(_f, _e, _i) \ { .flags = (_f), .u.execute = (_e), .intercept = x86_intercept_##_i } +#define IIP(_f, _e, _i, _p) \ + { .flags = (_f), .u.execute = (_e), .intercept = x86_intercept_##_i, \ + .check_perm = (_p) } #define GP(_f, _g) { .flags = ((_f) | Prefix), .u.gprefix = (_g) } #define D2bv(_f) D((_f) | ByteOp), D(_f) @@ -2873,6 +2879,7 @@ done_prefixes: } c->execute = opcode.u.execute; + c->check_perm = opcode.check_perm; c->intercept = opcode.intercept; /* Unrecognised? */ @@ -3136,6 +3143,13 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt) goto done; } + /* Do instruction specific permission checks */ + if (c->check_perm) { + rc = c->check_perm(ctxt); + if (rc != X86EMUL_CONTINUE) + goto done; + } + if (unlikely(ctxt->guest_mode) && c->intercept) { rc = ops->intercept(ctxt, c->intercept, X86_ICPT_POST_EXCEPT); |