direct-io.hg

changeset 6846:bf3fdeeba48b

merge two heads
author djm@kirby.fc.hp.com
date Fri Sep 02 12:31:56 2005 -0600 (2005-09-02)
parents 888877bc3d79 21ad2828dbdf
children 9361694781fc
files xen/arch/ia64/tools/README.xenia64 xen/arch/ia64/tools/README.xenia64linux xen/arch/ia64/xen/grant_table.c xen/arch/ia64/xen/regionreg.c xen/arch/ia64/xen/vcpu.c xen/include/asm-ia64/mm.h xen/include/asm-ia64/xensystem.h xen/include/public/arch-ia64.h
line diff
     3.1 --- a/xen/arch/ia64/xen/grant_table.c	Thu Sep 01 13:01:55 2005 -0600
     3.2 +++ b/xen/arch/ia64/xen/grant_table.c	Fri Sep 02 12:31:56 2005 -0600
     3.3 @@ -8,6 +8,8 @@
     3.4   * 
     3.5   * Copyright (c) 2005 Christopher Clark
     3.6   * Copyright (c) 2004 K A Fraser
     3.7 + * Copyright (c) 2005 Andrew Warfield
     3.8 + * Modifications by Geoffrey Lefebvre are (c) Intel Research Cambridge
     3.9   * 
    3.10   * This program is free software; you can redistribute it and/or modify
    3.11   * it under the terms of the GNU General Public License as published by
    3.12 @@ -34,14 +36,19 @@
    3.13  #include <xen/mm.h>
    3.14  #ifdef __ia64__
    3.15  #define __addr_ok(a) 1	// FIXME-ia64: a variant of access_ok??
    3.16 -// FIXME-ia64: need to implement real cmpxchg_user on ia64
    3.17 -//#define cmpxchg_user(_p,_o,_n) ((*_p == _o) ? ((*_p = _n), 0) : ((_o = *_p), 0))
    3.18  // FIXME-ia64: these belong in an asm/grant_table.h... PAGE_SIZE different
    3.19  #undef ORDER_GRANT_FRAMES
    3.20  //#undef NUM_GRANT_FRAMES
    3.21  #define ORDER_GRANT_FRAMES 0
    3.22  //#define NUM_GRANT_FRAMES  (1U << ORDER_GRANT_FRAMES)
    3.23  #endif
    3.24 +#include <acm/acm_hooks.h>
    3.25 +
    3.26 +#if defined(CONFIG_X86_64)
    3.27 +#define GRANT_PTE_FLAGS (_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
    3.28 +#else
    3.29 +#define GRANT_PTE_FLAGS (_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_DIRTY)
    3.30 +#endif
    3.31  
    3.32  #define PIN_FAIL(_lbl, _rc, _f, _a...)   \
    3.33      do {                           \
    3.34 @@ -55,7 +62,7 @@ get_maptrack_handle(
    3.35      grant_table_t *t)
    3.36  {
    3.37      unsigned int h;
    3.38 -    if ( unlikely((h = t->maptrack_head) == t->maptrack_limit) )
    3.39 +    if ( unlikely((h = t->maptrack_head) == (t->maptrack_limit - 1)) )
    3.40          return -1;
    3.41      t->maptrack_head = t->maptrack[h].ref_and_flags >> MAPTRACK_REF_SHIFT;
    3.42      t->map_count++;
    3.43 @@ -73,13 +80,13 @@ put_maptrack_handle(
    3.44  
    3.45  static int
    3.46  __gnttab_activate_grant_ref(
    3.47 -    struct domain          *mapping_d,          /* IN */
    3.48 +    struct domain   *mapping_d,          /* IN */
    3.49      struct vcpu     *mapping_ed,
    3.50 -    struct domain          *granting_d,
    3.51 -    grant_ref_t             ref,
    3.52 -    u16                     dev_hst_ro_flags,
    3.53 -    unsigned long           host_virt_addr,
    3.54 -    unsigned long          *pframe )            /* OUT */
    3.55 +    struct domain   *granting_d,
    3.56 +    grant_ref_t      ref,
    3.57 +    u16              dev_hst_ro_flags,
    3.58 +    u64              addr,
    3.59 +    unsigned long   *pframe )            /* OUT */
    3.60  {
    3.61      domid_t               sdom;
    3.62      u16                   sflags;
    3.63 @@ -100,7 +107,7 @@ static int
    3.64       * Returns:
    3.65       * .  -ve: error
    3.66       * .    1: ok
    3.67 -     * .    0: ok and TLB invalidate of host_virt_addr needed.
    3.68 +     * .    0: ok and TLB invalidate of host_addr needed.
    3.69       *
    3.70       * On success, *pframe contains mfn.
    3.71       */
    3.72 @@ -126,6 +133,10 @@ static int
    3.73          sflags = sha->flags;
    3.74          sdom   = sha->domid;
    3.75  
    3.76 +        /* This loop attempts to set the access (reading/writing) flags
    3.77 +         * in the grant table entry.  It tries a cmpxchg on the field
    3.78 +         * up to five times, and then fails under the assumption that 
    3.79 +         * the guest is misbehaving. */
    3.80          for ( ; ; )
    3.81          {
    3.82              u32 scombo, prev_scombo, new_scombo;
    3.83 @@ -188,7 +199,7 @@ static int
    3.84              PIN_FAIL(unlock_out, GNTST_general_error,
    3.85                       "Could not pin the granted frame (%lx)!\n", frame);
    3.86          }
    3.87 -#endif
    3.88 +#endif 
    3.89  
    3.90          if ( dev_hst_ro_flags & GNTMAP_device_map )
    3.91              act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ?
    3.92 @@ -266,7 +277,7 @@ static int
    3.93  
    3.94      /*
    3.95       * At this point:
    3.96 -     * act->pin updated to reflect mapping.
    3.97 +     * act->pin updated to reference count mappings.
    3.98       * sha->flags updated to indicate to granting domain mapping done.
    3.99       * frame contains the mfn.
   3.100       */
   3.101 @@ -276,21 +287,25 @@ static int
   3.102  #ifdef __ia64__
   3.103  // FIXME-ia64: any error checking need to be done here?
   3.104  #else
   3.105 -    if ( (host_virt_addr != 0) && (dev_hst_ro_flags & GNTMAP_host_map) )
   3.106 +    if ( (addr != 0) && (dev_hst_ro_flags & GNTMAP_host_map) )
   3.107      {
   3.108          /* Write update into the pagetable. */
   3.109          l1_pgentry_t pte;
   3.110 -        pte = l1e_from_pfn(frame, _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
   3.111 +        pte = l1e_from_pfn(frame, GRANT_PTE_FLAGS);
   3.112 +        
   3.113 +        if ( (dev_hst_ro_flags & GNTMAP_application_map) )
   3.114 +            l1e_add_flags(pte,_PAGE_USER);
   3.115          if ( !(dev_hst_ro_flags & GNTMAP_readonly) )
   3.116              l1e_add_flags(pte,_PAGE_RW);
   3.117 -        rc = update_grant_va_mapping( host_virt_addr, pte, 
   3.118 -                       mapping_d, mapping_ed );
   3.119  
   3.120 -        /*
   3.121 -         * IMPORTANT: (rc == 0) => must flush / invalidate entry in TLB.
   3.122 -         * This is done in the outer gnttab_map_grant_ref.
   3.123 -         */
   3.124 +        if ( dev_hst_ro_flags & GNTMAP_contains_pte )
   3.125 +            rc = update_grant_pte_mapping(addr, pte, mapping_d, mapping_ed);
   3.126 +        else
   3.127 +            rc = update_grant_va_mapping(addr, pte, mapping_d, mapping_ed);
   3.128  
   3.129 +        /* IMPORTANT: rc indicates the degree of TLB flush that is required.
   3.130 +         * GNTST_flush_one (1) or GNTST_flush_all (2). This is done in the 
   3.131 +         * outer gnttab_map_grant_ref. */
   3.132          if ( rc < 0 )
   3.133          {
   3.134              /* Failure: undo and abort. */
   3.135 @@ -334,20 +349,24 @@ static int
   3.136  /*
   3.137   * Returns 0 if TLB flush / invalidate required by caller.
   3.138   * va will indicate the address to be invalidated.
   3.139 + * 
   3.140 + * addr is _either_ a host virtual address, or the address of the pte to
   3.141 + * update, as indicated by the GNTMAP_contains_pte flag.
   3.142   */
   3.143  static int
   3.144  __gnttab_map_grant_ref(
   3.145      gnttab_map_grant_ref_t *uop,
   3.146      unsigned long *va)
   3.147  {
   3.148 -    domid_t               dom;
   3.149 -    grant_ref_t           ref;
   3.150 -    struct domain        *ld, *rd;
   3.151 +    domid_t        dom;
   3.152 +    grant_ref_t    ref;
   3.153 +    struct domain *ld, *rd;
   3.154      struct vcpu   *led;
   3.155 -    u16                   dev_hst_ro_flags;
   3.156 -    int                   handle;
   3.157 -    unsigned long         frame = 0, host_virt_addr;
   3.158 -    int                   rc;
   3.159 +    u16            dev_hst_ro_flags;
   3.160 +    int            handle;
   3.161 +    u64            addr;
   3.162 +    unsigned long  frame = 0;
   3.163 +    int            rc;
   3.164  
   3.165      led = current;
   3.166      ld = led->domain;
   3.167 @@ -355,19 +374,20 @@ static int
   3.168      /* Bitwise-OR avoids short-circuiting which screws control flow. */
   3.169      if ( unlikely(__get_user(dom, &uop->dom) |
   3.170                    __get_user(ref, &uop->ref) |
   3.171 -                  __get_user(host_virt_addr, &uop->host_addr) |
   3.172 +                  __get_user(addr, &uop->host_addr) |
   3.173                    __get_user(dev_hst_ro_flags, &uop->flags)) )
   3.174      {
   3.175          DPRINTK("Fault while reading gnttab_map_grant_ref_t.\n");
   3.176          return -EFAULT; /* don't set status */
   3.177      }
   3.178  
   3.179 -
   3.180 -    if ( ((host_virt_addr != 0) || (dev_hst_ro_flags & GNTMAP_host_map)) &&
   3.181 -         unlikely(!__addr_ok(host_virt_addr)))
   3.182 +    if ( (dev_hst_ro_flags & GNTMAP_host_map) &&
   3.183 +         ( (addr == 0) ||
   3.184 +           (!(dev_hst_ro_flags & GNTMAP_contains_pte) && 
   3.185 +            unlikely(!__addr_ok(addr))) ) )
   3.186      {
   3.187 -        DPRINTK("Bad virtual address (%lx) or flags (%x).\n",
   3.188 -                host_virt_addr, dev_hst_ro_flags);
   3.189 +        DPRINTK("Bad virtual address (%"PRIx64") or flags (%"PRIx16").\n",
   3.190 +                addr, dev_hst_ro_flags);
   3.191          (void)__put_user(GNTST_bad_virt_addr, &uop->handle);
   3.192          return GNTST_bad_gntref;
   3.193      }
   3.194 @@ -381,6 +401,11 @@ static int
   3.195          return GNTST_bad_gntref;
   3.196      }
   3.197  
   3.198 +    if (acm_pre_grant_map_ref(dom)) {
   3.199 +        (void)__put_user(GNTST_permission_denied, &uop->handle);
   3.200 +        return GNTST_permission_denied;
   3.201 +    }
   3.202 +
   3.203      if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
   3.204           unlikely(ld == rd) )
   3.205      {
   3.206 @@ -398,12 +423,20 @@ static int
   3.207          grant_mapping_t *new_mt;
   3.208          grant_table_t   *lgt      = ld->grant_table;
   3.209  
   3.210 +        if ( (lgt->maptrack_limit << 1) > MAPTRACK_MAX_ENTRIES )
   3.211 +        {
   3.212 +            put_domain(rd);
   3.213 +            DPRINTK("Maptrack table is at maximum size.\n");
   3.214 +            (void)__put_user(GNTST_no_device_space, &uop->handle);
   3.215 +            return GNTST_no_device_space;
   3.216 +        }
   3.217 +
   3.218          /* Grow the maptrack table. */
   3.219          new_mt = alloc_xenheap_pages(lgt->maptrack_order + 1);
   3.220          if ( new_mt == NULL )
   3.221          {
   3.222              put_domain(rd);
   3.223 -            DPRINTK("No more map handles available\n");
   3.224 +            DPRINTK("No more map handles available.\n");
   3.225              (void)__put_user(GNTST_no_device_space, &uop->handle);
   3.226              return GNTST_no_device_space;
   3.227          }
   3.228 @@ -417,7 +450,7 @@ static int
   3.229          lgt->maptrack_order   += 1;
   3.230          lgt->maptrack_limit  <<= 1;
   3.231  
   3.232 -        printk("Doubled maptrack size\n");
   3.233 +        DPRINTK("Doubled maptrack size\n");
   3.234          handle = get_maptrack_handle(ld->grant_table);
   3.235      }
   3.236  
   3.237 @@ -428,7 +461,7 @@ static int
   3.238  
   3.239      if ( 0 <= ( rc = __gnttab_activate_grant_ref( ld, led, rd, ref,
   3.240                                                    dev_hst_ro_flags,
   3.241 -                                                  host_virt_addr, &frame)))
   3.242 +                                                  addr, &frame)))
   3.243      {
   3.244          /*
   3.245           * Only make the maptrack live _after_ writing the pte, in case we 
   3.246 @@ -440,10 +473,11 @@ static int
   3.247              = (ref << MAPTRACK_REF_SHIFT) |
   3.248                (dev_hst_ro_flags & MAPTRACK_GNTMAP_MASK);
   3.249  
   3.250 -        (void)__put_user(frame, &uop->dev_bus_addr);
   3.251 +        (void)__put_user((u64)frame << PAGE_SHIFT, &uop->dev_bus_addr);
   3.252  
   3.253 -        if ( dev_hst_ro_flags & GNTMAP_host_map )
   3.254 -            *va = host_virt_addr;
   3.255 +        if ( ( dev_hst_ro_flags & GNTMAP_host_map ) &&
   3.256 +             !( dev_hst_ro_flags & GNTMAP_contains_pte) )
   3.257 +            *va = addr;
   3.258  
   3.259          (void)__put_user(handle, &uop->handle);
   3.260      }
   3.261 @@ -461,12 +495,12 @@ static long
   3.262  gnttab_map_grant_ref(
   3.263      gnttab_map_grant_ref_t *uop, unsigned int count)
   3.264  {
   3.265 -    int i, flush = 0;
   3.266 +    int i, rc, flush = 0;
   3.267      unsigned long va = 0;
   3.268  
   3.269      for ( i = 0; i < count; i++ )
   3.270 -        if ( __gnttab_map_grant_ref(&uop[i], &va) == 0 )
   3.271 -            flush++;
   3.272 +        if ( (rc =__gnttab_map_grant_ref(&uop[i], &va)) >= 0 )
   3.273 +            flush += rc;
   3.274  
   3.275  #ifdef __ia64__
   3.276  // FIXME-ia64: probably need to do something here to avoid stale mappings?
   3.277 @@ -485,29 +519,31 @@ static int
   3.278      gnttab_unmap_grant_ref_t *uop,
   3.279      unsigned long *va)
   3.280  {
   3.281 -    domid_t        dom;
   3.282 -    grant_ref_t    ref;
   3.283 -    u16            handle;
   3.284 -    struct domain *ld, *rd;
   3.285 -
   3.286 +    domid_t          dom;
   3.287 +    grant_ref_t      ref;
   3.288 +    u16              handle;
   3.289 +    struct domain   *ld, *rd;
   3.290      active_grant_entry_t *act;
   3.291 -    grant_entry_t *sha;
   3.292 +    grant_entry_t   *sha;
   3.293      grant_mapping_t *map;
   3.294 -    u16            flags;
   3.295 -    s16            rc = 1;
   3.296 -    unsigned long  frame, virt;
   3.297 +    u16              flags;
   3.298 +    s16              rc = 1;
   3.299 +    u64              addr, dev_bus_addr;
   3.300 +    unsigned long    frame;
   3.301  
   3.302      ld = current->domain;
   3.303  
   3.304      /* Bitwise-OR avoids short-circuiting which screws control flow. */
   3.305 -    if ( unlikely(__get_user(virt, &uop->host_addr) |
   3.306 -                  __get_user(frame, &uop->dev_bus_addr) |
   3.307 +    if ( unlikely(__get_user(addr, &uop->host_addr) |
   3.308 +                  __get_user(dev_bus_addr, &uop->dev_bus_addr) |
   3.309                    __get_user(handle, &uop->handle)) )
   3.310      {
   3.311          DPRINTK("Fault while reading gnttab_unmap_grant_ref_t.\n");
   3.312          return -EFAULT; /* don't set status */
   3.313      }
   3.314  
   3.315 +    frame = (unsigned long)(dev_bus_addr >> PAGE_SHIFT);
   3.316 +
   3.317      map = &ld->grant_table->maptrack[handle];
   3.318  
   3.319      if ( unlikely(handle >= ld->grant_table->maptrack_limit) ||
   3.320 @@ -561,44 +597,22 @@ static int
   3.321          /* Frame is now unmapped for device access. */
   3.322      }
   3.323  
   3.324 -    if ( (virt != 0) &&
   3.325 +    if ( (addr != 0) &&
   3.326           (flags & GNTMAP_host_map) &&
   3.327           ((act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask)) > 0))
   3.328      {
   3.329  #ifdef __ia64__
   3.330  // FIXME-ia64: any error checking need to be done here?
   3.331  #else
   3.332 -        l1_pgentry_t   *pl1e;
   3.333 -        unsigned long   _ol1e;
   3.334 -
   3.335 -        pl1e = &linear_pg_table[l1_linear_offset(virt)];
   3.336 -
   3.337 -        if ( unlikely(__get_user(_ol1e, (unsigned long *)pl1e) != 0) )
   3.338 +        if ( flags & GNTMAP_contains_pte )
   3.339          {
   3.340 -            DPRINTK("Could not find PTE entry for address %lx\n", virt);
   3.341 -            rc = -EINVAL;
   3.342 -            goto unmap_out;
   3.343 +            if ( (rc = clear_grant_pte_mapping(addr, frame, ld)) < 0 )
   3.344 +                goto unmap_out;
   3.345          }
   3.346 -
   3.347 -        /*
   3.348 -         * Check that the virtual address supplied is actually mapped to 
   3.349 -         * act->frame.
   3.350 -         */
   3.351 -        if ( unlikely((_ol1e >> PAGE_SHIFT) != frame ))
   3.352 +        else
   3.353          {
   3.354 -            DPRINTK("PTE entry %lx for address %lx doesn't match frame %lx\n",
   3.355 -                    _ol1e, virt, frame);
   3.356 -            rc = -EINVAL;
   3.357 -            goto unmap_out;
   3.358 -        }
   3.359 -
   3.360 -        /* Delete pagetable entry. */
   3.361 -        if ( unlikely(__put_user(0, (unsigned long *)pl1e)))
   3.362 -        {
   3.363 -            DPRINTK("Cannot delete PTE entry at %p for virtual address %lx\n",
   3.364 -                    pl1e, virt);
   3.365 -            rc = -EINVAL;
   3.366 -            goto unmap_out;
   3.367 +            if ( (rc = clear_grant_va_mapping(addr, frame)) < 0 )
   3.368 +                goto unmap_out;
   3.369          }
   3.370  #endif
   3.371  
   3.372 @@ -608,7 +622,8 @@ static int
   3.373                                                : GNTPIN_hstw_inc;
   3.374  
   3.375          rc = 0;
   3.376 -        *va = virt;
   3.377 +        if ( !( flags & GNTMAP_contains_pte) )
   3.378 +            *va = addr;
   3.379      }
   3.380  
   3.381      if ( (map->ref_and_flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0)
   3.382 @@ -637,6 +652,7 @@ static int
   3.383  
   3.384      if ( act->pin == 0 )
   3.385      {
   3.386 +        act->frame = 0xdeadbeef;
   3.387          clear_bit(_GTF_reading, &sha->flags);
   3.388          put_page(&frame_table[frame]);
   3.389      }
   3.390 @@ -678,7 +694,6 @@ gnttab_setup_table(
   3.391      gnttab_setup_table_t  op;
   3.392      struct domain        *d;
   3.393      int                   i;
   3.394 -    unsigned long addr;
   3.395  
   3.396      if ( count != 1 )
   3.397          return -EINVAL;
   3.398 @@ -726,7 +741,7 @@ gnttab_setup_table(
   3.399                      &uop->frame_list[i]);
   3.400  	} else {
   3.401              /* IA64 hack - need to map it somewhere */
   3.402 -            addr = (1UL << 40);
   3.403 +            unsigned long addr = (1UL << 40);
   3.404              map_domain_page(d, addr, virt_to_phys(d->grant_table->shared));
   3.405              (void)put_user(addr >> PAGE_SHIFT, &uop->frame_list[0]);
   3.406          }
   3.407 @@ -794,7 +809,7 @@ gnttab_dump_table(gnttab_dump_table_t *u
   3.408          if ( sha_copy.flags )
   3.409          {
   3.410              DPRINTK("Grant: dom (%hu) SHARED (%d) flags:(%hx) "
   3.411 -                    "dom:(%hu) frame:(%lx)\n",
   3.412 +                    "dom:(%hu) frame:(%x)\n",
   3.413                      op.dom, i, sha_copy.flags, sha_copy.domid, sha_copy.frame);
   3.414          }
   3.415      }
   3.416 @@ -835,48 +850,208 @@ gnttab_dump_table(gnttab_dump_table_t *u
   3.417  }
   3.418  #endif
   3.419  
   3.420 +static long
   3.421 +gnttab_donate(gnttab_donate_t *uop, unsigned int count)
   3.422 +{
   3.423 +    struct domain *d = current->domain;
   3.424 +    struct domain *e;
   3.425 +    struct pfn_info *page;
   3.426 +    u32 _d, _nd, x, y;
   3.427 +    int i;
   3.428 +    int result = GNTST_okay;
   3.429 +
   3.430 +#ifdef __ia64__
   3.431 +//FIXME-IA64: not support for now?
   3.432 +    return GNTST_general_error;
   3.433 +#else
   3.434 +    for (i = 0; i < count; i++) {
   3.435 +        gnttab_donate_t *gop = &uop[i];
   3.436 +#if GRANT_DEBUG
   3.437 +        printk("gnttab_donate: i=%d mfn=%lx domid=%d gref=%08x\n",
   3.438 +               i, gop->mfn, gop->domid, gop->handle);
   3.439 +#endif
   3.440 +        page = &frame_table[gop->mfn];
   3.441 +        
   3.442 +        if (unlikely(IS_XEN_HEAP_FRAME(page))) { 
   3.443 +            printk("gnttab_donate: xen heap frame mfn=%lx\n", 
   3.444 +                   (unsigned long) gop->mfn);
   3.445 +            gop->status = GNTST_bad_virt_addr;
   3.446 +            continue;
   3.447 +        }
   3.448 +        if (unlikely(!pfn_valid(page_to_pfn(page)))) {
   3.449 +            printk("gnttab_donate: invalid pfn for mfn=%lx\n", 
   3.450 +                   (unsigned long) gop->mfn);
   3.451 +            gop->status = GNTST_bad_virt_addr;
   3.452 +            continue;
   3.453 +        }
   3.454 +        if (unlikely((e = find_domain_by_id(gop->domid)) == NULL)) {
   3.455 +            printk("gnttab_donate: can't find domain %d\n", gop->domid);
   3.456 +            gop->status = GNTST_bad_domain;
   3.457 +            continue;
   3.458 +        }
   3.459 +
   3.460 +        spin_lock(&d->page_alloc_lock);
   3.461 +
   3.462 +        /*
   3.463 +         * The tricky bit: atomically release ownership while
   3.464 +         * there is just one benign reference to the page
   3.465 +         * (PGC_allocated). If that reference disappears then the
   3.466 +         * deallocation routine will safely spin.
   3.467 +         */
   3.468 +        _d  = pickle_domptr(d);
   3.469 +        _nd = page->u.inuse._domain;
   3.470 +        y   = page->count_info;
   3.471 +        do {
   3.472 +            x = y;
   3.473 +            if (unlikely((x & (PGC_count_mask|PGC_allocated)) !=
   3.474 +                         (1 | PGC_allocated)) || unlikely(_nd != _d)) {
   3.475 +                printk("gnttab_donate: Bad page values %p: ed=%p(%u), sd=%p,"
   3.476 +                       " caf=%08x, taf=%" PRtype_info "\n", 
   3.477 +                       (void *) page_to_pfn(page),
   3.478 +                        d, d->domain_id, unpickle_domptr(_nd), x, 
   3.479 +                        page->u.inuse.type_info);
   3.480 +                spin_unlock(&d->page_alloc_lock);
   3.481 +                put_domain(e);
   3.482 +                return 0;
   3.483 +            }
   3.484 +            __asm__ __volatile__(
   3.485 +                LOCK_PREFIX "cmpxchg8b %2"
   3.486 +                : "=d" (_nd), "=a" (y),
   3.487 +                "=m" (*(volatile u64 *)(&page->count_info))
   3.488 +                : "0" (_d), "1" (x), "c" (NULL), "b" (x) );
   3.489 +        } while (unlikely(_nd != _d) || unlikely(y != x));
   3.490 +
   3.491 +        /*
   3.492 +         * Unlink from 'd'. At least one reference remains (now
   3.493 +         * anonymous), so noone else is spinning to try to delete
   3.494 +         * this page from 'd'.
   3.495 +         */
   3.496 +        d->tot_pages--;
   3.497 +        list_del(&page->list);
   3.498 +
   3.499 +        spin_unlock(&d->page_alloc_lock);
   3.500 +
   3.501 +        spin_lock(&e->page_alloc_lock);
   3.502 +
   3.503 +        /*
   3.504 +         * Check that 'e' will accept the page and has reservation
   3.505 +         * headroom.  Also, a domain mustn't have PGC_allocated
   3.506 +         * pages when it is dying.
   3.507 +         */
   3.508 +#ifdef GRANT_DEBUG
   3.509 +        if (unlikely(e->tot_pages >= e->max_pages)) {
   3.510 +            printk("gnttab_dontate: no headroom tot_pages=%d max_pages=%d\n",
   3.511 +                   e->tot_pages, e->max_pages);
   3.512 +            spin_unlock(&e->page_alloc_lock);
   3.513 +            put_domain(e);
   3.514 +            result = GNTST_general_error;
   3.515 +            break;
   3.516 +        }
   3.517 +        if (unlikely(test_bit(DOMFLAGS_DYING, &e->domain_flags))) {
   3.518 +            printk("gnttab_donate: target domain is dying\n");
   3.519 +            spin_unlock(&e->page_alloc_lock);
   3.520 +            put_domain(e);
   3.521 +            result = GNTST_general_error;
   3.522 +            break;
   3.523 +        }
   3.524 +        if (unlikely(!gnttab_prepare_for_transfer(e, d, gop->handle))) {
   3.525 +            printk("gnttab_donate: gnttab_prepare_for_transfer fails\n");
   3.526 +            spin_unlock(&e->page_alloc_lock);
   3.527 +            put_domain(e);
   3.528 +            result = GNTST_general_error;
   3.529 +            break;
   3.530 +        }
   3.531 +#else
   3.532 +        ASSERT(e->tot_pages <= e->max_pages);
   3.533 +        if (unlikely(test_bit(DOMFLAGS_DYING, &e->domain_flags)) ||
   3.534 +            unlikely(e->tot_pages == e->max_pages) ||
   3.535 +            unlikely(!gnttab_prepare_for_transfer(e, d, gop->handle))) {
   3.536 +            printk("gnttab_donate: Transferee has no reservation headroom (%d,"
   3.537 +                   "%d) or provided a bad grant ref (%08x) or is dying (%p)\n",
   3.538 +                   e->tot_pages, e->max_pages, gop->handle, e->d_flags);
   3.539 +            spin_unlock(&e->page_alloc_lock);
   3.540 +            put_domain(e);
   3.541 +            result = GNTST_general_error;
   3.542 +            break;
   3.543 +        }
   3.544 +#endif
   3.545 +        /* Okay, add the page to 'e'. */
   3.546 +        if (unlikely(e->tot_pages++ == 0)) {
   3.547 +            get_knownalive_domain(e);
   3.548 +        }
   3.549 +        list_add_tail(&page->list, &e->page_list);
   3.550 +        page_set_owner(page, e);
   3.551 +        
   3.552 +        spin_unlock(&e->page_alloc_lock);
   3.553 +        
   3.554 +        /*
   3.555 +         * Transfer is all done: tell the guest about its new page
   3.556 +         * frame.
   3.557 +         */
   3.558 +        gnttab_notify_transfer(e, d, gop->handle, gop->mfn);
   3.559 +        
   3.560 +        put_domain(e);
   3.561 +        
   3.562 +        gop->status = GNTST_okay;
   3.563 +    }
   3.564 +    return result;
   3.565 +#endif
   3.566 +}
   3.567 +
   3.568  long 
   3.569  do_grant_table_op(
   3.570      unsigned int cmd, void *uop, unsigned int count)
   3.571  {
   3.572      long rc;
   3.573 -
   3.574 +    struct domain *d = current->domain;
   3.575 +    
   3.576      if ( count > 512 )
   3.577          return -EINVAL;
   3.578 -
   3.579 -    LOCK_BIGLOCK(current->domain);
   3.580 -
   3.581 +    
   3.582 +    LOCK_BIGLOCK(d);
   3.583 +    
   3.584 +#ifndef __ia64__
   3.585 +    sync_pagetable_state(d);
   3.586 +#endif
   3.587 +    
   3.588      rc = -EFAULT;
   3.589      switch ( cmd )
   3.590 -    {
   3.591 -    case GNTTABOP_map_grant_ref:
   3.592 -        if ( unlikely(!array_access_ok(
   3.593 -            uop, count, sizeof(gnttab_map_grant_ref_t))) )
   3.594 -            goto out;
   3.595 -        rc = gnttab_map_grant_ref((gnttab_map_grant_ref_t *)uop, count);
   3.596 -        break;
   3.597 -    case GNTTABOP_unmap_grant_ref:
   3.598 -        if ( unlikely(!array_access_ok(
   3.599 -            uop, count, sizeof(gnttab_unmap_grant_ref_t))) )
   3.600 -            goto out;
   3.601 -        rc = gnttab_unmap_grant_ref((gnttab_unmap_grant_ref_t *)uop, count);
   3.602 -        break;
   3.603 -    case GNTTABOP_setup_table:
   3.604 -        rc = gnttab_setup_table((gnttab_setup_table_t *)uop, count);
   3.605 -        break;
   3.606 +        {
   3.607 +        case GNTTABOP_map_grant_ref:
   3.608 +            if ( unlikely(!array_access_ok(
   3.609 +                              uop, count, sizeof(gnttab_map_grant_ref_t))) )
   3.610 +                goto out;
   3.611 +            rc = gnttab_map_grant_ref((gnttab_map_grant_ref_t *)uop, count);
   3.612 +            break;
   3.613 +        case GNTTABOP_unmap_grant_ref:
   3.614 +            if ( unlikely(!array_access_ok(
   3.615 +                              uop, count, sizeof(gnttab_unmap_grant_ref_t))) )
   3.616 +                goto out;
   3.617 +            rc = gnttab_unmap_grant_ref((gnttab_unmap_grant_ref_t *)uop, 
   3.618 +                                        count);
   3.619 +            break;
   3.620 +        case GNTTABOP_setup_table:
   3.621 +            rc = gnttab_setup_table((gnttab_setup_table_t *)uop, count);
   3.622 +            break;
   3.623  #if GRANT_DEBUG
   3.624 -    case GNTTABOP_dump_table:
   3.625 -        rc = gnttab_dump_table((gnttab_dump_table_t *)uop);
   3.626 -        break;
   3.627 +        case GNTTABOP_dump_table:
   3.628 +            rc = gnttab_dump_table((gnttab_dump_table_t *)uop);
   3.629 +            break;
   3.630  #endif
   3.631 -    default:
   3.632 -        rc = -ENOSYS;
   3.633 -        break;
   3.634 -    }
   3.635 -
   3.636 -out:
   3.637 -    UNLOCK_BIGLOCK(current->domain);
   3.638 -
   3.639 +        case GNTTABOP_donate:
   3.640 +            if (unlikely(!array_access_ok(uop, count, 
   3.641 +                                          sizeof(gnttab_donate_t))))
   3.642 +                goto out;
   3.643 +            rc = gnttab_donate(uop, count);
   3.644 +            break;
   3.645 +        default:
   3.646 +            rc = -ENOSYS;
   3.647 +            break;
   3.648 +        }
   3.649 +    
   3.650 +  out:
   3.651 +    UNLOCK_BIGLOCK(d);
   3.652 +    
   3.653      return rc;
   3.654  }
   3.655  
   3.656 @@ -890,103 +1065,101 @@ gnttab_check_unmap(
   3.657       * Called a _lot_ at domain creation because pages mapped by priv domains
   3.658       * also traverse this.
   3.659       */
   3.660 -
   3.661 +    
   3.662      /* Note: If the same frame is mapped multiple times, and then one of
   3.663       *       the ptes is overwritten, which maptrack handle gets invalidated?
   3.664       * Advice: Don't do it. Explicitly unmap.
   3.665       */
   3.666 -
   3.667 +    
   3.668      unsigned int handle, ref, refcount;
   3.669      grant_table_t        *lgt, *rgt;
   3.670      active_grant_entry_t *act;
   3.671      grant_mapping_t      *map;
   3.672      int found = 0;
   3.673 -
   3.674 +    
   3.675      lgt = ld->grant_table;
   3.676 -
   3.677 +    
   3.678  #if GRANT_DEBUG_VERBOSE
   3.679 -    if ( ld->domain_id != 0 )
   3.680 -    {
   3.681 -        DPRINTK("Foreign unref rd(%d) ld(%d) frm(%x) flgs(%x).\n",
   3.682 -                rd->domain_id, ld->domain_id, frame, readonly);
   3.683 -    }
   3.684 +    if ( ld->domain_ id != 0 ) {
   3.685 +            DPRINTK("Foreign unref rd(%d) ld(%d) frm(%lx) flgs(%x).\n",
   3.686 +                    rd->domain_id, ld->domain_id, frame, readonly);
   3.687 +      }
   3.688  #endif
   3.689 -
   3.690 +    
   3.691      /* Fast exit if we're not mapping anything using grant tables */
   3.692      if ( lgt->map_count == 0 )
   3.693          return 0;
   3.694 -
   3.695 -    if ( get_domain(rd) == 0 )
   3.696 -    {
   3.697 +    
   3.698 +    if ( get_domain(rd) == 0 ) {
   3.699          DPRINTK("gnttab_check_unmap: couldn't get_domain rd(%d)\n",
   3.700                  rd->domain_id);
   3.701          return 0;
   3.702      }
   3.703 -
   3.704 +    
   3.705      rgt = rd->grant_table;
   3.706 +    
   3.707 +    for ( handle = 0; handle < lgt->maptrack_limit; handle++ ) {
   3.708  
   3.709 -    for ( handle = 0; handle < lgt->maptrack_limit; handle++ )
   3.710 -    {
   3.711          map = &lgt->maptrack[handle];
   3.712 +            
   3.713 +        if ( map->domid != rd->domain_id )
   3.714 +            continue;
   3.715 +        
   3.716 +        if ( ( map->ref_and_flags & MAPTRACK_GNTMAP_MASK ) &&
   3.717 +             ( readonly ? 1 : (!(map->ref_and_flags & GNTMAP_readonly)))) {
   3.718  
   3.719 -        if ( ( map->ref_and_flags & MAPTRACK_GNTMAP_MASK ) &&
   3.720 -             ( readonly ? 1 : (!(map->ref_and_flags & GNTMAP_readonly))))
   3.721 -        {
   3.722              ref = (map->ref_and_flags >> MAPTRACK_REF_SHIFT);
   3.723              act = &rgt->active[ref];
   3.724 -
   3.725 +                    
   3.726              spin_lock(&rgt->lock);
   3.727 -
   3.728 -            if ( act->frame != frame )
   3.729 -            {
   3.730 +                    
   3.731 +            if ( act->frame != frame ) {
   3.732                  spin_unlock(&rgt->lock);
   3.733                  continue;
   3.734              }
   3.735 -
   3.736 +                    
   3.737              refcount = act->pin & ( readonly ? GNTPIN_hstr_mask
   3.738 -                                             : GNTPIN_hstw_mask );
   3.739 -            if ( refcount == 0 )
   3.740 -            {
   3.741 +                                    : GNTPIN_hstw_mask );
   3.742 +
   3.743 +            if ( refcount == 0 ) {
   3.744                  spin_unlock(&rgt->lock);
   3.745                  continue;
   3.746              }
   3.747 -
   3.748 +                    
   3.749              /* gotcha */
   3.750              DPRINTK("Grant unref rd(%d) ld(%d) frm(%lx) flgs(%x).\n",
   3.751                      rd->domain_id, ld->domain_id, frame, readonly);
   3.752 -
   3.753 +                    
   3.754              if ( readonly )
   3.755                  act->pin -= GNTPIN_hstr_inc;
   3.756 -            else
   3.757 -            {
   3.758 +            else {
   3.759                  act->pin -= GNTPIN_hstw_inc;
   3.760 -
   3.761 +                            
   3.762                  /* any more granted writable mappings? */
   3.763 -                if ( (act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) == 0 )
   3.764 -                {
   3.765 +                if ( (act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) == 0 ) {
   3.766                      clear_bit(_GTF_writing, &rgt->shared[ref].flags);
   3.767                      put_page_type(&frame_table[frame]);
   3.768                  }
   3.769              }
   3.770 -
   3.771 -            if ( act->pin == 0 )
   3.772 -            {
   3.773 +                
   3.774 +            if ( act->pin == 0 ) {
   3.775                  clear_bit(_GTF_reading, &rgt->shared[ref].flags);
   3.776                  put_page(&frame_table[frame]);
   3.777              }
   3.778 +
   3.779              spin_unlock(&rgt->lock);
   3.780 -
   3.781 +                    
   3.782              clear_bit(GNTMAP_host_map, &map->ref_and_flags);
   3.783 -
   3.784 +                    
   3.785              if ( !(map->ref_and_flags & GNTMAP_device_map) )
   3.786                  put_maptrack_handle(lgt, handle);
   3.787 -
   3.788 +                    
   3.789              found = 1;
   3.790              break;
   3.791          }
   3.792      }
   3.793      put_domain(rd);
   3.794 -
   3.795 +    
   3.796      return found;
   3.797  }
   3.798  
   3.799 @@ -1002,8 +1175,10 @@ gnttab_prepare_for_transfer(
   3.800      int            retries = 0;
   3.801      unsigned long  target_pfn;
   3.802  
   3.803 +#if GRANT_DEBUG_VERBOSE
   3.804      DPRINTK("gnttab_prepare_for_transfer rd(%hu) ld(%hu) ref(%hu).\n",
   3.805              rd->domain_id, ld->domain_id, ref);
   3.806 +#endif
   3.807  
   3.808      if ( unlikely((rgt = rd->grant_table) == NULL) ||
   3.809           unlikely(ref >= NR_GRANT_ENTRIES) )
   3.810 @@ -1081,8 +1256,10 @@ gnttab_notify_transfer(
   3.811      grant_entry_t  *sha;
   3.812      unsigned long   pfn;
   3.813  
   3.814 +#if GRANT_DEBUG_VERBOSE
   3.815      DPRINTK("gnttab_notify_transfer rd(%hu) ld(%hu) ref(%hu).\n",
   3.816              rd->domain_id, ld->domain_id, ref);
   3.817 +#endif
   3.818  
   3.819      sha = &rd->grant_table->shared[ref];
   3.820  
     4.1 --- a/xen/arch/ia64/xen/regionreg.c	Thu Sep 01 13:01:55 2005 -0600
     4.2 +++ b/xen/arch/ia64/xen/regionreg.c	Fri Sep 02 12:31:56 2005 -0600
     4.3 @@ -116,7 +116,7 @@ int allocate_rid_range(struct domain *d,
     4.4  	ridbits = IA64_MIN_IMPL_RID_BITS;
     4.5  
     4.6  	// convert to rid_blocks and find one
     4.7 -	n_rid_blocks = ridbits - IA64_MIN_IMPL_RID_BITS + 1;
     4.8 +	n_rid_blocks = 1UL << (ridbits - IA64_MIN_IMPL_RID_BITS);
     4.9  	
    4.10  	// skip over block 0, reserved for "meta-physical mappings (and Xen)"
    4.11  	for (i = n_rid_blocks; i < MAX_RID_BLOCKS; i += n_rid_blocks) {
     5.1 --- a/xen/arch/ia64/xen/vcpu.c	Thu Sep 01 13:01:55 2005 -0600
     5.2 +++ b/xen/arch/ia64/xen/vcpu.c	Fri Sep 02 12:31:56 2005 -0600
     5.3 @@ -1315,7 +1315,8 @@ IA64FAULT vcpu_translate(VCPU *vcpu, UIN
     5.4  	/* check 1-entry TLB */
     5.5  	if ((trp = match_dtlb(vcpu,address))) {
     5.6  		dtlb_translate_count++;
     5.7 -		*pteval = trp->page_flags;
     5.8 +		//*pteval = trp->page_flags;
     5.9 +		*pteval = vcpu->arch.dtlb_pte;
    5.10  		*itir = trp->itir;
    5.11  		return IA64_NO_FAULT;
    5.12  	}
     6.1 --- a/xen/include/asm-ia64/mm.h	Thu Sep 01 13:01:55 2005 -0600
     6.2 +++ b/xen/include/asm-ia64/mm.h	Fri Sep 02 12:31:56 2005 -0600
     6.3 @@ -34,6 +34,8 @@ typedef unsigned long page_flags_t;
     6.4   */
     6.5  #define PFN_ORDER(_pfn)	((_pfn)->u.free.order)
     6.6  
     6.7 +#define PRtype_info "08x"
     6.8 +
     6.9  struct page
    6.10  {
    6.11      /* Each frame can be threaded onto a doubly-linked list. */
    6.12 @@ -210,6 +212,12 @@ void memguard_unguard_range(void *p, uns
    6.13  #define memguard_unguard_range(_p,_l)  ((void)0)
    6.14  #endif
    6.15  
    6.16 +// prototype of misc memory stuff
    6.17 +unsigned long __get_free_pages(unsigned int mask, unsigned int order);
    6.18 +void __free_pages(struct page *page, unsigned int order);
    6.19 +void *pgtable_quicklist_alloc(void);
    6.20 +void pgtable_quicklist_free(void *pgtable_entry);
    6.21 +
    6.22  // FOLLOWING FROM linux-2.6.7/include/mm.h
    6.23  
    6.24  /*
     7.1 --- a/xen/include/asm-ia64/xensystem.h	Thu Sep 01 13:01:55 2005 -0600
     7.2 +++ b/xen/include/asm-ia64/xensystem.h	Fri Sep 02 12:31:56 2005 -0600
     7.3 @@ -71,6 +71,10 @@ extern struct task_struct *vmx_ia64_swit
     7.4  } while (0)
     7.5  #endif // CONFIG_VTI
     7.6  
     7.7 +#undef switch_to
     7.8 +// FIXME SMP... see system.h, does this need to be different?
     7.9 +#define switch_to(prev,next,last)	__switch_to(prev, next, last)
    7.10 +
    7.11  #define __cmpxchg_user(ptr, new, old, _size)				\
    7.12  ({									\
    7.13  	register long __gu_r8 asm ("r8");				\
     8.1 --- a/xen/include/public/arch-ia64.h	Thu Sep 01 13:01:55 2005 -0600
     8.2 +++ b/xen/include/public/arch-ia64.h	Fri Sep 02 12:31:56 2005 -0600
     8.3 @@ -257,6 +257,8 @@ typedef mapped_regs_t vpd_t;
     8.4  typedef struct {
     8.5  	int domain_controller_evtchn;
     8.6  	unsigned int flags;
     8.7 +	unsigned short store_evtchn;
     8.8 +	unsigned long store_mfn;
     8.9  //} arch_shared_info_t;
    8.10  } arch_shared_info_t;		// DON'T PACK 
    8.11