[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH] x86: tighten checks in XEN_DOMCTL_memory_mapping handler


  • To: Jan Beulich <JBeulich@xxxxxxxx>, xen-devel <xen-devel@xxxxxxxxxxxxx>
  • From: Keir Fraser <keir.xen@xxxxxxxxx>
  • Date: Wed, 19 Sep 2012 12:24:47 +0100
  • Delivery-date: Wed, 19 Sep 2012 11:25:14 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xen.org>
  • Thread-index: Ac2WWV/49ZKZxNZMJkC135nF6yrHbQ==
  • Thread-topic: [Xen-devel] [PATCH] x86: tighten checks in XEN_DOMCTL_memory_mapping handler

On 19/09/2012 11:50, "Jan Beulich" <JBeulich@xxxxxxxx> wrote:

> Properly checking the MFN implies knowing the physical address width
> supported by the platform, so to obtain this consistently the
> respective code gets moved out of the MTRR subdir.
> 
> Btw., the model specific workaround in that code is likely unnecessary
> - I believe those CPU models don't support 64-bit mode. But I wasn't
> able to formally verify this, so I preferred to retain that code for
> now.
> 
> But domctl code here also was lacking other error checks (as was,
> looking at it again from that angle) the XEN_DOMCTL_ioport_mapping one.
> Besides adding the missing checks, printing is also added for the case
> where revoking access permissions didn't work (as that may have
> implications for the host operator, e.g. wanting to not pass through
> affected devices to another guest until the one previously using them
> did actually die).
> 
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>

Acked-by: Keir Fraser <keir@xxxxxxx>

> --- a/xen/arch/x86/cpu/common.c
> +++ b/xen/arch/x86/cpu/common.c
> @@ -36,6 +36,8 @@ integer_param("cpuid_mask_ext_edx", opt_
>  
>  struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};
>  
> +unsigned int paddr_bits __read_mostly = 36;
> +
>  /*
>   * Default host IA32_CR_PAT value to cover all memory types.
>   * BIOS usually sets it to 0x07040600070406.
> @@ -265,6 +267,8 @@ static void __cpuinit generic_identify(s
> }
> if ( xlvl >= 0x80000004 )
> get_model_name(c); /* Default name */
> +  if ( xlvl >= 0x80000008 )
> +   paddr_bits = cpuid_eax(0x80000008) & 0xff;
> }
>  
> /* Intel-defined flags: level 0x00000007 */
> --- a/xen/arch/x86/cpu/intel.c
> +++ b/xen/arch/x86/cpu/intel.c
> @@ -144,6 +144,11 @@ void __devinit early_intel_workaround(st
>       c->cpuid_level);
> }
> }
> +
> + /* CPUID workaround for Intel 0F33/0F34 CPU */
> + if (boot_cpu_data.x86 == 0xF && boot_cpu_data.x86_model == 3 &&
> +     (boot_cpu_data.x86_mask == 3 || boot_cpu_data.x86_mask == 4))
> +  paddr_bits = 36;
>  }
>  
>  /*
> --- a/xen/arch/x86/cpu/mtrr/main.c
> +++ b/xen/arch/x86/cpu/mtrr/main.c
> @@ -559,8 +559,6 @@ struct mtrr_value {
> unsigned long lsize;
>  };
>  
> -unsigned int paddr_bits __read_mostly = 36;
> -
>  /**
>   * mtrr_bp_init - initialize mtrrs on the boot CPU
>   *
> @@ -572,31 +570,8 @@ void __init mtrr_bp_init(void)
>  {
> if (cpu_has_mtrr) {
> mtrr_if = &generic_mtrr_ops;
> -  size_or_mask = 0xff000000; /* 36 bits */
> -  size_and_mask = 0x00f00000;
> -
> -  /* This is an AMD specific MSR, but we assume(hope?) that
> -     Intel will implement it to when they extend the address
> -     bus of the Xeon. */
> -  if (cpuid_eax(0x80000000) >= 0x80000008) {
> -   paddr_bits = cpuid_eax(0x80000008) & 0xff;
> -   /* CPUID workaround for Intel 0F33/0F34 CPU */
> -   if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
> -       boot_cpu_data.x86 == 0xF &&
> -       boot_cpu_data.x86_model == 0x3 &&
> -       (boot_cpu_data.x86_mask == 0x3 ||
> -        boot_cpu_data.x86_mask == 0x4))
> -    paddr_bits = 36;
> -
> -   size_or_mask = ~((1ULL << (paddr_bits - PAGE_SHIFT)) - 1);
> -   size_and_mask = ~size_or_mask & 0xfffff00000ULL;
> -  } else if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR &&
> -      boot_cpu_data.x86 == 6) {
> -   /* VIA C* family have Intel style MTRRs, but
> -      don't support PAE */
> -   size_or_mask = 0xfff00000; /* 32 bits */
> -   size_and_mask = 0;
> -  }
> +  size_or_mask = ~((1ULL << (paddr_bits - PAGE_SHIFT)) - 1);
> +  size_and_mask = ~size_or_mask & 0xfffff00000ULL;
> }
>  
> if (mtrr_if) {
> --- a/xen/arch/x86/domctl.c
> +++ b/xen/arch/x86/domctl.c
> @@ -825,10 +825,12 @@ long arch_do_domctl(
>          unsigned long mfn = domctl->u.memory_mapping.first_mfn;
>          unsigned long nr_mfns = domctl->u.memory_mapping.nr_mfns;
>          int add = domctl->u.memory_mapping.add_mapping;
> -        int i;
> +        unsigned long i;
>  
>          ret = -EINVAL;
> -        if ( (mfn + nr_mfns - 1) < mfn ) /* wrap? */
> +        if ( (mfn + nr_mfns - 1) < mfn || /* wrap? */
> +             ((mfn | (mfn + nr_mfns - 1)) >> (paddr_bits - PAGE_SHIFT)) ||
> +             (gfn + nr_mfns - 1) < gfn ) /* wrap? */
>              break;
>  
>          ret = -EPERM;
> @@ -853,8 +855,25 @@ long arch_do_domctl(
>                     d->domain_id, gfn, mfn, nr_mfns);
>  
>              ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1);
> -            for ( i = 0; i < nr_mfns; i++ )
> -                set_mmio_p2m_entry(d, gfn+i, _mfn(mfn+i));
> +            if ( !ret && paging_mode_translate(d) )
> +            {
> +                for ( i = 0; !ret && i < nr_mfns; i++ )
> +                    if ( !set_mmio_p2m_entry(d, gfn + i, _mfn(mfn + i)) )
> +                        ret = -EIO;
> +                if ( ret )
> +                {
> +                    printk(XENLOG_G_WARNING
> +                           "memory_map:fail: dom%d gfn=%lx mfn=%lx\n",
> +                           d->domain_id, gfn + i, mfn + i);
> +                    while ( i-- )
> +                        clear_mmio_p2m_entry(d, gfn + i);
> +                    if ( iomem_deny_access(d, mfn, mfn + nr_mfns - 1) &&
> +                         IS_PRIV(current->domain) )
> +                        printk(XENLOG_ERR
> +                               "memory_map: failed to deny dom%d access to
> [%lx,%lx]\n",
> +                               d->domain_id, mfn, mfn + nr_mfns - 1);
> +                }
> +            }
>          }
>          else
>          {
> @@ -862,9 +881,17 @@ long arch_do_domctl(
>                     "memory_map:remove: dom%d gfn=%lx mfn=%lx nr=%lx\n",
>                     d->domain_id, gfn, mfn, nr_mfns);
>  
> -            for ( i = 0; i < nr_mfns; i++ )
> -                clear_mmio_p2m_entry(d, gfn+i);
> +            if ( paging_mode_translate(d) )
> +                for ( i = 0; i < nr_mfns; i++ )
> +                    add |= !clear_mmio_p2m_entry(d, gfn + i);
>              ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1);
> +            if ( !ret && add )
> +                ret = -EIO;
> +            if ( ret && IS_PRIV(current->domain) )
> +                printk(XENLOG_ERR
> +                       "memory_map: error %ld %s dom%d access to
> [%lx,%lx]\n",
> +                       ret, add ? "removing" : "denying", d->domain_id,
> +                       mfn, mfn + nr_mfns - 1);
>          }
>  
>          rcu_unlock_domain(d);
> @@ -926,12 +953,23 @@ long arch_do_domctl(
>              if ( !found )
>              {
>                  g2m_ioport = xmalloc(struct g2m_ioport);
> +                if ( !g2m_ioport )
> +                    ret = -ENOMEM;
> +            }
> +            if ( !found && !ret )
> +            {
>                  g2m_ioport->gport = fgp;
>                  g2m_ioport->mport = fmp;
>                  g2m_ioport->np = np;
>                  list_add_tail(&g2m_ioport->list, &hd->g2m_ioport_list);
>              }
> -            ret = ioports_permit_access(d, fmp, fmp + np - 1);
> +            if ( !ret )
> +                ret = ioports_permit_access(d, fmp, fmp + np - 1);
> +            if ( ret && !found && g2m_ioport )
> +            {
> +                list_del(&g2m_ioport->list);
> +                xfree(g2m_ioport);
> +            }
>          }
>          else
>          {
> @@ -946,6 +984,10 @@ long arch_do_domctl(
>                      break;
>                  }
>              ret = ioports_deny_access(d, fmp, fmp + np - 1);
> +            if ( ret && IS_PRIV(current->domain) )
> +                printk(XENLOG_ERR
> +                       "ioport_map: error %ld denying dom%d access to
> [%x,%x]\n",
> +                       ret, d->domain_id, fmp, fmp + np - 1);
>          }
>          rcu_unlock_domain(d);
>      }
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxx
> http://lists.xen.org/xen-devel



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.