[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v2 05/17] xen/riscv: introduce things necessary for p2m initialization
Introduce the following things: - Update p2m_domain structure, which describe per p2m-table state, with: - lock to protect updates to p2m. - pool with pages used to construct p2m. - clean_pte which indicate if it is requires to clean the cache when writing an entry. - radix tree to store p2m type as PTE doesn't have enough free bits to store type. - default_access to store p2m access type for each page in the domain. - back pointer to domain structure. - p2m_init() to initalize members introduced in p2m_domain structure. - Introudce p2m_write_lock() and p2m_is_write_locked(). - Introduce p2m_force_tlb_flush_sync() to flush TLBs after p2m table update. Signed-off-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx> --- Changes in V2: - Use introduced erlier sbi_remote_hfence_gvma_vmid() for proper implementation of p2m_force_tlb_flush_sync() as TLB flushing needs to happen for each pCPU which potentially has cached a mapping, what is tracked by d->dirty_cpumask. - Drop unnecessary blanks. - Fix code style for # of pre-processor directive. - Drop max_mapped_gfn and lowest_mapped_gfn as they aren't used now. - [p2m_init()] Set p2m->clean_pte=false if CONFIG_HAS_PASSTHROUGH=n. - [p2m_init()] Update the comment above p2m->domain = d; - Drop p2m->need_flush as it seems to be always true for RISC-V and as a consequence drop p2m_tlb_flush_sync(). - Move to separate patch an introduction of root page table allocation. --- xen/arch/riscv/include/asm/p2m.h | 39 +++++++++++++++++++++ xen/arch/riscv/p2m.c | 58 ++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/xen/arch/riscv/include/asm/p2m.h b/xen/arch/riscv/include/asm/p2m.h index 359408e1be..9570eff014 100644 --- a/xen/arch/riscv/include/asm/p2m.h +++ b/xen/arch/riscv/include/asm/p2m.h @@ -3,6 +3,10 @@ #define ASM__RISCV__P2M_H #include <xen/errno.h> +#include <xen/mem_access.h> +#include <xen/mm.h> +#include <xen/radix-tree.h> +#include <xen/rwlock.h> #include <xen/types.h> #include <asm/page-bits.h> @@ -14,6 +18,29 @@ /* Per-p2m-table state */ struct p2m_domain { + /* + * Lock that protects updates to the p2m. + */ + rwlock_t lock; + + /* Pages used to construct the p2m */ + struct page_list_head pages; + + /* Indicate if it is required to clean the cache when writing an entry */ + bool clean_pte; + + struct radix_tree_root p2m_type; + + /* + * Default P2M access type for each page in the the domain: new pages, + * swapped in pages, cleared pages, and pages that are ambiguously + * retyped get this access type. See definition of p2m_access_t. + */ + p2m_access_t default_access; + + /* Back pointer to domain */ + struct domain *domain; + /* Current VMID in use */ uint16_t vmid; }; @@ -107,6 +134,18 @@ void p2m_vmid_allocator_init(void); int p2m_init(struct domain *d); +static inline void p2m_write_lock(struct p2m_domain *p2m) +{ + write_lock(&p2m->lock); +} + +void p2m_write_unlock(struct p2m_domain *p2m); + +static inline int p2m_is_write_locked(struct p2m_domain *p2m) +{ + return rw_is_write_locked(&p2m->lock); +} + #endif /* ASM__RISCV__P2M_H */ /* diff --git a/xen/arch/riscv/p2m.c b/xen/arch/riscv/p2m.c index f33c7147ff..e409997499 100644 --- a/xen/arch/riscv/p2m.c +++ b/xen/arch/riscv/p2m.c @@ -1,13 +1,46 @@ #include <xen/bitops.h> +#include <xen/domain_page.h> #include <xen/event.h> +#include <xen/iommu.h> #include <xen/lib.h> +#include <xen/mm.h> +#include <xen/pfn.h> +#include <xen/rwlock.h> #include <xen/sched.h> #include <xen/spinlock.h> #include <xen/xvmalloc.h> +#include <asm/page.h> #include <asm/p2m.h> #include <asm/sbi.h> +/* + * Force a synchronous P2M TLB flush. + * + * Must be called with the p2m lock held. + */ +static void p2m_force_tlb_flush_sync(struct p2m_domain *p2m) +{ + struct domain *d = p2m->domain; + + ASSERT(p2m_is_write_locked(p2m)); + + sbi_remote_hfence_gvma_vmid(d->dirty_cpumask, 0, 0, p2m->vmid); +} + +/* Unlock the flush and do a P2M TLB flush if necessary */ +void p2m_write_unlock(struct p2m_domain *p2m) +{ + /* + * The final flush is done with the P2M write lock taken to avoid + * someone else modifying the P2M wbefore the TLB invalidation has + * completed. + */ + p2m_force_tlb_flush_sync(p2m); + + write_unlock(&p2m->lock); +} + static spinlock_t vmid_alloc_lock = SPIN_LOCK_UNLOCKED; /* @@ -109,8 +142,33 @@ int p2m_init(struct domain *d) spin_lock_init(&d->arch.paging.lock); INIT_PAGE_LIST_HEAD(&d->arch.paging.p2m_freelist); + rwlock_init(&p2m->lock); + INIT_PAGE_LIST_HEAD(&p2m->pages); + p2m->vmid = INVALID_VMID; + p2m->default_access = p2m_access_rwx; + + radix_tree_init(&p2m->p2m_type); + +#ifdef CONFIG_HAS_PASSTHROUGH + /* + * Some IOMMUs don't support coherent PT walk. When the p2m is + * shared with the CPU, Xen has to make sure that the PT changes have + * reached the memory + */ + p2m->clean_pte = is_iommu_enabled(d) && + !iommu_has_feature(d, IOMMU_FEAT_COHERENT_WALK); +#else + p2m->clean_pte = false; +#endif + + /* + * "Trivial" initialisation is now complete. Set the backpointer so the + * users of p2m could get an access to domain structure. + */ + p2m->domain = d; + rc = p2m_alloc_vmid(d); if ( rc ) return rc; -- 2.49.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |