x86/emul: Simplfy emulation state setup

The current code to set up emulation state is ad-hoc and error prone.

 * Consistently zero all emulation state structures.
 * Avoid explicitly initialising some state to 0.
 * Explicitly identify all input and output state in x86_emulate_ctxt.  This
   involves rearanging some fields.
 * Have x86_decode() explicitly initalise all output state at its start.

While making the above changes, two minor tweaks:

 * Move the calculation of hvmemul_ctxt->ctxt.swint_emulate from
   _hvm_emulate_one() to hvm_emulate_init_once().  It doesn't need
   recalculating for each instruction.
 * Change force_writeback to being a boolean, to match its use.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Tim Deegan <tim@xen.org>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Paul Durrant <paul.durrant@citrix.com>
This commit is contained in:
Andrew Cooper committed 2016-12-02 17:23:01 +00:00
1 parent bfce0e62c3
commit 2191599bac
5 files changed
+48 -31

No files matched your search

+15 -13
View File
@@ -1770,13 +1770,6 @@ static int _hvm_emulate_one(struct hvm_emulate_ctxt *hvmemul_ctxt,
vio->mmio_retry = 0;
if ( cpu_has_vmx )
hvmemul_ctxt->ctxt.swint_emulate = x86_swint_emulate_none;
else if ( cpu_has_svm_nrips )
hvmemul_ctxt->ctxt.swint_emulate = x86_swint_emulate_icebp;
else
hvmemul_ctxt->ctxt.swint_emulate = x86_swint_emulate_all;
rc = x86_emulate(&hvmemul_ctxt->ctxt, ops);
if ( rc == X86EMUL_OKAY && vio->mmio_retry )
@@ -1947,14 +1940,23 @@ void hvm_emulate_init_once(
struct hvm_emulate_ctxt *hvmemul_ctxt,
struct cpu_user_regs *regs)
{
hvmemul_ctxt->intr_shadow = hvm_funcs.get_interrupt_shadow(current);
hvmemul_ctxt->ctxt.regs = regs;
hvmemul_ctxt->ctxt.force_writeback = 1;
hvmemul_ctxt->seg_reg_accessed = 0;
hvmemul_ctxt->seg_reg_dirty = 0;
hvmemul_ctxt->set_context = 0;
struct vcpu *curr = current;
memset(hvmemul_ctxt, 0, sizeof(*hvmemul_ctxt));
hvmemul_ctxt->intr_shadow = hvm_funcs.get_interrupt_shadow(curr);
hvmemul_get_seg_reg(x86_seg_cs, hvmemul_ctxt);
hvmemul_get_seg_reg(x86_seg_ss, hvmemul_ctxt);
hvmemul_ctxt->ctxt.regs = regs;
hvmemul_ctxt->ctxt.force_writeback = true;
if ( cpu_has_vmx )
hvmemul_ctxt->ctxt.swint_emulate = x86_swint_emulate_none;
else if ( cpu_has_svm_nrips )
hvmemul_ctxt->ctxt.swint_emulate = x86_swint_emulate_icebp;
else
hvmemul_ctxt->ctxt.swint_emulate = x86_swint_emulate_all;
}
void hvm_emulate_init_per_insn(
+8 -6
View File
@@ -5337,7 +5337,14 @@ int ptwr_do_page_fault(struct vcpu *v, unsigned long addr,
struct domain *d = v->domain;
struct page_info *page;
l1_pgentry_t pte;
struct ptwr_emulate_ctxt ptwr_ctxt;
struct ptwr_emulate_ctxt ptwr_ctxt = {
.ctxt = {
.regs = regs,
.addr_size = is_pv_32bit_domain(d) ? 32 : BITS_PER_LONG,
.sp_size = is_pv_32bit_domain(d) ? 32 : BITS_PER_LONG,
.swint_emulate = x86_swint_emulate_none,
},
};
int rc;
/* Attempt to read the PTE that maps the VA being accessed. */
@@ -5363,11 +5370,6 @@ int ptwr_do_page_fault(struct vcpu *v, unsigned long addr,
goto bail;
}
ptwr_ctxt.ctxt.regs = regs;
ptwr_ctxt.ctxt.force_writeback = 0;
ptwr_ctxt.ctxt.addr_size = ptwr_ctxt.ctxt.sp_size =
is_pv_32bit_domain(d) ? 32 : BITS_PER_LONG;
ptwr_ctxt.ctxt.swint_emulate = x86_swint_emulate_none;
ptwr_ctxt.cr2 = addr;
ptwr_ctxt.pte = pte;
+2 -2
View File
@@ -385,8 +385,9 @@ const struct x86_emulate_ops *shadow_init_emulation(
struct vcpu *v = current;
unsigned long addr;
memset(sh_ctxt, 0, sizeof(*sh_ctxt));
sh_ctxt->ctxt.regs = regs;
sh_ctxt->ctxt.force_writeback = 0;
sh_ctxt->ctxt.swint_emulate = x86_swint_emulate_none;
if ( is_pv_vcpu(v) )
@@ -396,7 +397,6 @@ const struct x86_emulate_ops *shadow_init_emulation(
}
/* Segment cache initialisation. Primed with CS. */
sh_ctxt->valid_seg_regs = 0;
creg = hvm_get_seg_reg(x86_seg_cs, sh_ctxt);
/* Work out the emulation mode. */
+1
View File
@@ -1904,6 +1904,7 @@ x86_decode(
state->regs = ctxt->regs;
state->eip = ctxt->regs->eip;
/* Initialise output state in x86_emulate_ctxt */
ctxt->retire.byte = 0;
op_bytes = def_op_bytes = ad_bytes = def_ad_bytes = ctxt->addr_size/8;
+22 -10
View File
@@ -410,6 +410,23 @@ struct cpu_user_regs;
struct x86_emulate_ctxt
{
/*
* Input-only state:
*/
/* Software event injection support. */
enum x86_swint_emulation swint_emulate;
/* Set this if writes may have side effects. */
bool force_writeback;
/* Caller data that can be used by x86_emulate_ops' routines. */
void *data;
/*
* Input/output state:
*/
/* Register state before/after emulation. */
struct cpu_user_regs *regs;
@@ -419,15 +436,13 @@ struct x86_emulate_ctxt
/* Stack pointer width in bits (16, 32 or 64). */
unsigned int sp_size;
/* Canonical opcode (see below). */
/*
* Output-only state:
*/
/* Canonical opcode (see below) (valid only on X86EMUL_OKAY). */
unsigned int opcode;
/* Software event injection support. */
enum x86_swint_emulation swint_emulate;
/* Set this if writes may have side effects. */
uint8_t force_writeback;
/* Retirement state, set by the emulator (valid only on X86EMUL_OKAY). */
union {
struct {
@@ -437,9 +452,6 @@ struct x86_emulate_ctxt
} flags;
uint8_t byte;
} retire;
/* Caller data that can be used by x86_emulate_ops' routines. */
void *data;
};
/*
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.