ia64/xen-unstable

changeset 19614:e421fd04e150

x86_emulate: Emulate LLDT and LTR instructions.

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;