ia64/xen-unstable

changeset 5540:78b0596ef957

bitkeeper revision 1.1726.1.5 (42b9a3d8CVbjmdABZ5J06wW5p1TtXw)

Merge bk://xen.bkbits.net/xeno-unstable.bk
into bkbits.net:/repos/x/xen-ia64/xeno-unstable-ia64.bk
author xen-ia64.adm@bkbits.net
date Wed Jun 22 17:46:00 2005 +0000 (2005-06-22)
parents a907e4db8c7e f2545bf8f4c7
children 51d5c1d35710 dca57ff5d1c1
files .rootkeys xen/arch/ia64/Makefile xen/arch/ia64/asm-offsets.c xen/arch/ia64/dom0_ops.c xen/arch/ia64/domain.c xen/arch/ia64/grant_table.c xen/arch/ia64/hypercall.c xen/arch/ia64/hyperprivop.S xen/arch/ia64/mm.c xen/arch/ia64/patch/linux-2.6.11/uaccess.h xen/arch/ia64/privop.c xen/arch/ia64/regionreg.c xen/arch/ia64/vmmu.c xen/arch/ia64/vmx_hypercall.c xen/arch/ia64/xenmisc.c xen/include/asm-ia64/config.h xen/include/asm-ia64/domain.h xen/include/asm-ia64/event.h xen/include/asm-ia64/mm.h xen/include/asm-ia64/shadow.h xen/include/asm-ia64/vmx_uaccess.h xen/include/asm-ia64/xensystem.h xen/include/public/arch-ia64.h
line diff
     1.1 --- a/.rootkeys	Wed Jun 22 17:42:58 2005 +0000
     1.2 +++ b/.rootkeys	Wed Jun 22 17:46:00 2005 +0000
     1.3 @@ -1127,6 +1127,7 @@ 421098b26C_0yoypoHqjDcJA9UrG_g xen/arch/
     1.4  421098b2PHgzf_Gg4R65YRNi_QzMKQ xen/arch/ia64/dom0_ops.c
     1.5  421098b2O7jsNfzQXA1v3rbAc1QhpA xen/arch/ia64/dom_fw.c
     1.6  421098b2ZlaBcyiuuPr3WpzaSDwg6Q xen/arch/ia64/domain.c
     1.7 +42b33bb9GLR-tzcaHalk8fz9cgK0aA xen/arch/ia64/grant_table.c
     1.8  42a08294zRikvZk_CR1iVojHjcVFZw xen/arch/ia64/hpsimserial.c
     1.9  4239e98a_HX-FCIcXtVqY0BbrDqVug xen/arch/ia64/hypercall.c
    1.10  4295e18f42gf1T-8W97A3KSlBaY1tA xen/arch/ia64/hyperprivop.S
    1.11 @@ -1134,6 +1135,7 @@ 421098b3LYAS8xJkQiGP7tiTlyBt0Q xen/arch/
    1.12  421098b3ys5GAr4z6_H1jD33oem82g xen/arch/ia64/irq.c
    1.13  4272a8e4lavI6DrTvqaIhXeR5RuKBw xen/arch/ia64/ivt.S
    1.14  421098b3Heh72KuoVlND3CH6c0B0aA xen/arch/ia64/lib/Makefile
    1.15 +42b2eaeez20voHWlBDjrqORiNg6uhg xen/arch/ia64/mm.c
    1.16  421098b3O0MYMUsmYVFy84VV_1gFwQ xen/arch/ia64/mm_init.c
    1.17  428b9f38Gp0KcPokG9Nq5v1rGk2FkA xen/arch/ia64/mmio.c
    1.18  425ae516maKAsHBJVSzs19cdRgt3Nw xen/arch/ia64/patch/linux-2.6.11/cpumask.h
    1.19 @@ -1232,6 +1234,7 @@ 421098b6M2WhsJ_ZMzFamAQcdc5gzw xen/arch/
    1.20  428b9f38PglyXM-mJJfo19ycuQrEhw xen/arch/ia64/vlsapic.c
    1.21  428b9f38EmpBsMHL3WbOZoieteBGdQ xen/arch/ia64/vmmu.c
    1.22  428b9f38hU-X5aX0MIY3EU0Yw4PjcA xen/arch/ia64/vmx_entry.S
    1.23 +42b2eaf3YR7Sfx76IvKeqfHJiU6qXw xen/arch/ia64/vmx_hypercall.c
    1.24  428b9f38S76bWI96g7uPLmE-uAcmdg xen/arch/ia64/vmx_init.c
    1.25  428b9f385AMSyCRYBsckQClQY4ZgHA xen/arch/ia64/vmx_interrupt.c
    1.26  428b9f380IOjPmj0N6eelH-WJjl1xg xen/arch/ia64/vmx_ivt.S
    1.27 @@ -1400,6 +1403,7 @@ 421098b72bPUyviWloEAIB85dGCm2Q xen/inclu
    1.28  421098b7Z6OwjZnrTZkh34DoDfcjrA xen/include/asm-ia64/regionreg.h
    1.29  421098b707cY5YluUcWK5Pc-71ETVw xen/include/asm-ia64/regs.h
    1.30  4214e2f3fbO_n9Z1kIcBR83d7W4OJw xen/include/asm-ia64/serial.h
    1.31 +42b89683nnFDAElJewfm2JxG-pv1BQ xen/include/asm-ia64/shadow.h
    1.32  429fb3bc53qJOyKJCBfhDNmTasj8Gw xen/include/asm-ia64/slab.h
    1.33  421098b7GkWOnlzSmPvNAhByOSZ1Dw xen/include/asm-ia64/time.h
    1.34  421098b7FK3xgShpnH0I0Ou3O4fJ2Q xen/include/asm-ia64/tlb.h
    1.35 @@ -1413,6 +1417,7 @@ 428b9f387tov0OtOEeF8fVWSR2v5Pg xen/inclu
    1.36  428b9f38is0zTsIm96_BKo4MLw0SzQ xen/include/asm-ia64/vmx_pal_vsa.h
    1.37  428b9f38iDqbugHUheJrcTCD7zlb4g xen/include/asm-ia64/vmx_phy_mode.h
    1.38  428b9f38grd_B0AGB1yp0Gi2befHaQ xen/include/asm-ia64/vmx_platform.h
    1.39 +42b8e0d63B41CDo2Nqmf8Vt0_RercA xen/include/asm-ia64/vmx_uaccess.h
    1.40  428b9f38XgwHchZEpOzRtWfz0agFNQ xen/include/asm-ia64/vmx_vcpu.h
    1.41  428b9f38tDTTJbkoONcAB9ODP8CiVg xen/include/asm-ia64/vmx_vpd.h
    1.42  428b9f38_o0U5uJqmxZf_bqi6_PqVw xen/include/asm-ia64/vtm.h
     2.1 --- a/xen/arch/ia64/Makefile	Wed Jun 22 17:42:58 2005 +0000
     2.2 +++ b/xen/arch/ia64/Makefile	Wed Jun 22 17:46:00 2005 +0000
     2.3 @@ -10,7 +10,7 @@ OBJS = xensetup.o setup.o time.o irq.o i
     2.4  	extable.o linuxextable.o xenirq.o xentime.o \
     2.5  	regionreg.o entry.o unaligned.o privop.o vcpu.o \
     2.6  	irq_ia64.o irq_lsapic.o vhpt.o xenasm.o hyperprivop.o dom_fw.o \
     2.7 -	sn_console.o
     2.8 +	grant_table.o sn_console.o
     2.9  
    2.10  ifeq ($(CONFIG_VTI),y)
    2.11  OBJS += vmx_init.o vmx_virt.o vmx_vcpu.o vmx_process.o vmx_vsa.o vmx_ivt.o \
     3.1 --- a/xen/arch/ia64/asm-offsets.c	Wed Jun 22 17:42:58 2005 +0000
     3.2 +++ b/xen/arch/ia64/asm-offsets.c	Wed Jun 22 17:46:00 2005 +0000
     3.3 @@ -54,11 +54,14 @@ void foo(void)
     3.4  	DEFINE(XSI_BANKNUM_OFS, offsetof(vcpu_info_t, arch.banknum));
     3.5  	DEFINE(XSI_BANK0_OFS, offsetof(vcpu_info_t, arch.bank0_regs[0]));
     3.6  	DEFINE(XSI_BANK1_OFS, offsetof(vcpu_info_t, arch.bank1_regs[0]));
     3.7 +	DEFINE(XSI_RR0_OFS, offsetof(vcpu_info_t, arch.rrs[0]));
     3.8  	DEFINE(XSI_METAPHYS_OFS, offsetof(vcpu_info_t, arch.metaphysical_mode));
     3.9  	DEFINE(XSI_PRECOVER_IFS_OFS, offsetof(vcpu_info_t, arch.precover_ifs));
    3.10  	DEFINE(XSI_INCOMPL_REG_OFS, offsetof(vcpu_info_t, arch.incomplete_regframe));
    3.11  	DEFINE(XSI_PEND_OFS, offsetof(vcpu_info_t, arch.pending_interruption));
    3.12  	DEFINE(XSI_RR0_OFS, offsetof(vcpu_info_t, arch.rrs[0]));
    3.13 +	DEFINE(XSI_TPR_OFS, offsetof(vcpu_info_t, arch.tpr));
    3.14 +	DEFINE(XSI_ITV_OFS, offsetof(vcpu_info_t, arch.itv));
    3.15  	//DEFINE(IA64_TASK_BLOCKED_OFFSET,offsetof (struct task_struct, blocked));
    3.16  	//DEFINE(IA64_TASK_CLEAR_CHILD_TID_OFFSET,offsetof (struct task_struct, clear_child_tid));
    3.17  	//DEFINE(IA64_TASK_GROUP_LEADER_OFFSET, offsetof (struct task_struct, group_leader));
    3.18 @@ -78,8 +81,13 @@ void foo(void)
    3.19  	DEFINE(IA64_VCPU_IRR0_OFFSET, offsetof (struct vcpu, arch.irr[0]));
    3.20  	DEFINE(IA64_VCPU_IRR3_OFFSET, offsetof (struct vcpu, arch.irr[3]));
    3.21  	DEFINE(IA64_VCPU_INSVC3_OFFSET, offsetof (struct vcpu, arch.insvc[3]));
    3.22 +	DEFINE(IA64_VCPU_STARTING_RID_OFFSET, offsetof (struct vcpu, arch.starting_rid));
    3.23 +	DEFINE(IA64_VCPU_ENDING_RID_OFFSET, offsetof (struct vcpu, arch.ending_rid));
    3.24 +	DEFINE(IA64_VCPU_DOMAIN_ITM_OFFSET, offsetof (struct vcpu, arch.domain_itm));
    3.25 +	DEFINE(IA64_VCPU_DOMAIN_ITM_LAST_OFFSET, offsetof (struct vcpu, arch.domain_itm_last));
    3.26  
    3.27  	BLANK();
    3.28 +	DEFINE(IA64_CPUINFO_ITM_NEXT_OFFSET, offsetof (struct cpuinfo_ia64, itm_next));
    3.29  
    3.30  	//DEFINE(IA64_SIGHAND_SIGLOCK_OFFSET,offsetof (struct sighand_struct, siglock));
    3.31  
     4.1 --- a/xen/arch/ia64/dom0_ops.c	Wed Jun 22 17:42:58 2005 +0000
     4.2 +++ b/xen/arch/ia64/dom0_ops.c	Wed Jun 22 17:46:00 2005 +0000
     4.3 @@ -27,6 +27,128 @@ long arch_do_dom0_op(dom0_op_t *op, dom0
     4.4  
     4.5      switch ( op->cmd )
     4.6      {
     4.7 +    case DOM0_GETPAGEFRAMEINFO:
     4.8 +    {
     4.9 +        struct pfn_info *page;
    4.10 +        unsigned long pfn = op->u.getpageframeinfo.pfn;
    4.11 +        domid_t dom = op->u.getpageframeinfo.domain;
    4.12 +        struct domain *d;
    4.13 +
    4.14 +        ret = -EINVAL;
    4.15 +
    4.16 +        if ( unlikely(pfn >= max_page) || 
    4.17 +             unlikely((d = find_domain_by_id(dom)) == NULL) )
    4.18 +            break;
    4.19 +
    4.20 +        page = &frame_table[pfn];
    4.21 +
    4.22 +        if ( likely(get_page(page, d)) )
    4.23 +        {
    4.24 +            ret = 0;
    4.25 +
    4.26 +            op->u.getpageframeinfo.type = NOTAB;
    4.27 +
    4.28 +            if ( (page->u.inuse.type_info & PGT_count_mask) != 0 )
    4.29 +            {
    4.30 +                switch ( page->u.inuse.type_info & PGT_type_mask )
    4.31 +                {
    4.32 +		default:
    4.33 +		    panic("No such page type\n");
    4.34 +                    break;
    4.35 +                }
    4.36 +            }
    4.37 +            
    4.38 +            put_page(page);
    4.39 +        }
    4.40 +
    4.41 +        put_domain(d);
    4.42 +
    4.43 +        copy_to_user(u_dom0_op, op, sizeof(*op));
    4.44 +    }
    4.45 +    break;
    4.46 +
    4.47 +    case DOM0_GETPAGEFRAMEINFO2:
    4.48 +    {
    4.49 +#define GPF2_BATCH 128
    4.50 +        int n,j;
    4.51 +        int num = op->u.getpageframeinfo2.num;
    4.52 +        domid_t dom = op->u.getpageframeinfo2.domain;
    4.53 +        unsigned long *s_ptr = (unsigned long*) op->u.getpageframeinfo2.array;
    4.54 +        struct domain *d;
    4.55 +        unsigned long *l_arr;
    4.56 +        ret = -ESRCH;
    4.57 +
    4.58 +        if ( unlikely((d = find_domain_by_id(dom)) == NULL) )
    4.59 +            break;
    4.60 +
    4.61 +        if ( unlikely(num > 1024) )
    4.62 +        {
    4.63 +            ret = -E2BIG;
    4.64 +            break;
    4.65 +        }
    4.66 +
    4.67 +        l_arr = (unsigned long *)alloc_xenheap_page();
    4.68 + 
    4.69 +        ret = 0;
    4.70 +        for( n = 0; n < num; )
    4.71 +        {
    4.72 +            int k = ((num-n)>GPF2_BATCH)?GPF2_BATCH:(num-n);
    4.73 +
    4.74 +            if ( copy_from_user(l_arr, &s_ptr[n], k*sizeof(unsigned long)) )
    4.75 +            {
    4.76 +                ret = -EINVAL;
    4.77 +                break;
    4.78 +            }
    4.79 +     
    4.80 +            for( j = 0; j < k; j++ )
    4.81 +            {      
    4.82 +                struct pfn_info *page;
    4.83 +                unsigned long mfn = l_arr[j];
    4.84 +
    4.85 +                if ( unlikely(mfn >= max_page) )
    4.86 +                    goto e2_err;
    4.87 +
    4.88 +                page = &frame_table[mfn];
    4.89 +  
    4.90 +                if ( likely(get_page(page, d)) )
    4.91 +                {
    4.92 +                    unsigned long type = 0;
    4.93 +
    4.94 +                    switch( page->u.inuse.type_info & PGT_type_mask )
    4.95 +                    {
    4.96 +		    default:
    4.97 +			panic("No such page type\n");
    4.98 +			break;
    4.99 +                    }
   4.100 +
   4.101 +                    if ( page->u.inuse.type_info & PGT_pinned )
   4.102 +                        type |= LPINTAB;
   4.103 +                    l_arr[j] |= type;
   4.104 +                    put_page(page);
   4.105 +                }
   4.106 +                else
   4.107 +                {
   4.108 +                e2_err:
   4.109 +                    l_arr[j] |= XTAB;
   4.110 +                }
   4.111 +
   4.112 +            }
   4.113 +
   4.114 +            if ( copy_to_user(&s_ptr[n], l_arr, k*sizeof(unsigned long)) )
   4.115 +            {
   4.116 +                ret = -EINVAL;
   4.117 +                break;
   4.118 +            }
   4.119 +
   4.120 +            n += j;
   4.121 +        }
   4.122 +
   4.123 +        free_xenheap_page((unsigned long)l_arr);
   4.124 +
   4.125 +        put_domain(d);
   4.126 +    }
   4.127 +    break;
   4.128 +#ifndef CONFIG_VTI
   4.129      /*
   4.130       * NOTE: DOM0_GETMEMLIST has somewhat different semantics on IA64 -
   4.131       * it actually allocates and maps pages.
   4.132 @@ -70,7 +192,42 @@ long arch_do_dom0_op(dom0_op_t *op, dom0
   4.133          }
   4.134      }
   4.135      break;
   4.136 +#else
   4.137 +    case DOM0_GETMEMLIST:
   4.138 +    {
   4.139 +	int i;
   4.140 +	struct domain *d = find_domain_by_id(op->u.getmemlist.domain);
   4.141 +	unsigned long max_pfns = op->u.getmemlist.max_pfns;
   4.142 +	unsigned long pfn;
   4.143 +	unsigned long *buffer = op->u.getmemlist.buffer;
   4.144 +	struct list_head *list_ent;
   4.145  
   4.146 +	ret = -EINVAL;
   4.147 +	if (!d) {
   4.148 +	    ret = 0;
   4.149 +
   4.150 +	    spin_lock(&d->page_alloc_lock);
   4.151 +	    list_ent = d->page_list.next;
   4.152 +	    for (i = 0; (i < max_pfns) && (list_ent != &d->page_list); i++) {
   4.153 +		pfn = list_entry(list_ent, struct pfn_info, list) -
   4.154 +		    frame_table;
   4.155 +		if (put_user(pfn, buffer)) {
   4.156 +		    ret = -EFAULT;
   4.157 +		    break;
   4.158 +		}
   4.159 +		buffer++;
   4.160 +		list_ent = frame_table[pfn].list.next;
   4.161 +	    }
   4.162 +	    spin_unlock(&d->page_alloc_lock);
   4.163 +
   4.164 +	    op->u.getmemlist.num_pfns = i;
   4.165 +	    copy_to_user(u_dom0_op, op, sizeof(*op));
   4.166 +
   4.167 +	    put_domain(d);
   4.168 +	}
   4.169 +    }
   4.170 +    break;
   4.171 +#endif // CONFIG_VTI
   4.172      default:
   4.173          ret = -ENOSYS;
   4.174  
     5.1 --- a/xen/arch/ia64/domain.c	Wed Jun 22 17:42:58 2005 +0000
     5.2 +++ b/xen/arch/ia64/domain.c	Wed Jun 22 17:46:00 2005 +0000
     5.3 @@ -258,6 +258,8 @@ void arch_do_createdomain(struct vcpu *v
     5.4  #define DOMAIN_RID_BITS_DEFAULT 18
     5.5  	if (!allocate_rid_range(d,DOMAIN_RID_BITS_DEFAULT)) // FIXME
     5.6  		BUG();
     5.7 +	v->arch.starting_rid = d->arch.starting_rid;
     5.8 +	v->arch.ending_rid = d->arch.ending_rid;
     5.9  	// the following will eventually need to be negotiated dynamically
    5.10  	d->xen_vastart = 0xf000000000000000;
    5.11  	d->xen_vaend = 0xf300000000000000;
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xen/arch/ia64/grant_table.c	Wed Jun 22 17:46:00 2005 +0000
     6.3 @@ -0,0 +1,1291 @@
     6.4 +#ifndef CONFIG_VTI
     6.5 +// temporarily in arch/ia64 until can merge into common/grant_table.c
     6.6 +/******************************************************************************
     6.7 + * common/grant_table.c
     6.8 + * 
     6.9 + * Mechanism for granting foreign access to page frames, and receiving
    6.10 + * page-ownership transfers.
    6.11 + * 
    6.12 + * Copyright (c) 2005 Christopher Clark
    6.13 + * Copyright (c) 2004 K A Fraser
    6.14 + * 
    6.15 + * This program is free software; you can redistribute it and/or modify
    6.16 + * it under the terms of the GNU General Public License as published by
    6.17 + * the Free Software Foundation; either version 2 of the License, or
    6.18 + * (at your option) any later version.
    6.19 + * 
    6.20 + * This program is distributed in the hope that it will be useful,
    6.21 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.22 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.23 + * GNU General Public License for more details.
    6.24 + * 
    6.25 + * You should have received a copy of the GNU General Public License
    6.26 + * along with this program; if not, write to the Free Software
    6.27 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    6.28 + */
    6.29 +
    6.30 +#define GRANT_DEBUG 0
    6.31 +#define GRANT_DEBUG_VERBOSE 0
    6.32 +
    6.33 +#include <xen/config.h>
    6.34 +#include <xen/lib.h>
    6.35 +#include <xen/sched.h>
    6.36 +#include <xen/shadow.h>
    6.37 +#include <xen/mm.h>
    6.38 +#ifdef __ia64__
    6.39 +#define __addr_ok(a) 1	// FIXME-ia64: a variant of access_ok??
    6.40 +// FIXME-ia64: need to implement real cmpxchg_user on ia64
    6.41 +//#define cmpxchg_user(_p,_o,_n) ((*_p == _o) ? ((*_p = _n), 0) : ((_o = *_p), 0))
    6.42 +// FIXME-ia64: these belong in an asm/grant_table.h... PAGE_SIZE different
    6.43 +#undef ORDER_GRANT_FRAMES
    6.44 +//#undef NUM_GRANT_FRAMES
    6.45 +#define ORDER_GRANT_FRAMES 0
    6.46 +//#define NUM_GRANT_FRAMES  (1U << ORDER_GRANT_FRAMES)
    6.47 +#endif
    6.48 +
    6.49 +#define PIN_FAIL(_lbl, _rc, _f, _a...)   \
    6.50 +    do {                           \
    6.51 +        DPRINTK( _f, ## _a );      \
    6.52 +        rc = (_rc);                \
    6.53 +        goto _lbl;                 \
    6.54 +    } while ( 0 )
    6.55 +
    6.56 +static inline int
    6.57 +get_maptrack_handle(
    6.58 +    grant_table_t *t)
    6.59 +{
    6.60 +    unsigned int h;
    6.61 +    if ( unlikely((h = t->maptrack_head) == t->maptrack_limit) )
    6.62 +        return -1;
    6.63 +    t->maptrack_head = t->maptrack[h].ref_and_flags >> MAPTRACK_REF_SHIFT;
    6.64 +    t->map_count++;
    6.65 +    return h;
    6.66 +}
    6.67 +
    6.68 +static inline void
    6.69 +put_maptrack_handle(
    6.70 +    grant_table_t *t, int handle)
    6.71 +{
    6.72 +    t->maptrack[handle].ref_and_flags = t->maptrack_head << MAPTRACK_REF_SHIFT;
    6.73 +    t->maptrack_head = handle;
    6.74 +    t->map_count--;
    6.75 +}
    6.76 +
    6.77 +static int
    6.78 +__gnttab_activate_grant_ref(
    6.79 +    struct domain          *mapping_d,          /* IN */
    6.80 +    struct vcpu     *mapping_ed,
    6.81 +    struct domain          *granting_d,
    6.82 +    grant_ref_t             ref,
    6.83 +    u16                     dev_hst_ro_flags,
    6.84 +    unsigned long           host_virt_addr,
    6.85 +    unsigned long          *pframe )            /* OUT */
    6.86 +{
    6.87 +    domid_t               sdom;
    6.88 +    u16                   sflags;
    6.89 +    active_grant_entry_t *act;
    6.90 +    grant_entry_t        *sha;
    6.91 +    s16                   rc = 1;
    6.92 +    unsigned long         frame = 0;
    6.93 +    int                   retries = 0;
    6.94 +
    6.95 +    /*
    6.96 +     * Objectives of this function:
    6.97 +     * . Make the record ( granting_d, ref ) active, if not already.
    6.98 +     * . Update shared grant entry of owner, indicating frame is mapped.
    6.99 +     * . Increment the owner act->pin reference counts.
   6.100 +     * . get_page on shared frame if new mapping.
   6.101 +     * . get_page_type if this is first RW mapping of frame.
   6.102 +     * . Add PTE to virtual address space of mapping_d, if necessary.
   6.103 +     * Returns:
   6.104 +     * .  -ve: error
   6.105 +     * .    1: ok
   6.106 +     * .    0: ok and TLB invalidate of host_virt_addr needed.
   6.107 +     *
   6.108 +     * On success, *pframe contains mfn.
   6.109 +     */
   6.110 +
   6.111 +    /*
   6.112 +     * We bound the number of times we retry CMPXCHG on memory locations that
   6.113 +     * we share with a guest OS. The reason is that the guest can modify that
   6.114 +     * location at a higher rate than we can read-modify-CMPXCHG, so the guest
   6.115 +     * could cause us to livelock. There are a few cases where it is valid for
   6.116 +     * the guest to race our updates (e.g., to change the GTF_readonly flag),
   6.117 +     * so we allow a few retries before failing.
   6.118 +     */
   6.119 +
   6.120 +    act = &granting_d->grant_table->active[ref];
   6.121 +    sha = &granting_d->grant_table->shared[ref];
   6.122 +
   6.123 +    spin_lock(&granting_d->grant_table->lock);
   6.124 +
   6.125 +    if ( act->pin == 0 )
   6.126 +    {
   6.127 +        /* CASE 1: Activating a previously inactive entry. */
   6.128 +
   6.129 +        sflags = sha->flags;
   6.130 +        sdom   = sha->domid;
   6.131 +
   6.132 +        for ( ; ; )
   6.133 +        {
   6.134 +            u32 scombo, prev_scombo, new_scombo;
   6.135 +
   6.136 +            if ( unlikely((sflags & GTF_type_mask) != GTF_permit_access) ||
   6.137 +                 unlikely(sdom != mapping_d->domain_id) )
   6.138 +                PIN_FAIL(unlock_out, GNTST_general_error,
   6.139 +                         "Bad flags (%x) or dom (%d). (NB. expected dom %d)\n",
   6.140 +                        sflags, sdom, mapping_d->domain_id);
   6.141 +
   6.142 +            /* Merge two 16-bit values into a 32-bit combined update. */
   6.143 +            /* NB. Endianness! */
   6.144 +            prev_scombo = scombo = ((u32)sdom << 16) | (u32)sflags;
   6.145 +
   6.146 +            new_scombo = scombo | GTF_reading;
   6.147 +            if ( !(dev_hst_ro_flags & GNTMAP_readonly) )
   6.148 +            {
   6.149 +                new_scombo |= GTF_writing;
   6.150 +                if ( unlikely(sflags & GTF_readonly) )
   6.151 +                    PIN_FAIL(unlock_out, GNTST_general_error,
   6.152 +                             "Attempt to write-pin a r/o grant entry.\n");
   6.153 +            }
   6.154 +
   6.155 +            /* NB. prev_scombo is updated in place to seen value. */
   6.156 +            if ( unlikely(cmpxchg_user((u32 *)&sha->flags,
   6.157 +                                       prev_scombo,
   6.158 +                                       new_scombo)) )
   6.159 +                PIN_FAIL(unlock_out, GNTST_general_error,
   6.160 +                         "Fault while modifying shared flags and domid.\n");
   6.161 +
   6.162 +            /* Did the combined update work (did we see what we expected?). */
   6.163 +            if ( likely(prev_scombo == scombo) )
   6.164 +                break;
   6.165 +
   6.166 +            if ( retries++ == 4 )
   6.167 +                PIN_FAIL(unlock_out, GNTST_general_error,
   6.168 +                         "Shared grant entry is unstable.\n");
   6.169 +
   6.170 +            /* Didn't see what we expected. Split out the seen flags & dom. */
   6.171 +            /* NB. Endianness! */
   6.172 +            sflags = (u16)prev_scombo;
   6.173 +            sdom   = (u16)(prev_scombo >> 16);
   6.174 +        }
   6.175 +
   6.176 +        /* rmb(); */ /* not on x86 */
   6.177 +
   6.178 +        frame = __gpfn_to_mfn_foreign(granting_d, sha->frame);
   6.179 +
   6.180 +#ifdef __ia64__
   6.181 +// FIXME-ia64: any error checking need to be done here?
   6.182 +#else
   6.183 +        if ( unlikely(!pfn_valid(frame)) ||
   6.184 +             unlikely(!((dev_hst_ro_flags & GNTMAP_readonly) ?
   6.185 +                        get_page(&frame_table[frame], granting_d) :
   6.186 +                        get_page_and_type(&frame_table[frame], granting_d,
   6.187 +                                          PGT_writable_page))) )
   6.188 +        {
   6.189 +            clear_bit(_GTF_writing, &sha->flags);
   6.190 +            clear_bit(_GTF_reading, &sha->flags);
   6.191 +            PIN_FAIL(unlock_out, GNTST_general_error,
   6.192 +                     "Could not pin the granted frame (%lx)!\n", frame);
   6.193 +        }
   6.194 +#endif
   6.195 +
   6.196 +        if ( dev_hst_ro_flags & GNTMAP_device_map )
   6.197 +            act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ?
   6.198 +                GNTPIN_devr_inc : GNTPIN_devw_inc;
   6.199 +        if ( dev_hst_ro_flags & GNTMAP_host_map )
   6.200 +            act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ?
   6.201 +                GNTPIN_hstr_inc : GNTPIN_hstw_inc;
   6.202 +        act->domid = sdom;
   6.203 +        act->frame = frame;
   6.204 +    }
   6.205 +    else 
   6.206 +    {
   6.207 +        /* CASE 2: Active modications to an already active entry. */
   6.208 +
   6.209 +        /*
   6.210 +         * A cheesy check for possible pin-count overflow.
   6.211 +         * A more accurate check cannot be done with a single comparison.
   6.212 +         */
   6.213 +        if ( (act->pin & 0x80808080U) != 0 )
   6.214 +            PIN_FAIL(unlock_out, ENOSPC,
   6.215 +                     "Risk of counter overflow %08x\n", act->pin);
   6.216 +
   6.217 +        frame = act->frame;
   6.218 +
   6.219 +        if ( !(dev_hst_ro_flags & GNTMAP_readonly) && 
   6.220 +             !((sflags = sha->flags) & GTF_writing) )
   6.221 +        {
   6.222 +            for ( ; ; )
   6.223 +            {
   6.224 +                u16 prev_sflags;
   6.225 +                
   6.226 +                if ( unlikely(sflags & GTF_readonly) )
   6.227 +                    PIN_FAIL(unlock_out, GNTST_general_error,
   6.228 +                             "Attempt to write-pin a r/o grant entry.\n");
   6.229 +
   6.230 +                prev_sflags = sflags;
   6.231 +
   6.232 +                /* NB. prev_sflags is updated in place to seen value. */
   6.233 +                if ( unlikely(cmpxchg_user(&sha->flags, prev_sflags, 
   6.234 +                                           prev_sflags | GTF_writing)) )
   6.235 +                    PIN_FAIL(unlock_out, GNTST_general_error,
   6.236 +                         "Fault while modifying shared flags.\n");
   6.237 +
   6.238 +                if ( likely(prev_sflags == sflags) )
   6.239 +                    break;
   6.240 +
   6.241 +                if ( retries++ == 4 )
   6.242 +                    PIN_FAIL(unlock_out, GNTST_general_error,
   6.243 +                             "Shared grant entry is unstable.\n");
   6.244 +
   6.245 +                sflags = prev_sflags;
   6.246 +            }
   6.247 +
   6.248 +#ifdef __ia64__
   6.249 +// FIXME-ia64: any error checking need to be done here?
   6.250 +#else
   6.251 +            if ( unlikely(!get_page_type(&frame_table[frame],
   6.252 +                                         PGT_writable_page)) )
   6.253 +            {
   6.254 +                clear_bit(_GTF_writing, &sha->flags);
   6.255 +                PIN_FAIL(unlock_out, GNTST_general_error,
   6.256 +                         "Attempt to write-pin a unwritable page.\n");
   6.257 +            }
   6.258 +#endif
   6.259 +        }
   6.260 +
   6.261 +        if ( dev_hst_ro_flags & GNTMAP_device_map )
   6.262 +            act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ? 
   6.263 +                GNTPIN_devr_inc : GNTPIN_devw_inc;
   6.264 +
   6.265 +        if ( dev_hst_ro_flags & GNTMAP_host_map )
   6.266 +            act->pin += (dev_hst_ro_flags & GNTMAP_readonly) ?
   6.267 +                GNTPIN_hstr_inc : GNTPIN_hstw_inc;
   6.268 +    }
   6.269 +
   6.270 +    /*
   6.271 +     * At this point:
   6.272 +     * act->pin updated to reflect mapping.
   6.273 +     * sha->flags updated to indicate to granting domain mapping done.
   6.274 +     * frame contains the mfn.
   6.275 +     */
   6.276 +
   6.277 +    spin_unlock(&granting_d->grant_table->lock);
   6.278 +
   6.279 +#ifdef __ia64__
   6.280 +// FIXME-ia64: any error checking need to be done here?
   6.281 +#else
   6.282 +    if ( (host_virt_addr != 0) && (dev_hst_ro_flags & GNTMAP_host_map) )
   6.283 +    {
   6.284 +        /* Write update into the pagetable. */
   6.285 +        l1_pgentry_t pte;
   6.286 +        pte = l1e_from_pfn(frame, _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
   6.287 +        if ( !(dev_hst_ro_flags & GNTMAP_readonly) )
   6.288 +            l1e_add_flags(pte,_PAGE_RW);
   6.289 +        rc = update_grant_va_mapping( host_virt_addr, pte, 
   6.290 +                       mapping_d, mapping_ed );
   6.291 +
   6.292 +        /*
   6.293 +         * IMPORTANT: (rc == 0) => must flush / invalidate entry in TLB.
   6.294 +         * This is done in the outer gnttab_map_grant_ref.
   6.295 +         */
   6.296 +
   6.297 +        if ( rc < 0 )
   6.298 +        {
   6.299 +            /* Failure: undo and abort. */
   6.300 +
   6.301 +            spin_lock(&granting_d->grant_table->lock);
   6.302 +
   6.303 +            if ( dev_hst_ro_flags & GNTMAP_readonly )
   6.304 +            {
   6.305 +                act->pin -= GNTPIN_hstr_inc;
   6.306 +            }
   6.307 +            else
   6.308 +            {
   6.309 +                act->pin -= GNTPIN_hstw_inc;
   6.310 +                if ( (act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) == 0 )
   6.311 +                {
   6.312 +                    clear_bit(_GTF_writing, &sha->flags);
   6.313 +                    put_page_type(&frame_table[frame]);
   6.314 +                }
   6.315 +            }
   6.316 +
   6.317 +            if ( act->pin == 0 )
   6.318 +            {
   6.319 +                clear_bit(_GTF_reading, &sha->flags);
   6.320 +                put_page(&frame_table[frame]);
   6.321 +            }
   6.322 +
   6.323 +            spin_unlock(&granting_d->grant_table->lock);
   6.324 +        }
   6.325 +
   6.326 +    }
   6.327 +#endif
   6.328 +
   6.329 +    *pframe = frame;
   6.330 +    return rc;
   6.331 +
   6.332 + unlock_out:
   6.333 +    spin_unlock(&granting_d->grant_table->lock);
   6.334 +    return rc;
   6.335 +}
   6.336 +
   6.337 +/*
   6.338 + * Returns 0 if TLB flush / invalidate required by caller.
   6.339 + * va will indicate the address to be invalidated.
   6.340 + */
   6.341 +static int
   6.342 +__gnttab_map_grant_ref(
   6.343 +    gnttab_map_grant_ref_t *uop,
   6.344 +    unsigned long *va)
   6.345 +{
   6.346 +    domid_t               dom;
   6.347 +    grant_ref_t           ref;
   6.348 +    struct domain        *ld, *rd;
   6.349 +    struct vcpu   *led;
   6.350 +    u16                   dev_hst_ro_flags;
   6.351 +    int                   handle;
   6.352 +    unsigned long         frame = 0, host_virt_addr;
   6.353 +    int                   rc;
   6.354 +
   6.355 +    led = current;
   6.356 +    ld = led->domain;
   6.357 +
   6.358 +    /* Bitwise-OR avoids short-circuiting which screws control flow. */
   6.359 +    if ( unlikely(__get_user(dom, &uop->dom) |
   6.360 +                  __get_user(ref, &uop->ref) |
   6.361 +                  __get_user(host_virt_addr, &uop->host_virt_addr) |
   6.362 +                  __get_user(dev_hst_ro_flags, &uop->flags)) )
   6.363 +    {
   6.364 +        DPRINTK("Fault while reading gnttab_map_grant_ref_t.\n");
   6.365 +        return -EFAULT; /* don't set status */
   6.366 +    }
   6.367 +
   6.368 +
   6.369 +    if ( ((host_virt_addr != 0) || (dev_hst_ro_flags & GNTMAP_host_map)) &&
   6.370 +         unlikely(!__addr_ok(host_virt_addr)))
   6.371 +    {
   6.372 +        DPRINTK("Bad virtual address (%lx) or flags (%x).\n",
   6.373 +                host_virt_addr, dev_hst_ro_flags);
   6.374 +        (void)__put_user(GNTST_bad_virt_addr, &uop->handle);
   6.375 +        return GNTST_bad_gntref;
   6.376 +    }
   6.377 +
   6.378 +    if ( unlikely(ref >= NR_GRANT_ENTRIES) ||
   6.379 +         unlikely((dev_hst_ro_flags &
   6.380 +                   (GNTMAP_device_map|GNTMAP_host_map)) == 0) )
   6.381 +    {
   6.382 +        DPRINTK("Bad ref (%d) or flags (%x).\n", ref, dev_hst_ro_flags);
   6.383 +        (void)__put_user(GNTST_bad_gntref, &uop->handle);
   6.384 +        return GNTST_bad_gntref;
   6.385 +    }
   6.386 +
   6.387 +    if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
   6.388 +         unlikely(ld == rd) )
   6.389 +    {
   6.390 +        if ( rd != NULL )
   6.391 +            put_domain(rd);
   6.392 +        DPRINTK("Could not find domain %d\n", dom);
   6.393 +        (void)__put_user(GNTST_bad_domain, &uop->handle);
   6.394 +        return GNTST_bad_domain;
   6.395 +    }
   6.396 +
   6.397 +    /* Get a maptrack handle. */
   6.398 +    if ( unlikely((handle = get_maptrack_handle(ld->grant_table)) == -1) )
   6.399 +    {
   6.400 +        int              i;
   6.401 +        grant_mapping_t *new_mt;
   6.402 +        grant_table_t   *lgt      = ld->grant_table;
   6.403 +
   6.404 +        /* Grow the maptrack table. */
   6.405 +        new_mt = alloc_xenheap_pages(lgt->maptrack_order + 1);
   6.406 +        if ( new_mt == NULL )
   6.407 +        {
   6.408 +            put_domain(rd);
   6.409 +            DPRINTK("No more map handles available\n");
   6.410 +            (void)__put_user(GNTST_no_device_space, &uop->handle);
   6.411 +            return GNTST_no_device_space;
   6.412 +        }
   6.413 +
   6.414 +        memcpy(new_mt, lgt->maptrack, PAGE_SIZE << lgt->maptrack_order);
   6.415 +        for ( i = lgt->maptrack_limit; i < (lgt->maptrack_limit << 1); i++ )
   6.416 +            new_mt[i].ref_and_flags = (i+1) << MAPTRACK_REF_SHIFT;
   6.417 +
   6.418 +        free_xenheap_pages(lgt->maptrack, lgt->maptrack_order);
   6.419 +        lgt->maptrack          = new_mt;
   6.420 +        lgt->maptrack_order   += 1;
   6.421 +        lgt->maptrack_limit  <<= 1;
   6.422 +
   6.423 +        printk("Doubled maptrack size\n");
   6.424 +        handle = get_maptrack_handle(ld->grant_table);
   6.425 +    }
   6.426 +
   6.427 +#if GRANT_DEBUG_VERBOSE
   6.428 +    DPRINTK("Mapping grant ref (%hu) for domain (%hu) with flags (%x)\n",
   6.429 +            ref, dom, dev_hst_ro_flags);
   6.430 +#endif
   6.431 +
   6.432 +    if ( 0 <= ( rc = __gnttab_activate_grant_ref( ld, led, rd, ref,
   6.433 +                                                  dev_hst_ro_flags,
   6.434 +                                                  host_virt_addr, &frame)))
   6.435 +    {
   6.436 +        /*
   6.437 +         * Only make the maptrack live _after_ writing the pte, in case we 
   6.438 +         * overwrite the same frame number, causing a maptrack walk to find it
   6.439 +         */
   6.440 +        ld->grant_table->maptrack[handle].domid = dom;
   6.441 +
   6.442 +        ld->grant_table->maptrack[handle].ref_and_flags
   6.443 +            = (ref << MAPTRACK_REF_SHIFT) |
   6.444 +              (dev_hst_ro_flags & MAPTRACK_GNTMAP_MASK);
   6.445 +
   6.446 +        (void)__put_user(frame, &uop->dev_bus_addr);
   6.447 +
   6.448 +        if ( dev_hst_ro_flags & GNTMAP_host_map )
   6.449 +            *va = host_virt_addr;
   6.450 +
   6.451 +        (void)__put_user(handle, &uop->handle);
   6.452 +    }
   6.453 +    else
   6.454 +    {
   6.455 +        (void)__put_user(rc, &uop->handle);
   6.456 +        put_maptrack_handle(ld->grant_table, handle);
   6.457 +    }
   6.458 +
   6.459 +    put_domain(rd);
   6.460 +    return rc;
   6.461 +}
   6.462 +
   6.463 +static long
   6.464 +gnttab_map_grant_ref(
   6.465 +    gnttab_map_grant_ref_t *uop, unsigned int count)
   6.466 +{
   6.467 +    int i, flush = 0;
   6.468 +    unsigned long va = 0;
   6.469 +
   6.470 +    for ( i = 0; i < count; i++ )
   6.471 +        if ( __gnttab_map_grant_ref(&uop[i], &va) == 0 )
   6.472 +            flush++;
   6.473 +
   6.474 +#ifdef __ia64__
   6.475 +// FIXME-ia64: probably need to do something here to avoid stale mappings?
   6.476 +#else
   6.477 +    if ( flush == 1 )
   6.478 +        flush_tlb_one_mask(current->domain->cpumask, va);
   6.479 +    else if ( flush != 0 ) 
   6.480 +        flush_tlb_mask(current->domain->cpumask);
   6.481 +#endif
   6.482 +
   6.483 +    return 0;
   6.484 +}
   6.485 +
   6.486 +static int
   6.487 +__gnttab_unmap_grant_ref(
   6.488 +    gnttab_unmap_grant_ref_t *uop,
   6.489 +    unsigned long *va)
   6.490 +{
   6.491 +    domid_t        dom;
   6.492 +    grant_ref_t    ref;
   6.493 +    u16            handle;
   6.494 +    struct domain *ld, *rd;
   6.495 +
   6.496 +    active_grant_entry_t *act;
   6.497 +    grant_entry_t *sha;
   6.498 +    grant_mapping_t *map;
   6.499 +    u16            flags;
   6.500 +    s16            rc = 1;
   6.501 +    unsigned long  frame, virt;
   6.502 +
   6.503 +    ld = current->domain;
   6.504 +
   6.505 +    /* Bitwise-OR avoids short-circuiting which screws control flow. */
   6.506 +    if ( unlikely(__get_user(virt, &uop->host_virt_addr) |
   6.507 +                  __get_user(frame, &uop->dev_bus_addr) |
   6.508 +                  __get_user(handle, &uop->handle)) )
   6.509 +    {
   6.510 +        DPRINTK("Fault while reading gnttab_unmap_grant_ref_t.\n");
   6.511 +        return -EFAULT; /* don't set status */
   6.512 +    }
   6.513 +
   6.514 +    map = &ld->grant_table->maptrack[handle];
   6.515 +
   6.516 +    if ( unlikely(handle >= ld->grant_table->maptrack_limit) ||
   6.517 +         unlikely(!(map->ref_and_flags & MAPTRACK_GNTMAP_MASK)) )
   6.518 +    {
   6.519 +        DPRINTK("Bad handle (%d).\n", handle);
   6.520 +        (void)__put_user(GNTST_bad_handle, &uop->status);
   6.521 +        return GNTST_bad_handle;
   6.522 +    }
   6.523 +
   6.524 +    dom   = map->domid;
   6.525 +    ref   = map->ref_and_flags >> MAPTRACK_REF_SHIFT;
   6.526 +    flags = map->ref_and_flags & MAPTRACK_GNTMAP_MASK;
   6.527 +
   6.528 +    if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
   6.529 +         unlikely(ld == rd) )
   6.530 +    {
   6.531 +        if ( rd != NULL )
   6.532 +            put_domain(rd);
   6.533 +        DPRINTK("Could not find domain %d\n", dom);
   6.534 +        (void)__put_user(GNTST_bad_domain, &uop->status);
   6.535 +        return GNTST_bad_domain;
   6.536 +    }
   6.537 +
   6.538 +#if GRANT_DEBUG_VERBOSE
   6.539 +    DPRINTK("Unmapping grant ref (%hu) for domain (%hu) with handle (%hu)\n",
   6.540 +            ref, dom, handle);
   6.541 +#endif
   6.542 +
   6.543 +    act = &rd->grant_table->active[ref];
   6.544 +    sha = &rd->grant_table->shared[ref];
   6.545 +
   6.546 +    spin_lock(&rd->grant_table->lock);
   6.547 +
   6.548 +    if ( frame == 0 )
   6.549 +    {
   6.550 +        frame = act->frame;
   6.551 +    }
   6.552 +    else if ( frame == GNTUNMAP_DEV_FROM_VIRT )
   6.553 +    {
   6.554 +        if ( !( flags & GNTMAP_device_map ) )
   6.555 +            PIN_FAIL(unmap_out, GNTST_bad_dev_addr,
   6.556 +                     "Bad frame number: frame not mapped for dev access.\n");
   6.557 +        frame = act->frame;
   6.558 +
   6.559 +        /* Frame will be unmapped for device access below if virt addr okay. */
   6.560 +    }
   6.561 +    else
   6.562 +    {
   6.563 +        if ( unlikely(frame != act->frame) )
   6.564 +            PIN_FAIL(unmap_out, GNTST_general_error,
   6.565 +                     "Bad frame number doesn't match gntref.\n");
   6.566 +        if ( flags & GNTMAP_device_map )
   6.567 +            act->pin -= (flags & GNTMAP_readonly) ? GNTPIN_devr_inc
   6.568 +                                                  : GNTPIN_devw_inc;
   6.569 +
   6.570 +        map->ref_and_flags &= ~GNTMAP_device_map;
   6.571 +        (void)__put_user(0, &uop->dev_bus_addr);
   6.572 +
   6.573 +        /* Frame is now unmapped for device access. */
   6.574 +    }
   6.575 +
   6.576 +#ifdef __ia64__
   6.577 +// FIXME-ia64: any error checking need to be done here?
   6.578 +#else
   6.579 +    if ( (virt != 0) &&
   6.580 +         (flags & GNTMAP_host_map) &&
   6.581 +         ((act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask)) > 0))
   6.582 +    {
   6.583 +        l1_pgentry_t   *pl1e;
   6.584 +        unsigned long   _ol1e;
   6.585 +
   6.586 +        pl1e = &linear_pg_table[l1_linear_offset(virt)];
   6.587 +
   6.588 +        if ( unlikely(__get_user(_ol1e, (unsigned long *)pl1e) != 0) )
   6.589 +        {
   6.590 +            DPRINTK("Could not find PTE entry for address %lx\n", virt);
   6.591 +            rc = -EINVAL;
   6.592 +            goto unmap_out;
   6.593 +        }
   6.594 +
   6.595 +        /*
   6.596 +         * Check that the virtual address supplied is actually mapped to 
   6.597 +         * act->frame.
   6.598 +         */
   6.599 +        if ( unlikely((_ol1e >> PAGE_SHIFT) != frame ))
   6.600 +        {
   6.601 +            DPRINTK("PTE entry %lx for address %lx doesn't match frame %lx\n",
   6.602 +                    _ol1e, virt, frame);
   6.603 +            rc = -EINVAL;
   6.604 +            goto unmap_out;
   6.605 +        }
   6.606 +
   6.607 +        /* Delete pagetable entry. */
   6.608 +        if ( unlikely(__put_user(0, (unsigned long *)pl1e)))
   6.609 +        {
   6.610 +            DPRINTK("Cannot delete PTE entry at %p for virtual address %lx\n",
   6.611 +                    pl1e, virt);
   6.612 +            rc = -EINVAL;
   6.613 +            goto unmap_out;
   6.614 +        }
   6.615 +
   6.616 +        map->ref_and_flags &= ~GNTMAP_host_map;
   6.617 +
   6.618 +        act->pin -= (flags & GNTMAP_readonly) ? GNTPIN_hstr_inc
   6.619 +                                              : GNTPIN_hstw_inc;
   6.620 +
   6.621 +        if ( frame == GNTUNMAP_DEV_FROM_VIRT )
   6.622 +        {
   6.623 +            act->pin -= (flags & GNTMAP_readonly) ? GNTPIN_devr_inc
   6.624 +                                                  : GNTPIN_devw_inc;
   6.625 +
   6.626 +            map->ref_and_flags &= ~GNTMAP_device_map;
   6.627 +            (void)__put_user(0, &uop->dev_bus_addr);
   6.628 +        }
   6.629 +
   6.630 +        rc = 0;
   6.631 +        *va = virt;
   6.632 +    }
   6.633 +#endif
   6.634 +
   6.635 +    if ( (map->ref_and_flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0)
   6.636 +    {
   6.637 +        map->ref_and_flags = 0;
   6.638 +        put_maptrack_handle(ld->grant_table, handle);
   6.639 +    }
   6.640 +
   6.641 +#ifdef __ia64__
   6.642 +// FIXME-ia64: any error checking need to be done here?  I think not and then
   6.643 +//  this can probably be macro-ized into nothingness
   6.644 +#else
   6.645 +    /* If just unmapped a writable mapping, mark as dirtied */
   6.646 +    if ( unlikely(shadow_mode_log_dirty(rd)) &&
   6.647 +        !( flags & GNTMAP_readonly ) )
   6.648 +         mark_dirty(rd, frame);
   6.649 +#endif
   6.650 +
   6.651 +    /* If the last writable mapping has been removed, put_page_type */
   6.652 +    if ( ( (act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask) ) == 0) &&
   6.653 +         ( !( flags & GNTMAP_readonly ) ) )
   6.654 +    {
   6.655 +        clear_bit(_GTF_writing, &sha->flags);
   6.656 +        put_page_type(&frame_table[frame]);
   6.657 +    }
   6.658 +
   6.659 +    if ( act->pin == 0 )
   6.660 +    {
   6.661 +        clear_bit(_GTF_reading, &sha->flags);
   6.662 +        put_page(&frame_table[frame]);
   6.663 +    }
   6.664 +
   6.665 + unmap_out:
   6.666 +    (void)__put_user(rc, &uop->status);
   6.667 +    spin_unlock(&rd->grant_table->lock);
   6.668 +    put_domain(rd);
   6.669 +    return rc;
   6.670 +}
   6.671 +
   6.672 +static long
   6.673 +gnttab_unmap_grant_ref(
   6.674 +    gnttab_unmap_grant_ref_t *uop, unsigned int count)
   6.675 +{
   6.676 +    int i, flush = 0;
   6.677 +    unsigned long va = 0;
   6.678 +
   6.679 +    for ( i = 0; i < count; i++ )
   6.680 +        if ( __gnttab_unmap_grant_ref(&uop[i], &va) == 0 )
   6.681 +            flush++;
   6.682 +
   6.683 +#ifdef __ia64__
   6.684 +// FIXME-ia64: probably need to do something here to avoid stale mappings?
   6.685 +#else
   6.686 +    if ( flush == 1 )
   6.687 +        flush_tlb_one_mask(current->domain->cpumask, va);
   6.688 +    else if ( flush != 0 ) 
   6.689 +        flush_tlb_mask(current->domain->cpumask);
   6.690 +#endif
   6.691 +
   6.692 +    return 0;
   6.693 +}
   6.694 +
   6.695 +static long 
   6.696 +gnttab_setup_table(
   6.697 +    gnttab_setup_table_t *uop, unsigned int count)
   6.698 +{
   6.699 +    gnttab_setup_table_t  op;
   6.700 +    struct domain        *d;
   6.701 +    int                   i;
   6.702 +
   6.703 +    if ( count != 1 )
   6.704 +        return -EINVAL;
   6.705 +
   6.706 +    if ( unlikely(copy_from_user(&op, uop, sizeof(op)) != 0) )
   6.707 +    {
   6.708 +        DPRINTK("Fault while reading gnttab_setup_table_t.\n");
   6.709 +        return -EFAULT;
   6.710 +    }
   6.711 +
   6.712 +    if ( unlikely(op.nr_frames > NR_GRANT_FRAMES) )
   6.713 +    {
   6.714 +        DPRINTK("Xen only supports up to %d grant-table frames per domain.\n",
   6.715 +                NR_GRANT_FRAMES);
   6.716 +        (void)put_user(GNTST_general_error, &uop->status);
   6.717 +        return 0;
   6.718 +    }
   6.719 +
   6.720 +    if ( op.dom == DOMID_SELF )
   6.721 +    {
   6.722 +        op.dom = current->domain->domain_id;
   6.723 +    }
   6.724 +    else if ( unlikely(!IS_PRIV(current->domain)) )
   6.725 +    {
   6.726 +        (void)put_user(GNTST_permission_denied, &uop->status);
   6.727 +        return 0;
   6.728 +    }
   6.729 +
   6.730 +    if ( unlikely((d = find_domain_by_id(op.dom)) == NULL) )
   6.731 +    {
   6.732 +        DPRINTK("Bad domid %d.\n", op.dom);
   6.733 +        (void)put_user(GNTST_bad_domain, &uop->status);
   6.734 +        return 0;
   6.735 +    }
   6.736 +
   6.737 +    if ( op.nr_frames <= NR_GRANT_FRAMES )
   6.738 +    {
   6.739 +        ASSERT(d->grant_table != NULL);
   6.740 +        (void)put_user(GNTST_okay, &uop->status);
   6.741 +        for ( i = 0; i < op.nr_frames; i++ )
   6.742 +            (void)put_user(
   6.743 +                (virt_to_phys(d->grant_table->shared) >> PAGE_SHIFT) + i,
   6.744 +                &uop->frame_list[i]);
   6.745 +    }
   6.746 +
   6.747 +    put_domain(d);
   6.748 +    return 0;
   6.749 +}
   6.750 +
   6.751 +#if GRANT_DEBUG
   6.752 +static int
   6.753 +gnttab_dump_table(gnttab_dump_table_t *uop)
   6.754 +{
   6.755 +    grant_table_t        *gt;
   6.756 +    gnttab_dump_table_t   op;
   6.757 +    struct domain        *d;
   6.758 +    u32                   shared_mfn;
   6.759 +    active_grant_entry_t *act;
   6.760 +    grant_entry_t         sha_copy;
   6.761 +    grant_mapping_t      *maptrack;
   6.762 +    int                   i;
   6.763 +
   6.764 +
   6.765 +    if ( unlikely(copy_from_user(&op, uop, sizeof(op)) != 0) )
   6.766 +    {
   6.767 +        DPRINTK("Fault while reading gnttab_dump_table_t.\n");
   6.768 +        return -EFAULT;
   6.769 +    }
   6.770 +
   6.771 +    if ( op.dom == DOMID_SELF )
   6.772 +    {
   6.773 +        op.dom = current->domain->domain_id;
   6.774 +    }
   6.775 +
   6.776 +    if ( unlikely((d = find_domain_by_id(op.dom)) == NULL) )
   6.777 +    {
   6.778 +        DPRINTK("Bad domid %d.\n", op.dom);
   6.779 +        (void)put_user(GNTST_bad_domain, &uop->status);
   6.780 +        return 0;
   6.781 +    }
   6.782 +
   6.783 +    ASSERT(d->grant_table != NULL);
   6.784 +    gt = d->grant_table;
   6.785 +    (void)put_user(GNTST_okay, &uop->status);
   6.786 +
   6.787 +    shared_mfn = virt_to_phys(d->grant_table->shared);
   6.788 +
   6.789 +    DPRINTK("Grant table for dom (%hu) MFN (%x)\n",
   6.790 +            op.dom, shared_mfn);
   6.791 +
   6.792 +    ASSERT(d->grant_table->active != NULL);
   6.793 +    ASSERT(d->grant_table->shared != NULL);
   6.794 +    ASSERT(d->grant_table->maptrack != NULL);
   6.795 +
   6.796 +    for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
   6.797 +    {
   6.798 +        sha_copy =  gt->shared[i];
   6.799 +
   6.800 +        if ( sha_copy.flags )
   6.801 +        {
   6.802 +            DPRINTK("Grant: dom (%hu) SHARED (%d) flags:(%hx) "
   6.803 +                    "dom:(%hu) frame:(%lx)\n",
   6.804 +                    op.dom, i, sha_copy.flags, sha_copy.domid, sha_copy.frame);
   6.805 +        }
   6.806 +    }
   6.807 +
   6.808 +    spin_lock(&gt->lock);
   6.809 +
   6.810 +    for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
   6.811 +    {
   6.812 +        act = &gt->active[i];
   6.813 +
   6.814 +        if ( act->pin )
   6.815 +        {
   6.816 +            DPRINTK("Grant: dom (%hu) ACTIVE (%d) pin:(%x) "
   6.817 +                    "dom:(%hu) frame:(%lx)\n",
   6.818 +                    op.dom, i, act->pin, act->domid, act->frame);
   6.819 +        }
   6.820 +    }
   6.821 +
   6.822 +    for ( i = 0; i < gt->maptrack_limit; i++ )
   6.823 +    {
   6.824 +        maptrack = &gt->maptrack[i];
   6.825 +
   6.826 +        if ( maptrack->ref_and_flags & MAPTRACK_GNTMAP_MASK )
   6.827 +        {
   6.828 +            DPRINTK("Grant: dom (%hu) MAP (%d) ref:(%hu) flags:(%x) "
   6.829 +                    "dom:(%hu)\n",
   6.830 +                    op.dom, i,
   6.831 +                    maptrack->ref_and_flags >> MAPTRACK_REF_SHIFT,
   6.832 +                    maptrack->ref_and_flags & MAPTRACK_GNTMAP_MASK,
   6.833 +                    maptrack->domid);
   6.834 +        }
   6.835 +    }
   6.836 +
   6.837 +    spin_unlock(&gt->lock);
   6.838 +
   6.839 +    put_domain(d);
   6.840 +    return 0;
   6.841 +}
   6.842 +#endif
   6.843 +
   6.844 +long 
   6.845 +do_grant_table_op(
   6.846 +    unsigned int cmd, void *uop, unsigned int count)
   6.847 +{
   6.848 +    long rc;
   6.849 +
   6.850 +    if ( count > 512 )
   6.851 +        return -EINVAL;
   6.852 +
   6.853 +    LOCK_BIGLOCK(current->domain);
   6.854 +
   6.855 +    rc = -EFAULT;
   6.856 +    switch ( cmd )
   6.857 +    {
   6.858 +    case GNTTABOP_map_grant_ref:
   6.859 +        if ( unlikely(!array_access_ok(
   6.860 +            uop, count, sizeof(gnttab_map_grant_ref_t))) )
   6.861 +            goto out;
   6.862 +        rc = gnttab_map_grant_ref((gnttab_map_grant_ref_t *)uop, count);
   6.863 +        break;
   6.864 +    case GNTTABOP_unmap_grant_ref:
   6.865 +        if ( unlikely(!array_access_ok(
   6.866 +            uop, count, sizeof(gnttab_unmap_grant_ref_t))) )
   6.867 +            goto out;
   6.868 +        rc = gnttab_unmap_grant_ref((gnttab_unmap_grant_ref_t *)uop, count);
   6.869 +        break;
   6.870 +    case GNTTABOP_setup_table:
   6.871 +        rc = gnttab_setup_table((gnttab_setup_table_t *)uop, count);
   6.872 +        break;
   6.873 +#if GRANT_DEBUG
   6.874 +    case GNTTABOP_dump_table:
   6.875 +        rc = gnttab_dump_table((gnttab_dump_table_t *)uop);
   6.876 +        break;
   6.877 +#endif
   6.878 +    default:
   6.879 +        rc = -ENOSYS;
   6.880 +        break;
   6.881 +    }
   6.882 +
   6.883 +out:
   6.884 +    UNLOCK_BIGLOCK(current->domain);
   6.885 +
   6.886 +    return rc;
   6.887 +}
   6.888 +
   6.889 +int
   6.890 +gnttab_check_unmap(
   6.891 +    struct domain *rd, struct domain *ld, unsigned long frame, int readonly)
   6.892 +{
   6.893 +    /* Called when put_page is invoked on a page belonging to a foreign domain.
   6.894 +     * Instead of decrementing the frame table ref count, locate the grant
   6.895 +     * table entry, if any, and if found, decrement that count.
   6.896 +     * Called a _lot_ at domain creation because pages mapped by priv domains
   6.897 +     * also traverse this.
   6.898 +     */
   6.899 +
   6.900 +    /* Note: If the same frame is mapped multiple times, and then one of
   6.901 +     *       the ptes is overwritten, which maptrack handle gets invalidated?
   6.902 +     * Advice: Don't do it. Explicitly unmap.
   6.903 +     */
   6.904 +
   6.905 +    unsigned int handle, ref, refcount;
   6.906 +    grant_table_t        *lgt, *rgt;
   6.907 +    active_grant_entry_t *act;
   6.908 +    grant_mapping_t      *map;
   6.909 +    int found = 0;
   6.910 +
   6.911 +    lgt = ld->grant_table;
   6.912 +
   6.913 +#if GRANT_DEBUG_VERBOSE
   6.914 +    if ( ld->domain_id != 0 )
   6.915 +    {
   6.916 +        DPRINTK("Foreign unref rd(%d) ld(%d) frm(%x) flgs(%x).\n",
   6.917 +                rd->domain_id, ld->domain_id, frame, readonly);
   6.918 +    }
   6.919 +#endif
   6.920 +
   6.921 +    /* Fast exit if we're not mapping anything using grant tables */
   6.922 +    if ( lgt->map_count == 0 )
   6.923 +        return 0;
   6.924 +
   6.925 +    if ( get_domain(rd) == 0 )
   6.926 +    {
   6.927 +        DPRINTK("gnttab_check_unmap: couldn't get_domain rd(%d)\n",
   6.928 +                rd->domain_id);
   6.929 +        return 0;
   6.930 +    }
   6.931 +
   6.932 +    rgt = rd->grant_table;
   6.933 +
   6.934 +    for ( handle = 0; handle < lgt->maptrack_limit; handle++ )
   6.935 +    {
   6.936 +        map = &lgt->maptrack[handle];
   6.937 +
   6.938 +        if ( ( map->ref_and_flags & MAPTRACK_GNTMAP_MASK ) &&
   6.939 +             ( readonly ? 1 : (!(map->ref_and_flags & GNTMAP_readonly))))
   6.940 +        {
   6.941 +            ref = (map->ref_and_flags >> MAPTRACK_REF_SHIFT);
   6.942 +            act = &rgt->active[ref];
   6.943 +
   6.944 +            spin_lock(&rgt->lock);
   6.945 +
   6.946 +            if ( act->frame != frame )
   6.947 +            {
   6.948 +                spin_unlock(&rgt->lock);
   6.949 +                continue;
   6.950 +            }
   6.951 +
   6.952 +            refcount = act->pin & ( readonly ? GNTPIN_hstr_mask
   6.953 +                                             : GNTPIN_hstw_mask );
   6.954 +            if ( refcount == 0 )
   6.955 +            {
   6.956 +                spin_unlock(&rgt->lock);
   6.957 +                continue;
   6.958 +            }
   6.959 +
   6.960 +            /* gotcha */
   6.961 +            DPRINTK("Grant unref rd(%d) ld(%d) frm(%lx) flgs(%x).\n",
   6.962 +                    rd->domain_id, ld->domain_id, frame, readonly);
   6.963 +
   6.964 +            if ( readonly )
   6.965 +                act->pin -= GNTPIN_hstr_inc;
   6.966 +            else
   6.967 +            {
   6.968 +                act->pin -= GNTPIN_hstw_inc;
   6.969 +
   6.970 +                /* any more granted writable mappings? */
   6.971 +                if ( (act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) == 0 )
   6.972 +                {
   6.973 +                    clear_bit(_GTF_writing, &rgt->shared[ref].flags);
   6.974 +                    put_page_type(&frame_table[frame]);
   6.975 +                }
   6.976 +            }
   6.977 +
   6.978 +            if ( act->pin == 0 )
   6.979 +            {
   6.980 +                clear_bit(_GTF_reading, &rgt->shared[ref].flags);
   6.981 +                put_page(&frame_table[frame]);
   6.982 +            }
   6.983 +            spin_unlock(&rgt->lock);
   6.984 +
   6.985 +            clear_bit(GNTMAP_host_map, &map->ref_and_flags);
   6.986 +
   6.987 +            if ( !(map->ref_and_flags & GNTMAP_device_map) )
   6.988 +                put_maptrack_handle(lgt, handle);
   6.989 +
   6.990 +            found = 1;
   6.991 +            break;
   6.992 +        }
   6.993 +    }
   6.994 +    put_domain(rd);
   6.995 +
   6.996 +    return found;
   6.997 +}
   6.998 +
   6.999 +int 
  6.1000 +gnttab_prepare_for_transfer(
  6.1001 +    struct domain *rd, struct domain *ld, grant_ref_t ref)
  6.1002 +{
  6.1003 +    grant_table_t *rgt;
  6.1004 +    grant_entry_t *sha;
  6.1005 +    domid_t        sdom;
  6.1006 +    u16            sflags;
  6.1007 +    u32            scombo, prev_scombo;
  6.1008 +    int            retries = 0;
  6.1009 +    unsigned long  target_pfn;
  6.1010 +
  6.1011 +    DPRINTK("gnttab_prepare_for_transfer rd(%hu) ld(%hu) ref(%hu).\n",
  6.1012 +            rd->domain_id, ld->domain_id, ref);
  6.1013 +
  6.1014 +    if ( unlikely((rgt = rd->grant_table) == NULL) ||
  6.1015 +         unlikely(ref >= NR_GRANT_ENTRIES) )
  6.1016 +    {
  6.1017 +        DPRINTK("Dom %d has no g.t., or ref is bad (%d).\n",
  6.1018 +                rd->domain_id, ref);
  6.1019 +        return 0;
  6.1020 +    }
  6.1021 +
  6.1022 +    spin_lock(&rgt->lock);
  6.1023 +
  6.1024 +    sha = &rgt->shared[ref];
  6.1025 +    
  6.1026 +    sflags = sha->flags;
  6.1027 +    sdom   = sha->domid;
  6.1028 +
  6.1029 +    for ( ; ; )
  6.1030 +    {
  6.1031 +        target_pfn = sha->frame;
  6.1032 +
  6.1033 +        if ( unlikely(target_pfn >= max_page ) )
  6.1034 +        {
  6.1035 +            DPRINTK("Bad pfn (%lx)\n", target_pfn);
  6.1036 +            goto fail;
  6.1037 +        }
  6.1038 +
  6.1039 +        if ( unlikely(sflags != GTF_accept_transfer) ||
  6.1040 +             unlikely(sdom != ld->domain_id) )
  6.1041 +        {
  6.1042 +            DPRINTK("Bad flags (%x) or dom (%d). (NB. expected dom %d)\n",
  6.1043 +                    sflags, sdom, ld->domain_id);
  6.1044 +            goto fail;
  6.1045 +        }
  6.1046 +
  6.1047 +        /* Merge two 16-bit values into a 32-bit combined update. */
  6.1048 +        /* NB. Endianness! */
  6.1049 +        prev_scombo = scombo = ((u32)sdom << 16) | (u32)sflags;
  6.1050 +
  6.1051 +        /* NB. prev_scombo is updated in place to seen value. */
  6.1052 +        if ( unlikely(cmpxchg_user((u32 *)&sha->flags, prev_scombo, 
  6.1053 +                                   prev_scombo | GTF_transfer_committed)) )
  6.1054 +        {
  6.1055 +            DPRINTK("Fault while modifying shared flags and domid.\n");
  6.1056 +            goto fail;
  6.1057 +        }
  6.1058 +
  6.1059 +        /* Did the combined update work (did we see what we expected?). */
  6.1060 +        if ( likely(prev_scombo == scombo) )
  6.1061 +            break;
  6.1062 +
  6.1063 +        if ( retries++ == 4 )
  6.1064 +        {
  6.1065 +            DPRINTK("Shared grant entry is unstable.\n");
  6.1066 +            goto fail;
  6.1067 +        }
  6.1068 +
  6.1069 +        /* Didn't see what we expected. Split out the seen flags & dom. */
  6.1070 +        /* NB. Endianness! */
  6.1071 +        sflags = (u16)prev_scombo;
  6.1072 +        sdom   = (u16)(prev_scombo >> 16);
  6.1073 +    }
  6.1074 +
  6.1075 +    spin_unlock(&rgt->lock);
  6.1076 +    return 1;
  6.1077 +
  6.1078 + fail:
  6.1079 +    spin_unlock(&rgt->lock);
  6.1080 +    return 0;
  6.1081 +}
  6.1082 +
  6.1083 +void 
  6.1084 +gnttab_notify_transfer(
  6.1085 +    struct domain *rd, struct domain *ld, grant_ref_t ref, unsigned long frame)
  6.1086 +{
  6.1087 +    grant_entry_t  *sha;
  6.1088 +    unsigned long   pfn;
  6.1089 +
  6.1090 +    DPRINTK("gnttab_notify_transfer rd(%hu) ld(%hu) ref(%hu).\n",
  6.1091 +            rd->domain_id, ld->domain_id, ref);
  6.1092 +
  6.1093 +    sha = &rd->grant_table->shared[ref];
  6.1094 +
  6.1095 +    spin_lock(&rd->grant_table->lock);
  6.1096 +
  6.1097 +#ifdef __ia64__
  6.1098 +// FIXME-ia64: any error checking need to be done here?
  6.1099 +#else
  6.1100 +    pfn = sha->frame;
  6.1101 +
  6.1102 +    if ( unlikely(pfn >= max_page ) )
  6.1103 +        DPRINTK("Bad pfn (%lx)\n", pfn);
  6.1104 +    else
  6.1105 +    {
  6.1106 +        machine_to_phys_mapping[frame] = pfn;
  6.1107 +
  6.1108 +        if ( unlikely(shadow_mode_log_dirty(ld)))
  6.1109 +             mark_dirty(ld, frame);
  6.1110 +
  6.1111 +        if (shadow_mode_translate(ld))
  6.1112 +            __phys_to_machine_mapping[pfn] = frame;
  6.1113 +    }
  6.1114 +#endif
  6.1115 +    sha->frame = __mfn_to_gpfn(rd, frame);
  6.1116 +    sha->domid = rd->domain_id;
  6.1117 +    wmb();
  6.1118 +    sha->flags = ( GTF_accept_transfer | GTF_transfer_completed );
  6.1119 +
  6.1120 +    spin_unlock(&rd->grant_table->lock);
  6.1121 +
  6.1122 +    return;
  6.1123 +}
  6.1124 +
  6.1125 +int 
  6.1126 +grant_table_create(
  6.1127 +    struct domain *d)
  6.1128 +{
  6.1129 +    grant_table_t *t;
  6.1130 +    int            i;
  6.1131 +
  6.1132 +    if ( (t = xmalloc(grant_table_t)) == NULL )
  6.1133 +        goto no_mem;
  6.1134 +
  6.1135 +    /* Simple stuff. */
  6.1136 +    memset(t, 0, sizeof(*t));
  6.1137 +    spin_lock_init(&t->lock);
  6.1138 +
  6.1139 +    /* Active grant table. */
  6.1140 +    if ( (t->active = xmalloc_array(active_grant_entry_t, NR_GRANT_ENTRIES))
  6.1141 +         == NULL )
  6.1142 +        goto no_mem;
  6.1143 +    memset(t->active, 0, sizeof(active_grant_entry_t) * NR_GRANT_ENTRIES);
  6.1144 +
  6.1145 +    /* Tracking of mapped foreign frames table */
  6.1146 +    if ( (t->maptrack = alloc_xenheap_page()) == NULL )
  6.1147 +        goto no_mem;
  6.1148 +    t->maptrack_order = 0;
  6.1149 +    t->maptrack_limit = PAGE_SIZE / sizeof(grant_mapping_t);
  6.1150 +    memset(t->maptrack, 0, PAGE_SIZE);
  6.1151 +    for ( i = 0; i < t->maptrack_limit; i++ )
  6.1152 +        t->maptrack[i].ref_and_flags = (i+1) << MAPTRACK_REF_SHIFT;
  6.1153 +
  6.1154 +    /* Shared grant table. */
  6.1155 +    t->shared = alloc_xenheap_pages(ORDER_GRANT_FRAMES);
  6.1156 +    if ( t->shared == NULL )
  6.1157 +        goto no_mem;
  6.1158 +    memset(t->shared, 0, NR_GRANT_FRAMES * PAGE_SIZE);
  6.1159 +
  6.1160 +#ifdef __ia64__
  6.1161 +// I don't think there's anything to do here on ia64?...
  6.1162 +#else
  6.1163 +    for ( i = 0; i < NR_GRANT_FRAMES; i++ )
  6.1164 +    {
  6.1165 +        SHARE_PFN_WITH_DOMAIN(
  6.1166 +            virt_to_page((char *)(t->shared)+(i*PAGE_SIZE)), d);
  6.1167 +        machine_to_phys_mapping[(virt_to_phys(t->shared) >> PAGE_SHIFT) + i] =
  6.1168 +            INVALID_M2P_ENTRY;
  6.1169 +    }
  6.1170 +#endif
  6.1171 +
  6.1172 +    /* Okay, install the structure. */
  6.1173 +    wmb(); /* avoid races with lock-free access to d->grant_table */
  6.1174 +    d->grant_table = t;
  6.1175 +    return 0;
  6.1176 +
  6.1177 + no_mem:
  6.1178 +    if ( t != NULL )
  6.1179 +    {
  6.1180 +        xfree(t->active);
  6.1181 +        if ( t->maptrack != NULL )
  6.1182 +            free_xenheap_page(t->maptrack);
  6.1183 +        xfree(t);
  6.1184 +    }
  6.1185 +    return -ENOMEM;
  6.1186 +}
  6.1187 +
  6.1188 +void
  6.1189 +gnttab_release_dev_mappings(grant_table_t *gt)
  6.1190 +{
  6.1191 +    grant_mapping_t        *map;
  6.1192 +    domid_t                 dom;
  6.1193 +    grant_ref_t             ref;
  6.1194 +    u16                     handle;
  6.1195 +    struct domain          *ld, *rd;
  6.1196 +    unsigned long           frame;
  6.1197 +    active_grant_entry_t   *act;
  6.1198 +    grant_entry_t          *sha;
  6.1199 +
  6.1200 +    ld = current->domain;
  6.1201 +
  6.1202 +    for ( handle = 0; handle < gt->maptrack_limit; handle++ )
  6.1203 +    {
  6.1204 +        map = &gt->maptrack[handle];
  6.1205 +
  6.1206 +        if ( map->ref_and_flags & GNTMAP_device_map )
  6.1207 +        {
  6.1208 +            dom = map->domid;
  6.1209 +            ref = map->ref_and_flags >> MAPTRACK_REF_SHIFT;
  6.1210 +
  6.1211 +            DPRINTK("Grant release (%hu) ref:(%hu) flags:(%x) dom:(%hu)\n",
  6.1212 +                    handle, ref,
  6.1213 +                    map->ref_and_flags & MAPTRACK_GNTMAP_MASK, dom);
  6.1214 +
  6.1215 +            if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
  6.1216 +                 unlikely(ld == rd) )
  6.1217 +            {
  6.1218 +                if ( rd != NULL )
  6.1219 +                    put_domain(rd);
  6.1220 +
  6.1221 +                printk(KERN_WARNING "Grant release: No dom%d\n", dom);
  6.1222 +                continue;
  6.1223 +            }
  6.1224 +
  6.1225 +            act = &rd->grant_table->active[ref];
  6.1226 +            sha = &rd->grant_table->shared[ref];
  6.1227 +
  6.1228 +            spin_lock(&rd->grant_table->lock);
  6.1229 +
  6.1230 +            if ( act->pin & (GNTPIN_devw_mask | GNTPIN_devr_mask) )
  6.1231 +            {
  6.1232 +                frame = act->frame;
  6.1233 +
  6.1234 +                if ( ( (act->pin & GNTPIN_hstw_mask) == 0 ) &&
  6.1235 +                     ( (act->pin & GNTPIN_devw_mask) >  0 ) )
  6.1236 +                {
  6.1237 +                    clear_bit(_GTF_writing, &sha->flags);
  6.1238 +                    put_page_type(&frame_table[frame]);
  6.1239 +                }
  6.1240 +
  6.1241 +                act->pin &= ~(GNTPIN_devw_mask | GNTPIN_devr_mask);
  6.1242 +
  6.1243 +                if ( act->pin == 0 )
  6.1244 +                {
  6.1245 +                    clear_bit(_GTF_reading, &sha->flags);
  6.1246 +                    map->ref_and_flags = 0;
  6.1247 +                    put_page(&frame_table[frame]);
  6.1248 +                }
  6.1249 +                else
  6.1250 +                    map->ref_and_flags &= ~GNTMAP_device_map;
  6.1251 +            }
  6.1252 +
  6.1253 +            spin_unlock(&rd->grant_table->lock);
  6.1254 +
  6.1255 +            put_domain(rd);
  6.1256 +        }
  6.1257 +    }
  6.1258 +}
  6.1259 +
  6.1260 +
  6.1261 +void
  6.1262 +grant_table_destroy(
  6.1263 +    struct domain *d)
  6.1264 +{
  6.1265 +    grant_table_t *t;
  6.1266 +
  6.1267 +    if ( (t = d->grant_table) != NULL )
  6.1268 +    {
  6.1269 +        /* Free memory relating to this grant table. */
  6.1270 +        d->grant_table = NULL;
  6.1271 +        free_xenheap_pages(t->shared, ORDER_GRANT_FRAMES);
  6.1272 +        free_xenheap_page(t->maptrack);
  6.1273 +        xfree(t->active);
  6.1274 +        xfree(t);
  6.1275 +    }
  6.1276 +}
  6.1277 +
  6.1278 +void
  6.1279 +grant_table_init(
  6.1280 +    void)
  6.1281 +{
  6.1282 +    /* Nothing. */
  6.1283 +}
  6.1284 +#endif
  6.1285 +
  6.1286 +/*
  6.1287 + * Local variables:
  6.1288 + * mode: C
  6.1289 + * c-set-style: "BSD"
  6.1290 + * c-basic-offset: 4
  6.1291 + * tab-width: 4
  6.1292 + * indent-tabs-mode: nil
  6.1293 + * End:
  6.1294 + */
     7.1 --- a/xen/arch/ia64/hypercall.c	Wed Jun 22 17:42:58 2005 +0000
     7.2 +++ b/xen/arch/ia64/hypercall.c	Wed Jun 22 17:46:00 2005 +0000
     7.3 @@ -40,6 +40,17 @@ ia64_hypercall (struct pt_regs *regs)
     7.4  #endif
     7.5  		x = pal_emulator_static(regs->r28);
     7.6  		if (regs->r28 == PAL_HALT_LIGHT) {
     7.7 +#if 1
     7.8 +#define SPURIOUS_VECTOR 15
     7.9 +			if (vcpu_check_pending_interrupts(v)!=SPURIOUS_VECTOR) {
    7.10 +//printf("Domain trying to go idle when interrupt pending!\n");
    7.11 +//this shouldn't happen, but it apparently does quite a bit!  so don't
    7.12 +//allow it to happen... i.e. if a domain has an interrupt pending and
    7.13 +//it tries to halt itself because it thinks it is idle, just return here
    7.14 +//as deliver_pending_interrupt is called on the way out and will deliver it
    7.15 +			}
    7.16 +			else
    7.17 +#endif
    7.18  			do_sched_op(SCHEDOP_yield);
    7.19  			//break;
    7.20  		}
    7.21 @@ -138,6 +149,12 @@ ia64_hypercall (struct pt_regs *regs)
    7.22  		regs->r8 = do_event_channel_op(regs->r14);
    7.23  		break;
    7.24  
    7.25 +#ifndef CONFIG_VTI
    7.26 +	    case __HYPERVISOR_grant_table_op:
    7.27 +		regs->r8 = do_grant_table_op(regs->r14, regs->r15, regs->r16);
    7.28 +		break;
    7.29 +#endif
    7.30 +
    7.31  	    case __HYPERVISOR_console_io:
    7.32  		regs->r8 = do_console_io(regs->r14, regs->r15, regs->r16);
    7.33  		break;
     8.1 --- a/xen/arch/ia64/hyperprivop.S	Wed Jun 22 17:42:58 2005 +0000
     8.2 +++ b/xen/arch/ia64/hyperprivop.S	Wed Jun 22 17:46:00 2005 +0000
     8.3 @@ -66,10 +66,13 @@ 1:	// when we get to here r20=~=interrup
     8.4  	cmp.eq p7,p6=XEN_HYPER_RFI,r17
     8.5  (p7)	br.sptk.many hyper_rfi;;
     8.6  
     8.7 +	// HYPERPRIVOP_GET_IVR?
     8.8 +	cmp.eq p7,p6=XEN_HYPER_GET_IVR,r17
     8.9 +(p7)	br.sptk.many hyper_get_ivr;;
    8.10 +
    8.11  	cmp.ne p7,p0=r20,r0
    8.12  (p7)	br.spnt.many dispatch_break_fault ;;
    8.13  
    8.14 -// hard to test, because only called from rbs_switch
    8.15  	// HYPERPRIVOP_COVER?
    8.16  	cmp.eq p7,p6=XEN_HYPER_COVER,r17
    8.17  (p7)	br.sptk.many hyper_cover;;
    8.18 @@ -82,6 +85,42 @@ 1:	// when we get to here r20=~=interrup
    8.19  	cmp.eq p7,p6=XEN_HYPER_RSM_DT,r17
    8.20  (p7)	br.sptk.many hyper_rsm_dt;;
    8.21  
    8.22 +	// HYPERPRIVOP_GET_TPR?
    8.23 +	cmp.eq p7,p6=XEN_HYPER_GET_TPR,r17
    8.24 +(p7)	br.sptk.many hyper_get_tpr;;
    8.25 +
    8.26 +	// HYPERPRIVOP_SET_TPR?
    8.27 +	cmp.eq p7,p6=XEN_HYPER_SET_TPR,r17
    8.28 +(p7)	br.sptk.many hyper_set_tpr;;
    8.29 +
    8.30 +	// HYPERPRIVOP_EOI?
    8.31 +	cmp.eq p7,p6=XEN_HYPER_EOI,r17
    8.32 +(p7)	br.sptk.many hyper_eoi;;
    8.33 +
    8.34 +	// HYPERPRIVOP_SET_ITM?
    8.35 +	cmp.eq p7,p6=XEN_HYPER_SET_ITM,r17
    8.36 +(p7)	br.sptk.many hyper_set_itm;;
    8.37 +
    8.38 +	// HYPERPRIVOP_SET_RR?
    8.39 +	cmp.eq p7,p6=XEN_HYPER_SET_RR,r17
    8.40 +(p7)	br.sptk.many hyper_set_rr;;
    8.41 +
    8.42 +	// HYPERPRIVOP_GET_RR?
    8.43 +	cmp.eq p7,p6=XEN_HYPER_GET_RR,r17
    8.44 +(p7)	br.sptk.many hyper_get_rr;;
    8.45 +
    8.46 +	// HYPERPRIVOP_PTC_GA?
    8.47 +	cmp.eq p7,p6=XEN_HYPER_PTC_GA,r17
    8.48 +(p7)	br.sptk.many hyper_ptc_ga;;
    8.49 +
    8.50 +	// HYPERPRIVOP_ITC_D?
    8.51 +	cmp.eq p7,p6=XEN_HYPER_ITC_D,r17
    8.52 +(p7)	br.sptk.many hyper_itc_d;;
    8.53 +
    8.54 +	// HYPERPRIVOP_ITC_I?
    8.55 +	cmp.eq p7,p6=XEN_HYPER_ITC_I,r17
    8.56 +(p7)	br.sptk.many hyper_itc_i;;
    8.57 +
    8.58  	// if not one of the above, give up for now and do it the slow way
    8.59  	br.sptk.many dispatch_break_fault ;;
    8.60  
    8.61 @@ -343,14 +382,15 @@ GLOBAL_ENTRY(fast_break_reflect)
    8.62  // ensure that, if giving up, registers at entry to fast_hyperprivop unchanged
    8.63  ENTRY(hyper_rfi)
    8.64  	// if no interrupts pending, proceed
    8.65 +	mov r30=r0
    8.66  	cmp.eq p7,p0=r20,r0
    8.67  (p7)	br.sptk.many 1f
    8.68 -	// interrupts pending, if rfi'ing to interrupts on, go slow way
    8.69 +	;;
    8.70  	adds r20=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 ;;
    8.71  	ld8 r21=[r20];;		// r21 = vcr.ipsr
    8.72  	extr.u r22=r21,IA64_PSR_I_BIT,1 ;;
    8.73 -	cmp.ne p7,p0=r22,r0 ;;
    8.74 -(p7)	br.spnt.many dispatch_break_fault ;;
    8.75 +	mov r30=r22	
    8.76 +	// r30 determines whether we might deliver an immediate extint
    8.77  1:
    8.78  	adds r20=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 ;;
    8.79  	ld8 r21=[r20];;		// r21 = vcr.ipsr
    8.80 @@ -384,13 +424,17 @@ 1:
    8.81  (p7)	cmp.geu p0,p7=r22,r24 ;;	//    !(iip>=high)
    8.82  (p7)	br.sptk.many dispatch_break_fault ;;
    8.83  
    8.84 -	// OK now, let's do an rfi.
    8.85 +1:	// OK now, let's do an rfi.
    8.86  #ifdef FAST_HYPERPRIVOP_CNT
    8.87  	movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_RFI);;
    8.88  	ld8 r23=[r20];;
    8.89  	adds r23=1,r23;;
    8.90  	st8 [r20]=r23;;
    8.91  #endif
    8.92 +	cmp.ne p6,p0=r30,r0
    8.93 +(p6)	br.cond.sptk.many check_extint;
    8.94 +	;;
    8.95 +just_do_rfi:
    8.96  	// r18=&vpsr.i|vpsr.ic, r21==vpsr, r22=vcr.iip
    8.97  	mov cr.iip=r22;;
    8.98  	adds r20=XSI_INCOMPL_REG_OFS-XSI_PSR_IC_OFS,r18 ;;
    8.99 @@ -403,11 +447,12 @@ 1:
   8.100  	dep r21=-1,r21,IA64_PSR_CPL1_BIT,1 ;;
   8.101  	// vpsr.i = vcr.ipsr.i; vpsr.ic = vcr.ipsr.ic
   8.102  	mov r19=r0 ;;
   8.103 -	extr.u r22=r21,IA64_PSR_I_BIT,1 ;;
   8.104 -	cmp.ne p7,p6=r22,r0 ;;
   8.105 +	extr.u r23=r21,IA64_PSR_I_BIT,1 ;;
   8.106 +	cmp.ne p7,p6=r23,r0 ;;
   8.107 +	// not done yet
   8.108  (p7)	dep r19=-1,r19,32,1
   8.109 -	extr.u r22=r21,IA64_PSR_IC_BIT,1 ;;
   8.110 -	cmp.ne p7,p6=r22,r0 ;;
   8.111 +	extr.u r23=r21,IA64_PSR_IC_BIT,1 ;;
   8.112 +	cmp.ne p7,p6=r23,r0 ;;
   8.113  (p7)	dep r19=-1,r19,0,1 ;;
   8.114  	st8 [r18]=r19 ;;
   8.115  	// force on psr.ic, i, dt, rt, it, bn
   8.116 @@ -421,6 +466,80 @@ 1:
   8.117  	rfi
   8.118  	;;
   8.119  
   8.120 +check_extint:
   8.121 +	br.sptk.many dispatch_break_fault ;;
   8.122 +
   8.123 +	// r18=&vpsr.i|vpsr.ic, r21==vpsr, r22=vcr.iip
   8.124 +	mov r30=IA64_KR(CURRENT);;
   8.125 +	adds r24=IA64_VCPU_INSVC3_OFFSET,r30;;
   8.126 +	mov r25=192
   8.127 +	adds r22=IA64_VCPU_IRR3_OFFSET,r30;;
   8.128 +	ld8 r23=[r22];;
   8.129 +	cmp.eq p6,p0=r23,r0;;
   8.130 +(p6)	adds r22=-8,r22;;
   8.131 +(p6)	adds r24=-8,r24;;
   8.132 +(p6)	adds r25=-64,r25;;
   8.133 +(p6)	ld8 r23=[r22];;
   8.134 +(p6)	cmp.eq p6,p0=r23,r0;;
   8.135 +(p6)	adds r22=-8,r22;;
   8.136 +(p6)	adds r24=-8,r24;;
   8.137 +(p6)	adds r25=-64,r25;;
   8.138 +(p6)	ld8 r23=[r22];;
   8.139 +(p6)	cmp.eq p6,p0=r23,r0;;
   8.140 +(p6)	adds r22=-8,r22;;
   8.141 +(p6)	adds r24=-8,r24;;
   8.142 +(p6)	adds r25=-64,r25;;
   8.143 +(p6)	ld8 r23=[r22];;
   8.144 +(p6)	cmp.eq p6,p0=r23,r0;;
   8.145 +	cmp.eq p6,p0=r23,r0
   8.146 +(p6)	br.cond.sptk.many 1f;	// this is actually an error
   8.147 +	// r22 points to non-zero element of irr, r23 has value
   8.148 +	// r24 points to corr element of insvc, r25 has elt*64
   8.149 +	ld8 r26=[r24];;
   8.150 +	cmp.geu p6,p0=r26,r23
   8.151 +(p6)	br.cond.spnt.many 1f;
   8.152 +	// not masked by insvc, get vector number
   8.153 +	shr.u r26=r23,1;;
   8.154 +	or r26=r23,r26;;
   8.155 +	shr.u r27=r26,2;;
   8.156 +	or r26=r26,r27;;
   8.157 +	shr.u r27=r26,4;;
   8.158 +	or r26=r26,r27;;
   8.159 +	shr.u r27=r26,8;;
   8.160 +	or r26=r26,r27;;
   8.161 +	shr.u r27=r26,16;;
   8.162 +	or r26=r26,r27;;
   8.163 +	shr.u r27=r26,32;;
   8.164 +	or r26=r26,r27;;
   8.165 +	andcm r26=0xffffffffffffffff,r26;;
   8.166 +	popcnt r26=r26;;
   8.167 +	sub r26=63,r26;;
   8.168 +	// r26 now contains the bit index (mod 64)
   8.169 +	mov r27=1;;
   8.170 +	shl r27=r27,r26;;
   8.171 +	// r27 now contains the (within the proper word) bit mask 
   8.172 +	add r26=r25,r26
   8.173 +	// r26 now contains the vector [0..255]
   8.174 +	adds r20=XSI_TPR_OFS-XSI_PSR_IC_OFS,r18 ;;
   8.175 +	ld8 r20=[r20] ;;
   8.176 +	extr.u r28=r20,16,1
   8.177 +	extr.u r29=r20,4,4 ;;
   8.178 +	cmp.ne p6,p0=r28,r0	// if tpr.mmi is set, return SPURIOUS
   8.179 +(p6)	br.cond.sptk.many 1f;
   8.180 +	shl r29=r29,4;;
   8.181 +	adds r29=15,r29;;
   8.182 +	cmp.ge p6,p0=r29,r26
   8.183 +(p6)	br.cond.sptk.many 1f;
   8.184 +	// OK, have an unmasked vector to process/return
   8.185 +	ld8 r25=[r24];;
   8.186 +	or r25=r25,r27;;
   8.187 +	st8 [r24]=r25;;
   8.188 +	ld8 r25=[r22];;
   8.189 +	andcm r25=r25,r27;;
   8.190 +	st8 [r22]=r25;;
   8.191 +	mov r8=r26;;
   8.192 +	// not done yet
   8.193 +
   8.194  ENTRY(hyper_cover)
   8.195  #ifdef FAST_HYPERPRIVOP_CNT
   8.196  	movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_COVER);;
   8.197 @@ -455,7 +574,6 @@ ENTRY(hyper_cover)
   8.198  	rfi
   8.199  	;;
   8.200  
   8.201 -#if 1
   8.202  // return from metaphysical mode (meta=1) to virtual mode (meta=0)
   8.203  ENTRY(hyper_ssm_dt)
   8.204  #ifdef FAST_HYPERPRIVOP_CNT
   8.205 @@ -526,4 +644,373 @@ 1:	extr.u r26=r24,41,2 ;;
   8.206  	mov pr=r31,-1 ;;
   8.207  	rfi
   8.208  	;;
   8.209 +
   8.210 +ENTRY(hyper_get_tpr)
   8.211 +#ifdef FAST_HYPERPRIVOP_CNT
   8.212 +	movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_GET_TPR);;
   8.213 +	ld8 r21=[r20];;
   8.214 +	adds r21=1,r21;;
   8.215 +	st8 [r20]=r21;;
   8.216  #endif
   8.217 +	mov r24=cr.ipsr
   8.218 +	mov r25=cr.iip;;
   8.219 +	adds r20=XSI_TPR_OFS-XSI_PSR_IC_OFS,r18 ;;
   8.220 +	ld8 r8=[r20];;
   8.221 +	extr.u r26=r24,41,2 ;;
   8.222 +	cmp.eq p6,p7=2,r26 ;;
   8.223 +(p6)	mov r26=0
   8.224 +(p6)	adds r25=16,r25
   8.225 +(p7)	adds r26=1,r26
   8.226 +	;;
   8.227 +	dep r24=r26,r24,41,2
   8.228 +	;;
   8.229 +	mov cr.ipsr=r24
   8.230 +	mov cr.iip=r25
   8.231 +	mov pr=r31,-1 ;;
   8.232 +	rfi
   8.233 +	;;
   8.234 +END(hyper_get_tpr)
   8.235 +
   8.236 +// if we get to here, there are no interrupts pending so we
   8.237 +// can change virtual tpr to any value without fear of provoking
   8.238 +// (or accidentally missing) delivering an interrupt
   8.239 +ENTRY(hyper_set_tpr)
   8.240 +#ifdef FAST_HYPERPRIVOP_CNT
   8.241 +	movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_SET_TPR);;
   8.242 +	ld8 r21=[r20];;
   8.243 +	adds r21=1,r21;;
   8.244 +	st8 [r20]=r21;;
   8.245 +#endif
   8.246 +	mov r24=cr.ipsr
   8.247 +	mov r25=cr.iip;;
   8.248 +	movl r27=0xff00;;
   8.249 +	adds r20=XSI_TPR_OFS-XSI_PSR_IC_OFS,r18 ;;
   8.250 +	andcm r8=r8,r27;;
   8.251 +	st8 [r20]=r8;;
   8.252 +	extr.u r26=r24,41,2 ;;
   8.253 +	cmp.eq p6,p7=2,r26 ;;
   8.254 +(p6)	mov r26=0
   8.255 +(p6)	adds r25=16,r25
   8.256 +(p7)	adds r26=1,r26
   8.257 +	;;
   8.258 +	dep r24=r26,r24,41,2
   8.259 +	;;
   8.260 +	mov cr.ipsr=r24
   8.261 +	mov cr.iip=r25
   8.262 +	mov pr=r31,-1 ;;
   8.263 +	rfi
   8.264 +	;;
   8.265 +END(hyper_set_tpr)
   8.266 +
   8.267 +ENTRY(hyper_get_ivr)
   8.268 +#ifdef FAST_HYPERPRIVOP_CNT
   8.269 +	movl r22=fast_hyperpriv_cnt+(8*XEN_HYPER_GET_IVR);;
   8.270 +	ld8 r21=[r22];;
   8.271 +	adds r21=1,r21;;
   8.272 +	st8 [r22]=r21;;
   8.273 +#endif
   8.274 +	mov r8=15;;
   8.275 +	// when we get to here r20=~=interrupts pending
   8.276 +	cmp.eq p7,p0=r20,r0;;
   8.277 +(p7)	adds r20=XSI_PEND_OFS-XSI_PSR_IC_OFS,r18 ;;
   8.278 +(p7)	st4 [r20]=r0;;
   8.279 +(p7)	br.spnt.many 1f ;;
   8.280 +	mov r30=IA64_KR(CURRENT);;
   8.281 +	adds r24=IA64_VCPU_INSVC3_OFFSET,r30;;
   8.282 +	mov r25=192
   8.283 +	adds r22=IA64_VCPU_IRR3_OFFSET,r30;;
   8.284 +	ld8 r23=[r22];;
   8.285 +	cmp.eq p6,p0=r23,r0;;
   8.286 +(p6)	adds r22=-8,r22;;
   8.287 +(p6)	adds r24=-8,r24;;
   8.288 +(p6)	adds r25=-64,r25;;
   8.289 +(p6)	ld8 r23=[r22];;
   8.290 +(p6)	cmp.eq p6,p0=r23,r0;;
   8.291 +(p6)	adds r22=-8,r22;;
   8.292 +(p6)	adds r24=-8,r24;;
   8.293 +(p6)	adds r25=-64,r25;;
   8.294 +(p6)	ld8 r23=[r22];;
   8.295 +(p6)	cmp.eq p6,p0=r23,r0;;
   8.296 +(p6)	adds r22=-8,r22;;
   8.297 +(p6)	adds r24=-8,r24;;
   8.298 +(p6)	adds r25=-64,r25;;
   8.299 +(p6)	ld8 r23=[r22];;
   8.300 +(p6)	cmp.eq p6,p0=r23,r0;;
   8.301 +	cmp.eq p6,p0=r23,r0
   8.302 +(p6)	br.cond.sptk.many 1f;	// this is actually an error
   8.303 +	// r22 points to non-zero element of irr, r23 has value
   8.304 +	// r24 points to corr element of insvc, r25 has elt*64
   8.305 +	ld8 r26=[r24];;
   8.306 +	cmp.geu p6,p0=r26,r23
   8.307 +(p6)	br.cond.spnt.many 1f;
   8.308 +	// not masked by insvc, get vector number
   8.309 +	shr.u r26=r23,1;;
   8.310 +	or r26=r23,r26;;
   8.311 +	shr.u r27=r26,2;;
   8.312 +	or r26=r26,r27;;
   8.313 +	shr.u r27=r26,4;;
   8.314 +	or r26=r26,r27;;
   8.315 +	shr.u r27=r26,8;;
   8.316 +	or r26=r26,r27;;
   8.317 +	shr.u r27=r26,16;;
   8.318 +	or r26=r26,r27;;
   8.319 +	shr.u r27=r26,32;;
   8.320 +	or r26=r26,r27;;
   8.321 +	andcm r26=0xffffffffffffffff,r26;;
   8.322 +	popcnt r26=r26;;
   8.323 +	sub r26=63,r26;;
   8.324 +	// r26 now contains the bit index (mod 64)
   8.325 +	mov r27=1;;
   8.326 +	shl r27=r27,r26;;
   8.327 +	// r27 now contains the (within the proper word) bit mask 
   8.328 +	add r26=r25,r26
   8.329 +	// r26 now contains the vector [0..255]
   8.330 +	adds r20=XSI_TPR_OFS-XSI_PSR_IC_OFS,r18 ;;
   8.331 +	ld8 r20=[r20] ;;
   8.332 +	extr.u r28=r20,16,1
   8.333 +	extr.u r29=r20,4,4 ;;
   8.334 +	cmp.ne p6,p0=r28,r0	// if tpr.mmi is set, return SPURIOUS
   8.335 +(p6)	br.cond.sptk.many 1f;
   8.336 +	shl r29=r29,4;;
   8.337 +	adds r29=15,r29;;
   8.338 +	cmp.ge p6,p0=r29,r26
   8.339 +(p6)	br.cond.sptk.many 1f;
   8.340 +	// OK, have an unmasked vector to process/return
   8.341 +	ld8 r25=[r24];;
   8.342 +	or r25=r25,r27;;
   8.343 +	st8 [r24]=r25;;
   8.344 +	ld8 r25=[r22];;
   8.345 +	andcm r25=r25,r27;;
   8.346 +	st8 [r22]=r25;;
   8.347 +	mov r8=r26;;
   8.348 +	// if its a clock tick, remember itm to avoid delivering it twice
   8.349 +	adds r20=XSI_ITV_OFS-XSI_PSR_IC_OFS,r18 ;;
   8.350 +	ld8 r20=[r20];;
   8.351 +	extr.u r20=r20,0,8;;
   8.352 +	cmp.eq p6,p0=r20,r8
   8.353 +	adds r22=IA64_VCPU_DOMAIN_ITM_LAST_OFFSET,r30
   8.354 +	adds r23=IA64_VCPU_DOMAIN_ITM_OFFSET,r30;;
   8.355 +	ld8 r23=[r23];;
   8.356 +(p6)	st8 [r22]=r23;;
   8.357 +	// all done
   8.358 +1:	mov r24=cr.ipsr
   8.359 +	mov r25=cr.iip;;
   8.360 +	extr.u r26=r24,41,2 ;;
   8.361 +	cmp.eq p6,p7=2,r26 ;;
   8.362 +(p6)	mov r26=0
   8.363 +(p6)	adds r25=16,r25
   8.364 +(p7)	adds r26=1,r26
   8.365 +	;;
   8.366 +	dep r24=r26,r24,41,2
   8.367 +	;;
   8.368 +	mov cr.ipsr=r24
   8.369 +	mov cr.iip=r25
   8.370 +	mov pr=r31,-1 ;;
   8.371 +	rfi
   8.372 +	;;
   8.373 +END(hyper_get_ivr)
   8.374 +
   8.375 +ENTRY(hyper_eoi)
   8.376 +	// when we get to here r20=~=interrupts pending
   8.377 +	cmp.ne p7,p0=r20,r0
   8.378 +(p7)	br.spnt.many dispatch_break_fault ;;
   8.379 +#ifdef FAST_HYPERPRIVOP_CNT
   8.380 +	movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_EOI);;
   8.381 +	ld8 r21=[r20];;
   8.382 +	adds r21=1,r21;;
   8.383 +	st8 [r20]=r21;;
   8.384 +#endif
   8.385 +	mov r22=IA64_KR(CURRENT);;
   8.386 +	adds r22=IA64_VCPU_INSVC3_OFFSET,r22;;
   8.387 +	ld8 r23=[r22];;
   8.388 +	cmp.eq p6,p0=r23,r0;;
   8.389 +(p6)	adds r22=-8,r22;;
   8.390 +(p6)	ld8 r23=[r22];;
   8.391 +(p6)	cmp.eq p6,p0=r23,r0;;
   8.392 +(p6)	adds r22=-8,r22;;
   8.393 +(p6)	ld8 r23=[r22];;
   8.394 +(p6)	cmp.eq p6,p0=r23,r0;;
   8.395 +(p6)	adds r22=-8,r22;;
   8.396 +(p6)	ld8 r23=[r22];;
   8.397 +(p6)	cmp.eq p6,p0=r23,r0;;
   8.398 +	cmp.eq p6,p0=r23,r0
   8.399 +(p6)	br.cond.sptk.many 1f;	// this is actually an error
   8.400 +	// r22 points to non-zero element of insvc, r23 has value
   8.401 +	shr.u r24=r23,1;;
   8.402 +	or r24=r23,r24;;
   8.403 +	shr.u r25=r24,2;;
   8.404 +	or r24=r24,r25;;
   8.405 +	shr.u r25=r24,4;;
   8.406 +	or r24=r24,r25;;
   8.407 +	shr.u r25=r24,8;;
   8.408 +	or r24=r24,r25;;
   8.409 +	shr.u r25=r24,16;;
   8.410 +	or r24=r24,r25;;
   8.411 +	shr.u r25=r24,32;;
   8.412 +	or r24=r24,r25;;
   8.413 +	andcm r24=0xffffffffffffffff,r24;;
   8.414 +	popcnt r24=r24;;
   8.415 +	sub r24=63,r24;;
   8.416 +	// r24 now contains the bit index
   8.417 +	mov r25=1;;
   8.418 +	shl r25=r25,r24;;
   8.419 +	andcm r23=r23,r25;;
   8.420 +	st8 [r22]=r23;;
   8.421 +1:	mov r24=cr.ipsr
   8.422 +	mov r25=cr.iip;;
   8.423 +	extr.u r26=r24,41,2 ;;
   8.424 +	cmp.eq p6,p7=2,r26 ;;
   8.425 +(p6)	mov r26=0
   8.426 +(p6)	adds r25=16,r25
   8.427 +(p7)	adds r26=1,r26
   8.428 +	;;
   8.429 +	dep r24=r26,r24,41,2
   8.430 +	;;
   8.431 +	mov cr.ipsr=r24
   8.432 +	mov cr.iip=r25
   8.433 +	mov pr=r31,-1 ;;
   8.434 +	rfi
   8.435 +	;;
   8.436 +END(hyper_eoi)
   8.437 +
   8.438 +ENTRY(hyper_set_itm)
   8.439 +	// when we get to here r20=~=interrupts pending
   8.440 +	cmp.ne p7,p0=r20,r0
   8.441 +(p7)	br.spnt.many dispatch_break_fault ;;
   8.442 +#ifdef FAST_HYPERPRIVOP_CNT
   8.443 +	movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_SET_ITM);;
   8.444 +	ld8 r21=[r20];;
   8.445 +	adds r21=1,r21;;
   8.446 +	st8 [r20]=r21;;
   8.447 +#endif
   8.448 +	movl r20=(PERCPU_ADDR)+IA64_CPUINFO_ITM_NEXT_OFFSET;;
   8.449 +	ld8 r21=[r20];;
   8.450 +	mov r20=IA64_KR(CURRENT);;
   8.451 +	adds r20=IA64_VCPU_DOMAIN_ITM_OFFSET,r20;;
   8.452 +	st8 [r20]=r8;;
   8.453 +	cmp.geu p6,p0=r21,r8;;
   8.454 +(p6)	mov r21=r8;;
   8.455 +	// now "safe set" cr.itm=r21
   8.456 +	mov r23=100;;
   8.457 +2:	mov cr.itm=r21;;
   8.458 +	srlz.d;;
   8.459 +	mov r22=ar.itc ;;
   8.460 +	cmp.leu p6,p0=r21,r22;;
   8.461 +	add r21=r21,r23;;
   8.462 +	shl r23=r23,1;;
   8.463 +(p6)	br.cond.spnt.few 2b;;
   8.464 +1:	mov r24=cr.ipsr
   8.465 +	mov r25=cr.iip;;
   8.466 +	extr.u r26=r24,41,2 ;;
   8.467 +	cmp.eq p6,p7=2,r26 ;;
   8.468 +(p6)	mov r26=0
   8.469 +(p6)	adds r25=16,r25
   8.470 +(p7)	adds r26=1,r26
   8.471 +	;;
   8.472 +	dep r24=r26,r24,41,2
   8.473 +	;;
   8.474 +	mov cr.ipsr=r24
   8.475 +	mov cr.iip=r25
   8.476 +	mov pr=r31,-1 ;;
   8.477 +	rfi
   8.478 +	;;
   8.479 +END(hyper_set_itm)
   8.480 +
   8.481 +ENTRY(hyper_get_rr)
   8.482 +#ifdef FAST_HYPERPRIVOP_CNT
   8.483 +	movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_GET_RR);;
   8.484 +	ld8 r21=[r20];;
   8.485 +	adds r21=1,r21;;
   8.486 +	st8 [r20]=r21;;
   8.487 +#endif
   8.488 +	extr.u r25=r8,61,3;;
   8.489 +	adds r20=XSI_RR0_OFS-XSI_PSR_IC_OFS,r18 ;;
   8.490 +	shl r25=r25,3;;
   8.491 +	add r20=r20,r25;;
   8.492 +	ld8 r8=[r20];;
   8.493 +1:	mov r24=cr.ipsr
   8.494 +	mov r25=cr.iip;;
   8.495 +	extr.u r26=r24,41,2 ;;
   8.496 +	cmp.eq p6,p7=2,r26 ;;
   8.497 +(p6)	mov r26=0
   8.498 +(p6)	adds r25=16,r25
   8.499 +(p7)	adds r26=1,r26
   8.500 +	;;
   8.501 +	dep r24=r26,r24,41,2
   8.502 +	;;
   8.503 +	mov cr.ipsr=r24
   8.504 +	mov cr.iip=r25
   8.505 +	mov pr=r31,-1 ;;
   8.506 +	rfi
   8.507 +	;;
   8.508 +END(hyper_get_rr)
   8.509 +
   8.510 +ENTRY(hyper_set_rr)
   8.511 +	extr.u r25=r8,61,3;;
   8.512 +	cmp.leu p7,p0=7,r25	// punt on setting rr7
   8.513 +(p7)	br.spnt.many dispatch_break_fault ;;
   8.514 +#ifdef FAST_HYPERPRIVOP_CNT
   8.515 +	movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_SET_RR);;
   8.516 +	ld8 r21=[r20];;
   8.517 +	adds r21=1,r21;;
   8.518 +	st8 [r20]=r21;;
   8.519 +#endif
   8.520 +	extr.u r26=r9,8,24	// r26 = r9.rid
   8.521 +	mov r20=IA64_KR(CURRENT);;
   8.522 +	adds r21=IA64_VCPU_STARTING_RID_OFFSET,r20;;
   8.523 +	ld4 r22=[r21];;
   8.524 +	adds r21=IA64_VCPU_ENDING_RID_OFFSET,r20;;
   8.525 +	ld4 r23=[r21];;
   8.526 +	adds r24=IA64_VCPU_META_SAVED_RR0_OFFSET,r20;;
   8.527 +	add r22=r26,r22;;
   8.528 +	cmp.geu p6,p0=r22,r23	// if r9.rid + starting_rid >= ending_rid
   8.529 +(p6)	br.cond.sptk.many 1f;	// this is an error, but just ignore/return
   8.530 +	// r21=starting_rid
   8.531 +	adds r20=XSI_RR0_OFS-XSI_PSR_IC_OFS,r18 ;;
   8.532 +	shl r25=r25,3;;
   8.533 +	add r20=r20,r25;;
   8.534 +	st8 [r20]=r9;;		// store away exactly what was passed
   8.535 +	// but adjust value actually placed in rr[r8]
   8.536 +	// r22 contains adjusted rid, "mangle" it (see regionreg.c)
   8.537 +	// and set ps to PAGE_SHIFT and ve to 1
   8.538 +	extr.u r27=r22,0,8
   8.539 +	extr.u r28=r22,8,8
   8.540 +	extr.u r29=r22,16,8;;
   8.541 +	dep.z r23=PAGE_SHIFT,2,6;;
   8.542 +	dep r23=-1,r23,0,1;;	// mangling is swapping bytes 1 & 3
   8.543 +	dep r23=r27,r23,24,8;;
   8.544 +	dep r23=r28,r23,16,8;;
   8.545 +	dep r23=r29,r23,8,8
   8.546 +	cmp.eq p6,p0=r25,r0;;	// if rr0, save for metaphysical
   8.547 +(p6)	st4 [r24]=r23
   8.548 +	mov rr[r8]=r23;;
   8.549 +	// done, mosey on back
   8.550 +1:	mov r24=cr.ipsr
   8.551 +	mov r25=cr.iip;;
   8.552 +	extr.u r26=r24,41,2 ;;
   8.553 +	cmp.eq p6,p7=2,r26 ;;
   8.554 +(p6)	mov r26=0
   8.555 +(p6)	adds r25=16,r25
   8.556 +(p7)	adds r26=1,r26
   8.557 +	;;
   8.558 +	dep r24=r26,r24,41,2
   8.559 +	;;
   8.560 +	mov cr.ipsr=r24
   8.561 +	mov cr.iip=r25
   8.562 +	mov pr=r31,-1 ;;
   8.563 +	rfi
   8.564 +	;;
   8.565 +END(hyper_set_rr)
   8.566 +
   8.567 +ENTRY(hyper_ptc_ga)
   8.568 +	br.spnt.many dispatch_break_fault ;;
   8.569 +END(hyper_ptc_ga)
   8.570 +
   8.571 +ENTRY(hyper_itc_d)
   8.572 +	br.spnt.many dispatch_break_fault ;;
   8.573 +END(hyper_itc_d)
   8.574 +
   8.575 +ENTRY(hyper_itc_i)
   8.576 +	br.spnt.many dispatch_break_fault ;;
   8.577 +END(hyper_itc_i)
   8.578 +
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/xen/arch/ia64/mm.c	Wed Jun 22 17:46:00 2005 +0000
     9.3 @@ -0,0 +1,141 @@
     9.4 +/******************************************************************************
     9.5 + * arch/ia64/mm.c
     9.6 + * 
     9.7 + * Copyright (c) 2002-2005 K A Fraser
     9.8 + * Copyright (c) 2004 Christian Limpach
     9.9 + * Copyright (c) 2005, Intel Corporation.
    9.10 + *  Xuefei Xu (Anthony Xu) (Anthony.xu@intel.com)
    9.11 + * 
    9.12 + * This program is free software; you can redistribute it and/or modify
    9.13 + * it under the terms of the GNU General Public License as published by
    9.14 + * the Free Software Foundation; either version 2 of the License, or
    9.15 + * (at your option) any later version.
    9.16 + * 
    9.17 + * This program is distributed in the hope that it will be useful,
    9.18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.20 + * GNU General Public License for more details.
    9.21 + * 
    9.22 + * You should have received a copy of the GNU General Public License
    9.23 + * along with this program; if not, write to the Free Software
    9.24 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    9.25 + */
    9.26 +
    9.27 +/*
    9.28 + * A description of the x86 page table API:
    9.29 + * 
    9.30 + * Domains trap to do_mmu_update with a list of update requests.
    9.31 + * This is a list of (ptr, val) pairs, where the requested operation
    9.32 + * is *ptr = val.
    9.33 + * 
    9.34 + * Reference counting of pages:
    9.35 + * ----------------------------
    9.36 + * Each page has two refcounts: tot_count and type_count.
    9.37 + * 
    9.38 + * TOT_COUNT is the obvious reference count. It counts all uses of a
    9.39 + * physical page frame by a domain, including uses as a page directory,
    9.40 + * a page table, or simple mappings via a PTE. This count prevents a
    9.41 + * domain from releasing a frame back to the free pool when it still holds
    9.42 + * a reference to it.
    9.43 + * 
    9.44 + * TYPE_COUNT is more subtle. A frame can be put to one of three
    9.45 + * mutually-exclusive uses: it might be used as a page directory, or a
    9.46 + * page table, or it may be mapped writable by the domain [of course, a
    9.47 + * frame may not be used in any of these three ways!].
    9.48 + * So, type_count is a count of the number of times a frame is being 
    9.49 + * referred to in its current incarnation. Therefore, a page can only
    9.50 + * change its type when its type count is zero.
    9.51 + * 
    9.52 + * Pinning the page type:
    9.53 + * ----------------------
    9.54 + * The type of a page can be pinned/unpinned with the commands
    9.55 + * MMUEXT_[UN]PIN_L?_TABLE. Each page can be pinned exactly once (that is,
    9.56 + * pinning is not reference counted, so it can't be nested).
    9.57 + * This is useful to prevent a page's type count falling to zero, at which
    9.58 + * point safety checks would need to be carried out next time the count
    9.59 + * is increased again.
    9.60 + * 
    9.61 + * A further note on writable page mappings:
    9.62 + * -----------------------------------------
    9.63 + * For simplicity, the count of writable mappings for a page may not
    9.64 + * correspond to reality. The 'writable count' is incremented for every
    9.65 + * PTE which maps the page with the _PAGE_RW flag set. However, for
    9.66 + * write access to be possible the page directory entry must also have
    9.67 + * its _PAGE_RW bit set. We do not check this as it complicates the 
    9.68 + * reference counting considerably [consider the case of multiple
    9.69 + * directory entries referencing a single page table, some with the RW
    9.70 + * bit set, others not -- it starts getting a bit messy].
    9.71 + * In normal use, this simplification shouldn't be a problem.
    9.72 + * However, the logic can be added if required.
    9.73 + * 
    9.74 + * One more note on read-only page mappings:
    9.75 + * -----------------------------------------
    9.76 + * We want domains to be able to map pages for read-only access. The
    9.77 + * main reason is that page tables and directories should be readable
    9.78 + * by a domain, but it would not be safe for them to be writable.
    9.79 + * However, domains have free access to rings 1 & 2 of the Intel
    9.80 + * privilege model. In terms of page protection, these are considered
    9.81 + * to be part of 'supervisor mode'. The WP bit in CR0 controls whether
    9.82 + * read-only restrictions are respected in supervisor mode -- if the 
    9.83 + * bit is clear then any mapped page is writable.
    9.84 + * 
    9.85 + * We get round this by always setting the WP bit and disallowing 
    9.86 + * updates to it. This is very unlikely to cause a problem for guest
    9.87 + * OS's, which will generally use the WP bit to simplify copy-on-write
    9.88 + * implementation (in that case, OS wants a fault when it writes to
    9.89 + * an application-supplied buffer).
    9.90 + */
    9.91 +
    9.92 +#include <xen/config.h>
    9.93 +#include <public/xen.h>
    9.94 +#include <xen/init.h>
    9.95 +#include <xen/lib.h>
    9.96 +#include <xen/mm.h>
    9.97 +#include <xen/errno.h>
    9.98 +#include <asm/vmx_vcpu.h>
    9.99 +#include <asm/vmmu.h>
   9.100 +#include <asm/regionreg.h>
   9.101 +
   9.102 +/*
   9.103 +        uregs->ptr is virtual address
   9.104 +        uregs->val is pte value
   9.105 + */
   9.106 +#ifdef CONFIG_VTI
   9.107 +int do_mmu_update(mmu_update_t *ureqs,u64 count,u64 *pdone,u64 foreigndom)
   9.108 +{
   9.109 +    int i,cmd;
   9.110 +    u64 mfn, gpfn;
   9.111 +    VCPU *vcpu;
   9.112 +    mmu_update_t req;
   9.113 +    ia64_rr rr;
   9.114 +    thash_cb_t *hcb;
   9.115 +    thash_data_t entry={0};
   9.116 +    vcpu = current;
   9.117 +    hcb = vmx_vcpu_get_vtlb(vcpu);
   9.118 +    for ( i = 0; i < count; i++ )
   9.119 +    {
   9.120 +        copy_from_user(&req, ureqs, sizeof(req));
   9.121 +        cmd = req.ptr&3;
   9.122 +        req.ptr &= ~3;
   9.123 +        if(cmd ==MMU_NORMAL_PT_UPDATE){
   9.124 +            entry.page_flags = req.val;
   9.125 +            entry.locked = 1;
   9.126 +            entry.tc = 1;
   9.127 +            entry.cl = DSIDE_TLB;
   9.128 +            rr = vmx_vcpu_rr(vcpu, req.ptr);
   9.129 +            entry.ps = rr.ps;
   9.130 +            entry.rid = rr.rid;
   9.131 +            vtlb_insert(hcb, &entry, req.ptr);
   9.132 +        }else if(cmd == MMU_MACHPHYS_UPDATE){
   9.133 +            mfn = req.ptr >>PAGE_SHIFT;
   9.134 +            gpfn = req.val;
   9.135 +            set_machinetophys(mfn,gpfn);
   9.136 +        }else{
   9.137 +            printf("Unkown command of mmu_update:ptr: %lx,val: %lx \n",req.ptr,req.val);
   9.138 +            while(1);
   9.139 +        }
   9.140 +        ureqs ++;
   9.141 +    }
   9.142 +    return 0;
   9.143 +}
   9.144 +#endif
    10.1 --- a/xen/arch/ia64/patch/linux-2.6.11/uaccess.h	Wed Jun 22 17:42:58 2005 +0000
    10.2 +++ b/xen/arch/ia64/patch/linux-2.6.11/uaccess.h	Wed Jun 22 17:46:00 2005 +0000
    10.3 @@ -1,6 +1,17 @@
    10.4 ---- ../../linux-2.6.11/include/asm-ia64/uaccess.h	2005-06-06 10:36:23.000000000 -0600
    10.5 -+++ include/asm-ia64/uaccess.h	2005-06-10 18:08:06.000000000 -0600
    10.6 -@@ -60,6 +60,11 @@
    10.7 +--- ../../linux-2.6.11/include/asm-ia64/uaccess.h	2005-03-02 00:37:53.000000000 -0700
    10.8 ++++ include/asm-ia64/uaccess.h	2005-06-21 21:53:20.000000000 -0600
    10.9 +@@ -32,6 +32,10 @@
   10.10 +  *	David Mosberger-Tang <davidm@hpl.hp.com>
   10.11 +  */
   10.12 + 
   10.13 ++#ifdef CONFIG_VTI
   10.14 ++#include <asm/vmx_uaccess.h>
   10.15 ++#else // CONFIG_VTI
   10.16 ++
   10.17 + #include <linux/compiler.h>
   10.18 + #include <linux/errno.h>
   10.19 + #include <linux/sched.h>
   10.20 +@@ -60,6 +64,11 @@
   10.21    * address TASK_SIZE is never valid.  We also need to make sure that the address doesn't
   10.22    * point inside the virtually mapped linear page table.
   10.23    */
   10.24 @@ -12,7 +23,7 @@
   10.25   #define __access_ok(addr, size, segment)						\
   10.26   ({											\
   10.27   	__chk_user_ptr(addr);								\
   10.28 -@@ -67,6 +72,7 @@
   10.29 +@@ -67,6 +76,7 @@
   10.30   	 && ((segment).seg == KERNEL_DS.seg						\
   10.31   	     || likely(REGION_OFFSET((unsigned long) (addr)) < RGN_MAP_LIMIT)));	\
   10.32   })
   10.33 @@ -20,3 +31,11 @@
   10.34   #define access_ok(type, addr, size)	__access_ok((addr), (size), get_fs())
   10.35   
   10.36   static inline int
   10.37 +@@ -343,6 +353,7 @@
   10.38 + 	__su_ret;						\
   10.39 + })
   10.40 + 
   10.41 ++#endif // CONFIG_VTI
   10.42 + /* Generic code can't deal with the location-relative format that we use for compactness.  */
   10.43 + #define ARCH_HAS_SORT_EXTABLE
   10.44 + #define ARCH_HAS_SEARCH_EXTABLE
    11.1 --- a/xen/arch/ia64/privop.c	Wed Jun 22 17:42:58 2005 +0000
    11.2 +++ b/xen/arch/ia64/privop.c	Wed Jun 22 17:46:00 2005 +0000
    11.3 @@ -205,8 +205,7 @@ IA64FAULT priv_itc_d(VCPU *vcpu, INST64 
    11.4  		return(IA64_ILLOP_FAULT);
    11.5  	if ((fault = vcpu_get_ifa(vcpu,&ifa)) != IA64_NO_FAULT)
    11.6  		return(IA64_ILLOP_FAULT);
    11.7 -	if (!inst.inst) pte = vcpu_get_tmp(vcpu,0);
    11.8 -	else pte = vcpu_get_gr(vcpu,inst.M41.r2);
    11.9 +	pte = vcpu_get_gr(vcpu,inst.M41.r2);
   11.10  
   11.11  	return (vcpu_itc_d(vcpu,pte,itir,ifa));
   11.12  }
   11.13 @@ -220,8 +219,7 @@ IA64FAULT priv_itc_i(VCPU *vcpu, INST64 
   11.14  		return(IA64_ILLOP_FAULT);
   11.15  	if ((fault = vcpu_get_ifa(vcpu,&ifa)) != IA64_NO_FAULT)
   11.16  		return(IA64_ILLOP_FAULT);
   11.17 -	if (!inst.inst) pte = vcpu_get_tmp(vcpu,0);
   11.18 -	else pte = vcpu_get_gr(vcpu,inst.M41.r2);
   11.19 +	pte = vcpu_get_gr(vcpu,inst.M41.r2);
   11.20  
   11.21  	return (vcpu_itc_i(vcpu,pte,itir,ifa));
   11.22  }
   11.23 @@ -800,12 +798,14 @@ ia64_hyperprivop(unsigned long iim, REGS
   11.24  		(void)vcpu_cover(v);
   11.25  		return 1;
   11.26  	    case HYPERPRIVOP_ITC_D:
   11.27 -		inst.inst = 0;
   11.28 -		(void)priv_itc_d(v,inst);
   11.29 +		(void)vcpu_get_itir(v,&itir);
   11.30 +		(void)vcpu_get_ifa(v,&ifa);
   11.31 +		(void)vcpu_itc_d(v,regs->r8,itir,ifa);
   11.32  		return 1;
   11.33  	    case HYPERPRIVOP_ITC_I:
   11.34 -		inst.inst = 0;
   11.35 -		(void)priv_itc_i(v,inst);
   11.36 +		(void)vcpu_get_itir(v,&itir);
   11.37 +		(void)vcpu_get_ifa(v,&ifa);
   11.38 +		(void)vcpu_itc_i(v,regs->r8,itir,ifa);
   11.39  		return 1;
   11.40  	    case HYPERPRIVOP_SSM_I:
   11.41  		(void)vcpu_set_psr_i(v);
   11.42 @@ -832,10 +832,8 @@ ia64_hyperprivop(unsigned long iim, REGS
   11.43  		regs->r8 = val;
   11.44  		return 1;
   11.45  	    case HYPERPRIVOP_PTC_GA:
   11.46 -		// FIXME: this doesn't seem to work yet, turned off
   11.47 -		//(void)vcpu_ptc_ga(v,regs->r8,regs->r9);
   11.48 -		//return 1;
   11.49 -		break;
   11.50 +		(void)vcpu_ptc_ga(v,regs->r8,(1L << ((regs->r9 & 0xfc) >> 2)));
   11.51 +		return 1;
   11.52  	    case HYPERPRIVOP_ITR_D:
   11.53  		(void)vcpu_get_itir(v,&itir);
   11.54  		(void)vcpu_get_ifa(v,&ifa);
    12.1 --- a/xen/arch/ia64/regionreg.c	Wed Jun 22 17:42:58 2005 +0000
    12.2 +++ b/xen/arch/ia64/regionreg.c	Wed Jun 22 17:46:00 2005 +0000
    12.3 @@ -148,11 +148,10 @@ int allocate_rid_range(struct domain *d,
    12.4  	for (j = i; j < i + n_rid_blocks; ++j) ridblock_owner[j] = d;
    12.5  	
    12.6  	// setup domain struct
    12.7 -	d->rid_bits = ridbits;
    12.8 -	d->starting_rid = i << IA64_MIN_IMPL_RID_BITS;
    12.9 -	d->ending_rid = (i+n_rid_blocks) << IA64_MIN_IMPL_RID_BITS;
   12.10 +	d->arch.rid_bits = ridbits;
   12.11 +	d->arch.starting_rid = i << IA64_MIN_IMPL_RID_BITS; d->arch.ending_rid = (i+n_rid_blocks) << IA64_MIN_IMPL_RID_BITS;
   12.12  printf("###allocating rid_range, domain %p: starting_rid=%lx, ending_rid=%lx\n",
   12.13 -d,d->starting_rid, d->ending_rid);
   12.14 +d,d->arch.starting_rid, d->arch.ending_rid);
   12.15  	
   12.16  	return 1;
   12.17  }
   12.18 @@ -161,14 +160,14 @@ d,d->starting_rid, d->ending_rid);
   12.19  int deallocate_rid_range(struct domain *d)
   12.20  {
   12.21  	int i;
   12.22 -	int rid_block_end = d->ending_rid >> IA64_MIN_IMPL_RID_BITS;
   12.23 -	int rid_block_start = d->starting_rid >> IA64_MIN_IMPL_RID_BITS;
   12.24 +	int rid_block_end = d->arch.ending_rid >> IA64_MIN_IMPL_RID_BITS;
   12.25 +	int rid_block_start = d->arch.starting_rid >> IA64_MIN_IMPL_RID_BITS;
   12.26  
   12.27  	return 1;  // KLUDGE ALERT
   12.28  	//
   12.29  	// not all domains will have allocated RIDs (physical mode loaders for instance)
   12.30  	//
   12.31 -	if (d->rid_bits == 0) return 1;
   12.32 +	if (d->arch.rid_bits == 0) return 1;
   12.33  
   12.34  #ifdef DEBUG
   12.35  	for (i = rid_block_start; i < rid_block_end; ++i) {
   12.36 @@ -179,9 +178,9 @@ int deallocate_rid_range(struct domain *
   12.37  	for (i = rid_block_start; i < rid_block_end; ++i)
   12.38  	ridblock_owner[i] = NULL;
   12.39  	
   12.40 -	d->rid_bits = 0;
   12.41 -	d->starting_rid = 0;
   12.42 -	d->ending_rid = 0;
   12.43 +	d->arch.rid_bits = 0;
   12.44 +	d->arch.starting_rid = 0;
   12.45 +	d->arch.ending_rid = 0;
   12.46  	return 1;
   12.47  }
   12.48  
   12.49 @@ -193,9 +192,8 @@ int deallocate_rid_range(struct domain *
   12.50  //  a region register; anytime it is "viewable" outside of this module,
   12.51  //  it should be unmangled
   12.52  
   12.53 -//This appears to work in Xen... turn it on later so no complications yet
   12.54 -#define CONFIG_MANGLE_RIDS
   12.55 -#ifdef CONFIG_MANGLE_RIDS
   12.56 +// NOTE: this function is also implemented in assembly code in hyper_set_rr!!
   12.57 +// Must ensure these two remain consistent!
   12.58  static inline unsigned long
   12.59  vmMangleRID(unsigned long RIDVal)
   12.60  {
   12.61 @@ -214,11 +212,6 @@ vmMangleRID(unsigned long RIDVal)
   12.62  
   12.63  // since vmMangleRID is symmetric, use it for unmangling also
   12.64  #define vmUnmangleRID(x)	vmMangleRID(x)
   12.65 -#else
   12.66 -// no mangling/unmangling
   12.67 -#define vmMangleRID(x)	(x)
   12.68 -#define vmUnmangleRID(x) (x)
   12.69 -#endif
   12.70  
   12.71  static inline void
   12.72  set_rr_no_srlz(unsigned long rr, unsigned long rrval)
   12.73 @@ -265,12 +258,12 @@ int set_one_rr(unsigned long rr, unsigne
   12.74  
   12.75  	rrv.rrval = val;
   12.76  	newrrv.rrval = 0;
   12.77 -	newrid = v->domain->starting_rid + rrv.rid;
   12.78 +	newrid = v->arch.starting_rid + rrv.rid;
   12.79  
   12.80 -	if (newrid > v->domain->ending_rid) {
   12.81 +	if (newrid > v->arch.ending_rid) {
   12.82  		printk("can't set rr%d to %lx, starting_rid=%lx,"
   12.83  			"ending_rid=%lx, val=%lx\n", rreg, newrid,
   12.84 -			v->domain->starting_rid,v->domain->ending_rid,val);
   12.85 +			v->arch.starting_rid,v->arch.ending_rid,val);
   12.86  		return 0;
   12.87  	}
   12.88  
   12.89 @@ -358,7 +351,7 @@ unsigned long physicalize_rid(struct vcp
   12.90  	ia64_rr rrv;
   12.91  	    
   12.92  	rrv.rrval = rrval;
   12.93 -	rrv.rid += v->domain->starting_rid;
   12.94 +	rrv.rid += v->arch.starting_rid;
   12.95  	return rrv.rrval;
   12.96  }
   12.97  
   12.98 @@ -368,7 +361,7 @@ virtualize_rid(struct vcpu *v, unsigned 
   12.99  	ia64_rr rrv;
  12.100  	    
  12.101  	rrv.rrval = rrval;
  12.102 -	rrv.rid -= v->domain->starting_rid;
  12.103 +	rrv.rid -= v->arch.starting_rid;
  12.104  	return rrv.rrval;
  12.105  }
  12.106  
    13.1 --- a/xen/arch/ia64/vmmu.c	Wed Jun 22 17:42:58 2005 +0000
    13.2 +++ b/xen/arch/ia64/vmmu.c	Wed Jun 22 17:46:00 2005 +0000
    13.3 @@ -792,3 +792,55 @@ IA64FAULT vmx_vcpu_tak(VCPU *vcpu, UINT6
    13.4      return IA64_NO_FAULT;
    13.5  }
    13.6  
    13.7 +/*
    13.8 + * [FIXME] Is there any effective way to move this routine
    13.9 + * into vmx_uaccess.h? struct exec_domain is incomplete type
   13.10 + * in that way...
   13.11 + *
   13.12 + * This is the interface to lookup virtual TLB, and then
   13.13 + * return corresponding machine address in 2nd parameter.
   13.14 + * The 3rd parameter contains how many bytes mapped by
   13.15 + * matched vTLB entry, thus to allow caller copy more once.
   13.16 + *
   13.17 + * If failed to lookup, -EFAULT is returned. Or else reutrn
   13.18 + * 0. All upper domain access utilities rely on this routine
   13.19 + * to determine the real machine address. 
   13.20 + *
   13.21 + * Yes, put_user and get_user seems to somhow slow upon it.
   13.22 + * However it's the necessary steps for any vmx domain virtual
   13.23 + * address, since that's difference address space as HV's one.
   13.24 + * Later some short-circuit may be created for special case
   13.25 + */
   13.26 +long
   13.27 +__domain_va_to_ma(unsigned long va, unsigned long* ma, unsigned long *len)
   13.28 +{
   13.29 +    unsigned long 	mpfn, gpfn, m, n = *len;
   13.30 +    thash_cb_t		*vtlb;
   13.31 +    unsigned long	end;	/* end of the area mapped by current entry */
   13.32 +    thash_data_t	*entry;
   13.33 +    struct vcpu *v = current;
   13.34 +    ia64_rr	vrr;
   13.35 +
   13.36 +    vtlb = vmx_vcpu_get_vtlb(v); 
   13.37 +    vrr = vmx_vcpu_rr(v, va);
   13.38 +    entry = vtlb_lookup_ex(vtlb, vrr.rid, va, DSIDE_TLB);
   13.39 +    if (entry == NULL)
   13.40 +	return -EFAULT;
   13.41 +
   13.42 +    gpfn =(entry->ppn>>(PAGE_SHIFT-12));
   13.43 +    gpfn =PAGEALIGN(gpfn,(entry->ps-PAGE_SHIFT));
   13.44 +    gpfn = gpfn | POFFSET(va>>PAGE_SHIFT,(entry->ps-PAGE_SHIFT)); 
   13.45 +
   13.46 +    mpfn = __gpfn_to_mfn(v->domain, gpfn);
   13.47 +    m = (mpfn<<PAGE_SHIFT) | (va & (PAGE_SIZE - 1));
   13.48 +    /* machine address may be not continuous */
   13.49 +    end = PAGEALIGN(m, PAGE_SHIFT) + PAGE_SIZE;
   13.50 +    /*end = PAGEALIGN(m, entry->ps) + PSIZE(entry->ps);*/
   13.51 +    /* Current entry can't map all requested area */
   13.52 +    if ((m + n) > end)
   13.53 +	n = end - m;
   13.54 +
   13.55 +    *ma = m;
   13.56 +    *len = n;
   13.57 +    return 0;
   13.58 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/xen/arch/ia64/vmx_hypercall.c	Wed Jun 22 17:46:00 2005 +0000
    14.3 @@ -0,0 +1,186 @@
    14.4 +/* -*-  Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
    14.5 +/*
    14.6 + * vmx_hyparcall.c: handling hypercall from domain
    14.7 + * Copyright (c) 2005, Intel Corporation.
    14.8 + *
    14.9 + * This program is free software; you can redistribute it and/or modify it
   14.10 + * under the terms and conditions of the GNU General Public License,
   14.11 + * version 2, as published by the Free Software Foundation.
   14.12 + *
   14.13 + * This program is distributed in the hope it will be useful, but WITHOUT
   14.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   14.16 + * more details.
   14.17 + *
   14.18 + * You should have received a copy of the GNU General Public License along with
   14.19 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
   14.20 + * Place - Suite 330, Boston, MA 02111-1307 USA.
   14.21 + *
   14.22 + *  Xuefei Xu (Anthony Xu) (Anthony.xu@intel.com)
   14.23 + */
   14.24 +
   14.25 +#include <xen/config.h>
   14.26 +#include <xen/errno.h>
   14.27 +#include <asm/vmx_vcpu.h>
   14.28 +#include <public/xen.h>
   14.29 +#include <public/event_channel.h>
   14.30 +#include <asm/vmmu.h>
   14.31 +#include <asm/tlb.h>
   14.32 +#include <asm/regionreg.h>
   14.33 +#include <asm/page.h>
   14.34 +#include <xen/mm.h>
   14.35 +
   14.36 +
   14.37 +void hyper_not_support(void)
   14.38 +{
   14.39 +    VCPU *vcpu=current;
   14.40 +    vmx_vcpu_set_gr(vcpu, 8, -1, 0);
   14.41 +    vmx_vcpu_increment_iip(vcpu);
   14.42 +}
   14.43 +
   14.44 +void hyper_mmu_update(void)
   14.45 +{
   14.46 +    VCPU *vcpu=current;
   14.47 +    u64 r32,r33,r34,r35,ret;
   14.48 +    vmx_vcpu_get_gr(vcpu,16,&r32);
   14.49 +    vmx_vcpu_get_gr(vcpu,17,&r33);
   14.50 +    vmx_vcpu_get_gr(vcpu,18,&r34);
   14.51 +    vmx_vcpu_get_gr(vcpu,19,&r35);
   14.52 +    ret=do_mmu_update((mmu_update_t*)r32,r33,r34,r35);
   14.53 +    vmx_vcpu_set_gr(vcpu, 8, ret, 0);
   14.54 +    vmx_vcpu_increment_iip(vcpu);
   14.55 +}
   14.56 +
   14.57 +void hyper_dom_mem_op(void)
   14.58 +{
   14.59 +    VCPU *vcpu=current;
   14.60 +    u64 r32,r33,r34,r35,r36;
   14.61 +    u64 ret;
   14.62 +    vmx_vcpu_get_gr(vcpu,16,&r32);
   14.63 +    vmx_vcpu_get_gr(vcpu,17,&r33);
   14.64 +    vmx_vcpu_get_gr(vcpu,18,&r34);
   14.65 +    vmx_vcpu_get_gr(vcpu,19,&r35);
   14.66 +    vmx_vcpu_get_gr(vcpu,20,&r36);
   14.67 +    ret=do_dom_mem_op(r32,(u64 *)r33,r34,r35,r36);
   14.68 +    printf("do_dom_mem return value: %lx\n", ret);
   14.69 +    vmx_vcpu_set_gr(vcpu, 8, ret, 0);
   14.70 +
   14.71 +    vmx_vcpu_increment_iip(vcpu);
   14.72 +}
   14.73 +
   14.74 +
   14.75 +void hyper_sched_op(void)
   14.76 +{
   14.77 +    VCPU *vcpu=current;
   14.78 +    u64 r32,ret;
   14.79 +    vmx_vcpu_get_gr(vcpu,16,&r32);
   14.80 +    ret=do_sched_op(r32);
   14.81 +    vmx_vcpu_set_gr(vcpu, 8, ret, 0);
   14.82 +
   14.83 +    vmx_vcpu_increment_iip(vcpu);
   14.84 +}
   14.85 +
   14.86 +void hyper_dom0_op(void)
   14.87 +{
   14.88 +    VCPU *vcpu=current;
   14.89 +    u64 r32,ret;
   14.90 +    vmx_vcpu_get_gr(vcpu,16,&r32);
   14.91 +    ret=do_dom0_op((dom0_op_t *)r32);
   14.92 +    vmx_vcpu_set_gr(vcpu, 8, ret, 0);
   14.93 +
   14.94 +    vmx_vcpu_increment_iip(vcpu);
   14.95 +}
   14.96 +
   14.97 +void hyper_event_channel_op(void)
   14.98 +{
   14.99 +    VCPU *vcpu=current;
  14.100 +    u64 r32,ret;
  14.101 +    vmx_vcpu_get_gr(vcpu,16,&r32);
  14.102 +    ret=do_event_channel_op((evtchn_op_t *)r32);
  14.103 +    vmx_vcpu_set_gr(vcpu, 8, ret, 0);
  14.104 +    vmx_vcpu_increment_iip(vcpu);
  14.105 +}
  14.106 +
  14.107 +void hyper_xen_version(void)
  14.108 +{
  14.109 +    VCPU *vcpu=current;
  14.110 +    u64 r32,ret;
  14.111 +    vmx_vcpu_get_gr(vcpu,16,&r32);
  14.112 +    ret=do_xen_version((int )r32);
  14.113 +    vmx_vcpu_set_gr(vcpu, 8, ret, 0);
  14.114 +    vmx_vcpu_increment_iip(vcpu);
  14.115 +}
  14.116 +
  14.117 +static int do_lock_page(VCPU *vcpu, u64 va, u64 lock)
  14.118 +{
  14.119 +    int i;
  14.120 +    ia64_rr rr;
  14.121 +    thash_cb_t *hcb;
  14.122 +    hcb = vmx_vcpu_get_vtlb(vcpu);
  14.123 +    rr = vmx_vcpu_rr(vcpu, va);
  14.124 +    return thash_lock_tc(hcb, va ,1U<<rr.ps, rr.rid, DSIDE_TLB, lock);
  14.125 +}
  14.126 +
  14.127 +/*
  14.128 + * Lock guest page in vTLB, so that it's not relinquished by recycle
  14.129 + * session when HV is servicing that hypercall.
  14.130 + */
  14.131 +void hyper_lock_page(void)
  14.132 +{
  14.133 +//TODO:
  14.134 +    VCPU *vcpu=current;
  14.135 +    u64 va,lock, ret;
  14.136 +    vmx_vcpu_get_gr(vcpu,16,&va);
  14.137 +    vmx_vcpu_get_gr(vcpu,17,&lock);
  14.138 +    ret=do_lock_page(vcpu, va, lock);
  14.139 +    vmx_vcpu_set_gr(vcpu, 8, ret, 0);
  14.140 +
  14.141 +    vmx_vcpu_increment_iip(vcpu);
  14.142 +}
  14.143 +
  14.144 +static int do_set_shared_page(VCPU *vcpu, u64 gpa)
  14.145 +{
  14.146 +    u64 shared_info, o_info;
  14.147 +    if(vcpu->domain!=dom0)
  14.148 +        return -EPERM;
  14.149 +    shared_info = __gpa_to_mpa(vcpu->domain, gpa);
  14.150 +    o_info = (u64)vcpu->domain->shared_info;
  14.151 +    vcpu->domain->shared_info= (shared_info_t *)__va(shared_info);
  14.152 +
  14.153 +    /* Copy existing shared info into new page */
  14.154 +    if (!o_info) {
  14.155 +	memcpy((void*)vcpu->domain->shared_info, (void*)o_info, PAGE_SIZE);
  14.156 +	/* If original page belongs to xen heap, then relinguish back
  14.157 +	 * to xen heap. Or else, leave to domain itself to decide.
  14.158 +	 */
  14.159 +	if (likely(IS_XEN_HEAP_FRAME(virt_to_page(o_info))))
  14.160 +		free_xenheap_page(o_info);
  14.161 +    }
  14.162 +    return 0;
  14.163 +}
  14.164 +
  14.165 +void hyper_set_shared_page(void)
  14.166 +{
  14.167 +    VCPU *vcpu=current;
  14.168 +    u64 gpa,ret;
  14.169 +    vmx_vcpu_get_gr(vcpu,16,&gpa);
  14.170 +
  14.171 +    ret=do_set_shared_page(vcpu, gpa);
  14.172 +    vmx_vcpu_set_gr(vcpu, 8, ret, 0);
  14.173 +
  14.174 +    vmx_vcpu_increment_iip(vcpu);
  14.175 +}
  14.176 +
  14.177 +/*
  14.178 +void hyper_grant_table_op(void)
  14.179 +{
  14.180 +    VCPU *vcpu=current;
  14.181 +    u64 r32,r33,r34,ret;
  14.182 +    vmx_vcpu_get_gr(vcpu,16,&r32);
  14.183 +    vmx_vcpu_get_gr(vcpu,17,&r33);
  14.184 +    vmx_vcpu_get_gr(vcpu,18,&r34);
  14.185 +
  14.186 +    ret=do_grant_table_op((unsigned int)r32, (void *)r33, (unsigned int)r34);
  14.187 +    vmx_vcpu_set_gr(vcpu, 8, ret, 0);
  14.188 +}
  14.189 +*/
    15.1 --- a/xen/arch/ia64/xenmisc.c	Wed Jun 22 17:42:58 2005 +0000
    15.2 +++ b/xen/arch/ia64/xenmisc.c	Wed Jun 22 17:46:00 2005 +0000
    15.3 @@ -62,8 +62,10 @@ void sync_lazy_execstate_cpu(unsigned in
    15.4  void sync_lazy_execstate_mask(cpumask_t mask) {}
    15.5  void sync_lazy_execstate_all(void) {}
    15.6  
    15.7 +#ifdef CONFIG_VTI
    15.8  int grant_table_create(struct domain *d) { return 0; }
    15.9  void grant_table_destroy(struct domain *d) { return; }
   15.10 +#endif
   15.11  
   15.12  struct pt_regs *guest_cpu_user_regs(void) { return ia64_task_regs(current); }
   15.13  
   15.14 @@ -72,6 +74,35 @@ void raise_actimer_softirq(void)
   15.15  	raise_softirq(AC_TIMER_SOFTIRQ);
   15.16  }
   15.17  
   15.18 +#ifndef CONFIG_VTI
   15.19 +unsigned long
   15.20 +__gpfn_to_mfn_foreign(struct domain *d, unsigned long gpfn)
   15.21 +{
   15.22 +	if (d == dom0)
   15.23 +		return(gpfn);
   15.24 +	else {
   15.25 +		unsigned long pte = lookup_domain_mpa(d,gpfn << PAGE_SHIFT);
   15.26 +		if (!pte) {
   15.27 +printk("__gpfn_to_mfn_foreign: bad gpfn. spinning...\n");
   15.28 +while(1);
   15.29 +			return 0;
   15.30 +		}
   15.31 +		return ((pte & _PFN_MASK) >> PAGE_SHIFT);
   15.32 +	}
   15.33 +}
   15.34 +
   15.35 +u32
   15.36 +__mfn_to_gpfn(struct domain *d, unsigned long frame)
   15.37 +{
   15.38 +	// FIXME: is this right?
   15.39 +if ((frame << PAGE_SHIFT) & _PAGE_PPN_MASK) {
   15.40 +printk("__mfn_to_gpfn: bad frame. spinning...\n");
   15.41 +while(1);
   15.42 +}
   15.43 +	return frame;
   15.44 +}
   15.45 +#endif
   15.46 +
   15.47  unsigned long __hypercall_create_continuation(
   15.48  	unsigned int op, unsigned int nr_args, ...)
   15.49  {
    16.1 --- a/xen/include/asm-ia64/config.h	Wed Jun 22 17:42:58 2005 +0000
    16.2 +++ b/xen/include/asm-ia64/config.h	Wed Jun 22 17:46:00 2005 +0000
    16.3 @@ -103,6 +103,9 @@ extern char _end[]; /* standard ELF symb
    16.4  #define	get_cpu()	0
    16.5  #define put_cpu()	do {} while(0)
    16.6  
    16.7 +// needed for common/dom0_ops.c until hyperthreading is supported
    16.8 +#define smp_num_siblings 1
    16.9 +
   16.10  // from linux/include/linux/mm.h
   16.11  struct page;
   16.12  
    17.1 --- a/xen/include/asm-ia64/domain.h	Wed Jun 22 17:42:58 2005 +0000
    17.2 +++ b/xen/include/asm-ia64/domain.h	Wed Jun 22 17:46:00 2005 +0000
    17.3 @@ -54,9 +54,6 @@ struct arch_domain {
    17.4      u64 entry;
    17.5  #endif
    17.6  };
    17.7 -#define starting_rid arch.starting_rid
    17.8 -#define ending_rid arch.ending_rid
    17.9 -#define rid_bits arch.rid_bits
   17.10  #define xen_vastart arch.xen_vastart
   17.11  #define xen_vaend arch.xen_vaend
   17.12  #define shared_info_va arch.shared_info_va
   17.13 @@ -83,6 +80,8 @@ struct arch_vcpu {
   17.14      int metaphysical_rr0;		// from arch_domain (so is pinned)
   17.15      int metaphysical_saved_rr0;		// from arch_domain (so is pinned)
   17.16      int breakimm;			// from arch_domain (so is pinned)
   17.17 +    int starting_rid;		/* first RID assigned to domain */
   17.18 +    int ending_rid;		/* one beyond highest RID assigned to domain */
   17.19      struct mm_struct *active_mm;
   17.20      struct thread_struct _thread;	// this must be last
   17.21  #ifdef CONFIG_VTI
    18.1 --- a/xen/include/asm-ia64/event.h	Wed Jun 22 17:42:58 2005 +0000
    18.2 +++ b/xen/include/asm-ia64/event.h	Wed Jun 22 17:46:00 2005 +0000
    18.3 @@ -11,6 +11,7 @@
    18.4  
    18.5  static inline void evtchn_notify(struct vcpu *v)
    18.6  {
    18.7 +	vcpu_pend_interrupt(v, v->vcpu_info->arch.evtchn_vector);
    18.8  }
    18.9  
   18.10  #endif
    19.1 --- a/xen/include/asm-ia64/mm.h	Wed Jun 22 17:42:58 2005 +0000
    19.2 +++ b/xen/include/asm-ia64/mm.h	Wed Jun 22 17:46:00 2005 +0000
    19.3 @@ -132,6 +132,7 @@ void add_to_domain_alloc_list(unsigned l
    19.4  
    19.5  static inline void put_page(struct pfn_info *page)
    19.6  {
    19.7 +#ifdef CONFIG_VTI	// doesn't work with non-VTI in grant tables yet
    19.8      u32 nx, x, y = page->count_info;
    19.9  
   19.10      do {
   19.11 @@ -142,12 +143,14 @@ static inline void put_page(struct pfn_i
   19.12  
   19.13      if (unlikely((nx & PGC_count_mask) == 0))
   19.14  	free_domheap_page(page);
   19.15 +#endif
   19.16  }
   19.17  
   19.18  /* count_info and ownership are checked atomically. */
   19.19  static inline int get_page(struct pfn_info *page,
   19.20                             struct domain *domain)
   19.21  {
   19.22 +#ifdef CONFIG_VTI
   19.23      u64 x, nx, y = *((u64*)&page->count_info);
   19.24      u32 _domain = pickle_domptr(domain);
   19.25  
   19.26 @@ -164,13 +167,34 @@ static inline int get_page(struct pfn_in
   19.27  	}
   19.28      }
   19.29      while(unlikely(y = cmpxchg(&page->count_info, x, nx)) != x);
   19.30 -
   19.31 +#endif
   19.32      return 1;
   19.33  }
   19.34  
   19.35  /* No type info now */
   19.36 -#define put_page_and_type(page) put_page((page))
   19.37 -#define get_page_and_type(page, domain, type) get_page((page))
   19.38 +#define put_page_type(page)
   19.39 +#define get_page_type(page, type) 1
   19.40 +static inline void put_page_and_type(struct pfn_info *page)
   19.41 +{
   19.42 +    put_page_type(page);
   19.43 +    put_page(page);
   19.44 +}
   19.45 +
   19.46 +
   19.47 +static inline int get_page_and_type(struct pfn_info *page,
   19.48 +                                    struct domain *domain,
   19.49 +                                    u32 type)
   19.50 +{
   19.51 +    int rc = get_page(page, domain);
   19.52 +
   19.53 +    if ( likely(rc) && unlikely(!get_page_type(page, type)) )
   19.54 +    {
   19.55 +        put_page(page);
   19.56 +        rc = 0;
   19.57 +    }
   19.58 +
   19.59 +    return rc;
   19.60 +}
   19.61  
   19.62  #define	set_machinetophys(_mfn, _pfn) do { } while(0);
   19.63  
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/xen/include/asm-ia64/shadow.h	Wed Jun 22 17:46:00 2005 +0000
    20.3 @@ -0,0 +1,1 @@
    20.4 +/* empty */
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/xen/include/asm-ia64/vmx_uaccess.h	Wed Jun 22 17:46:00 2005 +0000
    21.3 @@ -0,0 +1,156 @@
    21.4 +/* -*-  Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
    21.5 +/*
    21.6 + * vmx_uaccess.h: Defines vmx specific macros to transfer memory areas
    21.7 + * across the domain/hypervisor boundary.
    21.8 + *
    21.9 + * This program is free software; you can redistribute it and/or modify it
   21.10 + * under the terms and conditions of the GNU General Public License,
   21.11 + * version 2, as published by the Free Software Foundation.
   21.12 + *
   21.13 + * This program is distributed in the hope it will be useful, but WITHOUT
   21.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   21.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   21.16 + * more details.
   21.17 + *
   21.18 + * You should have received a copy of the GNU General Public License along with
   21.19 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
   21.20 + * Place - Suite 330, Boston, MA 02111-1307 USA.
   21.21 + *
   21.22 + * Note:  For vmx enabled environment, poor man's policy is actually
   21.23 + * useless since HV resides in completely different address space as
   21.24 + * domain. So the only way to do the access is search vTLB first, and
   21.25 + * access identity mapped address if hit.
   21.26 + *
   21.27 + * Copyright (c) 2004, Intel Corporation.
   21.28 + * 	Kun Tian (Kevin Tian) (kevin.tian@intel.com)
   21.29 + */
   21.30 +
   21.31 +#ifndef __ASM_IA64_VMX_UACCESS_H__
   21.32 +#define __ASM_IA64_VMX_UACCESS_H__
   21.33 +
   21.34 +#include <xen/compiler.h>
   21.35 +#include <xen/errno.h>
   21.36 +#include <xen/sched.h>
   21.37 +
   21.38 +#include <asm/intrinsics.h>
   21.39 +#include <asm/vmmu.h>
   21.40 +
   21.41 +/* Since HV never accesses domain space directly, most security check can
   21.42 + * be dummy now
   21.43 + */
   21.44 +asm (".section \"__ex_table\", \"a\"\n\t.previous");
   21.45 +
   21.46 +/* For back compatibility */
   21.47 +#define __access_ok(addr, size, segment)	1
   21.48 +#define access_ok(addr, size, segment)	__access_ok((addr), (size), (segment))
   21.49 +
   21.50 +/*
   21.51 + * These are the main single-value transfer routines.  They automatically
   21.52 + * use the right size if we just have the right pointer type.
   21.53 + *
   21.54 + * Careful to not
   21.55 + * (a) re-use the arguments for side effects (sizeof/typeof is ok)
   21.56 + * (b) require any knowledge of processes at this stage
   21.57 + */
   21.58 +#define put_user(x, ptr)	__put_user((x), (ptr))
   21.59 +#define get_user(x, ptr)	__get_user((x), (ptr))
   21.60 +
   21.61 +#define __put_user(x, ptr)	__do_put_user((__typeof__(*(ptr))) (x), (ptr), sizeof(*(ptr)))
   21.62 +#define __get_user(x, ptr)	__do_get_user((x), (ptr), sizeof(*(ptr)))
   21.63 +
   21.64 +/* TODO: add specific unaligned access later. If assuming aligned at
   21.65 + * 1,2,4,8 bytes by far, it's impossible for operand spaning two
   21.66 + * vTLB entry
   21.67 + */
   21.68 +extern long
   21.69 +__domain_va_to_ma(unsigned long va, unsigned long* ma, unsigned long *len);
   21.70 +
   21.71 +#define __do_put_user(x, ptr, size)					\
   21.72 +({									\
   21.73 +    __typeof__ (x) __pu_x = (x);					\
   21.74 +    __typeof__ (*(ptr)) __user *__pu_ptr = (ptr);			\
   21.75 +    __typeof__ (size) __pu_size = (size);				\
   21.76 +    unsigned long __pu_ma;						\
   21.77 +    long __pu_err;							\
   21.78 +									\
   21.79 +    __pu_err = __domain_va_to_ma((unsigned long)__pu_ptr,		\
   21.80 +				&__pu_ma, &__pu_size);			\
   21.81 +    __pu_err ? (__pu_err = -EFAULT) :					\
   21.82 +    	(*((__typeof__ (*(ptr)) *)__va(__pu_ma)) = x);			\
   21.83 +    __pu_err;								\
   21.84 +})
   21.85 +
   21.86 +#define __do_get_user(x, ptr, size)					\
   21.87 +({									\
   21.88 +    __typeof__ (x) __gu_x = (x);					\
   21.89 +    __typeof__ (*(ptr)) __user *__gu_ptr = (ptr);			\
   21.90 +    __typeof__ (size) __gu_size = (size);				\
   21.91 +    unsigned long __gu_ma;						\
   21.92 +    long __gu_err;							\
   21.93 +									\
   21.94 +    __gu_err = __domain_va_to_ma((unsigned long)__gu_ptr,		\
   21.95 +				&__gu_ma, &__gu_size);			\
   21.96 +    __gu_err ? (__gu_err = -EFAULT) :					\
   21.97 +    	(x = *((__typeof__ (*(ptr)) *)__va(__gu_ma)));			\
   21.98 +    __gu_err;								\
   21.99 +})
  21.100 +
  21.101 +/* More complex copy from domain */
  21.102 +#define copy_from_user(to, from, n)	__copy_from_user((to), (from), (n))
  21.103 +#define copy_to_user(to, from, n)	__copy_to_user((to), (from), (n))
  21.104 +#define clear_user(to, n)		__clear_user((t0), (n))
  21.105 +
  21.106 +static inline unsigned long
  21.107 +__copy_from_user(void *to, void *from, unsigned long n)
  21.108 +{
  21.109 +    unsigned long ma, i;
  21.110 +
  21.111 +    i = n;
  21.112 +    while(!__domain_va_to_ma((unsigned long)from, &ma, &i)) {
  21.113 +	    memcpy(to, (void *)__va(ma), i);
  21.114 +	    n -= i;
  21.115 +        if (!n)
  21.116 +            break;
  21.117 +	    from += i;
  21.118 +	    to += i;
  21.119 +	    i = n;
  21.120 +    }
  21.121 +    return n;
  21.122 +}
  21.123 +
  21.124 +static inline unsigned long
  21.125 +__copy_to_user(void *to, void *from, unsigned long n)
  21.126 +{
  21.127 +    unsigned long ma, i;
  21.128 +
  21.129 +    i = n;
  21.130 +    while(!__domain_va_to_ma((unsigned long)to, &ma, &i)) {
  21.131 +	    memcpy((void *)__va(ma), from, i);
  21.132 +	    n -= i;
  21.133 +        if (!n)
  21.134 +            break;
  21.135 +	    from += i;
  21.136 +	    to += i;
  21.137 +	    i = n;
  21.138 +    }
  21.139 +    return n;
  21.140 +}
  21.141 +
  21.142 +static inline unsigned long
  21.143 +__clear_user(void *to, unsigned long n)
  21.144 +{
  21.145 +    unsigned long ma, i;
  21.146 +
  21.147 +    i = n;
  21.148 +    while(!__domain_va_to_ma((unsigned long)to, &ma, &i)) {
  21.149 +	    memset((void *)__va(ma), 0, i);
  21.150 +	    n -= i;
  21.151 +        if (!n)
  21.152 +            break;
  21.153 +	    to += i;
  21.154 +	    i = n;
  21.155 +    }
  21.156 +    return n;
  21.157 +}
  21.158 +
  21.159 +#endif // __ASM_IA64_VMX_UACCESS_H__
    22.1 --- a/xen/include/asm-ia64/xensystem.h	Wed Jun 22 17:42:58 2005 +0000
    22.2 +++ b/xen/include/asm-ia64/xensystem.h	Wed Jun 22 17:46:00 2005 +0000
    22.3 @@ -61,5 +61,37 @@ extern struct task_struct *vmx_ia64_swit
    22.4  } while (0)
    22.5  #endif // CONFIG_VTI
    22.6  
    22.7 +#define __cmpxchg_user(ptr, new, old, _size)				\
    22.8 +({									\
    22.9 +	register long __gu_r8 asm ("r8");				\
   22.10 +	register long __gu_r9 asm ("r9");				\
   22.11 +	asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));			\
   22.12 +	asm volatile ("mov %2=r0;;\n"					\
   22.13 +		"[1:]\tcmpxchg"_size".acq %0=[%3],%4,ar.ccv\n"		\
   22.14 +		"\t.xdata4 \"__ex_table\", 1b-., 1f-.+4\n"		\
   22.15 +		"[1:]"							\
   22.16 +		: "=r"(old), "=r"(__gu_r9), "=r"(__gu_r8) :		\
   22.17 +		"r"(ptr), "r"(new) : "memory");				\
   22.18 +	(old) = __gu_r9;						\
   22.19 +	__gu_r8;							\
   22.20 +})
   22.21 +
   22.22 +
   22.23 +// NOTE: Xen defines args as pointer,old,new whereas ia64 uses pointer,new,old
   22.24 +//  so reverse them here
   22.25 +#define cmpxchg_user(_p,_o,_n)					\
   22.26 +({								\
   22.27 +	register long _rc;					\
   22.28 +	ia64_mf();						\
   22.29 +	switch ( sizeof(*(_p)) ) {				\
   22.30 +	    case 1: _rc = __cmpxchg_user(_p,_n,_o,"1"); break;	\
   22.31 +	    case 2: _rc = __cmpxchg_user(_p,_n,_o,"2"); break;	\
   22.32 +	    case 4: _rc = __cmpxchg_user(_p,_n,_o,"4"); break;	\
   22.33 +	    case 8: _rc = __cmpxchg_user(_p,_n,_o,"8"); break;	\
   22.34 +	}							\
   22.35 +	ia64_mf();						\
   22.36 +	_rc;							\
   22.37 +})
   22.38 +
   22.39  #endif // __ASSEMBLY__
   22.40  #endif // _ASM_IA64_XENSYSTEM_H
    23.1 --- a/xen/include/public/arch-ia64.h	Wed Jun 22 17:42:58 2005 +0000
    23.2 +++ b/xen/include/public/arch-ia64.h	Wed Jun 22 17:46:00 2005 +0000
    23.3 @@ -182,11 +182,11 @@ typedef struct {
    23.4  	unsigned long krs[8];	// kernel registers
    23.5  	unsigned long pkrs[8];	// protection key registers
    23.6  	unsigned long tmp[8];	// temp registers (e.g. for hyperprivops)
    23.7 +	int evtchn_vector;
    23.8  //} PACKED arch_vcpu_info_t;
    23.9  } arch_vcpu_info_t;		// DON'T PACK 
   23.10  
   23.11  typedef struct {
   23.12 -	int evtchn_vector;
   23.13  	int domain_controller_evtchn;
   23.14  	unsigned int flags;
   23.15  //} PACKED arch_shared_info_t;
   23.16 @@ -200,12 +200,22 @@ typedef struct vcpu_guest_context {
   23.17  
   23.18  #endif /* !__ASSEMBLY__ */
   23.19  
   23.20 -#define	XEN_HYPER_RFI			1
   23.21 -#define	XEN_HYPER_RSM_DT		2
   23.22 -#define	XEN_HYPER_SSM_DT		3
   23.23 -#define	XEN_HYPER_COVER			4
   23.24 -#define	XEN_HYPER_ITC_D			5
   23.25 -#define	XEN_HYPER_ITC_I			6
   23.26 -#define	XEN_HYPER_SSM_I			7
   23.27 +#define	XEN_HYPER_RFI			0x1
   23.28 +#define	XEN_HYPER_RSM_DT		0x2
   23.29 +#define	XEN_HYPER_SSM_DT		0x3
   23.30 +#define	XEN_HYPER_COVER			0x4
   23.31 +#define	XEN_HYPER_ITC_D			0x5
   23.32 +#define	XEN_HYPER_ITC_I			0x6
   23.33 +#define	XEN_HYPER_SSM_I			0x7
   23.34 +#define	XEN_HYPER_GET_IVR		0x8
   23.35 +#define	XEN_HYPER_GET_TPR		0x9
   23.36 +#define	XEN_HYPER_SET_TPR		0xa
   23.37 +#define	XEN_HYPER_EOI			0xb
   23.38 +#define	XEN_HYPER_SET_ITM		0xc
   23.39 +#define	XEN_HYPER_THASH			0xd
   23.40 +#define	XEN_HYPER_PTC_GA		0xe
   23.41 +#define	XEN_HYPER_ITR_D			0xf
   23.42 +#define	XEN_HYPER_GET_RR		0x10
   23.43 +#define	XEN_HYPER_SET_RR		0x11
   23.44  
   23.45  #endif /* __HYPERVISOR_IF_IA64_H__ */