ia64/xen-unstable

changeset 17403:324f772239a7

x86_64: Be more careful in emulating 32-bit call gates.

An assertion could legitimately fire.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Apr 08 09:46:57 2008 +0100 (2008-04-08)
parents 146f214a0e63
children af1d20b86b02
files xen/arch/x86/traps.c
line diff
     1.1 --- a/xen/arch/x86/traps.c	Mon Apr 07 15:02:47 2008 +0100
     1.2 +++ b/xen/arch/x86/traps.c	Tue Apr 08 09:46:57 2008 +0100
     1.3 @@ -1305,23 +1305,24 @@ static int read_gate_descriptor(unsigned
     1.4      const struct desc_struct *pdesc;
     1.5  
     1.6  
     1.7 -    pdesc = (const struct desc_struct *)(!(gate_sel & 4) ?
     1.8 -                                         GDT_VIRT_START(v) :
     1.9 -                                         LDT_VIRT_START(v))
    1.10 -            + (gate_sel >> 3);
    1.11 -    if ( gate_sel < 4 ||
    1.12 -         (gate_sel >= FIRST_RESERVED_GDT_BYTE && !(gate_sel & 4)) ||
    1.13 +    pdesc = (const struct desc_struct *)
    1.14 +        (!(gate_sel & 4) ? GDT_VIRT_START(v) : LDT_VIRT_START(v))
    1.15 +        + (gate_sel >> 3);
    1.16 +    if ( (gate_sel < 4) ||
    1.17 +         ((gate_sel >= FIRST_RESERVED_GDT_BYTE) && !(gate_sel & 4)) ||
    1.18           __get_user(desc, pdesc) )
    1.19          return 0;
    1.20  
    1.21      *sel = (desc.a >> 16) & 0x0000fffc;
    1.22      *off = (desc.a & 0x0000ffff) | (desc.b & 0xffff0000);
    1.23      *ar = desc.b & 0x0000ffff;
    1.24 +
    1.25      /*
    1.26       * check_descriptor() clears the DPL field and stores the
    1.27       * guest requested DPL in the selector's RPL field.
    1.28       */
    1.29 -    ASSERT(!(*ar & _SEGMENT_DPL));
    1.30 +    if ( *ar & _SEGMENT_DPL )
    1.31 +        return 0;
    1.32      *ar |= (desc.a >> (16 - 13)) & _SEGMENT_DPL;
    1.33  
    1.34      if ( !is_pv_32bit_vcpu(v) )
    1.35 @@ -2137,8 +2138,8 @@ static void emulate_gate_op(struct cpu_u
    1.36  
    1.37      /* Check whether this fault is due to the use of a call gate. */
    1.38      if ( !read_gate_descriptor(regs->error_code, v, &sel, &off, &ar) ||
    1.39 -         ((ar >> 13) & 3) < (regs->cs & 3) ||
    1.40 -         (ar & _SEGMENT_TYPE) != 0xc00 )
    1.41 +         (((ar >> 13) & 3) < (regs->cs & 3)) ||
    1.42 +         ((ar & _SEGMENT_TYPE) != 0xc00) )
    1.43      {
    1.44          do_guest_trap(TRAP_gp_fault, regs, 1);
    1.45          return;
    1.46 @@ -2232,15 +2233,18 @@ static void emulate_gate_op(struct cpu_u
    1.47                      {
    1.48                          if ( (modrm & 7) == 4 )
    1.49                          {
    1.50 -                            unsigned int sib = insn_fetch(u8, base, eip, limit);
    1.51 +                            unsigned int sib;
    1.52 +                            sib = insn_fetch(u8, base, eip, limit);
    1.53  
    1.54                              modrm = (modrm & ~7) | (sib & 7);
    1.55                              if ( (sib >>= 3) != 4 )
    1.56 -                                opnd_off = *(unsigned long *)decode_register(sib & 7, regs, 0);
    1.57 +                                opnd_off = *(unsigned long *)
    1.58 +                                    decode_register(sib & 7, regs, 0);
    1.59                              opnd_off <<= sib >> 3;
    1.60                          }
    1.61                          if ( (modrm & 7) != 5 || (modrm & 0xc0) )
    1.62 -                            opnd_off += *(unsigned long *)decode_register(modrm & 7, regs, 0);
    1.63 +                            opnd_off += *(unsigned long *)
    1.64 +                                decode_register(modrm & 7, regs, 0);
    1.65                          else
    1.66                              modrm |= 0x87;
    1.67                          if ( !opnd_sel )