ia64/xen-unstable
changeset 1820:3d4f8eb89670
bitkeeper revision 1.1106.1.2 (40faa780dekT3E5arFwcbQDu1MbX6g)
Cleaned up Xen's instruction emulator.
Cleaned up Xen's instruction emulator.
author | kaf24@scramble.cl.cam.ac.uk |
---|---|
date | Sun Jul 18 16:38:24 2004 +0000 (2004-07-18) |
parents | 0990231d8436 |
children | 1a488e40456a |
files | xen/arch/x86/x86_32/emulate.c |
line diff
1.1 --- a/xen/arch/x86/x86_32/emulate.c Sun Jul 18 16:37:38 2004 +0000 1.2 +++ b/xen/arch/x86/x86_32/emulate.c Sun Jul 18 16:38:24 2004 +0000 1.3 @@ -30,6 +30,15 @@ 1.4 #include <xen/perfc.h> 1.5 #include <asm/processor.h> 1.6 1.7 +/* 1.8 + * Obtain the base and limit associated with the given segment selector. 1.9 + * The selector must identify a 32-bit code or data segment. Any segment that 1.10 + * appears to be truncated to not overlap with Xen is assumed to be a truncated 1.11 + * 4GB segment, and the returned limit reflects this. 1.12 + * @seg (IN) : Segment selector to decode. 1.13 + * @base (OUT): Decoded linear base address. 1.14 + * @limit (OUT): Decoded segment limit, in bytes. 0 == unlimited (4GB). 1.15 + */ 1.16 int get_baselimit(u16 seg, unsigned long *base, unsigned long *limit) 1.17 { 1.18 struct domain *d = current; 1.19 @@ -80,6 +89,7 @@ int get_baselimit(u16 seg, unsigned long 1.20 return 0; 1.21 } 1.22 1.23 +/* Turn a segment+offset into a linear address. */ 1.24 int linearise_address(u16 seg, unsigned long off, unsigned long *linear) 1.25 { 1.26 unsigned long base, limit; 1.27 @@ -95,6 +105,7 @@ int linearise_address(u16 seg, unsigned 1.28 return 1; 1.29 } 1.30 1.31 +/* Decode Reg field of a ModRM byte: return a pointer into a register block. */ 1.32 void *decode_reg(struct pt_regs *regs, u8 b) 1.33 { 1.34 switch ( b & 7 ) 1.35 @@ -120,6 +131,9 @@ void *decode_reg(struct pt_regs *regs, u 1.36 * @pseg (IN) : address in pt_regs block of the override segment. 1.37 * @regs (IN) : addrress of the the pt_regs block. 1.38 */ 1.39 +#define DECODE_EA_FAILED 0 1.40 +#define DECODE_EA_FIXME 1 1.41 +#define DECODE_EA_SUCCESS 2 1.42 int decode_effective_address(u8 **ppb, void **preg, void **pmem, 1.43 unsigned int *pseg, struct pt_regs *regs) 1.44 { 1.45 @@ -132,7 +146,7 @@ int decode_effective_address(u8 **ppb, v 1.46 if ( get_user(modrm, pb) ) 1.47 { 1.48 DPRINTK("Fault while extracting modrm byte\n"); 1.49 - return 0; 1.50 + return DECODE_EA_FAILED; 1.51 } 1.52 1.53 pb++; 1.54 @@ -144,7 +158,7 @@ int decode_effective_address(u8 **ppb, v 1.55 if ( rm == 4 ) 1.56 { 1.57 DPRINTK("FIXME: Add decoding for the SIB byte.\n"); 1.58 - return 0; 1.59 + return DECODE_EA_FIXME; 1.60 } 1.61 1.62 /* Decode Reg and R/M fields. */ 1.63 @@ -164,7 +178,7 @@ int decode_effective_address(u8 **ppb, v 1.64 if ( get_user(disp32, (u32 *)pb) ) 1.65 { 1.66 DPRINTK("Fault while extracting <disp8>.\n"); 1.67 - return 0; 1.68 + return DECODE_EA_FAILED; 1.69 } 1.70 pb += 4; 1.71 } 1.72 @@ -176,7 +190,7 @@ int decode_effective_address(u8 **ppb, v 1.73 if ( get_user(disp8, pb) ) 1.74 { 1.75 DPRINTK("Fault while extracting <disp8>.\n"); 1.76 - return 0; 1.77 + return DECODE_EA_FAILED; 1.78 } 1.79 pb++; 1.80 disp32 = (disp8 & 0x80) ? (disp8 | ~0xff) : disp8;; 1.81 @@ -188,22 +202,22 @@ int decode_effective_address(u8 **ppb, v 1.82 if ( get_user(disp32, (u32 *)pb) ) 1.83 { 1.84 DPRINTK("Fault while extracting <disp8>.\n"); 1.85 - return 0; 1.86 + return DECODE_EA_FAILED; 1.87 } 1.88 pb += 4; 1.89 break; 1.90 1.91 case 3: 1.92 DPRINTK("Not a memory operand!\n"); 1.93 - return 0; 1.94 + return DECODE_EA_FAILED; 1.95 } 1.96 1.97 if ( !get_baselimit((u16)(*pseg), &ea, &limit) ) 1.98 - return 0; 1.99 + return DECODE_EA_FAILED; 1.100 if ( limit != 0 ) 1.101 { 1.102 DPRINTK("Bailing: not a 4GB data segment.\n"); 1.103 - return 0; 1.104 + return DECODE_EA_FAILED; 1.105 } 1.106 1.107 offset = disp32; 1.108 @@ -212,23 +226,42 @@ int decode_effective_address(u8 **ppb, v 1.109 if ( (offset & 0xf0000000) != 0xf0000000 ) 1.110 { 1.111 DPRINTK("Bailing: not a -ve offset into 4GB segment.\n"); 1.112 - return 0; 1.113 + return DECODE_EA_FAILED; 1.114 } 1.115 1.116 ea += offset; 1.117 if ( ea > (PAGE_OFFSET - PAGE_SIZE) ) 1.118 { 1.119 DPRINTK("!!!! DISALLOWING UNSAFE ACCESS !!!!\n"); 1.120 - return 0; 1.121 + return DECODE_EA_FAILED; 1.122 } 1.123 1.124 *ppb = pb; 1.125 *preg = regreg; 1.126 *pmem = (void *)ea; 1.127 1.128 - return 1; 1.129 + return DECODE_EA_SUCCESS; 1.130 } 1.131 1.132 +#define GET_IMM8 \ 1.133 + if ( get_user(ib, (u8 *)pb) ) { \ 1.134 + DPRINTK("Fault while extracting imm8\n"); \ 1.135 + return 0; \ 1.136 + } \ 1.137 + pb += 1; 1.138 +#define GET_IMM16 \ 1.139 + if ( get_user(iw, (u8 *)pb) ) { \ 1.140 + DPRINTK("Fault while extracting imm16\n"); \ 1.141 + return 0; \ 1.142 + } \ 1.143 + pb += 2; 1.144 +#define GET_IMM32 \ 1.145 + if ( get_user(il, (u32 *)pb) ) { \ 1.146 + DPRINTK("Fault while extracting imm32\n"); \ 1.147 + return 0; \ 1.148 + } \ 1.149 + pb += 4; 1.150 + 1.151 /* 1.152 * Called from the general-protection fault handler to attempt to decode 1.153 * and emulate an instruction that depends on 4GB segments. At this point 1.154 @@ -239,14 +272,17 @@ int gpf_emulate_4gb(struct pt_regs *regs 1.155 { 1.156 struct domain *d = current; 1.157 trap_info_t *ti; 1.158 - u8 *eip, *nextbyte, b, mb, rb; 1.159 - u16 mw, rw; 1.160 - u32 ml, rl, eflags; 1.161 - unsigned int *pseg = NULL; 1.162 - int i; 1.163 + struct guest_trap_bounce *gtb; 1.164 + 1.165 + u8 *eip; /* ptr to instruction start */ 1.166 + u8 *pb, b; /* ptr into instr. / current instr. byte */ 1.167 + u8 ib, mb, rb; /* byte operand from imm/register/memory */ 1.168 + u16 iw, mw, rw; /* word operand from imm/register/memory */ 1.169 + u32 il, ml, rl; /* long operand from imm/register/memory */ 1.170 + void *reg, *mem; /* ptr to register/memory operand */ 1.171 + unsigned int *pseg = NULL; /* segment for memory operand (NULL=default) */ 1.172 + u32 eflags; 1.173 int opsz_override = 0; 1.174 - void *reg, *mem; 1.175 - struct guest_trap_bounce *gtb; 1.176 1.177 if ( !linearise_address((u16)regs->xcs, regs->eip, (unsigned long *)&eip) ) 1.178 { 1.179 @@ -255,11 +291,11 @@ int gpf_emulate_4gb(struct pt_regs *regs 1.180 } 1.181 1.182 /* Parse prefix bytes. We're basically looking for segment override. */ 1.183 - for ( i = 0; i < 4; i++ ) 1.184 + for ( pb = eip; (pb - eip) < 4; pb++ ) 1.185 { 1.186 - if ( get_user(b, &eip[i]) ) 1.187 + if ( get_user(b, pb) ) 1.188 { 1.189 - DPRINTK("Fault while accessing byte %d of instruction\n", i); 1.190 + DPRINTK("Fault while accessing byte %d of instruction\n", pb-eip); 1.191 return 0; 1.192 } 1.193 1.194 @@ -298,141 +334,94 @@ int gpf_emulate_4gb(struct pt_regs *regs 1.195 } 1.196 done_prefix: 1.197 1.198 - nextbyte = &eip[i+1]; 1.199 - if ( !decode_effective_address(&nextbyte, ®, &mem, pseg, regs) ) 1.200 + pb++; /* skip opcode byte */ 1.201 + switch ( decode_effective_address(&pb, ®, &mem, pseg, regs) ) 1.202 + { 1.203 + case DECODE_EA_FAILED: 1.204 + return 0; 1.205 + case DECODE_EA_FIXME: 1.206 goto undecodeable; 1.207 + } 1.208 1.209 /* Only handle single-byte opcodes right now. Sufficient for MOV. */ 1.210 - /* 1.211 - * XXX Now I see how this decode routine is panning out, it needs 1.212 - * refactoring. Lots of duplicated cruft in here... 1.213 - */ 1.214 switch ( b ) 1.215 { 1.216 case 0x88: /* movb r,r/m */ 1.217 if ( __put_user(*(u8 *)reg, (u8 *)mem) ) 1.218 goto page_fault_w; 1.219 - regs->eip += nextbyte - eip; 1.220 break; 1.221 case 0x89: /* movl r,r/m */ 1.222 - if ( opsz_override ) 1.223 - { 1.224 - if ( __put_user(*(u16 *)reg, (u16 *)mem) ) 1.225 - goto page_fault_w; 1.226 - } 1.227 - else 1.228 - { 1.229 - if ( __put_user(*(u32 *)reg, (u32 *)mem) ) 1.230 - goto page_fault_w; 1.231 - } 1.232 - regs->eip += nextbyte - eip; 1.233 + if ( opsz_override ? __put_user(*(u16 *)reg, (u16 *)mem) 1.234 + : __put_user(*(u32 *)reg, (u32 *)mem) ) 1.235 + goto page_fault_w; 1.236 break; 1.237 case 0x8a: /* movb r/m,r */ 1.238 if ( __get_user(*(u8 *)reg, (u8 *)mem) ) 1.239 goto page_fault_r; 1.240 - regs->eip += nextbyte - eip; 1.241 break; 1.242 case 0x8b: /* movl r/m,r */ 1.243 - if ( opsz_override ) 1.244 - { 1.245 - if ( __get_user(*(u16 *)reg, (u16 *)mem) ) 1.246 - goto page_fault_r; 1.247 - } 1.248 - else 1.249 - { 1.250 - if ( __get_user(*(u32 *)reg, (u32 *)mem) ) 1.251 - goto page_fault_r; 1.252 - } 1.253 - regs->eip += nextbyte - eip; 1.254 + if ( opsz_override ? __get_user(*(u16 *)reg, (u16 *)mem) 1.255 + : __get_user(*(u32 *)reg, (u32 *)mem) ) 1.256 + goto page_fault_r; 1.257 break; 1.258 case 0xc6: /* movb imm,r/m */ 1.259 if ( reg != ®s->eax ) /* Reg == /0 */ 1.260 goto undecodeable; 1.261 - if ( get_user(rb, nextbyte) ) 1.262 - { 1.263 - DPRINTK("Fault while extracting immediate byte\n"); 1.264 - return 0; 1.265 - } 1.266 - if ( __put_user(rb, (u8 *)mem) ) 1.267 + GET_IMM8; 1.268 + if ( __put_user(ib, (u8 *)mem) ) 1.269 goto page_fault_w; 1.270 - regs->eip += nextbyte - eip + 1; 1.271 break; 1.272 case 0xc7: /* movl imm,r/m */ 1.273 if ( reg != ®s->eax ) /* Reg == /0 */ 1.274 goto undecodeable; 1.275 if ( opsz_override ) 1.276 { 1.277 - if ( get_user(rw, (u16 *)nextbyte) ) 1.278 - { 1.279 - DPRINTK("Fault while extracting immediate word\n"); 1.280 - return 0; 1.281 - } 1.282 - if ( __put_user(rw, (u16 *)mem) ) 1.283 + GET_IMM16; 1.284 + if ( __put_user(iw, (u16 *)mem) ) 1.285 goto page_fault_w; 1.286 - regs->eip += nextbyte - eip + 2; 1.287 } 1.288 else 1.289 { 1.290 - if ( get_user(rl, (u32 *)nextbyte) ) 1.291 - { 1.292 - DPRINTK("Fault while extracting immediate longword\n"); 1.293 - return 0; 1.294 - } 1.295 - if ( __put_user(rl, (u32 *)mem) ) 1.296 + GET_IMM32; 1.297 + if ( __put_user(il, (u32 *)mem) ) 1.298 goto page_fault_w; 1.299 - regs->eip += nextbyte - eip + 4; 1.300 } 1.301 break; 1.302 case 0x80: /* cmpb imm8,r/m */ 1.303 if ( reg != ®s->edi ) /* Reg == /7 */ 1.304 goto undecodeable; 1.305 - if ( get_user(rb, nextbyte) ) 1.306 - { 1.307 - DPRINTK("Fault while extracting immediate byte\n"); 1.308 - return 0; 1.309 - } 1.310 + GET_IMM8; 1.311 if ( __get_user(mb, (u8 *)mem) ) 1.312 goto page_fault_r; 1.313 __asm__ __volatile__ ( 1.314 "cmpb %b1,%b2 ; pushf ; popl %0" 1.315 : "=a" (eflags) 1.316 - : "0" (rb), "b" (mb) ); 1.317 + : "0" (ib), "b" (mb) ); 1.318 regs->eflags &= ~0x8d5; /* OF,SF,ZF,AF,PF,CF */ 1.319 regs->eflags |= eflags & 0x8d5; 1.320 - regs->eip += nextbyte - eip + 1; 1.321 break; 1.322 case 0x81: /* cmpl imm32,r/m */ 1.323 if ( reg != ®s->edi ) /* Reg == /7 */ 1.324 goto undecodeable; 1.325 if ( opsz_override ) 1.326 { 1.327 - if ( get_user(rw, (u16 *)nextbyte) ) 1.328 - { 1.329 - DPRINTK("Fault while extracting immediate word\n"); 1.330 - return 0; 1.331 - } 1.332 + GET_IMM16; 1.333 if ( __get_user(mw, (u16 *)mem) ) 1.334 goto page_fault_r; 1.335 __asm__ __volatile__ ( 1.336 "cmpw %w1,%w2 ; pushf ; popl %0" 1.337 : "=a" (eflags) 1.338 - : "0" (rw), "b" (mw) ); 1.339 - regs->eip += nextbyte - eip + 2; 1.340 + : "0" (iw), "b" (mw) ); 1.341 } 1.342 else 1.343 { 1.344 - if ( get_user(rl, (u32 *)nextbyte) ) 1.345 - { 1.346 - DPRINTK("Fault while extracting immediate longword\n"); 1.347 - return 0; 1.348 - } 1.349 + GET_IMM32; 1.350 if ( __get_user(ml, (u32 *)mem) ) 1.351 goto page_fault_r; 1.352 __asm__ __volatile__ ( 1.353 "cmpl %1,%2 ; pushf ; popl %0" 1.354 : "=a" (eflags) 1.355 - : "0" (rl), "b" (ml) ); 1.356 - regs->eip += nextbyte - eip + 4; 1.357 + : "0" (il), "b" (ml) ); 1.358 } 1.359 regs->eflags &= ~0x8d5; /* OF,SF,ZF,AF,PF,CF */ 1.360 regs->eflags |= eflags & 0x8d5; 1.361 @@ -440,35 +429,29 @@ int gpf_emulate_4gb(struct pt_regs *regs 1.362 case 0x83: /* cmpl imm8,r/m */ 1.363 if ( reg != ®s->edi ) /* Reg == /7 */ 1.364 goto undecodeable; 1.365 - if ( get_user(rb, nextbyte) ) 1.366 - { 1.367 - DPRINTK("Fault while extracting immediate byte\n"); 1.368 - return 0; 1.369 - } 1.370 + GET_IMM8; 1.371 if ( opsz_override ) 1.372 { 1.373 - rw = (rb & 0x80) ? (rb | ~0xff) : rb; 1.374 + iw = (u16)(s16)(s8)ib; 1.375 if ( __get_user(mw, (u16 *)mem) ) 1.376 goto page_fault_r; 1.377 __asm__ __volatile__ ( 1.378 "cmpw %w1,%w2 ; pushf ; popl %0" 1.379 : "=a" (eflags) 1.380 - : "0" (rw), "b" (mw) ); 1.381 - regs->eip += nextbyte - eip + 2; 1.382 + : "0" (iw), "b" (mw) ); 1.383 } 1.384 else 1.385 { 1.386 - rl = (rb & 0x80) ? (rb | ~0xff) : rb; 1.387 + il = (u32)(s32)(s8)ib; 1.388 if ( __get_user(ml, (u32 *)mem) ) 1.389 goto page_fault_r; 1.390 __asm__ __volatile__ ( 1.391 "cmpl %1,%2 ; pushf ; popl %0" 1.392 : "=a" (eflags) 1.393 - : "0" (rl), "b" (ml) ); 1.394 + : "0" (il), "b" (ml) ); 1.395 } 1.396 regs->eflags &= ~0x8d5; /* OF,SF,ZF,AF,PF,CF */ 1.397 regs->eflags |= eflags & 0x8d5; 1.398 - regs->eip += nextbyte - eip + 1; 1.399 break; 1.400 case 0x38: /* cmpb r,r/m */ 1.401 case 0x3a: /* cmpb r/m,r */ 1.402 @@ -481,7 +464,6 @@ int gpf_emulate_4gb(struct pt_regs *regs 1.403 : "0" ((b==0x38)?rb:mb), "b" ((b==0x38)?mb:rb) ); 1.404 regs->eflags &= ~0x8d5; /* OF,SF,ZF,AF,PF,CF */ 1.405 regs->eflags |= eflags & 0x8d5; 1.406 - regs->eip += nextbyte - eip; 1.407 break; 1.408 case 0x39: /* cmpl r,r/m */ 1.409 case 0x3b: /* cmpl r/m,r */ 1.410 @@ -507,24 +489,23 @@ int gpf_emulate_4gb(struct pt_regs *regs 1.411 } 1.412 regs->eflags &= ~0x8d5; /* OF,SF,ZF,AF,PF,CF */ 1.413 regs->eflags |= eflags & 0x8d5; 1.414 - regs->eip += nextbyte - eip; 1.415 break; 1.416 default: 1.417 DPRINTK("Unhandleable opcode byte %02x\n", b); 1.418 goto undecodeable; 1.419 } 1.420 1.421 + /* Success! */ 1.422 + regs->eip += pb - eip; 1.423 perfc_incrc(emulations); 1.424 - 1.425 - /* Success! */ 1.426 return 1; 1.427 1.428 undecodeable: 1.429 - printk("Undecodable instruction %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x " 1.430 - "caused GPF(0) at %04x:%08lx\n", 1.431 - eip[0], eip[1], eip[2], eip[3], 1.432 - eip[4], eip[5], eip[6], eip[7], 1.433 - regs->xcs, regs->eip); 1.434 + DPRINTK("Undecodable instruction %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x " 1.435 + "caused GPF(0) at %04x:%08lx\n", 1.436 + eip[0], eip[1], eip[2], eip[3], 1.437 + eip[4], eip[5], eip[6], eip[7], 1.438 + regs->xcs, regs->eip); 1.439 return 0; 1.440 1.441 page_fault_w: