ia64/xen-unstable

changeset 12675:88935ae47fa9

[XEN] Simplify x86_emulate interface.

- No distinction between 'special' and 'normal' memory accesses.
- No reliance on caller-supplied %cr2 value
- Memory operations include segment identifier to allow callers
to support non-zero-based segments

TODO:
1. HVM emulations should take into account segment base, limit, and
attributes.
2. We ought to obey stack-size attribute on PUSH/POP instructions.
Could extend the mode input field, or could add an extra call-out
hook, or perhaps we don't care at all...

Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Thu Nov 30 10:57:28 2006 +0000 (2006-11-30)
parents d1b0a5adaeab
children 5d6be0099bdf
files tools/tests/test_x86_emulator.c xen/arch/x86/mm.c xen/arch/x86/mm/shadow/common.c xen/arch/x86/mm/shadow/multi.c xen/arch/x86/x86_emulate.c xen/include/asm-x86/x86_emulate.h
line diff
     1.1 --- a/tools/tests/test_x86_emulator.c	Wed Nov 29 23:40:40 2006 +0000
     1.2 +++ b/tools/tests/test_x86_emulator.c	Thu Nov 30 10:57:28 2006 +0000
     1.3 @@ -17,12 +17,14 @@ typedef int64_t            s64;
     1.4  
     1.5  #define PFEC_write_access (1U<<1)
     1.6  
     1.7 -static int read_any(
     1.8 -    unsigned long addr,
     1.9 +static int read(
    1.10 +    unsigned int seg,
    1.11 +    unsigned long offset,
    1.12      unsigned long *val,
    1.13      unsigned int bytes,
    1.14      struct x86_emulate_ctxt *ctxt)
    1.15  {
    1.16 +    unsigned long addr = offset;
    1.17      switch ( bytes )
    1.18      {
    1.19      case 1: *val = *(u8 *)addr; break;
    1.20 @@ -33,12 +35,14 @@ static int read_any(
    1.21      return X86EMUL_CONTINUE;
    1.22  }
    1.23  
    1.24 -static int write_any(
    1.25 -    unsigned long addr,
    1.26 +static int write(
    1.27 +    unsigned int seg,
    1.28 +    unsigned long offset,
    1.29      unsigned long val,
    1.30      unsigned int bytes,
    1.31      struct x86_emulate_ctxt *ctxt)
    1.32  {
    1.33 +    unsigned long addr = offset;
    1.34      switch ( bytes )
    1.35      {
    1.36      case 1: *(u8 *)addr = (u8)val; break;
    1.37 @@ -49,13 +53,15 @@ static int write_any(
    1.38      return X86EMUL_CONTINUE;
    1.39  }
    1.40  
    1.41 -static int cmpxchg_any(
    1.42 -    unsigned long addr,
    1.43 +static int cmpxchg(
    1.44 +    unsigned int seg,
    1.45 +    unsigned long offset,
    1.46      unsigned long old,
    1.47      unsigned long new,
    1.48      unsigned int bytes,
    1.49      struct x86_emulate_ctxt *ctxt)
    1.50  {
    1.51 +    unsigned long addr = offset;
    1.52      switch ( bytes )
    1.53      {
    1.54      case 1: *(u8 *)addr = (u8)new; break;
    1.55 @@ -66,21 +72,23 @@ static int cmpxchg_any(
    1.56      return X86EMUL_CONTINUE;
    1.57  }
    1.58  
    1.59 -static int cmpxchg8b_any(
    1.60 -    unsigned long addr,
    1.61 +static int cmpxchg8b(
    1.62 +    unsigned int seg,
    1.63 +    unsigned long offset,
    1.64      unsigned long old_lo,
    1.65      unsigned long old_hi,
    1.66      unsigned long new_lo,
    1.67      unsigned long new_hi,
    1.68      struct x86_emulate_ctxt *ctxt)
    1.69  {
    1.70 +    unsigned long addr = offset;
    1.71      ((unsigned long *)addr)[0] = new_lo;
    1.72      ((unsigned long *)addr)[1] = new_hi;
    1.73      return X86EMUL_CONTINUE;
    1.74  }
    1.75  
    1.76  static struct x86_emulate_ops emulops = {
    1.77 -    read_any, write_any, read_any, write_any, cmpxchg_any, cmpxchg8b_any
    1.78 +    read, write, cmpxchg, cmpxchg8b
    1.79  };
    1.80  
    1.81  int main(int argc, char **argv)
    1.82 @@ -108,7 +116,7 @@ int main(int argc, char **argv)
    1.83      regs.eip    = (unsigned long)&instr[0];
    1.84      regs.ecx    = 0x12345678;
    1.85      regs.error_code = PFEC_write_access;
    1.86 -    ctxt.cr2    = (unsigned long)res;
    1.87 +    regs.eax    = (unsigned long)res;
    1.88      *res        = 0x7FFFFFFF;
    1.89      rc = x86_emulate_memop(&ctxt, &emulops);
    1.90      if ( (rc != 0) || 
    1.91 @@ -127,7 +135,7 @@ int main(int argc, char **argv)
    1.92  #else
    1.93      regs.ecx    = 0x12345678UL;
    1.94  #endif
    1.95 -    ctxt.cr2    = (unsigned long)res;
    1.96 +    regs.eax    = (unsigned long)res;
    1.97      regs.error_code = 0;
    1.98      rc = x86_emulate_memop(&ctxt, &emulops);
    1.99      if ( (rc != 0) || 
   1.100 @@ -142,7 +150,7 @@ int main(int argc, char **argv)
   1.101      regs.eflags = 0x200;
   1.102      regs.eip    = (unsigned long)&instr[0];
   1.103      regs.ecx    = ~0UL;
   1.104 -    ctxt.cr2    = (unsigned long)res;
   1.105 +    regs.eax    = (unsigned long)res;
   1.106      regs.error_code = 0;
   1.107      rc = x86_emulate_memop(&ctxt, &emulops);
   1.108      if ( (rc != 0) || 
   1.109 @@ -152,13 +160,13 @@ int main(int argc, char **argv)
   1.110          goto fail;
   1.111      printf("okay\n");
   1.112  
   1.113 -    printf("%-40s", "Testing lock cmpxchgb %%cl,(%%eax)...");
   1.114 -    instr[0] = 0xf0; instr[1] = 0x0f; instr[2] = 0xb0; instr[3] = 0x08;
   1.115 +    printf("%-40s", "Testing lock cmpxchgb %%cl,(%%ebx)...");
   1.116 +    instr[0] = 0xf0; instr[1] = 0x0f; instr[2] = 0xb0; instr[3] = 0x0b;
   1.117      regs.eflags = 0x200;
   1.118      regs.eip    = (unsigned long)&instr[0];
   1.119      regs.eax    = 0x92345677UL;
   1.120      regs.ecx    = 0xAA;
   1.121 -    ctxt.cr2    = (unsigned long)res;
   1.122 +    regs.ebx    = (unsigned long)res;
   1.123      regs.error_code = PFEC_write_access;
   1.124      rc = x86_emulate_memop(&ctxt, &emulops);
   1.125      if ( (rc != 0) || 
   1.126 @@ -169,13 +177,13 @@ int main(int argc, char **argv)
   1.127          goto fail;
   1.128      printf("okay\n");
   1.129  
   1.130 -    printf("%-40s", "Testing lock cmpxchgb %%cl,(%%eax)...");
   1.131 -    instr[0] = 0xf0; instr[1] = 0x0f; instr[2] = 0xb0; instr[3] = 0x08;
   1.132 +    printf("%-40s", "Testing lock cmpxchgb %%cl,(%%ebx)...");
   1.133 +    instr[0] = 0xf0; instr[1] = 0x0f; instr[2] = 0xb0; instr[3] = 0x0b;
   1.134      regs.eflags = 0x200;
   1.135      regs.eip    = (unsigned long)&instr[0];
   1.136      regs.eax    = 0xAABBCC77UL;
   1.137      regs.ecx    = 0xFF;
   1.138 -    ctxt.cr2    = (unsigned long)res;
   1.139 +    regs.ebx    = (unsigned long)res;
   1.140      regs.error_code = PFEC_write_access;
   1.141      rc = x86_emulate_memop(&ctxt, &emulops);
   1.142      if ( (rc != 0) || 
   1.143 @@ -192,7 +200,7 @@ int main(int argc, char **argv)
   1.144      regs.eflags = 0x200;
   1.145      regs.eip    = (unsigned long)&instr[0];
   1.146      regs.ecx    = 0x12345678;
   1.147 -    ctxt.cr2    = (unsigned long)res;
   1.148 +    regs.eax    = (unsigned long)res;
   1.149      regs.error_code = PFEC_write_access;
   1.150      rc = x86_emulate_memop(&ctxt, &emulops);
   1.151      if ( (rc != 0) || 
   1.152 @@ -203,14 +211,14 @@ int main(int argc, char **argv)
   1.153          goto fail;
   1.154      printf("okay\n");
   1.155  
   1.156 -    printf("%-40s", "Testing lock cmpxchgl %%ecx,(%%eax)...");
   1.157 -    instr[0] = 0xf0; instr[1] = 0x0f; instr[2] = 0xb1; instr[3] = 0x08;
   1.158 +    printf("%-40s", "Testing lock cmpxchgl %%ecx,(%%ebx)...");
   1.159 +    instr[0] = 0xf0; instr[1] = 0x0f; instr[2] = 0xb1; instr[3] = 0x0b;
   1.160      regs.eflags = 0x200;
   1.161      *res        = 0x923456AA;
   1.162      regs.eip    = (unsigned long)&instr[0];
   1.163      regs.eax    = 0x923456AAUL;
   1.164      regs.ecx    = 0xDDEEFF00L;
   1.165 -    ctxt.cr2    = (unsigned long)res;
   1.166 +    regs.ebx    = (unsigned long)res;
   1.167      regs.error_code = PFEC_write_access;
   1.168      rc = x86_emulate_memop(&ctxt, &emulops);
   1.169      if ( (rc != 0) || 
   1.170 @@ -230,7 +238,6 @@ int main(int argc, char **argv)
   1.171      regs.esi    = (unsigned long)res + 0;
   1.172      regs.edi    = (unsigned long)res + 2;
   1.173      regs.error_code = 0; /* read fault */
   1.174 -    ctxt.cr2    = regs.esi;
   1.175      rc = x86_emulate_memop(&ctxt, &emulops);
   1.176      if ( (rc != 0) || 
   1.177           (*res != 0x44554455) ||
   1.178 @@ -248,7 +255,6 @@ int main(int argc, char **argv)
   1.179      regs.eflags = 0x200;
   1.180      regs.eip    = (unsigned long)&instr[0];
   1.181      regs.edi    = (unsigned long)res;
   1.182 -    ctxt.cr2    = regs.edi;
   1.183      regs.error_code = PFEC_write_access;
   1.184      rc = x86_emulate_memop(&ctxt, &emulops);
   1.185      if ( (rc != 0) || 
   1.186 @@ -258,6 +264,22 @@ int main(int argc, char **argv)
   1.187          goto fail;
   1.188      printf("okay\n");
   1.189  
   1.190 +    printf("%-40s", "Testing btrl %eax,(%edi)...");
   1.191 +    instr[0] = 0x0f; instr[1] = 0xb3; instr[2] = 0x07;
   1.192 +    *res        = 0x2233445F;
   1.193 +    regs.eflags = 0x200;
   1.194 +    regs.eip    = (unsigned long)&instr[0];
   1.195 +    regs.eax    = -32;
   1.196 +    regs.edi    = (unsigned long)(res+1);
   1.197 +    regs.error_code = PFEC_write_access;
   1.198 +    rc = x86_emulate_memop(&ctxt, &emulops);
   1.199 +    if ( (rc != 0) || 
   1.200 +         (*res != 0x2233445E) ||
   1.201 +         ((regs.eflags&0x201) != 0x201) ||
   1.202 +         (regs.eip != (unsigned long)&instr[3]) )
   1.203 +        goto fail;
   1.204 +    printf("okay\n");
   1.205 +
   1.206      res[0] = 0x12345678;
   1.207      res[1] = 0x87654321;
   1.208  
   1.209 @@ -270,7 +292,6 @@ int main(int argc, char **argv)
   1.210      regs.ecx    = 0xCCCCFFFF;
   1.211      regs.eip    = (unsigned long)&instr[0];
   1.212      regs.edi    = (unsigned long)res;
   1.213 -    ctxt.cr2    = regs.edi;
   1.214      regs.error_code = PFEC_write_access;
   1.215      rc = x86_emulate_memop(&ctxt, &emulops);
   1.216      if ( (rc != 0) || 
   1.217 @@ -285,7 +306,6 @@ int main(int argc, char **argv)
   1.218      instr[0] = 0x0f; instr[1] = 0xc7; instr[2] = 0x0f;
   1.219      regs.eip    = (unsigned long)&instr[0];
   1.220      regs.edi    = (unsigned long)res;
   1.221 -    ctxt.cr2    = regs.edi;
   1.222      regs.error_code = PFEC_write_access;
   1.223      rc = x86_emulate_memop(&ctxt, &emulops);
   1.224      if ( (rc != 0) || 
   1.225 @@ -302,7 +322,7 @@ int main(int argc, char **argv)
   1.226      instr[0] = 0x0f; instr[1] = 0xbe; instr[2] = 0x08;
   1.227      regs.eip    = (unsigned long)&instr[0];
   1.228      regs.ecx    = 0x12345678;
   1.229 -    ctxt.cr2    = (unsigned long)res;
   1.230 +    regs.eax    = (unsigned long)res;
   1.231      *res        = 0x82;
   1.232      regs.error_code = 0;
   1.233      rc = x86_emulate_memop(&ctxt, &emulops);
   1.234 @@ -318,7 +338,7 @@ int main(int argc, char **argv)
   1.235      instr[0] = 0x0f; instr[1] = 0xb7; instr[2] = 0x08;
   1.236      regs.eip    = (unsigned long)&instr[0];
   1.237      regs.ecx    = 0x12345678;
   1.238 -    ctxt.cr2    = (unsigned long)res;
   1.239 +    regs.eax    = (unsigned long)res;
   1.240      *res        = 0x1234aa82;
   1.241      regs.error_code = 0;
   1.242      rc = x86_emulate_memop(&ctxt, &emulops);
     2.1 --- a/xen/arch/x86/mm.c	Wed Nov 29 23:40:40 2006 +0000
     2.2 +++ b/xen/arch/x86/mm.c	Thu Nov 30 10:57:28 2006 +0000
     2.3 @@ -3033,12 +3033,39 @@ long arch_memory_op(int op, XEN_GUEST_HA
     2.4   * Writable Pagetables
     2.5   */
     2.6  
     2.7 +struct ptwr_emulate_ctxt {
     2.8 +    struct x86_emulate_ctxt ctxt;
     2.9 +    unsigned long cr2;
    2.10 +    l1_pgentry_t  pte;
    2.11 +};
    2.12 +
    2.13 +static int ptwr_emulated_read(
    2.14 +    unsigned int seg,
    2.15 +    unsigned long offset,
    2.16 +    unsigned long *val,
    2.17 +    unsigned int bytes,
    2.18 +    struct x86_emulate_ctxt *ctxt)
    2.19 +{
    2.20 +    unsigned int rc;
    2.21 +    unsigned long addr = offset;
    2.22 +
    2.23 +    *val = 0;
    2.24 +    if ( (rc = copy_from_user((void *)val, (void *)addr, bytes)) != 0 )
    2.25 +    {
    2.26 +        propagate_page_fault(addr + bytes - rc, 0); /* read fault */
    2.27 +        return X86EMUL_PROPAGATE_FAULT;
    2.28 +    }
    2.29 +
    2.30 +    return X86EMUL_CONTINUE;
    2.31 +}
    2.32 +
    2.33  static int ptwr_emulated_update(
    2.34      unsigned long addr,
    2.35      paddr_t old,
    2.36      paddr_t val,
    2.37      unsigned int bytes,
    2.38 -    unsigned int do_cmpxchg)
    2.39 +    unsigned int do_cmpxchg,
    2.40 +    struct ptwr_emulate_ctxt *ptwr_ctxt)
    2.41  {
    2.42      unsigned long gmfn, mfn;
    2.43      struct page_info *page;
    2.44 @@ -3046,11 +3073,11 @@ static int ptwr_emulated_update(
    2.45      struct vcpu *v = current;
    2.46      struct domain *d = v->domain;
    2.47  
    2.48 -    /* Aligned access only, thank you. */
    2.49 -    if ( !access_ok(addr, bytes) || ((addr & (bytes-1)) != 0) )
    2.50 +    /* Only allow naturally-aligned stores within the original %cr2 page. */
    2.51 +    if ( unlikely(((addr^ptwr_ctxt->cr2) & PAGE_MASK) || (addr & (bytes-1))) )
    2.52      {
    2.53 -        MEM_LOG("ptwr_emulate: Unaligned or bad size ptwr access (%d, %lx)",
    2.54 -                bytes, addr);
    2.55 +        MEM_LOG("Bad ptwr access (cr2=%lx, addr=%lx, bytes=%u)",
    2.56 +                ptwr_ctxt->cr2, addr, bytes);
    2.57          return X86EMUL_UNHANDLEABLE;
    2.58      }
    2.59  
    2.60 @@ -3079,17 +3106,9 @@ static int ptwr_emulated_update(
    2.61          old  |= full;
    2.62      }
    2.63  
    2.64 -    /* Read the PTE that maps the page being updated. */
    2.65 -    guest_get_eff_l1e(v, addr, &pte);
    2.66 -    if ( unlikely(!(l1e_get_flags(pte) & _PAGE_PRESENT)) )
    2.67 -    {
    2.68 -        MEM_LOG("%s: Cannot get L1 PTE for guest address %lx",
    2.69 -                __func__, addr);
    2.70 -        return X86EMUL_UNHANDLEABLE;
    2.71 -    }
    2.72 -
    2.73 -    gmfn  = l1e_get_pfn(pte);
    2.74 -    mfn = gmfn_to_mfn(d, gmfn);
    2.75 +    pte  = ptwr_ctxt->pte;
    2.76 +    gmfn = l1e_get_pfn(pte);
    2.77 +    mfn  = gmfn_to_mfn(d, gmfn);
    2.78      page = mfn_to_page(mfn);
    2.79  
    2.80      /* We are looking only for read-only mappings of p.t. pages. */
    2.81 @@ -3164,26 +3183,33 @@ static int ptwr_emulated_update(
    2.82  }
    2.83  
    2.84  static int ptwr_emulated_write(
    2.85 -    unsigned long addr,
    2.86 +    unsigned int seg,
    2.87 +    unsigned long offset,
    2.88      unsigned long val,
    2.89      unsigned int bytes,
    2.90      struct x86_emulate_ctxt *ctxt)
    2.91  {
    2.92 -    return ptwr_emulated_update(addr, 0, val, bytes, 0);
    2.93 +    return ptwr_emulated_update(
    2.94 +        offset, 0, val, bytes, 0,
    2.95 +        container_of(ctxt, struct ptwr_emulate_ctxt, ctxt));
    2.96  }
    2.97  
    2.98  static int ptwr_emulated_cmpxchg(
    2.99 -    unsigned long addr,
   2.100 +    unsigned int seg,
   2.101 +    unsigned long offset,
   2.102      unsigned long old,
   2.103      unsigned long new,
   2.104      unsigned int bytes,
   2.105      struct x86_emulate_ctxt *ctxt)
   2.106  {
   2.107 -    return ptwr_emulated_update(addr, old, new, bytes, 1);
   2.108 +    return ptwr_emulated_update(
   2.109 +        offset, old, new, bytes, 1,
   2.110 +        container_of(ctxt, struct ptwr_emulate_ctxt, ctxt));
   2.111  }
   2.112  
   2.113  static int ptwr_emulated_cmpxchg8b(
   2.114 -    unsigned long addr,
   2.115 +    unsigned int seg,
   2.116 +    unsigned long offset,
   2.117      unsigned long old,
   2.118      unsigned long old_hi,
   2.119      unsigned long new,
   2.120 @@ -3192,18 +3218,16 @@ static int ptwr_emulated_cmpxchg8b(
   2.121  {
   2.122      if ( CONFIG_PAGING_LEVELS == 2 )
   2.123          return X86EMUL_UNHANDLEABLE;
   2.124 -    else
   2.125 -        return ptwr_emulated_update(
   2.126 -            addr, ((u64)old_hi << 32) | old, ((u64)new_hi << 32) | new, 8, 1);
   2.127 +    return ptwr_emulated_update(
   2.128 +        offset, ((u64)old_hi << 32) | old, ((u64)new_hi << 32) | new, 8, 1,
   2.129 +        container_of(ctxt, struct ptwr_emulate_ctxt, ctxt));
   2.130  }
   2.131  
   2.132  static struct x86_emulate_ops ptwr_emulate_ops = {
   2.133 -    .read_std           = x86_emulate_read_std,
   2.134 -    .write_std          = x86_emulate_write_std,
   2.135 -    .read_emulated      = x86_emulate_read_std,
   2.136 -    .write_emulated     = ptwr_emulated_write,
   2.137 -    .cmpxchg_emulated   = ptwr_emulated_cmpxchg,
   2.138 -    .cmpxchg8b_emulated = ptwr_emulated_cmpxchg8b
   2.139 +    .read      = ptwr_emulated_read,
   2.140 +    .write     = ptwr_emulated_write,
   2.141 +    .cmpxchg   = ptwr_emulated_cmpxchg,
   2.142 +    .cmpxchg8b = ptwr_emulated_cmpxchg8b
   2.143  };
   2.144  
   2.145  /* Write page fault handler: check if guest is trying to modify a PTE. */
   2.146 @@ -3214,7 +3238,7 @@ int ptwr_do_page_fault(struct vcpu *v, u
   2.147      unsigned long     pfn;
   2.148      struct page_info *page;
   2.149      l1_pgentry_t      pte;
   2.150 -    struct x86_emulate_ctxt emul_ctxt;
   2.151 +    struct ptwr_emulate_ctxt ptwr_ctxt;
   2.152  
   2.153      LOCK_BIGLOCK(d);
   2.154  
   2.155 @@ -3235,10 +3259,11 @@ int ptwr_do_page_fault(struct vcpu *v, u
   2.156           (page_get_owner(page) != d) )
   2.157          goto bail;
   2.158  
   2.159 -    emul_ctxt.regs = guest_cpu_user_regs();
   2.160 -    emul_ctxt.cr2  = addr;
   2.161 -    emul_ctxt.mode = X86EMUL_MODE_HOST;
   2.162 -    if ( x86_emulate_memop(&emul_ctxt, &ptwr_emulate_ops) )
   2.163 +    ptwr_ctxt.ctxt.regs = guest_cpu_user_regs();
   2.164 +    ptwr_ctxt.ctxt.mode = X86EMUL_MODE_HOST;
   2.165 +    ptwr_ctxt.cr2       = addr;
   2.166 +    ptwr_ctxt.pte       = pte;
   2.167 +    if ( x86_emulate_memop(&ptwr_ctxt.ctxt, &ptwr_emulate_ops) )
   2.168          goto bail;
   2.169  
   2.170      UNLOCK_BIGLOCK(d);
     3.1 --- a/xen/arch/x86/mm/shadow/common.c	Wed Nov 29 23:40:40 2006 +0000
     3.2 +++ b/xen/arch/x86/mm/shadow/common.c	Thu Nov 30 10:57:28 2006 +0000
     3.3 @@ -70,11 +70,14 @@ int _shadow_mode_refcounts(struct domain
     3.4   */
     3.5  
     3.6  static int
     3.7 -sh_x86_emulate_read_std(unsigned long addr,
     3.8 -                         unsigned long *val,
     3.9 -                         unsigned int bytes,
    3.10 -                         struct x86_emulate_ctxt *ctxt)
    3.11 +sh_x86_emulate_read(unsigned int seg,
    3.12 +                    unsigned long offset,
    3.13 +                    unsigned long *val,
    3.14 +                    unsigned int bytes,
    3.15 +                    struct x86_emulate_ctxt *ctxt)
    3.16  {
    3.17 +    unsigned long addr = offset;
    3.18 +
    3.19      *val = 0;
    3.20      // XXX -- this is WRONG.
    3.21      //        It entirely ignores the permissions in the page tables.
    3.22 @@ -99,40 +102,15 @@ sh_x86_emulate_read_std(unsigned long ad
    3.23  }
    3.24  
    3.25  static int
    3.26 -sh_x86_emulate_write_std(unsigned long addr,
    3.27 -                          unsigned long val,
    3.28 -                          unsigned int bytes,
    3.29 -                          struct x86_emulate_ctxt *ctxt)
    3.30 -{
    3.31 -#if 0
    3.32 -    struct vcpu *v = current;
    3.33 -    SHADOW_PRINTK("d=%u v=%u a=%#lx v=%#lx bytes=%u\n",
    3.34 -                  v->domain->domain_id, v->vcpu_id, addr, val, bytes);
    3.35 -#endif
    3.36 -
    3.37 -    // XXX -- this is WRONG.
    3.38 -    //        It entirely ignores the permissions in the page tables.
    3.39 -    //        In this case, that includes user vs supervisor, and
    3.40 -    //        write access.
    3.41 -    //
    3.42 -    if ( hvm_copy_to_guest_virt(addr, &val, bytes) == 0 )
    3.43 -        return X86EMUL_CONTINUE;
    3.44 -
    3.45 -    /* If we got here, there was nothing mapped here, or a bad GFN 
    3.46 -     * was mapped here.  This should never happen: we're here because
    3.47 -     * of a write fault at the end of the instruction we're emulating,
    3.48 -     * which should be handled by sh_x86_emulate_write_emulated. */ 
    3.49 -    SHADOW_PRINTK("write failed to va %#lx\n", addr);
    3.50 -    return X86EMUL_PROPAGATE_FAULT;
    3.51 -}
    3.52 -
    3.53 -static int
    3.54 -sh_x86_emulate_write_emulated(unsigned long addr,
    3.55 -                               unsigned long val,
    3.56 -                               unsigned int bytes,
    3.57 -                               struct x86_emulate_ctxt *ctxt)
    3.58 +sh_x86_emulate_write(unsigned int seg,
    3.59 +                     unsigned long offset,
    3.60 +                     unsigned long val,
    3.61 +                     unsigned int bytes,
    3.62 +                     struct x86_emulate_ctxt *ctxt)
    3.63  {
    3.64      struct vcpu *v = current;
    3.65 +    unsigned long addr = offset;
    3.66 +
    3.67  #if 0
    3.68      SHADOW_PRINTK("d=%u v=%u a=%#lx v=%#lx bytes=%u\n",
    3.69                    v->domain->domain_id, v->vcpu_id, addr, val, bytes);
    3.70 @@ -141,13 +119,16 @@ sh_x86_emulate_write_emulated(unsigned l
    3.71  }
    3.72  
    3.73  static int 
    3.74 -sh_x86_emulate_cmpxchg_emulated(unsigned long addr,
    3.75 -                                 unsigned long old,
    3.76 -                                 unsigned long new,
    3.77 -                                 unsigned int bytes,
    3.78 -                                 struct x86_emulate_ctxt *ctxt)
    3.79 +sh_x86_emulate_cmpxchg(unsigned int seg,
    3.80 +                       unsigned long offset,
    3.81 +                       unsigned long old,
    3.82 +                       unsigned long new,
    3.83 +                       unsigned int bytes,
    3.84 +                       struct x86_emulate_ctxt *ctxt)
    3.85  {
    3.86      struct vcpu *v = current;
    3.87 +    unsigned long addr = offset;
    3.88 +
    3.89  #if 0
    3.90      SHADOW_PRINTK("d=%u v=%u a=%#lx o?=%#lx n:=%#lx bytes=%u\n",
    3.91                     v->domain->domain_id, v->vcpu_id, addr, old, new, bytes);
    3.92 @@ -157,14 +138,17 @@ sh_x86_emulate_cmpxchg_emulated(unsigned
    3.93  }
    3.94  
    3.95  static int 
    3.96 -sh_x86_emulate_cmpxchg8b_emulated(unsigned long addr,
    3.97 -                                   unsigned long old_lo,
    3.98 -                                   unsigned long old_hi,
    3.99 -                                   unsigned long new_lo,
   3.100 -                                   unsigned long new_hi,
   3.101 -                                   struct x86_emulate_ctxt *ctxt)
   3.102 +sh_x86_emulate_cmpxchg8b(unsigned int seg,
   3.103 +                         unsigned long offset,
   3.104 +                         unsigned long old_lo,
   3.105 +                         unsigned long old_hi,
   3.106 +                         unsigned long new_lo,
   3.107 +                         unsigned long new_hi,
   3.108 +                         struct x86_emulate_ctxt *ctxt)
   3.109  {
   3.110      struct vcpu *v = current;
   3.111 +    unsigned long addr = offset;
   3.112 +
   3.113  #if 0
   3.114      SHADOW_PRINTK("d=%u v=%u a=%#lx o?=%#lx:%lx n:=%#lx:%lx\n",
   3.115                     v->domain->domain_id, v->vcpu_id, addr, old_hi, old_lo,
   3.116 @@ -176,12 +160,10 @@ sh_x86_emulate_cmpxchg8b_emulated(unsign
   3.117  
   3.118  
   3.119  struct x86_emulate_ops shadow_emulator_ops = {
   3.120 -    .read_std           = sh_x86_emulate_read_std,
   3.121 -    .write_std          = sh_x86_emulate_write_std,
   3.122 -    .read_emulated      = sh_x86_emulate_read_std,
   3.123 -    .write_emulated     = sh_x86_emulate_write_emulated,
   3.124 -    .cmpxchg_emulated   = sh_x86_emulate_cmpxchg_emulated,
   3.125 -    .cmpxchg8b_emulated = sh_x86_emulate_cmpxchg8b_emulated,
   3.126 +    .read      = sh_x86_emulate_read,
   3.127 +    .write     = sh_x86_emulate_write,
   3.128 +    .cmpxchg   = sh_x86_emulate_cmpxchg,
   3.129 +    .cmpxchg8b = sh_x86_emulate_cmpxchg8b,
   3.130  };
   3.131  
   3.132  /**************************************************************************/
     4.1 --- a/xen/arch/x86/mm/shadow/multi.c	Wed Nov 29 23:40:40 2006 +0000
     4.2 +++ b/xen/arch/x86/mm/shadow/multi.c	Thu Nov 30 10:57:28 2006 +0000
     4.3 @@ -2812,7 +2812,6 @@ static int sh_page_fault(struct vcpu *v,
     4.4      if ( is_hvm_domain(d) )
     4.5          hvm_store_cpu_guest_regs(v, regs, NULL);
     4.6      emul_ctxt.regs = regs;
     4.7 -    emul_ctxt.cr2  = va;
     4.8      emul_ctxt.mode = (is_hvm_domain(d) ?
     4.9                        hvm_guest_x86_mode(v) : X86EMUL_MODE_HOST);
    4.10  
     5.1 --- a/xen/arch/x86/x86_emulate.c	Wed Nov 29 23:40:40 2006 +0000
     5.2 +++ b/xen/arch/x86/x86_emulate.c	Thu Nov 30 10:57:28 2006 +0000
     5.3 @@ -15,9 +15,9 @@
     5.4  #include <xen/config.h>
     5.5  #include <xen/types.h>
     5.6  #include <xen/lib.h>
     5.7 -#include <xen/mm.h>
     5.8  #include <asm/regs.h>
     5.9  #define dprintf(_f, _a...) gdprintk(XENLOG_WARNING, _f , ## _a )
    5.10 +#undef cmpxchg
    5.11  #endif
    5.12  #include <asm-x86/x86_emulate.h>
    5.13  
    5.14 @@ -38,6 +38,7 @@
    5.15  /* Operand sizes: 8-bit operands or specified/overridden size. */
    5.16  #define ByteOp      (1<<0) /* 8-bit operands. */
    5.17  /* Destination operand type. */
    5.18 +#define DstBitBase  (0<<1) /* Memory operand, bit string. */
    5.19  #define ImplicitOps (1<<1) /* Implicit in opcode. No generic decode. */
    5.20  #define DstReg      (2<<1) /* Register operand. */
    5.21  #define DstMem      (3<<1) /* Memory operand. */
    5.22 @@ -111,8 +112,8 @@ static uint8_t opcode_table[256] = {
    5.23      /* 0x90 - 0x9F */
    5.24      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    5.25      /* 0xA0 - 0xA7 */
    5.26 -    ByteOp|DstReg|SrcMem|Mov, DstReg|SrcMem|Mov,
    5.27 -    ByteOp|DstMem|SrcReg|Mov, DstMem|SrcReg|Mov,
    5.28 +    ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
    5.29 +    ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
    5.30      ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, 0, 0,
    5.31      /* 0xA8 - 0xAF */
    5.32      0, 0, ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
    5.33 @@ -170,14 +171,15 @@ static uint8_t twobyte_table[256] = {
    5.34      /* 0x90 - 0x9F */
    5.35      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    5.36      /* 0xA0 - 0xA7 */
    5.37 -    0, 0, 0, DstMem|SrcReg|ModRM, 0, 0, 0, 0, 
    5.38 +    0, 0, 0, DstBitBase|SrcReg|ModRM, 0, 0, 0, 0, 
    5.39      /* 0xA8 - 0xAF */
    5.40 -    0, 0, 0, DstMem|SrcReg|ModRM, 0, 0, 0, 0,
    5.41 +    0, 0, 0, DstBitBase|SrcReg|ModRM, 0, 0, 0, 0,
    5.42      /* 0xB0 - 0xB7 */
    5.43 -    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, 0, DstMem|SrcReg|ModRM,
    5.44 +    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
    5.45 +    0, DstBitBase|SrcReg|ModRM,
    5.46      0, 0, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov,
    5.47      /* 0xB8 - 0xBF */
    5.48 -    0, 0, DstMem|SrcImmByte|ModRM, DstMem|SrcReg|ModRM,
    5.49 +    0, 0, DstBitBase|SrcImmByte|ModRM, DstBitBase|SrcReg|ModRM,
    5.50      0, 0, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov,
    5.51      /* 0xC0 - 0xCF */
    5.52      0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0, 0, 0, 0, 0, 0, 0,
    5.53 @@ -193,7 +195,12 @@ static uint8_t twobyte_table[256] = {
    5.54  struct operand {
    5.55      enum { OP_REG, OP_MEM, OP_IMM } type;
    5.56      unsigned int  bytes;
    5.57 -    unsigned long val, orig_val, *ptr;
    5.58 +    unsigned long val, orig_val;
    5.59 +    /* OP_REG: Pointer to register field. */
    5.60 +    unsigned long *reg;
    5.61 +    /* OP_MEM: Segment and offset. */
    5.62 +    unsigned int  mem_seg;
    5.63 +    unsigned long mem_off;
    5.64  };
    5.65  
    5.66  /* EFLAGS bit definitions. */
    5.67 @@ -366,24 +373,23 @@ do{ __asm__ __volatile__ (              
    5.68  #endif /* __i386__ */
    5.69  
    5.70  /* Fetch next part of the instruction being emulated. */
    5.71 -#define _insn_fetch(_size)                                              \
    5.72 -({ unsigned long _x, _ptr = _regs.eip;                                  \
    5.73 -   if ( mode == X86EMUL_MODE_REAL ) _ptr += _regs.cs << 4;              \
    5.74 -   rc = ops->read_std(_ptr, &_x, (_size), ctxt);                        \
    5.75 -   if ( rc != 0 )                                                       \
    5.76 -       goto done;                                                       \
    5.77 -   _regs.eip += (_size);                                                \
    5.78 -   _x;                                                                  \
    5.79 +#define _insn_fetch(_size)                                      \
    5.80 +({ unsigned long _x;                                            \
    5.81 +   rc = ops->read(_regs.cs, _regs.eip, &_x, (_size), ctxt);     \
    5.82 +   if ( rc != 0 )                                               \
    5.83 +       goto done;                                               \
    5.84 +   _regs.eip += (_size);                                        \
    5.85 +   _x;                                                          \
    5.86  })
    5.87  #define insn_fetch(_type) ((_type)_insn_fetch(sizeof(_type)))
    5.88  
    5.89 -/* Access/update address held in a register, based on addressing mode. */
    5.90 -#define register_address(sel, reg)                                      \
    5.91 -({  unsigned long __reg = (reg);                                        \
    5.92 -    (((mode == X86EMUL_MODE_REAL) ? ((unsigned long)(sel) << 4) : 0) +  \
    5.93 -     ((ad_bytes == sizeof(unsigned long)) ? __reg :                     \
    5.94 -      (__reg & ((1UL << (ad_bytes << 3)) - 1))));                       \
    5.95 +#define truncate_ea(ea)                                 \
    5.96 +({  unsigned long __ea = (ea);                          \
    5.97 +    ((ad_bytes == sizeof(unsigned long)) ? __ea :       \
    5.98 +     (__ea & ((1UL << (ad_bytes << 3)) - 1)));          \
    5.99  })
   5.100 +
   5.101 +/* Update address held in a register, based on addressing mode. */
   5.102  #define register_address_increment(reg, inc)                            \
   5.103  do {                                                                    \
   5.104      int _inc = (inc); /* signed type ensures sign extension to long */  \
   5.105 @@ -394,17 +400,6 @@ do {                                    
   5.106                  (((reg) + _inc) & ((1UL << (ad_bytes << 3)) - 1));      \
   5.107  } while (0)
   5.108  
   5.109 -/*
   5.110 - * We cannot handle a page fault on a data access that straddles two pages
   5.111 - * and faults on the second page. This is because CR2 is not equal to the
   5.112 - * memory operand's effective address in this case. Rather than fix up the
   5.113 - * effective address it is okay for us to fail the emulation.
   5.114 - */
   5.115 -#define page_boundary_test() do {                               \
   5.116 -    if ( ((cr2 & (PAGE_SIZE-1)) == 0) && ((ea & 7) != 0) )      \
   5.117 -        goto bad_ea;                                            \
   5.118 -} while ( 0 )
   5.119 -
   5.120  void *
   5.121  decode_register(
   5.122      uint8_t modrm_reg, struct cpu_user_regs *regs, int highbyte_regs)
   5.123 @@ -452,16 +447,12 @@ dump_instr(
   5.124  {
   5.125  #ifdef __XEN__
   5.126      int i;
   5.127 -    unsigned long x, pc;
   5.128 -
   5.129 -    pc = ctxt->regs->eip;
   5.130 -    if ( ctxt->mode == X86EMUL_MODE_REAL )
   5.131 -        pc += ctxt->regs->cs << 4;
   5.132 +    unsigned long x, eip = ctxt->regs->eip;
   5.133  
   5.134      dprintf("Instr:");
   5.135 -    for ( i = 0; i < 16; i++, pc++ )
   5.136 +    for ( i = 0; i < 16; i++, eip++ )
   5.137      {
   5.138 -        if ( ops->read_std(pc, &x, 1, ctxt) != 0 )
   5.139 +        if ( ops->read(ctxt->regs->cs, eip, &x, 1, ctxt) != 0 )
   5.140              printk(" ??");
   5.141          else
   5.142              printk(" %02x", (uint8_t)x);
   5.143 @@ -480,19 +471,13 @@ x86_emulate_memop(
   5.144  
   5.145      uint8_t b, d, sib, sib_index, sib_base, twobyte = 0, rex_prefix = 0;
   5.146      uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
   5.147 -    uint16_t *seg = &_regs.ds; /* override segment */
   5.148      unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i;
   5.149      int rc = 0;
   5.150      struct operand src, dst;
   5.151 -    unsigned long ea = 0, cr2 = ctxt->cr2;
   5.152      int mode = ctxt->mode;
   5.153  
   5.154 -    /*
   5.155 -     * We do not emulate faults on instruction fetch. We assume that the
   5.156 -     * guest never executes out of a special memory area.
   5.157 -     */
   5.158 -    if ( _regs.error_code & PFEC_insn_fetch )
   5.159 -        return -1;
   5.160 +    unsigned int  ea_seg = X86_SEG_DS;
   5.161 +    unsigned long ea_off = 0;
   5.162  
   5.163      switch ( mode )
   5.164      {
   5.165 @@ -528,22 +513,22 @@ x86_emulate_memop(
   5.166                  ad_bytes ^= 6;  /* switch between 2/4 bytes */
   5.167              break;
   5.168          case 0x2e: /* CS override */
   5.169 -            seg = &_regs.cs;
   5.170 +            ea_seg = X86_SEG_CS;
   5.171              break;
   5.172          case 0x3e: /* DS override */
   5.173 -            seg = &_regs.ds;
   5.174 +            ea_seg = X86_SEG_DS;
   5.175              break;
   5.176          case 0x26: /* ES override */
   5.177 -            seg = &_regs.es;
   5.178 +            ea_seg = X86_SEG_ES;
   5.179              break;
   5.180          case 0x64: /* FS override */
   5.181 -            seg = &_regs.fs;
   5.182 +            ea_seg = X86_SEG_FS;
   5.183              break;
   5.184          case 0x65: /* GS override */
   5.185 -            seg = &_regs.gs;
   5.186 +            ea_seg = X86_SEG_GS;
   5.187              break;
   5.188          case 0x36: /* SS override */
   5.189 -            seg = &_regs.ss;
   5.190 +            ea_seg = X86_SEG_SS;
   5.191              break;
   5.192          case 0xf0: /* LOCK */
   5.193              lock_prefix = 1;
   5.194 @@ -604,20 +589,20 @@ x86_emulate_memop(
   5.195              /* 16-bit ModR/M decode. */
   5.196              switch ( modrm_rm )
   5.197              {
   5.198 -            case 0: ea = _regs.ebx + _regs.esi; break;
   5.199 -            case 1: ea = _regs.ebx + _regs.edi; break;
   5.200 -            case 2: ea = _regs.ebp + _regs.esi; break;
   5.201 -            case 3: ea = _regs.ebp + _regs.edi; break;
   5.202 -            case 4: ea = _regs.esi; break;
   5.203 -            case 5: ea = _regs.edi; break;
   5.204 -            case 6: ea = _regs.ebp; break;
   5.205 -            case 7: ea = _regs.ebx; break;
   5.206 +            case 0: ea_off = _regs.ebx + _regs.esi; break;
   5.207 +            case 1: ea_off = _regs.ebx + _regs.edi; break;
   5.208 +            case 2: ea_off = _regs.ebp + _regs.esi; break;
   5.209 +            case 3: ea_off = _regs.ebp + _regs.edi; break;
   5.210 +            case 4: ea_off = _regs.esi; break;
   5.211 +            case 5: ea_off = _regs.edi; break;
   5.212 +            case 6: ea_off = _regs.ebp; break;
   5.213 +            case 7: ea_off = _regs.ebx; break;
   5.214              }
   5.215              switch ( modrm_mod )
   5.216              {
   5.217 -            case 0: if ( modrm_rm == 6 ) ea = insn_fetch(int16_t); break;
   5.218 -            case 1: ea += insn_fetch(int8_t);  break;
   5.219 -            case 2: ea += insn_fetch(int16_t); break;
   5.220 +            case 0: if ( modrm_rm == 6 ) ea_off = insn_fetch(int16_t); break;
   5.221 +            case 1: ea_off += insn_fetch(int8_t);  break;
   5.222 +            case 2: ea_off += insn_fetch(int16_t); break;
   5.223              }
   5.224          }
   5.225          else
   5.226 @@ -629,83 +614,50 @@ x86_emulate_memop(
   5.227                  sib_index = ((sib >> 3) & 7) | ((modrm << 2) & 8);
   5.228                  sib_base  = (sib & 7) | ((modrm << 3) & 8);
   5.229                  if ( sib_index != 4 )
   5.230 -                    ea = *(long *)decode_register(sib_index, &_regs, 0);
   5.231 -                ea <<= (sib >> 6) & 3;
   5.232 +                    ea_off = *(long *)decode_register(sib_index, &_regs, 0);
   5.233 +                ea_off <<= (sib >> 6) & 3;
   5.234                  if ( (modrm_mod == 0) && ((sib_base & 7) == 5) )
   5.235 -                    ea += insn_fetch(int32_t);
   5.236 +                    ea_off += insn_fetch(int32_t);
   5.237                  else
   5.238 -                    ea += *(long *)decode_register(sib_base, &_regs, 0);
   5.239 +                    ea_off += *(long *)decode_register(sib_base, &_regs, 0);
   5.240              }
   5.241              else
   5.242              {
   5.243                  modrm_rm |= (rex_prefix & 1) << 3;
   5.244 -                ea = *(long *)decode_register(modrm_rm, &_regs, 0);
   5.245 +                ea_off = *(long *)decode_register(modrm_rm, &_regs, 0);
   5.246              }
   5.247              switch ( modrm_mod )
   5.248              {
   5.249              case 0:
   5.250                  if ( (modrm_rm & 7) != 5 )
   5.251                      break;
   5.252 -                ea = insn_fetch(int32_t);
   5.253 +                ea_off = insn_fetch(int32_t);
   5.254                  if ( mode != X86EMUL_MODE_PROT64 )
   5.255                      break;
   5.256                  /* Relative to RIP of next instruction. Argh! */
   5.257 -                ea += _regs.eip;
   5.258 +                ea_off += _regs.eip;
   5.259                  if ( (d & SrcMask) == SrcImm )
   5.260 -                    ea += (d & ByteOp) ? 1 : ((op_bytes == 8) ? 4 : op_bytes);
   5.261 +                    ea_off += (d & ByteOp) ? 1 :
   5.262 +                        ((op_bytes == 8) ? 4 : op_bytes);
   5.263                  else if ( (d & SrcMask) == SrcImmByte )
   5.264 -                    ea += 1;
   5.265 +                    ea_off += 1;
   5.266                  else if ( ((b == 0xf6) || (b == 0xf7)) &&
   5.267                            ((modrm_reg & 7) <= 1) )
   5.268                      /* Special case in Grp3: test has immediate operand. */
   5.269 -                    ea += (d & ByteOp) ? 1
   5.270 +                    ea_off += (d & ByteOp) ? 1
   5.271                          : ((op_bytes == 8) ? 4 : op_bytes);
   5.272                  break;
   5.273 -            case 1: ea += insn_fetch(int8_t);  break;
   5.274 -            case 2: ea += insn_fetch(int32_t); break;
   5.275 +            case 1: ea_off += insn_fetch(int8_t);  break;
   5.276 +            case 2: ea_off += insn_fetch(int32_t); break;
   5.277              }
   5.278          }
   5.279  
   5.280 -        ea = register_address(*seg, ea);
   5.281 -        page_boundary_test();
   5.282 +        ea_off = truncate_ea(ea_off);
   5.283      }
   5.284  
   5.285 -    /* Decode and fetch the destination operand: register or memory. */
   5.286 -    switch ( d & DstMask )
   5.287 -    {
   5.288 -    case ImplicitOps:
   5.289 -        /* Special instructions do their own operand decoding. */
   5.290 +    /* Special instructions do their own operand decoding. */
   5.291 +    if ( (d & DstMask) == ImplicitOps )
   5.292          goto special_insn;
   5.293 -    case DstReg:
   5.294 -        dst.type = OP_REG;
   5.295 -        if ( d & ByteOp )
   5.296 -        {
   5.297 -            dst.ptr = decode_register(modrm_reg, &_regs, (rex_prefix == 0));
   5.298 -            dst.val = *(uint8_t *)dst.ptr;
   5.299 -            dst.bytes = 1;
   5.300 -        }
   5.301 -        else
   5.302 -        {
   5.303 -            dst.ptr = decode_register(modrm_reg, &_regs, 0);
   5.304 -            switch ( (dst.bytes = op_bytes) )
   5.305 -            {
   5.306 -            case 2: dst.val = *(uint16_t *)dst.ptr; break;
   5.307 -            case 4: dst.val = *(uint32_t *)dst.ptr; break;
   5.308 -            case 8: dst.val = *(uint64_t *)dst.ptr; break;
   5.309 -            }
   5.310 -        }
   5.311 -        break;
   5.312 -    case DstMem:
   5.313 -        dst.type  = OP_MEM;
   5.314 -        dst.ptr   = (unsigned long *)cr2;
   5.315 -        dst.bytes = (d & ByteOp) ? 1 : op_bytes;
   5.316 -        if ( !(d & Mov) && /* optimisation - avoid slow emulated read */
   5.317 -             ((rc = ops->read_emulated((unsigned long)dst.ptr,
   5.318 -                                       &dst.val, dst.bytes, ctxt)) != 0) )
   5.319 -             goto done;
   5.320 -        break;
   5.321 -    }
   5.322 -    dst.orig_val = dst.val;
   5.323  
   5.324      /* Decode and fetch the source operand: register, memory or immediate. */
   5.325      switch ( d & SrcMask )
   5.326 @@ -716,18 +668,18 @@ x86_emulate_memop(
   5.327          src.type = OP_REG;
   5.328          if ( d & ByteOp )
   5.329          {
   5.330 -            src.ptr = decode_register(modrm_reg, &_regs, (rex_prefix == 0));
   5.331 -            src.val = src.orig_val = *(uint8_t *)src.ptr;
   5.332 +            src.reg = decode_register(modrm_reg, &_regs, (rex_prefix == 0));
   5.333 +            src.val = src.orig_val = *(uint8_t *)src.reg;
   5.334              src.bytes = 1;
   5.335          }
   5.336          else
   5.337          {
   5.338 -            src.ptr = decode_register(modrm_reg, &_regs, 0);
   5.339 +            src.reg = decode_register(modrm_reg, &_regs, 0);
   5.340              switch ( (src.bytes = op_bytes) )
   5.341              {
   5.342 -            case 2: src.val = src.orig_val = *(uint16_t *)src.ptr; break;
   5.343 -            case 4: src.val = src.orig_val = *(uint32_t *)src.ptr; break;
   5.344 -            case 8: src.val = src.orig_val = *(uint64_t *)src.ptr; break;
   5.345 +            case 2: src.val = src.orig_val = *(uint16_t *)src.reg; break;
   5.346 +            case 4: src.val = src.orig_val = *(uint32_t *)src.reg; break;
   5.347 +            case 8: src.val = src.orig_val = *(uint64_t *)src.reg; break;
   5.348              }
   5.349          }
   5.350          break;
   5.351 @@ -741,15 +693,15 @@ x86_emulate_memop(
   5.352          src.bytes = (d & ByteOp) ? 1 : op_bytes;
   5.353      srcmem_common:
   5.354          src.type  = OP_MEM;
   5.355 -        src.ptr   = (unsigned long *)cr2;
   5.356 -        if ( (rc = ops->read_emulated((unsigned long)src.ptr, 
   5.357 -                                      &src.val, src.bytes, ctxt)) != 0 )
   5.358 +        src.mem_seg = ea_seg;
   5.359 +        src.mem_off = ea_off;
   5.360 +        if ( (rc = ops->read(src.mem_seg, src.mem_off,
   5.361 +                             &src.val, src.bytes, ctxt)) != 0 )
   5.362              goto done;
   5.363          src.orig_val = src.val;
   5.364          break;
   5.365      case SrcImm:
   5.366          src.type  = OP_IMM;
   5.367 -        src.ptr   = (unsigned long *)_regs.eip;
   5.368          src.bytes = (d & ByteOp) ? 1 : op_bytes;
   5.369          if ( src.bytes == 8 ) src.bytes = 4;
   5.370          /* NB. Immediates are sign-extended as necessary. */
   5.371 @@ -762,12 +714,81 @@ x86_emulate_memop(
   5.372          break;
   5.373      case SrcImmByte:
   5.374          src.type  = OP_IMM;
   5.375 -        src.ptr   = (unsigned long *)_regs.eip;
   5.376          src.bytes = 1;
   5.377          src.val   = insn_fetch(int8_t);
   5.378          break;
   5.379      }
   5.380  
   5.381 +    /* Decode and fetch the destination operand: register or memory. */
   5.382 +    switch ( d & DstMask )
   5.383 +    {
   5.384 +    case DstReg:
   5.385 +        dst.type = OP_REG;
   5.386 +        if ( d & ByteOp )
   5.387 +        {
   5.388 +            dst.reg = decode_register(modrm_reg, &_regs, (rex_prefix == 0));
   5.389 +            dst.val = *(uint8_t *)dst.reg;
   5.390 +            dst.bytes = 1;
   5.391 +        }
   5.392 +        else
   5.393 +        {
   5.394 +            dst.reg = decode_register(modrm_reg, &_regs, 0);
   5.395 +            switch ( (dst.bytes = op_bytes) )
   5.396 +            {
   5.397 +            case 2: dst.val = *(uint16_t *)dst.reg; break;
   5.398 +            case 4: dst.val = *(uint32_t *)dst.reg; break;
   5.399 +            case 8: dst.val = *(uint64_t *)dst.reg; break;
   5.400 +            }
   5.401 +        }
   5.402 +        break;
   5.403 +    case DstBitBase:
   5.404 +        dst.mem_off = ea_off;
   5.405 +        if ( (d & SrcMask) == SrcImmByte )
   5.406 +        {
   5.407 +            src.val &= (op_bytes << 3) - 1;
   5.408 +        }
   5.409 +        else
   5.410 +        {
   5.411 +            /*
   5.412 +             * EA       += BitOffset DIV op_bytes*8
   5.413 +             * BitOffset = BitOffset MOD op_byte*8
   5.414 +             * DIV truncates towards negative infinity.
   5.415 +             * MOD always produces a positive result.
   5.416 +             */
   5.417 +            if ( op_bytes == 2 )
   5.418 +                src.val = (int16_t)src.val;
   5.419 +            else if ( op_bytes == 4 )
   5.420 +                src.val = (int32_t)src.val;
   5.421 +            if ( (long)src.val < 0 )
   5.422 +            {
   5.423 +                unsigned long byte_offset;
   5.424 +                byte_offset = op_bytes + (((-src.val-1) >> 3) & ~(op_bytes-1));
   5.425 +                dst.mem_off -= byte_offset;
   5.426 +                src.val = (byte_offset << 3) + src.val;
   5.427 +            }
   5.428 +            else
   5.429 +            {
   5.430 +                dst.mem_off += (src.val >> 3) & ~(op_bytes - 1);
   5.431 +                src.val &= (op_bytes << 3) - 1;
   5.432 +            }
   5.433 +        }
   5.434 +        /* Becomes a normal DstMem operation from here on. */
   5.435 +        d = (d & ~DstMask) | DstMem;
   5.436 +        goto dstmem_common;
   5.437 +    case DstMem:
   5.438 +        dst.mem_off = ea_off;
   5.439 +    dstmem_common:
   5.440 +        dst.mem_seg = ea_seg;
   5.441 +        dst.type  = OP_MEM;
   5.442 +        dst.bytes = (d & ByteOp) ? 1 : op_bytes;
   5.443 +        if ( !(d & Mov) && /* optimisation - avoid slow emulated read */
   5.444 +             ((rc = ops->read(dst.mem_seg, dst.mem_off,
   5.445 +                              &dst.val, dst.bytes, ctxt)) != 0) )
   5.446 +             goto done;
   5.447 +        break;
   5.448 +    }
   5.449 +    dst.orig_val = dst.val;
   5.450 +
   5.451      if ( twobyte )
   5.452          goto twobyte_insn;
   5.453  
   5.454 @@ -822,45 +843,25 @@ x86_emulate_memop(
   5.455          /* Write back the register source. */
   5.456          switch ( dst.bytes )
   5.457          {
   5.458 -        case 1: *(uint8_t  *)src.ptr = (uint8_t)dst.val; break;
   5.459 -        case 2: *(uint16_t *)src.ptr = (uint16_t)dst.val; break;
   5.460 -        case 4: *src.ptr = (uint32_t)dst.val; break; /* 64b reg: zero-extend */
   5.461 -        case 8: *src.ptr = dst.val; break;
   5.462 +        case 1: *(uint8_t  *)src.reg = (uint8_t)dst.val; break;
   5.463 +        case 2: *(uint16_t *)src.reg = (uint16_t)dst.val; break;
   5.464 +        case 4: *src.reg = (uint32_t)dst.val; break; /* 64b reg: zero-extend */
   5.465 +        case 8: *src.reg = dst.val; break;
   5.466          }
   5.467          /* Write back the memory destination with implicit LOCK prefix. */
   5.468          dst.val = src.val;
   5.469          lock_prefix = 1;
   5.470          break;
   5.471 -    case 0xa0 ... 0xa1: /* mov */
   5.472 -        dst.ptr = (unsigned long *)&_regs.eax;
   5.473 -        dst.val = src.val;
   5.474 -        /* Source EA is not encoded via ModRM. */
   5.475 -        ea = register_address(*seg, _insn_fetch(ad_bytes));
   5.476 -        page_boundary_test();
   5.477 -        break;
   5.478 -    case 0xa2 ... 0xa3: /* mov */
   5.479 -        dst.val = (unsigned long)_regs.eax;
   5.480 -        /* Destination EA is not encoded via ModRM. */
   5.481 -        ea = register_address(*seg, _insn_fetch(ad_bytes));
   5.482 -        page_boundary_test();
   5.483 -        break;
   5.484      case 0x88 ... 0x8b: /* mov */
   5.485      case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */
   5.486          dst.val = src.val;
   5.487          break;
   5.488      case 0x8f: /* pop (sole member of Grp1a) */
   5.489 -        /*
   5.490 -         * If the faulting access was a read it means that the fault occurred
   5.491 -         * when accessing the implicit stack operand. We assume the guest never
   5.492 -         * uses special memory areas as stack space.
   5.493 -         */
   5.494 -        if ( !(_regs.error_code & PFEC_write_access) )
   5.495 -            goto cannot_emulate; /* fault on stack access: bail */
   5.496          /* 64-bit mode: POP always pops a 64-bit operand. */
   5.497          if ( mode == X86EMUL_MODE_PROT64 )
   5.498              dst.bytes = 8;
   5.499 -        if ( (rc = ops->read_std(register_address(_regs.ss, _regs.esp),
   5.500 -                                 &dst.val, dst.bytes, ctxt)) != 0 )
   5.501 +        if ( (rc = ops->read(X86_SEG_SS, truncate_ea(_regs.esp),
   5.502 +                             &dst.val, dst.bytes, ctxt)) != 0 )
   5.503              goto done;
   5.504          register_address_increment(_regs.esp, dst.bytes);
   5.505          break;
   5.506 @@ -903,7 +904,6 @@ x86_emulate_memop(
   5.507          case 0 ... 1: /* test */
   5.508              /* Special case in Grp3: test has an immediate source operand. */
   5.509              src.type = OP_IMM;
   5.510 -            src.ptr  = (unsigned long *)_regs.eip;
   5.511              src.bytes = (d & ByteOp) ? 1 : op_bytes;
   5.512              if ( src.bytes == 8 ) src.bytes = 4;
   5.513              switch ( src.bytes )
   5.514 @@ -933,24 +933,17 @@ x86_emulate_memop(
   5.515              emulate_1op("dec", dst, _regs.eflags);
   5.516              break;
   5.517          case 6: /* push */
   5.518 -            /*
   5.519 -             * If the faulting access was a write it means that the fault
   5.520 -             * occurred when accessing the implicit stack operand. We assume
   5.521 -             * the guest never uses special memory areas as stack space.
   5.522 -             */
   5.523 -            if ( _regs.error_code & PFEC_write_access )
   5.524 -                goto cannot_emulate; /* fault on stack access: bail */
   5.525              /* 64-bit mode: PUSH always pushes a 64-bit operand. */
   5.526              if ( mode == X86EMUL_MODE_PROT64 )
   5.527              {
   5.528                  dst.bytes = 8;
   5.529 -                if ( (rc = ops->read_std((unsigned long)dst.ptr,
   5.530 -                                         &dst.val, 8, ctxt)) != 0 )
   5.531 +                if ( (rc = ops->read(dst.mem_seg, dst.mem_off,
   5.532 +                                     &dst.val, 8, ctxt)) != 0 )
   5.533                      goto done;
   5.534              }
   5.535              register_address_increment(_regs.esp, -dst.bytes);
   5.536 -            if ( (rc = ops->write_std(register_address(_regs.ss, _regs.esp),
   5.537 -                                      dst.val, dst.bytes, ctxt)) != 0 )
   5.538 +            if ( (rc = ops->write(X86_SEG_SS, truncate_ea(_regs.esp),
   5.539 +                                  dst.val, dst.bytes, ctxt)) != 0 )
   5.540                  goto done;
   5.541              dst.val = dst.orig_val; /* skanky: disable writeback */
   5.542              break;
   5.543 @@ -969,20 +962,20 @@ x86_emulate_memop(
   5.544              /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */
   5.545              switch ( dst.bytes )
   5.546              {
   5.547 -            case 1: *(uint8_t  *)dst.ptr = (uint8_t)dst.val; break;
   5.548 -            case 2: *(uint16_t *)dst.ptr = (uint16_t)dst.val; break;
   5.549 -            case 4: *dst.ptr = (uint32_t)dst.val; break; /* 64b: zero-ext */
   5.550 -            case 8: *dst.ptr = dst.val; break;
   5.551 +            case 1: *(uint8_t  *)dst.reg = (uint8_t)dst.val; break;
   5.552 +            case 2: *(uint16_t *)dst.reg = (uint16_t)dst.val; break;
   5.553 +            case 4: *dst.reg = (uint32_t)dst.val; break; /* 64b: zero-ext */
   5.554 +            case 8: *dst.reg = dst.val; break;
   5.555              }
   5.556              break;
   5.557          case OP_MEM:
   5.558              if ( lock_prefix )
   5.559 -                rc = ops->cmpxchg_emulated(
   5.560 -                    (unsigned long)dst.ptr, dst.orig_val,
   5.561 +                rc = ops->cmpxchg(
   5.562 +                    dst.mem_seg, dst.mem_off, dst.orig_val,
   5.563                      dst.val, dst.bytes, ctxt);
   5.564              else
   5.565 -                rc = ops->write_emulated(
   5.566 -                    (unsigned long)dst.ptr, dst.val, dst.bytes, ctxt);
   5.567 +                rc = ops->write(
   5.568 +                    dst.mem_seg, dst.mem_off, dst.val, dst.bytes, ctxt);
   5.569              if ( rc != 0 )
   5.570                  goto done;
   5.571          default:
   5.572 @@ -1011,50 +1004,51 @@ x86_emulate_memop(
   5.573      }
   5.574      switch ( b )
   5.575      {
   5.576 +    case 0xa0 ... 0xa1: /* mov moffs,{%al,%ax,%eax,%rax} */
   5.577 +        /* Source EA is not encoded via ModRM. */
   5.578 +        dst.type  = OP_REG;
   5.579 +        dst.reg   = (unsigned long *)&_regs.eax;
   5.580 +        dst.bytes = (d & ByteOp) ? 1 : op_bytes;
   5.581 +        if ( (rc = ops->read(ea_seg, _insn_fetch(ad_bytes),
   5.582 +                             &dst.val, dst.bytes, ctxt)) != 0 )
   5.583 +            goto done;
   5.584 +        break;
   5.585 +    case 0xa2 ... 0xa3: /* mov {%al,%ax,%eax,%rax},moffs */
   5.586 +        /* Destination EA is not encoded via ModRM. */
   5.587 +        dst.type    = OP_MEM;
   5.588 +        dst.mem_seg = ea_seg;
   5.589 +        dst.mem_off = _insn_fetch(ad_bytes);
   5.590 +        dst.bytes   = (d & ByteOp) ? 1 : op_bytes;
   5.591 +        dst.val     = (unsigned long)_regs.eax;
   5.592 +        break;
   5.593      case 0xa4 ... 0xa5: /* movs */
   5.594          dst.type  = OP_MEM;
   5.595          dst.bytes = (d & ByteOp) ? 1 : op_bytes;
   5.596 -        if ( _regs.error_code & PFEC_write_access )
   5.597 -        {
   5.598 -            /* Write fault: destination is special memory. */
   5.599 -            dst.ptr = (unsigned long *)cr2;
   5.600 -            if ( (rc = ops->read_std(register_address(*seg, _regs.esi),
   5.601 -                                     &dst.val, dst.bytes, ctxt)) != 0 )
   5.602 -                goto done;
   5.603 -            ea = register_address(_regs.es, _regs.edi);
   5.604 -        }
   5.605 -        else
   5.606 -        {
   5.607 -            /* Read fault: source is special memory. */
   5.608 -            dst.ptr = (unsigned long *)register_address(_regs.es, _regs.edi);
   5.609 -            if ( (rc = ops->read_emulated(cr2, &dst.val,
   5.610 -                                          dst.bytes, ctxt)) != 0 )
   5.611 -                goto done;
   5.612 -            ea = register_address(*seg, _regs.esi);
   5.613 -        }
   5.614 -        page_boundary_test();
   5.615 +        dst.mem_seg = X86_SEG_ES;
   5.616 +        dst.mem_off = truncate_ea(_regs.edi);
   5.617 +        if ( (rc = ops->read(ea_seg, truncate_ea(_regs.esi),
   5.618 +                             &dst.val, dst.bytes, ctxt)) != 0 )
   5.619 +            goto done;
   5.620          register_address_increment(
   5.621              _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
   5.622          register_address_increment(
   5.623              _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
   5.624          break;
   5.625      case 0xaa ... 0xab: /* stos */
   5.626 -        ea = register_address(_regs.es, _regs.edi);
   5.627 -        page_boundary_test();
   5.628          dst.type  = OP_MEM;
   5.629          dst.bytes = (d & ByteOp) ? 1 : op_bytes;
   5.630 -        dst.ptr   = (unsigned long *)cr2;
   5.631 +        dst.mem_seg = X86_SEG_ES;
   5.632 +        dst.mem_off = truncate_ea(_regs.edi);
   5.633          dst.val   = _regs.eax;
   5.634          register_address_increment(
   5.635              _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
   5.636          break;
   5.637      case 0xac ... 0xad: /* lods */
   5.638 -        ea = register_address(*seg, _regs.esi);
   5.639 -        page_boundary_test();
   5.640          dst.type  = OP_REG;
   5.641          dst.bytes = (d & ByteOp) ? 1 : op_bytes;
   5.642 -        dst.ptr   = (unsigned long *)&_regs.eax;
   5.643 -        if ( (rc = ops->read_emulated(cr2, &dst.val, dst.bytes, ctxt)) != 0 )
   5.644 +        dst.reg   = (unsigned long *)&_regs.eax;
   5.645 +        if ( (rc = ops->read(ea_seg, truncate_ea(_regs.esi),
   5.646 +                             &dst.val, dst.bytes, ctxt)) != 0 )
   5.647              goto done;
   5.648          register_address_increment(
   5.649              _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
   5.650 @@ -1116,19 +1110,16 @@ x86_emulate_memop(
   5.651          {
   5.652              /* Failure: write the value we saw to EAX. */
   5.653              dst.type = OP_REG;
   5.654 -            dst.ptr  = (unsigned long *)&_regs.eax;
   5.655 +            dst.reg  = (unsigned long *)&_regs.eax;
   5.656          }
   5.657          break;
   5.658      case 0xa3: bt: /* bt */
   5.659 -        src.val &= (dst.bytes << 3) - 1; /* only subword offset */
   5.660          emulate_2op_SrcV_nobyte("bt", src, dst, _regs.eflags);
   5.661          break;
   5.662      case 0xb3: btr: /* btr */
   5.663 -        src.val &= (dst.bytes << 3) - 1; /* only subword offset */
   5.664          emulate_2op_SrcV_nobyte("btr", src, dst, _regs.eflags);
   5.665          break;
   5.666      case 0xab: bts: /* bts */
   5.667 -        src.val &= (dst.bytes << 3) - 1; /* only subword offset */
   5.668          emulate_2op_SrcV_nobyte("bts", src, dst, _regs.eflags);
   5.669          break;
   5.670      case 0xb6 ... 0xb7: /* movzx */
   5.671 @@ -1136,7 +1127,6 @@ x86_emulate_memop(
   5.672          dst.val = (d & ByteOp) ? (uint8_t)src.val : (uint16_t)src.val;
   5.673          break;
   5.674      case 0xbb: btc: /* btc */
   5.675 -        src.val &= (dst.bytes << 3) - 1; /* only subword offset */
   5.676          emulate_2op_SrcV_nobyte("btc", src, dst, _regs.eflags);
   5.677          break;
   5.678      case 0xba: /* Grp8 */
   5.679 @@ -1167,8 +1157,8 @@ x86_emulate_memop(
   5.680  #if defined(__i386__)
   5.681      {
   5.682          unsigned long old_lo, old_hi;
   5.683 -        if ( ((rc = ops->read_emulated(cr2+0, &old_lo, 4, ctxt)) != 0) ||
   5.684 -             ((rc = ops->read_emulated(cr2+4, &old_hi, 4, ctxt)) != 0) )
   5.685 +        if ( ((rc = ops->read(ea_seg, ea_off+0, &old_lo, 4, ctxt)) != 0) ||
   5.686 +             ((rc = ops->read(ea_seg, ea_off+4, &old_hi, 4, ctxt)) != 0) )
   5.687              goto done;
   5.688          if ( (old_lo != _regs.eax) || (old_hi != _regs.edx) )
   5.689          {
   5.690 @@ -1176,15 +1166,15 @@ x86_emulate_memop(
   5.691              _regs.edx = old_hi;
   5.692              _regs.eflags &= ~EFLG_ZF;
   5.693          }
   5.694 -        else if ( ops->cmpxchg8b_emulated == NULL )
   5.695 +        else if ( ops->cmpxchg8b == NULL )
   5.696          {
   5.697              rc = X86EMUL_UNHANDLEABLE;
   5.698              goto done;
   5.699          }
   5.700          else
   5.701          {
   5.702 -            if ( (rc = ops->cmpxchg8b_emulated(cr2, old_lo, old_hi, _regs.ebx,
   5.703 -                                               _regs.ecx, ctxt)) != 0 )
   5.704 +            if ( (rc = ops->cmpxchg8b(ea_seg, ea_off, old_lo, old_hi,
   5.705 +                                      _regs.ebx, _regs.ecx, ctxt)) != 0 )
   5.706                  goto done;
   5.707              _regs.eflags |= EFLG_ZF;
   5.708          }
   5.709 @@ -1193,7 +1183,7 @@ x86_emulate_memop(
   5.710  #elif defined(__x86_64__)
   5.711      {
   5.712          unsigned long old, new;
   5.713 -        if ( (rc = ops->read_emulated(cr2, &old, 8, ctxt)) != 0 )
   5.714 +        if ( (rc = ops->read(ea_seg, ea_off, &old, 8, ctxt)) != 0 )
   5.715              goto done;
   5.716          if ( ((uint32_t)(old>>0) != (uint32_t)_regs.eax) ||
   5.717               ((uint32_t)(old>>32) != (uint32_t)_regs.edx) )
   5.718 @@ -1205,7 +1195,7 @@ x86_emulate_memop(
   5.719          else
   5.720          {
   5.721              new = (_regs.ecx<<32)|(uint32_t)_regs.ebx;
   5.722 -            if ( (rc = ops->cmpxchg_emulated(cr2, old, new, 8, ctxt)) != 0 )
   5.723 +            if ( (rc = ops->cmpxchg(ea_seg, ea_off, old, new, 8, ctxt)) != 0 )
   5.724                  goto done;
   5.725              _regs.eflags |= EFLG_ZF;
   5.726          }
   5.727 @@ -1219,55 +1209,4 @@ x86_emulate_memop(
   5.728      dprintf("Cannot emulate %02x\n", b);
   5.729      dump_instr(ctxt, ops);
   5.730      return -1;
   5.731 -
   5.732 - bad_ea:
   5.733 -    dprintf("Access faulted on page boundary (cr2=%lx,ea=%lx).\n", cr2, ea);
   5.734 -    dump_instr(ctxt, ops);
   5.735 -    show_execution_state(ctxt->regs);
   5.736 -    return -1;
   5.737  }
   5.738 -
   5.739 -#ifdef __XEN__
   5.740 -
   5.741 -#include <asm/mm.h>
   5.742 -#include <asm/uaccess.h>
   5.743 -
   5.744 -int
   5.745 -x86_emulate_read_std(
   5.746 -    unsigned long addr,
   5.747 -    unsigned long *val,
   5.748 -    unsigned int bytes,
   5.749 -    struct x86_emulate_ctxt *ctxt)
   5.750 -{
   5.751 -    unsigned int rc;
   5.752 -
   5.753 -    *val = 0;
   5.754 -
   5.755 -    if ( (rc = copy_from_user((void *)val, (void *)addr, bytes)) != 0 )
   5.756 -    {
   5.757 -        propagate_page_fault(addr + bytes - rc, 0); /* read fault */
   5.758 -        return X86EMUL_PROPAGATE_FAULT;
   5.759 -    }
   5.760 -
   5.761 -    return X86EMUL_CONTINUE;
   5.762 -}
   5.763 -
   5.764 -int
   5.765 -x86_emulate_write_std(
   5.766 -    unsigned long addr,
   5.767 -    unsigned long val,
   5.768 -    unsigned int bytes,
   5.769 -    struct x86_emulate_ctxt *ctxt)
   5.770 -{
   5.771 -    unsigned int rc;
   5.772 -
   5.773 -    if ( (rc = copy_to_user((void *)addr, (void *)&val, bytes)) != 0 )
   5.774 -    {
   5.775 -        propagate_page_fault(addr + bytes - rc, PFEC_write_access);
   5.776 -        return X86EMUL_PROPAGATE_FAULT;
   5.777 -    }
   5.778 -
   5.779 -    return X86EMUL_CONTINUE;
   5.780 -}
   5.781 -
   5.782 -#endif
     6.1 --- a/xen/include/asm-x86/x86_emulate.h	Wed Nov 29 23:40:40 2006 +0000
     6.2 +++ b/xen/include/asm-x86/x86_emulate.h	Thu Nov 30 10:57:28 2006 +0000
     6.3 @@ -11,35 +11,27 @@
     6.4  
     6.5  struct x86_emulate_ctxt;
     6.6  
     6.7 +#define X86_SEG_CS 0
     6.8 +#define X86_SEG_SS 1
     6.9 +#define X86_SEG_DS 2
    6.10 +#define X86_SEG_ES 3
    6.11 +#define X86_SEG_FS 4
    6.12 +#define X86_SEG_GS 5
    6.13 +
    6.14  /*
    6.15   * x86_emulate_ops:
    6.16   * 
    6.17   * These operations represent the instruction emulator's interface to memory.
    6.18 - * There are two categories of operation: those that act on ordinary memory
    6.19 - * regions (*_std), and those that act on memory regions known to require
    6.20 - * special treatment or emulation (*_emulated).
    6.21 - * 
    6.22 - * The emulator assumes that an instruction accesses only one 'emulated memory'
    6.23 - * location, that this location is the given linear faulting address (cr2), and
    6.24 - * that this is one of the instruction's data operands. Instruction fetches and
    6.25 - * stack operations are assumed never to access emulated memory. The emulator
    6.26 - * automatically deduces which operand of a string-move operation is accessing
    6.27 - * emulated memory, and assumes that the other operand accesses normal memory.
    6.28   * 
    6.29   * NOTES:
    6.30 - *  1. The emulator isn't very smart about emulated vs. standard memory.
    6.31 - *     'Emulated memory' access addresses should be checked for sanity.
    6.32 - *     'Normal memory' accesses may fault, and the caller must arrange to
    6.33 - *     detect and handle reentrancy into the emulator via recursive faults.
    6.34 - *     Accesses may be unaligned and may cross page boundaries.
    6.35 - *  2. If the access fails (cannot emulate, or a standard access faults) then
    6.36 + *  1. If the access fails (cannot emulate, or a standard access faults) then
    6.37   *     it is up to the memop to propagate the fault to the guest VM via
    6.38   *     some out-of-band mechanism, unknown to the emulator. The memop signals
    6.39   *     failure by returning X86EMUL_PROPAGATE_FAULT to the emulator, which will
    6.40   *     then immediately bail.
    6.41 - *  3. Valid access sizes are 1, 2, 4 and 8 bytes. On x86/32 systems only
    6.42 + *  2. Valid access sizes are 1, 2, 4 and 8 bytes. On x86/32 systems only
    6.43   *     cmpxchg8b_emulated need support 8-byte accesses.
    6.44 - *  4. The emulator cannot handle 64-bit mode emulation on an x86/32 system.
    6.45 + *  3. The emulator cannot handle 64-bit mode emulation on an x86/32 system.
    6.46   */
    6.47  /* Access completed successfully: continue emulation as normal. */
    6.48  #define X86EMUL_CONTINUE        0
    6.49 @@ -52,74 +44,51 @@ struct x86_emulate_ctxt;
    6.50  struct x86_emulate_ops
    6.51  {
    6.52      /*
    6.53 -     * read_std: Read bytes of standard (non-emulated/special) memory.
    6.54 -     *           Used for instruction fetch, stack operations, and others.
    6.55 -     *  @addr:  [IN ] Linear address from which to read.
    6.56 -     *  @val:   [OUT] Value read from memory, zero-extended to 'u_long'.
    6.57 +     * All functions:
    6.58 +     *  @seg:   [IN ] Segment being dereferenced (specified as X86_SEG_??).
    6.59 +     *  @offset [IN ] Offset within segment.
    6.60 +     */
    6.61 +
    6.62 +    /*
    6.63 +     * read: Emulate a memory read.
    6.64 +     *  @val:   [OUT] Value read from memory, zero-extended to 'ulong'.
    6.65       *  @bytes: [IN ] Number of bytes to read from memory.
    6.66       */
    6.67 -    int (*read_std)(
    6.68 -        unsigned long addr,
    6.69 +    int (*read)(
    6.70 +        unsigned int seg,
    6.71 +        unsigned long offset,
    6.72          unsigned long *val,
    6.73          unsigned int bytes,
    6.74          struct x86_emulate_ctxt *ctxt);
    6.75  
    6.76      /*
    6.77 -     * write_std: Write bytes of standard (non-emulated/special) memory.
    6.78 -     *            Used for stack operations, and others.
    6.79 -     *  @addr:  [IN ] Linear address to which to write.
    6.80 +     * write: Emulate a memory write.
    6.81       *  @val:   [IN ] Value to write to memory (low-order bytes used as req'd).
    6.82       *  @bytes: [IN ] Number of bytes to write to memory.
    6.83       */
    6.84 -    int (*write_std)(
    6.85 -        unsigned long addr,
    6.86 +    int (*write)(
    6.87 +        unsigned int seg,
    6.88 +        unsigned long offset,
    6.89          unsigned long val,
    6.90          unsigned int bytes,
    6.91          struct x86_emulate_ctxt *ctxt);
    6.92  
    6.93      /*
    6.94 -     * read_emulated: Read bytes from emulated/special memory area.
    6.95 -     *  @addr:  [IN ] Linear address from which to read.
    6.96 -     *  @val:   [OUT] Value read from memory, zero-extended to 'u_long'.
    6.97 -     *  @bytes: [IN ] Number of bytes to read from memory.
    6.98 -     */
    6.99 -    int (*read_emulated)(
   6.100 -        unsigned long addr,
   6.101 -        unsigned long *val,
   6.102 -        unsigned int bytes,
   6.103 -        struct x86_emulate_ctxt *ctxt);
   6.104 -
   6.105 -    /*
   6.106 -     * write_emulated: Read bytes from emulated/special memory area.
   6.107 -     *  @addr:  [IN ] Linear address to which to write.
   6.108 -     *  @val:   [IN ] Value to write to memory (low-order bytes used as req'd).
   6.109 -     *  @bytes: [IN ] Number of bytes to write to memory.
   6.110 -     */
   6.111 -    int (*write_emulated)(
   6.112 -        unsigned long addr,
   6.113 -        unsigned long val,
   6.114 -        unsigned int bytes,
   6.115 -        struct x86_emulate_ctxt *ctxt);
   6.116 -
   6.117 -    /*
   6.118 -     * cmpxchg_emulated: Emulate an atomic (LOCKed) CMPXCHG operation on an
   6.119 -     *                   emulated/special memory area.
   6.120 -     *  @addr:  [IN ] Linear address to access.
   6.121 +     * cmpxchg: Emulate an atomic (LOCKed) CMPXCHG operation.
   6.122       *  @old:   [IN ] Value expected to be current at @addr.
   6.123       *  @new:   [IN ] Value to write to @addr.
   6.124       *  @bytes: [IN ] Number of bytes to access using CMPXCHG.
   6.125       */
   6.126 -    int (*cmpxchg_emulated)(
   6.127 -        unsigned long addr,
   6.128 +    int (*cmpxchg)(
   6.129 +        unsigned int seg,
   6.130 +        unsigned long offset,
   6.131          unsigned long old,
   6.132          unsigned long new,
   6.133          unsigned int bytes,
   6.134          struct x86_emulate_ctxt *ctxt);
   6.135  
   6.136      /*
   6.137 -     * cmpxchg8b_emulated: Emulate an atomic (LOCKed) CMPXCHG8B operation on an
   6.138 -     *                     emulated/special memory area.
   6.139 -     *  @addr:  [IN ] Linear address to access.
   6.140 +     * cmpxchg8b: Emulate an atomic (LOCKed) CMPXCHG8B operation.
   6.141       *  @old:   [IN ] Value expected to be current at @addr.
   6.142       *  @new:   [IN ] Value to write to @addr.
   6.143       * NOTES:
   6.144 @@ -128,8 +97,9 @@ struct x86_emulate_ops
   6.145       *  2. Not defining this function (i.e., specifying NULL) is equivalent
   6.146       *     to defining a function that always returns X86EMUL_UNHANDLEABLE.
   6.147       */
   6.148 -    int (*cmpxchg8b_emulated)(
   6.149 -        unsigned long addr,
   6.150 +    int (*cmpxchg8b)(
   6.151 +        unsigned int seg,
   6.152 +        unsigned long offset,
   6.153          unsigned long old_lo,
   6.154          unsigned long old_hi,
   6.155          unsigned long new_lo,
   6.156 @@ -137,20 +107,6 @@ struct x86_emulate_ops
   6.157          struct x86_emulate_ctxt *ctxt);
   6.158  };
   6.159  
   6.160 -/* Standard reader/writer functions that callers may wish to use. */
   6.161 -extern int
   6.162 -x86_emulate_read_std(
   6.163 -    unsigned long addr,
   6.164 -    unsigned long *val,
   6.165 -    unsigned int bytes,
   6.166 -    struct x86_emulate_ctxt *ctxt);
   6.167 -extern int
   6.168 -x86_emulate_write_std(
   6.169 -    unsigned long addr,
   6.170 -    unsigned long val,
   6.171 -    unsigned int bytes,
   6.172 -    struct x86_emulate_ctxt *ctxt);
   6.173 -
   6.174  struct cpu_user_regs;
   6.175  
   6.176  struct x86_emulate_ctxt
   6.177 @@ -158,9 +114,6 @@ struct x86_emulate_ctxt
   6.178      /* Register state before/after emulation. */
   6.179      struct cpu_user_regs   *regs;
   6.180  
   6.181 -    /* Linear faulting address (if emulating a page-faulting instruction). */
   6.182 -    unsigned long           cr2;
   6.183 -
   6.184      /* Emulated execution mode, represented by an X86EMUL_MODE value. */
   6.185      int                     mode;
   6.186  };