ia64/xen-unstable

changeset 3139:b013a6b30d9e

bitkeeper revision 1.1159.187.15 (41a61537tODn12flBND8W6jum0b79Q)

Fix hypercall preemption. At the same time I reimplemented most of the
multi-hypercall in arch-independent C code.
author kaf24@scramble.cl.cam.ac.uk
date Thu Nov 25 17:24:07 2004 +0000 (2004-11-25)
parents b835d903239c
children 4a88ba0e9ef1 0d7e310db68e
files .rootkeys xen/arch/x86/domain.c xen/arch/x86/memory.c xen/arch/x86/traps.c xen/arch/x86/x86_32/asm-offsets.c xen/arch/x86/x86_32/entry.S xen/common/dom_mem_ops.c xen/common/grant_table.c xen/common/multicall.c xen/include/asm-x86/mm.h xen/include/asm-x86/multicall.h xen/include/asm-x86/x86_32/uaccess.h xen/include/xen/multicall.h xen/include/xen/sched.h
line diff
     1.1 --- a/.rootkeys	Thu Nov 25 16:38:44 2004 +0000
     1.2 +++ b/.rootkeys	Thu Nov 25 17:24:07 2004 +0000
     1.3 @@ -697,6 +697,7 @@ 3ddb79bd9drcFPVxd4w2GPOIjLlXpA xen/commo
     1.4  3e4cd9d8LAAghUY0hNIK72uc2ch_Nw xen/common/keyhandler.c
     1.5  3ddb79bduhSEZI8xa7IbGQCpap5y2A xen/common/lib.c
     1.6  3ddb79bdS39UXxUtZnaScie83-7VTQ xen/common/memory.c
     1.7 +41a61536SZbR6cj1ukWTb0DYU-vz9w xen/common/multicall.c
     1.8  3ddb79bdD4SLmmdMD7yLW5HcUWucXw xen/common/page_alloc.c
     1.9  3e54c38dkHAev597bPr71-hGzTdocg xen/common/perfc.c
    1.10  4051bcecFeq4DE70p4zGO5setf47CA xen/common/physdev.c
    1.11 @@ -792,6 +793,7 @@ 3ddb79c3I98vWcQR8xEo34JMJ4Ahyw xen/inclu
    1.12  40ec25fd7cSvbP7Biw91zaU_g0xsEQ xen/include/asm-x86/mm.h
    1.13  3ddb79c3n_UbPuxlkNxvvLycClIkxA xen/include/asm-x86/mpspec.h
    1.14  3ddb79c2wa0dA_LGigxOelSGbJ284Q xen/include/asm-x86/msr.h
    1.15 +41a61536MFhNalgbVmYGXAhQsPTZNw xen/include/asm-x86/multicall.h
    1.16  3ddb79c3xjYnrv5t3VqYlR4tNEOl4Q xen/include/asm-x86/page.h
    1.17  3ddb79c3ysKUbxZuwKBRK3WXU2TlEg xen/include/asm-x86/pci.h
    1.18  404f1bb41Yl-5ZjIWnG66HDCj6OIWA xen/include/asm-x86/pda.h
    1.19 @@ -853,6 +855,7 @@ 3ddb79c1NfYlOrWNqgZkj9EwtFfJow xen/inclu
    1.20  3ddb79c18Ajy7micDGQQfJ0zWgEHtA xen/include/xen/list.h
    1.21  3ddb79c1gs2VbLbQlw0dcDUXYIepDA xen/include/xen/mm.h
    1.22  3ddb79c1ieLZfGSFwfvvSQ2NK1BMSg xen/include/xen/multiboot.h
    1.23 +41a61536ii6j2lJ2rXwMOLaG1CHPvw xen/include/xen/multicall.h
    1.24  3ddb79c2Fg44_PBPVxHSC0gTOMq4Ow xen/include/xen/pci.h
    1.25  3ddb79c0MOVXq8qZDQRGb6z64_xAwg xen/include/xen/pci_ids.h
    1.26  3e54c38dlSCVdyVM4PKcrSfzLLxWUQ xen/include/xen/perfc.h
     2.1 --- a/xen/arch/x86/domain.c	Thu Nov 25 16:38:44 2004 +0000
     2.2 +++ b/xen/arch/x86/domain.c	Thu Nov 25 17:24:07 2004 +0000
     2.3 @@ -32,6 +32,7 @@
     2.4  #include <asm/shadow.h>
     2.5  #include <xen/console.h>
     2.6  #include <xen/elf.h>
     2.7 +#include <xen/multicall.h>
     2.8  
     2.9  #if !defined(CONFIG_X86_64BITMODE)
    2.10  /* No ring-3 access in initial page tables. */
    2.11 @@ -428,17 +429,31 @@ long do_iopl(domid_t domain, unsigned in
    2.12  
    2.13  void hypercall_create_continuation(unsigned int op, unsigned int nr_args, ...)
    2.14  {
    2.15 -    execution_context_t *ec = get_execution_context();
    2.16 -    unsigned long *preg = &ec->ebx;
    2.17 +    struct mc_state *mcs = &mc_state[smp_processor_id()];
    2.18 +    execution_context_t *ec;
    2.19 +    unsigned long *preg;
    2.20      unsigned int i;
    2.21      va_list args;
    2.22  
    2.23 -    ec->eax  = op;
    2.24 -    ec->eip -= 2;  /* re-execute 'int 0x82' */
    2.25 +    va_start(args, nr_args);
    2.26 +
    2.27 +    if ( test_bit(_MCSF_in_multicall, &mcs->flags) )
    2.28 +    {
    2.29 +        __set_bit(_MCSF_call_preempted, &mcs->flags);
    2.30  
    2.31 -    va_start(args, nr_args);
    2.32 -    for ( i = 0; i < nr_args; i++ )
    2.33 -        *preg++ = va_arg(args, unsigned long);
    2.34 +        for ( i = 0; i < nr_args; i++ )
    2.35 +            mcs->call.args[i] = va_arg(args, unsigned long);
    2.36 +    }
    2.37 +    else
    2.38 +    {
    2.39 +        ec       = get_execution_context();
    2.40 +        ec->eax  = op;
    2.41 +        ec->eip -= 2;  /* re-execute 'int 0x82' */
    2.42 +        
    2.43 +        for ( i = 0, preg = &ec->ebx; i < nr_args; i++, preg++ )
    2.44 +            *preg = va_arg(args, unsigned long);
    2.45 +    }
    2.46 +
    2.47      va_end(args);
    2.48  }
    2.49  
     3.1 --- a/xen/arch/x86/memory.c	Thu Nov 25 16:38:44 2004 +0000
     3.2 +++ b/xen/arch/x86/memory.c	Thu Nov 25 17:24:07 2004 +0000
     3.3 @@ -1277,14 +1277,20 @@ static int do_extended_command(unsigned 
     3.4      return okay;
     3.5  }
     3.6  
     3.7 +int do_mmu_update(
     3.8 +    mmu_update_t *ureqs, unsigned int count, unsigned int *pdone)
     3.9 +{
    3.10 +/*
    3.11 + * We steal the m.s.b. of the @count parameter to indicate whether this
    3.12 + * invocation of do_mmu_update() is resuming a previously preempted call.
    3.13 + */
    3.14 +#define MMU_UPDATE_PREEMPTED  (~(~0U>>1))
    3.15  
    3.16 -int do_mmu_update(mmu_update_t *ureqs, int count, int *success_count)
    3.17 -{
    3.18      mmu_update_t req;
    3.19      unsigned long va = 0, deferred_ops, pfn, prev_pfn = 0;
    3.20      struct pfn_info *page;
    3.21      int rc = 0, okay = 1, i, cpu = smp_processor_id();
    3.22 -    unsigned int cmd;
    3.23 +    unsigned int cmd, done = 0;
    3.24      unsigned long prev_spfn = 0;
    3.25      l1_pgentry_t *prev_spl1e = 0;
    3.26      struct domain *d = current;
    3.27 @@ -1295,13 +1301,30 @@ int do_mmu_update(mmu_update_t *ureqs, i
    3.28  
    3.29      cleanup_writable_pagetable(d, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE);
    3.30  
    3.31 -    if ( unlikely(!access_ok(VERIFY_READ, ureqs, count * sizeof(req))) )
    3.32 +    /*
    3.33 +     * If we are resuming after preemption, read how much work we have already
    3.34 +     * done. This allows us to set the @done output parameter correctly.
    3.35 +     */
    3.36 +    if ( unlikely(count & MMU_UPDATE_PREEMPTED) )
    3.37 +    {
    3.38 +        count &= ~MMU_UPDATE_PREEMPTED;
    3.39 +        if ( unlikely(pdone != NULL) )
    3.40 +            (void)get_user(done, pdone);
    3.41 +    }
    3.42 +
    3.43 +    if ( unlikely(!array_access_ok(VERIFY_READ, ureqs, count, sizeof(req))) )
    3.44          return -EFAULT;
    3.45  
    3.46      for ( i = 0; i < count; i++ )
    3.47      {
    3.48 -        hypercall_may_preempt(
    3.49 -            __HYPERVISOR_mmu_update, 3, ureqs, count-i, success_count);
    3.50 +        if ( hypercall_preempt_check() )
    3.51 +        {
    3.52 +            hypercall_create_continuation(
    3.53 +                __HYPERVISOR_mmu_update, 3, ureqs, 
    3.54 +                (count - i) | MMU_UPDATE_PREEMPTED, pdone);
    3.55 +            rc = __HYPERVISOR_mmu_update;
    3.56 +            break;
    3.57 +        }
    3.58  
    3.59          if ( unlikely(__copy_from_user(&req, ureqs, sizeof(req)) != 0) )
    3.60          {
    3.61 @@ -1457,8 +1480,9 @@ int do_mmu_update(mmu_update_t *ureqs, i
    3.62          percpu_info[cpu].foreign = NULL;
    3.63      }
    3.64  
    3.65 -    if ( unlikely(success_count != NULL) )
    3.66 -        put_user(i, success_count);
    3.67 +    /* Add incremental work we have done to the @done output parameter. */
    3.68 +    if ( unlikely(pdone != NULL) )
    3.69 +        __put_user(done + i, pdone);
    3.70  
    3.71      return rc;
    3.72  }
     4.1 --- a/xen/arch/x86/traps.c	Thu Nov 25 16:38:44 2004 +0000
     4.2 +++ b/xen/arch/x86/traps.c	Thu Nov 25 17:24:07 2004 +0000
     4.3 @@ -804,7 +804,12 @@ long do_set_trap_table(trap_info_t *trap
     4.4  
     4.5      for ( ; ; )
     4.6      {
     4.7 -        hypercall_may_preempt(__HYPERVISOR_set_trap_table, 1, traps);
     4.8 +        if ( hypercall_preempt_check() )
     4.9 +        {
    4.10 +            hypercall_create_continuation(
    4.11 +                __HYPERVISOR_set_trap_table, 1, traps);
    4.12 +            return __HYPERVISOR_set_trap_table;
    4.13 +        }
    4.14  
    4.15          if ( copy_from_user(&cur, traps, sizeof(cur)) ) return -EFAULT;
    4.16  
     5.1 --- a/xen/arch/x86/x86_32/asm-offsets.c	Thu Nov 25 16:38:44 2004 +0000
     5.2 +++ b/xen/arch/x86/x86_32/asm-offsets.c	Thu Nov 25 17:24:07 2004 +0000
     5.3 @@ -59,4 +59,12 @@ void __dummy__(void)
     5.4      OFFSET(TRAPBOUNCE_cs, struct trap_bounce, cs);
     5.5      OFFSET(TRAPBOUNCE_eip, struct trap_bounce, eip);
     5.6      BLANK();
     5.7 +
     5.8 +    OFFSET(MULTICALL_op, multicall_entry_t, op);
     5.9 +    OFFSET(MULTICALL_arg0, multicall_entry_t, args[0]);
    5.10 +    OFFSET(MULTICALL_arg1, multicall_entry_t, args[1]);
    5.11 +    OFFSET(MULTICALL_arg2, multicall_entry_t, args[2]);
    5.12 +    OFFSET(MULTICALL_arg3, multicall_entry_t, args[3]);
    5.13 +    OFFSET(MULTICALL_arg4, multicall_entry_t, args[4]);
    5.14 +    OFFSET(MULTICALL_result, multicall_entry_t, args[5]);
    5.15  }
     6.1 --- a/xen/arch/x86/x86_32/entry.S	Thu Nov 25 16:38:44 2004 +0000
     6.2 +++ b/xen/arch/x86/x86_32/entry.S	Thu Nov 25 17:24:07 2004 +0000
     6.3 @@ -70,107 +70,6 @@ ENTRY(continue_nonidle_task)
     6.4          jmp test_all_events
     6.5  
     6.6          ALIGN
     6.7 -/*
     6.8 - * HYPERVISOR_multicall(call_list, nr_calls)
     6.9 - *   Execute a list of 'nr_calls' hypercalls, pointed at by 'call_list'.
    6.10 - *   This is fairly easy except that:
    6.11 - *   1. We may fault reading the call list, and must patch that up; and
    6.12 - *   2. We cannot recursively call HYPERVISOR_multicall, or a malicious
    6.13 - *      caller could cause our stack to blow up.
    6.14 - */
    6.15 -#define MULTICALL_ENTRY_ORDER 5
    6.16 -do_multicall:
    6.17 -        popl  %eax
    6.18 -        cmpl  $SYMBOL_NAME(multicall_return_from_call),%eax
    6.19 -        je    multicall_return_from_call
    6.20 -        pushl %ebx
    6.21 -        movl  4(%esp),%ebx   /* EBX == call_list */
    6.22 -        movl  8(%esp),%ecx   /* ECX == nr_calls  */
    6.23 -        /* Ensure the entire multicall list is below HYPERVISOR_VIRT_START. */
    6.24 -        movl  %ecx,%eax
    6.25 -        shll  $MULTICALL_ENTRY_ORDER,%eax
    6.26 -        addl  %ebx,%eax      /* EAX == end of multicall list */
    6.27 -        jc    bad_multicall_address
    6.28 -        cmpl  $__HYPERVISOR_VIRT_START,%eax
    6.29 -        jnc   bad_multicall_address
    6.30 -multicall_loop:
    6.31 -        pushl %ecx
    6.32 -        movl  4(%esp),%ecx               # %ecx = struct domain
    6.33 -        movl  DOMAIN_processor(%ecx),%eax
    6.34 -        shl   $6,%eax                    # sizeof(irq_cpustat) == 64
    6.35 -        testl $~0,SYMBOL_NAME(irq_stat)(%eax,1)
    6.36 -        jnz   multicall_preempt
    6.37 -multicall_fault1: 
    6.38 -        pushl 20(%ebx)      # args[4]
    6.39 -multicall_fault2: 
    6.40 -        pushl 16(%ebx)      # args[3]
    6.41 -multicall_fault3: 
    6.42 -        pushl 12(%ebx)      # args[2]
    6.43 -multicall_fault4: 
    6.44 -        pushl 8(%ebx)       # args[1]
    6.45 -multicall_fault5: 
    6.46 -        pushl 4(%ebx)       # args[0]
    6.47 -multicall_fault6: 
    6.48 -        movl  (%ebx),%eax   # op
    6.49 -        andl  $(NR_hypercalls-1),%eax
    6.50 -        call  *SYMBOL_NAME(hypercall_table)(,%eax,4)
    6.51 -multicall_return_from_call:
    6.52 -multicall_fault7:
    6.53 -        movl  %eax,24(%ebx) # args[5] == result
    6.54 -        addl  $20,%esp
    6.55 -        popl  %ecx
    6.56 -        addl  $(1<<MULTICALL_ENTRY_ORDER),%ebx
    6.57 -        loop  multicall_loop
    6.58 -        popl  %ebx
    6.59 -        xorl  %eax,%eax
    6.60 -        jmp   ret_from_hypercall
    6.61 -
    6.62 -multicall_preempt:
    6.63 -        # NB. remaining nr_calls is already at top of stack
    6.64 -        pushl %ebx                             # call_list
    6.65 -        pushl $2                               # nr_args == 2
    6.66 -        pushl $__HYPERVISOR_multicall          # op == __HYPERVISOR_multicall
    6.67 -        call  hypercall_create_continuation
    6.68 -        addl  $16,%esp
    6.69 -        popl  %ebx
    6.70 -        movl  $__HYPERVISOR_multicall,%eax        
    6.71 -        jmp   ret_from_hypercall
    6.72 -        
    6.73 -bad_multicall_address:
    6.74 -        popl  %ebx
    6.75 -        movl  $-EFAULT,%eax
    6.76 -        jmp   ret_from_hypercall        
    6.77 -                
    6.78 -.section __ex_table,"a"
    6.79 -        .align 4
    6.80 -        .long multicall_fault1, multicall_fixup1
    6.81 -        .long multicall_fault2, multicall_fixup2
    6.82 -        .long multicall_fault3, multicall_fixup3
    6.83 -        .long multicall_fault4, multicall_fixup4
    6.84 -        .long multicall_fault5, multicall_fixup5
    6.85 -        .long multicall_fault6, multicall_fixup6
    6.86 -        .long multicall_fault7, multicall_fixup6
    6.87 -.previous
    6.88 -               
    6.89 -.section .fixup,"ax"
    6.90 -multicall_fixup6: 
    6.91 -        addl  $4,%esp
    6.92 -multicall_fixup5: 
    6.93 -        addl  $4,%esp
    6.94 -multicall_fixup4: 
    6.95 -        addl  $4,%esp
    6.96 -multicall_fixup3: 
    6.97 -        addl  $4,%esp
    6.98 -multicall_fixup2: 
    6.99 -        addl  $4,%esp
   6.100 -multicall_fixup1:
   6.101 -        addl  $4,%esp
   6.102 -        popl  %ebx
   6.103 -        movl  $-EFAULT,%eax
   6.104 -        jmp   ret_from_hypercall
   6.105 -.previous        
   6.106 -                
   6.107 -        ALIGN
   6.108  restore_all_guest:
   6.109          testb $TF_failsafe_return,DOMAIN_thread_flags(%ebx)
   6.110          jnz  failsafe_callback
     7.1 --- a/xen/common/dom_mem_ops.c	Thu Nov 25 16:38:44 2004 +0000
     7.2 +++ b/xen/common/dom_mem_ops.c	Thu Nov 25 17:24:07 2004 +0000
     7.3 @@ -15,31 +15,46 @@
     7.4  #include <xen/event.h>
     7.5  #include <asm/domain_page.h>
     7.6  
     7.7 -static long alloc_dom_mem(struct domain *d, 
     7.8 -                          unsigned long *extent_list, 
     7.9 -                          unsigned long  nr_extents,
    7.10 -                          unsigned int   extent_order)
    7.11 +/*
    7.12 + * To allow safe resume of do_dom_mem_op() after preemption, we need to know 
    7.13 + * at what point in the page list to resume. For this purpose I steal the 
    7.14 + * high-order bits of the @op parameter, which are otherwise unused and zero.
    7.15 + */
    7.16 +#define START_EXTENT_SHIFT 4 /* op[:4] == start_extent */
    7.17 +
    7.18 +#define PREEMPT_CHECK(_op)                          \
    7.19 +    if ( hypercall_preempt_check() ) {              \
    7.20 +        hypercall_create_continuation(              \
    7.21 +            __HYPERVISOR_dom_mem_op, 5,             \
    7.22 +            (_op) | (i << START_EXTENT_SHIFT),      \
    7.23 +            extent_list, nr_extents, extent_order,  \
    7.24 +            (d == current) ? DOMID_SELF : d->id);   \
    7.25 +        return __HYPERVISOR_dom_mem_op;             \
    7.26 +    }
    7.27 +
    7.28 +static long
    7.29 +alloc_dom_mem(struct domain *d, 
    7.30 +              unsigned long *extent_list, 
    7.31 +              unsigned long  start_extent,
    7.32 +              unsigned long  nr_extents,
    7.33 +              unsigned int   extent_order)
    7.34  {
    7.35      struct pfn_info *page;
    7.36      unsigned long    i;
    7.37  
    7.38 -    if ( unlikely(!access_ok(VERIFY_WRITE, extent_list, 
    7.39 -                             nr_extents*sizeof(*extent_list))) )
    7.40 -        return 0;
    7.41 +    if ( unlikely(!array_access_ok(VERIFY_WRITE, extent_list, 
    7.42 +                                   nr_extents, sizeof(*extent_list))) )
    7.43 +        return start_extent;
    7.44  
    7.45      if ( (extent_order != 0) && !IS_CAPABLE_PHYSDEV(current) )
    7.46      {
    7.47          DPRINTK("Only I/O-capable domains may allocate > order-0 memory.\n");
    7.48 -        return 0;
    7.49 +        return start_extent;
    7.50      }
    7.51  
    7.52 -    for ( i = 0; i < nr_extents; i++ )
    7.53 +    for ( i = start_extent; i < nr_extents; i++ )
    7.54      {
    7.55 -        hypercall_may_preempt(
    7.56 -            __HYPERVISOR_dom_mem_op, 5,
    7.57 -            MEMOP_increase_reservation,
    7.58 -            &extent_list[i], nr_extents-i, extent_order,
    7.59 -            (d == current) ? DOMID_SELF : d->id);
    7.60 +        PREEMPT_CHECK(MEMOP_increase_reservation);
    7.61  
    7.62          if ( unlikely((page = alloc_domheap_pages(d, extent_order)) == NULL) )
    7.63          {
    7.64 @@ -55,25 +70,23 @@ static long alloc_dom_mem(struct domain 
    7.65      return i;
    7.66  }
    7.67      
    7.68 -static long free_dom_mem(struct domain *d,
    7.69 -                         unsigned long *extent_list, 
    7.70 -                         unsigned long  nr_extents,
    7.71 -                         unsigned int   extent_order)
    7.72 +static long
    7.73 +free_dom_mem(struct domain *d,
    7.74 +             unsigned long *extent_list, 
    7.75 +             unsigned long  start_extent,
    7.76 +             unsigned long  nr_extents,
    7.77 +             unsigned int   extent_order)
    7.78  {
    7.79      struct pfn_info *page;
    7.80      unsigned long    i, j, mpfn;
    7.81  
    7.82 -    if ( unlikely(!access_ok(VERIFY_READ, extent_list, 
    7.83 -                             nr_extents*sizeof(*extent_list))) )
    7.84 -        return 0;
    7.85 +    if ( unlikely(!array_access_ok(VERIFY_READ, extent_list, 
    7.86 +                                   nr_extents, sizeof(*extent_list))) )
    7.87 +        return start_extent;
    7.88  
    7.89 -    for ( i = 0; i < nr_extents; i++ )
    7.90 +    for ( i = start_extent; i < nr_extents; i++ )
    7.91      {
    7.92 -        hypercall_may_preempt(
    7.93 -            __HYPERVISOR_dom_mem_op, 5,
    7.94 -            MEMOP_decrease_reservation,
    7.95 -            &extent_list[i], nr_extents-i, extent_order,
    7.96 -            (d == current) ? DOMID_SELF : d->id);
    7.97 +        PREEMPT_CHECK(MEMOP_decrease_reservation);
    7.98  
    7.99          if ( unlikely(__get_user(mpfn, &extent_list[i]) != 0) )
   7.100              return i;
   7.101 @@ -106,15 +119,24 @@ static long free_dom_mem(struct domain *
   7.102  
   7.103      return i;
   7.104  }
   7.105 -    
   7.106 -long do_dom_mem_op(unsigned int   op, 
   7.107 -                   unsigned long *extent_list, 
   7.108 -                   unsigned long  nr_extents,
   7.109 -                   unsigned int   extent_order,
   7.110 -		   domid_t        domid)
   7.111 +
   7.112 +long
   7.113 +do_dom_mem_op(unsigned long  op, 
   7.114 +              unsigned long *extent_list, 
   7.115 +              unsigned long  nr_extents,
   7.116 +              unsigned int   extent_order,
   7.117 +              domid_t        domid)
   7.118  {
   7.119      struct domain *d;
   7.120 -    long           rc;
   7.121 +    unsigned long  rc, start_extent;
   7.122 +
   7.123 +    /* Extract @start_extent from @op. */
   7.124 +    start_extent  = op >> START_EXTENT_SHIFT;
   7.125 +    op           &= (1 << START_EXTENT_SHIFT) - 1;
   7.126 +
   7.127 +    if ( unlikely(start_extent > nr_extents) || 
   7.128 +         unlikely(nr_extents > (~0UL >> START_EXTENT_SHIFT)) )
   7.129 +        return -EINVAL;
   7.130  
   7.131      if ( likely(domid == DOMID_SELF) )
   7.132          d = current;
   7.133 @@ -126,10 +148,12 @@ long do_dom_mem_op(unsigned int   op,
   7.134      switch ( op )
   7.135      {
   7.136      case MEMOP_increase_reservation:
   7.137 -        rc = alloc_dom_mem(d, extent_list, nr_extents, extent_order);
   7.138 +        rc = alloc_dom_mem(
   7.139 +            d, extent_list, start_extent, nr_extents, extent_order);
   7.140  	break;
   7.141      case MEMOP_decrease_reservation:
   7.142 -        rc = free_dom_mem(d, extent_list, nr_extents, extent_order);
   7.143 +        rc = free_dom_mem(
   7.144 +            d, extent_list, start_extent, nr_extents, extent_order);
   7.145  	break;
   7.146      default:
   7.147          rc = -ENOSYS;
     8.1 --- a/xen/common/grant_table.c	Thu Nov 25 16:38:44 2004 +0000
     8.2 +++ b/xen/common/grant_table.c	Thu Nov 25 17:24:07 2004 +0000
     8.3 @@ -446,14 +446,14 @@ do_grant_table_op(
     8.4      switch ( cmd )
     8.5      {
     8.6      case GNTTABOP_map_grant_ref:
     8.7 -        if ( unlikely(!access_ok(VERIFY_WRITE, uop,
     8.8 -                                 count * sizeof(gnttab_map_grant_ref_t))) )
     8.9 +        if ( unlikely(!array_access_ok(
    8.10 +            VERIFY_WRITE, uop, count, sizeof(gnttab_map_grant_ref_t))) )
    8.11              return -EFAULT;
    8.12          rc = gnttab_map_grant_ref((gnttab_map_grant_ref_t *)uop, count);
    8.13          break;
    8.14      case GNTTABOP_unmap_grant_ref:
    8.15 -        if ( unlikely(!access_ok(VERIFY_WRITE, uop,
    8.16 -                                 count * sizeof(gnttab_unmap_grant_ref_t))) )
    8.17 +        if ( unlikely(!array_access_ok(
    8.18 +            VERIFY_WRITE, uop, count, sizeof(gnttab_unmap_grant_ref_t))) )
    8.19              return -EFAULT;
    8.20          rc = gnttab_unmap_grant_ref((gnttab_unmap_grant_ref_t *)uop, count);
    8.21          break;
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/xen/common/multicall.c	Thu Nov 25 17:24:07 2004 +0000
     9.3 @@ -0,0 +1,76 @@
     9.4 +/******************************************************************************
     9.5 + * multicall.c
     9.6 + */
     9.7 +
     9.8 +#include <xen/config.h>
     9.9 +#include <xen/types.h>
    9.10 +#include <xen/lib.h>
    9.11 +#include <xen/mm.h>
    9.12 +#include <xen/perfc.h>
    9.13 +#include <xen/sched.h>
    9.14 +#include <xen/event.h>
    9.15 +#include <xen/multicall.h>
    9.16 +
    9.17 +struct mc_state mc_state[NR_CPUS];
    9.18 +
    9.19 +long do_multicall(multicall_entry_t *call_list, unsigned int nr_calls)
    9.20 +{
    9.21 +    struct mc_state *mcs = &mc_state[smp_processor_id()];
    9.22 +    unsigned int     i;
    9.23 +
    9.24 +    if ( unlikely(__test_and_set_bit(_MCSF_in_multicall, &mcs->flags)) )
    9.25 +    {
    9.26 +        DPRINTK("Multicall reentry is disallowed.\n");
    9.27 +        return -EINVAL;
    9.28 +    }
    9.29 +
    9.30 +    if ( unlikely(!array_access_ok(VERIFY_WRITE, call_list, 
    9.31 +                                   nr_calls, sizeof(*call_list))) )
    9.32 +    {
    9.33 +        DPRINTK("Bad memory range %p for %u*%u bytes.\n",
    9.34 +                call_list, nr_calls, sizeof(*call_list));
    9.35 +        goto fault;
    9.36 +    }
    9.37 +
    9.38 +    for ( i = 0; i < nr_calls; i++ )
    9.39 +    {
    9.40 +        if ( unlikely(__copy_from_user(&mcs->call, &call_list[i], 
    9.41 +                                       sizeof(*call_list))) )
    9.42 +        {
    9.43 +            DPRINTK("Error copying from user range %p for %u bytes.\n",
    9.44 +                    &call_list[i], sizeof(*call_list));
    9.45 +            goto fault;
    9.46 +        }
    9.47 +
    9.48 +        do_multicall_call(&mcs->call);
    9.49 +
    9.50 +        if ( unlikely(__put_user(mcs->call.args[5], &call_list[i].args[5])) )
    9.51 +        {
    9.52 +            DPRINTK("Error writing result back to multicall block.\n");
    9.53 +            goto fault;
    9.54 +        }
    9.55 +
    9.56 +        if ( hypercall_preempt_check() )
    9.57 +        {
    9.58 +            /* If the sub-call wasn't preempted, skip over it. */
    9.59 +            if ( !test_bit(_MCSF_call_preempted, &mcs->flags) )
    9.60 +                i++;
    9.61 +
    9.62 +            /* Only create a continuation if there is work left to be done. */
    9.63 +            if ( i < nr_calls )
    9.64 +            {
    9.65 +                mcs->flags = 0;
    9.66 +                hypercall_create_continuation(
    9.67 +                    __HYPERVISOR_multicall, 2, &call_list[i], nr_calls-i);
    9.68 +                return __HYPERVISOR_multicall;
    9.69 +            }
    9.70 +        }
    9.71 +    }
    9.72 +
    9.73 +    mcs->flags = 0;
    9.74 +    return 0;
    9.75 +
    9.76 + fault:
    9.77 +    mcs->flags = 0;
    9.78 +    return -EFAULT;
    9.79 +}
    10.1 --- a/xen/include/asm-x86/mm.h	Thu Nov 25 16:38:44 2004 +0000
    10.2 +++ b/xen/include/asm-x86/mm.h	Thu Nov 25 17:24:07 2004 +0000
    10.3 @@ -221,9 +221,6 @@ extern unsigned long *machine_to_phys_ma
    10.4  #define machine_to_phys_mapping ((unsigned long *)RDWR_MPT_VIRT_START)
    10.5  #endif
    10.6  
    10.7 -/* Part of the domain API. */
    10.8 -int do_mmu_update(mmu_update_t *updates, int count, int *success_count);
    10.9 -
   10.10  #define DEFAULT_GDT_ENTRIES     (LAST_RESERVED_GDT_ENTRY+1)
   10.11  #define DEFAULT_GDT_ADDRESS     ((unsigned long)gdt_table)
   10.12  
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/xen/include/asm-x86/multicall.h	Thu Nov 25 17:24:07 2004 +0000
    11.3 @@ -0,0 +1,26 @@
    11.4 +/******************************************************************************
    11.5 + * asm-x86/multicall.h
    11.6 + */
    11.7 +
    11.8 +#ifndef __ASM_X86_MULTICALL_H__
    11.9 +#define __ASM_X86_MULTICALL_H__
   11.10 +
   11.11 +#include <asm-x86/x86_32/asm_defns.h>
   11.12 +
   11.13 +#define do_multicall_call(_call)                       \
   11.14 +    do {                                               \
   11.15 +        __asm__ __volatile__ (                         \
   11.16 +            "pushl "STR(MULTICALL_arg4)"(%0); "        \
   11.17 +            "pushl "STR(MULTICALL_arg3)"(%0); "        \
   11.18 +            "pushl "STR(MULTICALL_arg2)"(%0); "        \
   11.19 +            "pushl "STR(MULTICALL_arg1)"(%0); "        \
   11.20 +            "pushl "STR(MULTICALL_arg0)"(%0); "        \
   11.21 +            "movl  "STR(MULTICALL_op)"(%0),%%eax; "    \
   11.22 +            "andl  $("STR(NR_hypercalls)"-1),%%eax; "  \
   11.23 +            "call  *hypercall_table(,%%eax,4); "       \
   11.24 +            "movl  %%eax,"STR(MULTICALL_result)"(%0); "\
   11.25 +            "addl  $20,%%esp; "                        \
   11.26 +            : : "b" (_call) : "eax", "ecx", "edx" );   \
   11.27 +    } while ( 0 )
   11.28 +
   11.29 +#endif /* __ASM_X86_MULTICALL_H__ */
    12.1 --- a/xen/include/asm-x86/x86_32/uaccess.h	Thu Nov 25 16:38:44 2004 +0000
    12.2 +++ b/xen/include/asm-x86/x86_32/uaccess.h	Thu Nov 25 17:24:07 2004 +0000
    12.3 @@ -66,6 +66,9 @@ extern struct movsl_mask {
    12.4   */
    12.5  #define access_ok(type,addr,size) (likely(__range_ok(addr,size) == 0))
    12.6  
    12.7 +#define array_access_ok(type,addr,count,size) \
    12.8 +    (likely(count < (~0UL/size)) && access_ok(type,addr,count*size))
    12.9 +
   12.10  /*
   12.11   * The exception table consists of pairs of addresses: the first is the
   12.12   * address of an instruction that is allowed to fault, and the second is
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/xen/include/xen/multicall.h	Thu Nov 25 17:24:07 2004 +0000
    13.3 @@ -0,0 +1,21 @@
    13.4 +/******************************************************************************
    13.5 + * multicall.h
    13.6 + */
    13.7 +
    13.8 +#ifndef __XEN_MULTICALL_H__
    13.9 +#define __XEN_MULTICALL_H__
   13.10 +
   13.11 +#include <asm/multicall.h>
   13.12 +
   13.13 +#define _MCSF_in_multicall   0
   13.14 +#define _MCSF_call_preempted 1
   13.15 +#define MCSF_in_multicall    (1<<_MCSF_in_multicall)
   13.16 +#define MCSF_call_preempted  (1<<_MCSF_call_preempted)
   13.17 +struct mc_state {
   13.18 +    unsigned long     flags;
   13.19 +    multicall_entry_t call;
   13.20 +} __cacheline_aligned;
   13.21 +
   13.22 +extern struct mc_state mc_state[NR_CPUS];
   13.23 +
   13.24 +#endif /* __XEN_MULTICALL_H__ */
    14.1 --- a/xen/include/xen/sched.h	Thu Nov 25 16:38:44 2004 +0000
    14.2 +++ b/xen/include/xen/sched.h	Thu Nov 25 17:24:07 2004 +0000
    14.3 @@ -219,12 +219,8 @@ void continue_cpu_idle_loop(void);
    14.4  void continue_nonidle_task(void);
    14.5  
    14.6  void hypercall_create_continuation(unsigned int op, unsigned int nr_args, ...);
    14.7 -#define hypercall_may_preempt(_op, _nr_args, _args...)               \
    14.8 -    do {                                                             \
    14.9 -        if ( unlikely(softirq_pending(smp_processor_id())) ) {       \
   14.10 -            hypercall_create_continuation(_op , _nr_args , ##_args); \
   14.11 -            return _op;                                              \
   14.12 -    } } while ( 0 )
   14.13 +#define hypercall_preempt_check() \
   14.14 +    (unlikely(softirq_pending(smp_processor_id())))
   14.15  
   14.16  /* This domain_hash and domain_list are protected by the domlist_lock. */
   14.17  #define DOMAIN_HASH_SIZE 256