[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] xen/arm: p2m: Perform local TLB invalidation on vCPU migration
commit 607ad85d85f4856fa9feba44db4e16f033862eb0 Author: Julien Grall <julien.grall@xxxxxxx> AuthorDate: Wed Mar 8 18:06:02 2017 +0000 Commit: Stefano Stabellini <sstabellini@xxxxxxxxxx> CommitDate: Tue Mar 14 16:31:07 2017 -0700 xen/arm: p2m: Perform local TLB invalidation on vCPU migration The ARM architecture allows an OS to have per-CPU page tables, as it guarantees that TLBs never migrate from one CPU to another. This works fine until this is done in a guest. Consider the following scenario: - vcpu-0 maps P to V - vpcu-1 maps P' to V If run on the same physical CPU, vcpu-1 can hit in TLBs generated by vcpu-0 accesses, and access the wrong physical page. The solution to this is to keep a per-p2m map of which vCPU ran the last on each given pCPU and invalidate local TLBs if two vPCUs from the same VM run on the same CPU. Unfortunately it is not possible to allocate per-cpu variable on the fly. So for now the size of the array is NR_CPUS, this is fine because we still have space in the structure domain. We may want to add an helper to allocate per-cpu variable in the future. Signed-off-by: Julien Grall <julien.grall@xxxxxxx> Reviewed-by: Stefano Stabellini <sstabellini@xxxxxxxxxx> --- xen/arch/arm/p2m.c | 24 ++++++++++++++++++++++++ xen/include/asm-arm/p2m.h | 3 +++ 2 files changed, 27 insertions(+) diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index 1fc6ca3..6263760 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -130,6 +130,7 @@ void p2m_restore_state(struct vcpu *n) { register_t hcr; struct p2m_domain *p2m = &n->domain->arch.p2m; + uint8_t *last_vcpu_ran; if ( is_idle_vcpu(n) ) return; @@ -149,6 +150,17 @@ void p2m_restore_state(struct vcpu *n) WRITE_SYSREG(hcr, HCR_EL2); isb(); + + last_vcpu_ran = &p2m->last_vcpu_ran[smp_processor_id()]; + + /* + * Flush local TLB for the domain to prevent wrong TLB translation + * when running multiple vCPU of the same domain on a single pCPU. + */ + if ( *last_vcpu_ran != INVALID_VCPU_ID && *last_vcpu_ran != n->vcpu_id ) + flush_tlb_local(); + + *last_vcpu_ran = n->vcpu_id; } static void p2m_flush_tlb(struct p2m_domain *p2m) @@ -1247,6 +1259,7 @@ int p2m_init(struct domain *d) { struct p2m_domain *p2m = &d->arch.p2m; int rc = 0; + unsigned int cpu; rwlock_init(&p2m->lock); INIT_PAGE_LIST_HEAD(&p2m->pages); @@ -1275,6 +1288,17 @@ int p2m_init(struct domain *d) rc = p2m_alloc_table(d); + /* + * Make sure that the type chosen to is able to store the an vCPU ID + * between 0 and the maximum of virtual CPUS supported as long as + * the INVALID_VCPU_ID. + */ + BUILD_BUG_ON((1 << (sizeof(p2m->last_vcpu_ran[0]) * 8)) < MAX_VIRT_CPUS); + BUILD_BUG_ON((1 << (sizeof(p2m->last_vcpu_ran[0])* 8)) < INVALID_VCPU_ID); + + for_each_possible_cpu(cpu) + p2m->last_vcpu_ran[cpu] = INVALID_VCPU_ID; + return rc; } diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h index 0899523..18c57f9 100644 --- a/xen/include/asm-arm/p2m.h +++ b/xen/include/asm-arm/p2m.h @@ -96,6 +96,9 @@ struct p2m_domain { /* back pointer to domain */ struct domain *domain; + + /* Keeping track on which CPU this p2m was used and for which vCPU */ + uint8_t last_vcpu_ran[NR_CPUS]; }; /* -- generated by git-patchbot for /home/xen/git/xen.git#master _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx https://lists.xenproject.org/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |