WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] Move arch-specific portions of grant-table implementatio

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] Move arch-specific portions of grant-table implementation
From: Xen patchbot -unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 23 Nov 2005 15:16:08 +0000
Delivery-date: Wed, 23 Nov 2005 15:16:29 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 944cf29d126d9cdd84f033da9c0f8b1c843b1361
# Parent  6d9ea03c1baa19dfefbbb6ccc7ab43cff2383206
Move arch-specific portions of grant-table implementation
out of common code. Ready for use by ia64.

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r 6d9ea03c1baa -r 944cf29d126d xen/arch/ia64/Makefile
--- a/xen/arch/ia64/Makefile    Wed Nov 23 12:38:34 2005
+++ b/xen/arch/ia64/Makefile    Wed Nov 23 12:50:14 2005
@@ -10,7 +10,7 @@
        extable.o linuxextable.o sort.o xenirq.o xentime.o \
        regionreg.o entry.o unaligned.o privop.o vcpu.o \
        irq_ia64.o irq_lsapic.o vhpt.o xenasm.o hyperprivop.o dom_fw.o \
-       grant_table.o sn_console.o # ia64_ksyms.o 
+       sn_console.o # ia64_ksyms.o 
 
 OBJS += vmx_init.o vmx_virt.o vmx_vcpu.o vmx_process.o vmx_vsa.o vmx_ivt.o\
        vmx_phy_mode.o vmx_utility.o vmx_interrupt.o vmx_entry.o vmmu.o \
diff -r 6d9ea03c1baa -r 944cf29d126d xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Wed Nov 23 12:38:34 2005
+++ b/xen/arch/x86/mm.c Wed Nov 23 12:50:14 2005
@@ -2306,7 +2306,7 @@
 }
 
 
-int update_grant_pte_mapping(
+static int create_grant_pte_mapping(
     unsigned long pte_addr, l1_pgentry_t _nl1e, struct vcpu *v)
 {
     int rc = GNTST_okay;
@@ -2368,7 +2368,7 @@
     return rc;
 }
 
-int clear_grant_pte_mapping(
+static int destroy_grant_pte_mapping(
     unsigned long addr, unsigned long frame, struct domain *d)
 {
     int rc = GNTST_okay;
@@ -2445,7 +2445,7 @@
 }
 
 
-int update_grant_va_mapping(
+static int create_grant_va_mapping(
     unsigned long va, l1_pgentry_t _nl1e, struct vcpu *v)
 {
     l1_pgentry_t *pl1e, ol1e;
@@ -2475,7 +2475,8 @@
     return GNTST_okay;
 }
 
-int clear_grant_va_mapping(unsigned long addr, unsigned long frame)
+static int destroy_grant_va_mapping(
+    unsigned long addr, unsigned long frame)
 {
     l1_pgentry_t *pl1e, ol1e;
     
@@ -2508,6 +2509,74 @@
     return 0;
 }
 
+int create_grant_host_mapping(
+    unsigned long addr, unsigned long frame, unsigned int flags)
+{
+    l1_pgentry_t pte = l1e_from_pfn(frame, GRANT_PTE_FLAGS);
+        
+    if ( (flags & GNTMAP_application_map) )
+        l1e_add_flags(pte,_PAGE_USER);
+    if ( !(flags & GNTMAP_readonly) )
+        l1e_add_flags(pte,_PAGE_RW);
+
+    if ( flags & GNTMAP_contains_pte )
+        return create_grant_pte_mapping(addr, pte, current);
+    return create_grant_va_mapping(addr, pte, current);
+}
+
+int destroy_grant_host_mapping(
+    unsigned long addr, unsigned long frame, unsigned int flags)
+{
+    if ( flags & GNTMAP_contains_pte )
+        return destroy_grant_pte_mapping(addr, frame, current->domain);
+    return destroy_grant_va_mapping(addr, frame);
+}
+
+int steal_page_for_grant_transfer(
+    struct domain *d, struct pfn_info *page)
+{
+    u32 _d, _nd, x, y;
+
+    spin_lock(&d->page_alloc_lock);
+
+    /*
+     * The tricky bit: atomically release ownership while there is just one 
+     * benign reference to the page (PGC_allocated). If that reference 
+     * disappears then the deallocation routine will safely spin.
+     */
+    _d  = pickle_domptr(d);
+    _nd = page->u.inuse._domain;
+    y   = page->count_info;
+    do {
+        x = y;
+        if (unlikely((x & (PGC_count_mask|PGC_allocated)) !=
+                     (1 | PGC_allocated)) || unlikely(_nd != _d)) { 
+            DPRINTK("gnttab_transfer: Bad page %p: ed=%p(%u), sd=%p,"
+                    " caf=%08x, taf=%" PRtype_info "\n", 
+                    (void *) page_to_pfn(page),
+                    d, d->domain_id, unpickle_domptr(_nd), x, 
+                    page->u.inuse.type_info);
+            spin_unlock(&d->page_alloc_lock);
+            return -1;
+        }
+        __asm__ __volatile__(
+            LOCK_PREFIX "cmpxchg8b %2"
+            : "=d" (_nd), "=a" (y),
+            "=m" (*(volatile u64 *)(&page->count_info))
+            : "0" (_d), "1" (x), "c" (NULL), "b" (x) );
+    } while (unlikely(_nd != _d) || unlikely(y != x));
+
+    /*
+     * Unlink from 'd'. At least one reference remains (now anonymous), so 
+     * noone else is spinning to try to delete this page from 'd'.
+     */
+    d->tot_pages--;
+    list_del(&page->list);
+
+    spin_unlock(&d->page_alloc_lock);
+
+    return 0;
+}
 
 int do_update_va_mapping(unsigned long va, u64 val64,
                          unsigned long flags)
diff -r 6d9ea03c1baa -r 944cf29d126d xen/common/Makefile
--- a/xen/common/Makefile       Wed Nov 23 12:38:34 2005
+++ b/xen/common/Makefile       Wed Nov 23 12:50:14 2005
@@ -1,9 +1,5 @@
 
 include $(BASEDIR)/Rules.mk
-
-ifeq ($(TARGET_ARCH),ia64)
-OBJS := $(subst grant_table.o,,$(OBJS))
-endif
 
 ifneq ($(perfc),y)
 OBJS := $(subst perfc.o,,$(OBJS))
diff -r 6d9ea03c1baa -r 944cf29d126d xen/common/grant_table.c
--- a/xen/common/grant_table.c  Wed Nov 23 12:38:34 2005
+++ b/xen/common/grant_table.c  Wed Nov 23 12:50:14 2005
@@ -330,20 +330,7 @@
 
     if ( dev_hst_ro_flags & GNTMAP_host_map )
     {
-        /* Write update into the pagetable. */
-        l1_pgentry_t pte;
-        pte = l1e_from_pfn(frame, GRANT_PTE_FLAGS);
-        
-        if ( (dev_hst_ro_flags & GNTMAP_application_map) )
-            l1e_add_flags(pte,_PAGE_USER);
-        if ( !(dev_hst_ro_flags & GNTMAP_readonly) )
-            l1e_add_flags(pte,_PAGE_RW);
-
-        if ( dev_hst_ro_flags & GNTMAP_contains_pte )
-            rc = update_grant_pte_mapping(addr, pte, led);
-        else
-            rc = update_grant_va_mapping(addr, pte, led);
-
+        rc = create_grant_host_mapping(addr, frame, dev_hst_ro_flags);
         if ( rc < 0 )
         {
             /* Failure: undo and abort. */
@@ -488,16 +475,8 @@
          (flags & GNTMAP_host_map) &&
          ((act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask)) > 0))
     {
-        if ( flags & GNTMAP_contains_pte )
-        {
-            if ( (rc = clear_grant_pte_mapping(addr, frame, ld)) < 0 )
-                goto unmap_out;
-        }
-        else
-        {
-            if ( (rc = clear_grant_va_mapping(addr, frame)) < 0 )
-                goto unmap_out;
-        }
+        if ( (rc = destroy_grant_host_mapping(addr, frame, flags)) < 0 )
+            goto unmap_out;
 
         map->ref_and_flags &= ~GNTMAP_host_map;
 
@@ -512,9 +491,8 @@
     }
 
     /* If just unmapped a writable mapping, mark as dirtied */
-    if ( unlikely(shadow_mode_log_dirty(rd)) &&
-         !(flags & GNTMAP_readonly) )
-         mark_dirty(rd, frame);
+    if ( !(flags & GNTMAP_readonly) )
+         gnttab_log_dirty(rd, frame);
 
     /* If the last writable mapping has been removed, put_page_type */
     if ( ((act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0) &&
@@ -599,9 +577,8 @@
         ASSERT(d->grant_table != NULL);
         (void)put_user(GNTST_okay, &uop->status);
         for ( i = 0; i < op.nr_frames; i++ )
-            (void)put_user(
-                (virt_to_phys(d->grant_table->shared) >> PAGE_SHIFT) + i,
-                &uop->frame_list[i]);
+            (void)put_user(gnttab_shared_mfn(d, d->grant_table, i),
+                           &uop->frame_list[i]);
     }
 
     put_domain(d);
@@ -698,7 +675,6 @@
     struct domain *d = current->domain;
     struct domain *e;
     struct pfn_info *page;
-    u32 _d, _nd, x, y;
     int i;
     grant_entry_t *sha;
     gnttab_transfer_t gop;
@@ -723,46 +699,11 @@
             continue;
         }
 
-        spin_lock(&d->page_alloc_lock);
-
-        /*
-         * The tricky bit: atomically release ownership while
-         * there is just one benign reference to the page
-         * (PGC_allocated). If that reference disappears then the
-         * deallocation routine will safely spin.
-         */
-        _d  = pickle_domptr(d);
-        _nd = page->u.inuse._domain;
-        y   = page->count_info;
-        do {
-            x = y;
-            if (unlikely((x & (PGC_count_mask|PGC_allocated)) !=
-                         (1 | PGC_allocated)) || unlikely(_nd != _d)) { 
-                DPRINTK("gnttab_transfer: Bad page %p: ed=%p(%u), sd=%p,"
-                       " caf=%08x, taf=%" PRtype_info "\n", 
-                       (void *) page_to_pfn(page),
-                        d, d->domain_id, unpickle_domptr(_nd), x, 
-                        page->u.inuse.type_info);
-                spin_unlock(&d->page_alloc_lock);
-                (void)__put_user(GNTST_bad_page, &uop[i].status);
-                continue;
-            }
-            __asm__ __volatile__(
-                LOCK_PREFIX "cmpxchg8b %2"
-                : "=d" (_nd), "=a" (y),
-                "=m" (*(volatile u64 *)(&page->count_info))
-                : "0" (_d), "1" (x), "c" (NULL), "b" (x) );
-        } while (unlikely(_nd != _d) || unlikely(y != x));
-
-        /*
-         * Unlink from 'd'. At least one reference remains (now
-         * anonymous), so noone else is spinning to try to delete
-         * this page from 'd'.
-         */
-        d->tot_pages--;
-        list_del(&page->list);
-
-        spin_unlock(&d->page_alloc_lock);
+        if ( steal_page_for_grant_transfer(d, page) < 0 )
+        {
+            (void)__put_user(GNTST_bad_page, &uop[i].status);
+            continue;
+        }
 
         /* Find the target domain. */
         if ( unlikely((e = find_domain_by_id(gop.domid)) == NULL) )
@@ -991,14 +932,7 @@
     memset(t->shared, 0, NR_GRANT_FRAMES * PAGE_SIZE);
 
     for ( i = 0; i < NR_GRANT_FRAMES; i++ )
-    {
-        SHARE_PFN_WITH_DOMAIN(
-            virt_to_page((char *)t->shared + (i * PAGE_SIZE)),
-            d);
-        set_pfn_from_mfn(
-            (virt_to_phys(t->shared) >> PAGE_SHIFT) + i,
-            INVALID_M2P_ENTRY);
-    }
+        gnttab_create_shared_mfn(d, t, i);
 
     /* Okay, install the structure. */
     wmb(); /* avoid races with lock-free access to d->grant_table */
diff -r 6d9ea03c1baa -r 944cf29d126d xen/include/asm-x86/mm.h
--- a/xen/include/asm-x86/mm.h  Wed Nov 23 12:38:34 2005
+++ b/xen/include/asm-x86/mm.h  Wed Nov 23 12:50:14 2005
@@ -381,16 +381,4 @@
 
 extern int __sync_lazy_execstate(void);
 
-/*
- * Caller must own d's BIGLOCK, is responsible for flushing the TLB, and must 
- * hold a reference to the page.
- */
-int update_grant_va_mapping(
-    unsigned long va, l1_pgentry_t _nl1e, struct vcpu *v);
-int update_grant_pte_mapping(
-    unsigned long pte_addr, l1_pgentry_t _nl1e, struct vcpu *v);
-int clear_grant_va_mapping(unsigned long addr, unsigned long frame);
-int clear_grant_pte_mapping(
-    unsigned long addr, unsigned long frame, struct domain *d);
-
 #endif /* __ASM_X86_MM_H__ */
diff -r 6d9ea03c1baa -r 944cf29d126d xen/include/xen/grant_table.h
--- a/xen/include/xen/grant_table.h     Wed Nov 23 12:38:34 2005
+++ b/xen/include/xen/grant_table.h     Wed Nov 23 12:50:14 2005
@@ -4,7 +4,7 @@
  * Mechanism for granting foreign access to page frames, and receiving
  * page-ownership transfers.
  * 
- * Copyright (c) 2004 K A Fraser
+ * Copyright (c) 2004-2005 K A Fraser
  * 
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,11 +21,12 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifndef __XEN_GRANT_H__
-#define __XEN_GRANT_H__
+#ifndef __XEN_GRANT_TABLE_H__
+#define __XEN_GRANT_TABLE_H__
 
 #include <xen/config.h>
 #include <public/grant_table.h>
+#include <asm/grant_table.h>
 
 /* Active grant entry - used for shadowing GTF_permit_access grants. */
 typedef struct {
@@ -51,7 +52,6 @@
 #define GNTPIN_devr_inc      (1 << GNTPIN_devr_shift)
 #define GNTPIN_devr_mask     (0xFFU << GNTPIN_devr_shift)
 
-#define ORDER_GRANT_FRAMES   2
 #define NR_GRANT_FRAMES      (1U << ORDER_GRANT_FRAMES)
 #define NR_GRANT_ENTRIES     \
     ((NR_GRANT_FRAMES << PAGE_SHIFT) / sizeof(grant_entry_t))
@@ -107,4 +107,4 @@
 gnttab_release_mappings(
     struct domain *d);
 
-#endif /* __XEN_GRANT_H__ */
+#endif /* __XEN_GRANT_TABLE_H__ */
diff -r 6d9ea03c1baa -r 944cf29d126d xen/include/asm-ia64/grant_table.h
--- /dev/null   Wed Nov 23 12:38:34 2005
+++ b/xen/include/asm-ia64/grant_table.h        Wed Nov 23 12:50:14 2005
@@ -0,0 +1,26 @@
+/******************************************************************************
+ * include/asm-ia64/grant_table.h
+ */
+
+#ifndef __ASM_GRANT_TABLE_H__
+#define __ASM_GRANT_TABLE_H__
+
+#define ORDER_GRANT_FRAMES 0
+
+#define create_grant_host_mapping(a, f, fl)  0
+#define destroy_grant_host_mapping(a, f, fl) 0
+
+#define steal_page_for_grant_transfer(d, p)  0
+
+#define gnttab_create_shared_mfn(d, t, i) ((void)0)
+
+#define gnttab_shared_mfn(d, t, i)                                      \
+    ( ((d) == dom0) ?                                                   \
+      ((virt_to_phys((t)shared) >> PAGE_SHIFT) + (i)) :                 \
+      (map_domain_page((d), 1UL<<40, virt_to_phys((t)->shared)),        \
+       1UL << (40 - PAGE_SHIFT))                                        \
+    )
+
+#define gnttab_log_dirty(d, f) ((void)0)
+
+#endif /* __ASM_GRANT_TABLE_H__ */
diff -r 6d9ea03c1baa -r 944cf29d126d xen/include/asm-x86/grant_table.h
--- /dev/null   Wed Nov 23 12:38:34 2005
+++ b/xen/include/asm-x86/grant_table.h Wed Nov 23 12:50:14 2005
@@ -0,0 +1,42 @@
+/******************************************************************************
+ * include/asm-x86/grant_table.h
+ * 
+ * Copyright (c) 2004-2005 K A Fraser
+ */
+
+#ifndef __ASM_GRANT_TABLE_H__
+#define __ASM_GRANT_TABLE_H__
+
+#define ORDER_GRANT_FRAMES 2
+
+/*
+ * Caller must own caller's BIGLOCK, is responsible for flushing the TLB, and
+ * must hold a reference to the page.
+ */
+int create_grant_host_mapping(
+    unsigned long addr, unsigned long frame, unsigned int flags);
+int destroy_grant_host_mapping(
+    unsigned long addr, unsigned long frame, unsigned int flags);
+
+int steal_page_for_grant_transfer(
+    struct domain *d, struct pfn_info *page);
+
+#define gnttab_create_shared_mfn(d, t, i)                                \
+    do {                                                                 \
+        SHARE_PFN_WITH_DOMAIN(                                           \
+            virt_to_page((char *)(t)->shared + ((i) * PAGE_SIZE)), (d)); \
+        set_pfn_from_mfn(                                                \
+            (virt_to_phys((t)->shared) >> PAGE_SHIFT) + (i),             \
+            INVALID_M2P_ENTRY);                                          \
+    } while ( 0 )
+
+#define gnttab_shared_mfn(d, t, i)                      \
+    ((virt_to_phys((t)->shared) >> PAGE_SHIFT) + (i))
+
+#define gnttab_log_dirty(d, f)                          \
+    do {                                                \
+        if ( unlikely(shadow_mode_log_dirty((d))) )     \
+            mark_dirty((d), (f));                       \
+    } while ( 0 )
+
+#endif /* __ASM_GRANT_TABLE_H__ */
diff -r 6d9ea03c1baa -r 944cf29d126d xen/arch/ia64/xen/grant_table.c
--- a/xen/arch/ia64/xen/grant_table.c   Wed Nov 23 12:38:34 2005
+++ /dev/null   Wed Nov 23 12:50:14 2005
@@ -1,1354 +0,0 @@
-// temporarily in arch/ia64 until can merge into common/grant_table.c
-/******************************************************************************
- * common/grant_table.c
- * 
- * Mechanism for granting foreign access to page frames, and receiving
- * page-ownership transfers.
- * 
- * Copyright (c) 2005 Christopher Clark
- * Copyright (c) 2004 K A Fraser
- * Copyright (c) 2005 Andrew Warfield
- * Modifications by Geoffrey Lefebvre are (c) Intel Research Cambridge
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#define GRANT_DEBUG 0
-#define GRANT_DEBUG_VERBOSE 0
-
-#include <xen/config.h>
-#include <xen/lib.h>
-#include <xen/sched.h>
-#include <xen/shadow.h>
-#include <xen/mm.h>
-#ifdef __ia64__
-#define __addr_ok(a) 1 // FIXME-ia64: a variant of access_ok??
-// FIXME-ia64: these belong in an asm/grant_table.h... PAGE_SIZE different
-#undef ORDER_GRANT_FRAMES
-//#undef NUM_GRANT_FRAMES
-#define ORDER_GRANT_FRAMES 0
-//#define NUM_GRANT_FRAMES  (1U << ORDER_GRANT_FRAMES)
-#endif
-#include <acm/acm_hooks.h>
-
-#if defined(CONFIG_X86_64)
-#define GRANT_PTE_FLAGS (_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
-#else
-#define GRANT_PTE_FLAGS (_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_DIRTY)
-#endif
-
-#define PIN_FAIL(_lbl, _rc, _f, _a...)   \
-    do {                           \
-        DPRINTK( _f, ## _a );      \
-        rc = (_rc);                \
-        goto _lbl;                 \
-    } while ( 0 )
-
-static inline int
-get_maptrack_handle(
-    grant_table_t *t)
-{
-    unsigned int h;
-    if ( unlikely((h = t->maptrack_head) == (t->maptrack_limit - 1)) )
-        return -1;
-    t->maptrack_head = t->maptrack[h].ref_and_flags >> MAPTRACK_REF_SHIFT;
-    t->map_count++;
-    return h;
-}
-
-static inline void
-put_maptrack_handle(
-    grant_table_t *t, int handle)
-{
-    t->maptrack[handle].ref_and_flags = t->maptrack_head << MAPTRACK_REF_SHIFT;
-    t->maptrack_head = handle;
-    t->map_count--;
-}
-
-static int
-__gnttab_activate_grant_ref(
-    struct domain   *mapping_d,          /* IN */
-    struct vcpu     *mapping_ed,
-    struct domain   *granting_d,
-    grant_ref_t      ref,
-    u16              dev_hst_ro_flags,
-    u64              addr,
-    unsigned long   *pframe )            /* OUT */
-{
-    domid_t               sdom;
-    u16                   sflags;
-    active_grant_entry_t *act;
-    grant_entry_t        *sha;
-    s16                   rc = 1;
-    unsigned long         frame = 0;
-    int                   retries = 0;
-
-    /*
-     * Objectives of this function:
-     * . Make the record ( granting_d, ref ) active, if not already.
-     * . Update shared grant entry of owner, indicating frame is mapped.
-     * . Increment the owner act->pin reference counts.
-     * . get_page on shared frame if new mapping.
-     * . get_page_type if this is first RW mapping of frame.
-     * . Add PTE to virtual address space of mapping_d, if necessary.
-     * Returns:
-     * .  -ve: error
-     * .    1: ok
-     * .    0: ok and TLB invalidate of host_addr needed.
-     *
-     * On success, *pframe contains mfn.
-     */
-
-    /*
-     * We bound the number of times we retry CMPXCHG on memory locations that
-     * we share with a guest OS. The reason is that the guest can modify that
-     * location at a higher rate than we can read-modify-CMPXCHG, so the guest
-     * could cause us to livelock. There are a few cases where it is valid for
-     * the guest to race our updates (e.g., to change the GTF_readonly flag),
-     * so we allow a few retries before failing.
-     */
-
-    act = &granting_d->grant_table->active[ref];
-    sha = &granting_d->grant_table->shared[ref];
-
-    spin_lock(&granting_d->grant_table->lock);
-
-    if ( act->pin == 0 )
-    {
-        /* CASE 1: Activating a previously inactive entry. */
-
-        sflags = sha->flags;
-        sdom   = sha->domid;
-
-        /* This loop attempts to set the access (reading/writing) flags
-         * in the grant table entry.  It tries a cmpxchg on the field
-         * up to five times, and then fails under the assumption that 
-         * the guest is misbehaving. */
-        for ( ; ; )
-        {
-            u32 scombo, prev_scombo, new_scombo;
-
-            if ( unlikely((sflags & GTF_type_mask) != GTF_permit_access) ||
-                 unlikely(sdom != mapping_d->domain_id) )
-                PIN_FAIL(unlock_out, GNTST_general_error,
-                         "Bad flags (%x) or dom (%d). (NB. expected dom %d)\n",
-                        sflags, sdom, mapping_d->domain_id);
-
-            /* Merge two 16-bit values into a 32-bit combined update. */
-            /* NB. Endianness! */
-            prev_scombo = scombo = ((u32)sdom << 16) | (u32)sflags;
-
-            new_scombo = scombo | GTF_reading;
-            if ( !(dev_hst_ro_flags & GNTMAP_readonly) )
-            {
-                new_scombo |= GTF_writing;
-                if ( unlikely(sflags & GTF_readonly) )
-                    PIN_FAIL(unlock_out, GNTST_general_error,
-                             "Attempt to write-pin a r/o grant entry.\n");
-            }
-
-            /* NB. prev_scombo is updated in place to seen value. */
-            if ( unlikely(cmpxchg_user((u32 *)&sha->flags,
-                                       prev_scombo,
-                                       new_scombo)) )
-                PIN_FAIL(unlock_out, GNTST_general_error,
-                         "Fault while modifying shared flags and domid.\n");
-
-            /* Did the combined update work (did we see what we expected?). */
-            if ( likely(prev_scombo == scombo) )
-                break;
-
-            if ( retries++ == 4 )
-                PIN_FAIL(unlock_out, GNTST_general_error,
-                         "Shared grant entry is unstable.\n");
-
-            /* Didn't see what we expected. Split out the seen flags & dom. */
-            /* NB. Endianness! */
-            sflags = (u16)prev_scombo;
-            sdom   = (u16)(prev_scombo >> 16);
-        }
-
-        /* rmb(); */ /* not on x86 */
-
-        frame = __gpfn_to_mfn_foreign(granting_d, sha->frame);
-
-#ifdef __ia64__
-// FIXME-ia64: any error checking need to be done here?
-#else
-        if ( unlikely(!pfn_valid(frame)) ||
-             unlikely(!((dev_hst_ro_flags & GNTMAP_readonly) ?
-                        get_page(&frame_table[frame], granting_d) :
-                        get_page_and_type(&frame_table[frame], granting_d,
-                                          PGT_writable_page))) )
-        {
-            clear_bit(_GTF_writing, &sha->flags);
-            clear_bit(_GTF_reading, &sha->flags);
-            PIN_FAIL(unlock_out, GNTST_general_error,
-                     "Could not pin the granted frame (%lx)!\n", frame);
-        }
-#endif 
-
-        if ( dev_hst_ro_flags & GNTMAP_device_map )
-            act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ?
-                GNTPIN_devr_inc : GNTPIN_devw_inc;
-        if ( dev_hst_ro_flags & GNTMAP_host_map )
-            act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ?
-                GNTPIN_hstr_inc : GNTPIN_hstw_inc;
-        act->domid = sdom;
-        act->frame = frame;
-    }
-    else 
-    {
-        /* CASE 2: Active modications to an already active entry. */
-
-        /*
-         * A cheesy check for possible pin-count overflow.
-         * A more accurate check cannot be done with a single comparison.
-         */
-        if ( (act->pin & 0x80808080U) != 0 )
-            PIN_FAIL(unlock_out, ENOSPC,
-                     "Risk of counter overflow %08x\n", act->pin);
-
-        frame = act->frame;
-
-        if ( !(dev_hst_ro_flags & GNTMAP_readonly) && 
-             !((sflags = sha->flags) & GTF_writing) )
-        {
-            for ( ; ; )
-            {
-                u16 prev_sflags;
-                
-                if ( unlikely(sflags & GTF_readonly) )
-                    PIN_FAIL(unlock_out, GNTST_general_error,
-                             "Attempt to write-pin a r/o grant entry.\n");
-
-                prev_sflags = sflags;
-
-                /* NB. prev_sflags is updated in place to seen value. */
-                if ( unlikely(cmpxchg_user(&sha->flags, prev_sflags, 
-                                           prev_sflags | GTF_writing)) )
-                    PIN_FAIL(unlock_out, GNTST_general_error,
-                         "Fault while modifying shared flags.\n");
-
-                if ( likely(prev_sflags == sflags) )
-                    break;
-
-                if ( retries++ == 4 )
-                    PIN_FAIL(unlock_out, GNTST_general_error,
-                             "Shared grant entry is unstable.\n");
-
-                sflags = prev_sflags;
-            }
-
-#ifdef __ia64__
-// FIXME-ia64: any error checking need to be done here?
-#else
-            if ( unlikely(!get_page_type(&frame_table[frame],
-                                         PGT_writable_page)) )
-            {
-                clear_bit(_GTF_writing, &sha->flags);
-                PIN_FAIL(unlock_out, GNTST_general_error,
-                         "Attempt to write-pin a unwritable page.\n");
-            }
-#endif
-        }
-
-        if ( dev_hst_ro_flags & GNTMAP_device_map )
-            act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ? 
-                GNTPIN_devr_inc : GNTPIN_devw_inc;
-
-        if ( dev_hst_ro_flags & GNTMAP_host_map )
-            act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ?
-                GNTPIN_hstr_inc : GNTPIN_hstw_inc;
-    }
-
-    /*
-     * At this point:
-     * act->pin updated to reference count mappings.
-     * sha->flags updated to indicate to granting domain mapping done.
-     * frame contains the mfn.
-     */
-
-    spin_unlock(&granting_d->grant_table->lock);
-
-#ifdef __ia64__
-// FIXME-ia64: any error checking need to be done here?
-#else
-    if ( (addr != 0) && (dev_hst_ro_flags & GNTMAP_host_map) )
-    {
-        /* Write update into the pagetable. */
-        l1_pgentry_t pte;
-        pte = l1e_from_pfn(frame, GRANT_PTE_FLAGS);
-        
-        if ( (dev_hst_ro_flags & GNTMAP_application_map) )
-            l1e_add_flags(pte,_PAGE_USER);
-        if ( !(dev_hst_ro_flags & GNTMAP_readonly) )
-            l1e_add_flags(pte,_PAGE_RW);
-
-        if ( dev_hst_ro_flags & GNTMAP_contains_pte )
-            rc = update_grant_pte_mapping(addr, pte, mapping_d, mapping_ed);
-        else
-            rc = update_grant_va_mapping(addr, pte, mapping_d, mapping_ed);
-
-        /* IMPORTANT: rc indicates the degree of TLB flush that is required.
-         * GNTST_flush_one (1) or GNTST_flush_all (2). This is done in the 
-         * outer gnttab_map_grant_ref. */
-        if ( rc < 0 )
-        {
-            /* Failure: undo and abort. */
-
-            spin_lock(&granting_d->grant_table->lock);
-
-            if ( dev_hst_ro_flags & GNTMAP_readonly )
-            {
-                act->pin -= GNTPIN_hstr_inc;
-            }
-            else
-            {
-                act->pin -= GNTPIN_hstw_inc;
-                if ( (act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) == 0 )
-                {
-                    clear_bit(_GTF_writing, &sha->flags);
-                    put_page_type(&frame_table[frame]);
-                }
-            }
-
-            if ( act->pin == 0 )
-            {
-                clear_bit(_GTF_reading, &sha->flags);
-                put_page(&frame_table[frame]);
-            }
-
-            spin_unlock(&granting_d->grant_table->lock);
-        }
-
-    }
-#endif
-
-    *pframe = frame;
-    return rc;
-
- unlock_out:
-    spin_unlock(&granting_d->grant_table->lock);
-    return rc;
-}
-
-/*
- * Returns 0 if TLB flush / invalidate required by caller.
- * va will indicate the address to be invalidated.
- * 
- * addr is _either_ a host virtual address, or the address of the pte to
- * update, as indicated by the GNTMAP_contains_pte flag.
- */
-static int
-__gnttab_map_grant_ref(
-    gnttab_map_grant_ref_t *uop,
-    unsigned long *va)
-{
-    domid_t        dom;
-    grant_ref_t    ref;
-    struct domain *ld, *rd;
-    struct vcpu   *led;
-    u16            dev_hst_ro_flags;
-    int            handle;
-    u64            addr;
-    unsigned long  frame = 0;
-    int            rc;
-
-    led = current;
-    ld = led->domain;
-
-    /* Bitwise-OR avoids short-circuiting which screws control flow. */
-    if ( unlikely(__get_user(dom, &uop->dom) |
-                  __get_user(ref, &uop->ref) |
-                  __get_user(addr, &uop->host_addr) |
-                  __get_user(dev_hst_ro_flags, &uop->flags)) )
-    {
-        DPRINTK("Fault while reading gnttab_map_grant_ref_t.\n");
-        return -EFAULT; /* don't set status */
-    }
-
-    if ( (dev_hst_ro_flags & GNTMAP_host_map) &&
-         ( (addr == 0) ||
-           (!(dev_hst_ro_flags & GNTMAP_contains_pte) && 
-            unlikely(!__addr_ok(addr))) ) )
-    {
-        DPRINTK("Bad virtual address (%"PRIx64") or flags (%"PRIx16").\n",
-                addr, dev_hst_ro_flags);
-        (void)__put_user(GNTST_bad_virt_addr, &uop->handle);
-        return GNTST_bad_gntref;
-    }
-
-    if ( unlikely(ref >= NR_GRANT_ENTRIES) ||
-         unlikely((dev_hst_ro_flags &
-                   (GNTMAP_device_map|GNTMAP_host_map)) == 0) )
-    {
-        DPRINTK("Bad ref (%d) or flags (%x).\n", ref, dev_hst_ro_flags);
-        (void)__put_user(GNTST_bad_gntref, &uop->handle);
-        return GNTST_bad_gntref;
-    }
-
-    if (acm_pre_grant_map_ref(dom)) {
-        (void)__put_user(GNTST_permission_denied, &uop->handle);
-        return GNTST_permission_denied;
-    }
-
-    if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
-         unlikely(ld == rd) )
-    {
-        if ( rd != NULL )
-            put_domain(rd);
-        DPRINTK("Could not find domain %d\n", dom);
-        (void)__put_user(GNTST_bad_domain, &uop->handle);
-        return GNTST_bad_domain;
-    }
-
-    /* Get a maptrack handle. */
-    if ( unlikely((handle = get_maptrack_handle(ld->grant_table)) == -1) )
-    {
-        int              i;
-        grant_mapping_t *new_mt;
-        grant_table_t   *lgt      = ld->grant_table;
-
-        if ( (lgt->maptrack_limit << 1) > MAPTRACK_MAX_ENTRIES )
-        {
-            put_domain(rd);
-            DPRINTK("Maptrack table is at maximum size.\n");
-            (void)__put_user(GNTST_no_device_space, &uop->handle);
-            return GNTST_no_device_space;
-        }
-
-        /* Grow the maptrack table. */
-        new_mt = alloc_xenheap_pages(lgt->maptrack_order + 1);
-        if ( new_mt == NULL )
-        {
-            put_domain(rd);
-            DPRINTK("No more map handles available.\n");
-            (void)__put_user(GNTST_no_device_space, &uop->handle);
-            return GNTST_no_device_space;
-        }
-
-        memcpy(new_mt, lgt->maptrack, PAGE_SIZE << lgt->maptrack_order);
-        for ( i = lgt->maptrack_limit; i < (lgt->maptrack_limit << 1); i++ )
-            new_mt[i].ref_and_flags = (i+1) << MAPTRACK_REF_SHIFT;
-
-        free_xenheap_pages(lgt->maptrack, lgt->maptrack_order);
-        lgt->maptrack          = new_mt;
-        lgt->maptrack_order   += 1;
-        lgt->maptrack_limit  <<= 1;
-
-        DPRINTK("Doubled maptrack size\n");
-        handle = get_maptrack_handle(ld->grant_table);
-    }
-
-#if GRANT_DEBUG_VERBOSE
-    DPRINTK("Mapping grant ref (%hu) for domain (%hu) with flags (%x)\n",
-            ref, dom, dev_hst_ro_flags);
-#endif
-
-    if ( 0 <= ( rc = __gnttab_activate_grant_ref( ld, led, rd, ref,
-                                                  dev_hst_ro_flags,
-                                                  addr, &frame)))
-    {
-        /*
-         * Only make the maptrack live _after_ writing the pte, in case we 
-         * overwrite the same frame number, causing a maptrack walk to find it
-         */
-        ld->grant_table->maptrack[handle].domid = dom;
-
-        ld->grant_table->maptrack[handle].ref_and_flags
-            = (ref << MAPTRACK_REF_SHIFT) |
-              (dev_hst_ro_flags & MAPTRACK_GNTMAP_MASK);
-
-        (void)__put_user((u64)frame << PAGE_SHIFT, &uop->dev_bus_addr);
-
-        if ( ( dev_hst_ro_flags & GNTMAP_host_map ) &&
-             !( dev_hst_ro_flags & GNTMAP_contains_pte) )
-            *va = addr;
-
-        (void)__put_user(handle, &uop->handle);
-    }
-    else
-    {
-        (void)__put_user(rc, &uop->handle);
-        put_maptrack_handle(ld->grant_table, handle);
-    }
-
-    put_domain(rd);
-    return rc;
-}
-
-static long
-gnttab_map_grant_ref(
-    gnttab_map_grant_ref_t *uop, unsigned int count)
-{
-    int i, rc, flush = 0;
-    unsigned long va = 0;
-
-    for ( i = 0; i < count; i++ )
-        if ( (rc =__gnttab_map_grant_ref(&uop[i], &va)) >= 0 )
-            flush += rc;
-
-#ifdef __ia64__
-// FIXME-ia64: probably need to do something here to avoid stale mappings?
-#else
-    if ( flush == 1 )
-        flush_tlb_one_mask(current->domain->cpumask, va);
-    else if ( flush != 0 ) 
-        flush_tlb_mask(current->domain->cpumask);
-#endif
-
-    return 0;
-}
-
-static int
-__gnttab_unmap_grant_ref(
-    gnttab_unmap_grant_ref_t *uop,
-    unsigned long *va)
-{
-    domid_t          dom;
-    grant_ref_t      ref;
-    u16              handle;
-    struct domain   *ld, *rd;
-    active_grant_entry_t *act;
-    grant_entry_t   *sha;
-    grant_mapping_t *map;
-    u16              flags;
-    s16              rc = 1;
-    u64              addr, dev_bus_addr;
-    unsigned long    frame;
-
-    ld = current->domain;
-
-    /* Bitwise-OR avoids short-circuiting which screws control flow. */
-    if ( unlikely(__get_user(addr, &uop->host_addr) |
-                  __get_user(dev_bus_addr, &uop->dev_bus_addr) |
-                  __get_user(handle, &uop->handle)) )
-    {
-        DPRINTK("Fault while reading gnttab_unmap_grant_ref_t.\n");
-        return -EFAULT; /* don't set status */
-    }
-
-    frame = (unsigned long)(dev_bus_addr >> PAGE_SHIFT);
-
-    map = &ld->grant_table->maptrack[handle];
-
-    if ( unlikely(handle >= ld->grant_table->maptrack_limit) ||
-         unlikely(!(map->ref_and_flags & MAPTRACK_GNTMAP_MASK)) )
-    {
-        DPRINTK("Bad handle (%d).\n", handle);
-        (void)__put_user(GNTST_bad_handle, &uop->status);
-        return GNTST_bad_handle;
-    }
-
-    dom   = map->domid;
-    ref   = map->ref_and_flags >> MAPTRACK_REF_SHIFT;
-    flags = map->ref_and_flags & MAPTRACK_GNTMAP_MASK;
-
-    if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
-         unlikely(ld == rd) )
-    {
-        if ( rd != NULL )
-            put_domain(rd);
-        DPRINTK("Could not find domain %d\n", dom);
-        (void)__put_user(GNTST_bad_domain, &uop->status);
-        return GNTST_bad_domain;
-    }
-
-#if GRANT_DEBUG_VERBOSE
-    DPRINTK("Unmapping grant ref (%hu) for domain (%hu) with handle (%hu)\n",
-            ref, dom, handle);
-#endif
-
-    act = &rd->grant_table->active[ref];
-    sha = &rd->grant_table->shared[ref];
-
-    spin_lock(&rd->grant_table->lock);
-
-    if ( frame == 0 )
-    {
-        frame = act->frame;
-    }
-    else
-    {
-        if ( unlikely(frame != act->frame) )
-            PIN_FAIL(unmap_out, GNTST_general_error,
-                     "Bad frame number doesn't match gntref.\n");
-        if ( flags & GNTMAP_device_map )
-            act->pin -= (flags & GNTMAP_readonly) ? GNTPIN_devr_inc
-                                                  : GNTPIN_devw_inc;
-
-        map->ref_and_flags &= ~GNTMAP_device_map;
-        (void)__put_user(0, &uop->dev_bus_addr);
-
-        /* Frame is now unmapped for device access. */
-    }
-
-    if ( (addr != 0) &&
-         (flags & GNTMAP_host_map) &&
-         ((act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask)) > 0))
-    {
-#ifdef __ia64__
-// FIXME-ia64: any error checking need to be done here?
-#else
-        if ( flags & GNTMAP_contains_pte )
-        {
-            if ( (rc = clear_grant_pte_mapping(addr, frame, ld)) < 0 )
-                goto unmap_out;
-        }
-        else
-        {
-            if ( (rc = clear_grant_va_mapping(addr, frame)) < 0 )
-                goto unmap_out;
-        }
-#endif
-
-        map->ref_and_flags &= ~GNTMAP_host_map;
-
-        act->pin -= (flags & GNTMAP_readonly) ? GNTPIN_hstr_inc
-                                              : GNTPIN_hstw_inc;
-
-        rc = 0;
-        if ( !( flags & GNTMAP_contains_pte) )
-            *va = addr;
-    }
-
-    if ( (map->ref_and_flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0)
-    {
-        map->ref_and_flags = 0;
-        put_maptrack_handle(ld->grant_table, handle);
-    }
-
-#ifdef __ia64__
-// FIXME-ia64: any error checking need to be done here?  I think not and then
-//  this can probably be macro-ized into nothingness
-#else
-    /* If just unmapped a writable mapping, mark as dirtied */
-    if ( unlikely(shadow_mode_log_dirty(rd)) &&
-        !( flags & GNTMAP_readonly ) )
-         mark_dirty(rd, frame);
-#endif
-
-    /* If the last writable mapping has been removed, put_page_type */
-    if ( ( (act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask) ) == 0) &&
-         ( !( flags & GNTMAP_readonly ) ) )
-    {
-        clear_bit(_GTF_writing, &sha->flags);
-        put_page_type(&frame_table[frame]);
-    }
-
-    if ( act->pin == 0 )
-    {
-        act->frame = 0xdeadbeef;
-        clear_bit(_GTF_reading, &sha->flags);
-        put_page(&frame_table[frame]);
-    }
-
- unmap_out:
-    (void)__put_user(rc, &uop->status);
-    spin_unlock(&rd->grant_table->lock);
-    put_domain(rd);
-    return rc;
-}
-
-static long
-gnttab_unmap_grant_ref(
-    gnttab_unmap_grant_ref_t *uop, unsigned int count)
-{
-    int i, flush = 0;
-    unsigned long va = 0;
-
-    for ( i = 0; i < count; i++ )
-        if ( __gnttab_unmap_grant_ref(&uop[i], &va) == 0 )
-            flush++;
-
-#ifdef __ia64__
-// FIXME-ia64: probably need to do something here to avoid stale mappings?
-#else
-    if ( flush == 1 )
-        flush_tlb_one_mask(current->domain->cpumask, va);
-    else if ( flush != 0 ) 
-        flush_tlb_mask(current->domain->cpumask);
-#endif
-
-    return 0;
-}
-
-static long 
-gnttab_setup_table(
-    gnttab_setup_table_t *uop, unsigned int count)
-{
-    gnttab_setup_table_t  op;
-    struct domain        *d;
-    int                   i;
-
-    if ( count != 1 )
-        return -EINVAL;
-
-    if ( unlikely(copy_from_user(&op, uop, sizeof(op)) != 0) )
-    {
-        DPRINTK("Fault while reading gnttab_setup_table_t.\n");
-        return -EFAULT;
-    }
-
-    if ( unlikely(op.nr_frames > NR_GRANT_FRAMES) )
-    {
-        DPRINTK("Xen only supports up to %d grant-table frames per domain.\n",
-                NR_GRANT_FRAMES);
-        (void)put_user(GNTST_general_error, &uop->status);
-        return 0;
-    }
-
-    if ( op.dom == DOMID_SELF )
-    {
-        op.dom = current->domain->domain_id;
-    }
-    else if ( unlikely(!IS_PRIV(current->domain)) )
-    {
-        (void)put_user(GNTST_permission_denied, &uop->status);
-        return 0;
-    }
-
-    if ( unlikely((d = find_domain_by_id(op.dom)) == NULL) )
-    {
-        DPRINTK("Bad domid %d.\n", op.dom);
-        (void)put_user(GNTST_bad_domain, &uop->status);
-        return 0;
-    }
-
-    if ( op.nr_frames <= NR_GRANT_FRAMES )
-    {
-        ASSERT(d->grant_table != NULL);
-        (void)put_user(GNTST_okay, &uop->status);
-#ifdef __ia64__
-       if (d == dom0) {
-            for ( i = 0; i < op.nr_frames; i++ )
-                (void)put_user(
-                    (virt_to_phys(d->grant_table->shared) >> PAGE_SHIFT) + i,
-                    &uop->frame_list[i]);
-       } else {
-            /* IA64 hack - need to map it somewhere */
-            unsigned long addr = (1UL << 40);
-            map_domain_page(d, addr, virt_to_phys(d->grant_table->shared));
-            (void)put_user(addr >> PAGE_SHIFT, &uop->frame_list[0]);
-        }
-#else
-        for ( i = 0; i < op.nr_frames; i++ )
-            (void)put_user(
-                (virt_to_phys(d->grant_table->shared) >> PAGE_SHIFT) + i,
-                &uop->frame_list[i]);
-#endif
-    }
-
-    put_domain(d);
-    return 0;
-}
-
-#if GRANT_DEBUG
-static int
-gnttab_dump_table(gnttab_dump_table_t *uop)
-{
-    grant_table_t        *gt;
-    gnttab_dump_table_t   op;
-    struct domain        *d;
-    u32                   shared_mfn;
-    active_grant_entry_t *act;
-    grant_entry_t         sha_copy;
-    grant_mapping_t      *maptrack;
-    int                   i;
-
-
-    if ( unlikely(copy_from_user(&op, uop, sizeof(op)) != 0) )
-    {
-        DPRINTK("Fault while reading gnttab_dump_table_t.\n");
-        return -EFAULT;
-    }
-
-    if ( op.dom == DOMID_SELF )
-    {
-        op.dom = current->domain->domain_id;
-    }
-
-    if ( unlikely((d = find_domain_by_id(op.dom)) == NULL) )
-    {
-        DPRINTK("Bad domid %d.\n", op.dom);
-        (void)put_user(GNTST_bad_domain, &uop->status);
-        return 0;
-    }
-
-    ASSERT(d->grant_table != NULL);
-    gt = d->grant_table;
-    (void)put_user(GNTST_okay, &uop->status);
-
-    shared_mfn = virt_to_phys(d->grant_table->shared);
-
-    DPRINTK("Grant table for dom (%hu) MFN (%x)\n",
-            op.dom, shared_mfn);
-
-    ASSERT(d->grant_table->active != NULL);
-    ASSERT(d->grant_table->shared != NULL);
-    ASSERT(d->grant_table->maptrack != NULL);
-
-    for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
-    {
-        sha_copy =  gt->shared[i];
-
-        if ( sha_copy.flags )
-        {
-            DPRINTK("Grant: dom (%hu) SHARED (%d) flags:(%hx) "
-                    "dom:(%hu) frame:(%x)\n",
-                    op.dom, i, sha_copy.flags, sha_copy.domid, sha_copy.frame);
-        }
-    }
-
-    spin_lock(&gt->lock);
-
-    for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
-    {
-        act = &gt->active[i];
-
-        if ( act->pin )
-        {
-            DPRINTK("Grant: dom (%hu) ACTIVE (%d) pin:(%x) "
-                    "dom:(%hu) frame:(%lx)\n",
-                    op.dom, i, act->pin, act->domid, act->frame);
-        }
-    }
-
-    for ( i = 0; i < gt->maptrack_limit; i++ )
-    {
-        maptrack = &gt->maptrack[i];
-
-        if ( maptrack->ref_and_flags & MAPTRACK_GNTMAP_MASK )
-        {
-            DPRINTK("Grant: dom (%hu) MAP (%d) ref:(%hu) flags:(%x) "
-                    "dom:(%hu)\n",
-                    op.dom, i,
-                    maptrack->ref_and_flags >> MAPTRACK_REF_SHIFT,
-                    maptrack->ref_and_flags & MAPTRACK_GNTMAP_MASK,
-                    maptrack->domid);
-        }
-    }
-
-    spin_unlock(&gt->lock);
-
-    put_domain(d);
-    return 0;
-}
-#endif
-
-static long
-gnttab_transfer(gnttab_transfer_t *uop, unsigned int count)
-{
-    struct domain *d = current->domain;
-    struct domain *e;
-    struct pfn_info *page;
-    u32 _d, _nd, x, y;
-    int i;
-    int result = GNTST_okay;
-
-#ifdef __ia64__
-//FIXME-IA64: not support for now?
-    return GNTST_general_error;
-#else
-    for (i = 0; i < count; i++) {
-        gnttab_transfer_t *gop = &uop[i];
-#if GRANT_DEBUG
-        printk("gnttab_transfer: i=%d mfn=%lx domid=%d gref=%08x\n",
-               i, gop->mfn, gop->domid, gop->handle);
-#endif
-        page = &frame_table[gop->mfn];
-        
-        if (unlikely(IS_XEN_HEAP_FRAME(page))) { 
-            printk("gnttab_transfer: xen heap frame mfn=%lx\n", 
-                   (unsigned long) gop->mfn);
-            gop->status = GNTST_bad_virt_addr;
-            continue;
-        }
-        if (unlikely(!pfn_valid(page_to_pfn(page)))) {
-            printk("gnttab_transfer: invalid pfn for mfn=%lx\n", 
-                   (unsigned long) gop->mfn);
-            gop->status = GNTST_bad_virt_addr;
-            continue;
-        }
-        if (unlikely((e = find_domain_by_id(gop->domid)) == NULL)) {
-            printk("gnttab_transfer: can't find domain %d\n", gop->domid);
-            gop->status = GNTST_bad_domain;
-            continue;
-        }
-
-        spin_lock(&d->page_alloc_lock);
-
-        /*
-         * The tricky bit: atomically release ownership while
-         * there is just one benign reference to the page
-         * (PGC_allocated). If that reference disappears then the
-         * deallocation routine will safely spin.
-         */
-        _d  = pickle_domptr(d);
-        _nd = page->u.inuse._domain;
-        y   = page->count_info;
-        do {
-            x = y;
-            if (unlikely((x & (PGC_count_mask|PGC_allocated)) !=
-                         (1 | PGC_allocated)) || unlikely(_nd != _d)) {
-                printk("gnttab_transfer: Bad page values %p: ed=%p(%u), sd=%p,"
-                       " caf=%08x, taf=%" PRtype_info "\n", 
-                       (void *) page_to_pfn(page),
-                        d, d->domain_id, unpickle_domptr(_nd), x, 
-                        page->u.inuse.type_info);
-                spin_unlock(&d->page_alloc_lock);
-                put_domain(e);
-                return 0;
-            }
-            __asm__ __volatile__(
-                LOCK_PREFIX "cmpxchg8b %2"
-                : "=d" (_nd), "=a" (y),
-                "=m" (*(volatile u64 *)(&page->count_info))
-                : "0" (_d), "1" (x), "c" (NULL), "b" (x) );
-        } while (unlikely(_nd != _d) || unlikely(y != x));
-
-        /*
-         * Unlink from 'd'. At least one reference remains (now
-         * anonymous), so noone else is spinning to try to delete
-         * this page from 'd'.
-         */
-        d->tot_pages--;
-        list_del(&page->list);
-
-        spin_unlock(&d->page_alloc_lock);
-
-        spin_lock(&e->page_alloc_lock);
-
-        /*
-         * Check that 'e' will accept the page and has reservation
-         * headroom.  Also, a domain mustn't have PGC_allocated
-         * pages when it is dying.
-         */
-#ifdef GRANT_DEBUG
-        if (unlikely(e->tot_pages >= e->max_pages)) {
-            printk("gnttab_dontate: no headroom tot_pages=%d max_pages=%d\n",
-                   e->tot_pages, e->max_pages);
-            spin_unlock(&e->page_alloc_lock);
-            put_domain(e);
-            result = GNTST_general_error;
-            break;
-        }
-        if (unlikely(test_bit(DOMFLAGS_DYING, &e->domain_flags))) {
-            printk("gnttab_transfer: target domain is dying\n");
-            spin_unlock(&e->page_alloc_lock);
-            put_domain(e);
-            result = GNTST_general_error;
-            break;
-        }
-        if (unlikely(!gnttab_prepare_for_transfer(e, d, gop->ref))) {
-            printk("gnttab_transfer: gnttab_prepare_for_transfer fails\n");
-            spin_unlock(&e->page_alloc_lock);
-            put_domain(e);
-            result = GNTST_general_error;
-            break;
-        }
-#else
-        ASSERT(e->tot_pages <= e->max_pages);
-        if (unlikely(test_bit(DOMFLAGS_DYING, &e->domain_flags)) ||
-            unlikely(e->tot_pages == e->max_pages) ||
-            unlikely(!gnttab_prepare_for_transfer(e, d, gop->ref))) {
-            printk("gnttab_transfer: Transferee has no reservation headroom 
(%d,"
-                   "%d) or provided a bad grant ref (%08x) or is dying (%p)\n",
-                   e->tot_pages, e->max_pages, gop->ref, e->d_flags);
-            spin_unlock(&e->page_alloc_lock);
-            put_domain(e);
-            result = GNTST_general_error;
-            break;
-        }
-#endif
-        /* Okay, add the page to 'e'. */
-        if (unlikely(e->tot_pages++ == 0)) {
-            get_knownalive_domain(e);
-        }
-        list_add_tail(&page->list, &e->page_list);
-        page_set_owner(page, e);
-        
-        spin_unlock(&e->page_alloc_lock);
-        
-        /*
-         * Transfer is all done: tell the guest about its new page
-         * frame.
-         */
-        gnttab_notify_transfer(e, d, gop->ref, gop->mfn);
-        
-        put_domain(e);
-        
-        gop->status = GNTST_okay;
-    }
-    return result;
-#endif
-}
-
-long 
-do_grant_table_op(
-    unsigned int cmd, void *uop, unsigned int count)
-{
-    long rc;
-    struct domain *d = current->domain;
-    
-    if ( count > 512 )
-        return -EINVAL;
-    
-    LOCK_BIGLOCK(d);
-    
-#ifndef __ia64__
-    sync_pagetable_state(d);
-#endif
-    
-    rc = -EFAULT;
-    switch ( cmd )
-        {
-        case GNTTABOP_map_grant_ref:
-            if ( unlikely(!array_access_ok(
-                              uop, count, sizeof(gnttab_map_grant_ref_t))) )
-                goto out;
-            rc = gnttab_map_grant_ref((gnttab_map_grant_ref_t *)uop, count);
-            break;
-        case GNTTABOP_unmap_grant_ref:
-            if ( unlikely(!array_access_ok(
-                              uop, count, sizeof(gnttab_unmap_grant_ref_t))) )
-                goto out;
-            rc = gnttab_unmap_grant_ref((gnttab_unmap_grant_ref_t *)uop, 
-                                        count);
-            break;
-        case GNTTABOP_setup_table:
-            rc = gnttab_setup_table((gnttab_setup_table_t *)uop, count);
-            break;
-#if GRANT_DEBUG
-        case GNTTABOP_dump_table:
-            rc = gnttab_dump_table((gnttab_dump_table_t *)uop);
-            break;
-#endif
-        case GNTTABOP_transfer:
-            if (unlikely(!array_access_ok(uop, count, 
-                                          sizeof(gnttab_transfer_t))))
-                goto out;
-            rc = gnttab_transfer(uop, count);
-            break;
-        default:
-            rc = -ENOSYS;
-            break;
-        }
-    
-  out:
-    UNLOCK_BIGLOCK(d);
-    
-    return rc;
-}
-
-int 
-gnttab_prepare_for_transfer(
-    struct domain *rd, struct domain *ld, grant_ref_t ref)
-{
-    grant_table_t *rgt;
-    grant_entry_t *sha;
-    domid_t        sdom;
-    u16            sflags;
-    u32            scombo, prev_scombo;
-    int            retries = 0;
-    unsigned long  target_pfn;
-
-#if GRANT_DEBUG_VERBOSE
-    DPRINTK("gnttab_prepare_for_transfer rd(%hu) ld(%hu) ref(%hu).\n",
-            rd->domain_id, ld->domain_id, ref);
-#endif
-
-    if ( unlikely((rgt = rd->grant_table) == NULL) ||
-         unlikely(ref >= NR_GRANT_ENTRIES) )
-    {
-        DPRINTK("Dom %d has no g.t., or ref is bad (%d).\n",
-                rd->domain_id, ref);
-        return 0;
-    }
-
-    spin_lock(&rgt->lock);
-
-    sha = &rgt->shared[ref];
-    
-    sflags = sha->flags;
-    sdom   = sha->domid;
-
-    for ( ; ; )
-    {
-        target_pfn = sha->frame;
-
-        if ( unlikely(target_pfn >= max_page ) )
-        {
-            DPRINTK("Bad pfn (%lx)\n", target_pfn);
-            goto fail;
-        }
-
-        if ( unlikely(sflags != GTF_accept_transfer) ||
-             unlikely(sdom != ld->domain_id) )
-        {
-            DPRINTK("Bad flags (%x) or dom (%d). (NB. expected dom %d)\n",
-                    sflags, sdom, ld->domain_id);
-            goto fail;
-        }
-
-        /* Merge two 16-bit values into a 32-bit combined update. */
-        /* NB. Endianness! */
-        prev_scombo = scombo = ((u32)sdom << 16) | (u32)sflags;
-
-        /* NB. prev_scombo is updated in place to seen value. */
-        if ( unlikely(cmpxchg_user((u32 *)&sha->flags, prev_scombo, 
-                                   prev_scombo | GTF_transfer_committed)) )
-        {
-            DPRINTK("Fault while modifying shared flags and domid.\n");
-            goto fail;
-        }
-
-        /* Did the combined update work (did we see what we expected?). */
-        if ( likely(prev_scombo == scombo) )
-            break;
-
-        if ( retries++ == 4 )
-        {
-            DPRINTK("Shared grant entry is unstable.\n");
-            goto fail;
-        }
-
-        /* Didn't see what we expected. Split out the seen flags & dom. */
-        /* NB. Endianness! */
-        sflags = (u16)prev_scombo;
-        sdom   = (u16)(prev_scombo >> 16);
-    }
-
-    spin_unlock(&rgt->lock);
-    return 1;
-
- fail:
-    spin_unlock(&rgt->lock);
-    return 0;
-}
-
-void 
-gnttab_notify_transfer(
-    struct domain *rd, struct domain *ld, grant_ref_t ref, unsigned long frame)
-{
-    grant_entry_t  *sha;
-    unsigned long   pfn;
-
-#if GRANT_DEBUG_VERBOSE
-    DPRINTK("gnttab_notify_transfer rd(%hu) ld(%hu) ref(%hu).\n",
-            rd->domain_id, ld->domain_id, ref);
-#endif
-
-    sha = &rd->grant_table->shared[ref];
-
-    spin_lock(&rd->grant_table->lock);
-
-#ifdef __ia64__
-// FIXME-ia64: any error checking need to be done here?
-#else
-    pfn = sha->frame;
-
-    if ( unlikely(pfn >= max_page ) )
-        DPRINTK("Bad pfn (%lx)\n", pfn);
-    else
-    {
-        machine_to_phys_mapping[frame] = pfn;
-
-        if ( unlikely(shadow_mode_log_dirty(ld)))
-             mark_dirty(ld, frame);
-
-        if (shadow_mode_translate(ld))
-            __phys_to_machine_mapping[pfn] = frame;
-    }
-#endif
-    sha->frame = __mfn_to_gpfn(rd, frame);
-    sha->domid = rd->domain_id;
-    wmb();
-    sha->flags = ( GTF_accept_transfer | GTF_transfer_completed );
-
-    spin_unlock(&rd->grant_table->lock);
-
-    return;
-}
-
-int 
-grant_table_create(
-    struct domain *d)
-{
-    grant_table_t *t;
-    int            i;
-
-    if ( (t = xmalloc(grant_table_t)) == NULL )
-        goto no_mem;
-
-    /* Simple stuff. */
-    memset(t, 0, sizeof(*t));
-    spin_lock_init(&t->lock);
-
-    /* Active grant table. */
-    if ( (t->active = xmalloc_array(active_grant_entry_t, NR_GRANT_ENTRIES))
-         == NULL )
-        goto no_mem;
-    memset(t->active, 0, sizeof(active_grant_entry_t) * NR_GRANT_ENTRIES);
-
-    /* Tracking of mapped foreign frames table */
-    if ( (t->maptrack = alloc_xenheap_page()) == NULL )
-        goto no_mem;
-    t->maptrack_order = 0;
-    t->maptrack_limit = PAGE_SIZE / sizeof(grant_mapping_t);
-    memset(t->maptrack, 0, PAGE_SIZE);
-    for ( i = 0; i < t->maptrack_limit; i++ )
-        t->maptrack[i].ref_and_flags = (i+1) << MAPTRACK_REF_SHIFT;
-
-    /* Shared grant table. */
-    t->shared = alloc_xenheap_pages(ORDER_GRANT_FRAMES);
-    if ( t->shared == NULL )
-        goto no_mem;
-    memset(t->shared, 0, NR_GRANT_FRAMES * PAGE_SIZE);
-
-#ifdef __ia64__
-// I don't think there's anything to do here on ia64?...
-#else
-    for ( i = 0; i < NR_GRANT_FRAMES; i++ )
-    {
-        SHARE_PFN_WITH_DOMAIN(
-            virt_to_page((char *)(t->shared)+(i*PAGE_SIZE)), d);
-        machine_to_phys_mapping[(virt_to_phys(t->shared) >> PAGE_SHIFT) + i] =
-            INVALID_M2P_ENTRY;
-    }
-#endif
-
-    /* Okay, install the structure. */
-    wmb(); /* avoid races with lock-free access to d->grant_table */
-    d->grant_table = t;
-    return 0;
-
- no_mem:
-    if ( t != NULL )
-    {
-        xfree(t->active);
-        free_xenheap_page(t->maptrack);
-        xfree(t);
-    }
-    return -ENOMEM;
-}
-
-void
-gnttab_release_mappings(
-    struct domain *ld)
-{
-    grant_table_t          *gt = ld->grant_table;
-    grant_mapping_t        *map;
-    domid_t                 dom;
-    grant_ref_t             ref;
-    u16                     handle;
-    struct domain          *ld, *rd;
-    unsigned long           frame;
-    active_grant_entry_t   *act;
-    grant_entry_t          *sha;
-
-    for ( handle = 0; handle < gt->maptrack_limit; handle++ )
-    {
-        map = &gt->maptrack[handle];
-
-        if ( map->ref_and_flags & GNTMAP_device_map )
-        {
-            dom = map->domid;
-            ref = map->ref_and_flags >> MAPTRACK_REF_SHIFT;
-
-            DPRINTK("Grant release (%hu) ref:(%hu) flags:(%x) dom:(%hu)\n",
-                    handle, ref,
-                    map->ref_and_flags & MAPTRACK_GNTMAP_MASK, dom);
-
-            if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
-                 unlikely(ld == rd) )
-            {
-                if ( rd != NULL )
-                    put_domain(rd);
-
-                printk(KERN_WARNING "Grant release: No dom%d\n", dom);
-                continue;
-            }
-
-            act = &rd->grant_table->active[ref];
-            sha = &rd->grant_table->shared[ref];
-
-            spin_lock(&rd->grant_table->lock);
-
-            if ( act->pin & (GNTPIN_devw_mask | GNTPIN_devr_mask) )
-            {
-                frame = act->frame;
-
-                if ( ( (act->pin & GNTPIN_hstw_mask) == 0 ) &&
-                     ( (act->pin & GNTPIN_devw_mask) >  0 ) )
-                {
-                    clear_bit(_GTF_writing, &sha->flags);
-                    put_page_type(&frame_table[frame]);
-                }
-
-                act->pin &= ~(GNTPIN_devw_mask | GNTPIN_devr_mask);
-
-                if ( act->pin == 0 )
-                {
-                    clear_bit(_GTF_reading, &sha->flags);
-                    map->ref_and_flags = 0;
-                    put_page(&frame_table[frame]);
-                }
-                else
-                    map->ref_and_flags &= ~GNTMAP_device_map;
-            }
-
-            spin_unlock(&rd->grant_table->lock);
-
-            put_domain(rd);
-        }
-    }
-}
-
-
-void
-grant_table_destroy(
-    struct domain *d)
-{
-    grant_table_t *t;
-
-    if ( (t = d->grant_table) != NULL )
-    {
-        /* Free memory relating to this grant table. */
-        d->grant_table = NULL;
-        free_xenheap_pages(t->shared, ORDER_GRANT_FRAMES);
-        free_xenheap_page(t->maptrack);
-        xfree(t->active);
-        xfree(t);
-    }
-}
-
-void
-grant_table_init(
-    void)
-{
-    /* Nothing. */
-}
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] Move arch-specific portions of grant-table implementation, Xen patchbot -unstable <=