|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2] xen/arm: p2m: Correctly flush TLB in create_p2m_entries
On Thu, 2014-01-09 at 16:34 +0000, Julien Grall wrote:
> Except grant-table (I can't find {get,put}_page for grant-table code???),
I think they are in __gnttab_map_grant_ref, within __get_paged_frame or
through page_get_owner_and_reference.
and on unmap it is in__gnttab_unmap_common_complete.
It's a bit of a complex maze though so I'm not entirely sure, perhaps
Tim, Keir or Jan can confirm that a grant mapping always takes a
reference on the mapped page (it seems like PV x86 ought to be relying
on this for safety anyhow).
I think the flush in alloc_heap_pages would also serve as a backstop,
wouldn't it?
> all the callers are protected by a get_page before removing the page. So if
> the
> another VCPU is trying to access to this page before the flush, it will just
> read/write the wrong page.
>
> The downside of this patch is Xen flushes less TLBs. Instead of flushing all
> TLBs
> on the current PCPU, Xen flushes TLBs for a specific VMID on every CPUs. This
> should be safe because create_p2m_entries only deal with a specific domain.
>
> I don't think I forget case in this function. Let me know if it's the case.
> ---
> xen/arch/arm/p2m.c | 24 +++++++++++++++++++-----
> 1 file changed, 19 insertions(+), 5 deletions(-)
>
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index 11f4714..ad6f76e 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -238,7 +238,7 @@ static int create_p2m_entries(struct domain *d,
> int mattr,
> p2m_type_t t)
> {
> - int rc, flush;
> + int rc;
> struct p2m_domain *p2m = &d->arch.p2m;
> lpae_t *first = NULL, *second = NULL, *third = NULL;
> paddr_t addr;
> @@ -246,10 +246,14 @@ static int create_p2m_entries(struct domain *d,
> cur_first_offset = ~0,
> cur_second_offset = ~0;
> unsigned long count = 0;
> + unsigned int flush = 0;
> bool_t populate = (op == INSERT || op == ALLOCATE);
>
> spin_lock(&p2m->lock);
>
> + if ( d != current->domain )
> + p2m_load_VTTBR(d);
> +
> addr = start_gpaddr;
> while ( addr < end_gpaddr )
> {
> @@ -316,7 +320,7 @@ static int create_p2m_entries(struct domain *d,
> cur_second_offset = second_table_offset(addr);
> }
>
> - flush = third[third_table_offset(addr)].p2m.valid;
> + flush |= third[third_table_offset(addr)].p2m.valid;
>
> /* Allocate a new RAM page and attach */
> switch (op) {
> @@ -373,9 +377,6 @@ static int create_p2m_entries(struct domain *d,
> break;
> }
>
> - if ( flush )
> - flush_tlb_all_local();
> -
> /* Preempt every 2MiB (mapped) or 32 MiB (unmapped) - arbitrary */
> if ( op == RELINQUISH && count >= 0x2000 )
> {
> @@ -392,6 +393,16 @@ static int create_p2m_entries(struct domain *d,
> addr += PAGE_SIZE;
> }
>
> + if ( flush )
> + {
> + /* At the beginning of the function, Xen is updating VTTBR
> + * with the domain where the mappings are created. In this
> + * case it's only necessary to flush TLBs on every CPUs with
> + * the current VMID (our domain).
> + */
> + flush_tlb();
> + }
> +
> if ( op == ALLOCATE || op == INSERT )
> {
> unsigned long sgfn = paddr_to_pfn(start_gpaddr);
> @@ -409,6 +420,9 @@ out:
> if (second) unmap_domain_page(second);
> if (first) unmap_domain_page(first);
>
> + if ( d != current->domain )
> + p2m_load_VTTBR(current->domain);
> +
> spin_unlock(&p2m->lock);
>
> return rc;
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |