debuggers.hg
changeset 19652:e421fd04e150
x86_emulate: Emulate LLDT and LTR instructions.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Tue May 19 02:09:36 2009 +0100 (2009-05-19) |
parents | 4e7c5eb71774 |
children | 13a4f4e6d0a3 |
files | xen/arch/x86/x86_emulate/x86_emulate.c |
line diff
1.1 --- a/xen/arch/x86/x86_emulate/x86_emulate.c Tue May 19 02:08:01 2009 +0100 1.2 +++ b/xen/arch/x86/x86_emulate/x86_emulate.c Tue May 19 02:09:36 2009 +0100 1.3 @@ -172,7 +172,7 @@ static uint8_t opcode_table[256] = { 1.4 1.5 static uint8_t twobyte_table[256] = { 1.6 /* 0x00 - 0x07 */ 1.7 - 0, ImplicitOps|ModRM, 0, 0, 0, 0, ImplicitOps, 0, 1.8 + SrcMem16|ModRM, ImplicitOps|ModRM, 0, 0, 0, 0, ImplicitOps, 0, 1.9 /* 0x08 - 0x0F */ 1.10 ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps|ModRM, 0, 0, 1.11 /* 0x10 - 0x17 */ 1.12 @@ -971,8 +971,8 @@ protmode_load_seg( 1.13 struct { uint32_t a, b; } desc; 1.14 unsigned long val; 1.15 uint8_t dpl, rpl, cpl; 1.16 - uint32_t new_desc_b; 1.17 - int rc, fault_type = EXC_TS; 1.18 + uint32_t new_desc_b, a_flag = 0x100; 1.19 + int rc, fault_type = EXC_GP; 1.20 1.21 /* NULL selector? */ 1.22 if ( (sel & 0xfffc) == 0 ) 1.23 @@ -983,8 +983,8 @@ protmode_load_seg( 1.24 return ops->write_segment(seg, &segr, ctxt); 1.25 } 1.26 1.27 - /* LDT descriptor must be in the GDT. */ 1.28 - if ( (seg == x86_seg_ldtr) && (sel & 4) ) 1.29 + /* System segment descriptors must reside in the GDT. */ 1.30 + if ( !is_x86_user_segment(seg) && (sel & 4) ) 1.31 goto raise_exn; 1.32 1.33 if ( (rc = ops->read_segment(x86_seg_ss, &ss, ctxt)) || 1.34 @@ -1013,8 +1013,8 @@ protmode_load_seg( 1.35 goto raise_exn; 1.36 } 1.37 1.38 - /* LDT descriptor is a system segment. All others are code/data. */ 1.39 - if ( (desc.b & (1u<<12)) == ((seg == x86_seg_ldtr) << 12) ) 1.40 + /* System segments must have the system flag (S) set. */ 1.41 + if ( (desc.b & (1u<<12)) == (!is_x86_user_segment(seg) << 12) ) 1.42 goto raise_exn; 1.43 1.44 dpl = (desc.b >> 13) & 3; 1.45 @@ -1043,6 +1043,12 @@ protmode_load_seg( 1.46 if ( (desc.b & (15u<<8)) != (2u<<8) ) 1.47 goto raise_exn; 1.48 goto skip_accessed_flag; 1.49 + case x86_seg_tr: 1.50 + /* Available TSS system segment? */ 1.51 + if ( (desc.b & (15u<<8)) != (9u<<8) ) 1.52 + goto raise_exn; 1.53 + a_flag = 0x200; /* busy flag */ 1.54 + break; 1.55 default: 1.56 /* Readable code or data segment? */ 1.57 if ( (desc.b & (5u<<9)) == (4u<<9) ) 1.58 @@ -1055,8 +1061,8 @@ protmode_load_seg( 1.59 } 1.60 1.61 /* Ensure Accessed flag is set. */ 1.62 - new_desc_b = desc.b | 0x100; 1.63 - rc = ((desc.b & 0x100) ? X86EMUL_OKAY : 1.64 + new_desc_b = desc.b | a_flag; 1.65 + rc = ((desc.b & a_flag) ? X86EMUL_OKAY : 1.66 ops->cmpxchg( 1.67 x86_seg_none, desctab.base + (sel & 0xfff8) + 4, 1.68 &desc.b, &new_desc_b, 4, ctxt)); 1.69 @@ -1066,7 +1072,7 @@ protmode_load_seg( 1.70 return rc; 1.71 1.72 /* Force the Accessed flag in our local copy. */ 1.73 - desc.b |= 0x100; 1.74 + desc.b |= a_flag; 1.75 1.76 skip_accessed_flag: 1.77 segr.base = (((desc.b << 0) & 0xff000000u) | 1.78 @@ -3440,6 +3446,15 @@ x86_emulate( 1.79 twobyte_insn: 1.80 switch ( b ) 1.81 { 1.82 + case 0x00: /* Grp6 */ 1.83 + fail_if((modrm_reg & 6) != 2); 1.84 + generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, -1); 1.85 + generate_exception_if(!mode_ring0(), EXC_GP, 0); 1.86 + if ( (rc = load_seg((modrm_reg & 1) ? x86_seg_tr : x86_seg_ldtr, 1.87 + src.val, ctxt, ops)) != 0 ) 1.88 + goto done; 1.89 + break; 1.90 + 1.91 case 0x01: /* Grp7 */ { 1.92 struct segment_register reg; 1.93 unsigned long base, limit, cr0, cr0w;