ia64/xen-unstable
changeset 5560:51d5c1d35710
bitkeeper revision 1.1742 (42ba8b7fiNx5Cu0J91l9HCIo_TwvXQ)
Merge firebug.cl.cam.ac.uk:/local/scratch/kaf24/xen-unstable.bk
into firebug.cl.cam.ac.uk:/local/scratch/kaf24/xeno-unstable-ia64.bk
Merge firebug.cl.cam.ac.uk:/local/scratch/kaf24/xen-unstable.bk
into firebug.cl.cam.ac.uk:/local/scratch/kaf24/xeno-unstable-ia64.bk
line diff
1.1 --- a/.rootkeys Thu Jun 23 10:05:06 2005 +0000 1.2 +++ b/.rootkeys Thu Jun 23 10:14:23 2005 +0000 1.3 @@ -1132,6 +1132,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 @@ -1139,6 +1140,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 @@ -1237,6 +1239,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 @@ -1405,6 +1408,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 @@ -1418,6 +1422,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 Thu Jun 23 10:05:06 2005 +0000 2.2 +++ b/xen/arch/ia64/Makefile Thu Jun 23 10:14:23 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 Thu Jun 23 10:05:06 2005 +0000 3.2 +++ b/xen/arch/ia64/asm-offsets.c Thu Jun 23 10:14:23 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 Thu Jun 23 10:05:06 2005 +0000 4.2 +++ b/xen/arch/ia64/dom0_ops.c Thu Jun 23 10:14:23 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 Thu Jun 23 10:05:06 2005 +0000 5.2 +++ b/xen/arch/ia64/domain.c Thu Jun 23 10:14:23 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 Thu Jun 23 10:14:23 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(>->lock); 6.809 + 6.810 + for ( i = 0; i < NR_GRANT_ENTRIES; i++ ) 6.811 + { 6.812 + act = >->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 = >->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(>->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 = >->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 Thu Jun 23 10:05:06 2005 +0000 7.2 +++ b/xen/arch/ia64/hypercall.c Thu Jun 23 10:14:23 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 Thu Jun 23 10:05:06 2005 +0000 8.2 +++ b/xen/arch/ia64/hyperprivop.S Thu Jun 23 10:14:23 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 Thu Jun 23 10:14:23 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 Thu Jun 23 10:05:06 2005 +0000 10.2 +++ b/xen/arch/ia64/patch/linux-2.6.11/uaccess.h Thu Jun 23 10:14:23 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 Thu Jun 23 10:05:06 2005 +0000 11.2 +++ b/xen/arch/ia64/privop.c Thu Jun 23 10:14:23 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 Thu Jun 23 10:05:06 2005 +0000 12.2 +++ b/xen/arch/ia64/regionreg.c Thu Jun 23 10:14:23 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 Thu Jun 23 10:05:06 2005 +0000 13.2 +++ b/xen/arch/ia64/vmmu.c Thu Jun 23 10:14:23 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 Thu Jun 23 10:14:23 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 Thu Jun 23 10:05:06 2005 +0000 15.2 +++ b/xen/arch/ia64/xenmisc.c Thu Jun 23 10:14:23 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 Thu Jun 23 10:05:06 2005 +0000 16.2 +++ b/xen/include/asm-ia64/config.h Thu Jun 23 10:14:23 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 Thu Jun 23 10:05:06 2005 +0000 17.2 +++ b/xen/include/asm-ia64/domain.h Thu Jun 23 10:14:23 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 Thu Jun 23 10:05:06 2005 +0000 18.2 +++ b/xen/include/asm-ia64/event.h Thu Jun 23 10:14:23 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 Thu Jun 23 10:05:06 2005 +0000 19.2 +++ b/xen/include/asm-ia64/mm.h Thu Jun 23 10:14:23 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 Thu Jun 23 10:14:23 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 Thu Jun 23 10:14:23 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 Thu Jun 23 10:05:06 2005 +0000 22.2 +++ b/xen/include/asm-ia64/xensystem.h Thu Jun 23 10:14:23 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 Thu Jun 23 10:05:06 2005 +0000 23.2 +++ b/xen/include/public/arch-ia64.h Thu Jun 23 10:14:23 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__ */