[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v03 01/10] xen: implement guest_physmap_pin_range
From: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> guest_physmap_pin_range pins a range of guest pages so that their p2m mappings won't be changed. guest_physmap_unpin_range unpins the previously pinned pages. The pinning is done using a new count_info flag. Provide empty stubs for x86. Andrii Tseglytskyi <andrii.tseglytskyi@xxxxxxxxxxxxxxx>: - rebased to latest master branch - added guest_physmap_pinned_range() API - pass mfn instead of gmfn Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> Signed-off-by: Andrii Tseglytskyi <andrii.tseglytskyi@xxxxxxxxxxxxxxx> --- xen/arch/arm/p2m.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++ xen/include/asm-arm/mm.h | 11 +++++++ xen/include/asm-x86/p2m.h | 20 ++++++++++++ 3 files changed, 113 insertions(+) diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index 46ec01c..b3a16d3 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -214,6 +214,79 @@ err: return maddr; } +int guest_physmap_pin_range(struct domain *d, + xen_pfn_t mfn, + unsigned int order) +{ + int i; + struct page_info *page; + + for ( i = 0; i < (1UL << order); i++ ) + { + if ( !mfn_valid(mfn + i) ) + return -EINVAL; + + page = mfn_to_page(mfn + i); + if ( !page ) + return -EINVAL; + + if ( !get_page_type(page, PGT_writable_page) ) + return -EINVAL; + + if ( test_and_set_bit(_PGC_p2m_pinned, &page->count_info) ) + return -EBUSY; + } + return 0; +} + +int guest_physmap_unpin_range(struct domain *d, + xen_pfn_t mfn, + unsigned int order) +{ + int i; + struct page_info *page; + + for ( i = 0; i < (1UL << order); i++ ) + { + if ( !mfn_valid(mfn + i) ) + return -EINVAL; + + page = mfn_to_page(mfn + i); + if ( !page ) + return -EINVAL; + + if ( !test_and_clear_bit(_PGC_p2m_pinned, &page->count_info) ) + return -EINVAL; + } + return 0; +} + +int guest_physmap_pinned_range(struct domain *d, + xen_pfn_t mfn, + unsigned int order) +{ + int i, pins = 0; + struct page_info *page; + + for ( i = 0; i < (1UL << order); i++ ) + { + if ( !mfn_valid(mfn + i) ) + return 0; + + page = mfn_to_page(mfn + i); + if ( !page ) + return 0; + + if ( test_bit(_PGC_p2m_pinned, &page->count_info) ) + pins++; + } + + if ( i && (i == pins) ) + return 1; + + return 0; +} + int guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn, unsigned int order) @@ -478,10 +551,18 @@ static int apply_one_level(struct domain *d, struct p2m_domain *p2m = &d->arch.p2m; lpae_t pte; const lpae_t orig_pte = *entry; + struct page_info *page = NULL; int rc; BUG_ON(level > 3); + if ( guest_physmap_pinned_range(d, orig_pte.p2m.base, 0) ) + { + gdprintk(XENLOG_WARNING, "cannot change p2m mapping for paddr=%"PRIpaddr + " domid=%d, the page is pinned count_info %lu\n", *addr, d->domain_id, page->count_info); + return -EINVAL; + } + switch ( op ) { case ALLOCATE: @@ -819,6 +900,7 @@ static int apply_p2m_changes(struct domain *d, &addr, &maddr, &flush, mattr, t); if ( ret < 0 ) { rc = ret ; goto out; } + /* L3 had better have done something! We cannot descend any further */ BUG_ON(ret == P2M_ONE_DESCEND); count += ret; diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h index 9fa80a4..f6d9e6b 100644 --- a/xen/include/asm-arm/mm.h +++ b/xen/include/asm-arm/mm.h @@ -92,6 +92,10 @@ struct page_info /* Page is Xen heap? */ #define _PGC_xen_heap PG_shift(2) #define PGC_xen_heap PG_mask(1, 2) +/* The page belongs to a guest and it has been pinned. */ +#define _PGC_p2m_pinned PG_shift(3) +#define PGC_p2m_pinned PG_mask(1, 3) + /* ... */ /* Page is broken? */ #define _PGC_broken PG_shift(7) @@ -340,6 +344,13 @@ void free_init_memory(void); int guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn, unsigned int order); +int guest_physmap_pin_range(struct domain *d, paddr_t mfn, + unsigned int order); +int guest_physmap_unpin_range(struct domain *d, paddr_t mfn, + unsigned int order); +int guest_physmap_pinned_range(struct domain *d, paddr_t mfn, + unsigned int order); + extern void put_page_type(struct page_info *page); static inline void put_page_and_type(struct page_info *page) { diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h index 39f235d..c7f12b1 100644 --- a/xen/include/asm-x86/p2m.h +++ b/xen/include/asm-x86/p2m.h @@ -514,6 +514,26 @@ void guest_physmap_remove_page(struct domain *d, int guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn, unsigned int order); +static inline int guest_physmap_pin_range(struct domain *d, + paddr_t mfn, + unsigned int order) +{ + return -ENOSYS; +} +static inline int guest_physmap_unpin_range(struct domain *d, + paddr_t mfn, + unsigned int order) +{ + return -ENOSYS; +} + +static inline int guest_physmap_pinned_range(struct domain *d, + paddr_t mfn, + unsigned int order) +{ + return -ENOSYS; +} + /* Change types across all p2m entries in a domain */ void p2m_change_entry_type_global(struct domain *d, p2m_type_t ot, p2m_type_t nt); -- 1.9.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |