debuggers.hg

view xen/arch/x86/x86_32/seg_fixup.c @ 3715:d93748c50893

bitkeeper revision 1.1159.212.100 (42050e5fWLAKCQAvoZ3CPmyAaL-51g)

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