[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH V15 1/9] xen/arm: groundwork for mem_access support on ARM
Add necessary changes for page table construction routines to pass the default access information and hypercall continuation mask. Also, define necessary functions and data fields to be used later by mem_access. The p2m_access_t info will be stored in a Radix tree as the PTE lacks enough software programmable bits, thus in this patch we add the radix-tree construction/destruction portions. The tree itself will be used later by mem_access. Signed-off-by: Tamas K Lengyel <tklengyel@xxxxxxxxxxxxx> Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx> --- v14: - Update patch message to be more descriptive. v13: - Rename access_in_use to mem_access_enabled. - Define p2m_get_mem_access function prototype but return -ENOSYS for now. v11: - Move including common/mem_event.h down the series. v10: - Typo fix and drop reshuffling things that no longer need shuffling. v8: - Drop lock inputs as common mem_access_check is postponed. - Resurrect the radix tree with an extra boolean access_in_use flag to indicate if the tree is empty to avoid lookups. v7: - Remove radix tree init/destroy and move p2m_access_t store to page_info. - Add p2m_gpfn_lock/unlock functions. - Add bool_t lock input to p2m_lookup and apply_p2m_changes so the caller can specify if locking should be performed. This is needed in order to support mem_access_check from common. v6: - Move mem_event header include to first patch that needs it. v5: - #include grouping style-fix. v4: - Move p2m_get_hostp2m definition here. --- xen/arch/arm/p2m.c | 52 +++++++++++++++++++++++++++-------------- xen/include/asm-arm/domain.h | 1 + xen/include/asm-arm/p2m.h | 35 ++++++++++++++++++++++++++- xen/include/asm-arm/processor.h | 2 +- 4 files changed, 70 insertions(+), 20 deletions(-) diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index 8809f5a..137e5a0 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -305,7 +305,7 @@ static void p2m_set_permission(lpae_t *e, p2m_type_t t, p2m_access_t a) } static lpae_t mfn_to_p2m_entry(unsigned long mfn, unsigned int mattr, - p2m_type_t t) + p2m_type_t t, p2m_access_t a) { paddr_t pa = ((paddr_t) mfn) << PAGE_SHIFT; /* sh, xn and write bit will be defined in the following switches @@ -335,8 +335,7 @@ static lpae_t mfn_to_p2m_entry(unsigned long mfn, unsigned int mattr, break; } - /* We pass p2m_access_rwx as a placeholder for now. */ - p2m_set_permission(&e, t, p2m_access_rwx); + p2m_set_permission(&e, t, a); ASSERT(!(pa & ~PAGE_MASK)); ASSERT(!(pa & ~PADDR_MASK)); @@ -394,7 +393,7 @@ static int p2m_create_table(struct domain *d, lpae_t *entry, for ( i=0 ; i < LPAE_ENTRIES; i++ ) { pte = mfn_to_p2m_entry(base_pfn + (i<<(level_shift-LPAE_SHIFT)), - MATTR_MEM, t); + MATTR_MEM, t, p2m->default_access); /* * First and second level super pages set p2m.table = 0, but @@ -414,7 +413,8 @@ static int p2m_create_table(struct domain *d, lpae_t *entry, unmap_domain_page(p); - pte = mfn_to_p2m_entry(page_to_mfn(page), MATTR_MEM, p2m_invalid); + pte = mfn_to_p2m_entry(page_to_mfn(page), MATTR_MEM, p2m_invalid, + p2m->default_access); p2m_write_pte(entry, pte, flush_cache); @@ -537,7 +537,8 @@ static int apply_one_level(struct domain *d, paddr_t *maddr, bool_t *flush, int mattr, - p2m_type_t t) + p2m_type_t t, + p2m_access_t a) { const paddr_t level_size = level_sizes[level]; const paddr_t level_mask = level_masks[level]; @@ -566,7 +567,7 @@ static int apply_one_level(struct domain *d, page = alloc_domheap_pages(d, level_shift - PAGE_SHIFT, 0); if ( page ) { - pte = mfn_to_p2m_entry(page_to_mfn(page), mattr, t); + pte = mfn_to_p2m_entry(page_to_mfn(page), mattr, t, a); if ( level < 3 ) pte.p2m.table = 0; p2m_write_pte(entry, pte, flush_cache); @@ -601,7 +602,7 @@ static int apply_one_level(struct domain *d, (level == 3 || !p2m_table(orig_pte)) ) { /* New mapping is superpage aligned, make it */ - pte = mfn_to_p2m_entry(*maddr >> PAGE_SHIFT, mattr, t); + pte = mfn_to_p2m_entry(*maddr >> PAGE_SHIFT, mattr, t, a); if ( level < 3 ) pte.p2m.table = 0; /* Superpage entry */ @@ -770,7 +771,9 @@ static int apply_p2m_changes(struct domain *d, paddr_t end_gpaddr, paddr_t maddr, int mattr, - p2m_type_t t) + uint32_t mask, + p2m_type_t t, + p2m_access_t a) { int rc, ret; struct p2m_domain *p2m = &d->arch.p2m; @@ -863,7 +866,7 @@ static int apply_p2m_changes(struct domain *d, level, flush_pt, op, start_gpaddr, end_gpaddr, &addr, &maddr, &flush, - mattr, t); + mattr, t, a); if ( ret < 0 ) { rc = ret ; goto out; } count += ret; /* L3 had better have done something! We cannot descend any further */ @@ -921,7 +924,7 @@ out: */ apply_p2m_changes(d, REMOVE, start_gpaddr, addr + level_sizes[level], orig_maddr, - mattr, p2m_invalid); + mattr, 0, p2m_invalid, d->arch.p2m.default_access); } for ( level = P2M_ROOT_LEVEL; level < 4; level ++ ) @@ -940,7 +943,8 @@ int p2m_populate_ram(struct domain *d, paddr_t end) { return apply_p2m_changes(d, ALLOCATE, start, end, - 0, MATTR_MEM, p2m_ram_rw); + 0, MATTR_MEM, 0, p2m_ram_rw, + d->arch.p2m.default_access); } int map_mmio_regions(struct domain *d, @@ -952,7 +956,8 @@ int map_mmio_regions(struct domain *d, pfn_to_paddr(start_gfn), pfn_to_paddr(start_gfn + nr), pfn_to_paddr(mfn), - MATTR_DEV, p2m_mmio_direct); + MATTR_DEV, 0, p2m_mmio_direct, + d->arch.p2m.default_access); } int unmap_mmio_regions(struct domain *d, @@ -964,7 +969,8 @@ int unmap_mmio_regions(struct domain *d, pfn_to_paddr(start_gfn), pfn_to_paddr(start_gfn + nr), pfn_to_paddr(mfn), - MATTR_DEV, p2m_invalid); + MATTR_DEV, 0, p2m_invalid, + d->arch.p2m.default_access); } int guest_physmap_add_entry(struct domain *d, @@ -976,7 +982,8 @@ int guest_physmap_add_entry(struct domain *d, return apply_p2m_changes(d, INSERT, pfn_to_paddr(gpfn), pfn_to_paddr(gpfn + (1 << page_order)), - pfn_to_paddr(mfn), MATTR_MEM, t); + pfn_to_paddr(mfn), MATTR_MEM, 0, t, + d->arch.p2m.default_access); } void guest_physmap_remove_page(struct domain *d, @@ -986,7 +993,8 @@ void guest_physmap_remove_page(struct domain *d, apply_p2m_changes(d, REMOVE, pfn_to_paddr(gpfn), pfn_to_paddr(gpfn + (1<<page_order)), - pfn_to_paddr(mfn), MATTR_MEM, p2m_invalid); + pfn_to_paddr(mfn), MATTR_MEM, 0, p2m_invalid, + d->arch.p2m.default_access); } int p2m_alloc_table(struct domain *d) @@ -1090,6 +1098,8 @@ void p2m_teardown(struct domain *d) p2m_free_vmid(d); + radix_tree_destroy(&p2m->mem_access_settings, NULL); + spin_unlock(&p2m->lock); } @@ -1115,6 +1125,10 @@ int p2m_init(struct domain *d) p2m->max_mapped_gfn = 0; p2m->lowest_mapped_gfn = ULONG_MAX; + p2m->default_access = p2m_access_rwx; + p2m->mem_access_enabled = false; + radix_tree_init(&p2m->mem_access_settings); + err: spin_unlock(&p2m->lock); @@ -1129,7 +1143,8 @@ int relinquish_p2m_mapping(struct domain *d) pfn_to_paddr(p2m->lowest_mapped_gfn), pfn_to_paddr(p2m->max_mapped_gfn), pfn_to_paddr(INVALID_MFN), - MATTR_MEM, p2m_invalid); + MATTR_MEM, 0, p2m_invalid, + d->arch.p2m.default_access); } int p2m_cache_flush(struct domain *d, xen_pfn_t start_mfn, xen_pfn_t end_mfn) @@ -1143,7 +1158,8 @@ int p2m_cache_flush(struct domain *d, xen_pfn_t start_mfn, xen_pfn_t end_mfn) pfn_to_paddr(start_mfn), pfn_to_paddr(end_mfn), pfn_to_paddr(INVALID_MFN), - MATTR_MEM, p2m_invalid); + MATTR_MEM, 0, p2m_invalid, + d->arch.p2m.default_access); } unsigned long gmfn_to_mfn(struct domain *d, unsigned long gpfn) diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h index 9e0419e..f1a087e 100644 --- a/xen/include/asm-arm/domain.h +++ b/xen/include/asm-arm/domain.h @@ -17,6 +17,7 @@ struct hvm_domain { uint64_t params[HVM_NR_PARAMS]; struct hvm_iommu iommu; + bool_t introspection_enabled; } __cacheline_aligned; #ifdef CONFIG_ARM_64 diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h index 11efb5b..fec191f 100644 --- a/xen/include/asm-arm/p2m.h +++ b/xen/include/asm-arm/p2m.h @@ -2,8 +2,9 @@ #define _XEN_P2M_H #include <xen/mm.h> - +#include <xen/radix-tree.h> #include <xen/p2m-common.h> +#include <public/memory.h> #define paddr_bits PADDR_BITS @@ -48,6 +49,18 @@ struct p2m_domain { /* If true, and an access fault comes in and there is no vm_event listener, * pause domain. Otherwise, remove access restrictions. */ bool_t access_required; + + /* Defines if mem_access is in use for the domain. */ + bool_t mem_access_enabled; + + /* 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; + + /* Radix tree to store the p2m_access_t settings as the pte's don't have + * enough available bits to store this information. */ + struct radix_tree_root mem_access_settings; }; /* List of possible type for each page in the p2m entry. @@ -225,6 +238,26 @@ static inline int get_page_and_type(struct page_info *page, /* get host p2m table */ #define p2m_get_hostp2m(d) (&(d)->arch.p2m) +/* mem_event and mem_access are supported on any ARM guest */ +static inline bool_t p2m_mem_access_sanity_check(struct domain *d) +{ + return 1; +} + +static inline bool_t p2m_mem_event_sanity_check(struct domain *d) +{ + return 1; +} + +/* Get access type for a pfn + * If pfn == -1ul, gets the default access type */ +static inline +int p2m_get_mem_access(struct domain *d, unsigned long pfn, + xenmem_access_t *access) +{ + return -ENOSYS; +} + #endif /* _XEN_P2M_H */ /* diff --git a/xen/include/asm-arm/processor.h b/xen/include/asm-arm/processor.h index 5ccf61f..905c479 100644 --- a/xen/include/asm-arm/processor.h +++ b/xen/include/asm-arm/processor.h @@ -441,7 +441,7 @@ union hsr { struct hsr_dabt { unsigned long dfsc:6; /* Data Fault Status Code */ unsigned long write:1; /* Write / not Read */ - unsigned long s1ptw:1; /* */ + unsigned long s1ptw:1; /* Stage 2 fault during stage 1 translation */ unsigned long cache:1; /* Cache Maintenance */ unsigned long eat:1; /* External Abort Type */ #ifdef CONFIG_ARM_32 -- 2.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |