ia64/xen-unstable

changeset 2666:d10a9677a639

bitkeeper revision 1.1159.1.244 (417679e8xXMjFVu9LO2SfkqXqR2RjA)

Replace pseudo-4GB-segment instruction emulation with a segment-type
trick plus instruction replay. Simpler and more robust but actually
somewhat slower (we fault more times, as we can fault on both +ve and
-ve accesses).
author kaf24@freefall.cl.cam.ac.uk
date Wed Oct 20 14:44:56 2004 +0000 (2004-10-20)
parents 49fa29c29184
children 77b6b9acf383 6b58e5458fcd
files .rootkeys xen/arch/x86/x86_32/emulate.c xen/arch/x86/x86_32/seg_fixup.c xen/include/xen/perfc_defn.h
line diff
     1.1 --- a/.rootkeys	Wed Oct 20 08:12:06 2004 +0000
     1.2 +++ b/.rootkeys	Wed Oct 20 14:44:56 2004 +0000
     1.3 @@ -610,9 +610,9 @@ 3ddb79bc-Udq7ol-NX4q9XsYnN7A2Q xen/arch/
     1.4  3ddb79bccYVzXZJyVaxuv5T42Z1Fsw xen/arch/x86/trampoline.S
     1.5  3ddb79bcOftONV9h4QCxXOfiT0h91w xen/arch/x86/traps.c
     1.6  3e32af9aRnYGl4GMOaDKp7JdfhOGhg xen/arch/x86/x86_32/domain_page.c
     1.7 -40f92331jfOlE7MfKwpdkEb1CEf23g xen/arch/x86/x86_32/emulate.c
     1.8  3ddb79bcecupHj56ZbTa3B0FxDowMg xen/arch/x86/x86_32/entry.S
     1.9  3ddb79bcHwuCQDjBICDTSis52hWguw xen/arch/x86/x86_32/mm.c
    1.10 +40f92331jfOlE7MfKwpdkEb1CEf23g xen/arch/x86/x86_32/seg_fixup.c
    1.11  3ddb79bc4nTpGQOe6_-MbyZzkhlhFQ xen/arch/x86/x86_32/usercopy.c
    1.12  3ddb79bcOMCu9-5mKpjIh5d0qqBDPg xen/arch/x86/x86_32/xen.lds
    1.13  40e96d3aLDI-nViMuYneD7VKYlZrVg xen/arch/x86/x86_64/entry.S
     2.1 --- a/xen/arch/x86/x86_32/emulate.c	Wed Oct 20 08:12:06 2004 +0000
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,550 +0,0 @@
     2.4 -/******************************************************************************
     2.5 - * arch/x86/x86_32/emulate.c
     2.6 - * 
     2.7 - * Emulation of certain classes of IA32 instruction. Used to emulate 4GB
     2.8 - * segments, for example.
     2.9 - * 
    2.10 - * Copyright (c) 2004, K A Fraser
    2.11 - * 
    2.12 - * This program is free software; you can redistribute it and/or modify
    2.13 - * it under the terms of the GNU General Public License as published by
    2.14 - * the Free Software Foundation; either version 2 of the License, or
    2.15 - * (at your option) any later version.
    2.16 - * 
    2.17 - * This program is distributed in the hope that it will be useful,
    2.18 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.19 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.20 - * GNU General Public License for more details.
    2.21 - * 
    2.22 - * You should have received a copy of the GNU General Public License
    2.23 - * along with this program; if not, write to the Free Software
    2.24 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    2.25 - */
    2.26 -
    2.27 -#include <xen/config.h>
    2.28 -#include <xen/init.h>
    2.29 -#include <xen/sched.h>
    2.30 -#include <xen/lib.h>
    2.31 -#include <xen/errno.h>
    2.32 -#include <xen/mm.h>
    2.33 -#include <xen/perfc.h>
    2.34 -#include <asm/processor.h>
    2.35 -
    2.36 -/* Make the scary benign errors go away. */
    2.37 -#undef  DPRINTK
    2.38 -#define DPRINTK(_f, _a...) ((void)0)
    2.39 -
    2.40 -/*
    2.41 - * Obtain the base and limit associated with the given segment selector.
    2.42 - * The selector must identify a 32-bit code or data segment. Any segment that
    2.43 - * appears to be truncated to not overlap with Xen is assumed to be a truncated
    2.44 - * 4GB segment, and the returned limit reflects this.
    2.45 - *  @seg   (IN) : Segment selector to decode.
    2.46 - *  @base  (OUT): Decoded linear base address.
    2.47 - *  @limit (OUT): Decoded segment limit, in bytes. 0 == unlimited (4GB).
    2.48 - */
    2.49 -int get_baselimit(u16 seg, unsigned long *base, unsigned long *limit)
    2.50 -{
    2.51 -    struct domain *d = current;
    2.52 -    unsigned long *table, a, b;
    2.53 -    int            ldt = !!(seg & 4);
    2.54 -    int            idx = (seg >> 3) & 8191;
    2.55 -
    2.56 -    /* Get base and check limit. */
    2.57 -    if ( ldt )
    2.58 -    {
    2.59 -        table = (unsigned long *)LDT_VIRT_START;
    2.60 -        if ( idx >= d->mm.ldt_ents )
    2.61 -            goto fail;
    2.62 -    }
    2.63 -    else /* gdt */
    2.64 -    {
    2.65 -        table = (unsigned long *)GET_GDT_ADDRESS(d);
    2.66 -        if ( idx >= GET_GDT_ENTRIES(d) )
    2.67 -            goto fail;
    2.68 -    }
    2.69 -
    2.70 -    /* Grab the segment descriptor. */
    2.71 -    if ( __get_user(a, &table[2*idx+0]) ||
    2.72 -         __get_user(b, &table[2*idx+1]) )
    2.73 -        goto fail; /* Barking up the wrong tree. Decode needs a page fault.*/
    2.74 -
    2.75 -    /* We only parse 32-bit code and data segments. */
    2.76 -    if ( (b & (_SEGMENT_P|_SEGMENT_S|_SEGMENT_DB)) != 
    2.77 -         (_SEGMENT_P|_SEGMENT_S|_SEGMENT_DB) )
    2.78 -        goto fail;
    2.79 -
    2.80 -    /* Decode base and limit. */
    2.81 -    *base  = (b&(0xff<<24)) | ((b&0xff)<<16) | (a>>16);
    2.82 -    *limit = ((b & 0xf0000) | (a & 0x0ffff)) + 1;
    2.83 -    if ( (b & _SEGMENT_G) )
    2.84 -        *limit <<= 12;
    2.85 -
    2.86 -    /*
    2.87 -     * Anything that looks like a truncated segment we assume ought really
    2.88 -     * to be a 4GB segment. DANGER!
    2.89 -     */
    2.90 -    if ( (PAGE_OFFSET - (*base + *limit)) < PAGE_SIZE )
    2.91 -        *limit = 0;
    2.92 -
    2.93 -    return 1;
    2.94 -
    2.95 - fail:
    2.96 -    return 0;
    2.97 -}
    2.98 -
    2.99 -/* Turn a segment+offset into a linear address. */
   2.100 -int linearise_address(u16 seg, unsigned long off, unsigned long *linear)
   2.101 -{
   2.102 -    unsigned long base, limit;
   2.103 -
   2.104 -    if ( !get_baselimit(seg, &base, &limit) )
   2.105 -        return 0;
   2.106 -
   2.107 -    if ( off > (limit-1) )
   2.108 -        return 0;
   2.109 -
   2.110 -    *linear = base + off;
   2.111 -
   2.112 -    return 1;
   2.113 -}
   2.114 -
   2.115 -/* Decode Reg field of a ModRM byte: return a pointer into a register block. */
   2.116 -void *decode_reg(struct pt_regs *regs, u8 b)
   2.117 -{
   2.118 -    switch ( b & 7 )
   2.119 -    {
   2.120 -    case 0: return &regs->eax;
   2.121 -    case 1: return &regs->ecx;
   2.122 -    case 2: return &regs->edx;
   2.123 -    case 3: return &regs->ebx;
   2.124 -    case 4: return &regs->esp;
   2.125 -    case 5: return &regs->ebp;
   2.126 -    case 6: return &regs->esi;
   2.127 -    case 7: return &regs->edi;
   2.128 -    }
   2.129 -
   2.130 -    return NULL;
   2.131 -}
   2.132 -
   2.133 -/*
   2.134 - * Decode an effective address:
   2.135 - *  @ppb (IN/OUT): IN == address of ModR/M byte; OUT == byte following EA.
   2.136 - *  @preg (OUT)  : address in pt_regs block of the EA register parameter.
   2.137 - *  @pmem (OUT)  : address of the EA memory parameter.
   2.138 - *  @pseg (IN)   : address in pt_regs block of the override segment.
   2.139 - *  @regs (IN)   : addrress of the the pt_regs block.
   2.140 - */
   2.141 -#define DECODE_EA_FAILED  0
   2.142 -#define DECODE_EA_FIXME   1
   2.143 -#define DECODE_EA_SUCCESS 2
   2.144 -int decode_effective_address(u8 **ppb, void **preg, void **pmem,
   2.145 -                             unsigned int *pseg, struct pt_regs *regs)
   2.146 -{
   2.147 -    u8            modrm, mod, reg, rm, *pb = *ppb;
   2.148 -    void         *memreg, *regreg;
   2.149 -    unsigned long ea, limit, offset;
   2.150 -    u8            disp8;
   2.151 -    u32           disp32 = 0;
   2.152 -
   2.153 -    if ( get_user(modrm, pb) )
   2.154 -    {
   2.155 -        DPRINTK("Fault while extracting modrm byte\n");
   2.156 -        return DECODE_EA_FAILED;
   2.157 -    }
   2.158 -
   2.159 -    pb++;
   2.160 -
   2.161 -    mod = (modrm >> 6) & 3;
   2.162 -    reg = (modrm >> 3) & 7;
   2.163 -    rm  = (modrm >> 0) & 7;
   2.164 -
   2.165 -    if ( rm == 4 )
   2.166 -    {
   2.167 -        DPRINTK("FIXME: Add decoding for the SIB byte.\n");
   2.168 -        return DECODE_EA_FIXME;
   2.169 -    }
   2.170 -
   2.171 -    /* Decode Reg and R/M fields. */
   2.172 -    regreg = decode_reg(regs, reg);
   2.173 -    memreg = decode_reg(regs, rm);
   2.174 -
   2.175 -    /* Decode Mod field. */
   2.176 -    switch ( modrm >> 6 )
   2.177 -    {
   2.178 -    case 0:
   2.179 -        if ( pseg == NULL )
   2.180 -            pseg = &regs->xds;
   2.181 -        disp32 = 0;
   2.182 -        if ( rm == 5 ) /* disp32 rather than (EBP) */
   2.183 -        {
   2.184 -            memreg = NULL;
   2.185 -            if ( get_user(disp32, (u32 *)pb) )
   2.186 -            {
   2.187 -                DPRINTK("Fault while extracting <disp8>.\n");
   2.188 -                return DECODE_EA_FAILED;
   2.189 -            }
   2.190 -            pb += 4;
   2.191 -        }
   2.192 -        break;
   2.193 -
   2.194 -    case 1:
   2.195 -        if ( pseg == NULL ) /* NB. EBP defaults to SS */
   2.196 -            pseg = (rm == 5) ? &regs->xss : &regs->xds;
   2.197 -        if ( get_user(disp8, pb) )
   2.198 -        {
   2.199 -            DPRINTK("Fault while extracting <disp8>.\n");
   2.200 -            return DECODE_EA_FAILED;
   2.201 -        }
   2.202 -        pb++;
   2.203 -        disp32 = (disp8 & 0x80) ? (disp8 | ~0xff) : disp8;;
   2.204 -        break;
   2.205 -
   2.206 -    case 2:
   2.207 -        if ( pseg == NULL ) /* NB. EBP defaults to SS */
   2.208 -            pseg = (rm == 5) ? &regs->xss : &regs->xds;
   2.209 -        if ( get_user(disp32, (u32 *)pb) )
   2.210 -        {
   2.211 -            DPRINTK("Fault while extracting <disp8>.\n");
   2.212 -            return DECODE_EA_FAILED;
   2.213 -        }
   2.214 -        pb += 4;
   2.215 -        break;
   2.216 -
   2.217 -    case 3:
   2.218 -        DPRINTK("Not a memory operand!\n");
   2.219 -        return DECODE_EA_FAILED;
   2.220 -    }
   2.221 -
   2.222 -    if ( !get_baselimit((u16)(*pseg), &ea, &limit) )
   2.223 -        return DECODE_EA_FAILED;
   2.224 -    if ( limit != 0 )
   2.225 -    {
   2.226 -        DPRINTK("Bailing: not a 4GB data segment.\n");
   2.227 -        return DECODE_EA_FAILED;
   2.228 -    }
   2.229 -
   2.230 -    offset = disp32;
   2.231 -    if ( memreg != NULL )
   2.232 -        offset += *(u32 *)memreg;
   2.233 -    if ( (offset & 0xf0000000) != 0xf0000000 )
   2.234 -    {
   2.235 -        DPRINTK("Bailing: not a -ve offset into 4GB segment.\n");
   2.236 -        return DECODE_EA_FAILED;
   2.237 -    }
   2.238 -
   2.239 -    ea += offset;
   2.240 -    if ( ea > (PAGE_OFFSET - PAGE_SIZE) )
   2.241 -    {
   2.242 -        DPRINTK("!!!! DISALLOWING UNSAFE ACCESS !!!!\n");
   2.243 -        return DECODE_EA_FAILED;
   2.244 -    }
   2.245 -
   2.246 -    *ppb  = pb;
   2.247 -    *preg = regreg;
   2.248 -    *pmem = (void *)ea;
   2.249 -
   2.250 -    return DECODE_EA_SUCCESS;
   2.251 -}
   2.252 -
   2.253 -#define GET_IMM8                                   \
   2.254 -    if ( get_user(ib, (u8 *)pb) ) {                \
   2.255 -        DPRINTK("Fault while extracting imm8\n");  \
   2.256 -        return 0;                                  \
   2.257 -    }                                              \
   2.258 -    pb += 1;
   2.259 -#define GET_IMM16                                  \
   2.260 -    if ( get_user(iw, (u8 *)pb) ) {                \
   2.261 -        DPRINTK("Fault while extracting imm16\n"); \
   2.262 -        return 0;                                  \
   2.263 -    }                                              \
   2.264 -    pb += 2;
   2.265 -#define GET_IMM32                                  \
   2.266 -    if ( get_user(il, (u32 *)pb) ) {               \
   2.267 -        DPRINTK("Fault while extracting imm32\n"); \
   2.268 -        return 0;                                  \
   2.269 -    }                                              \
   2.270 -    pb += 4;
   2.271 -
   2.272 -/*
   2.273 - * Called from the general-protection fault handler to attempt to decode
   2.274 - * and emulate an instruction that depends on 4GB segments. At this point
   2.275 - * we assume that the instruction itself is paged into memory (the CPU
   2.276 - * must have triggered this in order to decode the instruction itself).
   2.277 - */
   2.278 -int gpf_emulate_4gb(struct pt_regs *regs)
   2.279 -{
   2.280 -    struct domain *d = current;
   2.281 -    trap_info_t   *ti;
   2.282 -    struct guest_trap_bounce *gtb;
   2.283 -
   2.284 -    u8            *eip;         /* ptr to instruction start */
   2.285 -    u8            *pb, b;       /* ptr into instr. / current instr. byte */
   2.286 -    u8             ib, mb, rb;  /* byte operand from imm/register/memory */
   2.287 -    u16            iw, mw, rw;  /* word operand from imm/register/memory */
   2.288 -    u32            il, ml, rl;  /* long operand from imm/register/memory */
   2.289 -    void          *reg, *mem;   /* ptr to register/memory operand */
   2.290 -    unsigned int  *pseg = NULL; /* segment for memory operand (NULL=default) */
   2.291 -    u32            eflags;
   2.292 -    int            opsz_override = 0;
   2.293 -
   2.294 -    if ( !linearise_address((u16)regs->xcs, regs->eip, (unsigned long *)&eip) )
   2.295 -    {
   2.296 -        DPRINTK("Cannot linearise %04x:%08lx\n", regs->xcs, regs->eip);
   2.297 -        return 0;
   2.298 -    }
   2.299 -
   2.300 -    /* Parse prefix bytes. We're basically looking for segment override. */
   2.301 -    for ( pb = eip; (pb - eip) < 4; pb++ )
   2.302 -    {
   2.303 -        if ( get_user(b, pb) )
   2.304 -        {
   2.305 -            DPRINTK("Fault while accessing byte %d of instruction\n", pb-eip);
   2.306 -            return 0;
   2.307 -        }
   2.308 -        
   2.309 -        switch ( b )
   2.310 -        {
   2.311 -        case 0xf0: /* LOCK */
   2.312 -        case 0xf2: /* REPNE/REPNZ */
   2.313 -        case 0xf3: /* REP/REPE/REPZ */
   2.314 -        case 0x67: /* Address-size override */
   2.315 -            DPRINTK("Unhandleable prefix byte %02x\n", b);
   2.316 -            goto undecodeable;
   2.317 -        case 0x66: /* Operand-size override */
   2.318 -            opsz_override = 1;
   2.319 -            break;
   2.320 -        case 0x2e: /* CS override */
   2.321 -            pseg = &regs->xcs;
   2.322 -            break;
   2.323 -        case 0x3e: /* DS override */
   2.324 -            pseg = &regs->xds;
   2.325 -            break;
   2.326 -        case 0x26: /* ES override */
   2.327 -            pseg = &regs->xes;
   2.328 -            break;
   2.329 -        case 0x64: /* FS override */
   2.330 -            pseg = &regs->xfs;
   2.331 -            break;
   2.332 -        case 0x65: /* GS override */
   2.333 -            pseg = &regs->xgs;
   2.334 -            break;
   2.335 -        case 0x36: /* SS override */
   2.336 -            pseg = &regs->xss;
   2.337 -            break;
   2.338 -        default: /* Not a prefix byte */
   2.339 -            goto done_prefix;
   2.340 -        }
   2.341 -    }
   2.342 - done_prefix:
   2.343 -
   2.344 -    pb++; /* skip opcode byte */
   2.345 -    switch ( decode_effective_address(&pb, &reg, &mem, pseg, regs) )
   2.346 -    {
   2.347 -    case DECODE_EA_FAILED:
   2.348 -        return 0;
   2.349 -    case DECODE_EA_FIXME:
   2.350 -        goto undecodeable;
   2.351 -    }
   2.352 -
   2.353 -    /* Only handle single-byte opcodes right now. Sufficient for MOV. */
   2.354 -    switch ( b )
   2.355 -    {
   2.356 -    case 0x88: /* movb r,r/m */
   2.357 -        if ( __put_user(*(u8 *)reg, (u8 *)mem) )
   2.358 -            goto page_fault_w;
   2.359 -        break;
   2.360 -    case 0x89: /* movl r,r/m */
   2.361 -        if ( opsz_override ? __put_user(*(u16 *)reg, (u16 *)mem)
   2.362 -                           : __put_user(*(u32 *)reg, (u32 *)mem) )
   2.363 -            goto page_fault_w;
   2.364 -        break;
   2.365 -    case 0x8a: /* movb r/m,r */
   2.366 -        if ( __get_user(*(u8 *)reg, (u8 *)mem) )
   2.367 -            goto page_fault_r;
   2.368 -        break;
   2.369 -    case 0x8b: /* movl r/m,r */
   2.370 -        if ( opsz_override ? __get_user(*(u16 *)reg, (u16 *)mem)
   2.371 -                           : __get_user(*(u32 *)reg, (u32 *)mem) )
   2.372 -            goto page_fault_r;
   2.373 -        break;
   2.374 -    case 0xc6: /* movb imm,r/m */
   2.375 -        if ( reg != &regs->eax ) /* Reg == /0 */
   2.376 -            goto undecodeable;
   2.377 -        GET_IMM8;
   2.378 -        if ( __put_user(ib, (u8 *)mem) )
   2.379 -            goto page_fault_w;
   2.380 -        break;
   2.381 -    case 0xc7: /* movl imm,r/m */
   2.382 -        if ( reg != &regs->eax ) /* Reg == /0 */
   2.383 -            goto undecodeable;
   2.384 -        if ( opsz_override )
   2.385 -        {
   2.386 -            GET_IMM16;
   2.387 -            if ( __put_user(iw, (u16 *)mem) )
   2.388 -                goto page_fault_w;
   2.389 -        }
   2.390 -        else
   2.391 -        {
   2.392 -            GET_IMM32;
   2.393 -            if ( __put_user(il, (u32 *)mem) )
   2.394 -                goto page_fault_w;
   2.395 -        }
   2.396 -        break;
   2.397 -    case 0x80: /* cmpb imm8,r/m */
   2.398 -        if ( reg != &regs->edi ) /* Reg == /7 */
   2.399 -            goto undecodeable;
   2.400 -        GET_IMM8;
   2.401 -        if ( __get_user(mb, (u8 *)mem) )
   2.402 -            goto page_fault_r;
   2.403 -        __asm__ __volatile__ (
   2.404 -            "cmpb %b1,%b2 ; pushf ; popl %0"
   2.405 -            : "=a" (eflags)
   2.406 -            : "0" (ib), "b" (mb) );
   2.407 -        regs->eflags &= ~0x8d5;     /* OF,SF,ZF,AF,PF,CF */
   2.408 -        regs->eflags |= eflags & 0x8d5;
   2.409 -        break;
   2.410 -    case 0x81: /* cmpl imm32,r/m */
   2.411 -        if ( reg != &regs->edi ) /* Reg == /7 */
   2.412 -            goto undecodeable;
   2.413 -        if ( opsz_override )
   2.414 -        {
   2.415 -            GET_IMM16;
   2.416 -            if ( __get_user(mw, (u16 *)mem) )
   2.417 -                goto page_fault_r;
   2.418 -            __asm__ __volatile__ (
   2.419 -                "cmpw %w1,%w2 ; pushf ; popl %0"
   2.420 -                : "=a" (eflags)
   2.421 -                : "0" (iw), "b" (mw) );
   2.422 -        }
   2.423 -        else
   2.424 -        {
   2.425 -            GET_IMM32;
   2.426 -            if ( __get_user(ml, (u32 *)mem) )
   2.427 -                goto page_fault_r;
   2.428 -            __asm__ __volatile__ (
   2.429 -                "cmpl %1,%2 ; pushf ; popl %0"
   2.430 -                : "=a" (eflags)
   2.431 -                : "0" (il), "b" (ml) );
   2.432 -        }
   2.433 -        regs->eflags &= ~0x8d5;     /* OF,SF,ZF,AF,PF,CF */
   2.434 -        regs->eflags |= eflags & 0x8d5;
   2.435 -        break;
   2.436 -    case 0x83: /* cmpl imm8,r/m */
   2.437 -        if ( reg != &regs->edi ) /* Reg == /7 */
   2.438 -            goto undecodeable;
   2.439 -        GET_IMM8;
   2.440 -        if ( opsz_override )
   2.441 -        {
   2.442 -            iw = (u16)(s16)(s8)ib;
   2.443 -            if ( __get_user(mw, (u16 *)mem) )
   2.444 -                goto page_fault_r;
   2.445 -            __asm__ __volatile__ (
   2.446 -                "cmpw %w1,%w2 ; pushf ; popl %0"
   2.447 -                : "=a" (eflags)
   2.448 -                : "0" (iw), "b" (mw) );
   2.449 -        }
   2.450 -        else
   2.451 -        {
   2.452 -            il = (u32)(s32)(s8)ib;
   2.453 -            if ( __get_user(ml, (u32 *)mem) )
   2.454 -                goto page_fault_r;
   2.455 -            __asm__ __volatile__ (
   2.456 -                "cmpl %1,%2 ; pushf ; popl %0"
   2.457 -                : "=a" (eflags)
   2.458 -                : "0" (il), "b" (ml) );
   2.459 -        }
   2.460 -        regs->eflags &= ~0x8d5;     /* OF,SF,ZF,AF,PF,CF */
   2.461 -        regs->eflags |= eflags & 0x8d5;
   2.462 -        break;
   2.463 -    case 0x38: /* cmpb r,r/m */
   2.464 -    case 0x3a: /* cmpb r/m,r */
   2.465 -        rb = *(u8 *)reg;
   2.466 -        if ( __get_user(mb, (u8 *)mem) )
   2.467 -            goto page_fault_r;
   2.468 -        __asm__ __volatile__ (
   2.469 -            "cmpb %b1,%b2 ; pushf ; popl %0"
   2.470 -            : "=a" (eflags)
   2.471 -            : "0" ((b==0x38)?rb:mb), "b" ((b==0x38)?mb:rb) );
   2.472 -        regs->eflags &= ~0x8d5;     /* OF,SF,ZF,AF,PF,CF */
   2.473 -        regs->eflags |= eflags & 0x8d5;
   2.474 -        break;
   2.475 -    case 0x39: /* cmpl r,r/m */
   2.476 -    case 0x3b: /* cmpl r/m,r */
   2.477 -        if ( opsz_override )
   2.478 -        {
   2.479 -            rw = *(u16 *)reg;
   2.480 -            if ( __get_user(mw, (u16 *)mem) )
   2.481 -                goto page_fault_r;
   2.482 -            __asm__ __volatile__ (
   2.483 -                "cmpw %w1,%w2 ; pushf ; popl %0"
   2.484 -                : "=a" (eflags)
   2.485 -                : "0" ((b==0x38)?rw:mw), "b" ((b==0x38)?mw:rw) );
   2.486 -        }
   2.487 -        else
   2.488 -        {
   2.489 -            rl = *(u32 *)reg;
   2.490 -            if ( __get_user(ml, (u32 *)mem) )
   2.491 -                goto page_fault_r;
   2.492 -            __asm__ __volatile__ (
   2.493 -                "cmpl %1,%2 ; pushf ; popl %0"
   2.494 -                : "=a" (eflags)
   2.495 -                : "0" ((b==0x38)?rl:ml), "b" ((b==0x38)?ml:rl) );
   2.496 -        }
   2.497 -        regs->eflags &= ~0x8d5;     /* OF,SF,ZF,AF,PF,CF */
   2.498 -        regs->eflags |= eflags & 0x8d5;
   2.499 -        break;
   2.500 -    default:
   2.501 -        DPRINTK("Unhandleable opcode byte %02x\n", b);
   2.502 -        goto undecodeable;
   2.503 -    }
   2.504 -
   2.505 -    /* Success! */
   2.506 -    perfc_incrc(emulations);
   2.507 -    regs->eip += pb - eip;
   2.508 -
   2.509 -    /* If requested, give a callback on otherwise unused vector 15. */
   2.510 -    if ( VM_ASSIST(d, VMASST_TYPE_4gb_segments_notify) )
   2.511 -    {
   2.512 -        ti  = &d->thread.traps[15];
   2.513 -        gtb = &guest_trap_bounce[d->processor];
   2.514 -        gtb->flags      = GTBF_TRAP;
   2.515 -        gtb->error_code = pb - eip;
   2.516 -        gtb->cs         = ti->cs;
   2.517 -        gtb->eip        = ti->address;
   2.518 -        if ( TI_GET_IF(ti) )
   2.519 -            d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
   2.520 -    }
   2.521 -
   2.522 -    return 1;
   2.523 -
   2.524 - undecodeable:
   2.525 -    DPRINTK("Undecodable instruction %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
   2.526 -            "caused GPF(0) at %04x:%08lx\n",
   2.527 -            eip[0], eip[1], eip[2], eip[3],
   2.528 -            eip[4], eip[5], eip[6], eip[7],
   2.529 -            regs->xcs, regs->eip);
   2.530 -    return 0;
   2.531 -
   2.532 - page_fault_w:
   2.533 -    ti  = &d->thread.traps[14];
   2.534 -    gtb = &guest_trap_bounce[d->processor];
   2.535 -    /*
   2.536 -     * XXX We don't distinguish between page-not-present and read-only.
   2.537 -     * Linux doesn't care, but this might need fixing if others do.
   2.538 -     */
   2.539 -    gtb->error_code = 6; /* user fault, write access, page not present */
   2.540 -    goto page_fault_common;
   2.541 - page_fault_r:
   2.542 -    ti  = &d->thread.traps[14];
   2.543 -    gtb = &guest_trap_bounce[d->processor];
   2.544 -    gtb->error_code = 4; /* user fault, read access, page not present */
   2.545 - page_fault_common:
   2.546 -    gtb->flags      = GTBF_TRAP_CR2;
   2.547 -    gtb->cr2        = (unsigned long)mem;
   2.548 -    gtb->cs         = ti->cs;
   2.549 -    gtb->eip        = ti->address;
   2.550 -    if ( TI_GET_IF(ti) )
   2.551 -        d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
   2.552 -    return 1;
   2.553 -}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/xen/arch/x86/x86_32/seg_fixup.c	Wed Oct 20 14:44:56 2004 +0000
     3.3 @@ -0,0 +1,488 @@
     3.4 +/******************************************************************************
     3.5 + * arch/x86/x86_32/seg_fixup.c
     3.6 + * 
     3.7 + * Support for -ve accesses to pseudo-4GB segments.
     3.8 + * 
     3.9 + * Copyright (c) 2004, K A Fraser
    3.10 + * 
    3.11 + * This program is free software; you can redistribute it and/or modify
    3.12 + * it under the terms of the GNU General Public License as published by
    3.13 + * the Free Software Foundation; either version 2 of the License, or
    3.14 + * (at your option) any later version.
    3.15 + * 
    3.16 + * This program is distributed in the hope that it will be useful,
    3.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.19 + * GNU General Public License for more details.
    3.20 + * 
    3.21 + * You should have received a copy of the GNU General Public License
    3.22 + * along with this program; if not, write to the Free Software
    3.23 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    3.24 + */
    3.25 +
    3.26 +#include <xen/config.h>
    3.27 +#include <xen/init.h>
    3.28 +#include <xen/sched.h>
    3.29 +#include <xen/lib.h>
    3.30 +#include <xen/errno.h>
    3.31 +#include <xen/mm.h>
    3.32 +#include <xen/perfc.h>
    3.33 +#include <asm/processor.h>
    3.34 +
    3.35 +/* Make the scary benign errors go away. */
    3.36 +#undef  DPRINTK
    3.37 +#define DPRINTK(_f, _a...) ((void)0)
    3.38 +
    3.39 +/* General instruction properties. */
    3.40 +#define INSN_SUFFIX_BYTES (7)
    3.41 +#define OPCODE_BYTE       (1<<4)  
    3.42 +#define HAS_MODRM         (1<<5)
    3.43 +
    3.44 +/* Short forms for the table. */
    3.45 +#define X  0 /* invalid for some random reason */
    3.46 +#define O  OPCODE_BYTE
    3.47 +#define M  HAS_MODRM
    3.48 +
    3.49 +static unsigned char insn_decode[256] = {
    3.50 +    /* 0x00 - 0x0F */
    3.51 +    O|M, O|M, O|M, O|M, X, X, X, X,
    3.52 +    O|M, O|M, O|M, O|M, X, X, X, X,
    3.53 +    /* 0x10 - 0x1F */
    3.54 +    O|M, O|M, O|M, O|M, X, X, X, X,
    3.55 +    O|M, O|M, O|M, O|M, X, X, X, X,
    3.56 +    /* 0x20 - 0x2F */
    3.57 +    O|M, O|M, O|M, O|M, X, X, X, X,
    3.58 +    O|M, O|M, O|M, O|M, X, X, X, X,
    3.59 +    /* 0x30 - 0x3F */
    3.60 +    O|M, O|M, O|M, O|M, X, X, X, X,
    3.61 +    O|M, O|M, O|M, O|M, X, X, X, X,
    3.62 +    /* 0x40 - 0x4F */
    3.63 +    X, X, X, X, X, X, X, X,
    3.64 +    X, X, X, X, X, X, X, X,
    3.65 +    /* 0x50 - 0x5F */
    3.66 +    X, X, X, X, X, X, X, X,
    3.67 +    X, X, X, X, X, X, X, X,
    3.68 +    /* 0x60 - 0x6F */
    3.69 +    X, X, X, X, X, X, X, X,
    3.70 +    X, O|M|4, X, O|M|1, X, X, X, X,
    3.71 +    /* 0x70 - 0x7F */
    3.72 +    X, X, X, X, X, X, X, X,
    3.73 +    X, X, X, X, X, X, X, X,
    3.74 +    /* 0x80 - 0x8F */
    3.75 +    O|M|1, O|M|4, O|M|1, O|M|1, O|M, O|M, O|M, O|M,
    3.76 +    O|M, O|M, O|M, O|M, O|M, O|M, O|M, X,
    3.77 +    /* 0x90 - 0x9F */
    3.78 +    X, X, X, X, X, X, X, X,
    3.79 +    X, X, X, X, X, X, X, X,
    3.80 +    /* 0xA0 - 0xAF */
    3.81 +    O|1, O|4, O|1, O|4, X, X, X, X,
    3.82 +    X, X, X, X, X, X, X, X,
    3.83 +    /* 0xB0 - 0xBF */
    3.84 +    X, X, X, X, X, X, X, X,
    3.85 +    X, X, X, X, X, X, X, X,
    3.86 +    /* 0xC0 - 0xCF */
    3.87 +    O|M|1, O|M|1, X, X, X, X, O|M|1, O|M|4,
    3.88 +    X, X, X, X, X, X, X, X,
    3.89 +    /* 0xD0 - 0xDF */
    3.90 +    O|M, O|M, O|M, O|M, X, X, X, X,
    3.91 +    X, X, X, X, X, X, X, X,
    3.92 +    /* 0xE0 - 0xEF */
    3.93 +    X, X, X, X, X, X, X, X,
    3.94 +    X, X, X, X, X, X, X, X,
    3.95 +    /* 0xF0 - 0xFF */
    3.96 +    X, X, X, X, X, X, X, X,
    3.97 +    X, X, X, X, X, X, O|M, O|M
    3.98 +};
    3.99 +
   3.100 +/*
   3.101 + * Obtain the base and limit associated with the given segment selector.
   3.102 + * The selector must identify a 32-bit code or data segment. Any segment that
   3.103 + * appears to be truncated to not overlap with Xen is assumed to be a truncated
   3.104 + * 4GB segment, and the returned limit reflects this.
   3.105 + *  @seg   (IN) : Segment selector to decode.
   3.106 + *  @base  (OUT): Decoded linear base address.
   3.107 + *  @limit (OUT): Decoded segment limit, in bytes. 0 == unlimited (4GB).
   3.108 + */
   3.109 +int get_baselimit(u16 seg, unsigned long *base, unsigned long *limit)
   3.110 +{
   3.111 +    struct domain *d = current;
   3.112 +    unsigned long *table, a, b;
   3.113 +    int            ldt = !!(seg & 4);
   3.114 +    int            idx = (seg >> 3) & 8191;
   3.115 +
   3.116 +    /* Get base and check limit. */
   3.117 +    if ( ldt )
   3.118 +    {
   3.119 +        table = (unsigned long *)LDT_VIRT_START;
   3.120 +        if ( idx >= d->mm.ldt_ents )
   3.121 +            goto fail;
   3.122 +    }
   3.123 +    else /* gdt */
   3.124 +    {
   3.125 +        table = (unsigned long *)GET_GDT_ADDRESS(d);
   3.126 +        if ( idx >= GET_GDT_ENTRIES(d) )
   3.127 +            goto fail;
   3.128 +    }
   3.129 +
   3.130 +    /* Grab the segment descriptor. */
   3.131 +    if ( __get_user(a, &table[2*idx+0]) ||
   3.132 +         __get_user(b, &table[2*idx+1]) )
   3.133 +        goto fail; /* Barking up the wrong tree. Decode needs a page fault.*/
   3.134 +
   3.135 +    /* We only parse 32-bit code and data segments. */
   3.136 +    if ( (b & (_SEGMENT_P|_SEGMENT_S|_SEGMENT_DB)) != 
   3.137 +         (_SEGMENT_P|_SEGMENT_S|_SEGMENT_DB) )
   3.138 +        goto fail;
   3.139 +
   3.140 +    /* Decode base and limit. */
   3.141 +    *base  = (b&(0xff<<24)) | ((b&0xff)<<16) | (a>>16);
   3.142 +    *limit = ((b & 0xf0000) | (a & 0x0ffff)) + 1;
   3.143 +    if ( (b & _SEGMENT_G) )
   3.144 +        *limit <<= 12;
   3.145 +
   3.146 +    /*
   3.147 +     * Anything that looks like a truncated segment we assume ought really
   3.148 +     * to be a 4GB segment. DANGER!
   3.149 +     */
   3.150 +    if ( (PAGE_OFFSET - (*base + *limit)) < PAGE_SIZE )
   3.151 +        *limit = 0;
   3.152 +
   3.153 +    return 1;
   3.154 +
   3.155 + fail:
   3.156 +    return 0;
   3.157 +}
   3.158 +
   3.159 +/* Turn a segment+offset into a linear address. */
   3.160 +int linearise_address(u16 seg, unsigned long off, unsigned long *linear)
   3.161 +{
   3.162 +    unsigned long base, limit;
   3.163 +
   3.164 +    if ( !get_baselimit(seg, &base, &limit) )
   3.165 +        return 0;
   3.166 +
   3.167 +    if ( off > (limit-1) )
   3.168 +        return 0;
   3.169 +
   3.170 +    *linear = base + off;
   3.171 +
   3.172 +    return 1;
   3.173 +}
   3.174 +
   3.175 +int fixup_seg(u16 seg, int positive_access)
   3.176 +{
   3.177 +    struct domain *d = current;
   3.178 +    unsigned long *table, a, b, base, limit;
   3.179 +    int            ldt = !!(seg & 4);
   3.180 +    int            idx = (seg >> 3) & 8191;
   3.181 +
   3.182 +    /* Get base and check limit. */
   3.183 +    if ( ldt )
   3.184 +    {
   3.185 +        table = (unsigned long *)LDT_VIRT_START;
   3.186 +        if ( idx >= d->mm.ldt_ents )
   3.187 +        {
   3.188 +            DPRINTK("Segment %04x out of LDT range (%d)\n",
   3.189 +                    seg, d->mm.ldt_ents);
   3.190 +            goto fail;
   3.191 +        }
   3.192 +    }
   3.193 +    else /* gdt */
   3.194 +    {
   3.195 +        table = (unsigned long *)GET_GDT_ADDRESS(d);
   3.196 +        if ( idx >= GET_GDT_ENTRIES(d) )
   3.197 +        {
   3.198 +            DPRINTK("Segment %04x out of GDT range (%d)\n",
   3.199 +                    seg, GET_GDT_ENTRIES(d));
   3.200 +            goto fail;
   3.201 +        }
   3.202 +    }
   3.203 +
   3.204 +    /* Grab the segment descriptor. */
   3.205 +    if ( __get_user(a, &table[2*idx+0]) ||
   3.206 +         __get_user(b, &table[2*idx+1]) )
   3.207 +    {
   3.208 +        DPRINTK("Fault while reading segment %04x\n", seg);
   3.209 +        goto fail; /* Barking up the wrong tree. Decode needs a page fault.*/
   3.210 +    }
   3.211 +
   3.212 +    /* We only parse 32-bit page-granularity non-privileged data segments. */
   3.213 +    if ( (b & (_SEGMENT_P|_SEGMENT_S|_SEGMENT_DB|
   3.214 +               _SEGMENT_G|(1<<11)|_SEGMENT_DPL)) != 
   3.215 +         (_SEGMENT_P|_SEGMENT_S|_SEGMENT_DB|_SEGMENT_G|_SEGMENT_DPL) )
   3.216 +    {
   3.217 +        DPRINTK("Bad segment %08lx:%08lx\n", a, b);
   3.218 +        goto fail;
   3.219 +    }
   3.220 +
   3.221 +    /* Decode base and limit. */
   3.222 +    base  = (b&(0xff<<24)) | ((b&0xff)<<16) | (a>>16);
   3.223 +    limit = (((b & 0xf0000) | (a & 0x0ffff)) + 1) << 12;
   3.224 +
   3.225 +    if ( b & (1 << 10) )
   3.226 +    {
   3.227 +        /* Expands-down: All the way to zero? Assume 4GB if so. */
   3.228 +        if ( ((base + limit) < PAGE_SIZE) && positive_access )
   3.229 +        {
   3.230 +            /* Flip to expands-up. */
   3.231 +            limit >>= 12;
   3.232 +            limit -= (-PAGE_OFFSET/PAGE_SIZE) + 2;
   3.233 +            goto flip;
   3.234 +        }
   3.235 +    }
   3.236 +    else
   3.237 +    {
   3.238 +        /* Expands-up: All the way to Xen space? Assume 4GB if so. */
   3.239 +        if ( ((PAGE_OFFSET - (base + limit)) < PAGE_SIZE) && !positive_access )
   3.240 +        {
   3.241 +            /* Flip to expands-down. */
   3.242 +            limit >>= 12;
   3.243 +            limit += (-PAGE_OFFSET/PAGE_SIZE) + 0;
   3.244 +            goto flip;
   3.245 +        }
   3.246 +    }
   3.247 +
   3.248 +    DPRINTK("None of the above! (%08lx:%08lx, %d, %08lx, %08lx, %08lx)\n", 
   3.249 +            a, b, positive_access, base, limit, base+limit);
   3.250 +
   3.251 + fail:
   3.252 +    return 0;
   3.253 +
   3.254 + flip:
   3.255 +    a &= ~0x0ffff; a |= limit & 0x0ffff;
   3.256 +    b &= ~0xf0000; b |= limit & 0xf0000;
   3.257 +    b ^= 1 << 10;
   3.258 +    /* NB. These can't fault. Checked readable above; must also be writable. */
   3.259 +    table[2*idx+0] = a;
   3.260 +    table[2*idx+1] = b;
   3.261 +    return 1;
   3.262 +}
   3.263 +
   3.264 +/* Decode Reg field of a ModRM byte: return a pointer into a register block. */
   3.265 +void *decode_reg(struct pt_regs *regs, u8 b)
   3.266 +{
   3.267 +    switch ( b & 7 )
   3.268 +    {
   3.269 +    case 0: return &regs->eax;
   3.270 +    case 1: return &regs->ecx;
   3.271 +    case 2: return &regs->edx;
   3.272 +    case 3: return &regs->ebx;
   3.273 +    case 4: return &regs->esp;
   3.274 +    case 5: return &regs->ebp;
   3.275 +    case 6: return &regs->esi;
   3.276 +    case 7: return &regs->edi;
   3.277 +    }
   3.278 +
   3.279 +    return NULL;
   3.280 +}
   3.281 +
   3.282 +/*
   3.283 + * Called from the general-protection fault handler to attempt to decode
   3.284 + * and emulate an instruction that depends on 4GB segments. At this point
   3.285 + * we assume that the instruction itself is paged into memory (the CPU
   3.286 + * must have triggered this in order to decode the instruction itself).
   3.287 + */
   3.288 +int gpf_emulate_4gb(struct pt_regs *regs)
   3.289 +{
   3.290 +    struct domain *d = current;
   3.291 +    trap_info_t   *ti;
   3.292 +    struct guest_trap_bounce *gtb;
   3.293 +    u8            modrm, mod, reg, rm, decode;
   3.294 +    void         *memreg, *regreg;
   3.295 +    unsigned long offset;
   3.296 +    u8            disp8;
   3.297 +    u32           disp32 = 0;
   3.298 +    u8            *eip;         /* ptr to instruction start */
   3.299 +    u8            *pb, b;       /* ptr into instr. / current instr. byte */
   3.300 +    unsigned int  *pseg = NULL; /* segment for memory operand (NULL=default) */
   3.301 +
   3.302 +    /* WARNING: We only work for ring-3 segments. */
   3.303 +    if ( unlikely((regs->xcs & 3) != 3) )
   3.304 +    {
   3.305 +        DPRINTK("Taken fault at bad CS %04x\n", regs->xcs);
   3.306 +        goto fail;
   3.307 +    }
   3.308 +
   3.309 +    if ( !linearise_address((u16)regs->xcs, regs->eip, (unsigned long *)&eip) )
   3.310 +    {
   3.311 +        DPRINTK("Cannot linearise %04x:%08lx\n", regs->xcs, regs->eip);
   3.312 +        goto fail;
   3.313 +    }
   3.314 +
   3.315 +    /* Parse prefix bytes. We're basically looking for segment override. */
   3.316 +    for ( pb = eip; ; pb++ )
   3.317 +    {
   3.318 +        if ( get_user(b, pb) )
   3.319 +        {
   3.320 +            DPRINTK("Fault while accessing byte %d of instruction\n", pb-eip);
   3.321 +            goto fail;
   3.322 +        }
   3.323 +
   3.324 +        if ( (pb - eip) == 4 )
   3.325 +            break;
   3.326 +        
   3.327 +        switch ( b )
   3.328 +        {
   3.329 +        case 0xf0: /* LOCK */
   3.330 +        case 0xf2: /* REPNE/REPNZ */
   3.331 +        case 0xf3: /* REP/REPE/REPZ */
   3.332 +        case 0x67: /* Address-size override */
   3.333 +            DPRINTK("Unhandleable prefix byte %02x\n", b);
   3.334 +            goto fixme;
   3.335 +        case 0x66: /* Operand-size override */
   3.336 +            break;
   3.337 +        case 0x2e: /* CS override */
   3.338 +            pseg = &regs->xcs;
   3.339 +            break;
   3.340 +        case 0x3e: /* DS override */
   3.341 +            pseg = &regs->xds;
   3.342 +            break;
   3.343 +        case 0x26: /* ES override */
   3.344 +            pseg = &regs->xes;
   3.345 +            break;
   3.346 +        case 0x64: /* FS override */
   3.347 +            pseg = &regs->xfs;
   3.348 +            break;
   3.349 +        case 0x65: /* GS override */
   3.350 +            pseg = &regs->xgs;
   3.351 +            break;
   3.352 +        case 0x36: /* SS override */
   3.353 +            pseg = &regs->xss;
   3.354 +            break;
   3.355 +        default: /* Not a prefix byte */
   3.356 +            goto done_prefix;
   3.357 +        }
   3.358 +    }
   3.359 + done_prefix:
   3.360 +
   3.361 +    decode = insn_decode[b]; /* opcode byte */
   3.362 +    pb++;
   3.363 +    if ( decode == 0 )
   3.364 +    {
   3.365 +        DPRINTK("Unsupported opcode %02x\n", b);
   3.366 +        goto fail;
   3.367 +    }
   3.368 +    
   3.369 +    if ( !(decode & HAS_MODRM) )
   3.370 +    {
   3.371 +        switch ( decode & 7 )
   3.372 +        {
   3.373 +        case 1:
   3.374 +            offset = (long)(*(char *)pb);
   3.375 +            goto skip_modrm;
   3.376 +        case 4:
   3.377 +            offset = *(long *)pb;
   3.378 +            goto skip_modrm;
   3.379 +        default:
   3.380 +            goto fail;
   3.381 +        }
   3.382 +    }
   3.383 +
   3.384 +    /*
   3.385 +     * Mod/RM processing.
   3.386 +     */
   3.387 +
   3.388 +    if ( get_user(modrm, pb) )
   3.389 +    {
   3.390 +        DPRINTK("Fault while extracting modrm byte\n");
   3.391 +        goto fail;
   3.392 +    }
   3.393 +
   3.394 +    pb++;
   3.395 +
   3.396 +    mod = (modrm >> 6) & 3;
   3.397 +    reg = (modrm >> 3) & 7;
   3.398 +    rm  = (modrm >> 0) & 7;
   3.399 +
   3.400 +    if ( rm == 4 )
   3.401 +    {
   3.402 +        DPRINTK("FIXME: Add decoding for the SIB byte.\n");
   3.403 +        goto fixme;
   3.404 +    }
   3.405 +
   3.406 +    /* Decode Reg and R/M fields. */
   3.407 +    regreg = decode_reg(regs, reg);
   3.408 +    memreg = decode_reg(regs, rm);
   3.409 +
   3.410 +    /* Decode Mod field. */
   3.411 +    switch ( modrm >> 6 )
   3.412 +    {
   3.413 +    case 0:
   3.414 +        if ( pseg == NULL )
   3.415 +            pseg = &regs->xds;
   3.416 +        disp32 = 0;
   3.417 +        if ( rm == 5 ) /* disp32 rather than (EBP) */
   3.418 +        {
   3.419 +            memreg = NULL;
   3.420 +            if ( get_user(disp32, (u32 *)pb) )
   3.421 +            {
   3.422 +                DPRINTK("Fault while extracting <disp8>.\n");
   3.423 +                goto fail;
   3.424 +            }
   3.425 +            pb += 4;
   3.426 +        }
   3.427 +        break;
   3.428 +
   3.429 +    case 1:
   3.430 +        if ( pseg == NULL ) /* NB. EBP defaults to SS */
   3.431 +            pseg = (rm == 5) ? &regs->xss : &regs->xds;
   3.432 +        if ( get_user(disp8, pb) )
   3.433 +        {
   3.434 +            DPRINTK("Fault while extracting <disp8>.\n");
   3.435 +            goto fail;
   3.436 +        }
   3.437 +        pb++;
   3.438 +        disp32 = (disp8 & 0x80) ? (disp8 | ~0xff) : disp8;;
   3.439 +        break;
   3.440 +
   3.441 +    case 2:
   3.442 +        if ( pseg == NULL ) /* NB. EBP defaults to SS */
   3.443 +            pseg = (rm == 5) ? &regs->xss : &regs->xds;
   3.444 +        if ( get_user(disp32, (u32 *)pb) )
   3.445 +        {
   3.446 +            DPRINTK("Fault while extracting <disp8>.\n");
   3.447 +            goto fail;
   3.448 +        }
   3.449 +        pb += 4;
   3.450 +        break;
   3.451 +
   3.452 +    case 3:
   3.453 +        DPRINTK("Not a memory operand!\n");
   3.454 +        goto fail;
   3.455 +    }
   3.456 +
   3.457 +    offset = disp32;
   3.458 +    if ( memreg != NULL )
   3.459 +        offset += *(u32 *)memreg;
   3.460 +
   3.461 + skip_modrm:
   3.462 +    if ( !fixup_seg((u16)(*pseg), (signed long)offset >= 0) )
   3.463 +        goto fail;
   3.464 +
   3.465 +    /* Success! */
   3.466 +    perfc_incrc(seg_fixups);
   3.467 +
   3.468 +    /* If requested, give a callback on otherwise unused vector 15. */
   3.469 +    if ( VM_ASSIST(d, VMASST_TYPE_4gb_segments_notify) )
   3.470 +    {
   3.471 +        ti  = &d->thread.traps[15];
   3.472 +        gtb = &guest_trap_bounce[d->processor];
   3.473 +        gtb->flags      = GTBF_TRAP;
   3.474 +        gtb->error_code = pb - eip;
   3.475 +        gtb->cs         = ti->cs;
   3.476 +        gtb->eip        = ti->address;
   3.477 +        if ( TI_GET_IF(ti) )
   3.478 +            d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
   3.479 +    }
   3.480 +
   3.481 +    return 1;
   3.482 +
   3.483 + fixme:
   3.484 +    DPRINTK("Undecodable instruction %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
   3.485 +            "caused GPF(0) at %04x:%08lx\n",
   3.486 +            eip[0], eip[1], eip[2], eip[3],
   3.487 +            eip[4], eip[5], eip[6], eip[7],
   3.488 +            regs->xcs, regs->eip);
   3.489 + fail:
   3.490 +    return 0;
   3.491 +}
     4.1 --- a/xen/include/xen/perfc_defn.h	Wed Oct 20 08:12:06 2004 +0000
     4.2 +++ b/xen/include/xen/perfc_defn.h	Wed Oct 20 14:44:56 2004 +0000
     4.3 @@ -1,5 +1,5 @@
     4.4  
     4.5 -PERFCOUNTER_CPU (emulations,   "instructions emulated" )
     4.6 +PERFCOUNTER_CPU (seg_fixups,   "segmentation fixups" )
     4.7  
     4.8  PERFCOUNTER_CPU( irqs,         "#interrupts" )
     4.9  PERFCOUNTER_CPU( ipis,         "#IPIs" )