debuggers.hg
annotate xen/arch/x86/x86_32/seg_fixup.c @ 3674:fb875591fd72
bitkeeper revision 1.1159.223.63 (42028527-fv-d9BM0_LRp8UKGP19gQ)
Fix NMI deferral.
Signed-off-by: keir.fraser@cl.cam.ac.uk
Fix NMI deferral.
Signed-off-by: keir.fraser@cl.cam.ac.uk
author | kaf24@scramble.cl.cam.ac.uk |
---|---|
date | Thu Feb 03 20:10:15 2005 +0000 (2005-02-03) |
parents | 983a02b6959a |
children | 7a4e8660d4f4 58658b628754 |
rev | line source |
---|---|
kaf24@2704 | 1 /****************************************************************************** |
kaf24@2704 | 2 * arch/x86/x86_32/seg_fixup.c |
kaf24@2704 | 3 * |
kaf24@2704 | 4 * Support for -ve accesses to pseudo-4GB segments. |
kaf24@2704 | 5 * |
kaf24@2704 | 6 * Copyright (c) 2004, K A Fraser |
kaf24@2704 | 7 * |
kaf24@2704 | 8 * This program is free software; you can redistribute it and/or modify |
kaf24@2704 | 9 * it under the terms of the GNU General Public License as published by |
kaf24@2704 | 10 * the Free Software Foundation; either version 2 of the License, or |
kaf24@2704 | 11 * (at your option) any later version. |
kaf24@2704 | 12 * |
kaf24@2704 | 13 * This program is distributed in the hope that it will be useful, |
kaf24@2704 | 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
kaf24@2704 | 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
kaf24@2704 | 16 * GNU General Public License for more details. |
kaf24@2704 | 17 * |
kaf24@2704 | 18 * You should have received a copy of the GNU General Public License |
kaf24@2704 | 19 * along with this program; if not, write to the Free Software |
kaf24@2704 | 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
kaf24@2704 | 21 */ |
kaf24@2704 | 22 |
kaf24@2704 | 23 #include <xen/config.h> |
kaf24@2704 | 24 #include <xen/init.h> |
kaf24@2704 | 25 #include <xen/sched.h> |
kaf24@2704 | 26 #include <xen/lib.h> |
kaf24@2704 | 27 #include <xen/errno.h> |
kaf24@2704 | 28 #include <xen/mm.h> |
kaf24@2704 | 29 #include <xen/perfc.h> |
kaf24@2704 | 30 #include <asm/processor.h> |
kaf24@2704 | 31 |
kaf24@2704 | 32 /* Make the scary benign errors go away. */ |
kaf24@2704 | 33 #undef DPRINTK |
kaf24@2704 | 34 #define DPRINTK(_f, _a...) ((void)0) |
kaf24@2704 | 35 |
kaf24@2704 | 36 /* General instruction properties. */ |
kaf24@2704 | 37 #define INSN_SUFFIX_BYTES (7) |
kaf24@2704 | 38 #define OPCODE_BYTE (1<<4) |
kaf24@2704 | 39 #define HAS_MODRM (1<<5) |
kaf24@2704 | 40 |
kaf24@2704 | 41 /* Short forms for the table. */ |
kaf24@2704 | 42 #define X 0 /* invalid for some random reason */ |
kaf24@2704 | 43 #define O OPCODE_BYTE |
kaf24@2704 | 44 #define M HAS_MODRM |
kaf24@2704 | 45 |
kaf24@2704 | 46 static unsigned char insn_decode[256] = { |
kaf24@2704 | 47 /* 0x00 - 0x0F */ |
kaf24@2704 | 48 O|M, O|M, O|M, O|M, X, X, X, X, |
kaf24@2704 | 49 O|M, O|M, O|M, O|M, X, X, X, X, |
kaf24@2704 | 50 /* 0x10 - 0x1F */ |
kaf24@2704 | 51 O|M, O|M, O|M, O|M, X, X, X, X, |
kaf24@2704 | 52 O|M, O|M, O|M, O|M, X, X, X, X, |
kaf24@2704 | 53 /* 0x20 - 0x2F */ |
kaf24@2704 | 54 O|M, O|M, O|M, O|M, X, X, X, X, |
kaf24@2704 | 55 O|M, O|M, O|M, O|M, X, X, X, X, |
kaf24@2704 | 56 /* 0x30 - 0x3F */ |
kaf24@2704 | 57 O|M, O|M, O|M, O|M, X, X, X, X, |
kaf24@2704 | 58 O|M, O|M, O|M, O|M, X, X, X, X, |
kaf24@2704 | 59 /* 0x40 - 0x4F */ |
kaf24@2704 | 60 X, X, X, X, X, X, X, X, |
kaf24@2704 | 61 X, X, X, X, X, X, X, X, |
kaf24@2704 | 62 /* 0x50 - 0x5F */ |
kaf24@2704 | 63 X, X, X, X, X, X, X, X, |
kaf24@2704 | 64 X, X, X, X, X, X, X, X, |
kaf24@2704 | 65 /* 0x60 - 0x6F */ |
kaf24@2704 | 66 X, X, X, X, X, X, X, X, |
kaf24@2704 | 67 X, O|M|4, X, O|M|1, X, X, X, X, |
kaf24@2704 | 68 /* 0x70 - 0x7F */ |
kaf24@2704 | 69 X, X, X, X, X, X, X, X, |
kaf24@2704 | 70 X, X, X, X, X, X, X, X, |
kaf24@2704 | 71 /* 0x80 - 0x8F */ |
kaf24@2704 | 72 O|M|1, O|M|4, O|M|1, O|M|1, O|M, O|M, O|M, O|M, |
kaf24@2704 | 73 O|M, O|M, O|M, O|M, O|M, O|M, O|M, X, |
kaf24@2704 | 74 /* 0x90 - 0x9F */ |
kaf24@2704 | 75 X, X, X, X, X, X, X, X, |
kaf24@2704 | 76 X, X, X, X, X, X, X, X, |
kaf24@2704 | 77 /* 0xA0 - 0xAF */ |
kaf24@3464 | 78 O|4, O|4, O|4, O|4, X, X, X, X, |
kaf24@2704 | 79 X, X, X, X, X, X, X, X, |
kaf24@2704 | 80 /* 0xB0 - 0xBF */ |
kaf24@2704 | 81 X, X, X, X, X, X, X, X, |
kaf24@2704 | 82 X, X, X, X, X, X, X, X, |
kaf24@2704 | 83 /* 0xC0 - 0xCF */ |
kaf24@2704 | 84 O|M|1, O|M|1, X, X, X, X, O|M|1, O|M|4, |
kaf24@2704 | 85 X, X, X, X, X, X, X, X, |
kaf24@2704 | 86 /* 0xD0 - 0xDF */ |
kaf24@2704 | 87 O|M, O|M, O|M, O|M, X, X, X, X, |
kaf24@2704 | 88 X, X, X, X, X, X, X, X, |
kaf24@2704 | 89 /* 0xE0 - 0xEF */ |
kaf24@2704 | 90 X, X, X, X, X, X, X, X, |
kaf24@2704 | 91 X, X, X, X, X, X, X, X, |
kaf24@2704 | 92 /* 0xF0 - 0xFF */ |
kaf24@2704 | 93 X, X, X, X, X, X, X, X, |
kaf24@2704 | 94 X, X, X, X, X, X, O|M, O|M |
kaf24@2704 | 95 }; |
kaf24@2704 | 96 |
kaf24@2704 | 97 /* |
kaf24@2704 | 98 * Obtain the base and limit associated with the given segment selector. |
kaf24@2704 | 99 * The selector must identify a 32-bit code or data segment. Any segment that |
kaf24@2704 | 100 * appears to be truncated to not overlap with Xen is assumed to be a truncated |
kaf24@2704 | 101 * 4GB segment, and the returned limit reflects this. |
kaf24@2704 | 102 * @seg (IN) : Segment selector to decode. |
kaf24@2704 | 103 * @base (OUT): Decoded linear base address. |
kaf24@2704 | 104 * @limit (OUT): Decoded segment limit, in bytes. 0 == unlimited (4GB). |
kaf24@2704 | 105 */ |
kaf24@2704 | 106 int get_baselimit(u16 seg, unsigned long *base, unsigned long *limit) |
kaf24@2704 | 107 { |
kaf24@2704 | 108 struct domain *d = current; |
kaf24@2704 | 109 unsigned long *table, a, b; |
kaf24@2704 | 110 int ldt = !!(seg & 4); |
kaf24@2704 | 111 int idx = (seg >> 3) & 8191; |
kaf24@2704 | 112 |
kaf24@2704 | 113 /* Get base and check limit. */ |
kaf24@2704 | 114 if ( ldt ) |
kaf24@2704 | 115 { |
kaf24@2704 | 116 table = (unsigned long *)LDT_VIRT_START; |
kaf24@2704 | 117 if ( idx >= d->mm.ldt_ents ) |
kaf24@2704 | 118 goto fail; |
kaf24@2704 | 119 } |
kaf24@2704 | 120 else /* gdt */ |
kaf24@2704 | 121 { |
kaf24@2704 | 122 table = (unsigned long *)GET_GDT_ADDRESS(d); |
kaf24@2704 | 123 if ( idx >= GET_GDT_ENTRIES(d) ) |
kaf24@2704 | 124 goto fail; |
kaf24@2704 | 125 } |
kaf24@2704 | 126 |
kaf24@2704 | 127 /* Grab the segment descriptor. */ |
kaf24@2704 | 128 if ( __get_user(a, &table[2*idx+0]) || |
kaf24@2704 | 129 __get_user(b, &table[2*idx+1]) ) |
kaf24@2704 | 130 goto fail; /* Barking up the wrong tree. Decode needs a page fault.*/ |
kaf24@2704 | 131 |
kaf24@2704 | 132 /* We only parse 32-bit code and data segments. */ |
kaf24@2704 | 133 if ( (b & (_SEGMENT_P|_SEGMENT_S|_SEGMENT_DB)) != |
kaf24@2704 | 134 (_SEGMENT_P|_SEGMENT_S|_SEGMENT_DB) ) |
kaf24@2704 | 135 goto fail; |
kaf24@2704 | 136 |
kaf24@2704 | 137 /* Decode base and limit. */ |
kaf24@2704 | 138 *base = (b&(0xff<<24)) | ((b&0xff)<<16) | (a>>16); |
kaf24@2704 | 139 *limit = ((b & 0xf0000) | (a & 0x0ffff)) + 1; |
kaf24@2704 | 140 if ( (b & _SEGMENT_G) ) |
kaf24@2704 | 141 *limit <<= 12; |
kaf24@2704 | 142 |
kaf24@2704 | 143 /* |
kaf24@2704 | 144 * Anything that looks like a truncated segment we assume ought really |
kaf24@2704 | 145 * to be a 4GB segment. DANGER! |
kaf24@2704 | 146 */ |
kaf24@2704 | 147 if ( (PAGE_OFFSET - (*base + *limit)) < PAGE_SIZE ) |
kaf24@2704 | 148 *limit = 0; |
kaf24@2704 | 149 |
kaf24@2704 | 150 return 1; |
kaf24@2704 | 151 |
kaf24@2704 | 152 fail: |
kaf24@2704 | 153 return 0; |
kaf24@2704 | 154 } |
kaf24@2704 | 155 |
kaf24@2704 | 156 /* Turn a segment+offset into a linear address. */ |
kaf24@2704 | 157 int linearise_address(u16 seg, unsigned long off, unsigned long *linear) |
kaf24@2704 | 158 { |
kaf24@2704 | 159 unsigned long base, limit; |
kaf24@2704 | 160 |
kaf24@2704 | 161 if ( !get_baselimit(seg, &base, &limit) ) |
kaf24@2704 | 162 return 0; |
kaf24@2704 | 163 |
kaf24@2704 | 164 if ( off > (limit-1) ) |
kaf24@2704 | 165 return 0; |
kaf24@2704 | 166 |
kaf24@2704 | 167 *linear = base + off; |
kaf24@2704 | 168 |
kaf24@2704 | 169 return 1; |
kaf24@2704 | 170 } |
kaf24@2704 | 171 |
mafetter@3155 | 172 int fixup_seg(u16 seg, unsigned long offset) |
kaf24@2704 | 173 { |
kaf24@2704 | 174 struct domain *d = current; |
kaf24@2704 | 175 unsigned long *table, a, b, base, limit; |
kaf24@2704 | 176 int ldt = !!(seg & 4); |
kaf24@2704 | 177 int idx = (seg >> 3) & 8191; |
kaf24@2704 | 178 |
kaf24@2704 | 179 /* Get base and check limit. */ |
kaf24@2704 | 180 if ( ldt ) |
kaf24@2704 | 181 { |
kaf24@2704 | 182 table = (unsigned long *)LDT_VIRT_START; |
kaf24@2704 | 183 if ( idx >= d->mm.ldt_ents ) |
kaf24@2704 | 184 { |
kaf24@3449 | 185 DPRINTK("Segment %04x out of LDT range (%ld)\n", |
kaf24@2704 | 186 seg, d->mm.ldt_ents); |
kaf24@2704 | 187 goto fail; |
kaf24@2704 | 188 } |
kaf24@2704 | 189 } |
kaf24@2704 | 190 else /* gdt */ |
kaf24@2704 | 191 { |
kaf24@2704 | 192 table = (unsigned long *)GET_GDT_ADDRESS(d); |
kaf24@2704 | 193 if ( idx >= GET_GDT_ENTRIES(d) ) |
kaf24@2704 | 194 { |
kaf24@2704 | 195 DPRINTK("Segment %04x out of GDT range (%d)\n", |
kaf24@2704 | 196 seg, GET_GDT_ENTRIES(d)); |
kaf24@2704 | 197 goto fail; |
kaf24@2704 | 198 } |
kaf24@2704 | 199 } |
kaf24@2704 | 200 |
kaf24@2704 | 201 /* Grab the segment descriptor. */ |
kaf24@2704 | 202 if ( __get_user(a, &table[2*idx+0]) || |
kaf24@2704 | 203 __get_user(b, &table[2*idx+1]) ) |
kaf24@2704 | 204 { |
kaf24@2704 | 205 DPRINTK("Fault while reading segment %04x\n", seg); |
kaf24@2704 | 206 goto fail; /* Barking up the wrong tree. Decode needs a page fault.*/ |
kaf24@2704 | 207 } |
kaf24@2704 | 208 |
kaf24@2704 | 209 /* We only parse 32-bit page-granularity non-privileged data segments. */ |
kaf24@2704 | 210 if ( (b & (_SEGMENT_P|_SEGMENT_S|_SEGMENT_DB| |
mafetter@3155 | 211 _SEGMENT_G|_SEGMENT_CODE|_SEGMENT_DPL)) != |
kaf24@2704 | 212 (_SEGMENT_P|_SEGMENT_S|_SEGMENT_DB|_SEGMENT_G|_SEGMENT_DPL) ) |
kaf24@2704 | 213 { |
kaf24@2704 | 214 DPRINTK("Bad segment %08lx:%08lx\n", a, b); |
kaf24@2704 | 215 goto fail; |
kaf24@2704 | 216 } |
kaf24@2704 | 217 |
kaf24@2704 | 218 /* Decode base and limit. */ |
kaf24@2704 | 219 base = (b&(0xff<<24)) | ((b&0xff)<<16) | (a>>16); |
kaf24@2704 | 220 limit = (((b & 0xf0000) | (a & 0x0ffff)) + 1) << 12; |
kaf24@2704 | 221 |
mafetter@3155 | 222 if ( b & _SEGMENT_EC ) |
kaf24@2704 | 223 { |
kaf24@2704 | 224 /* Expands-down: All the way to zero? Assume 4GB if so. */ |
mafetter@3155 | 225 if ( ((base + limit) < PAGE_SIZE) && (offset <= limit) ) |
kaf24@2704 | 226 { |
kaf24@2704 | 227 /* Flip to expands-up. */ |
kaf24@3137 | 228 limit = PAGE_OFFSET - base; |
kaf24@2704 | 229 goto flip; |
kaf24@2704 | 230 } |
kaf24@2704 | 231 } |
kaf24@2704 | 232 else |
kaf24@2704 | 233 { |
kaf24@3449 | 234 /* Expands-up: All the way to Xen space? Assume 4GB if so. */ |
mafetter@3155 | 235 if ( ((PAGE_OFFSET - (base + limit)) < PAGE_SIZE) && |
kaf24@3449 | 236 (offset > limit) ) |
kaf24@2704 | 237 { |
kaf24@2704 | 238 /* Flip to expands-down. */ |
kaf24@3137 | 239 limit = -(base & PAGE_MASK); |
kaf24@2704 | 240 goto flip; |
kaf24@2704 | 241 } |
kaf24@2704 | 242 } |
kaf24@2704 | 243 |
kaf24@3449 | 244 DPRINTK("None of the above! (%08lx:%08lx, %08lx, %08lx, %08lx)\n", |
kaf24@3449 | 245 a, b, base, limit, base+limit); |
kaf24@2704 | 246 |
kaf24@2704 | 247 fail: |
kaf24@2704 | 248 return 0; |
kaf24@2704 | 249 |
kaf24@2704 | 250 flip: |
kaf24@3137 | 251 limit = (limit >> 12) - 1; |
kaf24@2704 | 252 a &= ~0x0ffff; a |= limit & 0x0ffff; |
kaf24@2704 | 253 b &= ~0xf0000; b |= limit & 0xf0000; |
mafetter@3155 | 254 b ^= _SEGMENT_EC; /* grows-up <-> grows-down */ |
kaf24@2704 | 255 /* NB. These can't fault. Checked readable above; must also be writable. */ |
kaf24@2704 | 256 table[2*idx+0] = a; |
kaf24@2704 | 257 table[2*idx+1] = b; |
kaf24@2704 | 258 return 1; |
kaf24@2704 | 259 } |
kaf24@2704 | 260 |
kaf24@2704 | 261 /* Decode Reg field of a ModRM byte: return a pointer into a register block. */ |
ach61@2843 | 262 void *decode_reg(struct xen_regs *regs, u8 b) |
kaf24@2704 | 263 { |
kaf24@2704 | 264 switch ( b & 7 ) |
kaf24@2704 | 265 { |
kaf24@2704 | 266 case 0: return ®s->eax; |
kaf24@2704 | 267 case 1: return ®s->ecx; |
kaf24@2704 | 268 case 2: return ®s->edx; |
kaf24@2704 | 269 case 3: return ®s->ebx; |
kaf24@2704 | 270 case 4: return ®s->esp; |
kaf24@2704 | 271 case 5: return ®s->ebp; |
kaf24@2704 | 272 case 6: return ®s->esi; |
kaf24@2704 | 273 case 7: return ®s->edi; |
kaf24@2704 | 274 } |
kaf24@2704 | 275 |
kaf24@2704 | 276 return NULL; |
kaf24@2704 | 277 } |
kaf24@2704 | 278 |
kaf24@2704 | 279 /* |
kaf24@2704 | 280 * Called from the general-protection fault handler to attempt to decode |
kaf24@3462 | 281 * and emulate an instruction that depends on 4GB segments. |
kaf24@2704 | 282 */ |
ach61@2843 | 283 int gpf_emulate_4gb(struct xen_regs *regs) |
kaf24@2704 | 284 { |
kaf24@2704 | 285 struct domain *d = current; |
kaf24@2704 | 286 trap_info_t *ti; |
kaf24@3081 | 287 struct trap_bounce *tb; |
kaf24@2704 | 288 u8 modrm, mod, reg, rm, decode; |
kaf24@2704 | 289 void *memreg, *regreg; |
kaf24@2704 | 290 unsigned long offset; |
kaf24@2704 | 291 u8 disp8; |
kaf24@2704 | 292 u32 disp32 = 0; |
kaf24@2704 | 293 u8 *eip; /* ptr to instruction start */ |
kaf24@2704 | 294 u8 *pb, b; /* ptr into instr. / current instr. byte */ |
kaf24@2704 | 295 unsigned int *pseg = NULL; /* segment for memory operand (NULL=default) */ |
kaf24@2704 | 296 |
kaf24@2704 | 297 /* WARNING: We only work for ring-3 segments. */ |
kaf24@3207 | 298 if ( unlikely(VM86_MODE(regs)) || unlikely(!RING_3(regs)) ) |
kaf24@2704 | 299 { |
kaf24@2956 | 300 DPRINTK("Taken fault at bad CS %04x\n", regs->cs); |
kaf24@2704 | 301 goto fail; |
kaf24@2704 | 302 } |
kaf24@2704 | 303 |
kaf24@2956 | 304 if ( !linearise_address((u16)regs->cs, regs->eip, (unsigned long *)&eip) ) |
kaf24@2704 | 305 { |
kaf24@3449 | 306 DPRINTK("Cannot linearise %04x:%08x\n", regs->cs, regs->eip); |
kaf24@2704 | 307 goto fail; |
kaf24@2704 | 308 } |
kaf24@2704 | 309 |
kaf24@2704 | 310 /* Parse prefix bytes. We're basically looking for segment override. */ |
kaf24@2704 | 311 for ( pb = eip; ; pb++ ) |
kaf24@2704 | 312 { |
kaf24@2704 | 313 if ( get_user(b, pb) ) |
kaf24@2704 | 314 { |
kaf24@2704 | 315 DPRINTK("Fault while accessing byte %d of instruction\n", pb-eip); |
kaf24@3462 | 316 goto page_fault; |
kaf24@2704 | 317 } |
kaf24@2704 | 318 |
mafetter@3155 | 319 if ( (pb - eip) >= 15 ) |
mafetter@3155 | 320 { |
mafetter@3155 | 321 DPRINTK("Too many instruction prefixes for a legal instruction\n"); |
mafetter@3155 | 322 goto fail; |
mafetter@3155 | 323 } |
mafetter@3155 | 324 |
kaf24@2704 | 325 switch ( b ) |
kaf24@2704 | 326 { |
kaf24@2704 | 327 case 0x67: /* Address-size override */ |
kaf24@2704 | 328 DPRINTK("Unhandleable prefix byte %02x\n", b); |
kaf24@2704 | 329 goto fixme; |
kaf24@2704 | 330 case 0x66: /* Operand-size override */ |
mafetter@3155 | 331 case 0xf0: /* LOCK */ |
mafetter@3155 | 332 case 0xf2: /* REPNE/REPNZ */ |
mafetter@3155 | 333 case 0xf3: /* REP/REPE/REPZ */ |
kaf24@3449 | 334 break; |
kaf24@2704 | 335 case 0x2e: /* CS override */ |
kaf24@2956 | 336 pseg = ®s->cs; |
kaf24@3449 | 337 break; |
kaf24@2704 | 338 case 0x3e: /* DS override */ |
kaf24@2956 | 339 pseg = ®s->ds; |
kaf24@3449 | 340 break; |
kaf24@2704 | 341 case 0x26: /* ES override */ |
kaf24@2956 | 342 pseg = ®s->es; |
kaf24@3449 | 343 break; |
kaf24@2704 | 344 case 0x64: /* FS override */ |
kaf24@2956 | 345 pseg = ®s->fs; |
kaf24@3449 | 346 break; |
kaf24@2704 | 347 case 0x65: /* GS override */ |
kaf24@2956 | 348 pseg = ®s->gs; |
kaf24@3449 | 349 break; |
kaf24@2704 | 350 case 0x36: /* SS override */ |
kaf24@2956 | 351 pseg = ®s->ss; |
kaf24@3449 | 352 break; |
kaf24@2704 | 353 default: /* Not a prefix byte */ |
kaf24@2704 | 354 goto done_prefix; |
kaf24@2704 | 355 } |
kaf24@2704 | 356 } |
kaf24@2704 | 357 done_prefix: |
kaf24@2704 | 358 |
kaf24@2704 | 359 decode = insn_decode[b]; /* opcode byte */ |
kaf24@2704 | 360 pb++; |
kaf24@2704 | 361 if ( decode == 0 ) |
kaf24@2704 | 362 { |
kaf24@2704 | 363 DPRINTK("Unsupported opcode %02x\n", b); |
kaf24@2704 | 364 goto fail; |
kaf24@2704 | 365 } |
kaf24@2704 | 366 |
kaf24@2704 | 367 if ( !(decode & HAS_MODRM) ) |
kaf24@2704 | 368 { |
kaf24@3464 | 369 if ( (decode & 7) != 4 ) |
kaf24@3464 | 370 goto fail; |
kaf24@3464 | 371 |
kaf24@3464 | 372 if ( get_user(offset, (u32 *)pb) ) |
kaf24@2704 | 373 { |
kaf24@3464 | 374 DPRINTK("Fault while extracting <disp8>.\n"); |
kaf24@3464 | 375 goto page_fault; |
kaf24@2704 | 376 } |
kaf24@3464 | 377 pb += 4; |
kaf24@3464 | 378 |
kaf24@3464 | 379 goto skip_modrm; |
kaf24@2704 | 380 } |
kaf24@2704 | 381 |
kaf24@2704 | 382 /* |
kaf24@2704 | 383 * Mod/RM processing. |
kaf24@2704 | 384 */ |
kaf24@2704 | 385 |
kaf24@2704 | 386 if ( get_user(modrm, pb) ) |
kaf24@2704 | 387 { |
kaf24@2704 | 388 DPRINTK("Fault while extracting modrm byte\n"); |
kaf24@3462 | 389 goto page_fault; |
kaf24@2704 | 390 } |
kaf24@2704 | 391 |
kaf24@2704 | 392 pb++; |
kaf24@2704 | 393 |
kaf24@2704 | 394 mod = (modrm >> 6) & 3; |
kaf24@2704 | 395 reg = (modrm >> 3) & 7; |
kaf24@2704 | 396 rm = (modrm >> 0) & 7; |
kaf24@2704 | 397 |
kaf24@2704 | 398 if ( rm == 4 ) |
kaf24@2704 | 399 { |
kaf24@2704 | 400 DPRINTK("FIXME: Add decoding for the SIB byte.\n"); |
kaf24@2704 | 401 goto fixme; |
kaf24@2704 | 402 } |
kaf24@2704 | 403 |
kaf24@2704 | 404 /* Decode Reg and R/M fields. */ |
kaf24@2704 | 405 regreg = decode_reg(regs, reg); |
kaf24@2704 | 406 memreg = decode_reg(regs, rm); |
kaf24@2704 | 407 |
kaf24@2704 | 408 /* Decode Mod field. */ |
kaf24@2704 | 409 switch ( modrm >> 6 ) |
kaf24@2704 | 410 { |
kaf24@2704 | 411 case 0: |
kaf24@2704 | 412 if ( pseg == NULL ) |
kaf24@2956 | 413 pseg = ®s->ds; |
kaf24@2704 | 414 disp32 = 0; |
kaf24@2704 | 415 if ( rm == 5 ) /* disp32 rather than (EBP) */ |
kaf24@2704 | 416 { |
kaf24@2704 | 417 memreg = NULL; |
kaf24@2704 | 418 if ( get_user(disp32, (u32 *)pb) ) |
kaf24@2704 | 419 { |
kaf24@2704 | 420 DPRINTK("Fault while extracting <disp8>.\n"); |
kaf24@3462 | 421 goto page_fault; |
kaf24@2704 | 422 } |
kaf24@2704 | 423 pb += 4; |
kaf24@2704 | 424 } |
kaf24@2704 | 425 break; |
kaf24@2704 | 426 |
kaf24@2704 | 427 case 1: |
kaf24@2704 | 428 if ( pseg == NULL ) /* NB. EBP defaults to SS */ |
kaf24@2956 | 429 pseg = (rm == 5) ? ®s->ss : ®s->ds; |
kaf24@2704 | 430 if ( get_user(disp8, pb) ) |
kaf24@2704 | 431 { |
kaf24@2704 | 432 DPRINTK("Fault while extracting <disp8>.\n"); |
kaf24@3462 | 433 goto page_fault; |
kaf24@2704 | 434 } |
kaf24@2704 | 435 pb++; |
kaf24@2704 | 436 disp32 = (disp8 & 0x80) ? (disp8 | ~0xff) : disp8;; |
kaf24@2704 | 437 break; |
kaf24@2704 | 438 |
kaf24@2704 | 439 case 2: |
kaf24@2704 | 440 if ( pseg == NULL ) /* NB. EBP defaults to SS */ |
kaf24@2956 | 441 pseg = (rm == 5) ? ®s->ss : ®s->ds; |
kaf24@2704 | 442 if ( get_user(disp32, (u32 *)pb) ) |
kaf24@2704 | 443 { |
kaf24@2704 | 444 DPRINTK("Fault while extracting <disp8>.\n"); |
kaf24@3462 | 445 goto page_fault; |
kaf24@2704 | 446 } |
kaf24@2704 | 447 pb += 4; |
kaf24@2704 | 448 break; |
kaf24@2704 | 449 |
kaf24@2704 | 450 case 3: |
kaf24@2704 | 451 DPRINTK("Not a memory operand!\n"); |
kaf24@2704 | 452 goto fail; |
kaf24@2704 | 453 } |
kaf24@2704 | 454 |
kaf24@2704 | 455 offset = disp32; |
kaf24@2704 | 456 if ( memreg != NULL ) |
kaf24@2704 | 457 offset += *(u32 *)memreg; |
kaf24@2704 | 458 |
kaf24@2704 | 459 skip_modrm: |
mafetter@3155 | 460 if ( !fixup_seg((u16)(*pseg), offset) ) |
kaf24@2704 | 461 goto fail; |
kaf24@2704 | 462 |
kaf24@2704 | 463 /* Success! */ |
kaf24@2704 | 464 perfc_incrc(seg_fixups); |
kaf24@2704 | 465 |
kaf24@2704 | 466 /* If requested, give a callback on otherwise unused vector 15. */ |
kaf24@2704 | 467 if ( VM_ASSIST(d, VMASST_TYPE_4gb_segments_notify) ) |
kaf24@2704 | 468 { |
kaf24@2704 | 469 ti = &d->thread.traps[15]; |
kaf24@3081 | 470 tb = &d->thread.trap_bounce; |
kaf24@3127 | 471 tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE; |
kaf24@3081 | 472 tb->error_code = pb - eip; |
kaf24@3081 | 473 tb->cs = ti->cs; |
kaf24@3081 | 474 tb->eip = ti->address; |
kaf24@2704 | 475 if ( TI_GET_IF(ti) ) |
kaf24@2704 | 476 d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1; |
kaf24@2704 | 477 } |
kaf24@2704 | 478 |
kaf24@3462 | 479 return EXCRET_fault_fixed; |
kaf24@2704 | 480 |
kaf24@2704 | 481 fixme: |
kaf24@2704 | 482 DPRINTK("Undecodable instruction %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x " |
kaf24@3449 | 483 "caused GPF(0) at %04x:%08x\n", |
kaf24@2704 | 484 eip[0], eip[1], eip[2], eip[3], |
kaf24@2704 | 485 eip[4], eip[5], eip[6], eip[7], |
kaf24@2956 | 486 regs->cs, regs->eip); |
kaf24@2704 | 487 fail: |
kaf24@2704 | 488 return 0; |
kaf24@3462 | 489 |
kaf24@3462 | 490 page_fault: |
kaf24@3462 | 491 propagate_page_fault((unsigned long)pb, 4); |
kaf24@3462 | 492 return EXCRET_fault_fixed; |
kaf24@2704 | 493 } |