direct-io.hg
changeset 10676:af9809f51f81
[XEN] Clean up page-fault propagation when acessing guest addresses.
Signed-off-by: Keir Fraser <keir@xensource.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author | kfraser@localhost.localdomain |
---|---|
date | Thu Jul 13 09:55:14 2006 +0100 (2006-07-13) |
parents | a70c4f9657cc |
children | 2937703f0ed0 |
files | xen/arch/x86/mm.c xen/arch/x86/traps.c xen/arch/x86/x86_emulate.c |
line diff
1.1 --- a/xen/arch/x86/mm.c Wed Jul 12 19:16:14 2006 +0100 1.2 +++ b/xen/arch/x86/mm.c Thu Jul 13 09:55:14 2006 +0100 1.3 @@ -3386,13 +3386,13 @@ static int ptwr_emulated_update( 1.4 if ( bytes != sizeof(paddr_t) ) 1.5 { 1.6 paddr_t full; 1.7 - unsigned int offset = addr & (sizeof(paddr_t)-1); 1.8 + unsigned int rc, offset = addr & (sizeof(paddr_t)-1); 1.9 1.10 /* Align address; read full word. */ 1.11 addr &= ~(sizeof(paddr_t)-1); 1.12 - if ( copy_from_user(&full, (void *)addr, sizeof(paddr_t)) ) 1.13 + if ( (rc = copy_from_user(&full, (void *)addr, sizeof(paddr_t))) != 0 ) 1.14 { 1.15 - propagate_page_fault(addr, 0); /* read fault */ 1.16 + propagate_page_fault(addr+sizeof(paddr_t)-rc, 0); /* read fault */ 1.17 return X86EMUL_PROPAGATE_FAULT; 1.18 } 1.19 /* Mask out bits provided by caller. */
2.1 --- a/xen/arch/x86/traps.c Wed Jul 12 19:16:14 2006 +0100 2.2 +++ b/xen/arch/x86/traps.c Thu Jul 13 09:55:14 2006 +0100 2.3 @@ -403,16 +403,16 @@ static inline int do_trap(int trapnr, ch 2.4 return 0; 2.5 } 2.6 2.7 -#define DO_ERROR_NOCODE(trapnr, str, name) \ 2.8 -asmlinkage int do_##name(struct cpu_user_regs *regs) \ 2.9 -{ \ 2.10 - return do_trap(trapnr, str, regs, 0); \ 2.11 +#define DO_ERROR_NOCODE(trapnr, str, name) \ 2.12 +asmlinkage int do_##name(struct cpu_user_regs *regs) \ 2.13 +{ \ 2.14 + return do_trap(trapnr, str, regs, 0); \ 2.15 } 2.16 2.17 -#define DO_ERROR(trapnr, str, name) \ 2.18 -asmlinkage int do_##name(struct cpu_user_regs *regs) \ 2.19 -{ \ 2.20 - return do_trap(trapnr, str, regs, 1); \ 2.21 +#define DO_ERROR(trapnr, str, name) \ 2.22 +asmlinkage int do_##name(struct cpu_user_regs *regs) \ 2.23 +{ \ 2.24 + return do_trap(trapnr, str, regs, 1); \ 2.25 } 2.26 2.27 DO_ERROR_NOCODE( 0, "divide error", divide_error) 2.28 @@ -449,9 +449,9 @@ int cpuid_hypervisor_leaves( 2.29 2.30 static int emulate_forced_invalid_op(struct cpu_user_regs *regs) 2.31 { 2.32 - char signature[5], instr[2]; 2.33 + char sig[5], instr[2]; 2.34 uint32_t a, b, c, d; 2.35 - unsigned long eip; 2.36 + unsigned long eip, rc; 2.37 2.38 a = regs->eax; 2.39 b = regs->ebx; 2.40 @@ -460,14 +460,22 @@ static int emulate_forced_invalid_op(str 2.41 eip = regs->eip; 2.42 2.43 /* Check for forced emulation signature: ud2 ; .ascii "xen". */ 2.44 - if ( copy_from_user(signature, (char *)eip, sizeof(signature)) || 2.45 - memcmp(signature, "\xf\xbxen", sizeof(signature)) ) 2.46 + if ( (rc = copy_from_user(sig, (char *)eip, sizeof(sig))) != 0 ) 2.47 + { 2.48 + propagate_page_fault(eip + sizeof(sig) - rc, 0); 2.49 + return EXCRET_fault_fixed; 2.50 + } 2.51 + if ( memcmp(sig, "\xf\xbxen", sizeof(sig)) ) 2.52 return 0; 2.53 - eip += sizeof(signature); 2.54 + eip += sizeof(sig); 2.55 2.56 /* We only emulate CPUID. */ 2.57 - if ( copy_from_user(instr, (char *)eip, sizeof(instr)) || 2.58 - memcmp(instr, "\xf\xa2", sizeof(instr)) ) 2.59 + if ( ( rc = copy_from_user(instr, (char *)eip, sizeof(instr))) != 0 ) 2.60 + { 2.61 + propagate_page_fault(eip + sizeof(instr) - rc, 0); 2.62 + return EXCRET_fault_fixed; 2.63 + } 2.64 + if ( memcmp(instr, "\xf\xa2", sizeof(instr)) ) 2.65 return 0; 2.66 eip += sizeof(instr); 2.67 2.68 @@ -923,17 +931,14 @@ static inline int admin_io_okay( 2.69 #define outl_user(_v, _p, _d, _r) \ 2.70 (admin_io_okay(_p, 4, _d, _r) ? outl(_v, _p) : ((void)0)) 2.71 2.72 -/* Propagate a fault back to the guest kernel. */ 2.73 -#define PAGE_FAULT(_faultaddr, _errcode) \ 2.74 -({ propagate_page_fault(_faultaddr, _errcode); \ 2.75 - return EXCRET_fault_fixed; \ 2.76 -}) 2.77 - 2.78 -/* Isntruction fetch with error handling. */ 2.79 -#define insn_fetch(_type, _size, _ptr) \ 2.80 -({ unsigned long _x; \ 2.81 - if ( get_user(_x, (_type *)eip) ) \ 2.82 - PAGE_FAULT(eip, 0); /* read fault */ \ 2.83 +/* Instruction fetch with error handling. */ 2.84 +#define insn_fetch(_type, _size, _ptr) \ 2.85 +({ unsigned long _rc, _x; \ 2.86 + if ( (_rc = copy_from_user(&_x, (_type *)eip, sizeof(_type))) != 0 ) \ 2.87 + { \ 2.88 + propagate_page_fault(eip + sizeof(_type) - _rc, 0); \ 2.89 + return EXCRET_fault_fixed; \ 2.90 + } \ 2.91 eip += _size; (_type)_x; }) 2.92 2.93 static int emulate_privileged_op(struct cpu_user_regs *regs) 2.94 @@ -941,7 +946,7 @@ static int emulate_privileged_op(struct 2.95 struct vcpu *v = current; 2.96 unsigned long *reg, eip = regs->eip, res; 2.97 u8 opcode, modrm_reg = 0, modrm_rm = 0, rep_prefix = 0; 2.98 - unsigned int port, i, op_bytes = 4, data; 2.99 + unsigned int port, i, op_bytes = 4, data, rc; 2.100 u32 l, h; 2.101 2.102 /* Legacy prefixes. */ 2.103 @@ -1001,20 +1006,20 @@ static int emulate_privileged_op(struct 2.104 { 2.105 case 1: 2.106 data = (u8)inb_user((u16)regs->edx, v, regs); 2.107 - if ( put_user((u8)data, (u8 *)regs->edi) ) 2.108 - PAGE_FAULT(regs->edi, PGERR_write_access); 2.109 break; 2.110 case 2: 2.111 data = (u16)inw_user((u16)regs->edx, v, regs); 2.112 - if ( put_user((u16)data, (u16 *)regs->edi) ) 2.113 - PAGE_FAULT(regs->edi, PGERR_write_access); 2.114 break; 2.115 case 4: 2.116 data = (u32)inl_user((u16)regs->edx, v, regs); 2.117 - if ( put_user((u32)data, (u32 *)regs->edi) ) 2.118 - PAGE_FAULT(regs->edi, PGERR_write_access); 2.119 break; 2.120 } 2.121 + if ( (rc = copy_to_user((void *)regs->edi, &data, op_bytes)) != 0 ) 2.122 + { 2.123 + propagate_page_fault(regs->edi + op_bytes - rc, 2.124 + PGERR_write_access); 2.125 + return EXCRET_fault_fixed; 2.126 + } 2.127 regs->edi += (int)((regs->eflags & EF_DF) ? -op_bytes : op_bytes); 2.128 break; 2.129 2.130 @@ -1023,21 +1028,21 @@ static int emulate_privileged_op(struct 2.131 case 0x6f: /* OUTSW/OUTSL */ 2.132 if ( !guest_io_okay((u16)regs->edx, op_bytes, v, regs) ) 2.133 goto fail; 2.134 + rc = copy_from_user(&data, (void *)regs->esi, op_bytes); 2.135 + if ( rc != 0 ) 2.136 + { 2.137 + propagate_page_fault(regs->esi + op_bytes - rc, 0); 2.138 + return EXCRET_fault_fixed; 2.139 + } 2.140 switch ( op_bytes ) 2.141 { 2.142 case 1: 2.143 - if ( get_user(data, (u8 *)regs->esi) ) 2.144 - PAGE_FAULT(regs->esi, 0); /* read fault */ 2.145 outb_user((u8)data, (u16)regs->edx, v, regs); 2.146 break; 2.147 case 2: 2.148 - if ( get_user(data, (u16 *)regs->esi) ) 2.149 - PAGE_FAULT(regs->esi, 0); /* read fault */ 2.150 outw_user((u16)data, (u16)regs->edx, v, regs); 2.151 break; 2.152 case 4: 2.153 - if ( get_user(data, (u32 *)regs->esi) ) 2.154 - PAGE_FAULT(regs->esi, 0); /* read fault */ 2.155 outl_user((u32)data, (u16)regs->edx, v, regs); 2.156 break; 2.157 }
3.1 --- a/xen/arch/x86/x86_emulate.c Wed Jul 12 19:16:14 2006 +0100 3.2 +++ b/xen/arch/x86/x86_emulate.c Thu Jul 13 09:55:14 2006 +0100 3.3 @@ -1138,12 +1138,16 @@ x86_emulate_read_std( 3.4 unsigned int bytes, 3.5 struct x86_emulate_ctxt *ctxt) 3.6 { 3.7 + unsigned int rc; 3.8 + 3.9 *val = 0; 3.10 - if ( copy_from_user((void *)val, (void *)addr, bytes) ) 3.11 + 3.12 + if ( (rc = copy_from_user((void *)val, (void *)addr, bytes)) != 0 ) 3.13 { 3.14 - propagate_page_fault(addr, 0); /* read fault */ 3.15 + propagate_page_fault(addr + bytes - rc, 0); /* read fault */ 3.16 return X86EMUL_PROPAGATE_FAULT; 3.17 } 3.18 + 3.19 return X86EMUL_CONTINUE; 3.20 } 3.21 3.22 @@ -1154,11 +1158,14 @@ x86_emulate_write_std( 3.23 unsigned int bytes, 3.24 struct x86_emulate_ctxt *ctxt) 3.25 { 3.26 - if ( copy_to_user((void *)addr, (void *)&val, bytes) ) 3.27 + unsigned int rc; 3.28 + 3.29 + if ( (rc = copy_to_user((void *)addr, (void *)&val, bytes)) != 0 ) 3.30 { 3.31 - propagate_page_fault(addr, PGERR_write_access); /* write fault */ 3.32 + propagate_page_fault(addr + bytes - rc, PGERR_write_access); 3.33 return X86EMUL_PROPAGATE_FAULT; 3.34 } 3.35 + 3.36 return X86EMUL_CONTINUE; 3.37 } 3.38