mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
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
This commit is contained in:
commit
e17fa59f09
8 files changed
+170
-162
No files matched your search
@@ -80,7 +80,6 @@
|
||||
3e5a4e65ibVQmwlOn0j3sVH_j_6hAg linux-2.4.26-xen-sparse/arch/xen/kernel/evtchn.c
|
||||
3e5a4e65Hy_1iUvMTPsNqGNXd9uFpg linux-2.4.26-xen-sparse/arch/xen/kernel/head.S
|
||||
3e5a4e65RMGcuA-HCn3-wNx3fFQwdg linux-2.4.26-xen-sparse/arch/xen/kernel/i386_ksyms.c
|
||||
3e5a4e65MEvZhlr070sK5JsfAQlv7Q linux-2.4.26-xen-sparse/arch/xen/kernel/ioport.c
|
||||
3e5a4e653U6cELGv528IxOLHvCq8iA linux-2.4.26-xen-sparse/arch/xen/kernel/irq.c
|
||||
3e5a4e65muT6SU3ck47IP87Q7Ti5hA linux-2.4.26-xen-sparse/arch/xen/kernel/ldt.c
|
||||
4051db84bZeRX7a_Kh6VyyDuT5FOIg linux-2.4.26-xen-sparse/arch/xen/kernel/pci-dma.c
|
||||
@@ -164,6 +163,7 @@
|
||||
40f56238xFQe9T7M_U_FItM-bZIpLw linux-2.6.7-xen-sparse/arch/xen/i386/kernel/evtchn.c
|
||||
40f56238bnvciAuyzAiMkdzGErYt1A linux-2.6.7-xen-sparse/arch/xen/i386/kernel/head.S
|
||||
40f58a0d31M2EkuPbG94ns_nOi0PVA linux-2.6.7-xen-sparse/arch/xen/i386/kernel/i386_ksyms.c
|
||||
40faa751_zbZlAmLyQgCXdYekVFdWA linux-2.6.7-xen-sparse/arch/xen/i386/kernel/ioport.c
|
||||
40f562382aC3_Gt4RG-4ZsfvDRUg3Q linux-2.6.7-xen-sparse/arch/xen/i386/kernel/irq.c
|
||||
40f56238ue3YRsK52HG7iccNzP1AwQ linux-2.6.7-xen-sparse/arch/xen/i386/kernel/ldt.c
|
||||
40f56238a8iOVDEoostsbun_sy2i4g linux-2.6.7-xen-sparse/arch/xen/i386/kernel/process.c
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <asm/hypervisor-ifs/dom0_ops.h>
|
||||
|
||||
|
||||
asmlinkage int sys_iopl(unsigned int new_io_pl)
|
||||
{
|
||||
unsigned int old_io_pl = current->thread.io_pl;
|
||||
dom0_op_t op;
|
||||
|
||||
if ( !(start_info.flags & SIF_PRIVILEGED) )
|
||||
return -EPERM;
|
||||
|
||||
if ( new_io_pl > 3 )
|
||||
return -EINVAL;
|
||||
|
||||
/* Need "raw I/O" privileges for direct port access. */
|
||||
if ( (new_io_pl > old_io_pl) && !capable(CAP_SYS_RAWIO) )
|
||||
return -EPERM;
|
||||
|
||||
/* Maintain OS privileges even if user attempts to relinquish them. */
|
||||
if ( (new_io_pl == 0) && (start_info.flags & SIF_PRIVILEGED) )
|
||||
new_io_pl = 1;
|
||||
|
||||
/* Change our version of the privilege levels. */
|
||||
current->thread.io_pl = new_io_pl;
|
||||
|
||||
/* Force the change at ring 0. */
|
||||
op.cmd = DOM0_IOPL;
|
||||
op.u.iopl.domain = DOMID_SELF;
|
||||
op.u.iopl.iopl = new_io_pl;
|
||||
HYPERVISOR_dom0_op(&op);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
|
||||
{
|
||||
printk(KERN_INFO "ioperm not fully supported - %s\n",
|
||||
turn_on ? "set iopl to 3" : "ignore resource release");
|
||||
return turn_on ? sys_iopl(3) : 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -209,6 +209,7 @@ ln -sf ../../i386/kernel/pci-i386.h
|
||||
ln -sf ../../i386/kernel/ptrace.c
|
||||
ln -sf ../../i386/kernel/semaphore.c
|
||||
ln -sf ../../i386/kernel/sys_i386.c
|
||||
ln -sf ../../../${LINUX_26}/arch/xen/i386/kernel/ioport.c
|
||||
cd ../lib
|
||||
ln -sf ../../i386/lib/checksum.S
|
||||
ln -sf ../../i386/lib/dec_and_lock.c
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/hypervisor-ifs/dom0_ops.h>
|
||||
|
||||
asmlinkage long sys_iopl(unsigned int new_io_pl)
|
||||
{
|
||||
unsigned int old_io_pl = current->thread.io_pl;
|
||||
dom0_op_t op;
|
||||
|
||||
if (!(start_info.flags & SIF_PRIVILEGED))
|
||||
return -EPERM;
|
||||
|
||||
if (new_io_pl > 3)
|
||||
return -EINVAL;
|
||||
|
||||
/* Need "raw I/O" privileges for direct port access. */
|
||||
if ((new_io_pl > old_io_pl) && !capable(CAP_SYS_RAWIO))
|
||||
return -EPERM;
|
||||
|
||||
/* Maintain OS privileges even if user attempts to relinquish them. */
|
||||
if (new_io_pl == 0)
|
||||
new_io_pl = 1;
|
||||
|
||||
/* Change our version of the privilege levels. */
|
||||
current->thread.io_pl = new_io_pl;
|
||||
|
||||
/* Force the change at ring 0. */
|
||||
op.cmd = DOM0_IOPL;
|
||||
op.u.iopl.domain = DOMID_SELF;
|
||||
op.u.iopl.iopl = new_io_pl;
|
||||
HYPERVISOR_dom0_op(&op);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
|
||||
{
|
||||
printk(KERN_INFO "ioperm not fully supported - %s\n",
|
||||
turn_on ? "set iopl to 3" : "ignore resource release");
|
||||
return turn_on ? sys_iopl(3) : 0;
|
||||
}
|
||||
@@ -338,6 +338,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
|
||||
struct pt_regs * childregs;
|
||||
struct task_struct *tsk;
|
||||
int err;
|
||||
unsigned long eflags;
|
||||
|
||||
childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
|
||||
struct_cpy(childregs, regs);
|
||||
@@ -386,6 +387,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
|
||||
desc->b = LDT_entry_b(&info);
|
||||
}
|
||||
|
||||
|
||||
__asm__ __volatile__ ( "pushfl; popl %0" : "=r" (eflags) : );
|
||||
p->thread.io_pl = (eflags >> 12) & 3;
|
||||
|
||||
err = 0;
|
||||
out:
|
||||
if (err && p->thread.io_bitmap_ptr)
|
||||
@@ -532,6 +537,14 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
|
||||
*/
|
||||
load_TLS(next, cpu);
|
||||
|
||||
if (start_info.flags & SIF_PRIVILEGED) {
|
||||
dom0_op_t op;
|
||||
op.cmd = DOM0_IOPL;
|
||||
op.u.iopl.domain = DOMID_SELF;
|
||||
op.u.iopl.iopl = next->io_pl;
|
||||
HYPERVISOR_dom0_op(&op);
|
||||
}
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
/*
|
||||
|
||||
@@ -1206,6 +1206,17 @@ void __init setup_arch(char **cmdline_p)
|
||||
conswitchp = &dummy_con;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* If we are a privileged guest OS then we should request IO privs. */
|
||||
if (start_info.flags & SIF_PRIVILEGED) {
|
||||
dom0_op_t op;
|
||||
op.cmd = DOM0_IOPL;
|
||||
op.u.iopl.domain = DOMID_SELF;
|
||||
op.u.iopl.iopl = 1;
|
||||
if (HYPERVISOR_dom0_op(&op) != 0)
|
||||
panic("Unable to obtain IOPL, despite SIF_PRIVILEGED");
|
||||
current->thread.io_pl = 1;
|
||||
}
|
||||
}
|
||||
|
||||
#include "setup_arch_post.h"
|
||||
|
||||
@@ -422,6 +422,7 @@ struct thread_struct {
|
||||
unsigned long esp;
|
||||
unsigned long fs;
|
||||
unsigned long gs;
|
||||
unsigned int io_pl;
|
||||
/* Hardware debugging registers */
|
||||
unsigned long debugreg[8]; /* %%db0-7 debug registers */
|
||||
/* fault info */
|
||||
|
||||
+94
-113
@@ -30,6 +30,15 @@
|
||||
#include <xen/perfc.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
/*
|
||||
* Obtain the base and limit associated with the given segment selector.
|
||||
* The selector must identify a 32-bit code or data segment. Any segment that
|
||||
* appears to be truncated to not overlap with Xen is assumed to be a truncated
|
||||
* 4GB segment, and the returned limit reflects this.
|
||||
* @seg (IN) : Segment selector to decode.
|
||||
* @base (OUT): Decoded linear base address.
|
||||
* @limit (OUT): Decoded segment limit, in bytes. 0 == unlimited (4GB).
|
||||
*/
|
||||
int get_baselimit(u16 seg, unsigned long *base, unsigned long *limit)
|
||||
{
|
||||
struct domain *d = current;
|
||||
@@ -80,6 +89,7 @@ int get_baselimit(u16 seg, unsigned long *base, unsigned long *limit)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Turn a segment+offset into a linear address. */
|
||||
int linearise_address(u16 seg, unsigned long off, unsigned long *linear)
|
||||
{
|
||||
unsigned long base, limit;
|
||||
@@ -95,6 +105,7 @@ int linearise_address(u16 seg, unsigned long off, unsigned long *linear)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Decode Reg field of a ModRM byte: return a pointer into a register block. */
|
||||
void *decode_reg(struct pt_regs *regs, u8 b)
|
||||
{
|
||||
switch ( b & 7 )
|
||||
@@ -120,6 +131,9 @@ void *decode_reg(struct pt_regs *regs, u8 b)
|
||||
* @pseg (IN) : address in pt_regs block of the override segment.
|
||||
* @regs (IN) : addrress of the the pt_regs block.
|
||||
*/
|
||||
#define DECODE_EA_FAILED 0
|
||||
#define DECODE_EA_FIXME 1
|
||||
#define DECODE_EA_SUCCESS 2
|
||||
int decode_effective_address(u8 **ppb, void **preg, void **pmem,
|
||||
unsigned int *pseg, struct pt_regs *regs)
|
||||
{
|
||||
@@ -132,7 +146,7 @@ int decode_effective_address(u8 **ppb, void **preg, void **pmem,
|
||||
if ( get_user(modrm, pb) )
|
||||
{
|
||||
DPRINTK("Fault while extracting modrm byte\n");
|
||||
return 0;
|
||||
return DECODE_EA_FAILED;
|
||||
}
|
||||
|
||||
pb++;
|
||||
@@ -144,7 +158,7 @@ int decode_effective_address(u8 **ppb, void **preg, void **pmem,
|
||||
if ( rm == 4 )
|
||||
{
|
||||
DPRINTK("FIXME: Add decoding for the SIB byte.\n");
|
||||
return 0;
|
||||
return DECODE_EA_FIXME;
|
||||
}
|
||||
|
||||
/* Decode Reg and R/M fields. */
|
||||
@@ -164,7 +178,7 @@ int decode_effective_address(u8 **ppb, void **preg, void **pmem,
|
||||
if ( get_user(disp32, (u32 *)pb) )
|
||||
{
|
||||
DPRINTK("Fault while extracting <disp8>.\n");
|
||||
return 0;
|
||||
return DECODE_EA_FAILED;
|
||||
}
|
||||
pb += 4;
|
||||
}
|
||||
@@ -176,7 +190,7 @@ int decode_effective_address(u8 **ppb, void **preg, void **pmem,
|
||||
if ( get_user(disp8, pb) )
|
||||
{
|
||||
DPRINTK("Fault while extracting <disp8>.\n");
|
||||
return 0;
|
||||
return DECODE_EA_FAILED;
|
||||
}
|
||||
pb++;
|
||||
disp32 = (disp8 & 0x80) ? (disp8 | ~0xff) : disp8;;
|
||||
@@ -188,22 +202,22 @@ int decode_effective_address(u8 **ppb, void **preg, void **pmem,
|
||||
if ( get_user(disp32, (u32 *)pb) )
|
||||
{
|
||||
DPRINTK("Fault while extracting <disp8>.\n");
|
||||
return 0;
|
||||
return DECODE_EA_FAILED;
|
||||
}
|
||||
pb += 4;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
DPRINTK("Not a memory operand!\n");
|
||||
return 0;
|
||||
return DECODE_EA_FAILED;
|
||||
}
|
||||
|
||||
if ( !get_baselimit((u16)(*pseg), &ea, &limit) )
|
||||
return 0;
|
||||
return DECODE_EA_FAILED;
|
||||
if ( limit != 0 )
|
||||
{
|
||||
DPRINTK("Bailing: not a 4GB data segment.\n");
|
||||
return 0;
|
||||
return DECODE_EA_FAILED;
|
||||
}
|
||||
|
||||
offset = disp32;
|
||||
@@ -212,23 +226,42 @@ int decode_effective_address(u8 **ppb, void **preg, void **pmem,
|
||||
if ( (offset & 0xf0000000) != 0xf0000000 )
|
||||
{
|
||||
DPRINTK("Bailing: not a -ve offset into 4GB segment.\n");
|
||||
return 0;
|
||||
return DECODE_EA_FAILED;
|
||||
}
|
||||
|
||||
ea += offset;
|
||||
if ( ea > (PAGE_OFFSET - PAGE_SIZE) )
|
||||
{
|
||||
DPRINTK("!!!! DISALLOWING UNSAFE ACCESS !!!!\n");
|
||||
return 0;
|
||||
return DECODE_EA_FAILED;
|
||||
}
|
||||
|
||||
*ppb = pb;
|
||||
*preg = regreg;
|
||||
*pmem = (void *)ea;
|
||||
|
||||
return 1;
|
||||
return DECODE_EA_SUCCESS;
|
||||
}
|
||||
|
||||
#define GET_IMM8 \
|
||||
if ( get_user(ib, (u8 *)pb) ) { \
|
||||
DPRINTK("Fault while extracting imm8\n"); \
|
||||
return 0; \
|
||||
} \
|
||||
pb += 1;
|
||||
#define GET_IMM16 \
|
||||
if ( get_user(iw, (u8 *)pb) ) { \
|
||||
DPRINTK("Fault while extracting imm16\n"); \
|
||||
return 0; \
|
||||
} \
|
||||
pb += 2;
|
||||
#define GET_IMM32 \
|
||||
if ( get_user(il, (u32 *)pb) ) { \
|
||||
DPRINTK("Fault while extracting imm32\n"); \
|
||||
return 0; \
|
||||
} \
|
||||
pb += 4;
|
||||
|
||||
/*
|
||||
* Called from the general-protection fault handler to attempt to decode
|
||||
* and emulate an instruction that depends on 4GB segments. At this point
|
||||
@@ -239,15 +272,18 @@ int gpf_emulate_4gb(struct pt_regs *regs)
|
||||
{
|
||||
struct domain *d = current;
|
||||
trap_info_t *ti;
|
||||
u8 *eip, *nextbyte, b, mb, rb;
|
||||
u16 mw, rw;
|
||||
u32 ml, rl, eflags;
|
||||
unsigned int *pseg = NULL;
|
||||
int i;
|
||||
int opsz_override = 0;
|
||||
void *reg, *mem;
|
||||
struct guest_trap_bounce *gtb;
|
||||
|
||||
u8 *eip; /* ptr to instruction start */
|
||||
u8 *pb, b; /* ptr into instr. / current instr. byte */
|
||||
u8 ib, mb, rb; /* byte operand from imm/register/memory */
|
||||
u16 iw, mw, rw; /* word operand from imm/register/memory */
|
||||
u32 il, ml, rl; /* long operand from imm/register/memory */
|
||||
void *reg, *mem; /* ptr to register/memory operand */
|
||||
unsigned int *pseg = NULL; /* segment for memory operand (NULL=default) */
|
||||
u32 eflags;
|
||||
int opsz_override = 0;
|
||||
|
||||
if ( !linearise_address((u16)regs->xcs, regs->eip, (unsigned long *)&eip) )
|
||||
{
|
||||
DPRINTK("Cannot linearise %04x:%08lx\n", regs->xcs, regs->eip);
|
||||
@@ -255,11 +291,11 @@ int gpf_emulate_4gb(struct pt_regs *regs)
|
||||
}
|
||||
|
||||
/* Parse prefix bytes. We're basically looking for segment override. */
|
||||
for ( i = 0; i < 4; i++ )
|
||||
for ( pb = eip; (pb - eip) < 4; pb++ )
|
||||
{
|
||||
if ( get_user(b, &eip[i]) )
|
||||
if ( get_user(b, pb) )
|
||||
{
|
||||
DPRINTK("Fault while accessing byte %d of instruction\n", i);
|
||||
DPRINTK("Fault while accessing byte %d of instruction\n", pb-eip);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -298,141 +334,94 @@ int gpf_emulate_4gb(struct pt_regs *regs)
|
||||
}
|
||||
done_prefix:
|
||||
|
||||
nextbyte = &eip[i+1];
|
||||
if ( !decode_effective_address(&nextbyte, ®, &mem, pseg, regs) )
|
||||
pb++; /* skip opcode byte */
|
||||
switch ( decode_effective_address(&pb, ®, &mem, pseg, regs) )
|
||||
{
|
||||
case DECODE_EA_FAILED:
|
||||
return 0;
|
||||
case DECODE_EA_FIXME:
|
||||
goto undecodeable;
|
||||
}
|
||||
|
||||
/* Only handle single-byte opcodes right now. Sufficient for MOV. */
|
||||
/*
|
||||
* XXX Now I see how this decode routine is panning out, it needs
|
||||
* refactoring. Lots of duplicated cruft in here...
|
||||
*/
|
||||
switch ( b )
|
||||
{
|
||||
case 0x88: /* movb r,r/m */
|
||||
if ( __put_user(*(u8 *)reg, (u8 *)mem) )
|
||||
goto page_fault_w;
|
||||
regs->eip += nextbyte - eip;
|
||||
break;
|
||||
case 0x89: /* movl r,r/m */
|
||||
if ( opsz_override )
|
||||
{
|
||||
if ( __put_user(*(u16 *)reg, (u16 *)mem) )
|
||||
goto page_fault_w;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( __put_user(*(u32 *)reg, (u32 *)mem) )
|
||||
goto page_fault_w;
|
||||
}
|
||||
regs->eip += nextbyte - eip;
|
||||
if ( opsz_override ? __put_user(*(u16 *)reg, (u16 *)mem)
|
||||
: __put_user(*(u32 *)reg, (u32 *)mem) )
|
||||
goto page_fault_w;
|
||||
break;
|
||||
case 0x8a: /* movb r/m,r */
|
||||
if ( __get_user(*(u8 *)reg, (u8 *)mem) )
|
||||
goto page_fault_r;
|
||||
regs->eip += nextbyte - eip;
|
||||
break;
|
||||
case 0x8b: /* movl r/m,r */
|
||||
if ( opsz_override )
|
||||
{
|
||||
if ( __get_user(*(u16 *)reg, (u16 *)mem) )
|
||||
goto page_fault_r;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( __get_user(*(u32 *)reg, (u32 *)mem) )
|
||||
goto page_fault_r;
|
||||
}
|
||||
regs->eip += nextbyte - eip;
|
||||
if ( opsz_override ? __get_user(*(u16 *)reg, (u16 *)mem)
|
||||
: __get_user(*(u32 *)reg, (u32 *)mem) )
|
||||
goto page_fault_r;
|
||||
break;
|
||||
case 0xc6: /* movb imm,r/m */
|
||||
if ( reg != ®s->eax ) /* Reg == /0 */
|
||||
goto undecodeable;
|
||||
if ( get_user(rb, nextbyte) )
|
||||
{
|
||||
DPRINTK("Fault while extracting immediate byte\n");
|
||||
return 0;
|
||||
}
|
||||
if ( __put_user(rb, (u8 *)mem) )
|
||||
GET_IMM8;
|
||||
if ( __put_user(ib, (u8 *)mem) )
|
||||
goto page_fault_w;
|
||||
regs->eip += nextbyte - eip + 1;
|
||||
break;
|
||||
case 0xc7: /* movl imm,r/m */
|
||||
if ( reg != ®s->eax ) /* Reg == /0 */
|
||||
goto undecodeable;
|
||||
if ( opsz_override )
|
||||
{
|
||||
if ( get_user(rw, (u16 *)nextbyte) )
|
||||
{
|
||||
DPRINTK("Fault while extracting immediate word\n");
|
||||
return 0;
|
||||
}
|
||||
if ( __put_user(rw, (u16 *)mem) )
|
||||
GET_IMM16;
|
||||
if ( __put_user(iw, (u16 *)mem) )
|
||||
goto page_fault_w;
|
||||
regs->eip += nextbyte - eip + 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( get_user(rl, (u32 *)nextbyte) )
|
||||
{
|
||||
DPRINTK("Fault while extracting immediate longword\n");
|
||||
return 0;
|
||||
}
|
||||
if ( __put_user(rl, (u32 *)mem) )
|
||||
GET_IMM32;
|
||||
if ( __put_user(il, (u32 *)mem) )
|
||||
goto page_fault_w;
|
||||
regs->eip += nextbyte - eip + 4;
|
||||
}
|
||||
break;
|
||||
case 0x80: /* cmpb imm8,r/m */
|
||||
if ( reg != ®s->edi ) /* Reg == /7 */
|
||||
goto undecodeable;
|
||||
if ( get_user(rb, nextbyte) )
|
||||
{
|
||||
DPRINTK("Fault while extracting immediate byte\n");
|
||||
return 0;
|
||||
}
|
||||
GET_IMM8;
|
||||
if ( __get_user(mb, (u8 *)mem) )
|
||||
goto page_fault_r;
|
||||
__asm__ __volatile__ (
|
||||
"cmpb %b1,%b2 ; pushf ; popl %0"
|
||||
: "=a" (eflags)
|
||||
: "0" (rb), "b" (mb) );
|
||||
: "0" (ib), "b" (mb) );
|
||||
regs->eflags &= ~0x8d5; /* OF,SF,ZF,AF,PF,CF */
|
||||
regs->eflags |= eflags & 0x8d5;
|
||||
regs->eip += nextbyte - eip + 1;
|
||||
break;
|
||||
case 0x81: /* cmpl imm32,r/m */
|
||||
if ( reg != ®s->edi ) /* Reg == /7 */
|
||||
goto undecodeable;
|
||||
if ( opsz_override )
|
||||
{
|
||||
if ( get_user(rw, (u16 *)nextbyte) )
|
||||
{
|
||||
DPRINTK("Fault while extracting immediate word\n");
|
||||
return 0;
|
||||
}
|
||||
GET_IMM16;
|
||||
if ( __get_user(mw, (u16 *)mem) )
|
||||
goto page_fault_r;
|
||||
__asm__ __volatile__ (
|
||||
"cmpw %w1,%w2 ; pushf ; popl %0"
|
||||
: "=a" (eflags)
|
||||
: "0" (rw), "b" (mw) );
|
||||
regs->eip += nextbyte - eip + 2;
|
||||
: "0" (iw), "b" (mw) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( get_user(rl, (u32 *)nextbyte) )
|
||||
{
|
||||
DPRINTK("Fault while extracting immediate longword\n");
|
||||
return 0;
|
||||
}
|
||||
GET_IMM32;
|
||||
if ( __get_user(ml, (u32 *)mem) )
|
||||
goto page_fault_r;
|
||||
__asm__ __volatile__ (
|
||||
"cmpl %1,%2 ; pushf ; popl %0"
|
||||
: "=a" (eflags)
|
||||
: "0" (rl), "b" (ml) );
|
||||
regs->eip += nextbyte - eip + 4;
|
||||
: "0" (il), "b" (ml) );
|
||||
}
|
||||
regs->eflags &= ~0x8d5; /* OF,SF,ZF,AF,PF,CF */
|
||||
regs->eflags |= eflags & 0x8d5;
|
||||
@@ -440,35 +429,29 @@ int gpf_emulate_4gb(struct pt_regs *regs)
|
||||
case 0x83: /* cmpl imm8,r/m */
|
||||
if ( reg != ®s->edi ) /* Reg == /7 */
|
||||
goto undecodeable;
|
||||
if ( get_user(rb, nextbyte) )
|
||||
{
|
||||
DPRINTK("Fault while extracting immediate byte\n");
|
||||
return 0;
|
||||
}
|
||||
GET_IMM8;
|
||||
if ( opsz_override )
|
||||
{
|
||||
rw = (rb & 0x80) ? (rb | ~0xff) : rb;
|
||||
iw = (u16)(s16)(s8)ib;
|
||||
if ( __get_user(mw, (u16 *)mem) )
|
||||
goto page_fault_r;
|
||||
__asm__ __volatile__ (
|
||||
"cmpw %w1,%w2 ; pushf ; popl %0"
|
||||
: "=a" (eflags)
|
||||
: "0" (rw), "b" (mw) );
|
||||
regs->eip += nextbyte - eip + 2;
|
||||
: "0" (iw), "b" (mw) );
|
||||
}
|
||||
else
|
||||
{
|
||||
rl = (rb & 0x80) ? (rb | ~0xff) : rb;
|
||||
il = (u32)(s32)(s8)ib;
|
||||
if ( __get_user(ml, (u32 *)mem) )
|
||||
goto page_fault_r;
|
||||
__asm__ __volatile__ (
|
||||
"cmpl %1,%2 ; pushf ; popl %0"
|
||||
: "=a" (eflags)
|
||||
: "0" (rl), "b" (ml) );
|
||||
: "0" (il), "b" (ml) );
|
||||
}
|
||||
regs->eflags &= ~0x8d5; /* OF,SF,ZF,AF,PF,CF */
|
||||
regs->eflags |= eflags & 0x8d5;
|
||||
regs->eip += nextbyte - eip + 1;
|
||||
break;
|
||||
case 0x38: /* cmpb r,r/m */
|
||||
case 0x3a: /* cmpb r/m,r */
|
||||
@@ -481,7 +464,6 @@ int gpf_emulate_4gb(struct pt_regs *regs)
|
||||
: "0" ((b==0x38)?rb:mb), "b" ((b==0x38)?mb:rb) );
|
||||
regs->eflags &= ~0x8d5; /* OF,SF,ZF,AF,PF,CF */
|
||||
regs->eflags |= eflags & 0x8d5;
|
||||
regs->eip += nextbyte - eip;
|
||||
break;
|
||||
case 0x39: /* cmpl r,r/m */
|
||||
case 0x3b: /* cmpl r/m,r */
|
||||
@@ -507,24 +489,23 @@ int gpf_emulate_4gb(struct pt_regs *regs)
|
||||
}
|
||||
regs->eflags &= ~0x8d5; /* OF,SF,ZF,AF,PF,CF */
|
||||
regs->eflags |= eflags & 0x8d5;
|
||||
regs->eip += nextbyte - eip;
|
||||
break;
|
||||
default:
|
||||
DPRINTK("Unhandleable opcode byte %02x\n", b);
|
||||
goto undecodeable;
|
||||
}
|
||||
|
||||
perfc_incrc(emulations);
|
||||
|
||||
/* Success! */
|
||||
regs->eip += pb - eip;
|
||||
perfc_incrc(emulations);
|
||||
return 1;
|
||||
|
||||
undecodeable:
|
||||
printk("Undecodable instruction %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
|
||||
"caused GPF(0) at %04x:%08lx\n",
|
||||
eip[0], eip[1], eip[2], eip[3],
|
||||
eip[4], eip[5], eip[6], eip[7],
|
||||
regs->xcs, regs->eip);
|
||||
DPRINTK("Undecodable instruction %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
|
||||
"caused GPF(0) at %04x:%08lx\n",
|
||||
eip[0], eip[1], eip[2], eip[3],
|
||||
eip[4], eip[5], eip[6], eip[7],
|
||||
regs->xcs, regs->eip);
|
||||
return 0;
|
||||
|
||||
page_fault_w:
|
||||
|
||||