ia64/xen-unstable

changeset 19786:d835ad2f6980

x86: properly handle vcpu-to-pcpu mask conversion

This is one of the prerequisites to extend to number of vCPU-s the
hypervisor can support per guest.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 18 10:04:57 2009 +0100 (2009-06-18)
parents 82366af53828
children cecc76506afc
files xen/arch/x86/mm.c xen/arch/x86/x86_64/compat/mm.c xen/include/asm-x86/guest_access.h
line diff
     1.1 --- a/xen/arch/x86/mm.c	Thu Jun 18 09:56:28 2009 +0100
     1.2 +++ b/xen/arch/x86/mm.c	Thu Jun 18 10:04:57 2009 +0100
     1.3 @@ -2565,29 +2565,41 @@ static int set_foreigndom(domid_t domid)
     1.4      return okay;
     1.5  }
     1.6  
     1.7 -static inline cpumask_t vcpumask_to_pcpumask(
     1.8 -    struct domain *d, unsigned long vmask)
     1.9 +static inline int vcpumask_to_pcpumask(
    1.10 +    struct domain *d, XEN_GUEST_HANDLE(const_void) bmap, cpumask_t *pmask)
    1.11  {
    1.12 -    unsigned int vcpu_id;
    1.13 -    cpumask_t    pmask = CPU_MASK_NONE;
    1.14 +    unsigned int vcpu_id, vcpu_bias, offs;
    1.15 +    unsigned long vmask;
    1.16      struct vcpu *v;
    1.17 -
    1.18 -    /*
    1.19 -     * Callers copy only a single guest-sized longword from the guest.
    1.20 -     * This must be wide enough to reference all VCPUs. Worst case is 32 bits.
    1.21 -     */
    1.22 -    BUILD_BUG_ON(MAX_VIRT_CPUS > 32);
    1.23 -
    1.24 -    while ( vmask != 0 )
    1.25 +    bool_t is_native = !is_pv_32on64_domain(d);
    1.26 +
    1.27 +    cpus_clear(*pmask);
    1.28 +    for ( vmask = 0, offs = 0; ; ++offs)
    1.29      {
    1.30 -        vcpu_id = find_first_set_bit(vmask);
    1.31 -        vmask &= ~(1UL << vcpu_id);
    1.32 -        if ( (vcpu_id < MAX_VIRT_CPUS) &&
    1.33 -             ((v = d->vcpu[vcpu_id]) != NULL) )
    1.34 -            cpus_or(pmask, pmask, v->vcpu_dirty_cpumask);
    1.35 +        vcpu_bias = offs * (is_native ? BITS_PER_LONG : 32);
    1.36 +        if ( vcpu_bias >= MAX_VIRT_CPUS )
    1.37 +            return 0;
    1.38 +
    1.39 +        if ( unlikely(is_native ?
    1.40 +                      copy_from_guest_offset(&vmask, bmap, offs, 1) :
    1.41 +                      copy_from_guest_offset((unsigned int *)&vmask, bmap,
    1.42 +                                             offs, 1)) )
    1.43 +        {
    1.44 +            cpus_clear(*pmask);
    1.45 +            return -EFAULT;
    1.46 +        }
    1.47 +
    1.48 +        while ( vmask )
    1.49 +        {
    1.50 +            vcpu_id = find_first_set_bit(vmask);
    1.51 +            vmask &= ~(1UL << vcpu_id);
    1.52 +            vcpu_id += vcpu_bias;
    1.53 +            if ( (vcpu_id >= MAX_VIRT_CPUS) )
    1.54 +                return 0;
    1.55 +            if ( ((v = d->vcpu[vcpu_id]) != NULL) )
    1.56 +                cpus_or(*pmask, *pmask, v->vcpu_dirty_cpumask);
    1.57 +        }
    1.58      }
    1.59 -
    1.60 -    return pmask;
    1.61  }
    1.62  
    1.63  #ifdef __i386__
    1.64 @@ -2816,14 +2828,13 @@ int do_mmuext_op(
    1.65          case MMUEXT_TLB_FLUSH_MULTI:
    1.66          case MMUEXT_INVLPG_MULTI:
    1.67          {
    1.68 -            unsigned long vmask;
    1.69              cpumask_t     pmask;
    1.70 -            if ( unlikely(copy_from_guest(&vmask, op.arg2.vcpumask, 1)) )
    1.71 +
    1.72 +            if ( unlikely(vcpumask_to_pcpumask(d, op.arg2.vcpumask, &pmask)) )
    1.73              {
    1.74                  okay = 0;
    1.75                  break;
    1.76              }
    1.77 -            pmask = vcpumask_to_pcpumask(d, vmask);
    1.78              if ( op.cmd == MMUEXT_TLB_FLUSH_MULTI )
    1.79                  flush_tlb_mask(&pmask);
    1.80              else
    1.81 @@ -3630,7 +3641,7 @@ int do_update_va_mapping(unsigned long v
    1.82      struct domain *d   = v->domain;
    1.83      struct page_info *gl1pg;
    1.84      l1_pgentry_t  *pl1e;
    1.85 -    unsigned long  vmask, bmap_ptr, gl1mfn;
    1.86 +    unsigned long  bmap_ptr, gl1mfn;
    1.87      cpumask_t      pmask;
    1.88      int            rc;
    1.89  
    1.90 @@ -3682,11 +3693,9 @@ int do_update_va_mapping(unsigned long v
    1.91          default:
    1.92              if ( this_cpu(percpu_mm_info).deferred_ops & DOP_FLUSH_ALL_TLBS )
    1.93                  break;
    1.94 -            if ( unlikely(!is_pv_32on64_domain(d) ?
    1.95 -                          get_user(vmask, (unsigned long *)bmap_ptr) :
    1.96 -                          get_user(vmask, (unsigned int *)bmap_ptr)) )
    1.97 -                rc = -EFAULT, vmask = 0;
    1.98 -            pmask = vcpumask_to_pcpumask(d, vmask);
    1.99 +            rc = vcpumask_to_pcpumask(d, const_guest_handle_from_ptr(bmap_ptr,
   1.100 +                                                                     void),
   1.101 +                                      &pmask);
   1.102              if ( cpu_isset(smp_processor_id(), pmask) )
   1.103                  this_cpu(percpu_mm_info).deferred_ops &= ~DOP_FLUSH_TLB;
   1.104              flush_tlb_mask(&pmask);
   1.105 @@ -3710,11 +3719,9 @@ int do_update_va_mapping(unsigned long v
   1.106              flush_tlb_one_mask(&d->domain_dirty_cpumask, va);
   1.107              break;
   1.108          default:
   1.109 -            if ( unlikely(!is_pv_32on64_domain(d) ?
   1.110 -                          get_user(vmask, (unsigned long *)bmap_ptr) :
   1.111 -                          get_user(vmask, (unsigned int *)bmap_ptr)) )
   1.112 -                rc = -EFAULT, vmask = 0;
   1.113 -            pmask = vcpumask_to_pcpumask(d, vmask);
   1.114 +            rc = vcpumask_to_pcpumask(d, const_guest_handle_from_ptr(bmap_ptr,
   1.115 +                                                                     void),
   1.116 +                                      &pmask);
   1.117              if ( this_cpu(percpu_mm_info).deferred_ops & DOP_FLUSH_TLB )
   1.118                  cpu_clear(smp_processor_id(), pmask);
   1.119              flush_tlb_one_mask(&pmask, va);
     2.1 --- a/xen/arch/x86/x86_64/compat/mm.c	Thu Jun 18 09:56:28 2009 +0100
     2.2 +++ b/xen/arch/x86/x86_64/compat/mm.c	Thu Jun 18 10:04:57 2009 +0100
     2.3 @@ -278,18 +278,7 @@ int compat_mmuext_op(XEN_GUEST_HANDLE(mm
     2.4              }
     2.5  
     2.6  #define XLAT_mmuext_op_HNDL_arg2_vcpumask(_d_, _s_) \
     2.7 -            do \
     2.8 -            { \
     2.9 -                unsigned int vcpumask; \
    2.10 -                if ( i < --limit ) \
    2.11 -                { \
    2.12 -                    (_d_)->arg2.vcpumask.p = (void *)(nat_ops.p + limit); \
    2.13 -                    if ( copy_from_compat(&vcpumask, (_s_)->arg2.vcpumask, 1) == 0 ) \
    2.14 -                        *(unsigned long *)(_d_)->arg2.vcpumask.p = vcpumask; \
    2.15 -                    else \
    2.16 -                        rc = -EFAULT; \
    2.17 -                } \
    2.18 -            } while(0)
    2.19 +        guest_from_compat_handle((_d_)->arg2.vcpumask, (_s_)->arg2.vcpumask)
    2.20              XLAT_mmuext_op(nat_op, &cmp_op);
    2.21  #undef XLAT_mmuext_op_HNDL_arg2_vcpumask
    2.22  
     3.1 --- a/xen/include/asm-x86/guest_access.h	Thu Jun 18 09:56:28 2009 +0100
     3.2 +++ b/xen/include/asm-x86/guest_access.h	Thu Jun 18 10:04:57 2009 +0100
     3.3 @@ -45,6 +45,8 @@
     3.4  
     3.5  #define guest_handle_from_ptr(ptr, type)        \
     3.6      ((XEN_GUEST_HANDLE(type)) { (type *)ptr })
     3.7 +#define const_guest_handle_from_ptr(ptr, type)  \
     3.8 +    ((XEN_GUEST_HANDLE(const_##type)) { (const type *)ptr })
     3.9  
    3.10  /*
    3.11   * Copy an array of objects to guest context via a guest handle,