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

Re: [Xen-devel] [PATCH] xen: arm: avoid truncation in mfn to paddr conversions



On Mon, 2 Dec 2013, Ian Campbell wrote:
> Although MFNs are 64-bit in the hypercall ABI they are most often unsigned
> long internally, and therefore be 32-bit on arm32. Physical addresses are
> always 64-bit via paddr_t.
> 
> This means that the common "mfn << PAGE_SHIFT" pattern risks losing some of
> the top bits of the address is high enough. This need not imply a high amount
> of RAM, just a sparse physical address map.
> 
> The correct form is ((paddr_t)mfn)<<PAGE_SHIFT and we have the pfn_to_paddr
> macro which implements this. Grep for PAGE_SHIFT and << and switch to the
> macro everywhere we can in the arch specific code. Note that page.h is
> included by mm.h which defines the macro and so remains with the open coded
> cast. I have inspected the common code matching this pattern and it uses the
> correct casts where necessary (x86 also has pfn_to_paddr, so as a further
> cleanup we could fix the common code too, but I haven't done that here).
> 
> I observed this as failure to boot a guest on midway, due to trying to map a
> foreign page which belonged to no guest. I think this likely explains the
> crashes which Julien has seen too.
> 
> Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>

Acked-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>


>  xen/arch/arm/domain_build.c |    4 ++--
>  xen/arch/arm/mm.c           |    4 ++--
>  xen/arch/arm/p2m.c          |   16 +++++++++-------
>  xen/arch/arm/setup.c        |    8 ++++----
>  xen/include/asm-arm/mm.h    |    4 ++--
>  5 files changed, 19 insertions(+), 17 deletions(-)
> 
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 90fe88e..6c2fd3c 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -84,8 +84,8 @@ static void allocate_memory_11(struct domain *d, struct 
> kernel_info *kinfo)
>          panic("Failed to allocate contiguous memory for dom0\n");
>  
>      spfn = page_to_mfn(pg);
> -    start = spfn << PAGE_SHIFT;
> -    size = (1 << order) << PAGE_SHIFT;
> +    start = pfn_to_paddr(spfn);
> +    size = pfn_to_paddr((1 << order));
>  
>      // 1:1 mapping
>      printk("Populate P2M %#"PRIx64"->%#"PRIx64" (1:1 mapping for dom0)\n",
> diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
> index 2de7dc7..8189915 100644
> --- a/xen/arch/arm/mm.c
> +++ b/xen/arch/arm/mm.c
> @@ -1032,10 +1032,10 @@ static int xenmem_add_to_physmap_one(
>              return rc;
>          }
>  
> -        maddr = p2m_lookup(od, idx << PAGE_SHIFT);
> +        maddr = p2m_lookup(od, pfn_to_paddr(idx));
>          if ( maddr == INVALID_PADDR )
>          {
> -            dump_p2m_lookup(od, idx << PAGE_SHIFT);
> +            dump_p2m_lookup(od, pfn_to_paddr(idx));
>              rcu_unlock_domain(od);
>              return -EINVAL;
>          }
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index af32511..1d5c841 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -296,18 +296,20 @@ int guest_physmap_add_page(struct domain *d,
>                             unsigned long mfn,
>                             unsigned int page_order)
>  {
> -    return create_p2m_entries(d, INSERT, gpfn << PAGE_SHIFT,
> -                              (gpfn + (1<<page_order)) << PAGE_SHIFT,
> -                              mfn << PAGE_SHIFT, MATTR_MEM);
> +    return create_p2m_entries(d, INSERT,
> +                              pfn_to_paddr(gpfn),
> +                              pfn_to_paddr(gpfn + (1<<page_order)),
> +                              pfn_to_paddr(mfn), MATTR_MEM);
>  }
>  
>  void guest_physmap_remove_page(struct domain *d,
>                                 unsigned long gpfn,
>                                 unsigned long mfn, unsigned int page_order)
>  {
> -    create_p2m_entries(d, REMOVE, gpfn << PAGE_SHIFT,
> -                       (gpfn + (1<<page_order)) << PAGE_SHIFT,
> -                       mfn << PAGE_SHIFT, MATTR_MEM);
> +    create_p2m_entries(d, REMOVE,
> +                       pfn_to_paddr(gpfn),
> +                       pfn_to_paddr(gpfn + (1<<page_order)),
> +                       pfn_to_paddr(mfn), MATTR_MEM);
>  }
>  
>  int p2m_alloc_table(struct domain *d)
> @@ -450,7 +452,7 @@ err:
>  
>  unsigned long gmfn_to_mfn(struct domain *d, unsigned long gpfn)
>  {
> -    paddr_t p = p2m_lookup(d, gpfn << PAGE_SHIFT);
> +    paddr_t p = p2m_lookup(d, pfn_to_paddr(gpfn));
>      return p >> PAGE_SHIFT;
>  }
>  
> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> index 6834813..e640d81 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -456,7 +456,7 @@ static void __init setup_mm(unsigned long dtb_paddr, 
> size_t dtb_size)
>      {
>          /* xenheap is always in the initial contiguous region */
>          e = consider_modules(contig_start, contig_end,
> -                             xenheap_pages<<PAGE_SHIFT,
> +                             pfn_to_paddr(xenheap_pages),
>                               32<<20, 0);
>          if ( e )
>              break;
> @@ -470,7 +470,7 @@ static void __init setup_mm(unsigned long dtb_paddr, 
> size_t dtb_size)
>      domheap_pages = heap_pages - xenheap_pages;
>  
>      early_printk("Xen heap: %"PRIpaddr"-%"PRIpaddr" (%lu pages)\n",
> -                 e - (xenheap_pages << PAGE_SHIFT), e,
> +                 e - (pfn_to_paddr(xenheap_pages)), e,
>                   xenheap_pages);
>      early_printk("Dom heap: %lu pages\n", domheap_pages);
>  
> @@ -517,8 +517,8 @@ static void __init setup_mm(unsigned long dtb_paddr, 
> size_t dtb_size)
>                  e = bank_end;
>  
>              /* Avoid the xenheap */
> -            if ( s < ((xenheap_mfn_start+xenheap_pages) << PAGE_SHIFT)
> -                 && (xenheap_mfn_start << PAGE_SHIFT) < e )
> +            if ( s < pfn_to_paddr(xenheap_mfn_start+xenheap_pages)
> +                 && pfn_to_paddr(xenheap_mfn_start) < e )
>              {
>                  e = pfn_to_paddr(xenheap_mfn_start);
>                  n = pfn_to_paddr(xenheap_mfn_start+xenheap_pages);
> diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
> index ce66099..b8d4e7d 100644
> --- a/xen/include/asm-arm/mm.h
> +++ b/xen/include/asm-arm/mm.h
> @@ -123,8 +123,8 @@ extern unsigned long xenheap_virt_end;
>  #endif
>  
>  #define is_xen_fixed_mfn(mfn)                                   \
> -    ((((mfn) << PAGE_SHIFT) >= virt_to_maddr(&_start)) &&       \
> -     (((mfn) << PAGE_SHIFT) <= virt_to_maddr(&_end)))
> +    ((pfn_to_paddr(mfn) >= virt_to_maddr(&_start)) &&       \
> +     (pfn_to_paddr(mfn) <= virt_to_maddr(&_end)))
>  
>  #define page_get_owner(_p)    (_p)->v.inuse.domain
>  #define page_set_owner(_p,_d) ((_p)->v.inuse.domain = (_d))
> -- 
> 1.7.10.4
> 

_______________________________________________
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®.