diff -r e40591366a0f xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Mon Nov 12 09:53:14 2007 +0000 +++ b/xen/arch/x86/mm.c Tue Nov 13 16:22:08 2007 +0000 @@ -849,12 +849,14 @@ void put_page_from_l1e(l1_pgentry_t l1e, void put_page_from_l1e(l1_pgentry_t l1e, struct domain *d) { unsigned long pfn = l1e_get_pfn(l1e); - struct page_info *page = mfn_to_page(pfn); + struct page_info *page; struct domain *e; struct vcpu *v; if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) || !mfn_valid(pfn) ) return; + + page = mfn_to_page(pfn); e = page_get_owner(page); @@ -2772,6 +2774,8 @@ int create_grant_host_mapping( l1e_add_flags(pte,_PAGE_USER); if ( !(flags & GNTMAP_readonly) ) l1e_add_flags(pte,_PAGE_RW); + if ( (flags & GNTMAP_nocache) ) + l1e_add_flags(pte,_PAGE_PCD); if ( flags & GNTMAP_contains_pte ) return create_grant_pte_mapping(addr, pte, current); diff -r e40591366a0f xen/common/grant_table.c --- a/xen/common/grant_table.c Mon Nov 12 09:53:14 2007 +0000 +++ b/xen/common/grant_table.c Tue Nov 13 15:50:01 2007 +0000 @@ -198,7 +198,6 @@ __gnttab_map_grant_ref( int handle; unsigned long frame = 0; int rc = GNTST_okay; - int is_iomem = 0; struct active_grant_entry *act; struct grant_mapping *mt; grant_entry_t *sha; @@ -329,24 +328,38 @@ __gnttab_map_grant_ref( spin_unlock(&rd->grant_table->lock); - if ( op->flags & GNTMAP_host_map ) - { - /* Could be an iomem page for setting up permission */ - if ( is_iomem_page(frame) ) - { - is_iomem = 1; - if ( iomem_permit_access(ld, frame, frame) ) - { - gdprintk(XENLOG_WARNING, - "Could not permit access to grant frame " - "%lx as iomem\n", frame); + /* Could be an iomem page for remapping */ + if ( rd->domain_id == 0 && + is_iomem_page(frame) && + iomem_access_permitted(rd, frame, frame) ) + { + if ( op->flags & GNTMAP_host_map ) + { + /* Reference counting for in-range I/O pages. */ + if ( mfn_valid(frame) && + !((op->flags & GNTMAP_readonly) ? + get_page(mfn_to_page(frame), rd) : + get_page_and_type(mfn_to_page(frame), rd, + PGT_writable_page))) { + if ( !rd->is_dying ) + gdprintk(XENLOG_WARNING, + "Could not pin grant frame %lx\n", frame); rc = GNTST_general_error; goto undo_out; } - } - } - - if ( !is_iomem ) + + rc = create_grant_host_mapping(op->host_addr, frame, op->flags); + if ( rc != GNTST_okay ) + { + if ( mfn_valid(frame) && + !(op->flags & GNTMAP_readonly) ) + put_page_type(mfn_to_page(frame)); + put_page(mfn_to_page(frame)); + goto undo_out; + } + } + } + else { if ( unlikely(!mfn_valid(frame)) || unlikely(!((op->flags & GNTMAP_readonly) ? @@ -527,12 +540,6 @@ __gnttab_unmap_common( op->flags)) < 0 ) goto unmap_out; } - else if ( is_iomem_page(op->frame) && - iomem_access_permitted(ld, op->frame, op->frame) ) - { - if ( (rc = iomem_deny_access(ld, op->frame, op->frame)) < 0 ) - goto unmap_out; - } ASSERT(act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask)); op->map->flags &= ~GNTMAP_host_map; @@ -607,10 +614,25 @@ __gnttab_unmap_common_complete(struct gn goto unmap_out; } - if ( op->flags & GNTMAP_readonly ) - put_page(mfn_to_page(op->frame)); - else - put_page_and_type(mfn_to_page(op->frame)); + if ( rd->domain_id == 0 && + is_iomem_page(op->frame) ) + { + /* Only do refcounting on in-range mfns */ + if ( mfn_valid(op->frame) ) + { + if ( op->flags & GNTMAP_readonly ) + put_page(mfn_to_page(op->frame)); + else + put_page_and_type(mfn_to_page(op->frame)); + } + } + else + { + if ( op->flags & GNTMAP_readonly ) + put_page(mfn_to_page(op->frame)); + else + put_page_and_type(mfn_to_page(op->frame)); + } } if ( (op->map->flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0 ) @@ -1592,7 +1614,6 @@ gnttab_release_mappings( struct domain *rd; struct active_grant_entry *act; struct grant_entry *sha; - int rc; BUG_ON(!d->is_dying); @@ -1651,9 +1672,14 @@ gnttab_release_mappings( BUG_ON(!(act->pin & GNTPIN_hstw_mask)); act->pin -= GNTPIN_hstw_inc; - if ( is_iomem_page(act->frame) && - iomem_access_permitted(rd, act->frame, act->frame) ) - rc = iomem_deny_access(rd, act->frame, act->frame); + if ( rd->domain_id == 0 && + is_iomem_page(act->frame) ) + { + /* Only do reference count on in-range mfns */ + if( mfn_valid(act->frame) ) + gnttab_release_put_page_and_type + (mfn_to_page(act->frame)); + } else gnttab_release_put_page_and_type(mfn_to_page(act->frame)); } diff -r e40591366a0f xen/include/public/grant_table.h --- a/xen/include/public/grant_table.h Mon Nov 12 09:53:14 2007 +0000 +++ b/xen/include/public/grant_table.h Tue Nov 13 11:26:26 2007 +0000 @@ -380,6 +380,9 @@ DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_and #define _GNTMAP_contains_pte (4) #define GNTMAP_contains_pte (1<<_GNTMAP_contains_pte) +#define _GNTMAP_nocache (5) +#define GNTMAP_nocache (1<<_GNTMAP_nocache) + /* * Values for error status returns. All errors are -ve. */