ia64/xen-unstable

changeset 1821:1a488e40456a

bitkeeper revision 1.1108 (40faa786-NQDR74N9ltmfUON6lXTWw)

Merge scramble.cl.cam.ac.uk:/auto/groups/xeno/BK/xeno.bk
into scramble.cl.cam.ac.uk:/local/scratch/kaf24/xeno
author kaf24@scramble.cl.cam.ac.uk
date Sun Jul 18 16:38:30 2004 +0000 (2004-07-18)
parents 67207b5553cd 3d4f8eb89670
children 101465779482 cf5056d3e5e8 44e286624053 b18621623b26 51332b88e187
files .rootkeys linux-2.4.26-xen-sparse/arch/xen/kernel/ioport.c linux-2.4.26-xen-sparse/mkbuildtree linux-2.6.7-xen-sparse/arch/xen/i386/kernel/ioport.c linux-2.6.7-xen-sparse/arch/xen/i386/kernel/process.c linux-2.6.7-xen-sparse/arch/xen/i386/kernel/setup.c linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/processor.h xen/arch/x86/x86_32/emulate.c
line diff
     1.1 --- a/.rootkeys	Sat Jul 17 20:09:56 2004 +0000
     1.2 +++ b/.rootkeys	Sun Jul 18 16:38:30 2004 +0000
     1.3 @@ -80,7 +80,6 @@ 3e5a4e65_hqfuxtGG8IUy6wRM86Ecg linux-2.4
     1.4  3e5a4e65ibVQmwlOn0j3sVH_j_6hAg linux-2.4.26-xen-sparse/arch/xen/kernel/evtchn.c
     1.5  3e5a4e65Hy_1iUvMTPsNqGNXd9uFpg linux-2.4.26-xen-sparse/arch/xen/kernel/head.S
     1.6  3e5a4e65RMGcuA-HCn3-wNx3fFQwdg linux-2.4.26-xen-sparse/arch/xen/kernel/i386_ksyms.c
     1.7 -3e5a4e65MEvZhlr070sK5JsfAQlv7Q linux-2.4.26-xen-sparse/arch/xen/kernel/ioport.c
     1.8  3e5a4e653U6cELGv528IxOLHvCq8iA linux-2.4.26-xen-sparse/arch/xen/kernel/irq.c
     1.9  3e5a4e65muT6SU3ck47IP87Q7Ti5hA linux-2.4.26-xen-sparse/arch/xen/kernel/ldt.c
    1.10  4051db84bZeRX7a_Kh6VyyDuT5FOIg linux-2.4.26-xen-sparse/arch/xen/kernel/pci-dma.c
    1.11 @@ -164,6 +163,7 @@ 40f56238XDtHSijkAFlbv1PT8Bhw_Q linux-2.6
    1.12  40f56238xFQe9T7M_U_FItM-bZIpLw linux-2.6.7-xen-sparse/arch/xen/i386/kernel/evtchn.c
    1.13  40f56238bnvciAuyzAiMkdzGErYt1A linux-2.6.7-xen-sparse/arch/xen/i386/kernel/head.S
    1.14  40f58a0d31M2EkuPbG94ns_nOi0PVA linux-2.6.7-xen-sparse/arch/xen/i386/kernel/i386_ksyms.c
    1.15 +40faa751_zbZlAmLyQgCXdYekVFdWA linux-2.6.7-xen-sparse/arch/xen/i386/kernel/ioport.c
    1.16  40f562382aC3_Gt4RG-4ZsfvDRUg3Q linux-2.6.7-xen-sparse/arch/xen/i386/kernel/irq.c
    1.17  40f56238ue3YRsK52HG7iccNzP1AwQ linux-2.6.7-xen-sparse/arch/xen/i386/kernel/ldt.c
    1.18  40f56238a8iOVDEoostsbun_sy2i4g linux-2.6.7-xen-sparse/arch/xen/i386/kernel/process.c
     2.1 --- a/linux-2.4.26-xen-sparse/arch/xen/kernel/ioport.c	Sat Jul 17 20:09:56 2004 +0000
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,48 +0,0 @@
     2.4 -#include <linux/sched.h>
     2.5 -#include <linux/kernel.h>
     2.6 -#include <linux/errno.h>
     2.7 -#include <linux/types.h>
     2.8 -#include <linux/stddef.h>
     2.9 -#include <asm/hypervisor-ifs/dom0_ops.h>
    2.10 -
    2.11 -
    2.12 -asmlinkage int sys_iopl(unsigned int new_io_pl)
    2.13 -{
    2.14 -    unsigned int old_io_pl = current->thread.io_pl;
    2.15 -    dom0_op_t op;
    2.16 -
    2.17 -    if ( !(start_info.flags & SIF_PRIVILEGED) )
    2.18 -        return -EPERM;
    2.19 -
    2.20 -    if ( new_io_pl > 3 )
    2.21 -        return -EINVAL;
    2.22 -
    2.23 -    /* Need "raw I/O" privileges for direct port access. */
    2.24 -    if ( (new_io_pl > old_io_pl) && !capable(CAP_SYS_RAWIO) )
    2.25 -        return -EPERM;
    2.26 -
    2.27 -    /* Maintain OS privileges even if user attempts to relinquish them. */
    2.28 -    if ( (new_io_pl == 0) && (start_info.flags & SIF_PRIVILEGED) )
    2.29 -        new_io_pl = 1;
    2.30 -
    2.31 -    /* Change our version of the privilege levels. */
    2.32 -    current->thread.io_pl = new_io_pl;
    2.33 -
    2.34 -    /* Force the change at ring 0. */
    2.35 -    op.cmd           = DOM0_IOPL;
    2.36 -    op.u.iopl.domain = DOMID_SELF;
    2.37 -    op.u.iopl.iopl   = new_io_pl;
    2.38 -    HYPERVISOR_dom0_op(&op);
    2.39 -
    2.40 -    return 0;
    2.41 -}
    2.42 -
    2.43 -
    2.44 -asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
    2.45 -{
    2.46 -    printk(KERN_INFO "ioperm not fully supported - %s\n",
    2.47 -           turn_on ? "set iopl to 3" : "ignore resource release");
    2.48 -    return turn_on ? sys_iopl(3) : 0;
    2.49 -}
    2.50 -
    2.51 -
     3.1 --- a/linux-2.4.26-xen-sparse/mkbuildtree	Sat Jul 17 20:09:56 2004 +0000
     3.2 +++ b/linux-2.4.26-xen-sparse/mkbuildtree	Sun Jul 18 16:38:30 2004 +0000
     3.3 @@ -209,6 +209,7 @@ ln -sf ../../i386/kernel/pci-i386.h
     3.4  ln -sf ../../i386/kernel/ptrace.c
     3.5  ln -sf ../../i386/kernel/semaphore.c 
     3.6  ln -sf ../../i386/kernel/sys_i386.c 
     3.7 +ln -sf ../../../${LINUX_26}/arch/xen/i386/kernel/ioport.c
     3.8  cd ../lib
     3.9  ln -sf ../../i386/lib/checksum.S 
    3.10  ln -sf ../../i386/lib/dec_and_lock.c 
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/linux-2.6.7-xen-sparse/arch/xen/i386/kernel/ioport.c	Sun Jul 18 16:38:30 2004 +0000
     4.3 @@ -0,0 +1,49 @@
     4.4 +#include <linux/sched.h>
     4.5 +#include <linux/kernel.h>
     4.6 +#include <linux/errno.h>
     4.7 +#include <linux/types.h>
     4.8 +#include <linux/ioport.h>
     4.9 +#include <linux/mm.h>
    4.10 +#include <linux/smp.h>
    4.11 +#include <linux/smp_lock.h>
    4.12 +#include <linux/stddef.h>
    4.13 +#include <linux/slab.h>
    4.14 +#include <asm/hypervisor-ifs/dom0_ops.h>
    4.15 +
    4.16 +asmlinkage long sys_iopl(unsigned int new_io_pl)
    4.17 +{
    4.18 +	unsigned int old_io_pl = current->thread.io_pl;
    4.19 +	dom0_op_t op;
    4.20 +
    4.21 +	if (!(start_info.flags & SIF_PRIVILEGED))
    4.22 +		return -EPERM;
    4.23 +
    4.24 +	if (new_io_pl > 3)
    4.25 +		return -EINVAL;
    4.26 +
    4.27 +	/* Need "raw I/O" privileges for direct port access. */
    4.28 +	if ((new_io_pl > old_io_pl) && !capable(CAP_SYS_RAWIO))
    4.29 +		return -EPERM;
    4.30 +
    4.31 +	/* Maintain OS privileges even if user attempts to relinquish them. */
    4.32 +	if (new_io_pl == 0)
    4.33 +		new_io_pl = 1;
    4.34 +
    4.35 +	/* Change our version of the privilege levels. */
    4.36 +	current->thread.io_pl = new_io_pl;
    4.37 +
    4.38 +	/* Force the change at ring 0. */
    4.39 +	op.cmd           = DOM0_IOPL;
    4.40 +	op.u.iopl.domain = DOMID_SELF;
    4.41 +	op.u.iopl.iopl   = new_io_pl;
    4.42 +	HYPERVISOR_dom0_op(&op);
    4.43 +
    4.44 +	return 0;
    4.45 +}
    4.46 +
    4.47 +asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
    4.48 +{
    4.49 +	printk(KERN_INFO "ioperm not fully supported - %s\n",
    4.50 +		turn_on ? "set iopl to 3" : "ignore resource release");
    4.51 +	return turn_on ? sys_iopl(3) : 0;
    4.52 +}
     5.1 --- a/linux-2.6.7-xen-sparse/arch/xen/i386/kernel/process.c	Sat Jul 17 20:09:56 2004 +0000
     5.2 +++ b/linux-2.6.7-xen-sparse/arch/xen/i386/kernel/process.c	Sun Jul 18 16:38:30 2004 +0000
     5.3 @@ -338,6 +338,7 @@ int copy_thread(int nr, unsigned long cl
     5.4  	struct pt_regs * childregs;
     5.5  	struct task_struct *tsk;
     5.6  	int err;
     5.7 +	unsigned long eflags;
     5.8  
     5.9  	childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
    5.10  	struct_cpy(childregs, regs);
    5.11 @@ -386,6 +387,10 @@ int copy_thread(int nr, unsigned long cl
    5.12  		desc->b = LDT_entry_b(&info);
    5.13  	}
    5.14  
    5.15 +
    5.16 +	__asm__ __volatile__ ( "pushfl; popl %0" : "=r" (eflags) : );
    5.17 +	p->thread.io_pl = (eflags >> 12) & 3;
    5.18 +
    5.19  	err = 0;
    5.20   out:
    5.21  	if (err && p->thread.io_bitmap_ptr)
    5.22 @@ -532,6 +537,14 @@ struct task_struct fastcall * __switch_t
    5.23  	 */
    5.24  	load_TLS(next, cpu);
    5.25  
    5.26 +	if (start_info.flags & SIF_PRIVILEGED) {
    5.27 +		dom0_op_t op;
    5.28 +		op.cmd           = DOM0_IOPL;
    5.29 +		op.u.iopl.domain = DOMID_SELF;
    5.30 +		op.u.iopl.iopl   = next->io_pl;
    5.31 +		HYPERVISOR_dom0_op(&op);
    5.32 +	}
    5.33 +
    5.34  	local_irq_restore(flags);
    5.35  
    5.36  	/*
     6.1 --- a/linux-2.6.7-xen-sparse/arch/xen/i386/kernel/setup.c	Sat Jul 17 20:09:56 2004 +0000
     6.2 +++ b/linux-2.6.7-xen-sparse/arch/xen/i386/kernel/setup.c	Sun Jul 18 16:38:30 2004 +0000
     6.3 @@ -1206,6 +1206,17 @@ void __init setup_arch(char **cmdline_p)
     6.4  	conswitchp = &dummy_con;
     6.5  #endif
     6.6  #endif
     6.7 +
     6.8 +	/* If we are a privileged guest OS then we should request IO privs. */
     6.9 +	if (start_info.flags & SIF_PRIVILEGED) {
    6.10 +		dom0_op_t op;
    6.11 +		op.cmd           = DOM0_IOPL;
    6.12 +		op.u.iopl.domain = DOMID_SELF;
    6.13 +		op.u.iopl.iopl   = 1;
    6.14 +		if (HYPERVISOR_dom0_op(&op) != 0)
    6.15 +			panic("Unable to obtain IOPL, despite SIF_PRIVILEGED");
    6.16 +		current->thread.io_pl = 1;
    6.17 +	}
    6.18  }
    6.19  
    6.20  #include "setup_arch_post.h"
     7.1 --- a/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/processor.h	Sat Jul 17 20:09:56 2004 +0000
     7.2 +++ b/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/processor.h	Sun Jul 18 16:38:30 2004 +0000
     7.3 @@ -422,6 +422,7 @@ struct thread_struct {
     7.4  	unsigned long	esp;
     7.5  	unsigned long	fs;
     7.6  	unsigned long	gs;
     7.7 +	unsigned int	io_pl;
     7.8  /* Hardware debugging registers */
     7.9  	unsigned long	debugreg[8];  /* %%db0-7 debug registers */
    7.10  /* fault info */
     8.1 --- a/xen/arch/x86/x86_32/emulate.c	Sat Jul 17 20:09:56 2004 +0000
     8.2 +++ b/xen/arch/x86/x86_32/emulate.c	Sun Jul 18 16:38:30 2004 +0000
     8.3 @@ -30,6 +30,15 @@
     8.4  #include <xen/perfc.h>
     8.5  #include <asm/processor.h>
     8.6  
     8.7 +/*
     8.8 + * Obtain the base and limit associated with the given segment selector.
     8.9 + * The selector must identify a 32-bit code or data segment. Any segment that
    8.10 + * appears to be truncated to not overlap with Xen is assumed to be a truncated
    8.11 + * 4GB segment, and the returned limit reflects this.
    8.12 + *  @seg   (IN) : Segment selector to decode.
    8.13 + *  @base  (OUT): Decoded linear base address.
    8.14 + *  @limit (OUT): Decoded segment limit, in bytes. 0 == unlimited (4GB).
    8.15 + */
    8.16  int get_baselimit(u16 seg, unsigned long *base, unsigned long *limit)
    8.17  {
    8.18      struct domain *d = current;
    8.19 @@ -80,6 +89,7 @@ int get_baselimit(u16 seg, unsigned long
    8.20      return 0;
    8.21  }
    8.22  
    8.23 +/* Turn a segment+offset into a linear address. */
    8.24  int linearise_address(u16 seg, unsigned long off, unsigned long *linear)
    8.25  {
    8.26      unsigned long base, limit;
    8.27 @@ -95,6 +105,7 @@ int linearise_address(u16 seg, unsigned 
    8.28      return 1;
    8.29  }
    8.30  
    8.31 +/* Decode Reg field of a ModRM byte: return a pointer into a register block. */
    8.32  void *decode_reg(struct pt_regs *regs, u8 b)
    8.33  {
    8.34      switch ( b & 7 )
    8.35 @@ -120,6 +131,9 @@ void *decode_reg(struct pt_regs *regs, u
    8.36   *  @pseg (IN)   : address in pt_regs block of the override segment.
    8.37   *  @regs (IN)   : addrress of the the pt_regs block.
    8.38   */
    8.39 +#define DECODE_EA_FAILED  0
    8.40 +#define DECODE_EA_FIXME   1
    8.41 +#define DECODE_EA_SUCCESS 2
    8.42  int decode_effective_address(u8 **ppb, void **preg, void **pmem,
    8.43                               unsigned int *pseg, struct pt_regs *regs)
    8.44  {
    8.45 @@ -132,7 +146,7 @@ int decode_effective_address(u8 **ppb, v
    8.46      if ( get_user(modrm, pb) )
    8.47      {
    8.48          DPRINTK("Fault while extracting modrm byte\n");
    8.49 -        return 0;
    8.50 +        return DECODE_EA_FAILED;
    8.51      }
    8.52  
    8.53      pb++;
    8.54 @@ -144,7 +158,7 @@ int decode_effective_address(u8 **ppb, v
    8.55      if ( rm == 4 )
    8.56      {
    8.57          DPRINTK("FIXME: Add decoding for the SIB byte.\n");
    8.58 -        return 0;
    8.59 +        return DECODE_EA_FIXME;
    8.60      }
    8.61  
    8.62      /* Decode Reg and R/M fields. */
    8.63 @@ -164,7 +178,7 @@ int decode_effective_address(u8 **ppb, v
    8.64              if ( get_user(disp32, (u32 *)pb) )
    8.65              {
    8.66                  DPRINTK("Fault while extracting <disp8>.\n");
    8.67 -                return 0;
    8.68 +                return DECODE_EA_FAILED;
    8.69              }
    8.70              pb += 4;
    8.71          }
    8.72 @@ -176,7 +190,7 @@ int decode_effective_address(u8 **ppb, v
    8.73          if ( get_user(disp8, pb) )
    8.74          {
    8.75              DPRINTK("Fault while extracting <disp8>.\n");
    8.76 -            return 0;
    8.77 +            return DECODE_EA_FAILED;
    8.78          }
    8.79          pb++;
    8.80          disp32 = (disp8 & 0x80) ? (disp8 | ~0xff) : disp8;;
    8.81 @@ -188,22 +202,22 @@ int decode_effective_address(u8 **ppb, v
    8.82          if ( get_user(disp32, (u32 *)pb) )
    8.83          {
    8.84              DPRINTK("Fault while extracting <disp8>.\n");
    8.85 -            return 0;
    8.86 +            return DECODE_EA_FAILED;
    8.87          }
    8.88          pb += 4;
    8.89          break;
    8.90  
    8.91      case 3:
    8.92          DPRINTK("Not a memory operand!\n");
    8.93 -        return 0;
    8.94 +        return DECODE_EA_FAILED;
    8.95      }
    8.96  
    8.97      if ( !get_baselimit((u16)(*pseg), &ea, &limit) )
    8.98 -        return 0;
    8.99 +        return DECODE_EA_FAILED;
   8.100      if ( limit != 0 )
   8.101      {
   8.102          DPRINTK("Bailing: not a 4GB data segment.\n");
   8.103 -        return 0;
   8.104 +        return DECODE_EA_FAILED;
   8.105      }
   8.106  
   8.107      offset = disp32;
   8.108 @@ -212,23 +226,42 @@ int decode_effective_address(u8 **ppb, v
   8.109      if ( (offset & 0xf0000000) != 0xf0000000 )
   8.110      {
   8.111          DPRINTK("Bailing: not a -ve offset into 4GB segment.\n");
   8.112 -        return 0;
   8.113 +        return DECODE_EA_FAILED;
   8.114      }
   8.115  
   8.116      ea += offset;
   8.117      if ( ea > (PAGE_OFFSET - PAGE_SIZE) )
   8.118      {
   8.119          DPRINTK("!!!! DISALLOWING UNSAFE ACCESS !!!!\n");
   8.120 -        return 0;
   8.121 +        return DECODE_EA_FAILED;
   8.122      }
   8.123  
   8.124      *ppb  = pb;
   8.125      *preg = regreg;
   8.126      *pmem = (void *)ea;
   8.127  
   8.128 -    return 1;
   8.129 +    return DECODE_EA_SUCCESS;
   8.130  }
   8.131  
   8.132 +#define GET_IMM8                                   \
   8.133 +    if ( get_user(ib, (u8 *)pb) ) {                \
   8.134 +        DPRINTK("Fault while extracting imm8\n");  \
   8.135 +        return 0;                                  \
   8.136 +    }                                              \
   8.137 +    pb += 1;
   8.138 +#define GET_IMM16                                  \
   8.139 +    if ( get_user(iw, (u8 *)pb) ) {                \
   8.140 +        DPRINTK("Fault while extracting imm16\n"); \
   8.141 +        return 0;                                  \
   8.142 +    }                                              \
   8.143 +    pb += 2;
   8.144 +#define GET_IMM32                                  \
   8.145 +    if ( get_user(il, (u32 *)pb) ) {               \
   8.146 +        DPRINTK("Fault while extracting imm32\n"); \
   8.147 +        return 0;                                  \
   8.148 +    }                                              \
   8.149 +    pb += 4;
   8.150 +
   8.151  /*
   8.152   * Called from the general-protection fault handler to attempt to decode
   8.153   * and emulate an instruction that depends on 4GB segments. At this point
   8.154 @@ -239,14 +272,17 @@ int gpf_emulate_4gb(struct pt_regs *regs
   8.155  {
   8.156      struct domain *d = current;
   8.157      trap_info_t   *ti;
   8.158 -    u8            *eip, *nextbyte, b, mb, rb;
   8.159 -    u16            mw, rw;
   8.160 -    u32            ml, rl, eflags;
   8.161 -    unsigned int  *pseg = NULL;
   8.162 -    int            i;
   8.163 +    struct guest_trap_bounce *gtb;
   8.164 +
   8.165 +    u8            *eip;         /* ptr to instruction start */
   8.166 +    u8            *pb, b;       /* ptr into instr. / current instr. byte */
   8.167 +    u8             ib, mb, rb;  /* byte operand from imm/register/memory */
   8.168 +    u16            iw, mw, rw;  /* word operand from imm/register/memory */
   8.169 +    u32            il, ml, rl;  /* long operand from imm/register/memory */
   8.170 +    void          *reg, *mem;   /* ptr to register/memory operand */
   8.171 +    unsigned int  *pseg = NULL; /* segment for memory operand (NULL=default) */
   8.172 +    u32            eflags;
   8.173      int            opsz_override = 0;
   8.174 -    void          *reg, *mem;
   8.175 -    struct guest_trap_bounce *gtb;
   8.176  
   8.177      if ( !linearise_address((u16)regs->xcs, regs->eip, (unsigned long *)&eip) )
   8.178      {
   8.179 @@ -255,11 +291,11 @@ int gpf_emulate_4gb(struct pt_regs *regs
   8.180      }
   8.181  
   8.182      /* Parse prefix bytes. We're basically looking for segment override. */
   8.183 -    for ( i = 0; i < 4; i++ )
   8.184 +    for ( pb = eip; (pb - eip) < 4; pb++ )
   8.185      {
   8.186 -        if ( get_user(b, &eip[i]) )
   8.187 +        if ( get_user(b, pb) )
   8.188          {
   8.189 -            DPRINTK("Fault while accessing byte %d of instruction\n", i);
   8.190 +            DPRINTK("Fault while accessing byte %d of instruction\n", pb-eip);
   8.191              return 0;
   8.192          }
   8.193          
   8.194 @@ -298,141 +334,94 @@ int gpf_emulate_4gb(struct pt_regs *regs
   8.195      }
   8.196   done_prefix:
   8.197  
   8.198 -    nextbyte = &eip[i+1];
   8.199 -    if ( !decode_effective_address(&nextbyte, &reg, &mem, pseg, regs) )
   8.200 +    pb++; /* skip opcode byte */
   8.201 +    switch ( decode_effective_address(&pb, &reg, &mem, pseg, regs) )
   8.202 +    {
   8.203 +    case DECODE_EA_FAILED:
   8.204 +        return 0;
   8.205 +    case DECODE_EA_FIXME:
   8.206          goto undecodeable;
   8.207 +    }
   8.208  
   8.209      /* Only handle single-byte opcodes right now. Sufficient for MOV. */
   8.210 -    /*
   8.211 -     * XXX Now I see how this decode routine is panning out, it needs
   8.212 -     * refactoring. Lots of duplicated cruft in here...
   8.213 -     */
   8.214      switch ( b )
   8.215      {
   8.216      case 0x88: /* movb r,r/m */
   8.217          if ( __put_user(*(u8 *)reg, (u8 *)mem) )
   8.218              goto page_fault_w;
   8.219 -        regs->eip += nextbyte - eip;
   8.220          break;
   8.221      case 0x89: /* movl r,r/m */
   8.222 -        if ( opsz_override )
   8.223 -        {
   8.224 -            if ( __put_user(*(u16 *)reg, (u16 *)mem) )
   8.225 -                goto page_fault_w;
   8.226 -        }
   8.227 -        else
   8.228 -        {
   8.229 -            if ( __put_user(*(u32 *)reg, (u32 *)mem) )
   8.230 -                goto page_fault_w;
   8.231 -        }
   8.232 -        regs->eip += nextbyte - eip;
   8.233 +        if ( opsz_override ? __put_user(*(u16 *)reg, (u16 *)mem)
   8.234 +                           : __put_user(*(u32 *)reg, (u32 *)mem) )
   8.235 +            goto page_fault_w;
   8.236          break;
   8.237      case 0x8a: /* movb r/m,r */
   8.238          if ( __get_user(*(u8 *)reg, (u8 *)mem) )
   8.239              goto page_fault_r;
   8.240 -        regs->eip += nextbyte - eip;
   8.241          break;
   8.242      case 0x8b: /* movl r/m,r */
   8.243 -        if ( opsz_override )
   8.244 -        {
   8.245 -            if ( __get_user(*(u16 *)reg, (u16 *)mem) )
   8.246 -                goto page_fault_r;
   8.247 -        }
   8.248 -        else
   8.249 -        {
   8.250 -            if ( __get_user(*(u32 *)reg, (u32 *)mem) )
   8.251 -                goto page_fault_r;
   8.252 -        }
   8.253 -        regs->eip += nextbyte - eip;
   8.254 +        if ( opsz_override ? __get_user(*(u16 *)reg, (u16 *)mem)
   8.255 +                           : __get_user(*(u32 *)reg, (u32 *)mem) )
   8.256 +            goto page_fault_r;
   8.257          break;
   8.258      case 0xc6: /* movb imm,r/m */
   8.259          if ( reg != &regs->eax ) /* Reg == /0 */
   8.260              goto undecodeable;
   8.261 -        if ( get_user(rb, nextbyte) )
   8.262 -        {
   8.263 -            DPRINTK("Fault while extracting immediate byte\n");
   8.264 -            return 0;
   8.265 -        }
   8.266 -        if ( __put_user(rb, (u8 *)mem) )
   8.267 +        GET_IMM8;
   8.268 +        if ( __put_user(ib, (u8 *)mem) )
   8.269              goto page_fault_w;
   8.270 -        regs->eip += nextbyte - eip + 1;
   8.271          break;
   8.272      case 0xc7: /* movl imm,r/m */
   8.273          if ( reg != &regs->eax ) /* Reg == /0 */
   8.274              goto undecodeable;
   8.275          if ( opsz_override )
   8.276          {
   8.277 -            if ( get_user(rw, (u16 *)nextbyte) )
   8.278 -            {
   8.279 -                DPRINTK("Fault while extracting immediate word\n");
   8.280 -                return 0;
   8.281 -            }
   8.282 -            if ( __put_user(rw, (u16 *)mem) )
   8.283 +            GET_IMM16;
   8.284 +            if ( __put_user(iw, (u16 *)mem) )
   8.285                  goto page_fault_w;
   8.286 -            regs->eip += nextbyte - eip + 2;
   8.287          }
   8.288          else
   8.289          {
   8.290 -            if ( get_user(rl, (u32 *)nextbyte) )
   8.291 -            {
   8.292 -                DPRINTK("Fault while extracting immediate longword\n");
   8.293 -                return 0;
   8.294 -            }
   8.295 -            if ( __put_user(rl, (u32 *)mem) )
   8.296 +            GET_IMM32;
   8.297 +            if ( __put_user(il, (u32 *)mem) )
   8.298                  goto page_fault_w;
   8.299 -            regs->eip += nextbyte - eip + 4;
   8.300          }
   8.301          break;
   8.302      case 0x80: /* cmpb imm8,r/m */
   8.303          if ( reg != &regs->edi ) /* Reg == /7 */
   8.304              goto undecodeable;
   8.305 -        if ( get_user(rb, nextbyte) )
   8.306 -        {
   8.307 -            DPRINTK("Fault while extracting immediate byte\n");
   8.308 -            return 0;
   8.309 -        }
   8.310 +        GET_IMM8;
   8.311          if ( __get_user(mb, (u8 *)mem) )
   8.312              goto page_fault_r;
   8.313          __asm__ __volatile__ (
   8.314              "cmpb %b1,%b2 ; pushf ; popl %0"
   8.315              : "=a" (eflags)
   8.316 -            : "0" (rb), "b" (mb) );
   8.317 +            : "0" (ib), "b" (mb) );
   8.318          regs->eflags &= ~0x8d5;     /* OF,SF,ZF,AF,PF,CF */
   8.319          regs->eflags |= eflags & 0x8d5;
   8.320 -        regs->eip += nextbyte - eip + 1;
   8.321          break;
   8.322      case 0x81: /* cmpl imm32,r/m */
   8.323          if ( reg != &regs->edi ) /* Reg == /7 */
   8.324              goto undecodeable;
   8.325          if ( opsz_override )
   8.326          {
   8.327 -            if ( get_user(rw, (u16 *)nextbyte) )
   8.328 -            {
   8.329 -                DPRINTK("Fault while extracting immediate word\n");
   8.330 -                return 0;
   8.331 -            }
   8.332 +            GET_IMM16;
   8.333              if ( __get_user(mw, (u16 *)mem) )
   8.334                  goto page_fault_r;
   8.335              __asm__ __volatile__ (
   8.336                  "cmpw %w1,%w2 ; pushf ; popl %0"
   8.337                  : "=a" (eflags)
   8.338 -                : "0" (rw), "b" (mw) );
   8.339 -            regs->eip += nextbyte - eip + 2;
   8.340 +                : "0" (iw), "b" (mw) );
   8.341          }
   8.342          else
   8.343          {
   8.344 -            if ( get_user(rl, (u32 *)nextbyte) )
   8.345 -            {
   8.346 -                DPRINTK("Fault while extracting immediate longword\n");
   8.347 -                return 0;
   8.348 -            }
   8.349 +            GET_IMM32;
   8.350              if ( __get_user(ml, (u32 *)mem) )
   8.351                  goto page_fault_r;
   8.352              __asm__ __volatile__ (
   8.353                  "cmpl %1,%2 ; pushf ; popl %0"
   8.354                  : "=a" (eflags)
   8.355 -                : "0" (rl), "b" (ml) );
   8.356 -            regs->eip += nextbyte - eip + 4;
   8.357 +                : "0" (il), "b" (ml) );
   8.358          }
   8.359          regs->eflags &= ~0x8d5;     /* OF,SF,ZF,AF,PF,CF */
   8.360          regs->eflags |= eflags & 0x8d5;
   8.361 @@ -440,35 +429,29 @@ int gpf_emulate_4gb(struct pt_regs *regs
   8.362      case 0x83: /* cmpl imm8,r/m */
   8.363          if ( reg != &regs->edi ) /* Reg == /7 */
   8.364              goto undecodeable;
   8.365 -        if ( get_user(rb, nextbyte) )
   8.366 -        {
   8.367 -            DPRINTK("Fault while extracting immediate byte\n");
   8.368 -            return 0;
   8.369 -        }
   8.370 +        GET_IMM8;
   8.371          if ( opsz_override )
   8.372          {
   8.373 -            rw = (rb & 0x80) ? (rb | ~0xff) : rb;
   8.374 +            iw = (u16)(s16)(s8)ib;
   8.375              if ( __get_user(mw, (u16 *)mem) )
   8.376                  goto page_fault_r;
   8.377              __asm__ __volatile__ (
   8.378                  "cmpw %w1,%w2 ; pushf ; popl %0"
   8.379                  : "=a" (eflags)
   8.380 -                : "0" (rw), "b" (mw) );
   8.381 -            regs->eip += nextbyte - eip + 2;
   8.382 +                : "0" (iw), "b" (mw) );
   8.383          }
   8.384          else
   8.385          {
   8.386 -            rl = (rb & 0x80) ? (rb | ~0xff) : rb;
   8.387 +            il = (u32)(s32)(s8)ib;
   8.388              if ( __get_user(ml, (u32 *)mem) )
   8.389                  goto page_fault_r;
   8.390              __asm__ __volatile__ (
   8.391                  "cmpl %1,%2 ; pushf ; popl %0"
   8.392                  : "=a" (eflags)
   8.393 -                : "0" (rl), "b" (ml) );
   8.394 +                : "0" (il), "b" (ml) );
   8.395          }
   8.396          regs->eflags &= ~0x8d5;     /* OF,SF,ZF,AF,PF,CF */
   8.397          regs->eflags |= eflags & 0x8d5;
   8.398 -        regs->eip += nextbyte - eip + 1;
   8.399          break;
   8.400      case 0x38: /* cmpb r,r/m */
   8.401      case 0x3a: /* cmpb r/m,r */
   8.402 @@ -481,7 +464,6 @@ int gpf_emulate_4gb(struct pt_regs *regs
   8.403              : "0" ((b==0x38)?rb:mb), "b" ((b==0x38)?mb:rb) );
   8.404          regs->eflags &= ~0x8d5;     /* OF,SF,ZF,AF,PF,CF */
   8.405          regs->eflags |= eflags & 0x8d5;
   8.406 -        regs->eip += nextbyte - eip;
   8.407          break;
   8.408      case 0x39: /* cmpl r,r/m */
   8.409      case 0x3b: /* cmpl r/m,r */
   8.410 @@ -507,24 +489,23 @@ int gpf_emulate_4gb(struct pt_regs *regs
   8.411          }
   8.412          regs->eflags &= ~0x8d5;     /* OF,SF,ZF,AF,PF,CF */
   8.413          regs->eflags |= eflags & 0x8d5;
   8.414 -        regs->eip += nextbyte - eip;
   8.415          break;
   8.416      default:
   8.417          DPRINTK("Unhandleable opcode byte %02x\n", b);
   8.418          goto undecodeable;
   8.419      }
   8.420  
   8.421 +    /* Success! */
   8.422 +    regs->eip += pb - eip;
   8.423      perfc_incrc(emulations);
   8.424 -
   8.425 -    /* Success! */
   8.426      return 1;
   8.427  
   8.428   undecodeable:
   8.429 -    printk("Undecodable instruction %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
   8.430 -           "caused GPF(0) at %04x:%08lx\n",
   8.431 -           eip[0], eip[1], eip[2], eip[3],
   8.432 -           eip[4], eip[5], eip[6], eip[7],
   8.433 -           regs->xcs, regs->eip);
   8.434 +    DPRINTK("Undecodable instruction %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
   8.435 +            "caused GPF(0) at %04x:%08lx\n",
   8.436 +            eip[0], eip[1], eip[2], eip[3],
   8.437 +            eip[4], eip[5], eip[6], eip[7],
   8.438 +            regs->xcs, regs->eip);
   8.439      return 0;
   8.440  
   8.441   page_fault_w: