debuggers.hg
changeset 12660: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>
- 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 };