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
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, ®, &mem, pseg, regs) ) 8.200 + pb++; /* skip opcode byte */ 8.201 + switch ( decode_effective_address(&pb, ®, &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 != ®s->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 != ®s->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 != ®s->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 != ®s->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 != ®s->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: