Index: xen-unstable.hg/xen/arch/ia64/xen/regionreg.c
===================================================================
--- xen-unstable.hg.orig/xen/arch/ia64/xen/regionreg.c	2008-01-21 19:39:54.000000000 +0900
+++ xen-unstable.hg/xen/arch/ia64/xen/regionreg.c	2008-01-21 19:42:44.000000000 +0900
@@ -11,6 +11,7 @@
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/sched.h>
+#include <linux/efi.h>
 #include <asm/page.h>
 #include <asm/regionreg.h>
 #include <asm/vhpt.h>
@@ -19,7 +20,12 @@
 
 /* Defined in xemasm.S  */
 extern void ia64_new_rr7(unsigned long rid, void *shared_info, void *shared_arch_info, unsigned long shared_info_va, unsigned long va_vhpt);
-extern void ia64_new_rr7_efi(unsigned long rid);
+extern void ia64_new_rr7_efi(unsigned long rid,
+			      unsigned long percpu_pte,
+			      unsigned long palcode_pte,
+			      unsigned long vhpt_vaddr,
+			      unsigned long shared_info_vaddr,
+			      unsigned long mapped_regs_vaddr);
 
 /* RID virtualization mechanism is really simple:  domains have less rid bits
    than the host and the host rid space is shared among the domains.  (Values
@@ -280,15 +286,79 @@ int set_one_rr(unsigned long rr, unsigne
 	return 1;
 }
 
+extern void ia64_disable_vhpt_walker(void);
+
 int set_one_rr_efi(unsigned long rr, unsigned long val)
 {
 	unsigned long rreg = REGION_NUMBER(rr);
+	unsigned long percpu = 0UL;
+	unsigned long palcode = 0UL;
+	unsigned long vhpt = 0UL;
+#if VHPT_ENABLED
+	unsigned long pta = 0UL;
+#endif
+	unsigned long shared_info = 0UL;
+	unsigned long mapped_regs = 0UL;
+	int cpu;
 
-	BUG_ON(rreg != 6 && rreg != 7);
-	if (rreg == 6)
+	if (rreg == 6) {
 		set_rr(rr, val);
-	else
-		ia64_new_rr7_efi(val);
+		return 1;
+	}
+	BUG_ON(rreg != 7);
+
+	cpu = smp_processor_id();
+
+	/* This can't be done using per_cpu(ia64_mca_per_cpu_pte, cpu)
+	 * as it is set up too late
+	 */
+	if (ia64_tr_isset(IA64_TR_PERCPU_DATA, 1, cpu))
+		percpu = pte_val(pfn_pte(ia64_tpa(PERCPU_ADDR) >>
+					 PAGE_SHIFT, PAGE_KERNEL));
+
+	/* This can't be done using per_cpu(ia66_mca_pal_pte, cpu)
+	 * as it is set up too late.
+	 * It could also be calculated using:
+	 *   paddr = __pa(pal_vaddr)
+	 *   pte = pte_val(pfn_pte(paddr) >> PAGE_SHIFT, PAGE_KERNEL))
+	 */
+	// XXX: ia64_tr_isset(IA64_TR_PALCODE, 0, cpu) is always true
+	if (ia64_tr_isset(IA64_TR_PALCODE, 0, cpu))
+		palcode = pte_val(pfn_pte(ia64_tpa(pal_vaddr) >>
+					  PAGE_SHIFT, PAGE_KERNEL));
+
+	/* - on non-vmx shared_info and mapped_regs are pinned
+	 *   at the same time as vhpt in ia64_new_rr7() via set_one_rr()
+	 * - in vmx shared_info and mapped_regs are never pinned.
+	 *   vhpt is pinned in vmx_switch_rr7() via vmx_load_all_rr()
+	 *   or vmx_vcpu_set_rr() (I'm not sure which happens first.
+	 */
+	//if (ia64_tr_isset(IA64_TR_VHPT, 1, cpu)) { // Not needes as
+	// we can use ia64_saved_vhpt[]
+	// XXX: Fix up for VMX
+#if VHPT_ENABLED
+	if (ia64_saved_vhpt[cpu]) {
+		vhpt = ia64_saved_vhpt[cpu];
+		BUG_ON(!vhpt);
+		vhpt = __va_ul(vhpt);
+		pta = ia64_get_pta();
+		ia64_disable_vhpt_walker();
+	}
+#endif
+
+	// N.B: Always zero for VMX, so no need to check VMX_DOMAIN(current)
+	if (ia64_saved_shared_info[cpu]) {
+		shared_info = ia64_saved_shared_info[cpu];
+		mapped_regs = shared_info + XMAPPEDREGS_OFS;
+	}
+
+	//XXX: palcode is only tested for non-zeroness in ia64_new_rr7_efi()
+	ia64_new_rr7_efi(val, percpu, palcode, vhpt, shared_info, mapped_regs);
+
+#if VHPT_ENABLED
+	if (pta)
+		ia64_set_pta(pta);
+#endif
 
 	return 1;
 }
Index: xen-unstable.hg/xen/arch/ia64/xen/xenasm.S
===================================================================
--- xen-unstable.hg.orig/xen/arch/ia64/xen/xenasm.S	2008-01-21 19:39:54.000000000 +0900
+++ xen-unstable.hg/xen/arch/ia64/xen/xenasm.S	2008-01-21 20:04:56.000000000 +0900
@@ -203,22 +203,16 @@ GLOBAL_ENTRY(ia64_new_rr7)
 END(ia64_new_rr7)
 
 
-/* ia64_new_rr7_efi
- * in0 = rid
- *
- * There seems to be no need to repin: percpu, palcode, mapped_regs
- * or vhpt. If they do need to be repinned then special care
- * needs to betaken to track the correct value to repin.
- * That is generally the values that were most recently pinned by
- * ia64_new_rr7.
- *
- * This code function could probably be merged with ia64_new_rr7
- * as it is just a trimmed down version.
- */
+// in0 = rid
+// in1 = percpu_pte
+// in2 = palcode_pte
+// in3 = vhpt_vaddr
+// in4 = shared_info_vaddr
+// in5 = mapped_regs_vaddr
 GLOBAL_ENTRY(ia64_new_rr7_efi)
 	// FIXME? not sure this unwind statement is correct...
 	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(1)
-	alloc loc1 = ar.pfs, 1, 6, 0, 0
+	alloc loc1 = ar.pfs, 6, 10, 0, 0
 	movl loc2=PERCPU_ADDR
 1:	{
 	  mov loc3 = psr		// save psr
@@ -227,8 +221,13 @@ GLOBAL_ENTRY(ia64_new_rr7_efi)
 	};;
 	.body
 	tpa loc2=loc2			// grab this BEFORE changing rr7
+	cmp.ne p8,p0=r0,in4
+	cmp.ne p9,p0=r0,in5
+(p8)	tpa loc8=in4			// grab shared_info BEFORE changing rr7
+(p9)	tpa loc9=in5			// grab mapped_regs BEFORE changing rr7
 	adds r8 = 1f-1b,r8		// calculate return address for call
 	;;
+//	tpa loc7=in2			// grab arch_vcpu_info BEFORE chg rr7
 	movl r17=PSR_BITS_TO_SET
 	mov loc4=ar.rsc			// save RSE configuration
 	movl r16=PSR_BITS_TO_CLEAR
@@ -238,7 +237,7 @@ GLOBAL_ENTRY(ia64_new_rr7_efi)
 	or loc3=loc3,r17		// add in psr the bits to set
 	;;
 	andcm r16=loc3,r16		// removes bits to clear from psr
-	dep loc5=0,r8,0,KERNEL_TR_PAGE_SHIFT // Xen code paddr
+	dep loc6=0,r8,0,KERNEL_TR_PAGE_SHIFT // Xen code paddr
 	br.call.sptk.many rp=ia64_switch_mode_phys
 1:
 	// now in physical mode with psr.i/ic off so do rr7 switch
@@ -249,6 +248,11 @@ GLOBAL_ENTRY(ia64_new_rr7_efi)
 	srlz.d
 	;;
 
+	movl r16=pal_vaddr
+	;;
+	dep     r16=0,r16,60,4
+	;;
+	ld8 loc5=[r16]
 	movl	r26=PAGE_KERNEL
 	;;
 
@@ -267,7 +271,7 @@ GLOBAL_ENTRY(ia64_new_rr7_efi)
 	mov r16=IA64_TR_KERNEL
 	mov cr.itir=r24
 	mov cr.ifa=r17
-	or r18=loc5,r26
+	or r18=loc6,r26
 	;;
 	itr.i itr[r16]=r18
 	;;
@@ -284,7 +288,7 @@ GLOBAL_ENTRY(ia64_new_rr7_efi)
 	dep r18=0,r13,0,KERNEL_TR_PAGE_SHIFT
 	;;
 	cmp.eq p7,p0=r17,r18
-(p7)	br.cond.sptk	ia64_new_rr7_efi
+(p7)	br.cond.sptk ia64_new_rr7_efi_stack_overlaps
 	mov r25=IA64_GRANULE_SHIFT<<2
 	dep r21=0,r13,60,4		// physical address of "current"
 	;;
@@ -303,6 +307,126 @@ GLOBAL_ENTRY(ia64_new_rr7_efi)
 	;;
 ia64_new_rr7_efi_stack_overlaps:
 
+	//  Per-cpu
+	cmp.eq p7,p0=r0,in1
+(p7)	br.cond.sptk ia64_new_rr7_efi_percpu_not_mapped
+	mov r24=PERCPU_PAGE_SHIFT<<2
+	movl r22=PERCPU_ADDR
+	;;
+	ptr.d	r22,r24
+	;;
+	srlz.d
+	;;
+	mov cr.itir=r24
+	mov cr.ifa=r22
+	mov r25=IA64_TR_PERCPU_DATA
+	;;
+	itr.d dtr[r25]=in1		// wire in new mapping...
+	;;
+	srlz.d
+	;;
+ia64_new_rr7_efi_percpu_not_mapped:
+
+	// [ lots of stuff not re-pinned ]
+	// Have: r17=KERNEL_START
+	//       r13=current (predicate)
+	//       r26=PAGE_KERNEL
+	//	loc3=mangled psr
+	//	loc2=tpa PERCPU_ADDR
+	// [ Re-Pin Shared info - cut, needs in1 & in3 ]
+	// [ Re-Pin mapped_regs - cut, needs in3 & loc5 ]
+
+	// Purge/insert PAL TR
+	// N.B: This may not be neccessary, but it seems harmless
+	cmp.eq p7,p0=r0,in2
+(p7)	br.cond.sptk ia64_new_rr7_efi_palcode_not_mapped
+	;;
+	mov r24=IA64_TR_PALCODE
+	mov r23=IA64_GRANULE_SHIFT<<2
+	dep r25=0,loc5,60,4			// convert pal vaddr to paddr
+	;;
+	ptr.i	loc5,r23
+	;;
+	srlz.i
+	;;
+	or r25=r25,r26			// construct PA | page properties
+	mov cr.itir=r23
+	mov cr.ifa=loc5
+	;;
+	itr.i itr[r24]=r25
+	;;
+	srlz.i
+	;;
+ia64_new_rr7_efi_palcode_not_mapped:
+
+	//  Shared info
+	cmp.eq p7,p0=r0,in4
+(p7)	br.cond.sptk ia64_new_rr7_efi_shared_info_not_mapped
+	mov r24=XSI_SHIFT<<2
+	movl r25=__pgprot(__DIRTY_BITS | _PAGE_PL_PRIV | _PAGE_AR_RW)
+	;;
+	ptr.d in4,r24
+	;;
+	srlz.d
+	;;
+	or r23=loc8,r25			// construct PA | page properties
+	mov cr.itir=r24
+	mov cr.ifa=in4
+	mov r21=IA64_TR_SHARED_INFO
+	;;
+	itr.d dtr[r21]=r23		// wire in new mapping...
+	;;
+	srlz.d
+	;;
+
+	// Map mapped_regs
+	mov r22=XMAPPEDREGS_OFS
+	mov r24=XMAPPEDREGS_SHIFT<<2
+	;;
+	ptr.d	in5,r24
+	;;
+	srlz.d
+	;;
+	or r23=loc9,r25			// construct PA | page properties
+	mov cr.itir=r24
+	mov cr.ifa=in5
+	mov r21=IA64_TR_MAPPED_REGS
+	;;
+	itr.d dtr[r21]=r23		// wire in new mapping...
+	;;
+	srlz.d
+	;;
+ia64_new_rr7_efi_shared_info_not_mapped:
+
+#if VHPT_ENABLED
+	// 5. VHPT
+	cmp.eq p7,p0=r0,in3
+(p7)    br.cond.sptk ia64_new_rr7_efi_vhpt_not_mapped
+	;;
+	//GET_VA_VCPU_VHPT_MADDR(r2,r3);;
+	dep r16=0,in3,0,IA64_GRANULE_SHIFT
+	movl r26=PAGE_KERNEL		// XXX: r26 is already set
+	;;
+	mov r18=IA64_TR_VHPT
+	dep r17=0,r16,60,4		// physical address of
+	                                // va_vhpt & ~(IA64_GRANULE_SIZE - 1)
+
+	mov r23=IA64_GRANULE_SHIFT<<2	// XXX: r23 is already set
+	;;
+	ptr.d	r16,r23
+	;;
+	srlz.d
+	;;
+	or r17=r17,r26			// construct PA | page properties
+	mov cr.itir=r23
+	mov cr.ifa=r16
+	;;
+	itr.d dtr[r18]=r17		// wire in new mapping...
+	;;
+	srlz.d
+	;;
+ia64_new_rr7_efi_vhpt_not_mapped:
+#endif
 
 	// done, switch back to virtual and return
 	mov r16=loc3			// r16= original psr
Index: xen-unstable.hg/xen/arch/ia64/xen/domain.c
===================================================================
--- xen-unstable.hg.orig/xen/arch/ia64/xen/domain.c	2008-01-21 19:42:22.000000000 +0900
+++ xen-unstable.hg/xen/arch/ia64/xen/domain.c	2008-01-21 19:42:30.000000000 +0900
@@ -78,7 +78,7 @@ DEFINE_PER_CPU(struct vcpu *, fp_owner);
 
 #include <xen/sched-if.h>
 
-static void
+void
 ia64_disable_vhpt_walker(void)
 {
 	// disable VHPT. ia64_new_rr7() might cause VHPT
