[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [POWERPC][XEN] Handle foreign page mappings correctly
# HG changeset patch # User Jimi Xenidis <jimix@xxxxxxxxxxxxxx> # Node ID 2ba5452795d296df27625b862aa087de8d82918e # Parent 2e6c10dc7c0ba804665c6e13db8dbf7efe66f8cc [POWERPC][XEN] Handle foreign page mappings correctly The following patch performs the following: - add free_rma() to go with allocate_rma() - allocate_rma() returns -EINVAL if an RMA is already allocated - PFN_TYPE_REMOTE is now PFN_TYPE_FOREIGN - better checking of page_info in pfn2mfn() - Stop using RPN and LPN and use PFN and MFN respectively - Increase/decrease foreign domain refcount when another domain maps/unmaps it Signed-off-by: Jimi Xenidis <jimix@xxxxxxxxxxxxxx> Signed-off-by: Hollis Blanchard <hollisb@xxxxxxxxxx> --- xen/arch/powerpc/domain.c | 3 - xen/arch/powerpc/mm.c | 96 ++++++++++++++++++++++++++---------------- xen/arch/powerpc/papr/xlate.c | 60 ++++++++++++++++++++------ xen/arch/powerpc/usercopy.c | 4 - xen/include/asm-powerpc/mm.h | 5 +- 5 files changed, 112 insertions(+), 56 deletions(-) diff -r 2e6c10dc7c0b -r 2ba5452795d2 xen/arch/powerpc/domain.c --- a/xen/arch/powerpc/domain.c Tue Sep 12 10:53:46 2006 -0400 +++ b/xen/arch/powerpc/domain.c Tue Sep 12 11:01:04 2006 -0400 @@ -244,8 +244,7 @@ void sync_vcpu_execstate(struct vcpu *v) void domain_relinquish_resources(struct domain *d) { - if (d->arch.rma_page) - free_domheap_pages(d->arch.rma_page, d->arch.rma_order); + free_rma(d); free_extents(d); } diff -r 2e6c10dc7c0b -r 2ba5452795d2 xen/arch/powerpc/mm.c --- a/xen/arch/powerpc/mm.c Tue Sep 12 10:53:46 2006 -0400 +++ b/xen/arch/powerpc/mm.c Tue Sep 12 11:01:04 2006 -0400 @@ -299,7 +299,7 @@ int allocate_rma(struct domain *d, unsig ulong rma_sz; if (d->arch.rma_page) - free_domheap_pages(d->arch.rma_page, d->arch.rma_order); + return -EINVAL; d->arch.rma_page = alloc_domheap_pages(d, order, 0); if (d->arch.rma_page == NULL) { @@ -329,50 +329,74 @@ int allocate_rma(struct domain *d, unsig return 0; } +void free_rma(struct domain *d) +{ + if (d->arch.rma_page) { + free_domheap_pages(d->arch.rma_page, d->arch.rma_order); + } +} + ulong pfn2mfn(struct domain *d, ulong pfn, int *type) { ulong rma_base_mfn = page_to_mfn(d->arch.rma_page); ulong rma_size_mfn = 1UL << d->arch.rma_order; struct page_extents *pe; - - if (type) - *type = PFN_TYPE_NONE; + ulong mfn = INVALID_MFN; + int t = PFN_TYPE_NONE; /* quick tests first */ - if (pfn < rma_size_mfn) { - if (type) - *type = PFN_TYPE_RMA; - return pfn + rma_base_mfn; - } - if (test_bit(_DOMF_privileged, &d->domain_flags) && cpu_io_mfn(pfn)) { - if (type) - *type = PFN_TYPE_IO; - return pfn; - } - - list_for_each_entry (pe, &d->arch.extent_list, pe_list) { - uint end_pfn = pe->pfn + (1 << pe->order); - - if (pfn >= pe->pfn && pfn < end_pfn) { - if (type) - *type = PFN_TYPE_LOGICAL; - return page_to_mfn(pe->pg) + (pfn - pe->pfn); - } - } - - /* This hack allows dom0 to map all memory, necessary to - * initialize domU state. */ - if (test_bit(_DOMF_privileged, &d->domain_flags) && - pfn < max_page) { - if (type) - *type = PFN_TYPE_REMOTE; - return pfn; - } - - BUG(); - return INVALID_MFN; + t = PFN_TYPE_IO; + mfn = pfn; + } else { + if (pfn < rma_size_mfn) { + t = PFN_TYPE_RMA; + mfn = pfn + rma_base_mfn; + } else { + list_for_each_entry (pe, &d->arch.extent_list, pe_list) { + uint end_pfn = pe->pfn + (1 << pe->order); + + if (pfn >= pe->pfn && pfn < end_pfn) { + t = PFN_TYPE_LOGICAL; + mfn = page_to_mfn(pe->pg) + (pfn - pe->pfn); + break; + } + } + } + BUG_ON(t != PFN_TYPE_NONE && page_get_owner(mfn_to_page(mfn)) != d); + } + + if (t == PFN_TYPE_NONE) { + /* This hack allows dom0 to map all memory, necessary to + * initialize domU state. */ + if (test_bit(_DOMF_privileged, &d->domain_flags) && + mfn_valid(pfn)) { + struct page_info *pg; + + /* page better be allocated to some domain but not the caller */ + pg = mfn_to_page(pfn); + if (!(pg->count_info & PGC_allocated)) + panic("Foreign page: 0x%lx is not owned by any domain\n", + mfn); + if (page_get_owner(pg) == d) + panic("Foreign page: 0x%lx is owned by this domain\n", + mfn); + + t = PFN_TYPE_FOREIGN; + mfn = pfn; + } + } + + if (mfn == INVALID_MFN) { + printk("%s: Dom[%d] pfn 0x%lx is not a valid page\n", + __func__, d->domain_id, pfn); + } + + if (type) + *type = t; + + return mfn; } void guest_physmap_add_page( diff -r 2e6c10dc7c0b -r 2ba5452795d2 xen/arch/powerpc/papr/xlate.c --- a/xen/arch/powerpc/papr/xlate.c Tue Sep 12 10:53:46 2006 -0400 +++ b/xen/arch/powerpc/papr/xlate.c Tue Sep 12 11:01:04 2006 -0400 @@ -118,8 +118,8 @@ static void h_enter(struct cpu_user_regs int pgshift = PAGE_SHIFT; ulong idx; int limit = 0; /* how many PTEs to examine in the PTEG */ - ulong lpn; - ulong rpn; + ulong pfn; + ulong mfn; struct vcpu *v = get_current(); struct domain *d = v->domain; int mtype; @@ -160,11 +160,11 @@ static void h_enter(struct cpu_user_regs /* get the correct logical RPN in terms of 4K pages need to mask * off lp bits and unused arpn bits if this is a large page */ - lpn = ~0ULL << (pgshift - PAGE_SHIFT); - lpn = pte.bits.rpn & lpn; - - rpn = pfn2mfn(d, lpn, &mtype); - if (rpn == INVALID_MFN) { + pfn = ~0ULL << (pgshift - PAGE_SHIFT); + pfn = pte.bits.rpn & pfn; + + mfn = pfn2mfn(d, pfn, &mtype); + if (mfn == INVALID_MFN) { regs->gprs[3] = H_Parameter; return; } @@ -173,8 +173,8 @@ static void h_enter(struct cpu_user_regs /* only a privilaged dom can access outside IO space */ if ( !test_bit(_DOMF_privileged, &d->domain_flags) ) { regs->gprs[3] = H_Privilege; - printk("%s: unprivileged access to logical page: 0x%lx\n", - __func__, lpn); + printk("%s: unprivileged access to physical page: 0x%lx\n", + __func__, pfn); return; } @@ -192,7 +192,7 @@ static void h_enter(struct cpu_user_regs } } /* fixup the RPN field of our local PTE copy */ - pte.bits.rpn = rpn | lp_bits; + pte.bits.rpn = mfn | lp_bits; /* clear reserved bits in high word */ pte.bits.lock = 0x0; @@ -211,12 +211,12 @@ static void h_enter(struct cpu_user_regs /* data manipulations should be done prior to the pte insertion. */ if ( flags & H_ZERO_PAGE ) { - memset((void *)(rpn << PAGE_SHIFT), 0, 1UL << pgshift); + memset((void *)(mfn << PAGE_SHIFT), 0, 1UL << pgshift); } if ( flags & H_ICACHE_INVALIDATE ) { ulong k; - ulong addr = rpn << PAGE_SHIFT; + ulong addr = mfn << PAGE_SHIFT; for (k = 0; k < (1UL << pgshift); k += L1_CACHE_BYTES) { dcbst(addr + k); @@ -229,7 +229,7 @@ static void h_enter(struct cpu_user_regs if ( flags & H_ICACHE_SYNCHRONIZE ) { ulong k; - ulong addr = rpn << PAGE_SHIFT; + ulong addr = mfn << PAGE_SHIFT; for (k = 0; k < (1UL << pgshift); k += L1_CACHE_BYTES) { icbi(addr + k); sync(); @@ -251,6 +251,26 @@ static void h_enter(struct cpu_user_regs regs->gprs[3] = H_Success; regs->gprs[4] = idx; + + + switch (mtype) { + case PFN_TYPE_IO: + break; + case PFN_TYPE_FOREIGN: + { + struct page_info *pg = mfn_to_page(mfn); + struct domain *f = page_get_owner(pg); + + BUG_ON(f == d); + get_domain(f); + } + break; + case PFN_TYPE_RMA: + case PFN_TYPE_LOGICAL: + break; + default: + BUG(); + } return; } @@ -480,9 +500,21 @@ static void h_remove(struct cpu_user_reg /* XXX - I'm very skeptical of doing ANYTHING if not bits.v */ /* XXX - I think the spec should be questioned in this case (MFM) */ - if (pte->bits.v == 0) { + if (lpte.bits.v == 0) { printk("%s: removing invalid entry\n", __func__); } + + if (lpte.bits.v) { + ulong mfn = lpte.bits.rpn; + if (!cpu_io_mfn(mfn)) { + struct page_info *pg = mfn_to_page(mfn); + struct domain *f = page_get_owner(pg); + + if (f != d) + put_domain(f); + } + } + asm volatile("eieio; std %1, 0(%0); ptesync" : : "b" (pte), "r" (0) diff -r 2e6c10dc7c0b -r 2ba5452795d2 xen/arch/powerpc/usercopy.c --- a/xen/arch/powerpc/usercopy.c Tue Sep 12 10:53:46 2006 -0400 +++ b/xen/arch/powerpc/usercopy.c Tue Sep 12 11:01:04 2006 -0400 @@ -57,10 +57,10 @@ static unsigned long paddr_to_maddr(unsi case PFN_TYPE_LOGICAL: break; - case PFN_TYPE_REMOTE: + case PFN_TYPE_FOREIGN: /* I don't think this should ever happen, but I suppose it * could be possible */ - printk("%s: Dom:%d paddr: 0x%lx type: REMOTE\n", + printk("%s: Dom:%d paddr: 0x%lx type: FOREIGN\n", __func__, d->domain_id, paddr); WARN(); break; diff -r 2e6c10dc7c0b -r 2ba5452795d2 xen/include/asm-powerpc/mm.h --- a/xen/include/asm-powerpc/mm.h Tue Sep 12 10:53:46 2006 -0400 +++ b/xen/include/asm-powerpc/mm.h Tue Sep 12 11:01:04 2006 -0400 @@ -154,7 +154,7 @@ static inline void put_page(struct page_ while ( unlikely((y = cmpxchg(&page->count_info, x, nx)) != x) ); if ( unlikely((nx & PGC_count_mask) == 0) ) { - panic("about to free page\n"); + panic("about to free page: 0x%lx\n", page_to_mfn(page)); free_domheap_page(page); } } @@ -239,7 +239,7 @@ extern int update_grant_va_mapping(unsig #define PFN_TYPE_RMA 1 #define PFN_TYPE_LOGICAL 2 #define PFN_TYPE_IO 3 -#define PFN_TYPE_REMOTE 4 +#define PFN_TYPE_FOREIGN 4 extern ulong pfn2mfn(struct domain *d, ulong pfn, int *type); @@ -259,6 +259,7 @@ static inline unsigned long gmfn_to_mfn( #define mfn_to_gmfn(_d, mfn) (mfn) extern int allocate_rma(struct domain *d, unsigned int order_pages); +extern void free_rma(struct domain *d); extern uint allocate_extents(struct domain *d, uint nrpages, uint rma_nrpages); extern void free_extents(struct domain *d); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |