ia64/xen-unstable

changeset 3117:ce28d4a8e51d

bitkeeper revision 1.1159.192.1 (41a5b616PKr3oSl-gLQrEOCfYSXbTw)

Don't flip a segment unless it will actually help fix the problem.
Also made the insn decoder slightly more real.
Bug fix in detecting expand-down segments.
author mafetter@fleming.research
date Thu Nov 25 10:38:14 2004 +0000 (2004-11-25)
parents 85d6a1145160
children 733fc4c2fdcd
files xen/arch/x86/x86_32/mm.c xen/arch/x86/x86_32/seg_fixup.c xen/include/asm-x86/desc.h
line diff
     1.1 --- a/xen/arch/x86/x86_32/mm.c	Wed Nov 24 19:29:50 2004 +0000
     1.2 +++ b/xen/arch/x86/x86_32/mm.c	Thu Nov 25 10:38:14 2004 +0000
     1.3 @@ -191,7 +191,7 @@ int check_descriptor(unsigned long *d)
     1.4      if ( (b & _SEGMENT_G) )
     1.5          limit <<= 12;
     1.6  
     1.7 -    if ( (b & (3<<10)) == 1 )
     1.8 +    if ( (b & (_SEGMENT_CODE | _SEGMENT_EC)) == _SEGMENT_EC )
     1.9      {
    1.10          /*
    1.11           * Grows-down limit check. 
     2.1 --- a/xen/arch/x86/x86_32/seg_fixup.c	Wed Nov 24 19:29:50 2004 +0000
     2.2 +++ b/xen/arch/x86/x86_32/seg_fixup.c	Thu Nov 25 10:38:14 2004 +0000
     2.3 @@ -169,7 +169,7 @@ int linearise_address(u16 seg, unsigned 
     2.4      return 1;
     2.5  }
     2.6  
     2.7 -int fixup_seg(u16 seg, int positive_access)
     2.8 +int fixup_seg(u16 seg, unsigned long offset)
     2.9  {
    2.10      struct domain *d = current;
    2.11      unsigned long *table, a, b, base, limit;
    2.12 @@ -208,7 +208,7 @@ int fixup_seg(u16 seg, int positive_acce
    2.13  
    2.14      /* We only parse 32-bit page-granularity non-privileged data segments. */
    2.15      if ( (b & (_SEGMENT_P|_SEGMENT_S|_SEGMENT_DB|
    2.16 -               _SEGMENT_G|(1<<11)|_SEGMENT_DPL)) != 
    2.17 +               _SEGMENT_G|_SEGMENT_CODE|_SEGMENT_DPL)) != 
    2.18           (_SEGMENT_P|_SEGMENT_S|_SEGMENT_DB|_SEGMENT_G|_SEGMENT_DPL) )
    2.19      {
    2.20          DPRINTK("Bad segment %08lx:%08lx\n", a, b);
    2.21 @@ -219,10 +219,10 @@ int fixup_seg(u16 seg, int positive_acce
    2.22      base  = (b&(0xff<<24)) | ((b&0xff)<<16) | (a>>16);
    2.23      limit = (((b & 0xf0000) | (a & 0x0ffff)) + 1) << 12;
    2.24  
    2.25 -    if ( b & (1 << 10) )
    2.26 +    if ( b & _SEGMENT_EC )
    2.27      {
    2.28          /* Expands-down: All the way to zero? Assume 4GB if so. */
    2.29 -        if ( ((base + limit) < PAGE_SIZE) && positive_access )
    2.30 +        if ( ((base + limit) < PAGE_SIZE) && (offset <= limit)  )
    2.31          {
    2.32              /* Flip to expands-up. */
    2.33              limit = PAGE_OFFSET - base;
    2.34 @@ -231,8 +231,16 @@ int fixup_seg(u16 seg, int positive_acce
    2.35      }
    2.36      else
    2.37      {
    2.38 -        /* Expands-up: All the way to Xen space? Assume 4GB if so. */
    2.39 -        if ( ((PAGE_OFFSET - (base + limit)) < PAGE_SIZE) && !positive_access )
    2.40 +        /*
    2.41 +         * Expands-up: All the way to Xen space? Assume 4GB if so.
    2.42 +         * NB: we compare offset with limit-15, instead of the "real"
    2.43 +         * comparison of offset+15 (worst case) with limit,
    2.44 +         * to avoid possible unsigned int overflow of offset+15.
    2.45 +         * limit-15 will not underflow here because we don't allow expand-up
    2.46 +         * segments with maxlimit.
    2.47 +         */
    2.48 +        if ( ((PAGE_OFFSET - (base + limit)) < PAGE_SIZE) &&
    2.49 +             ((offset) > (limit-15)) )
    2.50          {
    2.51              /* Flip to expands-down. */
    2.52              limit = -(base & PAGE_MASK);
    2.53 @@ -250,7 +258,7 @@ int fixup_seg(u16 seg, int positive_acce
    2.54      limit = (limit >> 12) - 1;
    2.55      a &= ~0x0ffff; a |= limit & 0x0ffff;
    2.56      b &= ~0xf0000; b |= limit & 0xf0000;
    2.57 -    b ^= 1 << 10; /* grows-up <-> grows-down */
    2.58 +    b ^= _SEGMENT_EC; /* grows-up <-> grows-down */
    2.59      /* NB. These can't fault. Checked readable above; must also be writable. */
    2.60      table[2*idx+0] = a;
    2.61      table[2*idx+1] = b;
    2.62 @@ -317,37 +325,40 @@ int gpf_emulate_4gb(struct xen_regs *reg
    2.63              goto fail;
    2.64          }
    2.65  
    2.66 -        if ( (pb - eip) == 4 )
    2.67 -            break;
    2.68 -        
    2.69 +        if ( (pb - eip) >= 15 )
    2.70 +        {
    2.71 +            DPRINTK("Too many instruction prefixes for a legal instruction\n");
    2.72 +            goto fail;
    2.73 +        }
    2.74 +
    2.75          switch ( b )
    2.76          {
    2.77 -        case 0xf0: /* LOCK */
    2.78 -        case 0xf2: /* REPNE/REPNZ */
    2.79 -        case 0xf3: /* REP/REPE/REPZ */
    2.80          case 0x67: /* Address-size override */
    2.81              DPRINTK("Unhandleable prefix byte %02x\n", b);
    2.82              goto fixme;
    2.83          case 0x66: /* Operand-size override */
    2.84 -            break;
    2.85 +        case 0xf0: /* LOCK */
    2.86 +        case 0xf2: /* REPNE/REPNZ */
    2.87 +        case 0xf3: /* REP/REPE/REPZ */
    2.88 +            continue;
    2.89          case 0x2e: /* CS override */
    2.90              pseg = &regs->cs;
    2.91 -            break;
    2.92 +            continue;
    2.93          case 0x3e: /* DS override */
    2.94              pseg = &regs->ds;
    2.95 -            break;
    2.96 +            continue;
    2.97          case 0x26: /* ES override */
    2.98              pseg = &regs->es;
    2.99 -            break;
   2.100 +            continue;
   2.101          case 0x64: /* FS override */
   2.102              pseg = &regs->fs;
   2.103 -            break;
   2.104 +            continue;
   2.105          case 0x65: /* GS override */
   2.106              pseg = &regs->gs;
   2.107 -            break;
   2.108 +            continue;
   2.109          case 0x36: /* SS override */
   2.110              pseg = &regs->ss;
   2.111 -            break;
   2.112 +            continue;
   2.113          default: /* Not a prefix byte */
   2.114              goto done_prefix;
   2.115          }
   2.116 @@ -455,7 +466,7 @@ int gpf_emulate_4gb(struct xen_regs *reg
   2.117          offset += *(u32 *)memreg;
   2.118  
   2.119   skip_modrm:
   2.120 -    if ( !fixup_seg((u16)(*pseg), (signed long)offset >= 0) )
   2.121 +    if ( !fixup_seg((u16)(*pseg), offset) )
   2.122          goto fail;
   2.123  
   2.124      /* Success! */
     3.1 --- a/xen/include/asm-x86/desc.h	Wed Nov 24 19:29:50 2004 +0000
     3.2 +++ b/xen/include/asm-x86/desc.h	Thu Nov 25 10:38:14 2004 +0000
     3.3 @@ -27,8 +27,11 @@
     3.4       (((_s)&3) == 1))
     3.5  #define VALID_CODESEL(_s) ((_s) == FLAT_RING1_CS || VALID_SEL(_s))
     3.6  
     3.7 -/* These are bitmasks for the first 32 bits of a descriptor table entry. */
     3.8 +/* These are bitmasks for the high 32 bits of a descriptor table entry. */
     3.9  #define _SEGMENT_TYPE    (15<< 8)
    3.10 +#define _SEGMENT_EC      ( 1<<10) /* Expand-down or Conforming segment */
    3.11 +#define _SEGMENT_CODE    ( 1<<11) /* Code (vs data) segment for non-system
    3.12 +                                     segments */
    3.13  #define _SEGMENT_S       ( 1<<12) /* System descriptor (yes iff S==0) */
    3.14  #define _SEGMENT_DPL     ( 3<<13) /* Descriptor Privilege Level */
    3.15  #define _SEGMENT_P       ( 1<<15) /* Segment Present */