ia64/xen-unstable

changeset 10735:af9809f51f81

[XEN] Clean up page-fault propagation when acessing guest addresses.
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