direct-io.hg

changeset 15464:f1b62eb7f8be

[x86/32] Support two byte CMOVcc opcodes in 4G segment fixup.

These are present in Debian Etch's libc6-i686 package.

Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
author Ian Campbell <ian.campbell@xensource.com>
date Tue Jul 03 17:04:50 2007 +0100 (2007-07-03)
parents 56da8753ba8d
children 9fa9346e1c70
files xen/arch/x86/x86_32/seg_fixup.c
line diff
     1.1 --- a/xen/arch/x86/x86_32/seg_fixup.c	Tue Jul 03 16:02:31 2007 +0100
     1.2 +++ b/xen/arch/x86/x86_32/seg_fixup.c	Tue Jul 03 17:04:50 2007 +0100
     1.3 @@ -93,6 +93,57 @@ static unsigned char insn_decode[256] = 
     1.4      X, X, X, X, X, X, O|M, O|M
     1.5  };
     1.6  
     1.7 +static unsigned char twobyte_decode[256] = {
     1.8 +    /* 0x00 - 0x0F */
     1.9 +    X, X, X, X, X, X, X, X,
    1.10 +    X, X, X, X, X, X, X, X,
    1.11 +    /* 0x10 - 0x1F */
    1.12 +    X, X, X, X, X, X, X, X,
    1.13 +    X, X, X, X, X, X, X, X,
    1.14 +    /* 0x20 - 0x2F */
    1.15 +    X, X, X, X, X, X, X, X,
    1.16 +    X, X, X, X, X, X, X, X,
    1.17 +    /* 0x30 - 0x3F */
    1.18 +    X, X, X, X, X, X, X, X,
    1.19 +    X, X, X, X, X, X, X, X,
    1.20 +    /* 0x40 - 0x4F */
    1.21 +    O|M, O|M, O|M, O|M, O|M, O|M, O|M, O|M,
    1.22 +    O|M, O|M, O|M, O|M, O|M, O|M, O|M, O|M,
    1.23 +    /* 0x50 - 0x5F */
    1.24 +    X, X, X, X, X, X, X, X,
    1.25 +    X, X, X, X, X, X, X, X,
    1.26 +    /* 0x60 - 0x6F */
    1.27 +    X, X, X, X, X, X, X, X,
    1.28 +    X, X, X, X, X, X, X, X,
    1.29 +    /* 0x70 - 0x7F */
    1.30 +    X, X, X, X, X, X, X, X,
    1.31 +    X, X, X, X, X, X, X, X,
    1.32 +    /* 0x80 - 0x8F */
    1.33 +    X, X, X, X, X, X, X, X,
    1.34 +    X, X, X, X, X, X, X, X,
    1.35 +    /* 0x90 - 0x9F */
    1.36 +    X, X, X, X, X, X, X, X,
    1.37 +    X, X, X, X, X, X, X, X,
    1.38 +    /* 0xA0 - 0xAF */
    1.39 +    X, X, X, X, X, X, X, X,
    1.40 +    X, X, X, X, X, X, X, X,
    1.41 +    /* 0xB0 - 0xBF */
    1.42 +    X, X, X, X, X, X, X, X,
    1.43 +    X, X, X, X, X, X, X, X,
    1.44 +    /* 0xC0 - 0xCF */
    1.45 +    X, X, X, X, X, X, X, X,
    1.46 +    X, X, X, X, X, X, X, X,
    1.47 +    /* 0xD0 - 0xDF */
    1.48 +    X, X, X, X, X, X, X, X,
    1.49 +    X, X, X, X, X, X, X, X,
    1.50 +    /* 0xE0 - 0xEF */
    1.51 +    X, X, X, X, X, X, X, X,
    1.52 +    X, X, X, X, X, X, X, X,
    1.53 +    /* 0xF0 - 0xFF */
    1.54 +    X, X, X, X, X, X, X, X,
    1.55 +    X, X, X, X, X, X, X, X
    1.56 +};
    1.57 +
    1.58  /*
    1.59   * Obtain the base and limit associated with the given segment selector.
    1.60   * The selector must identify a 32-bit code or data segment. Any segment that
    1.61 @@ -275,6 +326,7 @@ int gpf_emulate_4gb(struct cpu_user_regs
    1.62      u8            *eip;         /* ptr to instruction start */
    1.63      u8            *pb, b;       /* ptr into instr. / current instr. byte */
    1.64      int            gs_override = 0;
    1.65 +    int            twobyte = 0;
    1.66  
    1.67      /* WARNING: We only work for ring-3 segments. */
    1.68      if ( unlikely(vm86_mode(regs)) || unlikely(!ring_3(regs)) )
    1.69 @@ -337,12 +389,36 @@ int gpf_emulate_4gb(struct cpu_user_regs
    1.70  
    1.71      decode = insn_decode[b]; /* opcode byte */
    1.72      pb++;
    1.73 +    if ( decode == 0 && b == 0x0f )
    1.74 +    {
    1.75 +        twobyte = 1;
    1.76 +
    1.77 +        if ( get_user(b, pb) )
    1.78 +        {
    1.79 +            dprintk(XENLOG_DEBUG,
    1.80 +                    "Fault while accessing byte %ld of instruction\n",
    1.81 +                    (long)(pb-eip));
    1.82 +            goto page_fault;
    1.83 +        }
    1.84 +
    1.85 +        if ( (pb - eip) >= 15 )
    1.86 +        {
    1.87 +            dprintk(XENLOG_DEBUG, "Too many opcode bytes for a "
    1.88 +                    "legal instruction\n");
    1.89 +            goto fail;
    1.90 +        }
    1.91 +
    1.92 +        decode = twobyte_decode[b];
    1.93 +        pb++;
    1.94 +    }
    1.95 +
    1.96      if ( decode == 0 )
    1.97      {
    1.98 -        dprintk(XENLOG_DEBUG, "Unsupported opcode %02x\n", b);
    1.99 +        dprintk(XENLOG_DEBUG, "Unsupported %sopcode %02x\n",
   1.100 +                twobyte ? "two byte " : "", b);
   1.101          goto fail;
   1.102      }
   1.103 -    
   1.104 +
   1.105      if ( !(decode & HAS_MODRM) )
   1.106      {
   1.107          /* Must be a <disp32>, or bail. */