ia64/xen-unstable

changeset 11745:5176c3ea3293

[IA64] per vcpu vhpt

Implement per vcpu vhpt option. allocate VHPT per vcpu.
added compile time option, xen_ia64_pervcpu_vhpt=y, to enable it.
Its default is on.
added xen boot time option, pervcpu_vhpt=0, to disable it.

This patch focuses on vcpu migration between physical cpus
becaseu vcpu is heavily migrated with credit scheduler.
This patch tries to reduce vTLB flush when vcpu is migrated

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author awilliam@xenbuild.aw
date Sun Oct 08 18:55:12 2006 -0600 (2006-10-08)
parents 4eb6e2ec1b39
children b725c9e51a7c
files xen/arch/ia64/Rules.mk xen/arch/ia64/vmx/vmx_entry.S xen/arch/ia64/xen/domain.c xen/arch/ia64/xen/regionreg.c xen/arch/ia64/xen/vhpt.c xen/include/asm-ia64/domain.h xen/include/asm-ia64/vhpt.h xen/include/asm-ia64/xenkregs.h
line diff
     1.1 --- a/xen/arch/ia64/Rules.mk	Sun Oct 08 18:35:17 2006 -0600
     1.2 +++ b/xen/arch/ia64/Rules.mk	Sun Oct 08 18:55:12 2006 -0600
     1.3 @@ -6,6 +6,7 @@ HAS_VGA  := y
     1.4  VALIDATE_VT	?= n
     1.5  no_warns ?= n
     1.6  xen_ia64_expose_p2m	?= y
     1.7 +xen_ia64_pervcpu_vhpt	?= y
     1.8  
     1.9  ifneq ($(COMPILE_ARCH),$(TARGET_ARCH))
    1.10  CROSS_COMPILE ?= /usr/local/sp_env/v2.2.5/i686/bin/ia64-unknown-linux-
    1.11 @@ -40,6 +41,9 @@ endif
    1.12  ifeq ($(xen_ia64_expose_p2m),y)
    1.13  CFLAGS	+= -DCONFIG_XEN_IA64_EXPOSE_P2M
    1.14  endif
    1.15 +ifeq ($(xen_ia64_pervcpu_vhpt),y)
    1.16 +CFLAGS	+= -DCONFIG_XEN_IA64_PERVCPU_VHPT
    1.17 +endif
    1.18  ifeq ($(no_warns),y)
    1.19  CFLAGS	+= -Wa,--fatal-warnings -Werror -Wno-uninitialized
    1.20  endif
     2.1 --- a/xen/arch/ia64/vmx/vmx_entry.S	Sun Oct 08 18:35:17 2006 -0600
     2.2 +++ b/xen/arch/ia64/vmx/vmx_entry.S	Sun Oct 08 18:55:12 2006 -0600
     2.3 @@ -669,7 +669,7 @@ 1:
     2.4  
     2.5     // re-pin mappings for guest_vhpt
     2.6  
     2.7 -   mov r24=IA64_TR_PERVP_VHPT
     2.8 +   mov r24=IA64_TR_VHPT
     2.9     movl r25=PAGE_KERNEL
    2.10     ;;
    2.11     or loc5 = r25,loc5          // construct PA | page properties
     3.1 --- a/xen/arch/ia64/xen/domain.c	Sun Oct 08 18:35:17 2006 -0600
     3.2 +++ b/xen/arch/ia64/xen/domain.c	Sun Oct 08 18:55:12 2006 -0600
     3.3 @@ -69,6 +69,16 @@ DEFINE_PER_CPU(int *, current_psr_ic_add
     3.4  
     3.5  #include <xen/sched-if.h>
     3.6  
     3.7 +static void
     3.8 +ia64_disable_vhpt_walker(void)
     3.9 +{
    3.10 +	// disable VHPT. ia64_new_rr7() might cause VHPT
    3.11 +	// fault without this because it flushes dtr[IA64_TR_VHPT]
    3.12 +	// (VHPT_SIZE_LOG2 << 2) is just for avoid
    3.13 +	// Reserved Register/Field fault.
    3.14 +	ia64_set_pta(VHPT_SIZE_LOG2 << 2);
    3.15 +}
    3.16 +
    3.17  static void flush_vtlb_for_context_switch(struct vcpu* vcpu)
    3.18  {
    3.19  	int cpu = smp_processor_id();
    3.20 @@ -92,8 +102,10 @@ static void flush_vtlb_for_context_switc
    3.21  		if (VMX_DOMAIN(vcpu)) {
    3.22  			// currently vTLB for vt-i domian is per vcpu.
    3.23  			// so any flushing isn't needed.
    3.24 +		} else if (HAS_PERVCPU_VHPT(vcpu->domain)) {
    3.25 +			// nothing to do
    3.26  		} else {
    3.27 -			vhpt_flush();
    3.28 +			local_vhpt_flush();
    3.29  		}
    3.30  		local_flush_tlb_all();
    3.31  		perfc_incrc(flush_vtlb_for_context_switch);
    3.32 @@ -111,9 +123,9 @@ void schedule_tail(struct vcpu *prev)
    3.33  		              current->processor);
    3.34  	} else {
    3.35  		ia64_set_iva(&ia64_ivt);
    3.36 -        	ia64_set_pta(VHPT_ADDR | (1 << 8) | (VHPT_SIZE_LOG2 << 2) |
    3.37 -		        VHPT_ENABLED);
    3.38 +		ia64_disable_vhpt_walker();
    3.39  		load_region_regs(current);
    3.40 +        	ia64_set_pta(vcpu_pta(current));
    3.41  		vcpu_load_kernel_regs(current);
    3.42  		__ia64_per_cpu_var(current_psr_i_addr) = &current->domain->
    3.43  		  shared_info->vcpu_info[current->vcpu_id].evtchn_upcall_mask;
    3.44 @@ -127,7 +139,6 @@ void schedule_tail(struct vcpu *prev)
    3.45  void context_switch(struct vcpu *prev, struct vcpu *next)
    3.46  {
    3.47      uint64_t spsr;
    3.48 -    uint64_t pta;
    3.49  
    3.50      local_irq_save(spsr);
    3.51  
    3.52 @@ -164,9 +175,9 @@ void context_switch(struct vcpu *prev, s
    3.53  
    3.54  	nd = current->domain;
    3.55      	if (!is_idle_domain(nd)) {
    3.56 -        	ia64_set_pta(VHPT_ADDR | (1 << 8) | (VHPT_SIZE_LOG2 << 2) |
    3.57 -			     VHPT_ENABLED);
    3.58 +		ia64_disable_vhpt_walker();
    3.59  	    	load_region_regs(current);
    3.60 +		ia64_set_pta(vcpu_pta(current));
    3.61  	    	vcpu_load_kernel_regs(current);
    3.62  		vcpu_set_next_timer(current);
    3.63  		if (vcpu_timer_expired(current))
    3.64 @@ -180,8 +191,7 @@ void context_switch(struct vcpu *prev, s
    3.65  		 * walker. Then all accesses happen within idle context will
    3.66  		 * be handled by TR mapping and identity mapping.
    3.67  		 */
    3.68 -		pta = ia64_get_pta();
    3.69 -		ia64_set_pta(pta & ~VHPT_ENABLED);
    3.70 +		ia64_disable_vhpt_walker();
    3.71  		__ia64_per_cpu_var(current_psr_i_addr) = NULL;
    3.72  		__ia64_per_cpu_var(current_psr_ic_addr) = NULL;
    3.73          }
    3.74 @@ -270,6 +280,13 @@ struct vcpu *alloc_vcpu_struct(struct do
    3.75  	    if (!d->arch.is_vti) {
    3.76  		int order;
    3.77  		int i;
    3.78 +		// vti domain has its own vhpt policy.
    3.79 +		if (HAS_PERVCPU_VHPT(d)) {
    3.80 +			if (pervcpu_vhpt_alloc(v) < 0) {
    3.81 +				free_xenheap_pages(v, KERNEL_STACK_SIZE_ORDER);
    3.82 +				return NULL;
    3.83 +			}
    3.84 +		}
    3.85  
    3.86  		/* Create privregs page only if not VTi. */
    3.87  		order = get_order_from_shift(XMAPPEDREGS_SHIFT);
    3.88 @@ -312,6 +329,8 @@ struct vcpu *alloc_vcpu_struct(struct do
    3.89  
    3.90  void relinquish_vcpu_resources(struct vcpu *v)
    3.91  {
    3.92 +    if (HAS_PERVCPU_VHPT(v->domain))
    3.93 +        pervcpu_vhpt_free(v);
    3.94      if (v->arch.privregs != NULL) {
    3.95          free_xenheap_pages(v->arch.privregs,
    3.96                             get_order_from_shift(XMAPPEDREGS_SHIFT));
    3.97 @@ -347,6 +366,11 @@ static void init_switch_stack(struct vcp
    3.98  	memset(v->arch._thread.fph,0,sizeof(struct ia64_fpreg)*96);
    3.99  }
   3.100  
   3.101 +#ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
   3.102 +static int opt_pervcpu_vhpt = 1;
   3.103 +integer_param("pervcpu_vhpt", opt_pervcpu_vhpt);
   3.104 +#endif
   3.105 +
   3.106  int arch_domain_create(struct domain *d)
   3.107  {
   3.108  	int i;
   3.109 @@ -361,6 +385,11 @@ int arch_domain_create(struct domain *d)
   3.110  	if (is_idle_domain(d))
   3.111  	    return 0;
   3.112  
   3.113 +#ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
   3.114 +	d->arch.has_pervcpu_vhpt = opt_pervcpu_vhpt;
   3.115 +	DPRINTK("%s:%d domain %d pervcpu_vhpt %d\n",
   3.116 +	        __func__, __LINE__, d->domain_id, d->arch.has_pervcpu_vhpt);
   3.117 +#endif
   3.118  	d->shared_info = alloc_xenheap_pages(get_order_from_shift(XSI_SHIFT));
   3.119  	if (d->shared_info == NULL)
   3.120  	    goto fail_nomem;
     4.1 --- a/xen/arch/ia64/xen/regionreg.c	Sun Oct 08 18:35:17 2006 -0600
     4.2 +++ b/xen/arch/ia64/xen/regionreg.c	Sun Oct 08 18:55:12 2006 -0600
     4.3 @@ -260,7 +260,7 @@ int set_one_rr(unsigned long rr, unsigne
     4.4  	} else if (rreg == 7) {
     4.5  		ia64_new_rr7(vmMangleRID(newrrv.rrval),v->domain->shared_info,
     4.6  			     v->arch.privregs, v->domain->arch.shared_info_va,
     4.7 -			     __get_cpu_var(vhpt_paddr));
     4.8 +		             vcpu_vhpt_maddr(v));
     4.9  	} else {
    4.10  		set_rr(rr,newrrv.rrval);
    4.11  	}
     5.1 --- a/xen/arch/ia64/xen/vhpt.c	Sun Oct 08 18:35:17 2006 -0600
     5.2 +++ b/xen/arch/ia64/xen/vhpt.c	Sun Oct 08 18:55:12 2006 -0600
     5.3 @@ -3,6 +3,10 @@
     5.4   *
     5.5   * Copyright (C) 2004 Hewlett-Packard Co
     5.6   *	Dan Magenheimer <dan.magenheimer@hp.com>
     5.7 + *
     5.8 + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
     5.9 + *                    VA Linux Systems Japan K.K.
    5.10 + *                    per vcpu vhpt support
    5.11   */
    5.12  #include <linux/config.h>
    5.13  #include <linux/kernel.h>
    5.14 @@ -24,18 +28,32 @@ extern long running_on_sim;
    5.15  DEFINE_PER_CPU (unsigned long, vhpt_paddr);
    5.16  DEFINE_PER_CPU (unsigned long, vhpt_pend);
    5.17  
    5.18 -void vhpt_flush(void)
    5.19 +static void
    5.20 + __vhpt_flush(unsigned long vhpt_maddr)
    5.21  {
    5.22 -	struct vhpt_lf_entry *v = __va(__ia64_per_cpu_var(vhpt_paddr));
    5.23 +	struct vhpt_lf_entry *v = (struct vhpt_lf_entry*)__va(vhpt_maddr);
    5.24  	int i;
    5.25  
    5.26  	for (i = 0; i < VHPT_NUM_ENTRIES; i++, v++)
    5.27  		v->ti_tag = INVALID_TI_TAG;
    5.28  }
    5.29  
    5.30 -static void vhpt_erase(void)
    5.31 +void
    5.32 +local_vhpt_flush(void)
    5.33  {
    5.34 -	struct vhpt_lf_entry *v = (struct vhpt_lf_entry *)VHPT_ADDR;
    5.35 +	__vhpt_flush(__ia64_per_cpu_var(vhpt_paddr));
    5.36 +}
    5.37 +
    5.38 +static void
    5.39 +vcpu_vhpt_flush(struct vcpu* v)
    5.40 +{
    5.41 +	__vhpt_flush(vcpu_vhpt_maddr(v));
    5.42 +}
    5.43 +
    5.44 +static void
    5.45 +vhpt_erase(unsigned long vhpt_maddr)
    5.46 +{
    5.47 +	struct vhpt_lf_entry *v = (struct vhpt_lf_entry*)__va(vhpt_maddr);
    5.48  	int i;
    5.49  
    5.50  	for (i = 0; i < VHPT_NUM_ENTRIES; i++, v++) {
    5.51 @@ -47,17 +65,6 @@ static void vhpt_erase(void)
    5.52  	// initialize cache too???
    5.53  }
    5.54  
    5.55 -
    5.56 -static void vhpt_map(unsigned long pte)
    5.57 -{
    5.58 -	unsigned long psr;
    5.59 -
    5.60 -	psr = ia64_clear_ic();
    5.61 -	ia64_itr(0x2, IA64_TR_VHPT, VHPT_ADDR, pte, VHPT_SIZE_LOG2);
    5.62 -	ia64_set_psr(psr);
    5.63 -	ia64_srlz_i();
    5.64 -}
    5.65 -
    5.66  void vhpt_insert (unsigned long vadr, unsigned long pte, unsigned long logps)
    5.67  {
    5.68  	struct vhpt_lf_entry *vlfe = (struct vhpt_lf_entry *)ia64_thash(vadr);
    5.69 @@ -102,7 +109,7 @@ void vhpt_multiple_insert(unsigned long 
    5.70  
    5.71  void vhpt_init(void)
    5.72  {
    5.73 -	unsigned long paddr, pte;
    5.74 +	unsigned long paddr;
    5.75  	struct page_info *page;
    5.76  #if !VHPT_ENABLED
    5.77  	return;
    5.78 @@ -122,14 +129,51 @@ void vhpt_init(void)
    5.79  	__get_cpu_var(vhpt_pend) = paddr + (1 << VHPT_SIZE_LOG2) - 1;
    5.80  	printf("vhpt_init: vhpt paddr=0x%lx, end=0x%lx\n",
    5.81  		paddr, __get_cpu_var(vhpt_pend));
    5.82 -	pte = pte_val(pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL));
    5.83 -	vhpt_map(pte);
    5.84 -	ia64_set_pta(VHPT_ADDR | (1 << 8) | (VHPT_SIZE_LOG2 << 2) |
    5.85 -		VHPT_ENABLED);
    5.86 -	vhpt_erase();
    5.87 +	vhpt_erase(paddr);
    5.88 +	// we don't enable VHPT here.
    5.89 +	// context_switch() or schedule_tail() does it.
    5.90  }
    5.91  
    5.92 +#ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
    5.93 +int
    5.94 +pervcpu_vhpt_alloc(struct vcpu *v)
    5.95 +{
    5.96 +	unsigned long vhpt_size_log2 = VHPT_SIZE_LOG2;
    5.97  
    5.98 +	v->arch.vhpt_entries =
    5.99 +		(1UL << vhpt_size_log2) / sizeof(struct vhpt_lf_entry);
   5.100 +	v->arch.vhpt_page =
   5.101 +		alloc_domheap_pages(NULL, vhpt_size_log2 - PAGE_SHIFT, 0);
   5.102 +	if (!v->arch.vhpt_page)
   5.103 +		return -ENOMEM;
   5.104 +	
   5.105 +	v->arch.vhpt_maddr = page_to_maddr(v->arch.vhpt_page);
   5.106 +	if (v->arch.vhpt_maddr & ((1 << VHPT_SIZE_LOG2) - 1))
   5.107 +		panic("pervcpu_vhpt_init: bad VHPT alignment!\n");
   5.108 +
   5.109 +	v->arch.pta.val = 0; // to zero reserved bits
   5.110 +	v->arch.pta.ve = 1; // enable vhpt
   5.111 +	v->arch.pta.size = VHPT_SIZE_LOG2;
   5.112 +	v->arch.pta.vf = 1; // long format
   5.113 +	//v->arch.pta.base = __va(v->arch.vhpt_maddr) >> 15;
   5.114 +	v->arch.pta.base = VHPT_ADDR >> 15;
   5.115 +
   5.116 +	vhpt_erase(v->arch.vhpt_maddr);
   5.117 +	smp_mb(); // per vcpu vhpt may be used by another physical cpu.
   5.118 +	return 0;
   5.119 +}
   5.120 +
   5.121 +void
   5.122 +pervcpu_vhpt_free(struct vcpu *v)
   5.123 +{
   5.124 +	free_domheap_pages(v->arch.vhpt_page, VHPT_SIZE_LOG2 - PAGE_SHIFT);
   5.125 +}
   5.126 +#endif
   5.127 +
   5.128 +// SMP: we can't assume v == current, vcpu might move to another physical cpu.
   5.129 +// So memory barrier is necessary.
   5.130 +// if we can guranttee that vcpu can run on only this physical cpu
   5.131 +// (e.g. vcpu == current), smp_mb() is unnecessary.
   5.132  void vcpu_flush_vtlb_all(struct vcpu *v)
   5.133  {
   5.134  	if (VMX_DOMAIN(v)) {
   5.135 @@ -144,9 +188,14 @@ void vcpu_flush_vtlb_all(struct vcpu *v)
   5.136  		/* First VCPU tlb.  */
   5.137  		vcpu_purge_tr_entry(&PSCBX(v,dtlb));
   5.138  		vcpu_purge_tr_entry(&PSCBX(v,itlb));
   5.139 +		smp_mb();
   5.140  
   5.141  		/* Then VHPT.  */
   5.142 -		vhpt_flush();
   5.143 +		if (HAS_PERVCPU_VHPT(v->domain))
   5.144 +			vcpu_vhpt_flush(v);
   5.145 +		else
   5.146 +			local_vhpt_flush();
   5.147 +		smp_mb();
   5.148  
   5.149  		/* Then mTLB.  */
   5.150  		local_flush_tlb_all();
   5.151 @@ -176,6 +225,13 @@ void domain_flush_vtlb_all (void)
   5.152  		if (v->processor == cpu)
   5.153  			vcpu_flush_vtlb_all(v);
   5.154  		else
   5.155 +			// SMP: it is racy to reference v->processor.
   5.156 +			// vcpu scheduler may move this vcpu to another
   5.157 +			// physicall processor, and change the value
   5.158 +			// using plain store.
   5.159 +			// We may be seeing the old value of it.
   5.160 +			// In such case, flush_vtlb_for_context_switch()
   5.161 +			// takes care of mTLB flush.
   5.162  			smp_call_function_single(v->processor,
   5.163  						 __vcpu_flush_vtlb_all,
   5.164  						 v, 1, 1);
   5.165 @@ -183,24 +239,42 @@ void domain_flush_vtlb_all (void)
   5.166  	perfc_incrc(domain_flush_vtlb_all);
   5.167  }
   5.168  
   5.169 -static void cpu_flush_vhpt_range (int cpu, u64 vadr, u64 addr_range)
   5.170 +// Callers may need to call smp_mb() before/after calling this.
   5.171 +// Be carefull.
   5.172 +static void
   5.173 +__flush_vhpt_range(unsigned long vhpt_maddr, u64 vadr, u64 addr_range)
   5.174  {
   5.175 -	void *vhpt_base = __va(per_cpu(vhpt_paddr, cpu));
   5.176 +	void *vhpt_base = __va(vhpt_maddr);
   5.177  
   5.178  	while ((long)addr_range > 0) {
   5.179  		/* Get the VHPT entry.  */
   5.180  		unsigned int off = ia64_thash(vadr) - VHPT_ADDR;
   5.181 -		volatile struct vhpt_lf_entry *v;
   5.182 -		v = vhpt_base + off;
   5.183 +		struct vhpt_lf_entry *v = vhpt_base + off;
   5.184  		v->ti_tag = INVALID_TI_TAG;
   5.185  		addr_range -= PAGE_SIZE;
   5.186  		vadr += PAGE_SIZE;
   5.187  	}
   5.188  }
   5.189  
   5.190 +static void
   5.191 +cpu_flush_vhpt_range(int cpu, u64 vadr, u64 addr_range)
   5.192 +{
   5.193 +	__flush_vhpt_range(per_cpu(vhpt_paddr, cpu), vadr, addr_range);
   5.194 +}
   5.195 +
   5.196 +static void
   5.197 +vcpu_flush_vhpt_range(struct vcpu* v, u64 vadr, u64 addr_range)
   5.198 +{
   5.199 +	__flush_vhpt_range(vcpu_vhpt_maddr(v), vadr, addr_range);
   5.200 +}
   5.201 +
   5.202  void vcpu_flush_tlb_vhpt_range (u64 vadr, u64 log_range)
   5.203  {
   5.204 -	cpu_flush_vhpt_range (current->processor, vadr, 1UL << log_range);
   5.205 +	if (HAS_PERVCPU_VHPT(current->domain))
   5.206 +		vcpu_flush_vhpt_range(current, vadr, 1UL << log_range);
   5.207 +	else
   5.208 +		cpu_flush_vhpt_range(current->processor,
   5.209 +		                     vadr, 1UL << log_range);
   5.210  	ia64_ptcl(vadr, log_range << 2);
   5.211  	ia64_srlz_i();
   5.212  	perfc_incrc(vcpu_flush_tlb_vhpt_range);
   5.213 @@ -233,8 +307,18 @@ void domain_flush_vtlb_range (struct dom
   5.214  		if (!test_bit(_VCPUF_initialised, &v->vcpu_flags))
   5.215  			continue;
   5.216  
   5.217 -		/* Invalidate VHPT entries.  */
   5.218 -		cpu_flush_vhpt_range (v->processor, vadr, addr_range);
   5.219 +		if (HAS_PERVCPU_VHPT(d)) {
   5.220 +			vcpu_flush_vhpt_range(v, vadr, addr_range);
   5.221 +		} else {
   5.222 +			// SMP: it is racy to reference v->processor.
   5.223 +			// vcpu scheduler may move this vcpu to another
   5.224 +			// physicall processor, and change the value
   5.225 +			// using plain store.
   5.226 +			// We may be seeing the old value of it.
   5.227 +			// In such case, flush_vtlb_for_context_switch()
   5.228 +			/* Invalidate VHPT entries.  */
   5.229 +			cpu_flush_vhpt_range(v->processor, vadr, addr_range);
   5.230 +		}
   5.231  	}
   5.232  	// ptc.ga has release semantics.
   5.233  
   5.234 @@ -246,7 +330,7 @@ void domain_flush_vtlb_range (struct dom
   5.235  static void flush_tlb_vhpt_all (struct domain *d)
   5.236  {
   5.237  	/* First VHPT.  */
   5.238 -	vhpt_flush ();
   5.239 +	local_vhpt_flush ();
   5.240  
   5.241  	/* Then mTLB.  */
   5.242  	local_flush_tlb_all ();
   5.243 @@ -255,7 +339,10 @@ static void flush_tlb_vhpt_all (struct d
   5.244  void domain_flush_tlb_vhpt(struct domain *d)
   5.245  {
   5.246  	/* Very heavy...  */
   5.247 -	on_each_cpu ((void (*)(void *))flush_tlb_vhpt_all, d, 1, 1);
   5.248 +	if (HAS_PERVCPU_VHPT(d) /* || VMX_DOMAIN(v) */)
   5.249 +		on_each_cpu((void (*)(void *))local_flush_tlb_all, NULL, 1, 1);
   5.250 +	else
   5.251 +		on_each_cpu((void (*)(void *))flush_tlb_vhpt_all, d, 1, 1);
   5.252  	cpus_clear (d->domain_dirty_cpumask);
   5.253  }
   5.254  
     6.1 --- a/xen/include/asm-ia64/domain.h	Sun Oct 08 18:35:17 2006 -0600
     6.2 +++ b/xen/include/asm-ia64/domain.h	Sun Oct 08 18:55:12 2006 -0600
     6.3 @@ -87,6 +87,9 @@ struct arch_domain {
     6.4          unsigned long flags;
     6.5          struct {
     6.6              unsigned int is_vti : 1;
     6.7 +#ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
     6.8 +            unsigned int has_pervcpu_vhpt : 1;
     6.9 +#endif
    6.10          };
    6.11      };
    6.12  
    6.13 @@ -142,6 +145,13 @@ struct arch_domain {
    6.14      (sizeof(vcpu_info_t) * (v)->vcpu_id + \
    6.15      offsetof(vcpu_info_t, evtchn_upcall_mask))
    6.16  
    6.17 +#ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
    6.18 +#define HAS_PERVCPU_VHPT(d)     ((d)->arch.has_pervcpu_vhpt)
    6.19 +#else
    6.20 +#define HAS_PERVCPU_VHPT(d)     (0)
    6.21 +#endif
    6.22 +
    6.23 +
    6.24  struct arch_vcpu {
    6.25      /* Save the state of vcpu.
    6.26         This is the first entry to speed up accesses.  */
    6.27 @@ -193,6 +203,13 @@ struct arch_vcpu {
    6.28      struct timer hlt_timer;
    6.29      struct arch_vmx_struct arch_vmx; /* Virtual Machine Extensions */
    6.30  
    6.31 +#ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
    6.32 +    PTA                 pta;
    6.33 +    unsigned long       vhpt_maddr;
    6.34 +    struct page_info*   vhpt_page;
    6.35 +    unsigned long       vhpt_entries;
    6.36 +#endif
    6.37 +
    6.38  #define INVALID_PROCESSOR       INT_MAX
    6.39      int last_processor;
    6.40  };
     7.1 --- a/xen/include/asm-ia64/vhpt.h	Sun Oct 08 18:35:17 2006 -0600
     7.2 +++ b/xen/include/asm-ia64/vhpt.h	Sun Oct 08 18:55:12 2006 -0600
     7.3 @@ -37,11 +37,46 @@ extern void vhpt_multiple_insert(unsigne
     7.4  				 unsigned long logps);
     7.5  extern void vhpt_insert (unsigned long vadr, unsigned long pte,
     7.6  			 unsigned long logps);
     7.7 -void vhpt_flush(void);
     7.8 +void local_vhpt_flush(void);
     7.9  
    7.10  /* Currently the VHPT is allocated per CPU.  */
    7.11  DECLARE_PER_CPU (unsigned long, vhpt_paddr);
    7.12  DECLARE_PER_CPU (unsigned long, vhpt_pend);
    7.13  
    7.14 +#ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
    7.15 +#if !VHPT_ENABLED
    7.16 +#error "VHPT_ENABLED must be set for CONFIG_XEN_IA64_PERVCPU_VHPT"
    7.17 +#endif
    7.18 +#endif
    7.19 +
    7.20 +#include <xen/sched.h>
    7.21 +int pervcpu_vhpt_alloc(struct vcpu *v);
    7.22 +void pervcpu_vhpt_free(struct vcpu *v);
    7.23 +static inline unsigned long
    7.24 +vcpu_vhpt_maddr(struct vcpu* v)
    7.25 +{
    7.26 +#ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
    7.27 +    if (HAS_PERVCPU_VHPT(v->domain))
    7.28 +        return v->arch.vhpt_maddr;
    7.29 +#endif
    7.30 +
    7.31 +#if 0
    7.32 +    // referencecing v->processor is racy.
    7.33 +    return per_cpu(vhpt_paddr, v->processor);
    7.34 +#endif
    7.35 +    BUG_ON(v != current);
    7.36 +    return __get_cpu_var(vhpt_paddr);
    7.37 +}
    7.38 +
    7.39 +static inline unsigned long
    7.40 +vcpu_pta(struct vcpu* v)
    7.41 +{
    7.42 +#ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
    7.43 +    if (HAS_PERVCPU_VHPT(v->domain))
    7.44 +        return v->arch.pta.val;
    7.45 +#endif
    7.46 +    return VHPT_ADDR | (1 << 8) | (VHPT_SIZE_LOG2 << 2) | VHPT_ENABLED;
    7.47 +}
    7.48 +
    7.49  #endif /* !__ASSEMBLY */
    7.50  #endif
     8.1 --- a/xen/include/asm-ia64/xenkregs.h	Sun Oct 08 18:35:17 2006 -0600
     8.2 +++ b/xen/include/asm-ia64/xenkregs.h	Sun Oct 08 18:55:12 2006 -0600
     8.3 @@ -7,8 +7,7 @@
     8.4  #define IA64_TR_SHARED_INFO	3	/* dtr3: page shared with domain */
     8.5  #define	IA64_TR_VHPT		4	/* dtr4: vhpt */
     8.6  #define IA64_TR_MAPPED_REGS	5	/* dtr5: vcpu mapped regs */
     8.7 -#define IA64_TR_PERVP_VHPT	6
     8.8 -#define IA64_DTR_GUEST_KERNEL   7
     8.9 +#define IA64_DTR_GUEST_KERNEL   6
    8.10  #define IA64_ITR_GUEST_KERNEL   2
    8.11  /* Processor status register bits: */
    8.12  #define IA64_PSR_VM_BIT		46