diff mbox

xen/arm: p2m: flush TLB by VMID when a new domain is creating

Message ID 1384448434-23183-1-git-send-email-julien.grall@linaro.org
State Accepted, archived
Headers show

Commit Message

Julien Grall Nov. 14, 2013, 5 p.m. UTC
Once the VMID is marked unused, a new domain can reuse the VMID for its
own. If the TLB is not flushed, entries can contain wrong translation.
When a new p2m is allocated, switch to the new VMID and flush TLB on
every physical CPUs.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
---
    Changes in v2:
        - This patch was formerly "xen/arm: p2m: flush TLB when a domain
        is destroyed
        - Flush TLB by VMID in p2m_alloc_table. It will avoid to flush
        all TLBs every domain destruction.

---
 xen/arch/arm/p2m.c                   | 10 ++++++++++
 xen/include/asm-arm/arm32/flushtlb.h | 11 +++++++++++
 xen/include/asm-arm/arm64/flushtlb.h | 11 +++++++++++
 3 files changed, 32 insertions(+)

Comments

Stefano Stabellini Nov. 14, 2013, 6:10 p.m. UTC | #1
On Thu, 14 Nov 2013, Julien Grall wrote:
> Once the VMID is marked unused, a new domain can reuse the VMID for its
> own. If the TLB is not flushed, entries can contain wrong translation.
> When a new p2m is allocated, switch to the new VMID and flush TLB on
> every physical CPUs.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> ---
>     Changes in v2:
>         - This patch was formerly "xen/arm: p2m: flush TLB when a domain
>         is destroyed
>         - Flush TLB by VMID in p2m_alloc_table. It will avoid to flush
>         all TLBs every domain destruction.
> 
> ---
>  xen/arch/arm/p2m.c                   | 10 ++++++++++
>  xen/include/asm-arm/arm32/flushtlb.h | 11 +++++++++++
>  xen/include/asm-arm/arm64/flushtlb.h | 11 +++++++++++
>  3 files changed, 32 insertions(+)
> 
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index 2d09fef..82dda65 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -302,6 +302,15 @@ int p2m_alloc_table(struct domain *d)
>      d->arch.vttbr = page_to_maddr(p2m->first_level)
>          | ((uint64_t)p2m->vmid&0xff)<<48;
>  
> +    p2m_load_VTTBR(d);
> +
> +    /* Make sure that all TLBs corresponding to the new VMID are flushed
> +     * before using it
> +     */
> +    flush_tlb();
> +
> +    p2m_load_VTTBR(current->domain);
> +
>      spin_unlock(&p2m->lock);
>  
>      return 0;
> @@ -357,6 +366,7 @@ static void p2m_free_vmid(struct domain *d)
>      spin_lock(&vmid_alloc_lock);
>      if ( p2m->vmid != INVALID_VMID )
>          clear_bit(p2m->vmid, vmid_mask);
> +
>      spin_unlock(&vmid_alloc_lock);
>  }
>  
> diff --git a/xen/include/asm-arm/arm32/flushtlb.h b/xen/include/asm-arm/arm32/flushtlb.h
> index a258f58..ab166f3 100644
> --- a/xen/include/asm-arm/arm32/flushtlb.h
> +++ b/xen/include/asm-arm/arm32/flushtlb.h
> @@ -12,6 +12,17 @@ static inline void flush_tlb_local(void)
>      isb();
>  }
>  
> +/* Flush inner shareable TLBs, current VMID only */
> +static inline void flush_tlb(void)
> +{
> +    dsb();
> +
> +    WRITE_CP32((uint32_t) 0, TLBIALLIS);
> +
> +    dsb();
> +    isb();
> +}

Why only inner shareable? Shouldn't we use the existing flush_tlb_local
instead?
Julien Grall Nov. 14, 2013, 8:35 p.m. UTC | #2
On 11/14/2013 06:10 PM, Stefano Stabellini wrote:
>
> Why only inner shareable? Shouldn't we use the existing flush_tlb_local
> instead?
>

As I understand TLBIALL is only to flush TLB on the local processor, 
rather than TLBIALLIS which is used to broadcast on all processor.

So here we need to flush on every processor TLBs by VMID.

--
Julien Grall
Stefano Stabellini Nov. 14, 2013, 8:41 p.m. UTC | #3
On Thu, 14 Nov 2013, Julien Grall wrote:
> On 11/14/2013 06:10 PM, Stefano Stabellini wrote:
> > 
> > Why only inner shareable? Shouldn't we use the existing flush_tlb_local
> > instead?
> > 
> 
> As I understand TLBIALL is only to flush TLB on the local processor, rather
> than TLBIALLIS which is used to broadcast on all processor.
> 
> So here we need to flush on every processor TLBs by VMID.

Right, sorry, my mistake.

Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Ian Campbell Nov. 19, 2013, 2:54 p.m. UTC | #4
On Thu, 2013-11-14 at 20:41 +0000, Stefano Stabellini wrote:
> On Thu, 14 Nov 2013, Julien Grall wrote:
> > On 11/14/2013 06:10 PM, Stefano Stabellini wrote:
> > > 
> > > Why only inner shareable? Shouldn't we use the existing flush_tlb_local
> > > instead?
> > > 
> > 
> > As I understand TLBIALL is only to flush TLB on the local processor, rather
> > than TLBIALLIS which is used to broadcast on all processor.
> > 
> > So here we need to flush on every processor TLBs by VMID.
> 
> Right, sorry, my mistake.
> 
> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>

Agreed, + committed.
diff mbox

Patch

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 2d09fef..82dda65 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -302,6 +302,15 @@  int p2m_alloc_table(struct domain *d)
     d->arch.vttbr = page_to_maddr(p2m->first_level)
         | ((uint64_t)p2m->vmid&0xff)<<48;
 
+    p2m_load_VTTBR(d);
+
+    /* Make sure that all TLBs corresponding to the new VMID are flushed
+     * before using it
+     */
+    flush_tlb();
+
+    p2m_load_VTTBR(current->domain);
+
     spin_unlock(&p2m->lock);
 
     return 0;
@@ -357,6 +366,7 @@  static void p2m_free_vmid(struct domain *d)
     spin_lock(&vmid_alloc_lock);
     if ( p2m->vmid != INVALID_VMID )
         clear_bit(p2m->vmid, vmid_mask);
+
     spin_unlock(&vmid_alloc_lock);
 }
 
diff --git a/xen/include/asm-arm/arm32/flushtlb.h b/xen/include/asm-arm/arm32/flushtlb.h
index a258f58..ab166f3 100644
--- a/xen/include/asm-arm/arm32/flushtlb.h
+++ b/xen/include/asm-arm/arm32/flushtlb.h
@@ -12,6 +12,17 @@  static inline void flush_tlb_local(void)
     isb();
 }
 
+/* Flush inner shareable TLBs, current VMID only */
+static inline void flush_tlb(void)
+{
+    dsb();
+
+    WRITE_CP32((uint32_t) 0, TLBIALLIS);
+
+    dsb();
+    isb();
+}
+
 /* Flush local TLBs, all VMIDs, non-hypervisor mode */
 static inline void flush_tlb_all_local(void)
 {
diff --git a/xen/include/asm-arm/arm64/flushtlb.h b/xen/include/asm-arm/arm64/flushtlb.h
index d0535a0..9ce79a8 100644
--- a/xen/include/asm-arm/arm64/flushtlb.h
+++ b/xen/include/asm-arm/arm64/flushtlb.h
@@ -12,6 +12,17 @@  static inline void flush_tlb_local(void)
         : : : "memory");
 }
 
+/* Flush innershareable TLBs, current VMID only */
+static inline void flush_tlb(void)
+{
+    asm volatile(
+        "dsb sy;"
+        "tlbi vmalle1is;"
+        "dsb sy;"
+        "isb;"
+        : : : "memory");
+}
+
 /* Flush local TLBs, all VMIDs, non-hypervisor mode */
 static inline void flush_tlb_all_local(void)
 {