On 17/10/2022 08:46, Henry Wang wrote:
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index f17500ddf3..8c9ddf58e1 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -1736,7 +1739,20 @@ void p2m_final_teardown(struct domain *d)
>      if ( !p2m->domain )
>          return;
>  

Everything below here is "dead" code, because...


> +    /*
> +     * No need to call relinquish_p2m_mapping() here because
> +     * p2m_final_teardown() is called either after 
> domain_relinquish_resources()
> +     * where relinquish_p2m_mapping() has been called, or from failure path 
> of
> +     * domain_create()/arch_domain_create() where mappings that require
> +     * p2m_put_l3_page() should never be created. For the latter case, also 
> see
> +     * comment on top of the p2m_set_entry() for more info.
> +     */
> +
> +    BUG_ON(p2m_teardown(d, false));
>      ASSERT(page_list_empty(&p2m->pages));
> +
> +    while ( p2m_teardown_allocation(d) == -ERESTART )
> +        continue; /* No preemption support here */
>      ASSERT(page_list_empty(&d->arch.paging.p2m_freelist));
>  
>      if ( p2m->root )
> @@ -1762,6 +1778,20 @@ int p2m_init(struct domain *d)
>      INIT_PAGE_LIST_HEAD(&p2m->pages);
>      INIT_PAGE_LIST_HEAD(&d->arch.paging.p2m_freelist);
>  
> +    /*
> +     * Hardware using GICv2 needs to create a P2M mapping of 8KB GICv2 area
> +     * when the domain is created. Considering the worst case for page
> +     * tables and keep a buffer, populate 16 pages to the P2M pages pool 
> here.
> +     * For GICv3, the above-mentioned P2M mapping is not necessary, but since
> +     * the allocated 16 pages here would not be lost, hence populate these
> +     * pages unconditionally.
> +     */
> +    spin_lock(&d->arch.paging.lock);
> +    rc = p2m_set_allocation(d, 16, NULL);
> +    spin_unlock(&d->arch.paging.lock);
> +    if ( rc != 0 )
> +        return rc;

... this early exit is ahead of p2m_init() settings p2m->domain = d.

In particular, you introduce a bug whereby ...

> +
>      p2m->vmid = INVALID_VMID;
>  
>      rc = p2m_alloc_vmid(d);

... this error path now leaks the 16 page p2m allocation.


This change is overly complex.  You add a set_allocation(16) path in
p2m_init(), so should only be adding a single set_allocation(0) to
compensate.

The `while ( p2m_teardown_allocation(d) == -ERESTART ) continue;` is
especially silly because you're specifically wasting time ignoring the
preemption wrapper around the non-preemptible function that you actually
want to use.

Looking at between 4.13 and staging, you want to be calling
set_allocation(0) in p2m_final_teardown() ahead of of the p->domain
check.  Except idempotency which is going to be irritating here.

It will be a no-op from the normal domain destroy path (as relinquish
resource will have emptied the whole pool), while in domain_create error
path, it has a maximum of 16 pages to release.

I'll draft a patch.

~Andrew

Reply via email to