[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.