[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC PATCH 14/16]: PVH xen: add xenmem_add_foreign_to_pmap()
In this patch, I add a new function, xenmem_add_foreign_to_pmap(), to map pages from foreign gue st into current dom0 for domU creation. Also, some minor grant changes for PVH. Signed-off-by: Mukesh Rathor <mukesh.rathor@xxxxxxxxxx> diff -r 2c894340b16f -r 47d2e652bd4d xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Fri Jan 11 16:43:02 2013 -0800 +++ b/xen/arch/x86/mm.c Fri Jan 11 16:45:36 2013 -0800 @@ -2608,7 +2608,7 @@ static struct domain *get_pg_owner(domid goto out; } - if ( unlikely(paging_mode_translate(curr)) ) + if ( !is_pvh_domain(curr) && unlikely(paging_mode_translate(curr)) ) { MEM_LOG("Cannot mix foreign mappings with translated domains"); goto out; @@ -3734,16 +3734,34 @@ static int replace_grant_p2m_mapping( old_mfn = get_gfn(d, gfn, &type); if ( !p2m_is_grant(type) || mfn_x(old_mfn) != frame ) { - put_gfn(d, gfn); gdprintk(XENLOG_WARNING, - "replace_grant_p2m_mapping: old mapping invalid (type %d, mfn %lx, frame %lx)\n", + "replace_grant_p2m_mapping: old mapping invalid " + "(type %d, mfn %lx, frame %lx)\n", type, mfn_x(old_mfn), frame); - return GNTST_general_error; + goto out_err; } guest_physmap_remove_page(d, gfn, frame, PAGE_ORDER_4K); + /* PVH: Because we free the existing mfn in XENMEM_add_to_physmap during + * grant map, we undo that here so the guest P2M (EPT/NPT) is consistent */ + if ( is_pvh_domain(d) ) { + struct page_info *page = alloc_domheap_page(d, 0); + + if ( page == NULL ) { + gdprintk(XENLOG_ERR, "Unable to alloc domheap page\n"); + goto out_err; + } + if ( guest_physmap_add_page(d, gfn, page_to_mfn(page), 0) != 0 ) { + gdprintk(XENLOG_ERR, "Unable to add mfn to replace grant\n"); + goto out_err; + } + } put_gfn(d, gfn); return GNTST_okay; + +out_err: + put_gfn(d, gfn); + return GNTST_general_error; } int replace_grant_host_mapping( @@ -4143,7 +4161,7 @@ long do_update_descriptor(u64 pa, u64 de page = get_page_from_gfn(dom, gmfn, NULL, P2M_ALLOC); if ( (((unsigned int)pa % sizeof(struct desc_struct)) != 0) || !page || - !check_descriptor(dom, &d) ) + (!is_pvh_domain(dom) && !check_descriptor(dom, &d)) ) { if ( page ) put_page(page); @@ -4217,7 +4235,81 @@ static int handle_iomem_range(unsigned l return 0; } -static int xenmem_add_to_physmap_once( +/* add frames from foreign domain to current domain's physmap. Similar to + * XENMAPSPACE_gmfn but the frame is foreign being mapped into current, + * and is not removed from foreign domain. + * Usage: libxl on pvh dom0 creating a guest and doing privcmd_ioctl_mmap + * Returns: 0 ==> success + */ +static long noinline xenmem_add_foreign_to_pmap( domid_t foreign_domid, + unsigned long fgmfn, unsigned long gpfn) +{ + unsigned long rc=0, prev_mfn, mfn = 0; + struct domain *fdom, *currd = current->domain; + p2m_type_t p2mt, p2mt_prev; + + if ( (fdom = get_pg_owner(foreign_domid)) == NULL ) { + return -EPERM; + } + + mfn = mfn_x(get_gfn_query_unlocked(fdom, fgmfn, &p2mt)); + + /* qemu, running on PVH dom0, mapping hvm domain's io pages during domain + * creation, doesn't have mfns in the HAP table */ + if ( !mfn_valid(mfn) && p2m_is_mmio(p2mt) ) { + + if (!is_hvm_domain(fdom)) { + printk("mmio type for non-hvm domain. fd:%d fgmfn:%lx gpfn:%lx\n", + foreign_domid, fgmfn, gpfn); + return -EINVAL; + } + mfn = fgmfn; /* map 1 to 1 */ + } + + if ( !p2m_is_valid(p2mt) ) { + put_pg_owner(fdom); + return -EINVAL; + } + + if ( !p2m_is_mmio(p2mt) && !get_page_from_pagenr(mfn, fdom) ) { + put_pg_owner(fdom); + return -EINVAL; + } + + /* Remove previously mapped page if it was present. */ + prev_mfn = mfn_x(get_gfn_query_unlocked(currd, gpfn, &p2mt_prev)); + if ( mfn_valid(prev_mfn) ) + { + if ( is_xen_heap_mfn(prev_mfn) ) + /* Xen heap frames are simply unhooked from this phys slot */ + guest_physmap_remove_page(currd, gpfn, prev_mfn, 0); + else + /* Normal domain memory is freed, to avoid leaking memory. */ + guest_remove_page(currd, gpfn); + } + + /* Map at new location. Can't use guest_physmap_add_page() because it + * will update the m2p table which will result in mfn --> gpfn of dom0 + * and not gpfn of domU. */ + if ( p2m_is_mmio(p2mt) ) { + if ( set_mmio_p2m_entry(currd, gpfn, _mfn(mfn)) == 0 ) { + printk("set_mmio_p2m failed. gpfn:%lx mfn:%lx fgmfn:%lx\n", + gpfn, mfn, fgmfn); + rc = -EINVAL; + } + + } else if ( set_foreign_p2m_entry(currd, gpfn, _mfn(mfn)) == 0 ) { + + printk("guest_physmap_add_page failed1. gpfn:%lx mfn:%lx fgmfn:%lx\n", + gpfn, mfn, fgmfn); + put_page(mfn_to_page(mfn)); + rc = -EINVAL; + } + put_pg_owner(fdom); + return rc; +} + +static int noinline xenmem_add_to_physmap_once( struct domain *d, uint16_t xatp_space, domid_t foreign_domid, unsigned long xatp_idx, unsigned long xatp_gpfn) { @@ -4278,6 +4370,13 @@ static int xenmem_add_to_physmap_once( page = mfn_to_page(mfn); break; } + + case XENMAPSPACE_gmfn_foreign: + { + rc = xenmem_add_foreign_to_pmap(foreign_domid, xatp_idx, xatp_gpfn); + return rc; + } + default: break; } diff -r 2c894340b16f -r 47d2e652bd4d xen/common/grant_table.c --- a/xen/common/grant_table.c Fri Jan 11 16:43:02 2013 -0800 +++ b/xen/common/grant_table.c Fri Jan 11 16:45:36 2013 -0800 @@ -529,7 +529,7 @@ static void mapcount( * addr is _either_ a host virtual address, or the address of the pte to * update, as indicated by the GNTMAP_contains_pte flag. */ -static void +static noinline void __gnttab_map_grant_ref( struct gnttab_map_grant_ref *op) { @@ -745,7 +745,7 @@ __gnttab_map_grant_ref( double_gt_lock(lgt, rgt); - if ( !is_hvm_domain(ld) && need_iommu(ld) ) + if ( !is_hvm_or_pvh_domain(ld) && need_iommu(ld) ) { unsigned int wrc, rdc; int err = 0; @@ -956,7 +956,7 @@ __gnttab_unmap_common( act->pin -= GNTPIN_hstw_inc; } - if ( !is_hvm_domain(ld) && need_iommu(ld) ) + if ( !is_hvm_or_pvh_domain(ld) && need_iommu(ld) ) { unsigned int wrc, rdc; int err = 0; _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |