|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [RFC v1 3/7] x86/emul: Separate out instruction completion
To support merging the emulated instruction and VMEXIT paths, split out
instruction completion from the core x86 emulation so it can be called
separately.
Signed-off-by: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>
---
xen/arch/x86/x86_emulate/x86_emulate.c | 48 +++++++++++++++-----------
xen/arch/x86/x86_emulate/x86_emulate.h | 3 ++
2 files changed, 30 insertions(+), 21 deletions(-)
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c
b/xen/arch/x86/x86_emulate/x86_emulate.c
index 364e6c092ded..76fbebf96b4d 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -320,7 +320,7 @@ do {
\
rc = ops->insn_fetch(ip, NULL, 0, ctxt); \
if ( rc ) goto done; \
_regs.r(ip) = ip; \
- singlestep = _regs.eflags & X86_EFLAGS_TF; \
+ ctxt->singlestep = _regs.eflags & X86_EFLAGS_TF; \
} while (0)
#define validate_far_branch(cs, ip) ({ \
@@ -337,7 +337,7 @@ do {
\
({ \
validate_far_branch(cs, newip); \
_regs.r(ip) = (newip); \
- singlestep = _regs.eflags & X86_EFLAGS_TF; \
+ ctxt->singlestep = _regs.eflags & X86_EFLAGS_TF; \
}), \
ops->write_segment(x86_seg_cs, cs, ctxt) \
)
@@ -1234,6 +1234,22 @@ int cf_check x86emul_unhandleable_rw(
return X86EMUL_UNHANDLEABLE;
}
+void x86_emulate_complete(struct x86_emulate_ctxt *ctxt, int rc)
+{
+ /* Zero the upper 32 bits of %rip if not in 64-bit mode. */
+ if ( !mode_64bit() )
+ ctxt->regs->r(ip) = (uint32_t)ctxt->regs->r(ip);
+
+ /* Should a singlestep #DB be raised? */
+ if ( rc == X86EMUL_OKAY && ctxt->singlestep && !ctxt->retire.mov_ss )
+ {
+ ctxt->retire.singlestep = true;
+ ctxt->retire.sti = false;
+ }
+
+ ctxt->regs->eflags &= ~X86_EFLAGS_RF;
+}
+
/* Helper definitions. */
#define op_bytes (state->op_bytes)
#define ad_bytes (state->ad_bytes)
@@ -1265,8 +1281,6 @@ x86_emulate(
uint8_t b, d, *opc = NULL;
unsigned int first_byte = 0, elem_bytes, insn_bytes = 0;
uint64_t op_mask = ~0ULL;
- bool singlestep = (_regs.eflags & X86_EFLAGS_TF) &&
- !is_branch_step(ctxt, ops);
bool sfence = false, fault_suppression = false;
struct operand src = { .reg = PTR_POISON };
struct operand dst = { .reg = PTR_POISON };
@@ -1280,6 +1294,9 @@ x86_emulate(
init_context(ctxt);
+ ctxt->singlestep = (_regs.eflags & X86_EFLAGS_TF) &&
+ !is_branch_step(ctxt, ops);
+
generate_exception_if((mode_vif() &&
(_regs.eflags & X86_EFLAGS_VIF) &&
(_regs.eflags & X86_EFLAGS_VIP)),
@@ -2064,7 +2081,7 @@ x86_emulate(
goto done;
_regs.r(ip) = imm1;
- singlestep = _regs.eflags & X86_EFLAGS_TF;
+ ctxt->singlestep = _regs.eflags & X86_EFLAGS_TF;
break;
#ifndef X86EMUL_NO_FPU
@@ -3103,7 +3120,7 @@ x86_emulate(
* Their only mitigation is to use a task gate for handling
* #DB (or to not use enable EFER.SCE to start with).
*/
- singlestep = _regs.eflags & X86_EFLAGS_TF;
+ ctxt->singlestep = _regs.eflags & X86_EFLAGS_TF;
break;
case X86EMUL_OPC(0x0f, 0x06): /* clts */
@@ -3189,7 +3206,7 @@ x86_emulate(
ctxt)) != X86EMUL_OKAY )
goto done;
- singlestep = _regs.eflags & X86_EFLAGS_TF;
+ ctxt->singlestep = _regs.eflags & X86_EFLAGS_TF;
break;
case X86EMUL_OPC(0x0f, 0x08): /* invd */
@@ -3918,7 +3935,7 @@ x86_emulate(
/* In particular mode_64bit() needs to return true from here on. */
ctxt->addr_size = ctxt->sp_size = 64;
- singlestep = _regs.eflags & X86_EFLAGS_TF;
+ ctxt->singlestep = _regs.eflags & X86_EFLAGS_TF;
break;
case X86EMUL_OPC(0x0f, 0x35): /* sysexit */
@@ -3958,7 +3975,7 @@ x86_emulate(
_regs.r(ip) = op_bytes == 8 ? _regs.r(dx) : _regs.edx;
_regs.r(sp) = op_bytes == 8 ? _regs.r(cx) : _regs.ecx;
- singlestep = _regs.eflags & X86_EFLAGS_TF;
+ ctxt->singlestep = _regs.eflags & X86_EFLAGS_TF;
break;
case X86EMUL_OPC(0x0f, 0x40) ... X86EMUL_OPC(0x0f, 0x4f): /* cmovcc */
@@ -8347,17 +8364,6 @@ x86_emulate(
put_fpu(fpu_type, false, state, ctxt, ops);
fpu_type = X86EMUL_FPU_none;
- /* Zero the upper 32 bits of %rip if not in 64-bit mode. */
- if ( !mode_64bit() )
- _regs.r(ip) = (uint32_t)_regs.r(ip);
-
- /* Should a singlestep #DB be raised? */
- if ( rc == X86EMUL_OKAY && singlestep && !ctxt->retire.mov_ss )
- {
- ctxt->retire.singlestep = true;
- ctxt->retire.sti = false;
- }
-
if ( rc != X86EMUL_DONE )
*ctxt->regs = _regs;
else
@@ -8366,7 +8372,7 @@ x86_emulate(
rc = X86EMUL_OKAY;
}
- ctxt->regs->eflags &= ~X86_EFLAGS_RF;
+ x86_emulate_complete(ctxt, rc);
done:
put_fpu(fpu_type, insn_bytes > 0 && dst.type == OP_MEM, state, ctxt, ops);
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.h
b/xen/arch/x86/x86_emulate/x86_emulate.h
index 0fd20747dc43..17bf14455cf3 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.h
+++ b/xen/arch/x86/x86_emulate/x86_emulate.h
@@ -594,6 +594,7 @@ struct x86_emulate_ctxt
} retire;
bool event_pending;
+ bool singlestep;
struct x86_event event;
};
@@ -680,6 +681,8 @@ x86_emulate(
struct x86_emulate_ctxt *ctxt,
const struct x86_emulate_ops *ops);
+void x86_emulate_complete(struct x86_emulate_ctxt *ctxt, int rc);
+
#ifndef NDEBUG
/*
* In debug builds, wrap x86_emulate() with some assertions about its expected
--
2.53.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |