ia64/xen-unstable

changeset 3140:4a88ba0e9ef1

bitkeeper revision 1.1159.183.13 (41a6157a-zf76ce2nvimtPMjs8dMWQ)

Merge scramble.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-2.0-testing.bk
into scramble.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-unstable.bk
author kaf24@scramble.cl.cam.ac.uk
date Thu Nov 25 17:25:14 2004 +0000 (2004-11-25)
parents 452731aa69b6 b013a6b30d9e
children dc6347709bff
files .rootkeys linux-2.4.28-xen-sparse/arch/xen/mm/fault.c linux-2.6.9-xen-sparse/arch/xen/i386/mm/hypervisor.c linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/page.h linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h 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/arch/x86/x86_32/mm.c xen/arch/x86/x86_32/seg_fixup.c xen/common/dom_mem_ops.c xen/common/grant_table.c xen/common/multicall.c xen/include/asm-x86/desc.h 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 15:12:06 2004 +0000
     1.2 +++ b/.rootkeys	Thu Nov 25 17:25:14 2004 +0000
     1.3 @@ -703,6 +703,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 @@ -798,6 +799,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 @@ -859,6 +861,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/linux-2.4.28-xen-sparse/arch/xen/mm/fault.c	Thu Nov 25 15:12:06 2004 +0000
     2.2 +++ b/linux-2.4.28-xen-sparse/arch/xen/mm/fault.c	Thu Nov 25 17:25:14 2004 +0000
     2.3 @@ -84,27 +84,6 @@ asmlinkage void do_page_fault(struct pt_
     2.4          error_code &= 3;
     2.5          error_code |= (regs->xcs & 2) << 1;
     2.6  
     2.7 -#if MMU_UPDATE_DEBUG > 0
     2.8 -        if ( (error_code == 0) && (address >= TASK_SIZE) )
     2.9 -        {
    2.10 -            unsigned long paddr = __pa(address);
    2.11 -            int i;
    2.12 -            for ( i = 0; i < mmu_update_queue_idx; i++ )
    2.13 -            {
    2.14 -                if ( update_debug_queue[i].ptr == paddr )
    2.15 -                {
    2.16 -                    printk("XXX now(EIP=%08lx:ptr=%08lx) "
    2.17 -                           "then(%s/%d:p/v=%08lx/%08lx)\n",
    2.18 -                           regs->eip, address,
    2.19 -                           update_debug_queue[i].file,
    2.20 -                           update_debug_queue[i].line,
    2.21 -                           update_debug_queue[i].ptr,
    2.22 -                           update_debug_queue[i].val);
    2.23 -                }
    2.24 -            }
    2.25 -        }
    2.26 -#endif
    2.27 -
    2.28  	if ( flush_page_update_queue() != 0 )
    2.29  		return;
    2.30  
     3.1 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/mm/hypervisor.c	Thu Nov 25 15:12:06 2004 +0000
     3.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/mm/hypervisor.c	Thu Nov 25 17:25:14 2004 +0000
     3.3 @@ -56,62 +56,6 @@ static mmu_update_t update_queue[QUEUE_S
     3.4  unsigned int mmu_update_queue_idx = 0;
     3.5  #define idx mmu_update_queue_idx
     3.6  
     3.7 -#if MMU_UPDATE_DEBUG > 0
     3.8 -page_update_debug_t update_debug_queue[QUEUE_SIZE] = {{0}};
     3.9 -#undef queue_l1_entry_update
    3.10 -#undef queue_l2_entry_update
    3.11 -#endif
    3.12 -#if MMU_UPDATE_DEBUG > 3
    3.13 -static void DEBUG_allow_pt_reads(void)
    3.14 -{
    3.15 -    pte_t *pte;
    3.16 -    mmu_update_t update;
    3.17 -    int i;
    3.18 -    for ( i = idx-1; i >= 0; i-- )
    3.19 -    {
    3.20 -        pte = update_debug_queue[i].ptep;
    3.21 -        if ( pte == NULL ) continue;
    3.22 -        update_debug_queue[i].ptep = NULL;
    3.23 -        update.ptr = virt_to_machine(pte);
    3.24 -        update.val = update_debug_queue[i].pteval;
    3.25 -        HYPERVISOR_mmu_update(&update, 1, NULL);
    3.26 -    }
    3.27 -}
    3.28 -static void DEBUG_disallow_pt_read(unsigned long va)
    3.29 -{
    3.30 -    pte_t *pte;
    3.31 -    pmd_t *pmd;
    3.32 -    pgd_t *pgd;
    3.33 -    unsigned long pteval;
    3.34 -    /*
    3.35 -     * We may fault because of an already outstanding update.
    3.36 -     * That's okay -- it'll get fixed up in the fault handler.
    3.37 -     */
    3.38 -    mmu_update_t update;
    3.39 -    pgd = pgd_offset_k(va);
    3.40 -    pmd = pmd_offset(pgd, va);
    3.41 -    pte = pte_offset_kernel(pmd, va); /* XXXcl */
    3.42 -    update.ptr = virt_to_machine(pte);
    3.43 -    pteval = *(unsigned long *)pte;
    3.44 -    update.val = pteval & ~_PAGE_PRESENT;
    3.45 -    HYPERVISOR_mmu_update(&update, 1, NULL);
    3.46 -    update_debug_queue[idx].ptep = pte;
    3.47 -    update_debug_queue[idx].pteval = pteval;
    3.48 -}
    3.49 -#endif
    3.50 -
    3.51 -#if MMU_UPDATE_DEBUG > 1
    3.52 -#undef queue_pt_switch
    3.53 -#undef queue_tlb_flush
    3.54 -#undef queue_invlpg
    3.55 -#undef queue_pgd_pin
    3.56 -#undef queue_pgd_unpin
    3.57 -#undef queue_pte_pin
    3.58 -#undef queue_pte_unpin
    3.59 -#undef queue_set_ldt
    3.60 -#endif
    3.61 -
    3.62 -
    3.63  /*
    3.64   * MULTICALL_flush_page_update_queue:
    3.65   *   This is a version of the flush which queues as part of a multicall.
    3.66 @@ -123,13 +67,6 @@ void MULTICALL_flush_page_update_queue(v
    3.67      spin_lock_irqsave(&update_lock, flags);
    3.68      if ( (_idx = idx) != 0 ) 
    3.69      {
    3.70 -#if MMU_UPDATE_DEBUG > 1
    3.71 -	    if (idx > 1)
    3.72 -        printk("Flushing %d entries from pt update queue\n", idx);
    3.73 -#endif
    3.74 -#if MMU_UPDATE_DEBUG > 3
    3.75 -        DEBUG_allow_pt_reads();
    3.76 -#endif
    3.77          idx = 0;
    3.78          wmb(); /* Make sure index is cleared first to avoid double updates. */
    3.79          queue_multicall3(__HYPERVISOR_mmu_update, 
    3.80 @@ -143,13 +80,6 @@ void MULTICALL_flush_page_update_queue(v
    3.81  static inline void __flush_page_update_queue(void)
    3.82  {
    3.83      unsigned int _idx = idx;
    3.84 -#if MMU_UPDATE_DEBUG > 1
    3.85 -    if (idx > 1)
    3.86 -    printk("Flushing %d entries from pt update queue\n", idx);
    3.87 -#endif
    3.88 -#if MMU_UPDATE_DEBUG > 3
    3.89 -    DEBUG_allow_pt_reads();
    3.90 -#endif
    3.91      idx = 0;
    3.92      wmb(); /* Make sure index is cleared first to avoid double updates. */
    3.93      if ( unlikely(HYPERVISOR_mmu_update(update_queue, _idx, NULL) < 0) )
    3.94 @@ -183,9 +113,6 @@ void queue_l1_entry_update(pte_t *ptr, u
    3.95  {
    3.96      unsigned long flags;
    3.97      spin_lock_irqsave(&update_lock, flags);
    3.98 -#if MMU_UPDATE_DEBUG > 3
    3.99 -    DEBUG_disallow_pt_read((unsigned long)ptr);
   3.100 -#endif
   3.101      update_queue[idx].ptr = virt_to_machine(ptr);
   3.102      update_queue[idx].val = val;
   3.103      increment_index();
   3.104 @@ -303,9 +230,6 @@ void xen_l1_entry_update(pte_t *ptr, uns
   3.105  {
   3.106      unsigned long flags;
   3.107      spin_lock_irqsave(&update_lock, flags);
   3.108 -#if MMU_UPDATE_DEBUG > 3
   3.109 -    DEBUG_disallow_pt_read((unsigned long)ptr);
   3.110 -#endif
   3.111      update_queue[idx].ptr = virt_to_machine(ptr);
   3.112      update_queue[idx].val = val;
   3.113      increment_index_and_flush();
     4.1 --- a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/page.h	Thu Nov 25 15:12:06 2004 +0000
     4.2 +++ b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/page.h	Thu Nov 25 17:25:14 2004 +0000
     4.3 @@ -90,16 +90,7 @@ typedef struct { unsigned long pmd; } pm
     4.4  typedef struct { unsigned long pgd; } pgd_t;
     4.5  typedef struct { unsigned long pgprot; } pgprot_t;
     4.6  #define boot_pte_t pte_t /* or would you rather have a typedef */
     4.7 -#if 0				/* XXXcl for MMU_UPDATE_DEBUG */
     4.8 -static inline unsigned long pte_val(pte_t x)
     4.9 -{
    4.10 -	unsigned long ret = x.pte_low;
    4.11 -	if ( (ret & 1) ) ret = machine_to_phys(ret);
    4.12 -	return ret;
    4.13 -}
    4.14 -#else
    4.15  #define pte_val(x)	(((x).pte_low & 1) ? machine_to_phys((x).pte_low) : (x).pte_low)
    4.16 -#endif
    4.17  #define pte_val_ma(x)	((x).pte_low)
    4.18  #define HPAGE_SHIFT	22
    4.19  #endif
     5.1 --- a/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h	Thu Nov 25 15:12:06 2004 +0000
     5.2 +++ b/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h	Thu Nov 25 17:25:14 2004 +0000
     5.3 @@ -94,91 +94,6 @@ void xen_pte_pin(unsigned long ptr);
     5.4  void xen_pte_unpin(unsigned long ptr);
     5.5  void xen_set_ldt(unsigned long ptr, unsigned long bytes);
     5.6  void xen_machphys_update(unsigned long mfn, unsigned long pfn);
     5.7 -#define MMU_UPDATE_DEBUG 0
     5.8 -
     5.9 -#if MMU_UPDATE_DEBUG > 0
    5.10 -typedef struct {
    5.11 -    void *ptr;
    5.12 -    unsigned long val, pteval;
    5.13 -    void *ptep;
    5.14 -    int line; char *file;
    5.15 -} page_update_debug_t;
    5.16 -extern page_update_debug_t update_debug_queue[];
    5.17 -#define queue_l1_entry_update(_p,_v) ({                           \
    5.18 - update_debug_queue[mmu_update_queue_idx].ptr  = (_p);             \
    5.19 - update_debug_queue[mmu_update_queue_idx].val  = (_v);             \
    5.20 - update_debug_queue[mmu_update_queue_idx].line = __LINE__;         \
    5.21 - update_debug_queue[mmu_update_queue_idx].file = __FILE__;         \
    5.22 - queue_l1_entry_update((_p),(_v));                                \
    5.23 -})
    5.24 -#define queue_l2_entry_update(_p,_v) ({                           \
    5.25 - update_debug_queue[mmu_update_queue_idx].ptr  = (_p);             \
    5.26 - update_debug_queue[mmu_update_queue_idx].val  = (_v);             \
    5.27 - update_debug_queue[mmu_update_queue_idx].line = __LINE__;         \
    5.28 - update_debug_queue[mmu_update_queue_idx].file = __FILE__;         \
    5.29 - queue_l2_entry_update((_p),(_v));                                \
    5.30 -})
    5.31 -#endif
    5.32 -
    5.33 -#if MMU_UPDATE_DEBUG > 1
    5.34 -#if MMU_UPDATE_DEBUG > 2
    5.35 -#undef queue_l1_entry_update
    5.36 -#define queue_l1_entry_update(_p,_v) ({                           \
    5.37 - update_debug_queue[mmu_update_queue_idx].ptr  = (_p);             \
    5.38 - update_debug_queue[mmu_update_queue_idx].val  = (_v);             \
    5.39 - update_debug_queue[mmu_update_queue_idx].line = __LINE__;         \
    5.40 - update_debug_queue[mmu_update_queue_idx].file = __FILE__;         \
    5.41 - printk("L1 %s %d: %p/%08lx (%08lx -> %08lx)\n", __FILE__, __LINE__,  \
    5.42 -        (_p), virt_to_machine(_p), pte_val(*(_p)),                 \
    5.43 -        (unsigned long)(_v));                                     \
    5.44 - queue_l1_entry_update((_p),(_v));                                \
    5.45 -})
    5.46 -#endif
    5.47 -#undef queue_l2_entry_update
    5.48 -#define queue_l2_entry_update(_p,_v) ({                           \
    5.49 - update_debug_queue[mmu_update_queue_idx].ptr  = (_p);             \
    5.50 - update_debug_queue[mmu_update_queue_idx].val  = (_v);             \
    5.51 - update_debug_queue[mmu_update_queue_idx].line = __LINE__;         \
    5.52 - update_debug_queue[mmu_update_queue_idx].file = __FILE__;         \
    5.53 - printk("L2 %s %d: %p/%08lx (%08lx -> %08lx)\n", __FILE__, __LINE__,  \
    5.54 -        (_p), virt_to_machine(_p), pmd_val(*_p),                  \
    5.55 -        (unsigned long)(_v));                                     \
    5.56 - queue_l2_entry_update((_p),(_v));                                \
    5.57 -})
    5.58 -#define queue_pt_switch(_p) ({                                    \
    5.59 - printk("PTSWITCH %s %d: %08lx\n", __FILE__, __LINE__, (_p));     \
    5.60 - queue_pt_switch(_p);                                             \
    5.61 -})   
    5.62 -#define queue_tlb_flush() ({                                      \
    5.63 - printk("TLB FLUSH %s %d\n", __FILE__, __LINE__);                 \
    5.64 - queue_tlb_flush();                                               \
    5.65 -})   
    5.66 -#define queue_invlpg(_p) ({                                       \
    5.67 - printk("INVLPG %s %d: %08lx\n", __FILE__, __LINE__, (_p));       \
    5.68 - queue_invlpg(_p);                                                \
    5.69 -})   
    5.70 -#define queue_pgd_pin(_p) ({                                      \
    5.71 - printk("PGD PIN %s %d: %08lx/%08lx\n", __FILE__, __LINE__, (_p), \
    5.72 -	phys_to_machine(_p));                                     \
    5.73 - queue_pgd_pin(_p);                                               \
    5.74 -})   
    5.75 -#define queue_pgd_unpin(_p) ({                                    \
    5.76 - printk("PGD UNPIN %s %d: %08lx\n", __FILE__, __LINE__, (_p));    \
    5.77 - queue_pgd_unpin(_p);                                             \
    5.78 -})   
    5.79 -#define queue_pte_pin(_p) ({                                      \
    5.80 - printk("PTE PIN %s %d: %08lx\n", __FILE__, __LINE__, (_p));      \
    5.81 - queue_pte_pin(_p);                                               \
    5.82 -})   
    5.83 -#define queue_pte_unpin(_p) ({                                    \
    5.84 - printk("PTE UNPIN %s %d: %08lx\n", __FILE__, __LINE__, (_p));    \
    5.85 - queue_pte_unpin(_p);                                             \
    5.86 -})   
    5.87 -#define queue_set_ldt(_p,_l) ({                                        \
    5.88 - printk("SETL LDT %s %d: %08lx %d\n", __FILE__, __LINE__, (_p), (_l)); \
    5.89 - queue_set_ldt((_p), (_l));                                            \
    5.90 -})   
    5.91 -#endif
    5.92  
    5.93  void _flush_page_update_queue(void);
    5.94  static inline int flush_page_update_queue(void)
     6.1 --- a/xen/arch/x86/domain.c	Thu Nov 25 15:12:06 2004 +0000
     6.2 +++ b/xen/arch/x86/domain.c	Thu Nov 25 17:25:14 2004 +0000
     6.3 @@ -32,6 +32,7 @@
     6.4  #include <asm/shadow.h>
     6.5  #include <xen/console.h>
     6.6  #include <xen/elf.h>
     6.7 +#include <xen/multicall.h>
     6.8  
     6.9  #if !defined(CONFIG_X86_64BITMODE)
    6.10  /* No ring-3 access in initial page tables. */
    6.11 @@ -428,17 +429,31 @@ long do_iopl(domid_t domain, unsigned in
    6.12  
    6.13  void hypercall_create_continuation(unsigned int op, unsigned int nr_args, ...)
    6.14  {
    6.15 -    execution_context_t *ec = get_execution_context();
    6.16 -    unsigned long *preg = &ec->ebx;
    6.17 +    struct mc_state *mcs = &mc_state[smp_processor_id()];
    6.18 +    execution_context_t *ec;
    6.19 +    unsigned long *preg;
    6.20      unsigned int i;
    6.21      va_list args;
    6.22  
    6.23 -    ec->eax  = op;
    6.24 -    ec->eip -= 2;  /* re-execute 'int 0x82' */
    6.25 +    va_start(args, nr_args);
    6.26 +
    6.27 +    if ( test_bit(_MCSF_in_multicall, &mcs->flags) )
    6.28 +    {
    6.29 +        __set_bit(_MCSF_call_preempted, &mcs->flags);
    6.30  
    6.31 -    va_start(args, nr_args);
    6.32 -    for ( i = 0; i < nr_args; i++ )
    6.33 -        *preg++ = va_arg(args, unsigned long);
    6.34 +        for ( i = 0; i < nr_args; i++ )
    6.35 +            mcs->call.args[i] = va_arg(args, unsigned long);
    6.36 +    }
    6.37 +    else
    6.38 +    {
    6.39 +        ec       = get_execution_context();
    6.40 +        ec->eax  = op;
    6.41 +        ec->eip -= 2;  /* re-execute 'int 0x82' */
    6.42 +        
    6.43 +        for ( i = 0, preg = &ec->ebx; i < nr_args; i++, preg++ )
    6.44 +            *preg = va_arg(args, unsigned long);
    6.45 +    }
    6.46 +
    6.47      va_end(args);
    6.48  }
    6.49  
     7.1 --- a/xen/arch/x86/memory.c	Thu Nov 25 15:12:06 2004 +0000
     7.2 +++ b/xen/arch/x86/memory.c	Thu Nov 25 17:25:14 2004 +0000
     7.3 @@ -1277,14 +1277,20 @@ static int do_extended_command(unsigned 
     7.4      return okay;
     7.5  }
     7.6  
     7.7 +int do_mmu_update(
     7.8 +    mmu_update_t *ureqs, unsigned int count, unsigned int *pdone)
     7.9 +{
    7.10 +/*
    7.11 + * We steal the m.s.b. of the @count parameter to indicate whether this
    7.12 + * invocation of do_mmu_update() is resuming a previously preempted call.
    7.13 + */
    7.14 +#define MMU_UPDATE_PREEMPTED  (~(~0U>>1))
    7.15  
    7.16 -int do_mmu_update(mmu_update_t *ureqs, int count, int *success_count)
    7.17 -{
    7.18      mmu_update_t req;
    7.19      unsigned long va = 0, deferred_ops, pfn, prev_pfn = 0;
    7.20      struct pfn_info *page;
    7.21      int rc = 0, okay = 1, i, cpu = smp_processor_id();
    7.22 -    unsigned int cmd;
    7.23 +    unsigned int cmd, done = 0;
    7.24      unsigned long prev_spfn = 0;
    7.25      l1_pgentry_t *prev_spl1e = 0;
    7.26      struct domain *d = current;
    7.27 @@ -1295,13 +1301,30 @@ int do_mmu_update(mmu_update_t *ureqs, i
    7.28  
    7.29      cleanup_writable_pagetable(d, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE);
    7.30  
    7.31 -    if ( unlikely(!access_ok(VERIFY_READ, ureqs, count * sizeof(req))) )
    7.32 +    /*
    7.33 +     * If we are resuming after preemption, read how much work we have already
    7.34 +     * done. This allows us to set the @done output parameter correctly.
    7.35 +     */
    7.36 +    if ( unlikely(count & MMU_UPDATE_PREEMPTED) )
    7.37 +    {
    7.38 +        count &= ~MMU_UPDATE_PREEMPTED;
    7.39 +        if ( unlikely(pdone != NULL) )
    7.40 +            (void)get_user(done, pdone);
    7.41 +    }
    7.42 +
    7.43 +    if ( unlikely(!array_access_ok(VERIFY_READ, ureqs, count, sizeof(req))) )
    7.44          return -EFAULT;
    7.45  
    7.46      for ( i = 0; i < count; i++ )
    7.47      {
    7.48 -        hypercall_may_preempt(
    7.49 -            __HYPERVISOR_mmu_update, 3, ureqs, count-i, success_count);
    7.50 +        if ( hypercall_preempt_check() )
    7.51 +        {
    7.52 +            hypercall_create_continuation(
    7.53 +                __HYPERVISOR_mmu_update, 3, ureqs, 
    7.54 +                (count - i) | MMU_UPDATE_PREEMPTED, pdone);
    7.55 +            rc = __HYPERVISOR_mmu_update;
    7.56 +            break;
    7.57 +        }
    7.58  
    7.59          if ( unlikely(__copy_from_user(&req, ureqs, sizeof(req)) != 0) )
    7.60          {
    7.61 @@ -1457,8 +1480,9 @@ int do_mmu_update(mmu_update_t *ureqs, i
    7.62          percpu_info[cpu].foreign = NULL;
    7.63      }
    7.64  
    7.65 -    if ( unlikely(success_count != NULL) )
    7.66 -        put_user(i, success_count);
    7.67 +    /* Add incremental work we have done to the @done output parameter. */
    7.68 +    if ( unlikely(pdone != NULL) )
    7.69 +        __put_user(done + i, pdone);
    7.70  
    7.71      return rc;
    7.72  }
     8.1 --- a/xen/arch/x86/traps.c	Thu Nov 25 15:12:06 2004 +0000
     8.2 +++ b/xen/arch/x86/traps.c	Thu Nov 25 17:25:14 2004 +0000
     8.3 @@ -804,7 +804,12 @@ long do_set_trap_table(trap_info_t *trap
     8.4  
     8.5      for ( ; ; )
     8.6      {
     8.7 -        hypercall_may_preempt(__HYPERVISOR_set_trap_table, 1, traps);
     8.8 +        if ( hypercall_preempt_check() )
     8.9 +        {
    8.10 +            hypercall_create_continuation(
    8.11 +                __HYPERVISOR_set_trap_table, 1, traps);
    8.12 +            return __HYPERVISOR_set_trap_table;
    8.13 +        }
    8.14  
    8.15          if ( copy_from_user(&cur, traps, sizeof(cur)) ) return -EFAULT;
    8.16  
     9.1 --- a/xen/arch/x86/x86_32/asm-offsets.c	Thu Nov 25 15:12:06 2004 +0000
     9.2 +++ b/xen/arch/x86/x86_32/asm-offsets.c	Thu Nov 25 17:25:14 2004 +0000
     9.3 @@ -59,4 +59,12 @@ void __dummy__(void)
     9.4      OFFSET(TRAPBOUNCE_cs, struct trap_bounce, cs);
     9.5      OFFSET(TRAPBOUNCE_eip, struct trap_bounce, eip);
     9.6      BLANK();
     9.7 +
     9.8 +    OFFSET(MULTICALL_op, multicall_entry_t, op);
     9.9 +    OFFSET(MULTICALL_arg0, multicall_entry_t, args[0]);
    9.10 +    OFFSET(MULTICALL_arg1, multicall_entry_t, args[1]);
    9.11 +    OFFSET(MULTICALL_arg2, multicall_entry_t, args[2]);
    9.12 +    OFFSET(MULTICALL_arg3, multicall_entry_t, args[3]);
    9.13 +    OFFSET(MULTICALL_arg4, multicall_entry_t, args[4]);
    9.14 +    OFFSET(MULTICALL_result, multicall_entry_t, args[5]);
    9.15  }
    10.1 --- a/xen/arch/x86/x86_32/entry.S	Thu Nov 25 15:12:06 2004 +0000
    10.2 +++ b/xen/arch/x86/x86_32/entry.S	Thu Nov 25 17:25:14 2004 +0000
    10.3 @@ -70,107 +70,6 @@ ENTRY(continue_nonidle_task)
    10.4          jmp test_all_events
    10.5  
    10.6          ALIGN
    10.7 -/*
    10.8 - * HYPERVISOR_multicall(call_list, nr_calls)
    10.9 - *   Execute a list of 'nr_calls' hypercalls, pointed at by 'call_list'.
   10.10 - *   This is fairly easy except that:
   10.11 - *   1. We may fault reading the call list, and must patch that up; and
   10.12 - *   2. We cannot recursively call HYPERVISOR_multicall, or a malicious
   10.13 - *      caller could cause our stack to blow up.
   10.14 - */
   10.15 -#define MULTICALL_ENTRY_ORDER 5
   10.16 -do_multicall:
   10.17 -        popl  %eax
   10.18 -        cmpl  $SYMBOL_NAME(multicall_return_from_call),%eax
   10.19 -        je    multicall_return_from_call
   10.20 -        pushl %ebx
   10.21 -        movl  4(%esp),%ebx   /* EBX == call_list */
   10.22 -        movl  8(%esp),%ecx   /* ECX == nr_calls  */
   10.23 -        /* Ensure the entire multicall list is below HYPERVISOR_VIRT_START. */
   10.24 -        movl  %ecx,%eax
   10.25 -        shll  $MULTICALL_ENTRY_ORDER,%eax
   10.26 -        addl  %ebx,%eax      /* EAX == end of multicall list */
   10.27 -        jc    bad_multicall_address
   10.28 -        cmpl  $__HYPERVISOR_VIRT_START,%eax
   10.29 -        jnc   bad_multicall_address
   10.30 -multicall_loop:
   10.31 -        pushl %ecx
   10.32 -        movl  4(%esp),%ecx               # %ecx = struct domain
   10.33 -        movl  DOMAIN_processor(%ecx),%eax
   10.34 -        shl   $6,%eax                    # sizeof(irq_cpustat) == 64
   10.35 -        testl $~0,SYMBOL_NAME(irq_stat)(%eax,1)
   10.36 -        jnz   multicall_preempt
   10.37 -multicall_fault1: 
   10.38 -        pushl 20(%ebx)      # args[4]
   10.39 -multicall_fault2: 
   10.40 -        pushl 16(%ebx)      # args[3]
   10.41 -multicall_fault3: 
   10.42 -        pushl 12(%ebx)      # args[2]
   10.43 -multicall_fault4: 
   10.44 -        pushl 8(%ebx)       # args[1]
   10.45 -multicall_fault5: 
   10.46 -        pushl 4(%ebx)       # args[0]
   10.47 -multicall_fault6: 
   10.48 -        movl  (%ebx),%eax   # op
   10.49 -        andl  $(NR_hypercalls-1),%eax
   10.50 -        call  *SYMBOL_NAME(hypercall_table)(,%eax,4)
   10.51 -multicall_return_from_call:
   10.52 -multicall_fault7:
   10.53 -        movl  %eax,24(%ebx) # args[5] == result
   10.54 -        addl  $20,%esp
   10.55 -        popl  %ecx
   10.56 -        addl  $(1<<MULTICALL_ENTRY_ORDER),%ebx
   10.57 -        loop  multicall_loop
   10.58 -        popl  %ebx
   10.59 -        xorl  %eax,%eax
   10.60 -        jmp   ret_from_hypercall
   10.61 -
   10.62 -multicall_preempt:
   10.63 -        # NB. remaining nr_calls is already at top of stack
   10.64 -        pushl %ebx                             # call_list
   10.65 -        pushl $2                               # nr_args == 2
   10.66 -        pushl $__HYPERVISOR_multicall          # op == __HYPERVISOR_multicall
   10.67 -        call  hypercall_create_continuation
   10.68 -        addl  $16,%esp
   10.69 -        popl  %ebx
   10.70 -        movl  $__HYPERVISOR_multicall,%eax        
   10.71 -        jmp   ret_from_hypercall
   10.72 -        
   10.73 -bad_multicall_address:
   10.74 -        popl  %ebx
   10.75 -        movl  $-EFAULT,%eax
   10.76 -        jmp   ret_from_hypercall        
   10.77 -                
   10.78 -.section __ex_table,"a"
   10.79 -        .align 4
   10.80 -        .long multicall_fault1, multicall_fixup1
   10.81 -        .long multicall_fault2, multicall_fixup2
   10.82 -        .long multicall_fault3, multicall_fixup3
   10.83 -        .long multicall_fault4, multicall_fixup4
   10.84 -        .long multicall_fault5, multicall_fixup5
   10.85 -        .long multicall_fault6, multicall_fixup6
   10.86 -        .long multicall_fault7, multicall_fixup6
   10.87 -.previous
   10.88 -               
   10.89 -.section .fixup,"ax"
   10.90 -multicall_fixup6: 
   10.91 -        addl  $4,%esp
   10.92 -multicall_fixup5: 
   10.93 -        addl  $4,%esp
   10.94 -multicall_fixup4: 
   10.95 -        addl  $4,%esp
   10.96 -multicall_fixup3: 
   10.97 -        addl  $4,%esp
   10.98 -multicall_fixup2: 
   10.99 -        addl  $4,%esp
  10.100 -multicall_fixup1:
  10.101 -        addl  $4,%esp
  10.102 -        popl  %ebx
  10.103 -        movl  $-EFAULT,%eax
  10.104 -        jmp   ret_from_hypercall
  10.105 -.previous        
  10.106 -                
  10.107 -        ALIGN
  10.108  restore_all_guest:
  10.109          testb $TF_failsafe_return,DOMAIN_thread_flags(%ebx)
  10.110          jnz  failsafe_callback
    11.1 --- a/xen/arch/x86/x86_32/mm.c	Thu Nov 25 15:12:06 2004 +0000
    11.2 +++ b/xen/arch/x86/x86_32/mm.c	Thu Nov 25 17:25:14 2004 +0000
    11.3 @@ -191,7 +191,7 @@ int check_descriptor(unsigned long *d)
    11.4      if ( (b & _SEGMENT_G) )
    11.5          limit <<= 12;
    11.6  
    11.7 -    if ( (b & (3<<10)) == 1 )
    11.8 +    if ( (b & (_SEGMENT_CODE | _SEGMENT_EC)) == _SEGMENT_EC )
    11.9      {
   11.10          /*
   11.11           * Grows-down limit check. 
    12.1 --- a/xen/arch/x86/x86_32/seg_fixup.c	Thu Nov 25 15:12:06 2004 +0000
    12.2 +++ b/xen/arch/x86/x86_32/seg_fixup.c	Thu Nov 25 17:25:14 2004 +0000
    12.3 @@ -169,7 +169,7 @@ int linearise_address(u16 seg, unsigned 
    12.4      return 1;
    12.5  }
    12.6  
    12.7 -int fixup_seg(u16 seg, int positive_access)
    12.8 +int fixup_seg(u16 seg, unsigned long offset)
    12.9  {
   12.10      struct domain *d = current;
   12.11      unsigned long *table, a, b, base, limit;
   12.12 @@ -208,7 +208,7 @@ int fixup_seg(u16 seg, int positive_acce
   12.13  
   12.14      /* We only parse 32-bit page-granularity non-privileged data segments. */
   12.15      if ( (b & (_SEGMENT_P|_SEGMENT_S|_SEGMENT_DB|
   12.16 -               _SEGMENT_G|(1<<11)|_SEGMENT_DPL)) != 
   12.17 +               _SEGMENT_G|_SEGMENT_CODE|_SEGMENT_DPL)) != 
   12.18           (_SEGMENT_P|_SEGMENT_S|_SEGMENT_DB|_SEGMENT_G|_SEGMENT_DPL) )
   12.19      {
   12.20          DPRINTK("Bad segment %08lx:%08lx\n", a, b);
   12.21 @@ -219,10 +219,10 @@ int fixup_seg(u16 seg, int positive_acce
   12.22      base  = (b&(0xff<<24)) | ((b&0xff)<<16) | (a>>16);
   12.23      limit = (((b & 0xf0000) | (a & 0x0ffff)) + 1) << 12;
   12.24  
   12.25 -    if ( b & (1 << 10) )
   12.26 +    if ( b & _SEGMENT_EC )
   12.27      {
   12.28          /* Expands-down: All the way to zero? Assume 4GB if so. */
   12.29 -        if ( ((base + limit) < PAGE_SIZE) && positive_access )
   12.30 +        if ( ((base + limit) < PAGE_SIZE) && (offset <= limit)  )
   12.31          {
   12.32              /* Flip to expands-up. */
   12.33              limit = PAGE_OFFSET - base;
   12.34 @@ -231,8 +231,16 @@ int fixup_seg(u16 seg, int positive_acce
   12.35      }
   12.36      else
   12.37      {
   12.38 -        /* Expands-up: All the way to Xen space? Assume 4GB if so. */
   12.39 -        if ( ((PAGE_OFFSET - (base + limit)) < PAGE_SIZE) && !positive_access )
   12.40 +        /*
   12.41 +         * Expands-up: All the way to Xen space? Assume 4GB if so.
   12.42 +         * NB: we compare offset with limit-15, instead of the "real"
   12.43 +         * comparison of offset+15 (worst case) with limit,
   12.44 +         * to avoid possible unsigned int overflow of offset+15.
   12.45 +         * limit-15 will not underflow here because we don't allow expand-up
   12.46 +         * segments with maxlimit.
   12.47 +         */
   12.48 +        if ( ((PAGE_OFFSET - (base + limit)) < PAGE_SIZE) &&
   12.49 +             ((offset) > (limit-15)) )
   12.50          {
   12.51              /* Flip to expands-down. */
   12.52              limit = -(base & PAGE_MASK);
   12.53 @@ -250,7 +258,7 @@ int fixup_seg(u16 seg, int positive_acce
   12.54      limit = (limit >> 12) - 1;
   12.55      a &= ~0x0ffff; a |= limit & 0x0ffff;
   12.56      b &= ~0xf0000; b |= limit & 0xf0000;
   12.57 -    b ^= 1 << 10; /* grows-up <-> grows-down */
   12.58 +    b ^= _SEGMENT_EC; /* grows-up <-> grows-down */
   12.59      /* NB. These can't fault. Checked readable above; must also be writable. */
   12.60      table[2*idx+0] = a;
   12.61      table[2*idx+1] = b;
   12.62 @@ -317,37 +325,40 @@ int gpf_emulate_4gb(struct xen_regs *reg
   12.63              goto fail;
   12.64          }
   12.65  
   12.66 -        if ( (pb - eip) == 4 )
   12.67 -            break;
   12.68 -        
   12.69 +        if ( (pb - eip) >= 15 )
   12.70 +        {
   12.71 +            DPRINTK("Too many instruction prefixes for a legal instruction\n");
   12.72 +            goto fail;
   12.73 +        }
   12.74 +
   12.75          switch ( b )
   12.76          {
   12.77 -        case 0xf0: /* LOCK */
   12.78 -        case 0xf2: /* REPNE/REPNZ */
   12.79 -        case 0xf3: /* REP/REPE/REPZ */
   12.80          case 0x67: /* Address-size override */
   12.81              DPRINTK("Unhandleable prefix byte %02x\n", b);
   12.82              goto fixme;
   12.83          case 0x66: /* Operand-size override */
   12.84 -            break;
   12.85 +        case 0xf0: /* LOCK */
   12.86 +        case 0xf2: /* REPNE/REPNZ */
   12.87 +        case 0xf3: /* REP/REPE/REPZ */
   12.88 +            continue;
   12.89          case 0x2e: /* CS override */
   12.90              pseg = &regs->cs;
   12.91 -            break;
   12.92 +            continue;
   12.93          case 0x3e: /* DS override */
   12.94              pseg = &regs->ds;
   12.95 -            break;
   12.96 +            continue;
   12.97          case 0x26: /* ES override */
   12.98              pseg = &regs->es;
   12.99 -            break;
  12.100 +            continue;
  12.101          case 0x64: /* FS override */
  12.102              pseg = &regs->fs;
  12.103 -            break;
  12.104 +            continue;
  12.105          case 0x65: /* GS override */
  12.106              pseg = &regs->gs;
  12.107 -            break;
  12.108 +            continue;
  12.109          case 0x36: /* SS override */
  12.110              pseg = &regs->ss;
  12.111 -            break;
  12.112 +            continue;
  12.113          default: /* Not a prefix byte */
  12.114              goto done_prefix;
  12.115          }
  12.116 @@ -455,7 +466,7 @@ int gpf_emulate_4gb(struct xen_regs *reg
  12.117          offset += *(u32 *)memreg;
  12.118  
  12.119   skip_modrm:
  12.120 -    if ( !fixup_seg((u16)(*pseg), (signed long)offset >= 0) )
  12.121 +    if ( !fixup_seg((u16)(*pseg), offset) )
  12.122          goto fail;
  12.123  
  12.124      /* Success! */
    13.1 --- a/xen/common/dom_mem_ops.c	Thu Nov 25 15:12:06 2004 +0000
    13.2 +++ b/xen/common/dom_mem_ops.c	Thu Nov 25 17:25:14 2004 +0000
    13.3 @@ -15,31 +15,46 @@
    13.4  #include <xen/event.h>
    13.5  #include <asm/domain_page.h>
    13.6  
    13.7 -static long alloc_dom_mem(struct domain *d, 
    13.8 -                          unsigned long *extent_list, 
    13.9 -                          unsigned long  nr_extents,
   13.10 -                          unsigned int   extent_order)
   13.11 +/*
   13.12 + * To allow safe resume of do_dom_mem_op() after preemption, we need to know 
   13.13 + * at what point in the page list to resume. For this purpose I steal the 
   13.14 + * high-order bits of the @op parameter, which are otherwise unused and zero.
   13.15 + */
   13.16 +#define START_EXTENT_SHIFT 4 /* op[:4] == start_extent */
   13.17 +
   13.18 +#define PREEMPT_CHECK(_op)                          \
   13.19 +    if ( hypercall_preempt_check() ) {              \
   13.20 +        hypercall_create_continuation(              \
   13.21 +            __HYPERVISOR_dom_mem_op, 5,             \
   13.22 +            (_op) | (i << START_EXTENT_SHIFT),      \
   13.23 +            extent_list, nr_extents, extent_order,  \
   13.24 +            (d == current) ? DOMID_SELF : d->id);   \
   13.25 +        return __HYPERVISOR_dom_mem_op;             \
   13.26 +    }
   13.27 +
   13.28 +static long
   13.29 +alloc_dom_mem(struct domain *d, 
   13.30 +              unsigned long *extent_list, 
   13.31 +              unsigned long  start_extent,
   13.32 +              unsigned long  nr_extents,
   13.33 +              unsigned int   extent_order)
   13.34  {
   13.35      struct pfn_info *page;
   13.36      unsigned long    i;
   13.37  
   13.38 -    if ( unlikely(!access_ok(VERIFY_WRITE, extent_list, 
   13.39 -                             nr_extents*sizeof(*extent_list))) )
   13.40 -        return 0;
   13.41 +    if ( unlikely(!array_access_ok(VERIFY_WRITE, extent_list, 
   13.42 +                                   nr_extents, sizeof(*extent_list))) )
   13.43 +        return start_extent;
   13.44  
   13.45      if ( (extent_order != 0) && !IS_CAPABLE_PHYSDEV(current) )
   13.46      {
   13.47          DPRINTK("Only I/O-capable domains may allocate > order-0 memory.\n");
   13.48 -        return 0;
   13.49 +        return start_extent;
   13.50      }
   13.51  
   13.52 -    for ( i = 0; i < nr_extents; i++ )
   13.53 +    for ( i = start_extent; i < nr_extents; i++ )
   13.54      {
   13.55 -        hypercall_may_preempt(
   13.56 -            __HYPERVISOR_dom_mem_op, 5,
   13.57 -            MEMOP_increase_reservation,
   13.58 -            &extent_list[i], nr_extents-i, extent_order,
   13.59 -            (d == current) ? DOMID_SELF : d->id);
   13.60 +        PREEMPT_CHECK(MEMOP_increase_reservation);
   13.61  
   13.62          if ( unlikely((page = alloc_domheap_pages(d, extent_order)) == NULL) )
   13.63          {
   13.64 @@ -55,25 +70,23 @@ static long alloc_dom_mem(struct domain 
   13.65      return i;
   13.66  }
   13.67      
   13.68 -static long free_dom_mem(struct domain *d,
   13.69 -                         unsigned long *extent_list, 
   13.70 -                         unsigned long  nr_extents,
   13.71 -                         unsigned int   extent_order)
   13.72 +static long
   13.73 +free_dom_mem(struct domain *d,
   13.74 +             unsigned long *extent_list, 
   13.75 +             unsigned long  start_extent,
   13.76 +             unsigned long  nr_extents,
   13.77 +             unsigned int   extent_order)
   13.78  {
   13.79      struct pfn_info *page;
   13.80      unsigned long    i, j, mpfn;
   13.81  
   13.82 -    if ( unlikely(!access_ok(VERIFY_READ, extent_list, 
   13.83 -                             nr_extents*sizeof(*extent_list))) )
   13.84 -        return 0;
   13.85 +    if ( unlikely(!array_access_ok(VERIFY_READ, extent_list, 
   13.86 +                                   nr_extents, sizeof(*extent_list))) )
   13.87 +        return start_extent;
   13.88  
   13.89 -    for ( i = 0; i < nr_extents; i++ )
   13.90 +    for ( i = start_extent; i < nr_extents; i++ )
   13.91      {
   13.92 -        hypercall_may_preempt(
   13.93 -            __HYPERVISOR_dom_mem_op, 5,
   13.94 -            MEMOP_decrease_reservation,
   13.95 -            &extent_list[i], nr_extents-i, extent_order,
   13.96 -            (d == current) ? DOMID_SELF : d->id);
   13.97 +        PREEMPT_CHECK(MEMOP_decrease_reservation);
   13.98  
   13.99          if ( unlikely(__get_user(mpfn, &extent_list[i]) != 0) )
  13.100              return i;
  13.101 @@ -106,15 +119,24 @@ static long free_dom_mem(struct domain *
  13.102  
  13.103      return i;
  13.104  }
  13.105 -    
  13.106 -long do_dom_mem_op(unsigned int   op, 
  13.107 -                   unsigned long *extent_list, 
  13.108 -                   unsigned long  nr_extents,
  13.109 -                   unsigned int   extent_order,
  13.110 -		   domid_t        domid)
  13.111 +
  13.112 +long
  13.113 +do_dom_mem_op(unsigned long  op, 
  13.114 +              unsigned long *extent_list, 
  13.115 +              unsigned long  nr_extents,
  13.116 +              unsigned int   extent_order,
  13.117 +              domid_t        domid)
  13.118  {
  13.119      struct domain *d;
  13.120 -    long           rc;
  13.121 +    unsigned long  rc, start_extent;
  13.122 +
  13.123 +    /* Extract @start_extent from @op. */
  13.124 +    start_extent  = op >> START_EXTENT_SHIFT;
  13.125 +    op           &= (1 << START_EXTENT_SHIFT) - 1;
  13.126 +
  13.127 +    if ( unlikely(start_extent > nr_extents) || 
  13.128 +         unlikely(nr_extents > (~0UL >> START_EXTENT_SHIFT)) )
  13.129 +        return -EINVAL;
  13.130  
  13.131      if ( likely(domid == DOMID_SELF) )
  13.132          d = current;
  13.133 @@ -126,10 +148,12 @@ long do_dom_mem_op(unsigned int   op,
  13.134      switch ( op )
  13.135      {
  13.136      case MEMOP_increase_reservation:
  13.137 -        rc = alloc_dom_mem(d, extent_list, nr_extents, extent_order);
  13.138 +        rc = alloc_dom_mem(
  13.139 +            d, extent_list, start_extent, nr_extents, extent_order);
  13.140  	break;
  13.141      case MEMOP_decrease_reservation:
  13.142 -        rc = free_dom_mem(d, extent_list, nr_extents, extent_order);
  13.143 +        rc = free_dom_mem(
  13.144 +            d, extent_list, start_extent, nr_extents, extent_order);
  13.145  	break;
  13.146      default:
  13.147          rc = -ENOSYS;
    14.1 --- a/xen/common/grant_table.c	Thu Nov 25 15:12:06 2004 +0000
    14.2 +++ b/xen/common/grant_table.c	Thu Nov 25 17:25:14 2004 +0000
    14.3 @@ -446,14 +446,14 @@ do_grant_table_op(
    14.4      switch ( cmd )
    14.5      {
    14.6      case GNTTABOP_map_grant_ref:
    14.7 -        if ( unlikely(!access_ok(VERIFY_WRITE, uop,
    14.8 -                                 count * sizeof(gnttab_map_grant_ref_t))) )
    14.9 +        if ( unlikely(!array_access_ok(
   14.10 +            VERIFY_WRITE, uop, count, sizeof(gnttab_map_grant_ref_t))) )
   14.11              return -EFAULT;
   14.12          rc = gnttab_map_grant_ref((gnttab_map_grant_ref_t *)uop, count);
   14.13          break;
   14.14      case GNTTABOP_unmap_grant_ref:
   14.15 -        if ( unlikely(!access_ok(VERIFY_WRITE, uop,
   14.16 -                                 count * sizeof(gnttab_unmap_grant_ref_t))) )
   14.17 +        if ( unlikely(!array_access_ok(
   14.18 +            VERIFY_WRITE, uop, count, sizeof(gnttab_unmap_grant_ref_t))) )
   14.19              return -EFAULT;
   14.20          rc = gnttab_unmap_grant_ref((gnttab_unmap_grant_ref_t *)uop, count);
   14.21          break;
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/xen/common/multicall.c	Thu Nov 25 17:25:14 2004 +0000
    15.3 @@ -0,0 +1,76 @@
    15.4 +/******************************************************************************
    15.5 + * multicall.c
    15.6 + */
    15.7 +
    15.8 +#include <xen/config.h>
    15.9 +#include <xen/types.h>
   15.10 +#include <xen/lib.h>
   15.11 +#include <xen/mm.h>
   15.12 +#include <xen/perfc.h>
   15.13 +#include <xen/sched.h>
   15.14 +#include <xen/event.h>
   15.15 +#include <xen/multicall.h>
   15.16 +
   15.17 +struct mc_state mc_state[NR_CPUS];
   15.18 +
   15.19 +long do_multicall(multicall_entry_t *call_list, unsigned int nr_calls)
   15.20 +{
   15.21 +    struct mc_state *mcs = &mc_state[smp_processor_id()];
   15.22 +    unsigned int     i;
   15.23 +
   15.24 +    if ( unlikely(__test_and_set_bit(_MCSF_in_multicall, &mcs->flags)) )
   15.25 +    {
   15.26 +        DPRINTK("Multicall reentry is disallowed.\n");
   15.27 +        return -EINVAL;
   15.28 +    }
   15.29 +
   15.30 +    if ( unlikely(!array_access_ok(VERIFY_WRITE, call_list, 
   15.31 +                                   nr_calls, sizeof(*call_list))) )
   15.32 +    {
   15.33 +        DPRINTK("Bad memory range %p for %u*%u bytes.\n",
   15.34 +                call_list, nr_calls, sizeof(*call_list));
   15.35 +        goto fault;
   15.36 +    }
   15.37 +
   15.38 +    for ( i = 0; i < nr_calls; i++ )
   15.39 +    {
   15.40 +        if ( unlikely(__copy_from_user(&mcs->call, &call_list[i], 
   15.41 +                                       sizeof(*call_list))) )
   15.42 +        {
   15.43 +            DPRINTK("Error copying from user range %p for %u bytes.\n",
   15.44 +                    &call_list[i], sizeof(*call_list));
   15.45 +            goto fault;
   15.46 +        }
   15.47 +
   15.48 +        do_multicall_call(&mcs->call);
   15.49 +
   15.50 +        if ( unlikely(__put_user(mcs->call.args[5], &call_list[i].args[5])) )
   15.51 +        {
   15.52 +            DPRINTK("Error writing result back to multicall block.\n");
   15.53 +            goto fault;
   15.54 +        }
   15.55 +
   15.56 +        if ( hypercall_preempt_check() )
   15.57 +        {
   15.58 +            /* If the sub-call wasn't preempted, skip over it. */
   15.59 +            if ( !test_bit(_MCSF_call_preempted, &mcs->flags) )
   15.60 +                i++;
   15.61 +
   15.62 +            /* Only create a continuation if there is work left to be done. */
   15.63 +            if ( i < nr_calls )
   15.64 +            {
   15.65 +                mcs->flags = 0;
   15.66 +                hypercall_create_continuation(
   15.67 +                    __HYPERVISOR_multicall, 2, &call_list[i], nr_calls-i);
   15.68 +                return __HYPERVISOR_multicall;
   15.69 +            }
   15.70 +        }
   15.71 +    }
   15.72 +
   15.73 +    mcs->flags = 0;
   15.74 +    return 0;
   15.75 +
   15.76 + fault:
   15.77 +    mcs->flags = 0;
   15.78 +    return -EFAULT;
   15.79 +}
    16.1 --- a/xen/include/asm-x86/desc.h	Thu Nov 25 15:12:06 2004 +0000
    16.2 +++ b/xen/include/asm-x86/desc.h	Thu Nov 25 17:25:14 2004 +0000
    16.3 @@ -27,8 +27,11 @@
    16.4       (((_s)&3) == 1))
    16.5  #define VALID_CODESEL(_s) ((_s) == FLAT_RING1_CS || VALID_SEL(_s))
    16.6  
    16.7 -/* These are bitmasks for the first 32 bits of a descriptor table entry. */
    16.8 +/* These are bitmasks for the high 32 bits of a descriptor table entry. */
    16.9  #define _SEGMENT_TYPE    (15<< 8)
   16.10 +#define _SEGMENT_EC      ( 1<<10) /* Expand-down or Conforming segment */
   16.11 +#define _SEGMENT_CODE    ( 1<<11) /* Code (vs data) segment for non-system
   16.12 +                                     segments */
   16.13  #define _SEGMENT_S       ( 1<<12) /* System descriptor (yes iff S==0) */
   16.14  #define _SEGMENT_DPL     ( 3<<13) /* Descriptor Privilege Level */
   16.15  #define _SEGMENT_P       ( 1<<15) /* Segment Present */
    17.1 --- a/xen/include/asm-x86/mm.h	Thu Nov 25 15:12:06 2004 +0000
    17.2 +++ b/xen/include/asm-x86/mm.h	Thu Nov 25 17:25:14 2004 +0000
    17.3 @@ -221,9 +221,6 @@ extern unsigned long *machine_to_phys_ma
    17.4  #define machine_to_phys_mapping ((unsigned long *)RDWR_MPT_VIRT_START)
    17.5  #endif
    17.6  
    17.7 -/* Part of the domain API. */
    17.8 -int do_mmu_update(mmu_update_t *updates, int count, int *success_count);
    17.9 -
   17.10  #define DEFAULT_GDT_ENTRIES     (LAST_RESERVED_GDT_ENTRY+1)
   17.11  #define DEFAULT_GDT_ADDRESS     ((unsigned long)gdt_table)
   17.12  
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/xen/include/asm-x86/multicall.h	Thu Nov 25 17:25:14 2004 +0000
    18.3 @@ -0,0 +1,26 @@
    18.4 +/******************************************************************************
    18.5 + * asm-x86/multicall.h
    18.6 + */
    18.7 +
    18.8 +#ifndef __ASM_X86_MULTICALL_H__
    18.9 +#define __ASM_X86_MULTICALL_H__
   18.10 +
   18.11 +#include <asm-x86/x86_32/asm_defns.h>
   18.12 +
   18.13 +#define do_multicall_call(_call)                       \
   18.14 +    do {                                               \
   18.15 +        __asm__ __volatile__ (                         \
   18.16 +            "pushl "STR(MULTICALL_arg4)"(%0); "        \
   18.17 +            "pushl "STR(MULTICALL_arg3)"(%0); "        \
   18.18 +            "pushl "STR(MULTICALL_arg2)"(%0); "        \
   18.19 +            "pushl "STR(MULTICALL_arg1)"(%0); "        \
   18.20 +            "pushl "STR(MULTICALL_arg0)"(%0); "        \
   18.21 +            "movl  "STR(MULTICALL_op)"(%0),%%eax; "    \
   18.22 +            "andl  $("STR(NR_hypercalls)"-1),%%eax; "  \
   18.23 +            "call  *hypercall_table(,%%eax,4); "       \
   18.24 +            "movl  %%eax,"STR(MULTICALL_result)"(%0); "\
   18.25 +            "addl  $20,%%esp; "                        \
   18.26 +            : : "b" (_call) : "eax", "ecx", "edx" );   \
   18.27 +    } while ( 0 )
   18.28 +
   18.29 +#endif /* __ASM_X86_MULTICALL_H__ */
    19.1 --- a/xen/include/asm-x86/x86_32/uaccess.h	Thu Nov 25 15:12:06 2004 +0000
    19.2 +++ b/xen/include/asm-x86/x86_32/uaccess.h	Thu Nov 25 17:25:14 2004 +0000
    19.3 @@ -66,6 +66,9 @@ extern struct movsl_mask {
    19.4   */
    19.5  #define access_ok(type,addr,size) (likely(__range_ok(addr,size) == 0))
    19.6  
    19.7 +#define array_access_ok(type,addr,count,size) \
    19.8 +    (likely(count < (~0UL/size)) && access_ok(type,addr,count*size))
    19.9 +
   19.10  /*
   19.11   * The exception table consists of pairs of addresses: the first is the
   19.12   * address of an instruction that is allowed to fault, and the second is
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/xen/include/xen/multicall.h	Thu Nov 25 17:25:14 2004 +0000
    20.3 @@ -0,0 +1,21 @@
    20.4 +/******************************************************************************
    20.5 + * multicall.h
    20.6 + */
    20.7 +
    20.8 +#ifndef __XEN_MULTICALL_H__
    20.9 +#define __XEN_MULTICALL_H__
   20.10 +
   20.11 +#include <asm/multicall.h>
   20.12 +
   20.13 +#define _MCSF_in_multicall   0
   20.14 +#define _MCSF_call_preempted 1
   20.15 +#define MCSF_in_multicall    (1<<_MCSF_in_multicall)
   20.16 +#define MCSF_call_preempted  (1<<_MCSF_call_preempted)
   20.17 +struct mc_state {
   20.18 +    unsigned long     flags;
   20.19 +    multicall_entry_t call;
   20.20 +} __cacheline_aligned;
   20.21 +
   20.22 +extern struct mc_state mc_state[NR_CPUS];
   20.23 +
   20.24 +#endif /* __XEN_MULTICALL_H__ */
    21.1 --- a/xen/include/xen/sched.h	Thu Nov 25 15:12:06 2004 +0000
    21.2 +++ b/xen/include/xen/sched.h	Thu Nov 25 17:25:14 2004 +0000
    21.3 @@ -219,12 +219,8 @@ void continue_cpu_idle_loop(void);
    21.4  void continue_nonidle_task(void);
    21.5  
    21.6  void hypercall_create_continuation(unsigned int op, unsigned int nr_args, ...);
    21.7 -#define hypercall_may_preempt(_op, _nr_args, _args...)               \
    21.8 -    do {                                                             \
    21.9 -        if ( unlikely(softirq_pending(smp_processor_id())) ) {       \
   21.10 -            hypercall_create_continuation(_op , _nr_args , ##_args); \
   21.11 -            return _op;                                              \
   21.12 -    } } while ( 0 )
   21.13 +#define hypercall_preempt_check() \
   21.14 +    (unlikely(softirq_pending(smp_processor_id())))
   21.15  
   21.16  /* This domain_hash and domain_list are protected by the domlist_lock. */
   21.17  #define DOMAIN_HASH_SIZE 256