aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-06-30 14:19:09 +0100
committerKeir Fraser <keir.fraser@citrix.com>2008-06-30 14:19:09 +0100
commit1be51142f1bc756a5d7b5f55146af2fab8a6d89b (patch)
tree66650fd91c71490c95c353a93b9fca6e961cb7cc
parent04465fbeb9188b148101cff73994496c40355582 (diff)
downloadxen-1be51142f1bc756a5d7b5f55146af2fab8a6d89b.tar.gz
xen-1be51142f1bc756a5d7b5f55146af2fab8a6d89b.tar.bz2
xen-1be51142f1bc756a5d7b5f55146af2fab8a6d89b.zip
x86_emulate: read/write/insn_fetch emulation hooks now all take a
pointer to emulator data buffer, and an arbitrary byte count (up to the size of a page of memory). Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
-rw-r--r--tools/tests/test_x86_emulator.c9
-rw-r--r--xen/arch/x86/hvm/emulate.c107
-rw-r--r--xen/arch/x86/mm.c29
-rw-r--r--xen/arch/x86/mm/shadow/common.c32
-rw-r--r--xen/arch/x86/x86_emulate/x86_emulate.c201
-rw-r--r--xen/arch/x86/x86_emulate/x86_emulate.h27
6 files changed, 224 insertions, 181 deletions
diff --git a/tools/tests/test_x86_emulator.c b/tools/tests/test_x86_emulator.c
index c325887ffc..4215686888 100644
--- a/tools/tests/test_x86_emulator.c
+++ b/tools/tests/test_x86_emulator.c
@@ -22,23 +22,22 @@
static int read(
unsigned int seg,
unsigned long offset,
- unsigned long *val,
+ void *p_data,
unsigned int bytes,
struct x86_emulate_ctxt *ctxt)
{
- *val = 0;
- memcpy(val, (void *)offset, bytes);
+ memcpy(p_data, (void *)offset, bytes);
return X86EMUL_OKAY;
}
static int write(
unsigned int seg,
unsigned long offset,
- unsigned long val,
+ void *p_data,
unsigned int bytes,
struct x86_emulate_ctxt *ctxt)
{
- memcpy((void *)offset, &val, bytes);
+ memcpy((void *)offset, p_data, bytes);
return X86EMUL_OKAY;
}
diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
index adf1b64ffc..2174116ed4 100644
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -21,15 +21,33 @@
static int hvmemul_do_io(
int is_mmio, paddr_t addr, unsigned long *reps, int size,
- paddr_t value, int dir, int df, int value_is_ptr, unsigned long *val)
+ paddr_t ram_gpa, int dir, int df, void *p_data)
{
+ paddr_t value = ram_gpa;
+ int value_is_ptr = (p_data == NULL);
struct vcpu *curr = current;
vcpu_iodata_t *vio = get_ioreq(curr);
ioreq_t *p = &vio->vp_ioreq;
int rc;
- /* Only retrieve the value from singleton (non-REP) reads. */
- ASSERT((val == NULL) || ((dir == IOREQ_READ) && !value_is_ptr));
+ /*
+ * Weird-sized accesses have undefined behaviour: we discard writes
+ * and read all-ones.
+ */
+ if ( unlikely((size > sizeof(long)) || (size & (size - 1))) )
+ {
+ gdprintk(XENLOG_WARNING, "bad mmio size %d\n", size);
+ ASSERT(p_data != NULL); /* cannot happen with a REP prefix */
+ if ( dir == IOREQ_READ )
+ memset(p_data, ~0, size);
+ return X86EMUL_UNHANDLEABLE;
+ }
+
+ if ( (p_data != NULL) && (dir == IOREQ_WRITE) )
+ {
+ memcpy(&value, p_data, size);
+ p_data = NULL;
+ }
if ( is_mmio && !value_is_ptr )
{
@@ -47,8 +65,7 @@ static int hvmemul_do_io(
unsigned int bytes = curr->arch.hvm_vcpu.mmio_large_read_bytes;
if ( (addr >= pa) && ((addr + size) <= (pa + bytes)) )
{
- *val = 0;
- memcpy(val, &curr->arch.hvm_vcpu.mmio_large_read[addr - pa],
+ memcpy(p_data, &curr->arch.hvm_vcpu.mmio_large_read[addr - pa],
size);
return X86EMUL_OKAY;
}
@@ -61,7 +78,7 @@ static int hvmemul_do_io(
break;
case HVMIO_completed:
curr->arch.hvm_vcpu.io_state = HVMIO_none;
- if ( val == NULL )
+ if ( p_data == NULL )
return X86EMUL_UNHANDLEABLE;
goto finish_access;
case HVMIO_dispatched:
@@ -82,7 +99,7 @@ static int hvmemul_do_io(
}
curr->arch.hvm_vcpu.io_state =
- (val == NULL) ? HVMIO_dispatched : HVMIO_awaiting_completion;
+ (p_data == NULL) ? HVMIO_dispatched : HVMIO_awaiting_completion;
p->dir = dir;
p->data_is_ptr = value_is_ptr;
@@ -116,7 +133,7 @@ static int hvmemul_do_io(
break;
case X86EMUL_UNHANDLEABLE:
hvm_send_assist_req(curr);
- rc = (val != NULL) ? X86EMUL_RETRY : X86EMUL_OKAY;
+ rc = (p_data != NULL) ? X86EMUL_RETRY : X86EMUL_OKAY;
break;
default:
BUG();
@@ -126,8 +143,8 @@ static int hvmemul_do_io(
return rc;
finish_access:
- if ( val != NULL )
- *val = curr->arch.hvm_vcpu.io_data;
+ if ( p_data != NULL )
+ memcpy(p_data, &curr->arch.hvm_vcpu.io_data, size);
if ( is_mmio && !value_is_ptr )
{
@@ -152,7 +169,7 @@ static int hvmemul_do_io(
sizeof(curr->arch.hvm_vcpu.mmio_large_read)) )
{
memcpy(&curr->arch.hvm_vcpu.mmio_large_read[addr - pa],
- val, size);
+ p_data, size);
curr->arch.hvm_vcpu.mmio_large_read_bytes += size;
}
}
@@ -163,18 +180,16 @@ static int hvmemul_do_io(
static int hvmemul_do_pio(
unsigned long port, unsigned long *reps, int size,
- paddr_t value, int dir, int df, int value_is_ptr, unsigned long *val)
+ paddr_t ram_gpa, int dir, int df, void *p_data)
{
- return hvmemul_do_io(0, port, reps, size, value,
- dir, df, value_is_ptr, val);
+ return hvmemul_do_io(0, port, reps, size, ram_gpa, dir, df, p_data);
}
static int hvmemul_do_mmio(
paddr_t gpa, unsigned long *reps, int size,
- paddr_t value, int dir, int df, int value_is_ptr, unsigned long *val)
+ paddr_t ram_gpa, int dir, int df, void *p_data)
{
- return hvmemul_do_io(1, gpa, reps, size, value,
- dir, df, value_is_ptr, val);
+ return hvmemul_do_io(1, gpa, reps, size, ram_gpa, dir, df, p_data);
}
/*
@@ -287,7 +302,7 @@ static int hvmemul_virtual_to_linear(
static int __hvmemul_read(
enum x86_segment seg,
unsigned long offset,
- unsigned long *val,
+ void *p_data,
unsigned int bytes,
enum hvm_access_type access_type,
struct hvm_emulate_ctxt *hvmemul_ctxt)
@@ -303,8 +318,6 @@ static int __hvmemul_read(
if ( rc != X86EMUL_OKAY )
return rc;
- *val = 0;
-
if ( unlikely(curr->arch.hvm_vcpu.mmio_gva == (addr & PAGE_MASK)) &&
curr->arch.hvm_vcpu.mmio_gva )
{
@@ -314,7 +327,7 @@ static int __hvmemul_read(
gpa = (((paddr_t)curr->arch.hvm_vcpu.mmio_gpfn << PAGE_SHIFT) | off);
if ( (off + bytes) <= PAGE_SIZE )
return hvmemul_do_mmio(gpa, &reps, bytes, 0,
- IOREQ_READ, 0, 0, val);
+ IOREQ_READ, 0, p_data);
}
if ( (seg != x86_seg_none) &&
@@ -322,15 +335,13 @@ static int __hvmemul_read(
pfec |= PFEC_user_mode;
rc = ((access_type == hvm_access_insn_fetch) ?
- hvm_fetch_from_guest_virt(val, addr, bytes, pfec) :
- hvm_copy_from_guest_virt(val, addr, bytes, pfec));
+ hvm_fetch_from_guest_virt(p_data, addr, bytes, pfec) :
+ hvm_copy_from_guest_virt(p_data, addr, bytes, pfec));
if ( rc == HVMCOPY_bad_gva_to_gfn )
return X86EMUL_EXCEPTION;
if ( rc == HVMCOPY_bad_gfn_to_mfn )
{
- unsigned long reps = 1;
-
if ( access_type == hvm_access_insn_fetch )
return X86EMUL_UNHANDLEABLE;
@@ -339,7 +350,7 @@ static int __hvmemul_read(
if ( rc != X86EMUL_OKAY )
return rc;
- return hvmemul_do_mmio(gpa, &reps, bytes, 0, IOREQ_READ, 0, 0, val);
+ return hvmemul_do_mmio(gpa, &reps, bytes, 0, IOREQ_READ, 0, p_data);
}
return X86EMUL_OKAY;
@@ -348,19 +359,19 @@ static int __hvmemul_read(
static int hvmemul_read(
enum x86_segment seg,
unsigned long offset,
- unsigned long *val,
+ void *p_data,
unsigned int bytes,
struct x86_emulate_ctxt *ctxt)
{
return __hvmemul_read(
- seg, offset, val, bytes, hvm_access_read,
+ seg, offset, p_data, bytes, hvm_access_read,
container_of(ctxt, struct hvm_emulate_ctxt, ctxt));
}
static int hvmemul_insn_fetch(
enum x86_segment seg,
unsigned long offset,
- unsigned long *val,
+ void *p_data,
unsigned int bytes,
struct x86_emulate_ctxt *ctxt)
{
@@ -371,19 +382,18 @@ static int hvmemul_insn_fetch(
/* Fall back if requested bytes are not in the prefetch cache. */
if ( unlikely((insn_off + bytes) > hvmemul_ctxt->insn_buf_bytes) )
return __hvmemul_read(
- seg, offset, val, bytes,
+ seg, offset, p_data, bytes,
hvm_access_insn_fetch, hvmemul_ctxt);
/* Hit the cache. Simple memcpy. */
- *val = 0;
- memcpy(val, &hvmemul_ctxt->insn_buf[insn_off], bytes);
+ memcpy(p_data, &hvmemul_ctxt->insn_buf[insn_off], bytes);
return X86EMUL_OKAY;
}
static int hvmemul_write(
enum x86_segment seg,
unsigned long offset,
- unsigned long val,
+ void *p_data,
unsigned int bytes,
struct x86_emulate_ctxt *ctxt)
{
@@ -406,29 +416,27 @@ static int hvmemul_write(
unsigned int off = addr & (PAGE_SIZE - 1);
gpa = (((paddr_t)curr->arch.hvm_vcpu.mmio_gpfn << PAGE_SHIFT) | off);
if ( (off + bytes) <= PAGE_SIZE )
- return hvmemul_do_mmio(gpa, &reps, bytes, val,
- IOREQ_WRITE, 0, 0, NULL);
+ return hvmemul_do_mmio(gpa, &reps, bytes, 0,
+ IOREQ_WRITE, 0, p_data);
}
if ( (seg != x86_seg_none) &&
(hvmemul_ctxt->seg_reg[x86_seg_ss].attr.fields.dpl == 3) )
pfec |= PFEC_user_mode;
- rc = hvm_copy_to_guest_virt(addr, &val, bytes, pfec);
+ rc = hvm_copy_to_guest_virt(addr, p_data, bytes, pfec);
if ( rc == HVMCOPY_bad_gva_to_gfn )
return X86EMUL_EXCEPTION;
if ( rc == HVMCOPY_bad_gfn_to_mfn )
{
- unsigned long reps = 1;
-
rc = hvmemul_linear_to_phys(
addr, &gpa, bytes, &reps, pfec, hvmemul_ctxt);
if ( rc != X86EMUL_OKAY )
return rc;
- return hvmemul_do_mmio(gpa, &reps, bytes, val,
- IOREQ_WRITE, 0, 0, NULL);
+ return hvmemul_do_mmio(gpa, &reps, bytes, 0,
+ IOREQ_WRITE, 0, p_data);
}
return X86EMUL_OKAY;
@@ -442,12 +450,8 @@ static int hvmemul_cmpxchg(
unsigned int bytes,
struct x86_emulate_ctxt *ctxt)
{
- unsigned long new = 0;
- if ( bytes > sizeof(new) )
- return X86EMUL_UNHANDLEABLE;
- memcpy(&new, p_new, bytes);
/* Fix this in case the guest is really relying on r-m-w atomicity. */
- return hvmemul_write(seg, offset, new, bytes, ctxt);
+ return hvmemul_write(seg, offset, p_new, bytes, ctxt);
}
static int hvmemul_rep_ins(
@@ -480,7 +484,7 @@ static int hvmemul_rep_ins(
return rc;
return hvmemul_do_pio(src_port, reps, bytes_per_rep, gpa, IOREQ_READ,
- !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1, NULL);
+ !!(ctxt->regs->eflags & X86_EFLAGS_DF), NULL);
}
static int hvmemul_rep_outs(
@@ -513,7 +517,7 @@ static int hvmemul_rep_outs(
return rc;
return hvmemul_do_pio(dst_port, reps, bytes_per_rep, gpa, IOREQ_WRITE,
- !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1, NULL);
+ !!(ctxt->regs->eflags & X86_EFLAGS_DF), NULL);
}
static int hvmemul_rep_movs(
@@ -563,14 +567,14 @@ static int hvmemul_rep_movs(
if ( !p2m_is_ram(p2mt) )
return hvmemul_do_mmio(
sgpa, reps, bytes_per_rep, dgpa, IOREQ_READ,
- !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1, NULL);
+ !!(ctxt->regs->eflags & X86_EFLAGS_DF), NULL);
(void)gfn_to_mfn_current(dgpa >> PAGE_SHIFT, &p2mt);
if ( p2m_is_ram(p2mt) )
return X86EMUL_UNHANDLEABLE;
return hvmemul_do_mmio(
dgpa, reps, bytes_per_rep, sgpa, IOREQ_WRITE,
- !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1, NULL);
+ !!(ctxt->regs->eflags & X86_EFLAGS_DF), NULL);
}
static int hvmemul_read_segment(
@@ -607,7 +611,8 @@ static int hvmemul_read_io(
struct x86_emulate_ctxt *ctxt)
{
unsigned long reps = 1;
- return hvmemul_do_pio(port, &reps, bytes, 0, IOREQ_READ, 0, 0, val);
+ *val = 0;
+ return hvmemul_do_pio(port, &reps, bytes, 0, IOREQ_READ, 0, val);
}
static int hvmemul_write_io(
@@ -617,7 +622,7 @@ static int hvmemul_write_io(
struct x86_emulate_ctxt *ctxt)
{
unsigned long reps = 1;
- return hvmemul_do_pio(port, &reps, bytes, val, IOREQ_WRITE, 0, 0, NULL);
+ return hvmemul_do_pio(port, &reps, bytes, 0, IOREQ_WRITE, 0, &val);
}
static int hvmemul_read_cr(
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 0dfc614a8a..afe4d965d6 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -3539,15 +3539,14 @@ struct ptwr_emulate_ctxt {
static int ptwr_emulated_read(
enum x86_segment seg,
unsigned long offset,
- unsigned long *val,
+ void *p_data,
unsigned int bytes,
struct x86_emulate_ctxt *ctxt)
{
unsigned int rc;
unsigned long addr = offset;
- *val = 0;
- if ( (rc = copy_from_user((void *)val, (void *)addr, bytes)) != 0 )
+ if ( (rc = copy_from_user(p_data, (void *)addr, bytes)) != 0 )
{
propagate_page_fault(addr + bytes - rc, 0); /* read fault */
return X86EMUL_EXCEPTION;
@@ -3574,7 +3573,7 @@ static int ptwr_emulated_update(
/* Only allow naturally-aligned stores within the original %cr2 page. */
if ( unlikely(((addr^ptwr_ctxt->cr2) & PAGE_MASK) || (addr & (bytes-1))) )
{
- MEM_LOG("Bad ptwr access (cr2=%lx, addr=%lx, bytes=%u)",
+ MEM_LOG("ptwr_emulate: bad access (cr2=%lx, addr=%lx, bytes=%u)",
ptwr_ctxt->cr2, addr, bytes);
return X86EMUL_UNHANDLEABLE;
}
@@ -3682,10 +3681,21 @@ static int ptwr_emulated_update(
static int ptwr_emulated_write(
enum x86_segment seg,
unsigned long offset,
- unsigned long val,
+ void *p_data,
unsigned int bytes,
struct x86_emulate_ctxt *ctxt)
{
+ paddr_t val = 0;
+
+ if ( (bytes > sizeof(paddr_t)) || (bytes & (bytes -1)) )
+ {
+ MEM_LOG("ptwr_emulate: bad write size (addr=%lx, bytes=%u)",
+ offset, bytes);
+ return X86EMUL_UNHANDLEABLE;
+ }
+
+ memcpy(&val, p_data, bytes);
+
return ptwr_emulated_update(
offset, 0, val, bytes, 0,
container_of(ctxt, struct ptwr_emulate_ctxt, ctxt));
@@ -3700,10 +3710,17 @@ static int ptwr_emulated_cmpxchg(
struct x86_emulate_ctxt *ctxt)
{
paddr_t old = 0, new = 0;
- if ( bytes > sizeof(paddr_t) )
+
+ if ( (bytes > sizeof(paddr_t)) || (bytes & (bytes -1)) )
+ {
+ MEM_LOG("ptwr_emulate: bad cmpxchg size (addr=%lx, bytes=%u)",
+ offset, bytes);
return X86EMUL_UNHANDLEABLE;
+ }
+
memcpy(&old, p_old, bytes);
memcpy(&new, p_new, bytes);
+
return ptwr_emulated_update(
offset, old, new, bytes, 1,
container_of(ctxt, struct ptwr_emulate_ctxt, ctxt));
diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c
index 9200930e79..57b44f927b 100644
--- a/xen/arch/x86/mm/shadow/common.c
+++ b/xen/arch/x86/mm/shadow/common.c
@@ -145,7 +145,7 @@ static int hvm_translate_linear_addr(
static int
hvm_read(enum x86_segment seg,
unsigned long offset,
- unsigned long *val,
+ void *p_data,
unsigned int bytes,
enum hvm_access_type access_type,
struct sh_emulate_ctxt *sh_ctxt)
@@ -158,12 +158,10 @@ hvm_read(enum x86_segment seg,
if ( rc )
return rc;
- *val = 0;
-
if ( access_type == hvm_access_insn_fetch )
- rc = hvm_fetch_from_guest_virt(val, addr, bytes, 0);
+ rc = hvm_fetch_from_guest_virt(p_data, addr, bytes, 0);
else
- rc = hvm_copy_from_guest_virt(val, addr, bytes, 0);
+ rc = hvm_copy_from_guest_virt(p_data, addr, bytes, 0);
switch ( rc )
{
@@ -181,20 +179,20 @@ hvm_read(enum x86_segment seg,
static int
hvm_emulate_read(enum x86_segment seg,
unsigned long offset,
- unsigned long *val,
+ void *p_data,
unsigned int bytes,
struct x86_emulate_ctxt *ctxt)
{
if ( !is_x86_user_segment(seg) )
return X86EMUL_UNHANDLEABLE;
- return hvm_read(seg, offset, val, bytes, hvm_access_read,
+ return hvm_read(seg, offset, p_data, bytes, hvm_access_read,
container_of(ctxt, struct sh_emulate_ctxt, ctxt));
}
static int
hvm_emulate_insn_fetch(enum x86_segment seg,
unsigned long offset,
- unsigned long *val,
+ void *p_data,
unsigned int bytes,
struct x86_emulate_ctxt *ctxt)
{
@@ -206,19 +204,18 @@ hvm_emulate_insn_fetch(enum x86_segment seg,
/* Fall back if requested bytes are not in the prefetch cache. */
if ( unlikely((insn_off + bytes) > sh_ctxt->insn_buf_bytes) )
- return hvm_read(seg, offset, val, bytes,
+ return hvm_read(seg, offset, p_data, bytes,
hvm_access_insn_fetch, sh_ctxt);
/* Hit the cache. Simple memcpy. */
- *val = 0;
- memcpy(val, &sh_ctxt->insn_buf[insn_off], bytes);
+ memcpy(p_data, &sh_ctxt->insn_buf[insn_off], bytes);
return X86EMUL_OKAY;
}
static int
hvm_emulate_write(enum x86_segment seg,
unsigned long offset,
- unsigned long val,
+ void *p_data,
unsigned int bytes,
struct x86_emulate_ctxt *ctxt)
{
@@ -241,7 +238,7 @@ hvm_emulate_write(enum x86_segment seg,
return rc;
return v->arch.paging.mode->shadow.x86_emulate_write(
- v, addr, &val, bytes, sh_ctxt);
+ v, addr, p_data, bytes, sh_ctxt);
}
static int
@@ -293,7 +290,7 @@ static struct x86_emulate_ops hvm_shadow_emulator_ops = {
static int
pv_emulate_read(enum x86_segment seg,
unsigned long offset,
- unsigned long *val,
+ void *p_data,
unsigned int bytes,
struct x86_emulate_ctxt *ctxt)
{
@@ -302,8 +299,7 @@ pv_emulate_read(enum x86_segment seg,
if ( !is_x86_user_segment(seg) )
return X86EMUL_UNHANDLEABLE;
- *val = 0;
- if ( (rc = copy_from_user((void *)val, (void *)offset, bytes)) != 0 )
+ if ( (rc = copy_from_user(p_data, (void *)offset, bytes)) != 0 )
{
propagate_page_fault(offset + bytes - rc, 0); /* read fault */
return X86EMUL_EXCEPTION;
@@ -315,7 +311,7 @@ pv_emulate_read(enum x86_segment seg,
static int
pv_emulate_write(enum x86_segment seg,
unsigned long offset,
- unsigned long val,
+ void *p_data,
unsigned int bytes,
struct x86_emulate_ctxt *ctxt)
{
@@ -325,7 +321,7 @@ pv_emulate_write(enum x86_segment seg,
if ( !is_x86_user_segment(seg) )
return X86EMUL_UNHANDLEABLE;
return v->arch.paging.mode->shadow.x86_emulate_write(
- v, offset, &val, bytes, sh_ctxt);
+ v, offset, p_data, bytes, sh_ctxt);
}
static int
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c
index 2cc9b40fff..61f18108c6 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -466,7 +466,7 @@ do{ asm volatile ( \
/* Fetch next part of the instruction being emulated. */
#define insn_fetch_bytes(_size) \
-({ unsigned long _x, _eip = _regs.eip; \
+({ unsigned long _x = 0, _eip = _regs.eip; \
if ( !mode_64bit() ) _eip = (uint32_t)_eip; /* ignore upper dword */ \
_regs.eip += (_size); /* real hardware doesn't truncate */ \
generate_exception_if((uint8_t)(_regs.eip - ctxt->regs->eip) > 15, \
@@ -655,6 +655,19 @@ static void __put_rep_prefix(
__put_rep_prefix(&_regs, ctxt->regs, ad_bytes, reps_completed); \
})
+/* Compatibility function: read guest memory, zero-extend result to a ulong. */
+static int read_ulong(
+ enum x86_segment seg,
+ unsigned long offset,
+ unsigned long *val,
+ unsigned int bytes,
+ struct x86_emulate_ctxt *ctxt,
+ struct x86_emulate_ops *ops)
+{
+ *val = 0;
+ return ops->read(seg, offset, val, bytes, ctxt);
+}
+
/*
* Unsigned multiplication with double-word result.
* IN: Multiplicand=m[0], Multiplier=m[1]
@@ -841,7 +854,8 @@ static int ioport_access_check(
(tr.limit < 0x67) )
goto raise_exception;
- if ( (rc = ops->read(x86_seg_none, tr.base + 0x66, &iobmp, 2, ctxt)) )
+ if ( (rc = read_ulong(x86_seg_none, tr.base + 0x66,
+ &iobmp, 2, ctxt, ops)) )
return rc;
/* Ensure TSS includes two bytes including byte containing first port. */
@@ -849,7 +863,8 @@ static int ioport_access_check(
if ( tr.limit <= iobmp )
goto raise_exception;
- if ( (rc = ops->read(x86_seg_none, tr.base + iobmp, &iobmp, 2, ctxt)) )
+ if ( (rc = read_ulong(x86_seg_none, tr.base + iobmp,
+ &iobmp, 2, ctxt, ops)) )
return rc;
if ( (iobmp & (((1<<bytes)-1) << (first_port&7))) != 0 )
goto raise_exception;
@@ -941,12 +956,12 @@ protmode_load_seg(
goto raise_exn;
do {
- if ( (rc = ops->read(x86_seg_none, desctab.base + (sel & 0xfff8),
- &val, 4, ctxt)) )
+ if ( (rc = read_ulong(x86_seg_none, desctab.base + (sel & 0xfff8),
+ &val, 4, ctxt, ops)) )
return rc;
desc.a = val;
- if ( (rc = ops->read(x86_seg_none, desctab.base + (sel & 0xfff8) + 4,
- &val, 4, ctxt)) )
+ if ( (rc = read_ulong(x86_seg_none, desctab.base + (sel & 0xfff8) + 4,
+ &val, 4, ctxt, ops)) )
return rc;
desc.b = val;
@@ -1402,8 +1417,8 @@ x86_emulate(
case 8: src.val = *(uint64_t *)src.reg; break;
}
}
- else if ( (rc = ops->read(src.mem.seg, src.mem.off,
- &src.val, src.bytes, ctxt)) )
+ else if ( (rc = read_ulong(src.mem.seg, src.mem.off,
+ &src.val, src.bytes, ctxt, ops)) )
goto done;
break;
case SrcImm:
@@ -1494,8 +1509,8 @@ x86_emulate(
}
else if ( !(d & Mov) ) /* optimisation - avoid slow emulated read */
{
- if ( (rc = ops->read(dst.mem.seg, dst.mem.off,
- &dst.val, dst.bytes, ctxt)) )
+ if ( (rc = read_ulong(dst.mem.seg, dst.mem.off,
+ &dst.val, dst.bytes, ctxt, ops)) )
goto done;
dst.orig_val = dst.val;
}
@@ -1571,8 +1586,8 @@ x86_emulate(
int lb, ub, idx;
generate_exception_if(mode_64bit() || (src.type != OP_MEM),
EXC_UD, -1);
- if ( (rc = ops->read(src.mem.seg, src.mem.off + op_bytes,
- &src_val2, op_bytes, ctxt)) )
+ if ( (rc = read_ulong(src.mem.seg, src.mem.off + op_bytes,
+ &src_val2, op_bytes, ctxt, ops)) )
goto done;
ub = (op_bytes == 2) ? (int16_t)src_val2 : (int32_t)src_val2;
lb = (op_bytes == 2) ? (int16_t)src.val : (int32_t)src.val;
@@ -1588,8 +1603,8 @@ x86_emulate(
/* movsxd */
if ( src.type == OP_REG )
src.val = *(int32_t *)src.reg;
- else if ( (rc = ops->read(src.mem.seg, src.mem.off,
- &src.val, 4, ctxt)) )
+ else if ( (rc = read_ulong(src.mem.seg, src.mem.off,
+ &src.val, 4, ctxt, ops)) )
goto done;
dst.val = (int32_t)src.val;
}
@@ -1613,8 +1628,8 @@ x86_emulate(
unsigned long src1; /* ModR/M source operand */
if ( ea.type == OP_REG )
src1 = *ea.reg;
- else if ( (rc = ops->read(ea.mem.seg, ea.mem.off,
- &src1, op_bytes, ctxt)) )
+ else if ( (rc = read_ulong(ea.mem.seg, ea.mem.off,
+ &src1, op_bytes, ctxt, ops)) )
goto done;
_regs.eflags &= ~(EFLG_OF|EFLG_CF);
switch ( dst.bytes )
@@ -1720,8 +1735,8 @@ x86_emulate(
/* 64-bit mode: POP defaults to a 64-bit operand. */
if ( mode_64bit() && (dst.bytes == 4) )
dst.bytes = 8;
- if ( (rc = ops->read(x86_seg_ss, sp_post_inc(dst.bytes),
- &dst.val, dst.bytes, ctxt)) != 0 )
+ if ( (rc = read_ulong(x86_seg_ss, sp_post_inc(dst.bytes),
+ &dst.val, dst.bytes, ctxt, ops)) != 0 )
goto done;
break;
@@ -1773,8 +1788,8 @@ x86_emulate(
dst.val = x86_seg_es;
les: /* dst.val identifies the segment */
generate_exception_if(src.type != OP_MEM, EXC_UD, -1);
- if ( (rc = ops->read(src.mem.seg, src.mem.off + src.bytes,
- &sel, 2, ctxt)) != 0 )
+ if ( (rc = read_ulong(src.mem.seg, src.mem.off + src.bytes,
+ &sel, 2, ctxt, ops)) != 0 )
goto done;
if ( (rc = load_seg(dst.val, (uint16_t)sel, ctxt, ops)) != 0 )
goto done;
@@ -2020,8 +2035,8 @@ x86_emulate(
dst.bytes = op_bytes = 8;
if ( dst.type == OP_REG )
dst.val = *dst.reg;
- else if ( (rc = ops->read(dst.mem.seg, dst.mem.off,
- &dst.val, 8, ctxt)) != 0 )
+ else if ( (rc = read_ulong(dst.mem.seg, dst.mem.off,
+ &dst.val, 8, ctxt, ops)) != 0 )
goto done;
}
src.val = _regs.eip;
@@ -2036,8 +2051,8 @@ x86_emulate(
generate_exception_if(dst.type != OP_MEM, EXC_UD, -1);
- if ( (rc = ops->read(dst.mem.seg, dst.mem.off+dst.bytes,
- &sel, 2, ctxt)) )
+ if ( (rc = read_ulong(dst.mem.seg, dst.mem.off+dst.bytes,
+ &sel, 2, ctxt, ops)) )
goto done;
if ( (modrm_reg & 7) == 3 ) /* call */
@@ -2046,9 +2061,9 @@ x86_emulate(
fail_if(ops->read_segment == NULL);
if ( (rc = ops->read_segment(x86_seg_cs, &reg, ctxt)) ||
(rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes),
- reg.sel, op_bytes, ctxt)) ||
+ &reg.sel, op_bytes, ctxt)) ||
(rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes),
- _regs.eip, op_bytes, ctxt)) )
+ &_regs.eip, op_bytes, ctxt)) )
goto done;
}
@@ -2066,12 +2081,12 @@ x86_emulate(
dst.bytes = 8;
if ( dst.type == OP_REG )
dst.val = *dst.reg;
- else if ( (rc = ops->read(dst.mem.seg, dst.mem.off,
- &dst.val, 8, ctxt)) != 0 )
+ else if ( (rc = read_ulong(dst.mem.seg, dst.mem.off,
+ &dst.val, 8, ctxt, ops)) != 0 )
goto done;
}
if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(dst.bytes),
- dst.val, dst.bytes, ctxt)) != 0 )
+ &dst.val, dst.bytes, ctxt)) != 0 )
goto done;
dst.type = OP_NONE;
break;
@@ -2106,7 +2121,7 @@ x86_emulate(
&dst.val, dst.bytes, ctxt);
else
rc = ops->write(
- dst.mem.seg, dst.mem.off, dst.val, dst.bytes, ctxt);
+ dst.mem.seg, dst.mem.off, &dst.val, dst.bytes, ctxt);
if ( rc != 0 )
goto done;
default:
@@ -2153,7 +2168,7 @@ x86_emulate(
if ( mode_64bit() && (op_bytes == 4) )
op_bytes = 8;
if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes),
- reg.sel, op_bytes, ctxt)) != 0 )
+ &reg.sel, op_bytes, ctxt)) != 0 )
goto done;
break;
}
@@ -2165,8 +2180,8 @@ x86_emulate(
/* 64-bit mode: POP defaults to a 64-bit operand. */
if ( mode_64bit() && (op_bytes == 4) )
op_bytes = 8;
- if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes),
- &dst.val, op_bytes, ctxt)) != 0 )
+ if ( (rc = read_ulong(x86_seg_ss, sp_post_inc(op_bytes),
+ &dst.val, op_bytes, ctxt, ops)) != 0 )
goto done;
if ( (rc = load_seg(src.val, (uint16_t)dst.val, ctxt, ops)) != 0 )
return rc;
@@ -2275,8 +2290,8 @@ x86_emulate(
dst.bytes = op_bytes;
if ( mode_64bit() && (dst.bytes == 4) )
dst.bytes = 8;
- if ( (rc = ops->read(x86_seg_ss, sp_post_inc(dst.bytes),
- &dst.val, dst.bytes, ctxt)) != 0 )
+ if ( (rc = read_ulong(x86_seg_ss, sp_post_inc(dst.bytes),
+ &dst.val, dst.bytes, ctxt, ops)) != 0 )
goto done;
break;
@@ -2288,7 +2303,7 @@ x86_emulate(
generate_exception_if(mode_64bit(), EXC_UD, -1);
for ( i = 0; i < 8; i++ )
if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes),
- regs[i], op_bytes, ctxt)) != 0 )
+ &regs[i], op_bytes, ctxt)) != 0 )
goto done;
break;
}
@@ -2303,8 +2318,8 @@ x86_emulate(
generate_exception_if(mode_64bit(), EXC_UD, -1);
for ( i = 0; i < 8; i++ )
{
- if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes),
- &dst.val, op_bytes, ctxt)) != 0 )
+ if ( (rc = read_ulong(x86_seg_ss, sp_post_inc(op_bytes),
+ &dst.val, op_bytes, ctxt, ops)) != 0 )
goto done;
switch ( op_bytes )
{
@@ -2382,8 +2397,8 @@ x86_emulate(
}
else
{
- if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi),
- &dst.val, dst.bytes, ctxt)) != 0 )
+ if ( (rc = read_ulong(ea.mem.seg, truncate_ea(_regs.esi),
+ &dst.val, dst.bytes, ctxt, ops)) != 0 )
goto done;
fail_if(ops->write_io == NULL);
if ( (rc = ops->write_io(port, dst.bytes, dst.val, ctxt)) != 0 )
@@ -2455,9 +2470,9 @@ x86_emulate(
if ( (rc = ops->read_segment(x86_seg_cs, &reg, ctxt)) ||
(rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes),
- reg.sel, op_bytes, ctxt)) ||
+ &reg.sel, op_bytes, ctxt)) ||
(rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes),
- _regs.eip, op_bytes, ctxt)) )
+ &_regs.eip, op_bytes, ctxt)) )
goto done;
if ( (rc = load_seg(x86_seg_cs, sel, ctxt, ops)) != 0 )
@@ -2483,8 +2498,8 @@ x86_emulate(
/* 64-bit mode: POP defaults to a 64-bit operand. */
if ( mode_64bit() && (op_bytes == 4) )
op_bytes = 8;
- if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes),
- &dst.val, op_bytes, ctxt)) != 0 )
+ if ( (rc = read_ulong(x86_seg_ss, sp_post_inc(op_bytes),
+ &dst.val, op_bytes, ctxt, ops)) != 0 )
goto done;
if ( op_bytes == 2 )
dst.val = (uint16_t)dst.val | (_regs.eflags & 0xffff0000u);
@@ -2507,8 +2522,8 @@ x86_emulate(
dst.type = OP_REG;
dst.reg = (unsigned long *)&_regs.eax;
dst.bytes = (d & ByteOp) ? 1 : op_bytes;
- if ( (rc = ops->read(ea.mem.seg, insn_fetch_bytes(ad_bytes),
- &dst.val, dst.bytes, ctxt)) != 0 )
+ if ( (rc = read_ulong(ea.mem.seg, insn_fetch_bytes(ad_bytes),
+ &dst.val, dst.bytes, ctxt, ops)) != 0 )
goto done;
break;
@@ -2536,8 +2551,8 @@ x86_emulate(
}
else
{
- if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi),
- &dst.val, dst.bytes, ctxt)) != 0 )
+ if ( (rc = read_ulong(ea.mem.seg, truncate_ea(_regs.esi),
+ &dst.val, dst.bytes, ctxt, ops)) != 0 )
goto done;
dst.type = OP_MEM;
nr_reps = 1;
@@ -2556,10 +2571,10 @@ x86_emulate(
unsigned long next_eip = _regs.eip;
get_rep_prefix();
src.bytes = dst.bytes = (d & ByteOp) ? 1 : op_bytes;
- if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi),
- &dst.val, dst.bytes, ctxt)) ||
- (rc = ops->read(x86_seg_es, truncate_ea(_regs.edi),
- &src.val, src.bytes, ctxt)) )
+ if ( (rc = read_ulong(ea.mem.seg, truncate_ea(_regs.esi),
+ &dst.val, dst.bytes, ctxt, ops)) ||
+ (rc = read_ulong(x86_seg_es, truncate_ea(_regs.edi),
+ &src.val, src.bytes, ctxt, ops)) )
goto done;
register_address_increment(
_regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
@@ -2592,8 +2607,8 @@ x86_emulate(
dst.type = OP_REG;
dst.bytes = (d & ByteOp) ? 1 : op_bytes;
dst.reg = (unsigned long *)&_regs.eax;
- if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi),
- &dst.val, dst.bytes, ctxt)) != 0 )
+ if ( (rc = read_ulong(ea.mem.seg, truncate_ea(_regs.esi),
+ &dst.val, dst.bytes, ctxt, ops)) != 0 )
goto done;
register_address_increment(
_regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
@@ -2606,8 +2621,8 @@ x86_emulate(
get_rep_prefix();
src.bytes = dst.bytes = (d & ByteOp) ? 1 : op_bytes;
dst.val = _regs.eax;
- if ( (rc = ops->read(x86_seg_es, truncate_ea(_regs.edi),
- &src.val, src.bytes, ctxt)) != 0 )
+ if ( (rc = read_ulong(x86_seg_es, truncate_ea(_regs.edi),
+ &src.val, src.bytes, ctxt, ops)) != 0 )
goto done;
register_address_increment(
_regs.edi, (_regs.eflags & EFLG_DF) ? -src.bytes : src.bytes);
@@ -2624,8 +2639,8 @@ x86_emulate(
case 0xc3: /* ret (near) */ {
int offset = (b == 0xc2) ? insn_fetch_type(uint16_t) : 0;
op_bytes = mode_64bit() ? 8 : op_bytes;
- if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes + offset),
- &dst.val, op_bytes, ctxt)) != 0 )
+ if ( (rc = read_ulong(x86_seg_ss, sp_post_inc(op_bytes + offset),
+ &dst.val, op_bytes, ctxt, ops)) != 0 )
goto done;
_regs.eip = dst.val;
break;
@@ -2640,7 +2655,7 @@ x86_emulate(
dst.bytes = (mode_64bit() && (op_bytes == 4)) ? 8 : op_bytes;
dst.reg = (unsigned long *)&_regs.ebp;
if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(dst.bytes),
- _regs.ebp, dst.bytes, ctxt)) )
+ &_regs.ebp, dst.bytes, ctxt)) )
goto done;
dst.val = _regs.esp;
@@ -2650,14 +2665,14 @@ x86_emulate(
{
unsigned long ebp, temp_data;
ebp = truncate_word(_regs.ebp - i*dst.bytes, ctxt->sp_size/8);
- if ( (rc = ops->read(x86_seg_ss, ebp,
- &temp_data, dst.bytes, ctxt)) ||
+ if ( (rc = read_ulong(x86_seg_ss, ebp,
+ &temp_data, dst.bytes, ctxt, ops)) ||
(rc = ops->write(x86_seg_ss, sp_pre_dec(dst.bytes),
- temp_data, dst.bytes, ctxt)) )
+ &temp_data, dst.bytes, ctxt)) )
goto done;
}
if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(dst.bytes),
- dst.val, dst.bytes, ctxt)) )
+ &dst.val, dst.bytes, ctxt)) )
goto done;
}
@@ -2683,8 +2698,8 @@ x86_emulate(
/* Second writeback, to %%ebp. */
dst.reg = (unsigned long *)&_regs.ebp;
- if ( (rc = ops->read(x86_seg_ss, sp_post_inc(dst.bytes),
- &dst.val, dst.bytes, ctxt)) )
+ if ( (rc = read_ulong(x86_seg_ss, sp_post_inc(dst.bytes),
+ &dst.val, dst.bytes, ctxt, ops)) )
goto done;
break;
@@ -2692,10 +2707,10 @@ x86_emulate(
case 0xcb: /* ret (far) */ {
int offset = (b == 0xca) ? insn_fetch_type(uint16_t) : 0;
op_bytes = mode_64bit() ? 8 : op_bytes;
- if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes),
- &dst.val, op_bytes, ctxt)) ||
- (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes + offset),
- &src.val, op_bytes, ctxt)) ||
+ if ( (rc = read_ulong(x86_seg_ss, sp_post_inc(op_bytes),
+ &dst.val, op_bytes, ctxt, ops)) ||
+ (rc = read_ulong(x86_seg_ss, sp_post_inc(op_bytes + offset),
+ &src.val, op_bytes, ctxt, ops)) ||
(rc = load_seg(x86_seg_cs, (uint16_t)src.val, ctxt, ops)) )
goto done;
_regs.eip = dst.val;
@@ -2729,12 +2744,12 @@ x86_emulate(
if ( !mode_iopl() )
mask |= EFLG_IF;
fail_if(!in_realmode(ctxt, ops));
- if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes),
- &eip, op_bytes, ctxt)) ||
- (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes),
- &cs, op_bytes, ctxt)) ||
- (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes),
- &eflags, op_bytes, ctxt)) )
+ if ( (rc = read_ulong(x86_seg_ss, sp_post_inc(op_bytes),
+ &eip, op_bytes, ctxt, ops)) ||
+ (rc = read_ulong(x86_seg_ss, sp_post_inc(op_bytes),
+ &cs, op_bytes, ctxt, ops)) ||
+ (rc = read_ulong(x86_seg_ss, sp_post_inc(op_bytes),
+ &eflags, op_bytes, ctxt, ops)) )
goto done;
if ( op_bytes == 2 )
eflags = (uint16_t)eflags | (_regs.eflags & 0xffff0000u);
@@ -2779,8 +2794,8 @@ x86_emulate(
case 0xd7: /* xlat */ {
unsigned long al = (uint8_t)_regs.eax;
- if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.ebx + al),
- &al, 1, ctxt)) != 0 )
+ if ( (rc = read_ulong(ea.mem.seg, truncate_ea(_regs.ebx + al),
+ &al, 1, ctxt, ops)) != 0 )
goto done;
*(uint8_t *)&_regs.eax = al;
break;
@@ -3242,9 +3257,9 @@ x86_emulate(
if ( op_bytes == 2 )
reg.base &= 0xffffff;
if ( (rc = ops->write(ea.mem.seg, ea.mem.off+0,
- reg.limit, 2, ctxt)) ||
+ &reg.limit, 2, ctxt)) ||
(rc = ops->write(ea.mem.seg, ea.mem.off+2,
- reg.base, mode_64bit() ? 8 : 4, ctxt)) )
+ &reg.base, mode_64bit() ? 8 : 4, ctxt)) )
goto done;
break;
case 2: /* lgdt */
@@ -3252,10 +3267,10 @@ x86_emulate(
generate_exception_if(ea.type != OP_MEM, EXC_UD, -1);
fail_if(ops->write_segment == NULL);
memset(&reg, 0, sizeof(reg));
- if ( (rc = ops->read(ea.mem.seg, ea.mem.off+0,
- &limit, 2, ctxt)) ||
- (rc = ops->read(ea.mem.seg, ea.mem.off+2,
- &base, mode_64bit() ? 8 : 4, ctxt)) )
+ if ( (rc = read_ulong(ea.mem.seg, ea.mem.off+0,
+ &limit, 2, ctxt, ops)) ||
+ (rc = read_ulong(ea.mem.seg, ea.mem.off+2,
+ &base, mode_64bit() ? 8 : 4, ctxt, ops)) )
goto done;
reg.base = base;
reg.limit = limit;
@@ -3282,8 +3297,8 @@ x86_emulate(
goto done;
if ( ea.type == OP_REG )
cr0w = *ea.reg;
- else if ( (rc = ops->read(ea.mem.seg, ea.mem.off,
- &cr0w, 2, ctxt)) )
+ else if ( (rc = read_ulong(ea.mem.seg, ea.mem.off,
+ &cr0w, 2, ctxt, ops)) )
goto done;
/* LMSW can: (1) set bits 0-3; (2) clear bits 1-3. */
cr0 = (cr0 & ~0xe) | (cr0w & 0xf);
@@ -3405,8 +3420,10 @@ x86_emulate(
if ( ea.type == OP_MEM )
{
unsigned long lval, hval;
- if ( (rc = ops->read(ea.mem.seg, ea.mem.off+0, &lval, 4, ctxt)) ||
- (rc = ops->read(ea.mem.seg, ea.mem.off+4, &hval, 4, ctxt)) )
+ if ( (rc = read_ulong(ea.mem.seg, ea.mem.off+0,
+ &lval, 4, ctxt, ops)) ||
+ (rc = read_ulong(ea.mem.seg, ea.mem.off+4,
+ &hval, 4, ctxt, ops)) )
goto done;
val = ((uint64_t)hval << 32) | (uint32_t)lval;
stub[2] = modrm & 0x38; /* movq (%eax),%mmN */
@@ -3429,8 +3446,8 @@ x86_emulate(
if ( ea.type == OP_MEM )
{
unsigned long lval = (uint32_t)val, hval = (uint32_t)(val >> 32);
- if ( (rc = ops->write(ea.mem.seg, ea.mem.off+0, lval, 4, ctxt)) ||
- (rc = ops->write(ea.mem.seg, ea.mem.off+4, hval, 4, ctxt)) )
+ if ( (rc = ops->write(ea.mem.seg, ea.mem.off+0, &lval, 4, ctxt)) ||
+ (rc = ops->write(ea.mem.seg, ea.mem.off+4, &hval, 4, ctxt)) )
goto done;
}
break;
@@ -3482,8 +3499,8 @@ x86_emulate(
/* Get actual old value. */
for ( i = 0; i < (op_bytes/sizeof(long)); i++ )
- if ( (rc = ops->read(ea.mem.seg, ea.mem.off + i*sizeof(long),
- &old[i], sizeof(long), ctxt)) != 0 )
+ if ( (rc = read_ulong(ea.mem.seg, ea.mem.off + i*sizeof(long),
+ &old[i], sizeof(long), ctxt, ops)) != 0 )
goto done;
/* Get expected and proposed values. */
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.h b/xen/arch/x86/x86_emulate/x86_emulate.h
index 419f419cb1..a373528ea4 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.h
+++ b/xen/arch/x86/x86_emulate/x86_emulate.h
@@ -102,7 +102,8 @@ enum x86_emulate_fpu_type {
};
/*
- * These operations represent the instruction emulator's interface to memory.
+ * These operations represent the instruction emulator's interface to memory,
+ * I/O ports, privileged state... pretty much everything other than GPRs.
*
* NOTES:
* 1. If the access fails (cannot emulate, or a standard access faults) then
@@ -110,8 +111,7 @@ enum x86_emulate_fpu_type {
* some out-of-band mechanism, unknown to the emulator. The memop signals
* failure by returning X86EMUL_EXCEPTION to the emulator, which will
* then immediately bail.
- * 2. Valid access sizes are 1, 2, 4 and 8 (x86/64 only) bytes.
- * 3. The emulator cannot handle 64-bit mode emulation on an x86/32 system.
+ * 2. The emulator cannot handle 64-bit mode emulation on an x86/32 system.
*/
struct x86_emulate_ops
{
@@ -121,19 +121,25 @@ struct x86_emulate_ops
* All memory-access functions:
* @seg: [IN ] Segment being dereferenced (specified as x86_seg_??).
* @offset:[IN ] Offset within segment.
+ * @p_data:[IN ] Pointer to i/o data buffer (length is @bytes)
* Read functions:
* @val: [OUT] Value read, zero-extended to 'ulong'.
* Write functions:
* @val: [IN ] Value to write (low-order bytes used as req'd).
* Variable-length access functions:
- * @bytes: [IN ] Number of bytes to read or write.
+ * @bytes: [IN ] Number of bytes to read or write. Valid access sizes are
+ * 1, 2, 4 and 8 (x86/64 only) bytes, unless otherwise
+ * stated.
*/
- /* read: Emulate a memory read. */
+ /*
+ * read: Emulate a memory read.
+ * @bytes: Access length (0 < @bytes < 4096).
+ */
int (*read)(
enum x86_segment seg,
unsigned long offset,
- unsigned long *val,
+ void *p_data,
unsigned int bytes,
struct x86_emulate_ctxt *ctxt);
@@ -144,15 +150,18 @@ struct x86_emulate_ops
int (*insn_fetch)(
enum x86_segment seg,
unsigned long offset,
- unsigned long *val,
+ void *p_data,
unsigned int bytes,
struct x86_emulate_ctxt *ctxt);
- /* write: Emulate a memory write. */
+ /*
+ * write: Emulate a memory write.
+ * @bytes: Access length (0 < @bytes < 4096).
+ */
int (*write)(
enum x86_segment seg,
unsigned long offset,
- unsigned long val,
+ void *p_data,
unsigned int bytes,
struct x86_emulate_ctxt *ctxt);