debuggers.hg

view xen/arch/x86/x86_32/seg_fixup.c @ 22906:700ac6445812

Now add KDB to the non-kdb tree
author Mukesh Rathor
date Thu Feb 03 15:42:41 2011 -0800 (2011-02-03)
parents 95eec4e77c3c
children
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/current.h>
31 #include <asm/processor.h>
32 #include <asm/regs.h>
33 #include <asm/x86_emulate.h>
35 /* General instruction properties. */
36 #define INSN_SUFFIX_BYTES (7)
37 #define OPCODE_BYTE (1<<4)
38 #define HAS_MODRM (1<<5)
40 /* Short forms for the table. */
41 #define X 0 /* invalid for some random reason */
42 #define O OPCODE_BYTE
43 #define M HAS_MODRM
45 static const u8 insn_decode[256] = {
46 /* 0x00 - 0x0F */
47 O|M, O|M, O|M, O|M, X, X, X, X,
48 O|M, O|M, O|M, O|M, X, X, X, X,
49 /* 0x10 - 0x1F */
50 O|M, O|M, O|M, O|M, X, X, X, X,
51 O|M, O|M, O|M, O|M, X, X, X, X,
52 /* 0x20 - 0x2F */
53 O|M, O|M, O|M, O|M, X, X, X, X,
54 O|M, O|M, O|M, O|M, X, X, X, X,
55 /* 0x30 - 0x3F */
56 O|M, O|M, O|M, O|M, X, X, X, X,
57 O|M, O|M, O|M, O|M, X, X, X, X,
58 /* 0x40 - 0x4F */
59 X, X, X, X, X, X, X, X,
60 X, X, X, X, X, X, X, X,
61 /* 0x50 - 0x5F */
62 X, X, X, X, X, X, X, X,
63 X, X, X, X, X, X, X, X,
64 /* 0x60 - 0x6F */
65 X, X, X, X, X, X, X, X,
66 X, O|M|4, X, O|M|1, X, X, X, X,
67 /* 0x70 - 0x7F */
68 X, X, X, X, X, X, X, X,
69 X, X, X, X, X, X, X, X,
70 /* 0x80 - 0x8F */
71 O|M|1, O|M|4, O|M|1, O|M|1, O|M, O|M, O|M, O|M,
72 O|M, O|M, O|M, O|M, O|M, X|M, O|M, O|M,
73 /* 0x90 - 0x9F */
74 X, X, X, X, X, X, X, X,
75 X, X, X, X, X, X, X, X,
76 /* 0xA0 - 0xAF */
77 O|4, O|4, O|4, O|4, X, X, X, X,
78 X, X, X, X, X, X, X, X,
79 /* 0xB0 - 0xBF */
80 X, X, X, X, X, X, X, X,
81 X, X, X, X, X, X, X, X,
82 /* 0xC0 - 0xCF */
83 O|M|1, O|M|1, X, X, X, X, O|M|1, O|M|4,
84 X, X, X, X, X, X, X, X,
85 /* 0xD0 - 0xDF */
86 O|M, O|M, O|M, O|M, X, X, X, X,
87 X, X, X, X, X, X, X, X,
88 /* 0xE0 - 0xEF */
89 X, X, X, X, X, X, X, X,
90 X, X, X, X, X, X, X, X,
91 /* 0xF0 - 0xFF */
92 X, X, X, X, X, X, O|M, O|M,
93 X, X, X, X, X, X, O|M, O|M
94 };
96 static const u8 float_decode[64] = {
97 O|M, O|M, O|M, O|M, O|M, O|M, O|M, O|M, /* 0xD8 */
98 O|M, X, O|M, O|M, O|M, O|M, O|M, O|M, /* 0xD9 */
99 O|M, O|M, O|M, O|M, O|M, O|M, O|M, O|M, /* 0xDA */
100 O|M, X, O|M, O|M, X, O|M, X, O|M, /* 0xDB */
101 O|M, O|M, O|M, O|M, O|M, O|M, O|M, O|M, /* 0xDC */
102 O|M, O|M, O|M, O|M, O|M, X, O|M, O|M, /* 0xDD */
103 O|M, O|M, O|M, O|M, O|M, O|M, O|M, O|M, /* 0xDE */
104 O|M, X, O|M, O|M, O|M, O|M, O|M, O|M, /* 0xDF */
105 };
107 static const u8 twobyte_decode[256] = {
108 /* 0x00 - 0x0F */
109 X, X, X, X, X, X, X, X,
110 X, X, X, X, X, X, X, X,
111 /* 0x10 - 0x1F */
112 X, X, X, X, X, X, X, X,
113 O|M, X, X, X, X, X, X, X,
114 /* 0x20 - 0x2F */
115 X, X, X, X, X, X, X, X,
116 X, X, X, X, X, X, X, X,
117 /* 0x30 - 0x3F */
118 X, X, X, X, X, X, X, X,
119 X, X, X, X, X, X, X, X,
120 /* 0x40 - 0x4F */
121 O|M, O|M, O|M, O|M, O|M, O|M, O|M, O|M,
122 O|M, O|M, O|M, O|M, O|M, O|M, O|M, O|M,
123 /* 0x50 - 0x5F */
124 X, X, X, X, X, X, X, X,
125 X, X, X, X, X, X, X, X,
126 /* 0x60 - 0x6F */
127 X, X, X, X, X, X, X, X,
128 X, X, X, X, X, X, X, X,
129 /* 0x70 - 0x7F */
130 X, X, X, X, X, X, X, X,
131 X, X, X, X, X, X, X, X,
132 /* 0x80 - 0x8F */
133 X, X, X, X, X, X, X, X,
134 X, X, X, X, X, X, X, X,
135 /* 0x90 - 0x9F */
136 O|M, O|M, O|M, O|M, O|M, O|M, O|M, O|M,
137 O|M, O|M, O|M, O|M, O|M, O|M, O|M, O|M,
138 /* 0xA0 - 0xAF */
139 X, X, X, O|M, O|M|1, O|M, O|M, X,
140 X, X, X, O|M, O|M|1, O|M, X, O|M,
141 /* 0xB0 - 0xBF */
142 X, X, X, O|M, X, X, O|M, O|M,
143 X, X, O|M|1, O|M, O|M, O|M, O|M, O|M,
144 /* 0xC0 - 0xCF */
145 O|M, O|M, X, O|M, X, X, X, O|M,
146 X, X, X, X, X, X, X, X,
147 /* 0xD0 - 0xDF */
148 X, X, X, X, X, X, X, X,
149 X, X, X, X, X, X, X, X,
150 /* 0xE0 - 0xEF */
151 X, X, X, X, X, X, X, X,
152 X, X, X, X, X, X, X, X,
153 /* 0xF0 - 0xFF */
154 X, X, X, X, X, X, X, X,
155 X, X, X, X, X, X, X, X
156 };
158 /*
159 * Obtain the base and limit associated with the given segment selector.
160 * The selector must identify a 32-bit code or data segment. Any segment that
161 * appears to be truncated to not overlap with Xen is assumed to be a truncated
162 * 4GB segment, and the returned limit reflects this.
163 * @seg (IN) : Segment selector to decode.
164 * @base (OUT): Decoded linear base address.
165 * @limit (OUT): Decoded segment limit, in bytes. 0 == unlimited (4GB).
166 */
167 static int get_baselimit(u16 seg, unsigned long *base, unsigned long *limit)
168 {
169 struct vcpu *curr = current;
170 uint32_t *table, a, b;
171 int ldt = !!(seg & 4);
172 int idx = (seg >> 3) & 8191;
174 /* Get base and check limit. */
175 if ( ldt )
176 {
177 table = (uint32_t *)LDT_VIRT_START(curr);
178 if ( idx >= curr->arch.guest_context.ldt_ents )
179 goto fail;
180 }
181 else /* gdt */
182 {
183 table = (uint32_t *)GDT_VIRT_START(curr);
184 if ( idx >= curr->arch.guest_context.gdt_ents )
185 goto fail;
186 }
188 /* Grab the segment descriptor. */
189 if ( __get_user(a, &table[2*idx+0]) ||
190 __get_user(b, &table[2*idx+1]) )
191 goto fail; /* Barking up the wrong tree. Decode needs a page fault.*/
193 /* We only parse 32-bit code and data segments. */
194 if ( (b & (_SEGMENT_P|_SEGMENT_S|_SEGMENT_DB)) !=
195 (_SEGMENT_P|_SEGMENT_S|_SEGMENT_DB) )
196 goto fail;
198 /* Decode base and limit. */
199 *base = (b&(0xff<<24)) | ((b&0xff)<<16) | (a>>16);
200 *limit = ((b & 0xf0000) | (a & 0x0ffff)) + 1;
201 if ( (b & _SEGMENT_G) )
202 *limit <<= 12;
204 /*
205 * Anything that looks like a truncated segment we assume ought really
206 * to be a 4GB segment. DANGER!
207 */
208 if ( (GUEST_SEGMENT_MAX_ADDR - (*base + *limit)) < PAGE_SIZE )
209 *limit = 0;
211 return 1;
213 fail:
214 return 0;
215 }
217 /* Turn a segment+offset into a linear address. */
218 static int linearise_address(u16 seg, unsigned long off, unsigned long *linear)
219 {
220 unsigned long base, limit;
222 if ( !get_baselimit(seg, &base, &limit) )
223 return 0;
225 if ( off > (limit-1) )
226 return 0;
228 *linear = base + off;
230 return 1;
231 }
233 static int fixup_seg(u16 seg, unsigned long offset)
234 {
235 struct vcpu *curr = current;
236 uint32_t *table, a, b, base, limit;
237 int ldt = !!(seg & 4);
238 int idx = (seg >> 3) & 8191;
240 /* Get base and check limit. */
241 if ( ldt )
242 {
243 table = (uint32_t *)LDT_VIRT_START(curr);
244 if ( idx >= curr->arch.guest_context.ldt_ents )
245 {
246 dprintk(XENLOG_DEBUG, "Segment %04x out of LDT range (%ld)\n",
247 seg, curr->arch.guest_context.ldt_ents);
248 goto fail;
249 }
250 }
251 else /* gdt */
252 {
253 table = (uint32_t *)GDT_VIRT_START(curr);
254 if ( idx >= curr->arch.guest_context.gdt_ents )
255 {
256 dprintk(XENLOG_DEBUG, "Segment %04x out of GDT range (%ld)\n",
257 seg, curr->arch.guest_context.gdt_ents);
258 goto fail;
259 }
260 }
262 /* Grab the segment descriptor. */
263 if ( __get_user(a, &table[2*idx+0]) ||
264 __get_user(b, &table[2*idx+1]) )
265 {
266 dprintk(XENLOG_DEBUG, "Fault while reading segment %04x\n", seg);
267 goto fail; /* Barking up the wrong tree. Decode needs a page fault.*/
268 }
270 /* We only parse 32-bit page-granularity non-privileged data segments. */
271 if ( (b & (_SEGMENT_P|_SEGMENT_S|_SEGMENT_DB|
272 _SEGMENT_G|_SEGMENT_CODE|_SEGMENT_DPL)) !=
273 (_SEGMENT_P|_SEGMENT_S|_SEGMENT_DB|_SEGMENT_G|_SEGMENT_DPL) )
274 {
275 dprintk(XENLOG_DEBUG, "Bad segment %08x:%08x\n", a, b);
276 goto fail;
277 }
279 /* Decode base and limit. */
280 base = (b&(0xff<<24)) | ((b&0xff)<<16) | (a>>16);
281 limit = (((b & 0xf0000) | (a & 0x0ffff)) + 1) << 12;
283 if ( b & _SEGMENT_EC )
284 {
285 /* Expands-down: All the way to zero? Assume 4GB if so. */
286 if ( ((base + limit) < PAGE_SIZE) && (offset <= limit) )
287 {
288 /* Flip to expands-up. */
289 limit = GUEST_SEGMENT_MAX_ADDR - base;
290 goto flip;
291 }
292 }
293 else
294 {
295 /* Expands-up: All the way to Xen space? Assume 4GB if so. */
296 if ( ((GUEST_SEGMENT_MAX_ADDR - (base + limit)) < PAGE_SIZE) &&
297 (offset > limit) )
298 {
299 /* Flip to expands-down. */
300 limit = -(base & PAGE_MASK);
301 goto flip;
302 }
303 }
305 dprintk(XENLOG_DEBUG, "None of the above! (%08x:%08x, %08x, %08x, %08x)\n",
306 a, b, base, limit, base+limit);
308 fail:
309 return 0;
311 flip:
312 limit = (limit >> 12) - 1;
313 a &= ~0x0ffff; a |= limit & 0x0ffff;
314 b &= ~0xf0000; b |= limit & 0xf0000;
315 b ^= _SEGMENT_EC; /* grows-up <-> grows-down */
316 /* NB. This can't fault. Checked readable above; must also be writable. */
317 atomic_write64((uint64_t *)&table[2*idx], ((uint64_t)b<<32) | a);
318 return 1;
319 }
321 /*
322 * Called from the general-protection fault handler to attempt to decode
323 * and emulate an instruction that depends on 4GB segments.
324 */
325 int gpf_emulate_4gb(struct cpu_user_regs *regs)
326 {
327 struct vcpu *curr = current;
328 u8 modrm, mod, rm, decode;
329 const u32 *base, *index = NULL;
330 unsigned long offset;
331 s8 disp8;
332 s32 disp32 = 0;
333 u8 *eip; /* ptr to instruction start */
334 u8 *pb, b; /* ptr into instr. / current instr. byte */
335 int gs_override = 0, scale = 0, opcode = -1;
336 const u8 *table = insn_decode;
338 /* WARNING: We only work for ring-3 segments. */
339 if ( unlikely(vm86_mode(regs)) || unlikely(!ring_3(regs)) )
340 goto fail;
342 if ( !linearise_address((u16)regs->cs, regs->eip, (unsigned long *)&eip) )
343 {
344 dprintk(XENLOG_DEBUG, "Cannot linearise %04x:%08x\n",
345 regs->cs, regs->eip);
346 goto fail;
347 }
349 /* Parse prefix bytes. We're basically looking for segment override. */
350 for ( pb = eip; ; pb++ )
351 {
352 if ( get_user(b, pb) )
353 {
354 dprintk(XENLOG_DEBUG,
355 "Fault while accessing byte %ld of instruction\n",
356 (long)(pb-eip));
357 goto page_fault;
358 }
360 if ( (pb - eip) >= 15 )
361 {
362 dprintk(XENLOG_DEBUG, "Too many instruction prefixes for a "
363 "legal instruction\n");
364 goto fail;
365 }
367 if ( opcode != -1 )
368 {
369 opcode = (opcode << 8) | b;
370 break;
371 }
373 switch ( b )
374 {
375 case 0x67: /* Address-size override */
376 case 0x2e: /* CS override */
377 case 0x3e: /* DS override */
378 case 0x26: /* ES override */
379 case 0x64: /* FS override */
380 case 0x36: /* SS override */
381 dprintk(XENLOG_DEBUG, "Unhandled prefix %02x\n", b);
382 goto fail;
383 case 0x66: /* Operand-size override */
384 case 0xf0: /* LOCK */
385 case 0xf2: /* REPNE/REPNZ */
386 case 0xf3: /* REP/REPE/REPZ */
387 break;
388 case 0x65: /* GS override */
389 gs_override = 1;
390 break;
391 case 0x0f: /* Not really a prefix byte */
392 table = twobyte_decode;
393 opcode = b;
394 break;
395 case 0xd8: /* Math coprocessor instructions. */
396 case 0xd9:
397 case 0xda:
398 case 0xdb:
399 case 0xdc:
400 case 0xdd:
401 case 0xde:
402 case 0xdf:
403 /* Float opcodes have a secondary opcode in the modrm byte. */
404 table = float_decode;
405 if ( get_user(modrm, pb + 1) )
406 {
407 dprintk(XENLOG_DEBUG, "Fault while extracting modrm byte\n");
408 goto page_fault;
409 }
411 opcode = (b << 8) | modrm;
412 b = ((b & 7) << 3) + ((modrm >> 3) & 7);
413 goto done_prefix;
415 default: /* Not a prefix byte */
416 goto done_prefix;
417 }
418 }
419 done_prefix:
421 if ( !gs_override )
422 {
423 dprintk(XENLOG_DEBUG, "Only instructions with GS override\n");
424 goto fail;
425 }
427 decode = table[b];
428 pb++;
430 if ( !(decode & OPCODE_BYTE) )
431 {
432 if (opcode == -1)
433 dprintk(XENLOG_DEBUG, "Unsupported opcode %02x\n", b);
434 else
435 dprintk(XENLOG_DEBUG, "Unsupported opcode %02x %02x\n",
436 opcode >> 8, opcode & 255);
437 goto fail;
438 }
440 if ( !(decode & HAS_MODRM) )
441 {
442 /* Must be a <disp32>, or bail. */
443 if ( (decode & INSN_SUFFIX_BYTES) != 4 )
444 goto fail;
446 if ( get_user(offset, (u32 *)pb) )
447 {
448 dprintk(XENLOG_DEBUG, "Fault while extracting <moffs32>.\n");
449 goto page_fault;
450 }
451 pb += 4;
453 goto skip_modrm;
454 }
456 /*
457 * Mod/RM processing.
458 */
460 if ( get_user(modrm, pb) )
461 {
462 dprintk(XENLOG_DEBUG, "Fault while extracting modrm byte\n");
463 goto page_fault;
464 }
466 pb++;
468 mod = (modrm >> 6) & 3;
469 rm = (modrm >> 0) & 7;
471 if ( rm == 4 )
472 {
473 u8 sib;
475 if ( get_user(sib, pb) )
476 {
477 dprintk(XENLOG_DEBUG, "Fault while extracting sib byte\n");
478 goto page_fault;
479 }
481 pb++;
483 rm = sib & 7;
484 if ( (sib & 0x38) != 0x20 )
485 index = decode_register((sib >> 3) & 7, regs, 0);
486 scale = sib >> 6;
487 }
489 /* Decode R/M field. */
490 base = decode_register(rm, regs, 0);
492 /* Decode Mod field. */
493 switch ( mod )
494 {
495 case 0:
496 if ( rm == 5 ) /* disp32 rather than (EBP) */
497 {
498 base = NULL;
499 if ( get_user(disp32, (u32 *)pb) )
500 {
501 dprintk(XENLOG_DEBUG, "Fault while extracting <base32>.\n");
502 goto page_fault;
503 }
504 pb += 4;
505 }
506 break;
508 case 1:
509 if ( get_user(disp8, pb) )
510 {
511 dprintk(XENLOG_DEBUG, "Fault while extracting <disp8>.\n");
512 goto page_fault;
513 }
514 pb++;
515 disp32 = disp8;
516 break;
518 case 2:
519 if ( get_user(disp32, (u32 *)pb) )
520 {
521 dprintk(XENLOG_DEBUG, "Fault while extracting <disp32>.\n");
522 goto page_fault;
523 }
524 pb += 4;
525 break;
527 case 3:
528 dprintk(XENLOG_DEBUG, "Not a memory operand!\n");
529 goto fail;
530 }
532 offset = disp32;
533 if ( base != NULL )
534 offset += *base;
535 if ( index != NULL )
536 offset += *index << scale;
538 skip_modrm:
539 if ( !fixup_seg((u16)regs->gs, offset) )
540 goto fail;
542 /* Success! */
543 perfc_incr(seg_fixups);
545 /* If requested, give a callback on otherwise unused vector 15. */
546 if ( VM_ASSIST(curr->domain, VMASST_TYPE_4gb_segments_notify) )
547 {
548 struct trap_info *ti = &curr->arch.guest_context.trap_ctxt[15];
549 struct trap_bounce *tb = &curr->arch.trap_bounce;
551 tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE;
552 tb->error_code = pb - eip;
553 tb->cs = ti->cs;
554 tb->eip = ti->address;
555 if ( TI_GET_IF(ti) )
556 tb->flags |= TBF_INTERRUPT;
557 }
559 return EXCRET_fault_fixed;
561 fail:
562 return 0;
564 page_fault:
565 propagate_page_fault((unsigned long)pb, 0); /* read fault */
566 return EXCRET_fault_fixed;
567 }
569 /*
570 * Local variables:
571 * mode: C
572 * c-set-style: "BSD"
573 * c-basic-offset: 4
574 * tab-width: 4
575 * indent-tabs-mode: nil
576 * End:
577 */