debuggers.hg

view xen/arch/x86/x86_32/seg_fixup.c @ 3491:2c56c6b39a48

bitkeeper revision 1.1159.212.18 (41ebe1caQQ_SlJestrvsT95t1oER-Q)

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