ia64/xen-unstable

changeset 8001:944cf29d126d

Move arch-specific portions of grant-table implementation
out of common code. Ready for use by ia64.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed Nov 23 13:50:14 2005 +0100 (2005-11-23)
parents 6d9ea03c1baa
children cd6a8d73f529
files xen/arch/ia64/Makefile xen/arch/x86/mm.c xen/common/Makefile xen/common/grant_table.c xen/include/asm-ia64/grant_table.h xen/include/asm-x86/grant_table.h xen/include/asm-x86/mm.h xen/include/xen/grant_table.h
line diff
     1.1 --- a/xen/arch/ia64/Makefile	Wed Nov 23 13:38:34 2005 +0100
     1.2 +++ b/xen/arch/ia64/Makefile	Wed Nov 23 13:50:14 2005 +0100
     1.3 @@ -10,7 +10,7 @@ OBJS = xensetup.o setup.o time.o irq.o p
     1.4  	extable.o linuxextable.o sort.o xenirq.o xentime.o \
     1.5  	regionreg.o entry.o unaligned.o privop.o vcpu.o \
     1.6  	irq_ia64.o irq_lsapic.o vhpt.o xenasm.o hyperprivop.o dom_fw.o \
     1.7 -	grant_table.o sn_console.o # ia64_ksyms.o 
     1.8 +	sn_console.o # ia64_ksyms.o 
     1.9  
    1.10  OBJS += vmx_init.o vmx_virt.o vmx_vcpu.o vmx_process.o vmx_vsa.o vmx_ivt.o\
    1.11  	vmx_phy_mode.o vmx_utility.o vmx_interrupt.o vmx_entry.o vmmu.o \
     2.1 --- a/xen/arch/ia64/xen/grant_table.c	Wed Nov 23 13:38:34 2005 +0100
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,1354 +0,0 @@
     2.4 -// temporarily in arch/ia64 until can merge into common/grant_table.c
     2.5 -/******************************************************************************
     2.6 - * common/grant_table.c
     2.7 - * 
     2.8 - * Mechanism for granting foreign access to page frames, and receiving
     2.9 - * page-ownership transfers.
    2.10 - * 
    2.11 - * Copyright (c) 2005 Christopher Clark
    2.12 - * Copyright (c) 2004 K A Fraser
    2.13 - * Copyright (c) 2005 Andrew Warfield
    2.14 - * Modifications by Geoffrey Lefebvre are (c) Intel Research Cambridge
    2.15 - * 
    2.16 - * This program is free software; you can redistribute it and/or modify
    2.17 - * it under the terms of the GNU General Public License as published by
    2.18 - * the Free Software Foundation; either version 2 of the License, or
    2.19 - * (at your option) any later version.
    2.20 - * 
    2.21 - * This program is distributed in the hope that it will be useful,
    2.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.24 - * GNU General Public License for more details.
    2.25 - * 
    2.26 - * You should have received a copy of the GNU General Public License
    2.27 - * along with this program; if not, write to the Free Software
    2.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    2.29 - */
    2.30 -
    2.31 -#define GRANT_DEBUG 0
    2.32 -#define GRANT_DEBUG_VERBOSE 0
    2.33 -
    2.34 -#include <xen/config.h>
    2.35 -#include <xen/lib.h>
    2.36 -#include <xen/sched.h>
    2.37 -#include <xen/shadow.h>
    2.38 -#include <xen/mm.h>
    2.39 -#ifdef __ia64__
    2.40 -#define __addr_ok(a) 1	// FIXME-ia64: a variant of access_ok??
    2.41 -// FIXME-ia64: these belong in an asm/grant_table.h... PAGE_SIZE different
    2.42 -#undef ORDER_GRANT_FRAMES
    2.43 -//#undef NUM_GRANT_FRAMES
    2.44 -#define ORDER_GRANT_FRAMES 0
    2.45 -//#define NUM_GRANT_FRAMES  (1U << ORDER_GRANT_FRAMES)
    2.46 -#endif
    2.47 -#include <acm/acm_hooks.h>
    2.48 -
    2.49 -#if defined(CONFIG_X86_64)
    2.50 -#define GRANT_PTE_FLAGS (_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
    2.51 -#else
    2.52 -#define GRANT_PTE_FLAGS (_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_DIRTY)
    2.53 -#endif
    2.54 -
    2.55 -#define PIN_FAIL(_lbl, _rc, _f, _a...)   \
    2.56 -    do {                           \
    2.57 -        DPRINTK( _f, ## _a );      \
    2.58 -        rc = (_rc);                \
    2.59 -        goto _lbl;                 \
    2.60 -    } while ( 0 )
    2.61 -
    2.62 -static inline int
    2.63 -get_maptrack_handle(
    2.64 -    grant_table_t *t)
    2.65 -{
    2.66 -    unsigned int h;
    2.67 -    if ( unlikely((h = t->maptrack_head) == (t->maptrack_limit - 1)) )
    2.68 -        return -1;
    2.69 -    t->maptrack_head = t->maptrack[h].ref_and_flags >> MAPTRACK_REF_SHIFT;
    2.70 -    t->map_count++;
    2.71 -    return h;
    2.72 -}
    2.73 -
    2.74 -static inline void
    2.75 -put_maptrack_handle(
    2.76 -    grant_table_t *t, int handle)
    2.77 -{
    2.78 -    t->maptrack[handle].ref_and_flags = t->maptrack_head << MAPTRACK_REF_SHIFT;
    2.79 -    t->maptrack_head = handle;
    2.80 -    t->map_count--;
    2.81 -}
    2.82 -
    2.83 -static int
    2.84 -__gnttab_activate_grant_ref(
    2.85 -    struct domain   *mapping_d,          /* IN */
    2.86 -    struct vcpu     *mapping_ed,
    2.87 -    struct domain   *granting_d,
    2.88 -    grant_ref_t      ref,
    2.89 -    u16              dev_hst_ro_flags,
    2.90 -    u64              addr,
    2.91 -    unsigned long   *pframe )            /* OUT */
    2.92 -{
    2.93 -    domid_t               sdom;
    2.94 -    u16                   sflags;
    2.95 -    active_grant_entry_t *act;
    2.96 -    grant_entry_t        *sha;
    2.97 -    s16                   rc = 1;
    2.98 -    unsigned long         frame = 0;
    2.99 -    int                   retries = 0;
   2.100 -
   2.101 -    /*
   2.102 -     * Objectives of this function:
   2.103 -     * . Make the record ( granting_d, ref ) active, if not already.
   2.104 -     * . Update shared grant entry of owner, indicating frame is mapped.
   2.105 -     * . Increment the owner act->pin reference counts.
   2.106 -     * . get_page on shared frame if new mapping.
   2.107 -     * . get_page_type if this is first RW mapping of frame.
   2.108 -     * . Add PTE to virtual address space of mapping_d, if necessary.
   2.109 -     * Returns:
   2.110 -     * .  -ve: error
   2.111 -     * .    1: ok
   2.112 -     * .    0: ok and TLB invalidate of host_addr needed.
   2.113 -     *
   2.114 -     * On success, *pframe contains mfn.
   2.115 -     */
   2.116 -
   2.117 -    /*
   2.118 -     * We bound the number of times we retry CMPXCHG on memory locations that
   2.119 -     * we share with a guest OS. The reason is that the guest can modify that
   2.120 -     * location at a higher rate than we can read-modify-CMPXCHG, so the guest
   2.121 -     * could cause us to livelock. There are a few cases where it is valid for
   2.122 -     * the guest to race our updates (e.g., to change the GTF_readonly flag),
   2.123 -     * so we allow a few retries before failing.
   2.124 -     */
   2.125 -
   2.126 -    act = &granting_d->grant_table->active[ref];
   2.127 -    sha = &granting_d->grant_table->shared[ref];
   2.128 -
   2.129 -    spin_lock(&granting_d->grant_table->lock);
   2.130 -
   2.131 -    if ( act->pin == 0 )
   2.132 -    {
   2.133 -        /* CASE 1: Activating a previously inactive entry. */
   2.134 -
   2.135 -        sflags = sha->flags;
   2.136 -        sdom   = sha->domid;
   2.137 -
   2.138 -        /* This loop attempts to set the access (reading/writing) flags
   2.139 -         * in the grant table entry.  It tries a cmpxchg on the field
   2.140 -         * up to five times, and then fails under the assumption that 
   2.141 -         * the guest is misbehaving. */
   2.142 -        for ( ; ; )
   2.143 -        {
   2.144 -            u32 scombo, prev_scombo, new_scombo;
   2.145 -
   2.146 -            if ( unlikely((sflags & GTF_type_mask) != GTF_permit_access) ||
   2.147 -                 unlikely(sdom != mapping_d->domain_id) )
   2.148 -                PIN_FAIL(unlock_out, GNTST_general_error,
   2.149 -                         "Bad flags (%x) or dom (%d). (NB. expected dom %d)\n",
   2.150 -                        sflags, sdom, mapping_d->domain_id);
   2.151 -
   2.152 -            /* Merge two 16-bit values into a 32-bit combined update. */
   2.153 -            /* NB. Endianness! */
   2.154 -            prev_scombo = scombo = ((u32)sdom << 16) | (u32)sflags;
   2.155 -
   2.156 -            new_scombo = scombo | GTF_reading;
   2.157 -            if ( !(dev_hst_ro_flags & GNTMAP_readonly) )
   2.158 -            {
   2.159 -                new_scombo |= GTF_writing;
   2.160 -                if ( unlikely(sflags & GTF_readonly) )
   2.161 -                    PIN_FAIL(unlock_out, GNTST_general_error,
   2.162 -                             "Attempt to write-pin a r/o grant entry.\n");
   2.163 -            }
   2.164 -
   2.165 -            /* NB. prev_scombo is updated in place to seen value. */
   2.166 -            if ( unlikely(cmpxchg_user((u32 *)&sha->flags,
   2.167 -                                       prev_scombo,
   2.168 -                                       new_scombo)) )
   2.169 -                PIN_FAIL(unlock_out, GNTST_general_error,
   2.170 -                         "Fault while modifying shared flags and domid.\n");
   2.171 -
   2.172 -            /* Did the combined update work (did we see what we expected?). */
   2.173 -            if ( likely(prev_scombo == scombo) )
   2.174 -                break;
   2.175 -
   2.176 -            if ( retries++ == 4 )
   2.177 -                PIN_FAIL(unlock_out, GNTST_general_error,
   2.178 -                         "Shared grant entry is unstable.\n");
   2.179 -
   2.180 -            /* Didn't see what we expected. Split out the seen flags & dom. */
   2.181 -            /* NB. Endianness! */
   2.182 -            sflags = (u16)prev_scombo;
   2.183 -            sdom   = (u16)(prev_scombo >> 16);
   2.184 -        }
   2.185 -
   2.186 -        /* rmb(); */ /* not on x86 */
   2.187 -
   2.188 -        frame = __gpfn_to_mfn_foreign(granting_d, sha->frame);
   2.189 -
   2.190 -#ifdef __ia64__
   2.191 -// FIXME-ia64: any error checking need to be done here?
   2.192 -#else
   2.193 -        if ( unlikely(!pfn_valid(frame)) ||
   2.194 -             unlikely(!((dev_hst_ro_flags & GNTMAP_readonly) ?
   2.195 -                        get_page(&frame_table[frame], granting_d) :
   2.196 -                        get_page_and_type(&frame_table[frame], granting_d,
   2.197 -                                          PGT_writable_page))) )
   2.198 -        {
   2.199 -            clear_bit(_GTF_writing, &sha->flags);
   2.200 -            clear_bit(_GTF_reading, &sha->flags);
   2.201 -            PIN_FAIL(unlock_out, GNTST_general_error,
   2.202 -                     "Could not pin the granted frame (%lx)!\n", frame);
   2.203 -        }
   2.204 -#endif 
   2.205 -
   2.206 -        if ( dev_hst_ro_flags & GNTMAP_device_map )
   2.207 -            act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ?
   2.208 -                GNTPIN_devr_inc : GNTPIN_devw_inc;
   2.209 -        if ( dev_hst_ro_flags & GNTMAP_host_map )
   2.210 -            act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ?
   2.211 -                GNTPIN_hstr_inc : GNTPIN_hstw_inc;
   2.212 -        act->domid = sdom;
   2.213 -        act->frame = frame;
   2.214 -    }
   2.215 -    else 
   2.216 -    {
   2.217 -        /* CASE 2: Active modications to an already active entry. */
   2.218 -
   2.219 -        /*
   2.220 -         * A cheesy check for possible pin-count overflow.
   2.221 -         * A more accurate check cannot be done with a single comparison.
   2.222 -         */
   2.223 -        if ( (act->pin & 0x80808080U) != 0 )
   2.224 -            PIN_FAIL(unlock_out, ENOSPC,
   2.225 -                     "Risk of counter overflow %08x\n", act->pin);
   2.226 -
   2.227 -        frame = act->frame;
   2.228 -
   2.229 -        if ( !(dev_hst_ro_flags & GNTMAP_readonly) && 
   2.230 -             !((sflags = sha->flags) & GTF_writing) )
   2.231 -        {
   2.232 -            for ( ; ; )
   2.233 -            {
   2.234 -                u16 prev_sflags;
   2.235 -                
   2.236 -                if ( unlikely(sflags & GTF_readonly) )
   2.237 -                    PIN_FAIL(unlock_out, GNTST_general_error,
   2.238 -                             "Attempt to write-pin a r/o grant entry.\n");
   2.239 -
   2.240 -                prev_sflags = sflags;
   2.241 -
   2.242 -                /* NB. prev_sflags is updated in place to seen value. */
   2.243 -                if ( unlikely(cmpxchg_user(&sha->flags, prev_sflags, 
   2.244 -                                           prev_sflags | GTF_writing)) )
   2.245 -                    PIN_FAIL(unlock_out, GNTST_general_error,
   2.246 -                         "Fault while modifying shared flags.\n");
   2.247 -
   2.248 -                if ( likely(prev_sflags == sflags) )
   2.249 -                    break;
   2.250 -
   2.251 -                if ( retries++ == 4 )
   2.252 -                    PIN_FAIL(unlock_out, GNTST_general_error,
   2.253 -                             "Shared grant entry is unstable.\n");
   2.254 -
   2.255 -                sflags = prev_sflags;
   2.256 -            }
   2.257 -
   2.258 -#ifdef __ia64__
   2.259 -// FIXME-ia64: any error checking need to be done here?
   2.260 -#else
   2.261 -            if ( unlikely(!get_page_type(&frame_table[frame],
   2.262 -                                         PGT_writable_page)) )
   2.263 -            {
   2.264 -                clear_bit(_GTF_writing, &sha->flags);
   2.265 -                PIN_FAIL(unlock_out, GNTST_general_error,
   2.266 -                         "Attempt to write-pin a unwritable page.\n");
   2.267 -            }
   2.268 -#endif
   2.269 -        }
   2.270 -
   2.271 -        if ( dev_hst_ro_flags & GNTMAP_device_map )
   2.272 -            act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ? 
   2.273 -                GNTPIN_devr_inc : GNTPIN_devw_inc;
   2.274 -
   2.275 -        if ( dev_hst_ro_flags & GNTMAP_host_map )
   2.276 -            act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ?
   2.277 -                GNTPIN_hstr_inc : GNTPIN_hstw_inc;
   2.278 -    }
   2.279 -
   2.280 -    /*
   2.281 -     * At this point:
   2.282 -     * act->pin updated to reference count mappings.
   2.283 -     * sha->flags updated to indicate to granting domain mapping done.
   2.284 -     * frame contains the mfn.
   2.285 -     */
   2.286 -
   2.287 -    spin_unlock(&granting_d->grant_table->lock);
   2.288 -
   2.289 -#ifdef __ia64__
   2.290 -// FIXME-ia64: any error checking need to be done here?
   2.291 -#else
   2.292 -    if ( (addr != 0) && (dev_hst_ro_flags & GNTMAP_host_map) )
   2.293 -    {
   2.294 -        /* Write update into the pagetable. */
   2.295 -        l1_pgentry_t pte;
   2.296 -        pte = l1e_from_pfn(frame, GRANT_PTE_FLAGS);
   2.297 -        
   2.298 -        if ( (dev_hst_ro_flags & GNTMAP_application_map) )
   2.299 -            l1e_add_flags(pte,_PAGE_USER);
   2.300 -        if ( !(dev_hst_ro_flags & GNTMAP_readonly) )
   2.301 -            l1e_add_flags(pte,_PAGE_RW);
   2.302 -
   2.303 -        if ( dev_hst_ro_flags & GNTMAP_contains_pte )
   2.304 -            rc = update_grant_pte_mapping(addr, pte, mapping_d, mapping_ed);
   2.305 -        else
   2.306 -            rc = update_grant_va_mapping(addr, pte, mapping_d, mapping_ed);
   2.307 -
   2.308 -        /* IMPORTANT: rc indicates the degree of TLB flush that is required.
   2.309 -         * GNTST_flush_one (1) or GNTST_flush_all (2). This is done in the 
   2.310 -         * outer gnttab_map_grant_ref. */
   2.311 -        if ( rc < 0 )
   2.312 -        {
   2.313 -            /* Failure: undo and abort. */
   2.314 -
   2.315 -            spin_lock(&granting_d->grant_table->lock);
   2.316 -
   2.317 -            if ( dev_hst_ro_flags & GNTMAP_readonly )
   2.318 -            {
   2.319 -                act->pin -= GNTPIN_hstr_inc;
   2.320 -            }
   2.321 -            else
   2.322 -            {
   2.323 -                act->pin -= GNTPIN_hstw_inc;
   2.324 -                if ( (act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) == 0 )
   2.325 -                {
   2.326 -                    clear_bit(_GTF_writing, &sha->flags);
   2.327 -                    put_page_type(&frame_table[frame]);
   2.328 -                }
   2.329 -            }
   2.330 -
   2.331 -            if ( act->pin == 0 )
   2.332 -            {
   2.333 -                clear_bit(_GTF_reading, &sha->flags);
   2.334 -                put_page(&frame_table[frame]);
   2.335 -            }
   2.336 -
   2.337 -            spin_unlock(&granting_d->grant_table->lock);
   2.338 -        }
   2.339 -
   2.340 -    }
   2.341 -#endif
   2.342 -
   2.343 -    *pframe = frame;
   2.344 -    return rc;
   2.345 -
   2.346 - unlock_out:
   2.347 -    spin_unlock(&granting_d->grant_table->lock);
   2.348 -    return rc;
   2.349 -}
   2.350 -
   2.351 -/*
   2.352 - * Returns 0 if TLB flush / invalidate required by caller.
   2.353 - * va will indicate the address to be invalidated.
   2.354 - * 
   2.355 - * addr is _either_ a host virtual address, or the address of the pte to
   2.356 - * update, as indicated by the GNTMAP_contains_pte flag.
   2.357 - */
   2.358 -static int
   2.359 -__gnttab_map_grant_ref(
   2.360 -    gnttab_map_grant_ref_t *uop,
   2.361 -    unsigned long *va)
   2.362 -{
   2.363 -    domid_t        dom;
   2.364 -    grant_ref_t    ref;
   2.365 -    struct domain *ld, *rd;
   2.366 -    struct vcpu   *led;
   2.367 -    u16            dev_hst_ro_flags;
   2.368 -    int            handle;
   2.369 -    u64            addr;
   2.370 -    unsigned long  frame = 0;
   2.371 -    int            rc;
   2.372 -
   2.373 -    led = current;
   2.374 -    ld = led->domain;
   2.375 -
   2.376 -    /* Bitwise-OR avoids short-circuiting which screws control flow. */
   2.377 -    if ( unlikely(__get_user(dom, &uop->dom) |
   2.378 -                  __get_user(ref, &uop->ref) |
   2.379 -                  __get_user(addr, &uop->host_addr) |
   2.380 -                  __get_user(dev_hst_ro_flags, &uop->flags)) )
   2.381 -    {
   2.382 -        DPRINTK("Fault while reading gnttab_map_grant_ref_t.\n");
   2.383 -        return -EFAULT; /* don't set status */
   2.384 -    }
   2.385 -
   2.386 -    if ( (dev_hst_ro_flags & GNTMAP_host_map) &&
   2.387 -         ( (addr == 0) ||
   2.388 -           (!(dev_hst_ro_flags & GNTMAP_contains_pte) && 
   2.389 -            unlikely(!__addr_ok(addr))) ) )
   2.390 -    {
   2.391 -        DPRINTK("Bad virtual address (%"PRIx64") or flags (%"PRIx16").\n",
   2.392 -                addr, dev_hst_ro_flags);
   2.393 -        (void)__put_user(GNTST_bad_virt_addr, &uop->handle);
   2.394 -        return GNTST_bad_gntref;
   2.395 -    }
   2.396 -
   2.397 -    if ( unlikely(ref >= NR_GRANT_ENTRIES) ||
   2.398 -         unlikely((dev_hst_ro_flags &
   2.399 -                   (GNTMAP_device_map|GNTMAP_host_map)) == 0) )
   2.400 -    {
   2.401 -        DPRINTK("Bad ref (%d) or flags (%x).\n", ref, dev_hst_ro_flags);
   2.402 -        (void)__put_user(GNTST_bad_gntref, &uop->handle);
   2.403 -        return GNTST_bad_gntref;
   2.404 -    }
   2.405 -
   2.406 -    if (acm_pre_grant_map_ref(dom)) {
   2.407 -        (void)__put_user(GNTST_permission_denied, &uop->handle);
   2.408 -        return GNTST_permission_denied;
   2.409 -    }
   2.410 -
   2.411 -    if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
   2.412 -         unlikely(ld == rd) )
   2.413 -    {
   2.414 -        if ( rd != NULL )
   2.415 -            put_domain(rd);
   2.416 -        DPRINTK("Could not find domain %d\n", dom);
   2.417 -        (void)__put_user(GNTST_bad_domain, &uop->handle);
   2.418 -        return GNTST_bad_domain;
   2.419 -    }
   2.420 -
   2.421 -    /* Get a maptrack handle. */
   2.422 -    if ( unlikely((handle = get_maptrack_handle(ld->grant_table)) == -1) )
   2.423 -    {
   2.424 -        int              i;
   2.425 -        grant_mapping_t *new_mt;
   2.426 -        grant_table_t   *lgt      = ld->grant_table;
   2.427 -
   2.428 -        if ( (lgt->maptrack_limit << 1) > MAPTRACK_MAX_ENTRIES )
   2.429 -        {
   2.430 -            put_domain(rd);
   2.431 -            DPRINTK("Maptrack table is at maximum size.\n");
   2.432 -            (void)__put_user(GNTST_no_device_space, &uop->handle);
   2.433 -            return GNTST_no_device_space;
   2.434 -        }
   2.435 -
   2.436 -        /* Grow the maptrack table. */
   2.437 -        new_mt = alloc_xenheap_pages(lgt->maptrack_order + 1);
   2.438 -        if ( new_mt == NULL )
   2.439 -        {
   2.440 -            put_domain(rd);
   2.441 -            DPRINTK("No more map handles available.\n");
   2.442 -            (void)__put_user(GNTST_no_device_space, &uop->handle);
   2.443 -            return GNTST_no_device_space;
   2.444 -        }
   2.445 -
   2.446 -        memcpy(new_mt, lgt->maptrack, PAGE_SIZE << lgt->maptrack_order);
   2.447 -        for ( i = lgt->maptrack_limit; i < (lgt->maptrack_limit << 1); i++ )
   2.448 -            new_mt[i].ref_and_flags = (i+1) << MAPTRACK_REF_SHIFT;
   2.449 -
   2.450 -        free_xenheap_pages(lgt->maptrack, lgt->maptrack_order);
   2.451 -        lgt->maptrack          = new_mt;
   2.452 -        lgt->maptrack_order   += 1;
   2.453 -        lgt->maptrack_limit  <<= 1;
   2.454 -
   2.455 -        DPRINTK("Doubled maptrack size\n");
   2.456 -        handle = get_maptrack_handle(ld->grant_table);
   2.457 -    }
   2.458 -
   2.459 -#if GRANT_DEBUG_VERBOSE
   2.460 -    DPRINTK("Mapping grant ref (%hu) for domain (%hu) with flags (%x)\n",
   2.461 -            ref, dom, dev_hst_ro_flags);
   2.462 -#endif
   2.463 -
   2.464 -    if ( 0 <= ( rc = __gnttab_activate_grant_ref( ld, led, rd, ref,
   2.465 -                                                  dev_hst_ro_flags,
   2.466 -                                                  addr, &frame)))
   2.467 -    {
   2.468 -        /*
   2.469 -         * Only make the maptrack live _after_ writing the pte, in case we 
   2.470 -         * overwrite the same frame number, causing a maptrack walk to find it
   2.471 -         */
   2.472 -        ld->grant_table->maptrack[handle].domid = dom;
   2.473 -
   2.474 -        ld->grant_table->maptrack[handle].ref_and_flags
   2.475 -            = (ref << MAPTRACK_REF_SHIFT) |
   2.476 -              (dev_hst_ro_flags & MAPTRACK_GNTMAP_MASK);
   2.477 -
   2.478 -        (void)__put_user((u64)frame << PAGE_SHIFT, &uop->dev_bus_addr);
   2.479 -
   2.480 -        if ( ( dev_hst_ro_flags & GNTMAP_host_map ) &&
   2.481 -             !( dev_hst_ro_flags & GNTMAP_contains_pte) )
   2.482 -            *va = addr;
   2.483 -
   2.484 -        (void)__put_user(handle, &uop->handle);
   2.485 -    }
   2.486 -    else
   2.487 -    {
   2.488 -        (void)__put_user(rc, &uop->handle);
   2.489 -        put_maptrack_handle(ld->grant_table, handle);
   2.490 -    }
   2.491 -
   2.492 -    put_domain(rd);
   2.493 -    return rc;
   2.494 -}
   2.495 -
   2.496 -static long
   2.497 -gnttab_map_grant_ref(
   2.498 -    gnttab_map_grant_ref_t *uop, unsigned int count)
   2.499 -{
   2.500 -    int i, rc, flush = 0;
   2.501 -    unsigned long va = 0;
   2.502 -
   2.503 -    for ( i = 0; i < count; i++ )
   2.504 -        if ( (rc =__gnttab_map_grant_ref(&uop[i], &va)) >= 0 )
   2.505 -            flush += rc;
   2.506 -
   2.507 -#ifdef __ia64__
   2.508 -// FIXME-ia64: probably need to do something here to avoid stale mappings?
   2.509 -#else
   2.510 -    if ( flush == 1 )
   2.511 -        flush_tlb_one_mask(current->domain->cpumask, va);
   2.512 -    else if ( flush != 0 ) 
   2.513 -        flush_tlb_mask(current->domain->cpumask);
   2.514 -#endif
   2.515 -
   2.516 -    return 0;
   2.517 -}
   2.518 -
   2.519 -static int
   2.520 -__gnttab_unmap_grant_ref(
   2.521 -    gnttab_unmap_grant_ref_t *uop,
   2.522 -    unsigned long *va)
   2.523 -{
   2.524 -    domid_t          dom;
   2.525 -    grant_ref_t      ref;
   2.526 -    u16              handle;
   2.527 -    struct domain   *ld, *rd;
   2.528 -    active_grant_entry_t *act;
   2.529 -    grant_entry_t   *sha;
   2.530 -    grant_mapping_t *map;
   2.531 -    u16              flags;
   2.532 -    s16              rc = 1;
   2.533 -    u64              addr, dev_bus_addr;
   2.534 -    unsigned long    frame;
   2.535 -
   2.536 -    ld = current->domain;
   2.537 -
   2.538 -    /* Bitwise-OR avoids short-circuiting which screws control flow. */
   2.539 -    if ( unlikely(__get_user(addr, &uop->host_addr) |
   2.540 -                  __get_user(dev_bus_addr, &uop->dev_bus_addr) |
   2.541 -                  __get_user(handle, &uop->handle)) )
   2.542 -    {
   2.543 -        DPRINTK("Fault while reading gnttab_unmap_grant_ref_t.\n");
   2.544 -        return -EFAULT; /* don't set status */
   2.545 -    }
   2.546 -
   2.547 -    frame = (unsigned long)(dev_bus_addr >> PAGE_SHIFT);
   2.548 -
   2.549 -    map = &ld->grant_table->maptrack[handle];
   2.550 -
   2.551 -    if ( unlikely(handle >= ld->grant_table->maptrack_limit) ||
   2.552 -         unlikely(!(map->ref_and_flags & MAPTRACK_GNTMAP_MASK)) )
   2.553 -    {
   2.554 -        DPRINTK("Bad handle (%d).\n", handle);
   2.555 -        (void)__put_user(GNTST_bad_handle, &uop->status);
   2.556 -        return GNTST_bad_handle;
   2.557 -    }
   2.558 -
   2.559 -    dom   = map->domid;
   2.560 -    ref   = map->ref_and_flags >> MAPTRACK_REF_SHIFT;
   2.561 -    flags = map->ref_and_flags & MAPTRACK_GNTMAP_MASK;
   2.562 -
   2.563 -    if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
   2.564 -         unlikely(ld == rd) )
   2.565 -    {
   2.566 -        if ( rd != NULL )
   2.567 -            put_domain(rd);
   2.568 -        DPRINTK("Could not find domain %d\n", dom);
   2.569 -        (void)__put_user(GNTST_bad_domain, &uop->status);
   2.570 -        return GNTST_bad_domain;
   2.571 -    }
   2.572 -
   2.573 -#if GRANT_DEBUG_VERBOSE
   2.574 -    DPRINTK("Unmapping grant ref (%hu) for domain (%hu) with handle (%hu)\n",
   2.575 -            ref, dom, handle);
   2.576 -#endif
   2.577 -
   2.578 -    act = &rd->grant_table->active[ref];
   2.579 -    sha = &rd->grant_table->shared[ref];
   2.580 -
   2.581 -    spin_lock(&rd->grant_table->lock);
   2.582 -
   2.583 -    if ( frame == 0 )
   2.584 -    {
   2.585 -        frame = act->frame;
   2.586 -    }
   2.587 -    else
   2.588 -    {
   2.589 -        if ( unlikely(frame != act->frame) )
   2.590 -            PIN_FAIL(unmap_out, GNTST_general_error,
   2.591 -                     "Bad frame number doesn't match gntref.\n");
   2.592 -        if ( flags & GNTMAP_device_map )
   2.593 -            act->pin -= (flags & GNTMAP_readonly) ? GNTPIN_devr_inc
   2.594 -                                                  : GNTPIN_devw_inc;
   2.595 -
   2.596 -        map->ref_and_flags &= ~GNTMAP_device_map;
   2.597 -        (void)__put_user(0, &uop->dev_bus_addr);
   2.598 -
   2.599 -        /* Frame is now unmapped for device access. */
   2.600 -    }
   2.601 -
   2.602 -    if ( (addr != 0) &&
   2.603 -         (flags & GNTMAP_host_map) &&
   2.604 -         ((act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask)) > 0))
   2.605 -    {
   2.606 -#ifdef __ia64__
   2.607 -// FIXME-ia64: any error checking need to be done here?
   2.608 -#else
   2.609 -        if ( flags & GNTMAP_contains_pte )
   2.610 -        {
   2.611 -            if ( (rc = clear_grant_pte_mapping(addr, frame, ld)) < 0 )
   2.612 -                goto unmap_out;
   2.613 -        }
   2.614 -        else
   2.615 -        {
   2.616 -            if ( (rc = clear_grant_va_mapping(addr, frame)) < 0 )
   2.617 -                goto unmap_out;
   2.618 -        }
   2.619 -#endif
   2.620 -
   2.621 -        map->ref_and_flags &= ~GNTMAP_host_map;
   2.622 -
   2.623 -        act->pin -= (flags & GNTMAP_readonly) ? GNTPIN_hstr_inc
   2.624 -                                              : GNTPIN_hstw_inc;
   2.625 -
   2.626 -        rc = 0;
   2.627 -        if ( !( flags & GNTMAP_contains_pte) )
   2.628 -            *va = addr;
   2.629 -    }
   2.630 -
   2.631 -    if ( (map->ref_and_flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0)
   2.632 -    {
   2.633 -        map->ref_and_flags = 0;
   2.634 -        put_maptrack_handle(ld->grant_table, handle);
   2.635 -    }
   2.636 -
   2.637 -#ifdef __ia64__
   2.638 -// FIXME-ia64: any error checking need to be done here?  I think not and then
   2.639 -//  this can probably be macro-ized into nothingness
   2.640 -#else
   2.641 -    /* If just unmapped a writable mapping, mark as dirtied */
   2.642 -    if ( unlikely(shadow_mode_log_dirty(rd)) &&
   2.643 -        !( flags & GNTMAP_readonly ) )
   2.644 -         mark_dirty(rd, frame);
   2.645 -#endif
   2.646 -
   2.647 -    /* If the last writable mapping has been removed, put_page_type */
   2.648 -    if ( ( (act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask) ) == 0) &&
   2.649 -         ( !( flags & GNTMAP_readonly ) ) )
   2.650 -    {
   2.651 -        clear_bit(_GTF_writing, &sha->flags);
   2.652 -        put_page_type(&frame_table[frame]);
   2.653 -    }
   2.654 -
   2.655 -    if ( act->pin == 0 )
   2.656 -    {
   2.657 -        act->frame = 0xdeadbeef;
   2.658 -        clear_bit(_GTF_reading, &sha->flags);
   2.659 -        put_page(&frame_table[frame]);
   2.660 -    }
   2.661 -
   2.662 - unmap_out:
   2.663 -    (void)__put_user(rc, &uop->status);
   2.664 -    spin_unlock(&rd->grant_table->lock);
   2.665 -    put_domain(rd);
   2.666 -    return rc;
   2.667 -}
   2.668 -
   2.669 -static long
   2.670 -gnttab_unmap_grant_ref(
   2.671 -    gnttab_unmap_grant_ref_t *uop, unsigned int count)
   2.672 -{
   2.673 -    int i, flush = 0;
   2.674 -    unsigned long va = 0;
   2.675 -
   2.676 -    for ( i = 0; i < count; i++ )
   2.677 -        if ( __gnttab_unmap_grant_ref(&uop[i], &va) == 0 )
   2.678 -            flush++;
   2.679 -
   2.680 -#ifdef __ia64__
   2.681 -// FIXME-ia64: probably need to do something here to avoid stale mappings?
   2.682 -#else
   2.683 -    if ( flush == 1 )
   2.684 -        flush_tlb_one_mask(current->domain->cpumask, va);
   2.685 -    else if ( flush != 0 ) 
   2.686 -        flush_tlb_mask(current->domain->cpumask);
   2.687 -#endif
   2.688 -
   2.689 -    return 0;
   2.690 -}
   2.691 -
   2.692 -static long 
   2.693 -gnttab_setup_table(
   2.694 -    gnttab_setup_table_t *uop, unsigned int count)
   2.695 -{
   2.696 -    gnttab_setup_table_t  op;
   2.697 -    struct domain        *d;
   2.698 -    int                   i;
   2.699 -
   2.700 -    if ( count != 1 )
   2.701 -        return -EINVAL;
   2.702 -
   2.703 -    if ( unlikely(copy_from_user(&op, uop, sizeof(op)) != 0) )
   2.704 -    {
   2.705 -        DPRINTK("Fault while reading gnttab_setup_table_t.\n");
   2.706 -        return -EFAULT;
   2.707 -    }
   2.708 -
   2.709 -    if ( unlikely(op.nr_frames > NR_GRANT_FRAMES) )
   2.710 -    {
   2.711 -        DPRINTK("Xen only supports up to %d grant-table frames per domain.\n",
   2.712 -                NR_GRANT_FRAMES);
   2.713 -        (void)put_user(GNTST_general_error, &uop->status);
   2.714 -        return 0;
   2.715 -    }
   2.716 -
   2.717 -    if ( op.dom == DOMID_SELF )
   2.718 -    {
   2.719 -        op.dom = current->domain->domain_id;
   2.720 -    }
   2.721 -    else if ( unlikely(!IS_PRIV(current->domain)) )
   2.722 -    {
   2.723 -        (void)put_user(GNTST_permission_denied, &uop->status);
   2.724 -        return 0;
   2.725 -    }
   2.726 -
   2.727 -    if ( unlikely((d = find_domain_by_id(op.dom)) == NULL) )
   2.728 -    {
   2.729 -        DPRINTK("Bad domid %d.\n", op.dom);
   2.730 -        (void)put_user(GNTST_bad_domain, &uop->status);
   2.731 -        return 0;
   2.732 -    }
   2.733 -
   2.734 -    if ( op.nr_frames <= NR_GRANT_FRAMES )
   2.735 -    {
   2.736 -        ASSERT(d->grant_table != NULL);
   2.737 -        (void)put_user(GNTST_okay, &uop->status);
   2.738 -#ifdef __ia64__
   2.739 -	if (d == dom0) {
   2.740 -            for ( i = 0; i < op.nr_frames; i++ )
   2.741 -                (void)put_user(
   2.742 -                    (virt_to_phys(d->grant_table->shared) >> PAGE_SHIFT) + i,
   2.743 -                    &uop->frame_list[i]);
   2.744 -	} else {
   2.745 -            /* IA64 hack - need to map it somewhere */
   2.746 -            unsigned long addr = (1UL << 40);
   2.747 -            map_domain_page(d, addr, virt_to_phys(d->grant_table->shared));
   2.748 -            (void)put_user(addr >> PAGE_SHIFT, &uop->frame_list[0]);
   2.749 -        }
   2.750 -#else
   2.751 -        for ( i = 0; i < op.nr_frames; i++ )
   2.752 -            (void)put_user(
   2.753 -                (virt_to_phys(d->grant_table->shared) >> PAGE_SHIFT) + i,
   2.754 -                &uop->frame_list[i]);
   2.755 -#endif
   2.756 -    }
   2.757 -
   2.758 -    put_domain(d);
   2.759 -    return 0;
   2.760 -}
   2.761 -
   2.762 -#if GRANT_DEBUG
   2.763 -static int
   2.764 -gnttab_dump_table(gnttab_dump_table_t *uop)
   2.765 -{
   2.766 -    grant_table_t        *gt;
   2.767 -    gnttab_dump_table_t   op;
   2.768 -    struct domain        *d;
   2.769 -    u32                   shared_mfn;
   2.770 -    active_grant_entry_t *act;
   2.771 -    grant_entry_t         sha_copy;
   2.772 -    grant_mapping_t      *maptrack;
   2.773 -    int                   i;
   2.774 -
   2.775 -
   2.776 -    if ( unlikely(copy_from_user(&op, uop, sizeof(op)) != 0) )
   2.777 -    {
   2.778 -        DPRINTK("Fault while reading gnttab_dump_table_t.\n");
   2.779 -        return -EFAULT;
   2.780 -    }
   2.781 -
   2.782 -    if ( op.dom == DOMID_SELF )
   2.783 -    {
   2.784 -        op.dom = current->domain->domain_id;
   2.785 -    }
   2.786 -
   2.787 -    if ( unlikely((d = find_domain_by_id(op.dom)) == NULL) )
   2.788 -    {
   2.789 -        DPRINTK("Bad domid %d.\n", op.dom);
   2.790 -        (void)put_user(GNTST_bad_domain, &uop->status);
   2.791 -        return 0;
   2.792 -    }
   2.793 -
   2.794 -    ASSERT(d->grant_table != NULL);
   2.795 -    gt = d->grant_table;
   2.796 -    (void)put_user(GNTST_okay, &uop->status);
   2.797 -
   2.798 -    shared_mfn = virt_to_phys(d->grant_table->shared);
   2.799 -
   2.800 -    DPRINTK("Grant table for dom (%hu) MFN (%x)\n",
   2.801 -            op.dom, shared_mfn);
   2.802 -
   2.803 -    ASSERT(d->grant_table->active != NULL);
   2.804 -    ASSERT(d->grant_table->shared != NULL);
   2.805 -    ASSERT(d->grant_table->maptrack != NULL);
   2.806 -
   2.807 -    for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
   2.808 -    {
   2.809 -        sha_copy =  gt->shared[i];
   2.810 -
   2.811 -        if ( sha_copy.flags )
   2.812 -        {
   2.813 -            DPRINTK("Grant: dom (%hu) SHARED (%d) flags:(%hx) "
   2.814 -                    "dom:(%hu) frame:(%x)\n",
   2.815 -                    op.dom, i, sha_copy.flags, sha_copy.domid, sha_copy.frame);
   2.816 -        }
   2.817 -    }
   2.818 -
   2.819 -    spin_lock(&gt->lock);
   2.820 -
   2.821 -    for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
   2.822 -    {
   2.823 -        act = &gt->active[i];
   2.824 -
   2.825 -        if ( act->pin )
   2.826 -        {
   2.827 -            DPRINTK("Grant: dom (%hu) ACTIVE (%d) pin:(%x) "
   2.828 -                    "dom:(%hu) frame:(%lx)\n",
   2.829 -                    op.dom, i, act->pin, act->domid, act->frame);
   2.830 -        }
   2.831 -    }
   2.832 -
   2.833 -    for ( i = 0; i < gt->maptrack_limit; i++ )
   2.834 -    {
   2.835 -        maptrack = &gt->maptrack[i];
   2.836 -
   2.837 -        if ( maptrack->ref_and_flags & MAPTRACK_GNTMAP_MASK )
   2.838 -        {
   2.839 -            DPRINTK("Grant: dom (%hu) MAP (%d) ref:(%hu) flags:(%x) "
   2.840 -                    "dom:(%hu)\n",
   2.841 -                    op.dom, i,
   2.842 -                    maptrack->ref_and_flags >> MAPTRACK_REF_SHIFT,
   2.843 -                    maptrack->ref_and_flags & MAPTRACK_GNTMAP_MASK,
   2.844 -                    maptrack->domid);
   2.845 -        }
   2.846 -    }
   2.847 -
   2.848 -    spin_unlock(&gt->lock);
   2.849 -
   2.850 -    put_domain(d);
   2.851 -    return 0;
   2.852 -}
   2.853 -#endif
   2.854 -
   2.855 -static long
   2.856 -gnttab_transfer(gnttab_transfer_t *uop, unsigned int count)
   2.857 -{
   2.858 -    struct domain *d = current->domain;
   2.859 -    struct domain *e;
   2.860 -    struct pfn_info *page;
   2.861 -    u32 _d, _nd, x, y;
   2.862 -    int i;
   2.863 -    int result = GNTST_okay;
   2.864 -
   2.865 -#ifdef __ia64__
   2.866 -//FIXME-IA64: not support for now?
   2.867 -    return GNTST_general_error;
   2.868 -#else
   2.869 -    for (i = 0; i < count; i++) {
   2.870 -        gnttab_transfer_t *gop = &uop[i];
   2.871 -#if GRANT_DEBUG
   2.872 -        printk("gnttab_transfer: i=%d mfn=%lx domid=%d gref=%08x\n",
   2.873 -               i, gop->mfn, gop->domid, gop->handle);
   2.874 -#endif
   2.875 -        page = &frame_table[gop->mfn];
   2.876 -        
   2.877 -        if (unlikely(IS_XEN_HEAP_FRAME(page))) { 
   2.878 -            printk("gnttab_transfer: xen heap frame mfn=%lx\n", 
   2.879 -                   (unsigned long) gop->mfn);
   2.880 -            gop->status = GNTST_bad_virt_addr;
   2.881 -            continue;
   2.882 -        }
   2.883 -        if (unlikely(!pfn_valid(page_to_pfn(page)))) {
   2.884 -            printk("gnttab_transfer: invalid pfn for mfn=%lx\n", 
   2.885 -                   (unsigned long) gop->mfn);
   2.886 -            gop->status = GNTST_bad_virt_addr;
   2.887 -            continue;
   2.888 -        }
   2.889 -        if (unlikely((e = find_domain_by_id(gop->domid)) == NULL)) {
   2.890 -            printk("gnttab_transfer: can't find domain %d\n", gop->domid);
   2.891 -            gop->status = GNTST_bad_domain;
   2.892 -            continue;
   2.893 -        }
   2.894 -
   2.895 -        spin_lock(&d->page_alloc_lock);
   2.896 -
   2.897 -        /*
   2.898 -         * The tricky bit: atomically release ownership while
   2.899 -         * there is just one benign reference to the page
   2.900 -         * (PGC_allocated). If that reference disappears then the
   2.901 -         * deallocation routine will safely spin.
   2.902 -         */
   2.903 -        _d  = pickle_domptr(d);
   2.904 -        _nd = page->u.inuse._domain;
   2.905 -        y   = page->count_info;
   2.906 -        do {
   2.907 -            x = y;
   2.908 -            if (unlikely((x & (PGC_count_mask|PGC_allocated)) !=
   2.909 -                         (1 | PGC_allocated)) || unlikely(_nd != _d)) {
   2.910 -                printk("gnttab_transfer: Bad page values %p: ed=%p(%u), sd=%p,"
   2.911 -                       " caf=%08x, taf=%" PRtype_info "\n", 
   2.912 -                       (void *) page_to_pfn(page),
   2.913 -                        d, d->domain_id, unpickle_domptr(_nd), x, 
   2.914 -                        page->u.inuse.type_info);
   2.915 -                spin_unlock(&d->page_alloc_lock);
   2.916 -                put_domain(e);
   2.917 -                return 0;
   2.918 -            }
   2.919 -            __asm__ __volatile__(
   2.920 -                LOCK_PREFIX "cmpxchg8b %2"
   2.921 -                : "=d" (_nd), "=a" (y),
   2.922 -                "=m" (*(volatile u64 *)(&page->count_info))
   2.923 -                : "0" (_d), "1" (x), "c" (NULL), "b" (x) );
   2.924 -        } while (unlikely(_nd != _d) || unlikely(y != x));
   2.925 -
   2.926 -        /*
   2.927 -         * Unlink from 'd'. At least one reference remains (now
   2.928 -         * anonymous), so noone else is spinning to try to delete
   2.929 -         * this page from 'd'.
   2.930 -         */
   2.931 -        d->tot_pages--;
   2.932 -        list_del(&page->list);
   2.933 -
   2.934 -        spin_unlock(&d->page_alloc_lock);
   2.935 -
   2.936 -        spin_lock(&e->page_alloc_lock);
   2.937 -
   2.938 -        /*
   2.939 -         * Check that 'e' will accept the page and has reservation
   2.940 -         * headroom.  Also, a domain mustn't have PGC_allocated
   2.941 -         * pages when it is dying.
   2.942 -         */
   2.943 -#ifdef GRANT_DEBUG
   2.944 -        if (unlikely(e->tot_pages >= e->max_pages)) {
   2.945 -            printk("gnttab_dontate: no headroom tot_pages=%d max_pages=%d\n",
   2.946 -                   e->tot_pages, e->max_pages);
   2.947 -            spin_unlock(&e->page_alloc_lock);
   2.948 -            put_domain(e);
   2.949 -            result = GNTST_general_error;
   2.950 -            break;
   2.951 -        }
   2.952 -        if (unlikely(test_bit(DOMFLAGS_DYING, &e->domain_flags))) {
   2.953 -            printk("gnttab_transfer: target domain is dying\n");
   2.954 -            spin_unlock(&e->page_alloc_lock);
   2.955 -            put_domain(e);
   2.956 -            result = GNTST_general_error;
   2.957 -            break;
   2.958 -        }
   2.959 -        if (unlikely(!gnttab_prepare_for_transfer(e, d, gop->ref))) {
   2.960 -            printk("gnttab_transfer: gnttab_prepare_for_transfer fails\n");
   2.961 -            spin_unlock(&e->page_alloc_lock);
   2.962 -            put_domain(e);
   2.963 -            result = GNTST_general_error;
   2.964 -            break;
   2.965 -        }
   2.966 -#else
   2.967 -        ASSERT(e->tot_pages <= e->max_pages);
   2.968 -        if (unlikely(test_bit(DOMFLAGS_DYING, &e->domain_flags)) ||
   2.969 -            unlikely(e->tot_pages == e->max_pages) ||
   2.970 -            unlikely(!gnttab_prepare_for_transfer(e, d, gop->ref))) {
   2.971 -            printk("gnttab_transfer: Transferee has no reservation headroom (%d,"
   2.972 -                   "%d) or provided a bad grant ref (%08x) or is dying (%p)\n",
   2.973 -                   e->tot_pages, e->max_pages, gop->ref, e->d_flags);
   2.974 -            spin_unlock(&e->page_alloc_lock);
   2.975 -            put_domain(e);
   2.976 -            result = GNTST_general_error;
   2.977 -            break;
   2.978 -        }
   2.979 -#endif
   2.980 -        /* Okay, add the page to 'e'. */
   2.981 -        if (unlikely(e->tot_pages++ == 0)) {
   2.982 -            get_knownalive_domain(e);
   2.983 -        }
   2.984 -        list_add_tail(&page->list, &e->page_list);
   2.985 -        page_set_owner(page, e);
   2.986 -        
   2.987 -        spin_unlock(&e->page_alloc_lock);
   2.988 -        
   2.989 -        /*
   2.990 -         * Transfer is all done: tell the guest about its new page
   2.991 -         * frame.
   2.992 -         */
   2.993 -        gnttab_notify_transfer(e, d, gop->ref, gop->mfn);
   2.994 -        
   2.995 -        put_domain(e);
   2.996 -        
   2.997 -        gop->status = GNTST_okay;
   2.998 -    }
   2.999 -    return result;
  2.1000 -#endif
  2.1001 -}
  2.1002 -
  2.1003 -long 
  2.1004 -do_grant_table_op(
  2.1005 -    unsigned int cmd, void *uop, unsigned int count)
  2.1006 -{
  2.1007 -    long rc;
  2.1008 -    struct domain *d = current->domain;
  2.1009 -    
  2.1010 -    if ( count > 512 )
  2.1011 -        return -EINVAL;
  2.1012 -    
  2.1013 -    LOCK_BIGLOCK(d);
  2.1014 -    
  2.1015 -#ifndef __ia64__
  2.1016 -    sync_pagetable_state(d);
  2.1017 -#endif
  2.1018 -    
  2.1019 -    rc = -EFAULT;
  2.1020 -    switch ( cmd )
  2.1021 -        {
  2.1022 -        case GNTTABOP_map_grant_ref:
  2.1023 -            if ( unlikely(!array_access_ok(
  2.1024 -                              uop, count, sizeof(gnttab_map_grant_ref_t))) )
  2.1025 -                goto out;
  2.1026 -            rc = gnttab_map_grant_ref((gnttab_map_grant_ref_t *)uop, count);
  2.1027 -            break;
  2.1028 -        case GNTTABOP_unmap_grant_ref:
  2.1029 -            if ( unlikely(!array_access_ok(
  2.1030 -                              uop, count, sizeof(gnttab_unmap_grant_ref_t))) )
  2.1031 -                goto out;
  2.1032 -            rc = gnttab_unmap_grant_ref((gnttab_unmap_grant_ref_t *)uop, 
  2.1033 -                                        count);
  2.1034 -            break;
  2.1035 -        case GNTTABOP_setup_table:
  2.1036 -            rc = gnttab_setup_table((gnttab_setup_table_t *)uop, count);
  2.1037 -            break;
  2.1038 -#if GRANT_DEBUG
  2.1039 -        case GNTTABOP_dump_table:
  2.1040 -            rc = gnttab_dump_table((gnttab_dump_table_t *)uop);
  2.1041 -            break;
  2.1042 -#endif
  2.1043 -        case GNTTABOP_transfer:
  2.1044 -            if (unlikely(!array_access_ok(uop, count, 
  2.1045 -                                          sizeof(gnttab_transfer_t))))
  2.1046 -                goto out;
  2.1047 -            rc = gnttab_transfer(uop, count);
  2.1048 -            break;
  2.1049 -        default:
  2.1050 -            rc = -ENOSYS;
  2.1051 -            break;
  2.1052 -        }
  2.1053 -    
  2.1054 -  out:
  2.1055 -    UNLOCK_BIGLOCK(d);
  2.1056 -    
  2.1057 -    return rc;
  2.1058 -}
  2.1059 -
  2.1060 -int 
  2.1061 -gnttab_prepare_for_transfer(
  2.1062 -    struct domain *rd, struct domain *ld, grant_ref_t ref)
  2.1063 -{
  2.1064 -    grant_table_t *rgt;
  2.1065 -    grant_entry_t *sha;
  2.1066 -    domid_t        sdom;
  2.1067 -    u16            sflags;
  2.1068 -    u32            scombo, prev_scombo;
  2.1069 -    int            retries = 0;
  2.1070 -    unsigned long  target_pfn;
  2.1071 -
  2.1072 -#if GRANT_DEBUG_VERBOSE
  2.1073 -    DPRINTK("gnttab_prepare_for_transfer rd(%hu) ld(%hu) ref(%hu).\n",
  2.1074 -            rd->domain_id, ld->domain_id, ref);
  2.1075 -#endif
  2.1076 -
  2.1077 -    if ( unlikely((rgt = rd->grant_table) == NULL) ||
  2.1078 -         unlikely(ref >= NR_GRANT_ENTRIES) )
  2.1079 -    {
  2.1080 -        DPRINTK("Dom %d has no g.t., or ref is bad (%d).\n",
  2.1081 -                rd->domain_id, ref);
  2.1082 -        return 0;
  2.1083 -    }
  2.1084 -
  2.1085 -    spin_lock(&rgt->lock);
  2.1086 -
  2.1087 -    sha = &rgt->shared[ref];
  2.1088 -    
  2.1089 -    sflags = sha->flags;
  2.1090 -    sdom   = sha->domid;
  2.1091 -
  2.1092 -    for ( ; ; )
  2.1093 -    {
  2.1094 -        target_pfn = sha->frame;
  2.1095 -
  2.1096 -        if ( unlikely(target_pfn >= max_page ) )
  2.1097 -        {
  2.1098 -            DPRINTK("Bad pfn (%lx)\n", target_pfn);
  2.1099 -            goto fail;
  2.1100 -        }
  2.1101 -
  2.1102 -        if ( unlikely(sflags != GTF_accept_transfer) ||
  2.1103 -             unlikely(sdom != ld->domain_id) )
  2.1104 -        {
  2.1105 -            DPRINTK("Bad flags (%x) or dom (%d). (NB. expected dom %d)\n",
  2.1106 -                    sflags, sdom, ld->domain_id);
  2.1107 -            goto fail;
  2.1108 -        }
  2.1109 -
  2.1110 -        /* Merge two 16-bit values into a 32-bit combined update. */
  2.1111 -        /* NB. Endianness! */
  2.1112 -        prev_scombo = scombo = ((u32)sdom << 16) | (u32)sflags;
  2.1113 -
  2.1114 -        /* NB. prev_scombo is updated in place to seen value. */
  2.1115 -        if ( unlikely(cmpxchg_user((u32 *)&sha->flags, prev_scombo, 
  2.1116 -                                   prev_scombo | GTF_transfer_committed)) )
  2.1117 -        {
  2.1118 -            DPRINTK("Fault while modifying shared flags and domid.\n");
  2.1119 -            goto fail;
  2.1120 -        }
  2.1121 -
  2.1122 -        /* Did the combined update work (did we see what we expected?). */
  2.1123 -        if ( likely(prev_scombo == scombo) )
  2.1124 -            break;
  2.1125 -
  2.1126 -        if ( retries++ == 4 )
  2.1127 -        {
  2.1128 -            DPRINTK("Shared grant entry is unstable.\n");
  2.1129 -            goto fail;
  2.1130 -        }
  2.1131 -
  2.1132 -        /* Didn't see what we expected. Split out the seen flags & dom. */
  2.1133 -        /* NB. Endianness! */
  2.1134 -        sflags = (u16)prev_scombo;
  2.1135 -        sdom   = (u16)(prev_scombo >> 16);
  2.1136 -    }
  2.1137 -
  2.1138 -    spin_unlock(&rgt->lock);
  2.1139 -    return 1;
  2.1140 -
  2.1141 - fail:
  2.1142 -    spin_unlock(&rgt->lock);
  2.1143 -    return 0;
  2.1144 -}
  2.1145 -
  2.1146 -void 
  2.1147 -gnttab_notify_transfer(
  2.1148 -    struct domain *rd, struct domain *ld, grant_ref_t ref, unsigned long frame)
  2.1149 -{
  2.1150 -    grant_entry_t  *sha;
  2.1151 -    unsigned long   pfn;
  2.1152 -
  2.1153 -#if GRANT_DEBUG_VERBOSE
  2.1154 -    DPRINTK("gnttab_notify_transfer rd(%hu) ld(%hu) ref(%hu).\n",
  2.1155 -            rd->domain_id, ld->domain_id, ref);
  2.1156 -#endif
  2.1157 -
  2.1158 -    sha = &rd->grant_table->shared[ref];
  2.1159 -
  2.1160 -    spin_lock(&rd->grant_table->lock);
  2.1161 -
  2.1162 -#ifdef __ia64__
  2.1163 -// FIXME-ia64: any error checking need to be done here?
  2.1164 -#else
  2.1165 -    pfn = sha->frame;
  2.1166 -
  2.1167 -    if ( unlikely(pfn >= max_page ) )
  2.1168 -        DPRINTK("Bad pfn (%lx)\n", pfn);
  2.1169 -    else
  2.1170 -    {
  2.1171 -        machine_to_phys_mapping[frame] = pfn;
  2.1172 -
  2.1173 -        if ( unlikely(shadow_mode_log_dirty(ld)))
  2.1174 -             mark_dirty(ld, frame);
  2.1175 -
  2.1176 -        if (shadow_mode_translate(ld))
  2.1177 -            __phys_to_machine_mapping[pfn] = frame;
  2.1178 -    }
  2.1179 -#endif
  2.1180 -    sha->frame = __mfn_to_gpfn(rd, frame);
  2.1181 -    sha->domid = rd->domain_id;
  2.1182 -    wmb();
  2.1183 -    sha->flags = ( GTF_accept_transfer | GTF_transfer_completed );
  2.1184 -
  2.1185 -    spin_unlock(&rd->grant_table->lock);
  2.1186 -
  2.1187 -    return;
  2.1188 -}
  2.1189 -
  2.1190 -int 
  2.1191 -grant_table_create(
  2.1192 -    struct domain *d)
  2.1193 -{
  2.1194 -    grant_table_t *t;
  2.1195 -    int            i;
  2.1196 -
  2.1197 -    if ( (t = xmalloc(grant_table_t)) == NULL )
  2.1198 -        goto no_mem;
  2.1199 -
  2.1200 -    /* Simple stuff. */
  2.1201 -    memset(t, 0, sizeof(*t));
  2.1202 -    spin_lock_init(&t->lock);
  2.1203 -
  2.1204 -    /* Active grant table. */
  2.1205 -    if ( (t->active = xmalloc_array(active_grant_entry_t, NR_GRANT_ENTRIES))
  2.1206 -         == NULL )
  2.1207 -        goto no_mem;
  2.1208 -    memset(t->active, 0, sizeof(active_grant_entry_t) * NR_GRANT_ENTRIES);
  2.1209 -
  2.1210 -    /* Tracking of mapped foreign frames table */
  2.1211 -    if ( (t->maptrack = alloc_xenheap_page()) == NULL )
  2.1212 -        goto no_mem;
  2.1213 -    t->maptrack_order = 0;
  2.1214 -    t->maptrack_limit = PAGE_SIZE / sizeof(grant_mapping_t);
  2.1215 -    memset(t->maptrack, 0, PAGE_SIZE);
  2.1216 -    for ( i = 0; i < t->maptrack_limit; i++ )
  2.1217 -        t->maptrack[i].ref_and_flags = (i+1) << MAPTRACK_REF_SHIFT;
  2.1218 -
  2.1219 -    /* Shared grant table. */
  2.1220 -    t->shared = alloc_xenheap_pages(ORDER_GRANT_FRAMES);
  2.1221 -    if ( t->shared == NULL )
  2.1222 -        goto no_mem;
  2.1223 -    memset(t->shared, 0, NR_GRANT_FRAMES * PAGE_SIZE);
  2.1224 -
  2.1225 -#ifdef __ia64__
  2.1226 -// I don't think there's anything to do here on ia64?...
  2.1227 -#else
  2.1228 -    for ( i = 0; i < NR_GRANT_FRAMES; i++ )
  2.1229 -    {
  2.1230 -        SHARE_PFN_WITH_DOMAIN(
  2.1231 -            virt_to_page((char *)(t->shared)+(i*PAGE_SIZE)), d);
  2.1232 -        machine_to_phys_mapping[(virt_to_phys(t->shared) >> PAGE_SHIFT) + i] =
  2.1233 -            INVALID_M2P_ENTRY;
  2.1234 -    }
  2.1235 -#endif
  2.1236 -
  2.1237 -    /* Okay, install the structure. */
  2.1238 -    wmb(); /* avoid races with lock-free access to d->grant_table */
  2.1239 -    d->grant_table = t;
  2.1240 -    return 0;
  2.1241 -
  2.1242 - no_mem:
  2.1243 -    if ( t != NULL )
  2.1244 -    {
  2.1245 -        xfree(t->active);
  2.1246 -        free_xenheap_page(t->maptrack);
  2.1247 -        xfree(t);
  2.1248 -    }
  2.1249 -    return -ENOMEM;
  2.1250 -}
  2.1251 -
  2.1252 -void
  2.1253 -gnttab_release_mappings(
  2.1254 -    struct domain *ld)
  2.1255 -{
  2.1256 -    grant_table_t          *gt = ld->grant_table;
  2.1257 -    grant_mapping_t        *map;
  2.1258 -    domid_t                 dom;
  2.1259 -    grant_ref_t             ref;
  2.1260 -    u16                     handle;
  2.1261 -    struct domain          *ld, *rd;
  2.1262 -    unsigned long           frame;
  2.1263 -    active_grant_entry_t   *act;
  2.1264 -    grant_entry_t          *sha;
  2.1265 -
  2.1266 -    for ( handle = 0; handle < gt->maptrack_limit; handle++ )
  2.1267 -    {
  2.1268 -        map = &gt->maptrack[handle];
  2.1269 -
  2.1270 -        if ( map->ref_and_flags & GNTMAP_device_map )
  2.1271 -        {
  2.1272 -            dom = map->domid;
  2.1273 -            ref = map->ref_and_flags >> MAPTRACK_REF_SHIFT;
  2.1274 -
  2.1275 -            DPRINTK("Grant release (%hu) ref:(%hu) flags:(%x) dom:(%hu)\n",
  2.1276 -                    handle, ref,
  2.1277 -                    map->ref_and_flags & MAPTRACK_GNTMAP_MASK, dom);
  2.1278 -
  2.1279 -            if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
  2.1280 -                 unlikely(ld == rd) )
  2.1281 -            {
  2.1282 -                if ( rd != NULL )
  2.1283 -                    put_domain(rd);
  2.1284 -
  2.1285 -                printk(KERN_WARNING "Grant release: No dom%d\n", dom);
  2.1286 -                continue;
  2.1287 -            }
  2.1288 -
  2.1289 -            act = &rd->grant_table->active[ref];
  2.1290 -            sha = &rd->grant_table->shared[ref];
  2.1291 -
  2.1292 -            spin_lock(&rd->grant_table->lock);
  2.1293 -
  2.1294 -            if ( act->pin & (GNTPIN_devw_mask | GNTPIN_devr_mask) )
  2.1295 -            {
  2.1296 -                frame = act->frame;
  2.1297 -
  2.1298 -                if ( ( (act->pin & GNTPIN_hstw_mask) == 0 ) &&
  2.1299 -                     ( (act->pin & GNTPIN_devw_mask) >  0 ) )
  2.1300 -                {
  2.1301 -                    clear_bit(_GTF_writing, &sha->flags);
  2.1302 -                    put_page_type(&frame_table[frame]);
  2.1303 -                }
  2.1304 -
  2.1305 -                act->pin &= ~(GNTPIN_devw_mask | GNTPIN_devr_mask);
  2.1306 -
  2.1307 -                if ( act->pin == 0 )
  2.1308 -                {
  2.1309 -                    clear_bit(_GTF_reading, &sha->flags);
  2.1310 -                    map->ref_and_flags = 0;
  2.1311 -                    put_page(&frame_table[frame]);
  2.1312 -                }
  2.1313 -                else
  2.1314 -                    map->ref_and_flags &= ~GNTMAP_device_map;
  2.1315 -            }
  2.1316 -
  2.1317 -            spin_unlock(&rd->grant_table->lock);
  2.1318 -
  2.1319 -            put_domain(rd);
  2.1320 -        }
  2.1321 -    }
  2.1322 -}
  2.1323 -
  2.1324 -
  2.1325 -void
  2.1326 -grant_table_destroy(
  2.1327 -    struct domain *d)
  2.1328 -{
  2.1329 -    grant_table_t *t;
  2.1330 -
  2.1331 -    if ( (t = d->grant_table) != NULL )
  2.1332 -    {
  2.1333 -        /* Free memory relating to this grant table. */
  2.1334 -        d->grant_table = NULL;
  2.1335 -        free_xenheap_pages(t->shared, ORDER_GRANT_FRAMES);
  2.1336 -        free_xenheap_page(t->maptrack);
  2.1337 -        xfree(t->active);
  2.1338 -        xfree(t);
  2.1339 -    }
  2.1340 -}
  2.1341 -
  2.1342 -void
  2.1343 -grant_table_init(
  2.1344 -    void)
  2.1345 -{
  2.1346 -    /* Nothing. */
  2.1347 -}
  2.1348 -
  2.1349 -/*
  2.1350 - * Local variables:
  2.1351 - * mode: C
  2.1352 - * c-set-style: "BSD"
  2.1353 - * c-basic-offset: 4
  2.1354 - * tab-width: 4
  2.1355 - * indent-tabs-mode: nil
  2.1356 - * End:
  2.1357 - */
     3.1 --- a/xen/arch/x86/mm.c	Wed Nov 23 13:38:34 2005 +0100
     3.2 +++ b/xen/arch/x86/mm.c	Wed Nov 23 13:50:14 2005 +0100
     3.3 @@ -2306,7 +2306,7 @@ int do_mmu_update(
     3.4  }
     3.5  
     3.6  
     3.7 -int update_grant_pte_mapping(
     3.8 +static int create_grant_pte_mapping(
     3.9      unsigned long pte_addr, l1_pgentry_t _nl1e, struct vcpu *v)
    3.10  {
    3.11      int rc = GNTST_okay;
    3.12 @@ -2368,7 +2368,7 @@ int update_grant_pte_mapping(
    3.13      return rc;
    3.14  }
    3.15  
    3.16 -int clear_grant_pte_mapping(
    3.17 +static int destroy_grant_pte_mapping(
    3.18      unsigned long addr, unsigned long frame, struct domain *d)
    3.19  {
    3.20      int rc = GNTST_okay;
    3.21 @@ -2445,7 +2445,7 @@ int clear_grant_pte_mapping(
    3.22  }
    3.23  
    3.24  
    3.25 -int update_grant_va_mapping(
    3.26 +static int create_grant_va_mapping(
    3.27      unsigned long va, l1_pgentry_t _nl1e, struct vcpu *v)
    3.28  {
    3.29      l1_pgentry_t *pl1e, ol1e;
    3.30 @@ -2475,7 +2475,8 @@ int update_grant_va_mapping(
    3.31      return GNTST_okay;
    3.32  }
    3.33  
    3.34 -int clear_grant_va_mapping(unsigned long addr, unsigned long frame)
    3.35 +static int destroy_grant_va_mapping(
    3.36 +    unsigned long addr, unsigned long frame)
    3.37  {
    3.38      l1_pgentry_t *pl1e, ol1e;
    3.39      
    3.40 @@ -2508,6 +2509,74 @@ int clear_grant_va_mapping(unsigned long
    3.41      return 0;
    3.42  }
    3.43  
    3.44 +int create_grant_host_mapping(
    3.45 +    unsigned long addr, unsigned long frame, unsigned int flags)
    3.46 +{
    3.47 +    l1_pgentry_t pte = l1e_from_pfn(frame, GRANT_PTE_FLAGS);
    3.48 +        
    3.49 +    if ( (flags & GNTMAP_application_map) )
    3.50 +        l1e_add_flags(pte,_PAGE_USER);
    3.51 +    if ( !(flags & GNTMAP_readonly) )
    3.52 +        l1e_add_flags(pte,_PAGE_RW);
    3.53 +
    3.54 +    if ( flags & GNTMAP_contains_pte )
    3.55 +        return create_grant_pte_mapping(addr, pte, current);
    3.56 +    return create_grant_va_mapping(addr, pte, current);
    3.57 +}
    3.58 +
    3.59 +int destroy_grant_host_mapping(
    3.60 +    unsigned long addr, unsigned long frame, unsigned int flags)
    3.61 +{
    3.62 +    if ( flags & GNTMAP_contains_pte )
    3.63 +        return destroy_grant_pte_mapping(addr, frame, current->domain);
    3.64 +    return destroy_grant_va_mapping(addr, frame);
    3.65 +}
    3.66 +
    3.67 +int steal_page_for_grant_transfer(
    3.68 +    struct domain *d, struct pfn_info *page)
    3.69 +{
    3.70 +    u32 _d, _nd, x, y;
    3.71 +
    3.72 +    spin_lock(&d->page_alloc_lock);
    3.73 +
    3.74 +    /*
    3.75 +     * The tricky bit: atomically release ownership while there is just one 
    3.76 +     * benign reference to the page (PGC_allocated). If that reference 
    3.77 +     * disappears then the deallocation routine will safely spin.
    3.78 +     */
    3.79 +    _d  = pickle_domptr(d);
    3.80 +    _nd = page->u.inuse._domain;
    3.81 +    y   = page->count_info;
    3.82 +    do {
    3.83 +        x = y;
    3.84 +        if (unlikely((x & (PGC_count_mask|PGC_allocated)) !=
    3.85 +                     (1 | PGC_allocated)) || unlikely(_nd != _d)) { 
    3.86 +            DPRINTK("gnttab_transfer: Bad page %p: ed=%p(%u), sd=%p,"
    3.87 +                    " caf=%08x, taf=%" PRtype_info "\n", 
    3.88 +                    (void *) page_to_pfn(page),
    3.89 +                    d, d->domain_id, unpickle_domptr(_nd), x, 
    3.90 +                    page->u.inuse.type_info);
    3.91 +            spin_unlock(&d->page_alloc_lock);
    3.92 +            return -1;
    3.93 +        }
    3.94 +        __asm__ __volatile__(
    3.95 +            LOCK_PREFIX "cmpxchg8b %2"
    3.96 +            : "=d" (_nd), "=a" (y),
    3.97 +            "=m" (*(volatile u64 *)(&page->count_info))
    3.98 +            : "0" (_d), "1" (x), "c" (NULL), "b" (x) );
    3.99 +    } while (unlikely(_nd != _d) || unlikely(y != x));
   3.100 +
   3.101 +    /*
   3.102 +     * Unlink from 'd'. At least one reference remains (now anonymous), so 
   3.103 +     * noone else is spinning to try to delete this page from 'd'.
   3.104 +     */
   3.105 +    d->tot_pages--;
   3.106 +    list_del(&page->list);
   3.107 +
   3.108 +    spin_unlock(&d->page_alloc_lock);
   3.109 +
   3.110 +    return 0;
   3.111 +}
   3.112  
   3.113  int do_update_va_mapping(unsigned long va, u64 val64,
   3.114                           unsigned long flags)
     4.1 --- a/xen/common/Makefile	Wed Nov 23 13:38:34 2005 +0100
     4.2 +++ b/xen/common/Makefile	Wed Nov 23 13:50:14 2005 +0100
     4.3 @@ -1,10 +1,6 @@
     4.4  
     4.5  include $(BASEDIR)/Rules.mk
     4.6  
     4.7 -ifeq ($(TARGET_ARCH),ia64)
     4.8 -OBJS := $(subst grant_table.o,,$(OBJS))
     4.9 -endif
    4.10 -
    4.11  ifneq ($(perfc),y)
    4.12  OBJS := $(subst perfc.o,,$(OBJS))
    4.13  endif
     5.1 --- a/xen/common/grant_table.c	Wed Nov 23 13:38:34 2005 +0100
     5.2 +++ b/xen/common/grant_table.c	Wed Nov 23 13:50:14 2005 +0100
     5.3 @@ -330,20 +330,7 @@ static int
     5.4  
     5.5      if ( dev_hst_ro_flags & GNTMAP_host_map )
     5.6      {
     5.7 -        /* Write update into the pagetable. */
     5.8 -        l1_pgentry_t pte;
     5.9 -        pte = l1e_from_pfn(frame, GRANT_PTE_FLAGS);
    5.10 -        
    5.11 -        if ( (dev_hst_ro_flags & GNTMAP_application_map) )
    5.12 -            l1e_add_flags(pte,_PAGE_USER);
    5.13 -        if ( !(dev_hst_ro_flags & GNTMAP_readonly) )
    5.14 -            l1e_add_flags(pte,_PAGE_RW);
    5.15 -
    5.16 -        if ( dev_hst_ro_flags & GNTMAP_contains_pte )
    5.17 -            rc = update_grant_pte_mapping(addr, pte, led);
    5.18 -        else
    5.19 -            rc = update_grant_va_mapping(addr, pte, led);
    5.20 -
    5.21 +        rc = create_grant_host_mapping(addr, frame, dev_hst_ro_flags);
    5.22          if ( rc < 0 )
    5.23          {
    5.24              /* Failure: undo and abort. */
    5.25 @@ -488,16 +475,8 @@ static int
    5.26           (flags & GNTMAP_host_map) &&
    5.27           ((act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask)) > 0))
    5.28      {
    5.29 -        if ( flags & GNTMAP_contains_pte )
    5.30 -        {
    5.31 -            if ( (rc = clear_grant_pte_mapping(addr, frame, ld)) < 0 )
    5.32 -                goto unmap_out;
    5.33 -        }
    5.34 -        else
    5.35 -        {
    5.36 -            if ( (rc = clear_grant_va_mapping(addr, frame)) < 0 )
    5.37 -                goto unmap_out;
    5.38 -        }
    5.39 +        if ( (rc = destroy_grant_host_mapping(addr, frame, flags)) < 0 )
    5.40 +            goto unmap_out;
    5.41  
    5.42          map->ref_and_flags &= ~GNTMAP_host_map;
    5.43  
    5.44 @@ -512,9 +491,8 @@ static int
    5.45      }
    5.46  
    5.47      /* If just unmapped a writable mapping, mark as dirtied */
    5.48 -    if ( unlikely(shadow_mode_log_dirty(rd)) &&
    5.49 -         !(flags & GNTMAP_readonly) )
    5.50 -         mark_dirty(rd, frame);
    5.51 +    if ( !(flags & GNTMAP_readonly) )
    5.52 +         gnttab_log_dirty(rd, frame);
    5.53  
    5.54      /* If the last writable mapping has been removed, put_page_type */
    5.55      if ( ((act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0) &&
    5.56 @@ -599,9 +577,8 @@ gnttab_setup_table(
    5.57          ASSERT(d->grant_table != NULL);
    5.58          (void)put_user(GNTST_okay, &uop->status);
    5.59          for ( i = 0; i < op.nr_frames; i++ )
    5.60 -            (void)put_user(
    5.61 -                (virt_to_phys(d->grant_table->shared) >> PAGE_SHIFT) + i,
    5.62 -                &uop->frame_list[i]);
    5.63 +            (void)put_user(gnttab_shared_mfn(d, d->grant_table, i),
    5.64 +                           &uop->frame_list[i]);
    5.65      }
    5.66  
    5.67      put_domain(d);
    5.68 @@ -698,7 +675,6 @@ gnttab_transfer(
    5.69      struct domain *d = current->domain;
    5.70      struct domain *e;
    5.71      struct pfn_info *page;
    5.72 -    u32 _d, _nd, x, y;
    5.73      int i;
    5.74      grant_entry_t *sha;
    5.75      gnttab_transfer_t gop;
    5.76 @@ -723,46 +699,11 @@ gnttab_transfer(
    5.77              continue;
    5.78          }
    5.79  
    5.80 -        spin_lock(&d->page_alloc_lock);
    5.81 -
    5.82 -        /*
    5.83 -         * The tricky bit: atomically release ownership while
    5.84 -         * there is just one benign reference to the page
    5.85 -         * (PGC_allocated). If that reference disappears then the
    5.86 -         * deallocation routine will safely spin.
    5.87 -         */
    5.88 -        _d  = pickle_domptr(d);
    5.89 -        _nd = page->u.inuse._domain;
    5.90 -        y   = page->count_info;
    5.91 -        do {
    5.92 -            x = y;
    5.93 -            if (unlikely((x & (PGC_count_mask|PGC_allocated)) !=
    5.94 -                         (1 | PGC_allocated)) || unlikely(_nd != _d)) { 
    5.95 -                DPRINTK("gnttab_transfer: Bad page %p: ed=%p(%u), sd=%p,"
    5.96 -                       " caf=%08x, taf=%" PRtype_info "\n", 
    5.97 -                       (void *) page_to_pfn(page),
    5.98 -                        d, d->domain_id, unpickle_domptr(_nd), x, 
    5.99 -                        page->u.inuse.type_info);
   5.100 -                spin_unlock(&d->page_alloc_lock);
   5.101 -                (void)__put_user(GNTST_bad_page, &uop[i].status);
   5.102 -                continue;
   5.103 -            }
   5.104 -            __asm__ __volatile__(
   5.105 -                LOCK_PREFIX "cmpxchg8b %2"
   5.106 -                : "=d" (_nd), "=a" (y),
   5.107 -                "=m" (*(volatile u64 *)(&page->count_info))
   5.108 -                : "0" (_d), "1" (x), "c" (NULL), "b" (x) );
   5.109 -        } while (unlikely(_nd != _d) || unlikely(y != x));
   5.110 -
   5.111 -        /*
   5.112 -         * Unlink from 'd'. At least one reference remains (now
   5.113 -         * anonymous), so noone else is spinning to try to delete
   5.114 -         * this page from 'd'.
   5.115 -         */
   5.116 -        d->tot_pages--;
   5.117 -        list_del(&page->list);
   5.118 -
   5.119 -        spin_unlock(&d->page_alloc_lock);
   5.120 +        if ( steal_page_for_grant_transfer(d, page) < 0 )
   5.121 +        {
   5.122 +            (void)__put_user(GNTST_bad_page, &uop[i].status);
   5.123 +            continue;
   5.124 +        }
   5.125  
   5.126          /* Find the target domain. */
   5.127          if ( unlikely((e = find_domain_by_id(gop.domid)) == NULL) )
   5.128 @@ -991,14 +932,7 @@ grant_table_create(
   5.129      memset(t->shared, 0, NR_GRANT_FRAMES * PAGE_SIZE);
   5.130  
   5.131      for ( i = 0; i < NR_GRANT_FRAMES; i++ )
   5.132 -    {
   5.133 -        SHARE_PFN_WITH_DOMAIN(
   5.134 -            virt_to_page((char *)t->shared + (i * PAGE_SIZE)),
   5.135 -            d);
   5.136 -        set_pfn_from_mfn(
   5.137 -            (virt_to_phys(t->shared) >> PAGE_SHIFT) + i,
   5.138 -            INVALID_M2P_ENTRY);
   5.139 -    }
   5.140 +        gnttab_create_shared_mfn(d, t, i);
   5.141  
   5.142      /* Okay, install the structure. */
   5.143      wmb(); /* avoid races with lock-free access to d->grant_table */
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xen/include/asm-ia64/grant_table.h	Wed Nov 23 13:50:14 2005 +0100
     6.3 @@ -0,0 +1,26 @@
     6.4 +/******************************************************************************
     6.5 + * include/asm-ia64/grant_table.h
     6.6 + */
     6.7 +
     6.8 +#ifndef __ASM_GRANT_TABLE_H__
     6.9 +#define __ASM_GRANT_TABLE_H__
    6.10 +
    6.11 +#define ORDER_GRANT_FRAMES 0
    6.12 +
    6.13 +#define create_grant_host_mapping(a, f, fl)  0
    6.14 +#define destroy_grant_host_mapping(a, f, fl) 0
    6.15 +
    6.16 +#define steal_page_for_grant_transfer(d, p)  0
    6.17 +
    6.18 +#define gnttab_create_shared_mfn(d, t, i) ((void)0)
    6.19 +
    6.20 +#define gnttab_shared_mfn(d, t, i)                                      \
    6.21 +    ( ((d) == dom0) ?                                                   \
    6.22 +      ((virt_to_phys((t)shared) >> PAGE_SHIFT) + (i)) :                 \
    6.23 +      (map_domain_page((d), 1UL<<40, virt_to_phys((t)->shared)),        \
    6.24 +       1UL << (40 - PAGE_SHIFT))                                        \
    6.25 +    )
    6.26 +
    6.27 +#define gnttab_log_dirty(d, f) ((void)0)
    6.28 +
    6.29 +#endif /* __ASM_GRANT_TABLE_H__ */
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/xen/include/asm-x86/grant_table.h	Wed Nov 23 13:50:14 2005 +0100
     7.3 @@ -0,0 +1,42 @@
     7.4 +/******************************************************************************
     7.5 + * include/asm-x86/grant_table.h
     7.6 + * 
     7.7 + * Copyright (c) 2004-2005 K A Fraser
     7.8 + */
     7.9 +
    7.10 +#ifndef __ASM_GRANT_TABLE_H__
    7.11 +#define __ASM_GRANT_TABLE_H__
    7.12 +
    7.13 +#define ORDER_GRANT_FRAMES 2
    7.14 +
    7.15 +/*
    7.16 + * Caller must own caller's BIGLOCK, is responsible for flushing the TLB, and
    7.17 + * must hold a reference to the page.
    7.18 + */
    7.19 +int create_grant_host_mapping(
    7.20 +    unsigned long addr, unsigned long frame, unsigned int flags);
    7.21 +int destroy_grant_host_mapping(
    7.22 +    unsigned long addr, unsigned long frame, unsigned int flags);
    7.23 +
    7.24 +int steal_page_for_grant_transfer(
    7.25 +    struct domain *d, struct pfn_info *page);
    7.26 +
    7.27 +#define gnttab_create_shared_mfn(d, t, i)                                \
    7.28 +    do {                                                                 \
    7.29 +        SHARE_PFN_WITH_DOMAIN(                                           \
    7.30 +            virt_to_page((char *)(t)->shared + ((i) * PAGE_SIZE)), (d)); \
    7.31 +        set_pfn_from_mfn(                                                \
    7.32 +            (virt_to_phys((t)->shared) >> PAGE_SHIFT) + (i),             \
    7.33 +            INVALID_M2P_ENTRY);                                          \
    7.34 +    } while ( 0 )
    7.35 +
    7.36 +#define gnttab_shared_mfn(d, t, i)                      \
    7.37 +    ((virt_to_phys((t)->shared) >> PAGE_SHIFT) + (i))
    7.38 +
    7.39 +#define gnttab_log_dirty(d, f)                          \
    7.40 +    do {                                                \
    7.41 +        if ( unlikely(shadow_mode_log_dirty((d))) )     \
    7.42 +            mark_dirty((d), (f));                       \
    7.43 +    } while ( 0 )
    7.44 +
    7.45 +#endif /* __ASM_GRANT_TABLE_H__ */
     8.1 --- a/xen/include/asm-x86/mm.h	Wed Nov 23 13:38:34 2005 +0100
     8.2 +++ b/xen/include/asm-x86/mm.h	Wed Nov 23 13:50:14 2005 +0100
     8.3 @@ -381,16 +381,4 @@ void propagate_page_fault(unsigned long 
     8.4  
     8.5  extern int __sync_lazy_execstate(void);
     8.6  
     8.7 -/*
     8.8 - * Caller must own d's BIGLOCK, is responsible for flushing the TLB, and must 
     8.9 - * hold a reference to the page.
    8.10 - */
    8.11 -int update_grant_va_mapping(
    8.12 -    unsigned long va, l1_pgentry_t _nl1e, struct vcpu *v);
    8.13 -int update_grant_pte_mapping(
    8.14 -    unsigned long pte_addr, l1_pgentry_t _nl1e, struct vcpu *v);
    8.15 -int clear_grant_va_mapping(unsigned long addr, unsigned long frame);
    8.16 -int clear_grant_pte_mapping(
    8.17 -    unsigned long addr, unsigned long frame, struct domain *d);
    8.18 -
    8.19  #endif /* __ASM_X86_MM_H__ */
     9.1 --- a/xen/include/xen/grant_table.h	Wed Nov 23 13:38:34 2005 +0100
     9.2 +++ b/xen/include/xen/grant_table.h	Wed Nov 23 13:50:14 2005 +0100
     9.3 @@ -4,7 +4,7 @@
     9.4   * Mechanism for granting foreign access to page frames, and receiving
     9.5   * page-ownership transfers.
     9.6   * 
     9.7 - * Copyright (c) 2004 K A Fraser
     9.8 + * Copyright (c) 2004-2005 K A Fraser
     9.9   * 
    9.10   * This program is free software; you can redistribute it and/or modify
    9.11   * it under the terms of the GNU General Public License as published by
    9.12 @@ -21,11 +21,12 @@
    9.13   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    9.14   */
    9.15  
    9.16 -#ifndef __XEN_GRANT_H__
    9.17 -#define __XEN_GRANT_H__
    9.18 +#ifndef __XEN_GRANT_TABLE_H__
    9.19 +#define __XEN_GRANT_TABLE_H__
    9.20  
    9.21  #include <xen/config.h>
    9.22  #include <public/grant_table.h>
    9.23 +#include <asm/grant_table.h>
    9.24  
    9.25  /* Active grant entry - used for shadowing GTF_permit_access grants. */
    9.26  typedef struct {
    9.27 @@ -51,7 +52,6 @@ typedef struct {
    9.28  #define GNTPIN_devr_inc      (1 << GNTPIN_devr_shift)
    9.29  #define GNTPIN_devr_mask     (0xFFU << GNTPIN_devr_shift)
    9.30  
    9.31 -#define ORDER_GRANT_FRAMES   2
    9.32  #define NR_GRANT_FRAMES      (1U << ORDER_GRANT_FRAMES)
    9.33  #define NR_GRANT_ENTRIES     \
    9.34      ((NR_GRANT_FRAMES << PAGE_SHIFT) / sizeof(grant_entry_t))
    9.35 @@ -107,4 +107,4 @@ void
    9.36  gnttab_release_mappings(
    9.37      struct domain *d);
    9.38  
    9.39 -#endif /* __XEN_GRANT_H__ */
    9.40 +#endif /* __XEN_GRANT_TABLE_H__ */