|
@@ -104,6 +104,7 @@
|
|
|
|
|
|
struct opcode {
|
|
struct opcode {
|
|
u32 flags;
|
|
u32 flags;
|
|
|
|
+ u8 intercept;
|
|
union {
|
|
union {
|
|
int (*execute)(struct x86_emulate_ctxt *ctxt);
|
|
int (*execute)(struct x86_emulate_ctxt *ctxt);
|
|
struct opcode *group;
|
|
struct opcode *group;
|
|
@@ -2423,10 +2424,13 @@ static int em_movdqu(struct x86_emulate_ctxt *ctxt)
|
|
}
|
|
}
|
|
|
|
|
|
#define D(_y) { .flags = (_y) }
|
|
#define D(_y) { .flags = (_y) }
|
|
|
|
+#define DI(_y, _i) { .flags = (_y), .intercept = x86_intercept_##_i }
|
|
#define N D(0)
|
|
#define N D(0)
|
|
#define G(_f, _g) { .flags = ((_f) | Group), .u.group = (_g) }
|
|
#define G(_f, _g) { .flags = ((_f) | Group), .u.group = (_g) }
|
|
#define GD(_f, _g) { .flags = ((_f) | Group | GroupDual), .u.gdual = (_g) }
|
|
#define GD(_f, _g) { .flags = ((_f) | Group | GroupDual), .u.gdual = (_g) }
|
|
#define I(_f, _e) { .flags = (_f), .u.execute = (_e) }
|
|
#define I(_f, _e) { .flags = (_f), .u.execute = (_e) }
|
|
|
|
+#define II(_f, _e, _i) \
|
|
|
|
+ { .flags = (_f), .u.execute = (_e), .intercept = x86_intercept_##_i }
|
|
#define GP(_f, _g) { .flags = ((_f) | Prefix), .u.gprefix = (_g) }
|
|
#define GP(_f, _g) { .flags = ((_f) | Prefix), .u.gprefix = (_g) }
|
|
|
|
|
|
#define D2bv(_f) D((_f) | ByteOp), D(_f)
|
|
#define D2bv(_f) D((_f) | ByteOp), D(_f)
|
|
@@ -2867,6 +2871,7 @@ done_prefixes:
|
|
}
|
|
}
|
|
|
|
|
|
c->execute = opcode.u.execute;
|
|
c->execute = opcode.u.execute;
|
|
|
|
+ c->intercept = opcode.intercept;
|
|
|
|
|
|
/* Unrecognised? */
|
|
/* Unrecognised? */
|
|
if (c->d == 0 || (c->d & Undefined))
|
|
if (c->d == 0 || (c->d & Undefined))
|
|
@@ -3116,12 +3121,26 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
|
|
goto done;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (unlikely(ctxt->guest_mode) && c->intercept) {
|
|
|
|
+ rc = ops->intercept(ctxt, c->intercept,
|
|
|
|
+ X86_ICPT_PRE_EXCEPT);
|
|
|
|
+ if (rc != X86EMUL_CONTINUE)
|
|
|
|
+ goto done;
|
|
|
|
+ }
|
|
|
|
+
|
|
/* Privileged instruction can be executed only in CPL=0 */
|
|
/* Privileged instruction can be executed only in CPL=0 */
|
|
if ((c->d & Priv) && ops->cpl(ctxt->vcpu)) {
|
|
if ((c->d & Priv) && ops->cpl(ctxt->vcpu)) {
|
|
rc = emulate_gp(ctxt, 0);
|
|
rc = emulate_gp(ctxt, 0);
|
|
goto done;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (unlikely(ctxt->guest_mode) && c->intercept) {
|
|
|
|
+ rc = ops->intercept(ctxt, c->intercept,
|
|
|
|
+ X86_ICPT_POST_EXCEPT);
|
|
|
|
+ if (rc != X86EMUL_CONTINUE)
|
|
|
|
+ goto done;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (c->rep_prefix && (c->d & String)) {
|
|
if (c->rep_prefix && (c->d & String)) {
|
|
/* All REP prefixes have the same first termination condition */
|
|
/* All REP prefixes have the same first termination condition */
|
|
if (address_mask(c, c->regs[VCPU_REGS_RCX]) == 0) {
|
|
if (address_mask(c, c->regs[VCPU_REGS_RCX]) == 0) {
|
|
@@ -3160,6 +3179,13 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
|
|
|
|
|
|
special_insn:
|
|
special_insn:
|
|
|
|
|
|
|
|
+ if (unlikely(ctxt->guest_mode) && c->intercept) {
|
|
|
|
+ rc = ops->intercept(ctxt, c->intercept,
|
|
|
|
+ X86_ICPT_POST_MEMACCESS);
|
|
|
|
+ if (rc != X86EMUL_CONTINUE)
|
|
|
|
+ goto done;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (c->execute) {
|
|
if (c->execute) {
|
|
rc = c->execute(ctxt);
|
|
rc = c->execute(ctxt);
|
|
if (rc != X86EMUL_CONTINUE)
|
|
if (rc != X86EMUL_CONTINUE)
|