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] Add preliminary grant table support (in arch/ia64 and tu

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] Add preliminary grant table support (in arch/ia64 and turned
From: BitKeeper Bot <riel@xxxxxxxxxxx>
Date: Fri, 17 Jun 2005 21:22:39 +0000
Cc: james@xxxxxxxxxxxxx
Delivery-date: Thu, 23 Jun 2005 11:02:22 +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 Development List <xen-devel@xxxxxxxxxxxxxxxxxxx>
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
ChangeSet 1.1713.2.8, 2005/06/17 15:22:39-06:00, djm@xxxxxxxxxxxxxxx

        Add preliminary grant table support (in arch/ia64 and turned
        off for CONFIG_VTI for now)



 arch/ia64/Makefile      |    2 
 arch/ia64/grant_table.c | 1294 ++++++++++++++++++++++++++++++++++++++++++++++++
 arch/ia64/hypercall.c   |    6 
 arch/ia64/xenmisc.c     |   31 +
 include/asm-ia64/mm.h   |    5 
 5 files changed, 1336 insertions(+), 2 deletions(-)


diff -Nru a/xen/arch/ia64/Makefile b/xen/arch/ia64/Makefile
--- a/xen/arch/ia64/Makefile    2005-06-23 07:03:29 -04:00
+++ b/xen/arch/ia64/Makefile    2005-06-23 07:03:29 -04:00
@@ -10,7 +10,7 @@
        extable.o linuxextable.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 \
-       sn_console.o
+       grant_table.o sn_console.o
 
 ifeq ($(CONFIG_VTI),y)
 OBJS += vmx_init.o vmx_virt.o vmx_vcpu.o vmx_process.o vmx_vsa.o vmx_ivt.o \
diff -Nru a/xen/arch/ia64/grant_table.c b/xen/arch/ia64/grant_table.c
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/xen/arch/ia64/grant_table.c       2005-06-23 07:03:29 -04:00
@@ -0,0 +1,1294 @@
+#ifndef CONFIG_VTI
+// 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
+ * 
+ * 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: need to implement real cmpxchg_user on ia64
+#define cmpxchg_user(_p,_o,_n) ((*_p == _o) ? ((*_p = _n), 0) : ((_o = *_p), 
0))
+// FIXME-ia64: the following are meaningless on ia64? move to some header file
+#define put_page(x) do { } while (0)
+#define put_page_type(x) do { } while (0)
+// 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
+
+#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) )
+        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,
+    unsigned long           host_virt_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_virt_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;
+
+        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 reflect mapping.
+     * 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 ( (host_virt_addr != 0) && (dev_hst_ro_flags & GNTMAP_host_map) )
+    {
+        /* Write update into the pagetable. */
+        l1_pgentry_t pte;
+        pte = l1e_from_pfn(frame, _PAGE_PRESENT | _PAGE_ACCESSED | 
_PAGE_DIRTY);
+        if ( !(dev_hst_ro_flags & GNTMAP_readonly) )
+            l1e_add_flags(pte,_PAGE_RW);
+        rc = update_grant_va_mapping( host_virt_addr, pte, 
+                       mapping_d, mapping_ed );
+
+        /*
+         * IMPORTANT: (rc == 0) => must flush / invalidate entry in TLB.
+         * 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.
+ */
+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;
+    unsigned long         frame = 0, host_virt_addr;
+    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(host_virt_addr, &uop->host_virt_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 ( ((host_virt_addr != 0) || (dev_hst_ro_flags & GNTMAP_host_map)) &&
+         unlikely(!__addr_ok(host_virt_addr)))
+    {
+        DPRINTK("Bad virtual address (%lx) or flags (%x).\n",
+                host_virt_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 ( 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;
+
+        /* 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;
+
+        printk("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,
+                                                  host_virt_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(frame, &uop->dev_bus_addr);
+
+        if ( dev_hst_ro_flags & GNTMAP_host_map )
+            *va = host_virt_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, flush = 0;
+    unsigned long va = 0;
+
+    for ( i = 0; i < count; i++ )
+        if ( __gnttab_map_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 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;
+    unsigned long  frame, virt;
+
+    ld = current->domain;
+
+    /* Bitwise-OR avoids short-circuiting which screws control flow. */
+    if ( unlikely(__get_user(virt, &uop->host_virt_addr) |
+                  __get_user(frame, &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 */
+    }
+
+    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 ( frame == GNTUNMAP_DEV_FROM_VIRT )
+    {
+        if ( !( flags & GNTMAP_device_map ) )
+            PIN_FAIL(unmap_out, GNTST_bad_dev_addr,
+                     "Bad frame number: frame not mapped for dev access.\n");
+        frame = act->frame;
+
+        /* Frame will be unmapped for device access below if virt addr okay. */
+    }
+    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. */
+    }
+
+#ifdef __ia64__
+// FIXME-ia64: any error checking need to be done here?
+#else
+    if ( (virt != 0) &&
+         (flags & GNTMAP_host_map) &&
+         ((act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask)) > 0))
+    {
+        l1_pgentry_t   *pl1e;
+        unsigned long   _ol1e;
+
+        pl1e = &linear_pg_table[l1_linear_offset(virt)];
+
+        if ( unlikely(__get_user(_ol1e, (unsigned long *)pl1e) != 0) )
+        {
+            DPRINTK("Could not find PTE entry for address %lx\n", virt);
+            rc = -EINVAL;
+            goto unmap_out;
+        }
+
+        /*
+         * Check that the virtual address supplied is actually mapped to 
+         * act->frame.
+         */
+        if ( unlikely((_ol1e >> PAGE_SHIFT) != frame ))
+        {
+            DPRINTK("PTE entry %lx for address %lx doesn't match frame %lx\n",
+                    _ol1e, virt, frame);
+            rc = -EINVAL;
+            goto unmap_out;
+        }
+
+        /* Delete pagetable entry. */
+        if ( unlikely(__put_user(0, (unsigned long *)pl1e)))
+        {
+            DPRINTK("Cannot delete PTE entry at %p for virtual address %lx\n",
+                    pl1e, virt);
+            rc = -EINVAL;
+            goto unmap_out;
+        }
+
+        map->ref_and_flags &= ~GNTMAP_host_map;
+
+        act->pin -= (flags & GNTMAP_readonly) ? GNTPIN_hstr_inc
+                                              : GNTPIN_hstw_inc;
+
+        if ( frame == GNTUNMAP_DEV_FROM_VIRT )
+        {
+            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);
+        }
+
+        rc = 0;
+        *va = virt;
+    }
+#endif
+
+    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 )
+    {
+        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);
+        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]);
+    }
+
+    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:(%lx)\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
+
+long 
+do_grant_table_op(
+    unsigned int cmd, void *uop, unsigned int count)
+{
+    long rc;
+
+    if ( count > 512 )
+        return -EINVAL;
+
+    LOCK_BIGLOCK(current->domain);
+
+    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
+    default:
+        rc = -ENOSYS;
+        break;
+    }
+
+out:
+    UNLOCK_BIGLOCK(current->domain);
+
+    return rc;
+}
+
+int
+gnttab_check_unmap(
+    struct domain *rd, struct domain *ld, unsigned long frame, int readonly)
+{
+    /* Called when put_page is invoked on a page belonging to a foreign domain.
+     * Instead of decrementing the frame table ref count, locate the grant
+     * table entry, if any, and if found, decrement that count.
+     * Called a _lot_ at domain creation because pages mapped by priv domains
+     * also traverse this.
+     */
+
+    /* Note: If the same frame is mapped multiple times, and then one of
+     *       the ptes is overwritten, which maptrack handle gets invalidated?
+     * Advice: Don't do it. Explicitly unmap.
+     */
+
+    unsigned int handle, ref, refcount;
+    grant_table_t        *lgt, *rgt;
+    active_grant_entry_t *act;
+    grant_mapping_t      *map;
+    int found = 0;
+
+    lgt = ld->grant_table;
+
+#if GRANT_DEBUG_VERBOSE
+    if ( ld->domain_id != 0 )
+    {
+        DPRINTK("Foreign unref rd(%d) ld(%d) frm(%x) flgs(%x).\n",
+                rd->domain_id, ld->domain_id, frame, readonly);
+    }
+#endif
+
+    /* Fast exit if we're not mapping anything using grant tables */
+    if ( lgt->map_count == 0 )
+        return 0;
+
+    if ( get_domain(rd) == 0 )
+    {
+        DPRINTK("gnttab_check_unmap: couldn't get_domain rd(%d)\n",
+                rd->domain_id);
+        return 0;
+    }
+
+    rgt = rd->grant_table;
+
+    for ( handle = 0; handle < lgt->maptrack_limit; handle++ )
+    {
+        map = &lgt->maptrack[handle];
+
+        if ( ( map->ref_and_flags & MAPTRACK_GNTMAP_MASK ) &&
+             ( readonly ? 1 : (!(map->ref_and_flags & GNTMAP_readonly))))
+        {
+            ref = (map->ref_and_flags >> MAPTRACK_REF_SHIFT);
+            act = &rgt->active[ref];
+
+            spin_lock(&rgt->lock);
+
+            if ( act->frame != frame )
+            {
+                spin_unlock(&rgt->lock);
+                continue;
+            }
+
+            refcount = act->pin & ( readonly ? GNTPIN_hstr_mask
+                                             : GNTPIN_hstw_mask );
+            if ( refcount == 0 )
+            {
+                spin_unlock(&rgt->lock);
+                continue;
+            }
+
+            /* gotcha */
+            DPRINTK("Grant unref rd(%d) ld(%d) frm(%lx) flgs(%x).\n",
+                    rd->domain_id, ld->domain_id, frame, readonly);
+
+            if ( readonly )
+                act->pin -= GNTPIN_hstr_inc;
+            else
+            {
+                act->pin -= GNTPIN_hstw_inc;
+
+                /* any more granted writable mappings? */
+                if ( (act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) == 0 )
+                {
+                    clear_bit(_GTF_writing, &rgt->shared[ref].flags);
+                    put_page_type(&frame_table[frame]);
+                }
+            }
+
+            if ( act->pin == 0 )
+            {
+                clear_bit(_GTF_reading, &rgt->shared[ref].flags);
+                put_page(&frame_table[frame]);
+            }
+            spin_unlock(&rgt->lock);
+
+            clear_bit(GNTMAP_host_map, &map->ref_and_flags);
+
+            if ( !(map->ref_and_flags & GNTMAP_device_map) )
+                put_maptrack_handle(lgt, handle);
+
+            found = 1;
+            break;
+        }
+    }
+    put_domain(rd);
+
+    return found;
+}
+
+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;
+
+    DPRINTK("gnttab_prepare_for_transfer rd(%hu) ld(%hu) ref(%hu).\n",
+            rd->domain_id, ld->domain_id, ref);
+
+    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;
+
+    DPRINTK("gnttab_notify_transfer rd(%hu) ld(%hu) ref(%hu).\n",
+            rd->domain_id, ld->domain_id, ref);
+
+    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);
+        if ( t->maptrack != NULL )
+            free_xenheap_page(t->maptrack);
+        xfree(t);
+    }
+    return -ENOMEM;
+}
+
+void
+gnttab_release_dev_mappings(grant_table_t *gt)
+{
+    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;
+
+    ld = current->domain;
+
+    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. */
+}
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -Nru a/xen/arch/ia64/hypercall.c b/xen/arch/ia64/hypercall.c
--- a/xen/arch/ia64/hypercall.c 2005-06-23 07:03:29 -04:00
+++ b/xen/arch/ia64/hypercall.c 2005-06-23 07:03:29 -04:00
@@ -149,6 +149,12 @@
                regs->r8 = do_event_channel_op(regs->r14);
                break;
 
+#ifndef CONFIG_VTI
+           case __HYPERVISOR_grant_table_op:
+               regs->r8 = do_grant_table_op(regs->r14, regs->r15, regs->r16);
+               break;
+#endif
+
            case __HYPERVISOR_console_io:
                regs->r8 = do_console_io(regs->r14, regs->r15, regs->r16);
                break;
diff -Nru a/xen/arch/ia64/xenmisc.c b/xen/arch/ia64/xenmisc.c
--- a/xen/arch/ia64/xenmisc.c   2005-06-23 07:03:29 -04:00
+++ b/xen/arch/ia64/xenmisc.c   2005-06-23 07:03:29 -04:00
@@ -62,8 +62,10 @@
 void sync_lazy_execstate_mask(cpumask_t mask) {}
 void sync_lazy_execstate_all(void) {}
 
+#ifdef CONFIG_VTI
 int grant_table_create(struct domain *d) { return 0; }
 void grant_table_destroy(struct domain *d) { return; }
+#endif
 
 struct pt_regs *guest_cpu_user_regs(void) { return ia64_task_regs(current); }
 
@@ -71,6 +73,35 @@
 {
        raise_softirq(AC_TIMER_SOFTIRQ);
 }
+
+#ifndef CONFIG_VTI
+unsigned long
+__gpfn_to_mfn_foreign(struct domain *d, unsigned long gpfn)
+{
+       if (d == dom0)
+               return(gpfn);
+       else {
+               unsigned long pte = lookup_domain_mpa(d,gpfn << PAGE_SHIFT);
+               if (!pte) {
+printk("__gpfn_to_mfn_foreign: bad gpfn. spinning...\n");
+while(1);
+                       return 0;
+               }
+               return ((pte & _PFN_MASK) >> PAGE_SHIFT);
+       }
+}
+
+u32
+__mfn_to_gpfn(struct domain *d, unsigned long frame)
+{
+       // FIXME: is this right?
+if ((frame << PAGE_SHIFT) & _PAGE_PPN_MASK) {
+printk("__mfn_to_gpfn: bad frame. spinning...\n");
+while(1);
+}
+       return frame;
+}
+#endif
 
 unsigned long __hypercall_create_continuation(
        unsigned int op, unsigned int nr_args, ...)
diff -Nru a/xen/include/asm-ia64/mm.h b/xen/include/asm-ia64/mm.h
--- a/xen/include/asm-ia64/mm.h 2005-06-23 07:03:29 -04:00
+++ b/xen/include/asm-ia64/mm.h 2005-06-23 07:03:29 -04:00
@@ -132,6 +132,7 @@
 
 static inline void put_page(struct pfn_info *page)
 {
+#ifdef CONFIG_VTI      // doesn't work with non-VTI in grant tables yet
     u32 nx, x, y = page->count_info;
 
     do {
@@ -142,12 +143,14 @@
 
     if (unlikely((nx & PGC_count_mask) == 0))
        free_domheap_page(page);
+#endif
 }
 
 /* count_info and ownership are checked atomically. */
 static inline int get_page(struct pfn_info *page,
                            struct domain *domain)
 {
+#if 0
     u64 x, nx, y = *((u64*)&page->count_info);
     u32 _domain = pickle_domptr(domain);
 
@@ -164,7 +167,7 @@
        }
     }
     while(unlikely(y = cmpxchg(&page->count_info, x, nx)) != x);
-
+#endif
     return 1;
 }
 

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] Add preliminary grant table support (in arch/ia64 and turned, BitKeeper Bot <=