From: Joerg Roedel Date: Mon, 4 Apr 2011 10:39:25 +0000 (+0200) Subject: KVM: x86 emulator: Add check_perm callback X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=d09beabd7cd4cf70d982ff54656dc6431df80fa4;p=linux-beck.git 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 Signed-off-by: Avi Kivity --- 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);