[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [XEN] Clean up page-fault propagation when acessing guest addresses.
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Node ID af9809f51f81a3c43f276f00c81a52ef558afda4 # Parent a70c4f9657cc2a9606ea37650b351e222527d72f [XEN] Clean up page-fault propagation when acessing guest addresses. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- xen/arch/x86/mm.c | 8 ++-- xen/arch/x86/traps.c | 87 +++++++++++++++++++++++---------------------- xen/arch/x86/x86_emulate.c | 19 ++++++--- 3 files changed, 63 insertions(+), 51 deletions(-) diff -r a70c4f9657cc -r af9809f51f81 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Wed Jul 12 19:16:14 2006 +0100 +++ b/xen/arch/x86/mm.c Thu Jul 13 09:55:14 2006 +0100 @@ -3386,13 +3386,13 @@ static int ptwr_emulated_update( if ( bytes != sizeof(paddr_t) ) { paddr_t full; - unsigned int offset = addr & (sizeof(paddr_t)-1); + unsigned int rc, offset = addr & (sizeof(paddr_t)-1); /* Align address; read full word. */ addr &= ~(sizeof(paddr_t)-1); - if ( copy_from_user(&full, (void *)addr, sizeof(paddr_t)) ) - { - propagate_page_fault(addr, 0); /* read fault */ + if ( (rc = copy_from_user(&full, (void *)addr, sizeof(paddr_t))) != 0 ) + { + propagate_page_fault(addr+sizeof(paddr_t)-rc, 0); /* read fault */ return X86EMUL_PROPAGATE_FAULT; } /* Mask out bits provided by caller. */ diff -r a70c4f9657cc -r af9809f51f81 xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c Wed Jul 12 19:16:14 2006 +0100 +++ b/xen/arch/x86/traps.c Thu Jul 13 09:55:14 2006 +0100 @@ -403,16 +403,16 @@ static inline int do_trap(int trapnr, ch return 0; } -#define DO_ERROR_NOCODE(trapnr, str, name) \ -asmlinkage int do_##name(struct cpu_user_regs *regs) \ -{ \ - return do_trap(trapnr, str, regs, 0); \ -} - -#define DO_ERROR(trapnr, str, name) \ -asmlinkage int do_##name(struct cpu_user_regs *regs) \ -{ \ - return do_trap(trapnr, str, regs, 1); \ +#define DO_ERROR_NOCODE(trapnr, str, name) \ +asmlinkage int do_##name(struct cpu_user_regs *regs) \ +{ \ + return do_trap(trapnr, str, regs, 0); \ +} + +#define DO_ERROR(trapnr, str, name) \ +asmlinkage int do_##name(struct cpu_user_regs *regs) \ +{ \ + return do_trap(trapnr, str, regs, 1); \ } DO_ERROR_NOCODE( 0, "divide error", divide_error) @@ -449,9 +449,9 @@ int cpuid_hypervisor_leaves( static int emulate_forced_invalid_op(struct cpu_user_regs *regs) { - char signature[5], instr[2]; + char sig[5], instr[2]; uint32_t a, b, c, d; - unsigned long eip; + unsigned long eip, rc; a = regs->eax; b = regs->ebx; @@ -460,14 +460,22 @@ static int emulate_forced_invalid_op(str eip = regs->eip; /* Check for forced emulation signature: ud2 ; .ascii "xen". */ - if ( copy_from_user(signature, (char *)eip, sizeof(signature)) || - memcmp(signature, "\xf\xbxen", sizeof(signature)) ) + if ( (rc = copy_from_user(sig, (char *)eip, sizeof(sig))) != 0 ) + { + propagate_page_fault(eip + sizeof(sig) - rc, 0); + return EXCRET_fault_fixed; + } + if ( memcmp(sig, "\xf\xbxen", sizeof(sig)) ) return 0; - eip += sizeof(signature); + eip += sizeof(sig); /* We only emulate CPUID. */ - if ( copy_from_user(instr, (char *)eip, sizeof(instr)) || - memcmp(instr, "\xf\xa2", sizeof(instr)) ) + if ( ( rc = copy_from_user(instr, (char *)eip, sizeof(instr))) != 0 ) + { + propagate_page_fault(eip + sizeof(instr) - rc, 0); + return EXCRET_fault_fixed; + } + if ( memcmp(instr, "\xf\xa2", sizeof(instr)) ) return 0; eip += sizeof(instr); @@ -923,17 +931,14 @@ static inline int admin_io_okay( #define outl_user(_v, _p, _d, _r) \ (admin_io_okay(_p, 4, _d, _r) ? outl(_v, _p) : ((void)0)) -/* Propagate a fault back to the guest kernel. */ -#define PAGE_FAULT(_faultaddr, _errcode) \ -({ propagate_page_fault(_faultaddr, _errcode); \ - return EXCRET_fault_fixed; \ -}) - -/* Isntruction fetch with error handling. */ -#define insn_fetch(_type, _size, _ptr) \ -({ unsigned long _x; \ - if ( get_user(_x, (_type *)eip) ) \ - PAGE_FAULT(eip, 0); /* read fault */ \ +/* Instruction fetch with error handling. */ +#define insn_fetch(_type, _size, _ptr) \ +({ unsigned long _rc, _x; \ + if ( (_rc = copy_from_user(&_x, (_type *)eip, sizeof(_type))) != 0 ) \ + { \ + propagate_page_fault(eip + sizeof(_type) - _rc, 0); \ + return EXCRET_fault_fixed; \ + } \ eip += _size; (_type)_x; }) static int emulate_privileged_op(struct cpu_user_regs *regs) @@ -941,7 +946,7 @@ static int emulate_privileged_op(struct struct vcpu *v = current; unsigned long *reg, eip = regs->eip, res; u8 opcode, modrm_reg = 0, modrm_rm = 0, rep_prefix = 0; - unsigned int port, i, op_bytes = 4, data; + unsigned int port, i, op_bytes = 4, data, rc; u32 l, h; /* Legacy prefixes. */ @@ -1001,19 +1006,19 @@ static int emulate_privileged_op(struct { case 1: data = (u8)inb_user((u16)regs->edx, v, regs); - if ( put_user((u8)data, (u8 *)regs->edi) ) - PAGE_FAULT(regs->edi, PGERR_write_access); break; case 2: data = (u16)inw_user((u16)regs->edx, v, regs); - if ( put_user((u16)data, (u16 *)regs->edi) ) - PAGE_FAULT(regs->edi, PGERR_write_access); break; case 4: data = (u32)inl_user((u16)regs->edx, v, regs); - if ( put_user((u32)data, (u32 *)regs->edi) ) - PAGE_FAULT(regs->edi, PGERR_write_access); break; + } + if ( (rc = copy_to_user((void *)regs->edi, &data, op_bytes)) != 0 ) + { + propagate_page_fault(regs->edi + op_bytes - rc, + PGERR_write_access); + return EXCRET_fault_fixed; } regs->edi += (int)((regs->eflags & EF_DF) ? -op_bytes : op_bytes); break; @@ -1023,21 +1028,21 @@ static int emulate_privileged_op(struct case 0x6f: /* OUTSW/OUTSL */ if ( !guest_io_okay((u16)regs->edx, op_bytes, v, regs) ) goto fail; + rc = copy_from_user(&data, (void *)regs->esi, op_bytes); + if ( rc != 0 ) + { + propagate_page_fault(regs->esi + op_bytes - rc, 0); + return EXCRET_fault_fixed; + } switch ( op_bytes ) { case 1: - if ( get_user(data, (u8 *)regs->esi) ) - PAGE_FAULT(regs->esi, 0); /* read fault */ outb_user((u8)data, (u16)regs->edx, v, regs); break; case 2: - if ( get_user(data, (u16 *)regs->esi) ) - PAGE_FAULT(regs->esi, 0); /* read fault */ outw_user((u16)data, (u16)regs->edx, v, regs); break; case 4: - if ( get_user(data, (u32 *)regs->esi) ) - PAGE_FAULT(regs->esi, 0); /* read fault */ outl_user((u32)data, (u16)regs->edx, v, regs); break; } diff -r a70c4f9657cc -r af9809f51f81 xen/arch/x86/x86_emulate.c --- a/xen/arch/x86/x86_emulate.c Wed Jul 12 19:16:14 2006 +0100 +++ b/xen/arch/x86/x86_emulate.c Thu Jul 13 09:55:14 2006 +0100 @@ -1138,12 +1138,16 @@ x86_emulate_read_std( unsigned int bytes, struct x86_emulate_ctxt *ctxt) { + unsigned int rc; + *val = 0; - if ( copy_from_user((void *)val, (void *)addr, bytes) ) - { - propagate_page_fault(addr, 0); /* read fault */ + + if ( (rc = copy_from_user((void *)val, (void *)addr, bytes)) != 0 ) + { + propagate_page_fault(addr + bytes - rc, 0); /* read fault */ return X86EMUL_PROPAGATE_FAULT; } + return X86EMUL_CONTINUE; } @@ -1154,11 +1158,14 @@ x86_emulate_write_std( unsigned int bytes, struct x86_emulate_ctxt *ctxt) { - if ( copy_to_user((void *)addr, (void *)&val, bytes) ) - { - propagate_page_fault(addr, PGERR_write_access); /* write fault */ + unsigned int rc; + + if ( (rc = copy_to_user((void *)addr, (void *)&val, bytes)) != 0 ) + { + propagate_page_fault(addr + bytes - rc, PGERR_write_access); return X86EMUL_PROPAGATE_FAULT; } + return X86EMUL_CONTINUE; } _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |