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

Re: [Xen-devel] [PATCH v2 15/15] xen: arm: handle 40-bit addresses in the p2m



On Fri, 22 Nov 2013, Ian Campbell wrote:
> On the X-gene platform there are resources up this high which must be mapped
> to dom0.
> 
> Remove the first level page from the p2m->pages list since it is actually two
> pages and must be freed as such. Do so in p2m_teardown.
> 
> I've also punted on the implementation of dump_p2m_lookup for high
> addresses...
> 
> Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
> ---
> v2:
> Remove irrelevant commentary from commit message
> No longer RFC
> ---
>  xen/arch/arm/p2m.c |   60 
> +++++++++++++++++++++++++++++++++++++++++-----------
>  1 file changed, 48 insertions(+), 12 deletions(-)
> 
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index 82dda65..af32511 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -7,6 +7,10 @@
>  #include <asm/flushtlb.h>
>  #include <asm/gic.h>
>  
> +/* First level P2M is 2 consecutive pages */
> +#define P2M_FIRST_ORDER 1
> +#define P2M_FIRST_ENTRIES (LPAE_ENTRIES<<P2M_FIRST_ORDER)
> +
>  void dump_p2m_lookup(struct domain *d, paddr_t addr)
>  {
>      struct p2m_domain *p2m = &d->arch.p2m;
> @@ -14,6 +18,12 @@ void dump_p2m_lookup(struct domain *d, paddr_t addr)
>  
>      printk("dom%d IPA 0x%"PRIpaddr"\n", d->domain_id, addr);
>  
> +    if ( first_linear_offset(addr) > LPAE_ENTRIES )
> +    {
> +        printk("Cannot dump addresses in second of first level pages...\n");
> +        return;
> +    }
> +
>      printk("P2M @ %p mfn:0x%lx\n",
>             p2m->first_level, page_to_mfn(p2m->first_level));
>  
> @@ -31,6 +41,30 @@ void p2m_load_VTTBR(struct domain *d)
>      isb(); /* Ensure update is visible */
>  }
>  
> +static int p2m_first_level_index(paddr_t addr)

Would it make sense to make this an inline function?
Regardless you have my acked-by.

> +{
> +    /*
> +     * 1st pages are concatenated so zeroeth offset gives us the
> +     * index of the 1st page
> +     */
> +    return zeroeth_table_offset(addr);
> +}
> +
> +/*
> + * Map whichever of the first pages contain addr. The caller should
> + * then use first_table_offset as an index.
> + */
> +static lpae_t *p2m_map_first(struct p2m_domain *p2m, paddr_t addr)
> +{
> +    struct page_info *page;
> +
> +    BUG_ON(first_linear_offset(addr) > P2M_FIRST_ENTRIES);
> +
> +    page = p2m->first_level + p2m_first_level_index(addr);
> +
> +    return __map_domain_page(page);
> +}
> +
>  /*
>   * Lookup the MFN corresponding to a domain's PFN.
>   *
> @@ -45,7 +79,7 @@ paddr_t p2m_lookup(struct domain *d, paddr_t paddr)
>  
>      spin_lock(&p2m->lock);
>  
> -    first = __map_domain_page(p2m->first_level);
> +    first = p2m_map_first(p2m, paddr);
>  
>      pte = first[first_table_offset(paddr)];
>      if ( !pte.p2m.valid || !pte.p2m.table )
> @@ -135,18 +169,21 @@ static int create_p2m_entries(struct domain *d,
>      struct p2m_domain *p2m = &d->arch.p2m;
>      lpae_t *first = NULL, *second = NULL, *third = NULL;
>      paddr_t addr;
> -    unsigned long cur_first_offset = ~0, cur_second_offset = ~0;
> +    unsigned long cur_first_page = ~0,
> +                  cur_first_offset = ~0,
> +                  cur_second_offset = ~0;
>  
>      spin_lock(&p2m->lock);
>  
> -    /* XXX Don't actually handle 40 bit guest physical addresses */
> -    BUG_ON(start_gpaddr & 0x8000000000ULL);
> -    BUG_ON(end_gpaddr   & 0x8000000000ULL);
> -
> -    first = __map_domain_page(p2m->first_level);
> -
>      for(addr = start_gpaddr; addr < end_gpaddr; addr += PAGE_SIZE)
>      {
> +        if ( cur_first_page != p2m_first_level_index(addr) )
> +        {
> +            if ( first ) unmap_domain_page(first);
> +            first = p2m_map_first(p2m, addr);
> +            cur_first_page = p2m_first_level_index(addr);
> +        }
> +
>          if ( !first[first_table_offset(addr)].p2m.valid )
>          {
>              rc = p2m_create_table(d, &first[first_table_offset(addr)]);
> @@ -279,15 +316,12 @@ int p2m_alloc_table(struct domain *d)
>      struct page_info *page;
>      void *p;
>  
> -    /* First level P2M is 2 consecutive pages */
> -    page = alloc_domheap_pages(NULL, 1, 0);
> +    page = alloc_domheap_pages(NULL, P2M_FIRST_ORDER, 0);
>      if ( page == NULL )
>          return -ENOMEM;
>  
>      spin_lock(&p2m->lock);
>  
> -    page_list_add(page, &p2m->pages);
> -
>      /* Clear both first level pages */
>      p = __map_domain_page(page);
>      clear_page(p);
> @@ -380,6 +414,8 @@ void p2m_teardown(struct domain *d)
>      while ( (pg = page_list_remove_head(&p2m->pages)) )
>          free_domheap_page(pg);
>  
> +    free_domheap_pages(p2m->first_level, P2M_FIRST_ORDER);
> +
>      p2m->first_level = NULL;
>  
>      p2m_free_vmid(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®.