ia64/xen-unstable

changeset 9068:c369d960f96b

Sketch a new interface for transferring hypercall arguments in memory.
Instead of manipulating guest virtual addresses, 'guest handles' are
passed across the hypercall interface, which may only be manipulated
via the interface exported by guest_access.h.

So far this has only been applied to the memory_op hypercall. The
interfaces are still subject to change. Other hypercalls can be updated
after the interface is agreed upon.

Also cleaned up the hypercall_create_continuation() interface to take
a format string and different-typed varargs (they do not all need to
be castable to longs).

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue Feb 28 17:45:20 2006 +0100 (2006-02-28)
parents 62309ca8b708
children 8ac43508b33b
files xen/Rules.mk xen/arch/ia64/vmx/vmx_hypercall.c xen/arch/ia64/xen/process.c xen/arch/x86/domain.c xen/arch/x86/mm.c xen/arch/x86/traps.c xen/arch/x86/x86_32/mm.c xen/arch/x86/x86_64/mm.c xen/common/memory.c xen/common/multicall.c xen/drivers/char/console.c xen/include/asm-x86/mm.h xen/include/public/memory.h xen/include/public/xen.h xen/include/xen/guest_access.h xen/include/xen/sched.h
line diff
     1.1 --- a/xen/Rules.mk	Tue Feb 28 11:58:45 2006 +0100
     1.2 +++ b/xen/Rules.mk	Tue Feb 28 17:45:20 2006 +0100
     1.3 @@ -45,7 +45,7 @@ ALL_OBJS += $(BASEDIR)/arch/$(TARGET_ARC
     1.4  
     1.5  include $(BASEDIR)/arch/$(TARGET_ARCH)/Rules.mk
     1.6  
     1.7 -CFLAGS += -g
     1.8 +CFLAGS += -g -D__XEN__
     1.9  
    1.10  ifneq ($(debug),y)
    1.11  CFLAGS += -DNDEBUG
     2.1 --- a/xen/arch/ia64/vmx/vmx_hypercall.c	Tue Feb 28 11:58:45 2006 +0100
     2.2 +++ b/xen/arch/ia64/vmx/vmx_hypercall.c	Tue Feb 28 17:45:20 2006 +0100
     2.3 @@ -52,45 +52,7 @@ void hyper_mmu_update(void)
     2.4      vcpu_set_gr(vcpu, 8, ret, 0);
     2.5      vmx_vcpu_increment_iip(vcpu);
     2.6  }
     2.7 -/* turn off temporarily, we will merge hypercall parameter convention with xeno, when
     2.8 -    VTI domain need to call hypercall */
     2.9 -#if 0
    2.10 -unsigned long __hypercall_create_continuation(
    2.11 -    unsigned int op, unsigned int nr_args, ...)
    2.12 -{
    2.13 -    struct mc_state *mcs = &mc_state[smp_processor_id()];
    2.14 -    VCPU *vcpu = current;
    2.15 -    struct cpu_user_regs *regs = vcpu_regs(vcpu);
    2.16 -    unsigned int i;
    2.17 -    va_list args;
    2.18  
    2.19 -    va_start(args, nr_args);
    2.20 -    if ( test_bit(_MCSF_in_multicall, &mcs->flags) ) {
    2.21 -	panic("PREEMPT happen in multicall\n");	// Not support yet
    2.22 -    } else {
    2.23 -	vcpu_set_gr(vcpu, 15, op, 0);
    2.24 -	for ( i = 0; i < nr_args; i++) {
    2.25 -	    switch (i) {
    2.26 -	    case 0: vcpu_set_gr(vcpu, 16, va_arg(args, unsigned long), 0);
    2.27 -		    break;
    2.28 -	    case 1: vcpu_set_gr(vcpu, 17, va_arg(args, unsigned long), 0);
    2.29 -		    break;
    2.30 -	    case 2: vcpu_set_gr(vcpu, 18, va_arg(args, unsigned long), 0);
    2.31 -		    break;
    2.32 -	    case 3: vcpu_set_gr(vcpu, 19, va_arg(args, unsigned long), 0);
    2.33 -		    break;
    2.34 -	    case 4: vcpu_set_gr(vcpu, 20, va_arg(args, unsigned long), 0);
    2.35 -		    break;
    2.36 -	    default: panic("Too many args for hypercall continuation\n");
    2.37 -		    break;
    2.38 -	    }
    2.39 -	}
    2.40 -    }
    2.41 -    vcpu->arch.hypercall_continuation = 1;
    2.42 -    va_end(args);
    2.43 -    return op;
    2.44 -}
    2.45 -#endif
    2.46  void hyper_dom_mem_op(void)
    2.47  {
    2.48      VCPU *vcpu=current;
     3.1 --- a/xen/arch/ia64/xen/process.c	Tue Feb 28 11:58:45 2006 +0100
     3.2 +++ b/xen/arch/ia64/xen/process.c	Tue Feb 28 17:45:20 2006 +0100
     3.3 @@ -796,31 +796,49 @@ printf("*** Handled privop masquerading 
     3.4  	reflect_interruption(isr,regs,vector);
     3.5  }
     3.6  
     3.7 -unsigned long __hypercall_create_continuation(
     3.8 -	unsigned int op, unsigned int nr_args, ...)
     3.9 +unsigned long hypercall_create_continuation(
    3.10 +	unsigned int op, const char *format, ...)
    3.11  {
    3.12      struct mc_state *mcs = &mc_state[smp_processor_id()];
    3.13      VCPU *vcpu = current;
    3.14      struct cpu_user_regs *regs = vcpu_regs(vcpu);
    3.15 +    const char *p = format;
    3.16 +    unsigned long arg;
    3.17      unsigned int i;
    3.18      va_list args;
    3.19  
    3.20 -    va_start(args, nr_args);
    3.21 +    va_start(args, format);
    3.22      if ( test_bit(_MCSF_in_multicall, &mcs->flags) ) {
    3.23  	panic("PREEMPT happen in multicall\n");	// Not support yet
    3.24      } else {
    3.25  	vcpu_set_gr(vcpu, 2, op, 0);
    3.26 -	for ( i = 0; i < nr_args; i++) {
    3.27 +	for ( i = 0; *p != '\0'; i++) {
    3.28 +            switch ( *p++ )
    3.29 +            {
    3.30 +            case 'i':
    3.31 +                arg = (unsigned long)va_arg(args, unsigned int);
    3.32 +                break;
    3.33 +            case 'l':
    3.34 +                arg = (unsigned long)va_arg(args, unsigned long);
    3.35 +                break;
    3.36 +            case 'p':
    3.37 +            case 'h':
    3.38 +                arg = (unsigned long)va_arg(args, void *);
    3.39 +                break;
    3.40 +            default:
    3.41 +                arg = 0;
    3.42 +                BUG();
    3.43 +            }
    3.44  	    switch (i) {
    3.45 -	    case 0: vcpu_set_gr(vcpu, 14, va_arg(args, unsigned long), 0);
    3.46 +	    case 0: vcpu_set_gr(vcpu, 14, arg, 0);
    3.47  		    break;
    3.48 -	    case 1: vcpu_set_gr(vcpu, 15, va_arg(args, unsigned long), 0);
    3.49 +	    case 1: vcpu_set_gr(vcpu, 15, arg, 0);
    3.50  		    break;
    3.51 -	    case 2: vcpu_set_gr(vcpu, 16, va_arg(args, unsigned long), 0);
    3.52 +	    case 2: vcpu_set_gr(vcpu, 16, arg, 0);
    3.53  		    break;
    3.54 -	    case 3: vcpu_set_gr(vcpu, 17, va_arg(args, unsigned long), 0);
    3.55 +	    case 3: vcpu_set_gr(vcpu, 17, arg, 0);
    3.56  		    break;
    3.57 -	    case 4: vcpu_set_gr(vcpu, 18, va_arg(args, unsigned long), 0);
    3.58 +	    case 4: vcpu_set_gr(vcpu, 18, arg, 0);
    3.59  		    break;
    3.60  	    default: panic("Too many args for hypercall continuation\n");
    3.61  		    break;
     4.1 --- a/xen/arch/x86/domain.c	Tue Feb 28 11:58:45 2006 +0100
     4.2 +++ b/xen/arch/x86/domain.c	Tue Feb 28 17:45:20 2006 +0100
     4.3 @@ -825,22 +825,37 @@ void sync_vcpu_execstate(struct vcpu *v)
     4.4      flush_tlb_mask(v->vcpu_dirty_cpumask);
     4.5  }
     4.6  
     4.7 -unsigned long __hypercall_create_continuation(
     4.8 -    unsigned int op, unsigned int nr_args, ...)
     4.9 +#define next_arg(fmt, args) ({                                              \
    4.10 +    unsigned long __arg;                                                    \
    4.11 +    switch ( *(fmt)++ )                                                     \
    4.12 +    {                                                                       \
    4.13 +    case 'i': __arg = (unsigned long)va_arg(args, unsigned int);  break;    \
    4.14 +    case 'l': __arg = (unsigned long)va_arg(args, unsigned long); break;    \
    4.15 +    case 'p': __arg = (unsigned long)va_arg(args, void *);        break;    \
    4.16 +    case 'h': __arg = (unsigned long)va_arg(args, void *);        break;    \
    4.17 +    default:  __arg = 0; BUG();                                             \
    4.18 +    }                                                                       \
    4.19 +    __arg;                                                                  \
    4.20 +})
    4.21 +
    4.22 +unsigned long hypercall_create_continuation(
    4.23 +    unsigned int op, const char *format, ...)
    4.24  {
    4.25      struct mc_state *mcs = &mc_state[smp_processor_id()];
    4.26      struct cpu_user_regs *regs;
    4.27 +    const char *p = format;
    4.28 +    unsigned long arg;
    4.29      unsigned int i;
    4.30      va_list args;
    4.31  
    4.32 -    va_start(args, nr_args);
    4.33 +    va_start(args, format);
    4.34  
    4.35      if ( test_bit(_MCSF_in_multicall, &mcs->flags) )
    4.36      {
    4.37          __set_bit(_MCSF_call_preempted, &mcs->flags);
    4.38  
    4.39 -        for ( i = 0; i < nr_args; i++ )
    4.40 -            mcs->call.args[i] = va_arg(args, unsigned long);
    4.41 +        for ( i = 0; *p != '\0'; i++ )
    4.42 +            mcs->call.args[i] = next_arg(p, args);
    4.43      }
    4.44      else
    4.45      {
    4.46 @@ -853,32 +868,34 @@ unsigned long __hypercall_create_continu
    4.47          else
    4.48              regs->eip -= 2;   /* re-execute 'int 0x82' */
    4.49  
    4.50 -        for ( i = 0; i < nr_args; i++ )
    4.51 +        for ( i = 0; *p != '\0'; i++ )
    4.52          {
    4.53 +            arg = next_arg(p, args);
    4.54              switch ( i )
    4.55              {
    4.56 -            case 0: regs->ebx = va_arg(args, unsigned long); break;
    4.57 -            case 1: regs->ecx = va_arg(args, unsigned long); break;
    4.58 -            case 2: regs->edx = va_arg(args, unsigned long); break;
    4.59 -            case 3: regs->esi = va_arg(args, unsigned long); break;
    4.60 -            case 4: regs->edi = va_arg(args, unsigned long); break;
    4.61 -            case 5: regs->ebp = va_arg(args, unsigned long); break;
    4.62 +            case 0: regs->ebx = arg; break;
    4.63 +            case 1: regs->ecx = arg; break;
    4.64 +            case 2: regs->edx = arg; break;
    4.65 +            case 3: regs->esi = arg; break;
    4.66 +            case 4: regs->edi = arg; break;
    4.67 +            case 5: regs->ebp = arg; break;
    4.68              }
    4.69          }
    4.70  #elif defined(__x86_64__)
    4.71          regs->rax  = op;
    4.72          regs->rip -= 2;  /* re-execute 'syscall' */
    4.73  
    4.74 -        for ( i = 0; i < nr_args; i++ )
    4.75 +        for ( i = 0; *p != '\0'; i++ )
    4.76          {
    4.77 +            arg = next_arg(p, args);
    4.78              switch ( i )
    4.79              {
    4.80 -            case 0: regs->rdi = va_arg(args, unsigned long); break;
    4.81 -            case 1: regs->rsi = va_arg(args, unsigned long); break;
    4.82 -            case 2: regs->rdx = va_arg(args, unsigned long); break;
    4.83 -            case 3: regs->r10 = va_arg(args, unsigned long); break;
    4.84 -            case 4: regs->r8  = va_arg(args, unsigned long); break;
    4.85 -            case 5: regs->r9  = va_arg(args, unsigned long); break;
    4.86 +            case 0: regs->rdi = arg; break;
    4.87 +            case 1: regs->rsi = arg; break;
    4.88 +            case 2: regs->rdx = arg; break;
    4.89 +            case 3: regs->r10 = arg; break;
    4.90 +            case 4: regs->r8  = arg; break;
    4.91 +            case 5: regs->r9  = arg; break;
    4.92              }
    4.93          }
    4.94  #endif
     5.1 --- a/xen/arch/x86/mm.c	Tue Feb 28 11:58:45 2006 +0100
     5.2 +++ b/xen/arch/x86/mm.c	Tue Feb 28 17:45:20 2006 +0100
     5.3 @@ -97,11 +97,11 @@
     5.4  #include <xen/domain_page.h>
     5.5  #include <xen/event.h>
     5.6  #include <xen/iocap.h>
     5.7 +#include <xen/guest_access.h>
     5.8  #include <asm/shadow.h>
     5.9  #include <asm/page.h>
    5.10  #include <asm/flushtlb.h>
    5.11  #include <asm/io.h>
    5.12 -#include <asm/uaccess.h>
    5.13  #include <asm/ldt.h>
    5.14  #include <asm/x86_emulate.h>
    5.15  #include <public/memory.h>
    5.16 @@ -1778,9 +1778,9 @@ int do_mmuext_op(
    5.17      {
    5.18          if ( hypercall_preempt_check() )
    5.19          {
    5.20 -            rc = hypercall4_create_continuation(
    5.21 -                __HYPERVISOR_mmuext_op, uops,
    5.22 -                (count - i) | MMU_UPDATE_PREEMPTED, pdone, foreigndom);
    5.23 +            rc = hypercall_create_continuation(
    5.24 +                __HYPERVISOR_mmuext_op, "pipi",
    5.25 +                uops, (count - i) | MMU_UPDATE_PREEMPTED, pdone, foreigndom);
    5.26              break;
    5.27          }
    5.28  
    5.29 @@ -2044,9 +2044,9 @@ int do_mmu_update(
    5.30      {
    5.31          if ( hypercall_preempt_check() )
    5.32          {
    5.33 -            rc = hypercall4_create_continuation(
    5.34 -                __HYPERVISOR_mmu_update, ureqs, 
    5.35 -                (count - i) | MMU_UPDATE_PREEMPTED, pdone, foreigndom);
    5.36 +            rc = hypercall_create_continuation(
    5.37 +                __HYPERVISOR_mmu_update, "pipi",
    5.38 +                ureqs, (count - i) | MMU_UPDATE_PREEMPTED, pdone, foreigndom);
    5.39              break;
    5.40          }
    5.41  
    5.42 @@ -2795,7 +2795,7 @@ long do_update_descriptor(u64 pa, u64 de
    5.43  }
    5.44  
    5.45  
    5.46 -long arch_memory_op(int op, void *arg)
    5.47 +long arch_memory_op(int op, GUEST_HANDLE(void) arg)
    5.48  {
    5.49      struct xen_reserved_phys_area xrpa;
    5.50      unsigned long pfn;
    5.51 @@ -2805,7 +2805,7 @@ long arch_memory_op(int op, void *arg)
    5.52      switch ( op )
    5.53      {
    5.54      case XENMEM_reserved_phys_area:
    5.55 -        if ( copy_from_user(&xrpa, arg, sizeof(xrpa)) )
    5.56 +        if ( copy_from_guest(&xrpa, arg, 1) )
    5.57              return -EFAULT;
    5.58  
    5.59          /* No guest has more than one reserved area. */
    5.60 @@ -2839,7 +2839,7 @@ long arch_memory_op(int op, void *arg)
    5.61  
    5.62          put_domain(d);
    5.63  
    5.64 -        if ( copy_to_user(arg, &xrpa, sizeof(xrpa)) )
    5.65 +        if ( copy_to_guest(arg, &xrpa, 1) )
    5.66              return -EFAULT;
    5.67  
    5.68          break;
     6.1 --- a/xen/arch/x86/traps.c	Tue Feb 28 11:58:45 2006 +0100
     6.2 +++ b/xen/arch/x86/traps.c	Tue Feb 28 17:45:20 2006 +0100
     6.3 @@ -1415,8 +1415,8 @@ long do_set_trap_table(struct trap_info 
     6.4      {
     6.5          if ( hypercall_preempt_check() )
     6.6          {
     6.7 -            rc = hypercall1_create_continuation(
     6.8 -                __HYPERVISOR_set_trap_table, traps);
     6.9 +            rc = hypercall_create_continuation(
    6.10 +                __HYPERVISOR_set_trap_table, "p", traps);
    6.11              break;
    6.12          }
    6.13  
     7.1 --- a/xen/arch/x86/x86_32/mm.c	Tue Feb 28 11:58:45 2006 +0100
     7.2 +++ b/xen/arch/x86/x86_32/mm.c	Tue Feb 28 17:45:20 2006 +0100
     7.3 @@ -23,6 +23,7 @@
     7.4  #include <xen/init.h>
     7.5  #include <xen/mm.h>
     7.6  #include <xen/sched.h>
     7.7 +#include <xen/guest_access.h>
     7.8  #include <asm/current.h>
     7.9  #include <asm/page.h>
    7.10  #include <asm/flushtlb.h>
    7.11 @@ -191,7 +192,7 @@ void subarch_init_memory(struct domain *
    7.12      }
    7.13  }
    7.14  
    7.15 -long subarch_memory_op(int op, void *arg)
    7.16 +long subarch_memory_op(int op, GUEST_HANDLE(void) arg)
    7.17  {
    7.18      struct xen_machphys_mfn_list xmml;
    7.19      unsigned long mfn;
    7.20 @@ -201,7 +202,7 @@ long subarch_memory_op(int op, void *arg
    7.21      switch ( op )
    7.22      {
    7.23      case XENMEM_machphys_mfn_list:
    7.24 -        if ( copy_from_user(&xmml, arg, sizeof(xmml)) )
    7.25 +        if ( copy_from_guest(&xmml, arg, 1) )
    7.26              return -EFAULT;
    7.27  
    7.28          max = min_t(unsigned int, xmml.max_extents, mpt_size >> 21);
    7.29 @@ -210,11 +211,12 @@ long subarch_memory_op(int op, void *arg
    7.30          {
    7.31              mfn = l2e_get_pfn(idle_pg_table_l2[l2_linear_offset(
    7.32                  RDWR_MPT_VIRT_START + (i << 21))]) + l1_table_offset(i << 21);
    7.33 -            if ( put_user(mfn, &xmml.extent_start[i]) )
    7.34 +            if ( copy_to_guest_offset(xmml.extent_start, i, &mfn, 1) )
    7.35                  return -EFAULT;
    7.36          }
    7.37  
    7.38 -        if ( put_user(i, &((struct xen_machphys_mfn_list *)arg)->nr_extents) )
    7.39 +        xmml.nr_extents = i;
    7.40 +        if ( copy_to_guest(arg, &xmml, 1) )
    7.41              return -EFAULT;
    7.42  
    7.43          break;
     8.1 --- a/xen/arch/x86/x86_64/mm.c	Tue Feb 28 11:58:45 2006 +0100
     8.2 +++ b/xen/arch/x86/x86_64/mm.c	Tue Feb 28 17:45:20 2006 +0100
     8.3 @@ -22,6 +22,7 @@
     8.4  #include <xen/init.h>
     8.5  #include <xen/mm.h>
     8.6  #include <xen/sched.h>
     8.7 +#include <xen/guest_access.h>
     8.8  #include <asm/current.h>
     8.9  #include <asm/asm_defns.h>
    8.10  #include <asm/page.h>
    8.11 @@ -182,7 +183,7 @@ void subarch_init_memory(struct domain *
    8.12      }
    8.13  }
    8.14  
    8.15 -long subarch_memory_op(int op, void *arg)
    8.16 +long subarch_memory_op(int op, GUEST_HANDLE(void) arg)
    8.17  {
    8.18      struct xen_machphys_mfn_list xmml;
    8.19      l3_pgentry_t l3e;
    8.20 @@ -194,7 +195,7 @@ long subarch_memory_op(int op, void *arg
    8.21      switch ( op )
    8.22      {
    8.23      case XENMEM_machphys_mfn_list:
    8.24 -        if ( copy_from_user(&xmml, arg, sizeof(xmml)) )
    8.25 +        if ( copy_from_guest(&xmml, arg, 1) )
    8.26              return -EFAULT;
    8.27  
    8.28          for ( i = 0, v = RDWR_MPT_VIRT_START;
    8.29 @@ -209,11 +210,12 @@ long subarch_memory_op(int op, void *arg
    8.30              if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
    8.31                  break;
    8.32              mfn = l2e_get_pfn(l2e) + l1_table_offset(v);
    8.33 -            if ( put_user(mfn, &xmml.extent_start[i]) )
    8.34 +            if ( copy_to_guest_offset(xmml.extent_start, i, &mfn, 1) )
    8.35                  return -EFAULT;
    8.36          }
    8.37  
    8.38 -        if ( put_user(i, &((struct xen_machphys_mfn_list *)arg)->nr_extents) )
    8.39 +        xmml.nr_extents = i;
    8.40 +        if ( copy_to_guest(arg, &xmml, 1) )
    8.41              return -EFAULT;
    8.42  
    8.43          break;
     9.1 --- a/xen/common/memory.c	Tue Feb 28 11:58:45 2006 +0100
     9.2 +++ b/xen/common/memory.c	Tue Feb 28 17:45:20 2006 +0100
     9.3 @@ -16,6 +16,7 @@
     9.4  #include <xen/event.h>
     9.5  #include <xen/shadow.h>
     9.6  #include <xen/iocap.h>
     9.7 +#include <xen/guest_access.h>
     9.8  #include <asm/current.h>
     9.9  #include <asm/hardirq.h>
    9.10  #include <public/memory.h>
    9.11 @@ -30,7 +31,7 @@
    9.12  static long
    9.13  increase_reservation(
    9.14      struct domain *d, 
    9.15 -    unsigned long *extent_list, 
    9.16 +    GUEST_HANDLE(xen_ulong) extent_list,
    9.17      unsigned int   nr_extents,
    9.18      unsigned int   extent_order,
    9.19      unsigned int   flags,
    9.20 @@ -39,8 +40,8 @@ increase_reservation(
    9.21      struct page_info *page;
    9.22      unsigned long     i, mfn;
    9.23  
    9.24 -    if ( (extent_list != NULL) &&
    9.25 -         !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
    9.26 +    if ( !guest_handle_is_null(extent_list) &&
    9.27 +         !guest_handle_okay(extent_list, nr_extents) )
    9.28          return 0;
    9.29  
    9.30      if ( (extent_order != 0) &&
    9.31 @@ -65,10 +66,10 @@ increase_reservation(
    9.32          }
    9.33  
    9.34          /* Inform the domain of the new page's machine address. */ 
    9.35 -        if ( extent_list != NULL )
    9.36 +        if ( !guest_handle_is_null(extent_list) )
    9.37          {
    9.38              mfn = page_to_mfn(page);
    9.39 -            if ( unlikely(__copy_to_user(&extent_list[i], &mfn, sizeof(mfn))) )
    9.40 +            if ( unlikely(__copy_to_guest_offset(extent_list, i, &mfn, 1)) )
    9.41                  return i;
    9.42          }
    9.43      }
    9.44 @@ -79,16 +80,16 @@ increase_reservation(
    9.45  static long
    9.46  populate_physmap(
    9.47      struct domain *d, 
    9.48 -    unsigned long *extent_list, 
    9.49 -    unsigned int   nr_extents,
    9.50 -    unsigned int   extent_order,
    9.51 -    unsigned int   flags,
    9.52 -    int           *preempted)
    9.53 +    GUEST_HANDLE(xen_ulong) extent_list,
    9.54 +    unsigned int  nr_extents,
    9.55 +    unsigned int  extent_order,
    9.56 +    unsigned int  flags,
    9.57 +    int          *preempted)
    9.58  {
    9.59      struct page_info *page;
    9.60      unsigned long    i, j, gpfn, mfn;
    9.61  
    9.62 -    if ( !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
    9.63 +    if ( !guest_handle_okay(extent_list, nr_extents) )
    9.64          return 0;
    9.65  
    9.66      if ( (extent_order != 0) &&
    9.67 @@ -103,7 +104,7 @@ populate_physmap(
    9.68              goto out;
    9.69          }
    9.70  
    9.71 -        if ( unlikely(__copy_from_user(&gpfn, &extent_list[i], sizeof(gpfn))) )
    9.72 +        if ( unlikely(__copy_from_guest_offset(&gpfn, extent_list, i, 1)) )
    9.73              goto out;
    9.74  
    9.75          if ( unlikely((page = alloc_domheap_pages(
    9.76 @@ -128,7 +129,7 @@ populate_physmap(
    9.77                  set_gpfn_from_mfn(mfn + j, gpfn + j);
    9.78  
    9.79              /* Inform the domain of the new page's machine address. */ 
    9.80 -            if ( unlikely(__copy_to_user(&extent_list[i], &mfn, sizeof(mfn))) )
    9.81 +            if ( unlikely(__copy_to_guest_offset(extent_list, i, &mfn, 1)) )
    9.82                  goto out;
    9.83          }
    9.84      }
    9.85 @@ -139,8 +140,8 @@ populate_physmap(
    9.86      
    9.87  static long
    9.88  decrease_reservation(
    9.89 -    struct domain *d, 
    9.90 -    unsigned long *extent_list, 
    9.91 +    struct domain *d,
    9.92 +    GUEST_HANDLE(xen_ulong) extent_list,
    9.93      unsigned int   nr_extents,
    9.94      unsigned int   extent_order,
    9.95      unsigned int   flags,
    9.96 @@ -149,7 +150,7 @@ decrease_reservation(
    9.97      struct page_info *page;
    9.98      unsigned long    i, j, gmfn, mfn;
    9.99  
   9.100 -    if ( !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
   9.101 +    if ( !guest_handle_okay(extent_list, nr_extents) )
   9.102          return 0;
   9.103  
   9.104      for ( i = 0; i < nr_extents; i++ )
   9.105 @@ -160,7 +161,7 @@ decrease_reservation(
   9.106              return i;
   9.107          }
   9.108  
   9.109 -        if ( unlikely(__copy_from_user(&gmfn, &extent_list[i], sizeof(gmfn))) )
   9.110 +        if ( unlikely(__copy_from_guest_offset(&gmfn, extent_list, i, 1)) )
   9.111              return i;
   9.112  
   9.113          for ( j = 0; j < (1 << extent_order); j++ )
   9.114 @@ -197,21 +198,21 @@ decrease_reservation(
   9.115  
   9.116  static long
   9.117  translate_gpfn_list(
   9.118 -    struct xen_translate_gpfn_list *uop, unsigned long *progress)
   9.119 +    GUEST_HANDLE(xen_translate_gpfn_list_t) uop, unsigned long *progress)
   9.120  {
   9.121      struct xen_translate_gpfn_list op;
   9.122      unsigned long i, gpfn, mfn;
   9.123      struct domain *d;
   9.124  
   9.125 -    if ( copy_from_user(&op, uop, sizeof(op)) )
   9.126 +    if ( copy_from_guest(&op, uop, 1) )
   9.127          return -EFAULT;
   9.128  
   9.129      /* Is size too large for us to encode a continuation? */
   9.130      if ( op.nr_gpfns > (ULONG_MAX >> START_EXTENT_SHIFT) )
   9.131          return -EINVAL;
   9.132  
   9.133 -    if ( !array_access_ok(op.gpfn_list, op.nr_gpfns, sizeof(*op.gpfn_list)) ||
   9.134 -         !array_access_ok(op.mfn_list, op.nr_gpfns, sizeof(*op.mfn_list)) )
   9.135 +    if ( !guest_handle_okay(op.gpfn_list, op.nr_gpfns) ||
   9.136 +         !guest_handle_okay(op.mfn_list,  op.nr_gpfns) )
   9.137          return -EFAULT;
   9.138  
   9.139      if ( op.domid == DOMID_SELF )
   9.140 @@ -237,8 +238,7 @@ translate_gpfn_list(
   9.141              return -EAGAIN;
   9.142          }
   9.143  
   9.144 -        if ( unlikely(__copy_from_user(&gpfn, &op.gpfn_list[i],
   9.145 -                                       sizeof(gpfn))) )
   9.146 +        if ( unlikely(__copy_from_guest_offset(&gpfn, op.gpfn_list, i, 1)) )
   9.147          {
   9.148              put_domain(d);
   9.149              return -EFAULT;
   9.150 @@ -246,8 +246,7 @@ translate_gpfn_list(
   9.151  
   9.152          mfn = gmfn_to_mfn(d, gpfn);
   9.153  
   9.154 -        if ( unlikely(__copy_to_user(&op.mfn_list[i], &mfn,
   9.155 -                                     sizeof(mfn))) )
   9.156 +        if ( unlikely(__copy_to_guest_offset(op.mfn_list, i, &mfn, 1)) )
   9.157          {
   9.158              put_domain(d);
   9.159              return -EFAULT;
   9.160 @@ -258,7 +257,7 @@ translate_gpfn_list(
   9.161      return 0;
   9.162  }
   9.163  
   9.164 -long do_memory_op(unsigned long cmd, void *arg)
   9.165 +long do_memory_op(unsigned long cmd, GUEST_HANDLE(void) arg)
   9.166  {
   9.167      struct domain *d;
   9.168      int rc, op, flags = 0, preempted = 0;
   9.169 @@ -273,7 +272,7 @@ long do_memory_op(unsigned long cmd, voi
   9.170      case XENMEM_increase_reservation:
   9.171      case XENMEM_decrease_reservation:
   9.172      case XENMEM_populate_physmap:
   9.173 -        if ( copy_from_user(&reservation, arg, sizeof(reservation)) )
   9.174 +        if ( copy_from_guest(&reservation, arg, 1) )
   9.175              return -EFAULT;
   9.176  
   9.177          /* Is size too large for us to encode a continuation? */
   9.178 @@ -283,9 +282,9 @@ long do_memory_op(unsigned long cmd, voi
   9.179          start_extent = cmd >> START_EXTENT_SHIFT;
   9.180          if ( unlikely(start_extent > reservation.nr_extents) )
   9.181              return -EINVAL;
   9.182 -        
   9.183 -        if ( reservation.extent_start != NULL )
   9.184 -            reservation.extent_start += start_extent;
   9.185 +
   9.186 +        if ( !guest_handle_is_null(reservation.extent_start) )
   9.187 +            guest_handle_add_offset(reservation.extent_start, start_extent);
   9.188          reservation.nr_extents -= start_extent;
   9.189  
   9.190          if ( (reservation.address_bits != 0) &&
   9.191 @@ -342,8 +341,9 @@ long do_memory_op(unsigned long cmd, voi
   9.192          rc += start_extent;
   9.193  
   9.194          if ( preempted )
   9.195 -            return hypercall2_create_continuation(
   9.196 -                __HYPERVISOR_memory_op, op | (rc << START_EXTENT_SHIFT), arg);
   9.197 +            return hypercall_create_continuation(
   9.198 +                __HYPERVISOR_memory_op, "lh",
   9.199 +                op | (rc << START_EXTENT_SHIFT), arg);
   9.200  
   9.201          break;
   9.202  
   9.203 @@ -353,10 +353,10 @@ long do_memory_op(unsigned long cmd, voi
   9.204  
   9.205      case XENMEM_current_reservation:
   9.206      case XENMEM_maximum_reservation:
   9.207 -        if ( copy_from_user(&domid, (domid_t *)arg, sizeof(domid)) )
   9.208 +        if ( copy_from_guest(&domid, arg, 1) )
   9.209              return -EFAULT;
   9.210  
   9.211 -        if ( likely((domid = (unsigned long)arg) == DOMID_SELF) )
   9.212 +        if ( likely(domid == DOMID_SELF) )
   9.213              d = current->domain;
   9.214          else if ( !IS_PRIV(current->domain) )
   9.215              return -EPERM;
   9.216 @@ -372,12 +372,13 @@ long do_memory_op(unsigned long cmd, voi
   9.217  
   9.218      case XENMEM_translate_gpfn_list:
   9.219          progress = cmd >> START_EXTENT_SHIFT;
   9.220 -        rc = translate_gpfn_list(arg, &progress);
   9.221 +        rc = translate_gpfn_list(
   9.222 +            guest_handle_cast(arg, xen_translate_gpfn_list_t),
   9.223 +            &progress);
   9.224          if ( rc == -EAGAIN )
   9.225 -            return hypercall2_create_continuation(
   9.226 -                __HYPERVISOR_memory_op,
   9.227 -                op | (progress << START_EXTENT_SHIFT),
   9.228 -                arg);
   9.229 +            return hypercall_create_continuation(
   9.230 +                __HYPERVISOR_memory_op, "lh",
   9.231 +                op | (progress << START_EXTENT_SHIFT), arg);
   9.232          break;
   9.233  
   9.234      default:
    10.1 --- a/xen/common/multicall.c	Tue Feb 28 11:58:45 2006 +0100
    10.2 +++ b/xen/common/multicall.c	Tue Feb 28 17:45:20 2006 +0100
    10.3 @@ -81,8 +81,8 @@ long do_multicall(struct multicall_entry
    10.4              if ( i < nr_calls )
    10.5              {
    10.6                  mcs->flags = 0;
    10.7 -                return hypercall2_create_continuation(
    10.8 -                    __HYPERVISOR_multicall, &call_list[i], nr_calls-i);
    10.9 +                return hypercall_create_continuation(
   10.10 +                    __HYPERVISOR_multicall, "pi", &call_list[i], nr_calls-i);
   10.11              }
   10.12          }
   10.13      }
    11.1 --- a/xen/drivers/char/console.c	Tue Feb 28 11:58:45 2006 +0100
    11.2 +++ b/xen/drivers/char/console.c	Tue Feb 28 17:45:20 2006 +0100
    11.3 @@ -335,8 +335,9 @@ long guest_console_write(char *buffer, i
    11.4          }
    11.5  
    11.6          if ( hypercall_preempt_check() )
    11.7 -            return hypercall3_create_continuation(
    11.8 -                __HYPERVISOR_console_io, CONSOLEIO_write, count, buffer);
    11.9 +            return hypercall_create_continuation(
   11.10 +                __HYPERVISOR_console_io, "iip",
   11.11 +                CONSOLEIO_write, count, buffer);
   11.12  
   11.13          kcount = min_t(int, count, sizeof(kbuf)-1);
   11.14          if ( copy_from_user(kbuf, buffer, kcount) )
    12.1 --- a/xen/include/asm-x86/mm.h	Tue Feb 28 11:58:45 2006 +0100
    12.2 +++ b/xen/include/asm-x86/mm.h	Tue Feb 28 17:45:20 2006 +0100
    12.3 @@ -376,7 +376,7 @@ void propagate_page_fault(unsigned long 
    12.4  int __sync_lazy_execstate(void);
    12.5  
    12.6  /* Arch-specific portion of memory_op hypercall. */
    12.7 -long arch_memory_op(int op, void *arg);
    12.8 -long subarch_memory_op(int op, void *arg);
    12.9 +long arch_memory_op(int op, GUEST_HANDLE(void) arg);
   12.10 +long subarch_memory_op(int op, GUEST_HANDLE(void) arg);
   12.11  
   12.12  #endif /* __ASM_X86_MM_H__ */
    13.1 --- a/xen/include/public/memory.h	Tue Feb 28 11:58:45 2006 +0100
    13.2 +++ b/xen/include/public/memory.h	Tue Feb 28 17:45:20 2006 +0100
    13.3 @@ -29,7 +29,7 @@ typedef struct xen_memory_reservation {
    13.4       *   OUT: GMFN bases of extents that were allocated
    13.5       *   (NB. This command also updates the mach_to_phys translation table)
    13.6       */
    13.7 -    unsigned long *extent_start;
    13.8 +    GUEST_HANDLE(xen_ulong) extent_start;
    13.9  
   13.10      /* Number of extents, and size/alignment of each (2^extent_order pages). */
   13.11      unsigned long  nr_extents;
   13.12 @@ -50,6 +50,7 @@ typedef struct xen_memory_reservation {
   13.13      domid_t        domid;
   13.14  
   13.15  } xen_memory_reservation_t;
   13.16 +DEFINE_GUEST_HANDLE(xen_memory_reservation_t);
   13.17  
   13.18  /*
   13.19   * Returns the maximum machine frame number of mapped RAM in this system.
   13.20 @@ -85,7 +86,7 @@ typedef struct xen_machphys_mfn_list {
   13.21       * any large discontiguities in the machine address space, 2MB gaps in
   13.22       * the machphys table will be represented by an MFN base of zero.
   13.23       */
   13.24 -    unsigned long *extent_start;
   13.25 +    GUEST_HANDLE(xen_ulong) extent_start;
   13.26  
   13.27      /*
   13.28       * Number of extents written to the above array. This will be smaller
   13.29 @@ -93,6 +94,7 @@ typedef struct xen_machphys_mfn_list {
   13.30       */
   13.31      unsigned int nr_extents;
   13.32  } xen_machphys_mfn_list_t;
   13.33 +DEFINE_GUEST_HANDLE(xen_machphys_mfn_list_t);
   13.34  
   13.35  /*
   13.36   * Returns the base and size of the specified reserved 'RAM hole' in the
   13.37 @@ -113,6 +115,7 @@ typedef struct xen_reserved_phys_area {
   13.38      /* Base and size of the specified reserved area. */
   13.39      unsigned long first_gpfn, nr_gpfns;
   13.40  } xen_reserved_phys_area_t;
   13.41 +DEFINE_GUEST_HANDLE(xen_reserved_phys_area_t);
   13.42  
   13.43  /*
   13.44   * Translates a list of domain-specific GPFNs into MFNs. Returns a -ve error
   13.45 @@ -127,14 +130,15 @@ typedef struct xen_translate_gpfn_list {
   13.46      unsigned long nr_gpfns;
   13.47  
   13.48      /* List of GPFNs to translate. */
   13.49 -    unsigned long *gpfn_list;
   13.50 +    GUEST_HANDLE(xen_ulong) gpfn_list;
   13.51  
   13.52      /*
   13.53       * Output list to contain MFN translations. May be the same as the input
   13.54       * list (in which case each input GPFN is overwritten with the output MFN).
   13.55       */
   13.56 -    unsigned long *mfn_list;
   13.57 +    GUEST_HANDLE(xen_ulong) mfn_list;
   13.58  } xen_translate_gpfn_list_t;
   13.59 +DEFINE_GUEST_HANDLE(xen_translate_gpfn_list_t);
   13.60  
   13.61  #endif /* __XEN_PUBLIC_MEMORY_H__ */
   13.62  
    14.1 --- a/xen/include/public/xen.h	Tue Feb 28 11:58:45 2006 +0100
    14.2 +++ b/xen/include/public/xen.h	Tue Feb 28 17:45:20 2006 +0100
    14.3 @@ -9,6 +9,22 @@
    14.4  #ifndef __XEN_PUBLIC_XEN_H__
    14.5  #define __XEN_PUBLIC_XEN_H__
    14.6  
    14.7 +#ifdef __XEN__
    14.8 +#define DEFINE_GUEST_HANDLE(type) struct __guest_handle_ ## type { type *p; }
    14.9 +#define GUEST_HANDLE(type)        struct __guest_handle_ ## type
   14.10 +#else
   14.11 +#define DEFINE_GUEST_HANDLE(type)
   14.12 +#define GUEST_HANDLE(type)        type *
   14.13 +#endif
   14.14 +
   14.15 +#ifndef __ASSEMBLY__
   14.16 +/* Guest handle for unsigned long pointer. Define a name with no whitespace. */
   14.17 +typedef unsigned long xen_ulong;
   14.18 +DEFINE_GUEST_HANDLE(xen_ulong);
   14.19 +/* Guest handle for arbitrary-type pointer (void *). */
   14.20 +DEFINE_GUEST_HANDLE(void);
   14.21 +#endif
   14.22 +
   14.23  #if defined(__i386__)
   14.24  #include "arch-x86_32.h"
   14.25  #elif defined(__x86_64__)
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/xen/include/xen/guest_access.h	Tue Feb 28 17:45:20 2006 +0100
    15.3 @@ -0,0 +1,71 @@
    15.4 +/******************************************************************************
    15.5 + * guest_access.h
    15.6 + * 
    15.7 + * Copyright (x) 2006, K A Fraser
    15.8 + */
    15.9 +
   15.10 +#ifndef __XEN_GUEST_ACCESS_H__
   15.11 +#define __XEN_GUEST_ACCESS_H__
   15.12 +
   15.13 +#include <asm/uaccess.h>
   15.14 +
   15.15 +/* Is the guest handle a NULL reference? */
   15.16 +#define guest_handle_is_null(hnd)        ((hnd).p == NULL)
   15.17 +
   15.18 +/* Offset the given guest handle into the array it refers to. */
   15.19 +#define guest_handle_add_offset(hnd, nr) ((hnd).p += (nr))
   15.20 +
   15.21 +/* Cast a guest handle to the specified type of handle. */
   15.22 +#define guest_handle_cast(hnd, type) ({         \
   15.23 +    type *_x = (hnd).p;                         \
   15.24 +    (GUEST_HANDLE(type)) { _x };                \
   15.25 +})
   15.26 +
   15.27 +/*
   15.28 + * Copy an array of objects to guest context via a guest handle.
   15.29 + * Optionally specify an offset into the guest array.
   15.30 + */
   15.31 +#define copy_to_guest_offset(hnd, off, ptr, nr) ({      \
   15.32 +    const typeof(ptr) _x = (hnd).p;                     \
   15.33 +    const typeof(ptr) _y = (ptr);                       \
   15.34 +    copy_to_user(_x+(off), _y, sizeof(*_x)*(nr));       \
   15.35 +})
   15.36 +#define copy_to_guest(hnd, ptr, nr)                     \
   15.37 +    copy_to_guest_offset(hnd, 0, ptr, nr)
   15.38 +
   15.39 +/*
   15.40 + * Copy an array of objects from guest context via a guest handle.
   15.41 + * Optionally specify an offset into the guest array.
   15.42 + */
   15.43 +#define copy_from_guest_offset(ptr, hnd, off, nr) ({    \
   15.44 +    const typeof(ptr) _x = (hnd).p;                     \
   15.45 +    const typeof(ptr) _y = (ptr);                       \
   15.46 +    copy_from_user(_y, _x+(off), sizeof(*_x)*(nr));     \
   15.47 +})
   15.48 +#define copy_from_guest(ptr, hnd, nr)                   \
   15.49 +    copy_from_guest_offset(ptr, hnd, 0, nr)
   15.50 +
   15.51 +/*
   15.52 + * Pre-validate a guest handle.
   15.53 + * Allows use of faster __copy_* functions.
   15.54 + */
   15.55 +#define guest_handle_okay(hnd, nr)                      \
   15.56 +    array_access_ok((hnd).p, (nr), sizeof(*(hnd).p))
   15.57 +
   15.58 +#define __copy_to_guest_offset(hnd, off, ptr, nr) ({    \
   15.59 +    const typeof(ptr) _x = (hnd).p;                     \
   15.60 +    const typeof(ptr) _y = (ptr);                       \
   15.61 +    __copy_to_user(_x+(off), _y, sizeof(*_x)*(nr));     \
   15.62 +})
   15.63 +#define __copy_to_guest(hnd, ptr, nr)                   \
   15.64 +    __copy_to_guest_offset(hnd, 0, ptr, nr)
   15.65 +
   15.66 +#define __copy_from_guest_offset(ptr, hnd, off, nr) ({  \
   15.67 +    const typeof(ptr) _x = (hnd).p;                     \
   15.68 +    const typeof(ptr) _y = (ptr);                       \
   15.69 +    __copy_from_user(_y, _x+(off), sizeof(*_x)*(nr));   \
   15.70 +})
   15.71 +#define __copy_from_guest(ptr, hnd, nr)                 \
   15.72 +    __copy_from_guest_offset(ptr, hnd, 0, nr)
   15.73 +
   15.74 +#endif /* __XEN_GUEST_ACCESS_H__ */
    16.1 --- a/xen/include/xen/sched.h	Tue Feb 28 11:58:45 2006 +0100
    16.2 +++ b/xen/include/xen/sched.h	Tue Feb 28 17:45:20 2006 +0100
    16.3 @@ -303,31 +303,18 @@ extern void continue_running(
    16.4  
    16.5  void startup_cpu_idle_loop(void);
    16.6  
    16.7 -unsigned long __hypercall_create_continuation(
    16.8 -    unsigned int op, unsigned int nr_args, ...);
    16.9 -#define hypercall0_create_continuation(_op)                               \
   16.10 -    __hypercall_create_continuation((_op), 0)
   16.11 -#define hypercall1_create_continuation(_op, _a1)                          \
   16.12 -    __hypercall_create_continuation((_op), 1,                             \
   16.13 -        (unsigned long)(_a1))
   16.14 -#define hypercall2_create_continuation(_op, _a1, _a2)                     \
   16.15 -    __hypercall_create_continuation((_op), 2,                             \
   16.16 -        (unsigned long)(_a1), (unsigned long)(_a2))
   16.17 -#define hypercall3_create_continuation(_op, _a1, _a2, _a3)                \
   16.18 -    __hypercall_create_continuation((_op), 3,                             \
   16.19 -        (unsigned long)(_a1), (unsigned long)(_a2), (unsigned long)(_a3))
   16.20 -#define hypercall4_create_continuation(_op, _a1, _a2, _a3, _a4)           \
   16.21 -    __hypercall_create_continuation((_op), 4,                             \
   16.22 -        (unsigned long)(_a1), (unsigned long)(_a2), (unsigned long)(_a3), \
   16.23 -        (unsigned long)(_a4))
   16.24 -#define hypercall5_create_continuation(_op, _a1, _a2, _a3, _a4, _a5)      \
   16.25 -    __hypercall_create_continuation((_op), 5,                             \
   16.26 -        (unsigned long)(_a1), (unsigned long)(_a2), (unsigned long)(_a3), \
   16.27 -        (unsigned long)(_a4), (unsigned long)(_a5))
   16.28 -#define hypercall6_create_continuation(_op, _a1, _a2, _a3, _a4, _a5, _a6) \
   16.29 -    __hypercall_create_continuation((_op), 6,                             \
   16.30 -        (unsigned long)(_a1), (unsigned long)(_a2), (unsigned long)(_a3), \
   16.31 -        (unsigned long)(_a4), (unsigned long)(_a5), (unsigned long)(_a6))
   16.32 +/*
   16.33 + * Creates a continuation to resume the current hypercall. The caller should
   16.34 + * return immediately, propagating the value returned from this invocation.
   16.35 + * The format string specifies the types and number of hypercall arguments.
   16.36 + * It contains one character per argument as follows:
   16.37 + *  'i' [unsigned] {char, int}
   16.38 + *  'l' [unsigned] long
   16.39 + *  'p' pointer (foo *)
   16.40 + *  'h' guest handle (GUEST_HANDLE(foo))
   16.41 + */
   16.42 +unsigned long hypercall_create_continuation(
   16.43 +    unsigned int op, const char *format, ...);
   16.44  
   16.45  #define hypercall_preempt_check() (unlikely(    \
   16.46          softirq_pending(smp_processor_id()) |   \