[IA64] Kexec: Unpin the correct VHPT TR in ia64_do_tlb_purge

When ia64_do_tlb_purge is called indrectly from play_dead()
GET_VA_VCPU_VHPT_MADDR(r2,r3) does not give the value of the VHPT
pinned into the TLB. I believe that this is because
current is changed between pinning and calling play_dead,
though I am not sure of the exact scemantics.

In any case, by recording the pinned value in a percpu variable,
and unpinning this value, the TR entry is removed and all is well.

Cc: Isaku Yamahata <yamahata@valinux.co.jp>
Signed-off-by: Simon Horman <horms@verge.net.au>

Index: xen-unstable.hg/xen/arch/ia64/linux-xen/mca_asm.S
===================================================================
--- xen-unstable.hg.orig/xen/arch/ia64/linux-xen/mca_asm.S	2008-02-05 16:18:42.000000000 +0900
+++ xen-unstable.hg/xen/arch/ia64/linux-xen/mca_asm.S	2008-02-05 16:18:50.000000000 +0900
@@ -322,7 +322,9 @@ ia64_do_tlb_purge:
 #ifdef XEN
 	// 5. VHPT
 #if VHPT_ENABLED
-	GET_VA_VCPU_VHPT_MADDR(r2,r3);;
+	// GET_VA_VCPU_VHPT_MADDR() may not give the
+	// value of the VHPT currently pinned into the TLB
+	GET_THIS_PADDR(r2, inserted_vhpt);;
 	dep r16=0,r2,0,IA64_GRANULE_SHIFT
 	mov r18=IA64_GRANULE_SHIFT<<2
 	;;
Index: xen-unstable.hg/xen/arch/ia64/xen/regionreg.c
===================================================================
--- xen-unstable.hg.orig/xen/arch/ia64/xen/regionreg.c	2008-02-05 16:18:42.000000000 +0900
+++ xen-unstable.hg/xen/arch/ia64/xen/regionreg.c	2008-02-05 16:18:50.000000000 +0900
@@ -15,6 +15,7 @@
 #include <asm/regionreg.h>
 #include <asm/vhpt.h>
 #include <asm/vcpu.h>
+#include <asm/percpu.h>
 
 /* 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);
@@ -227,6 +228,10 @@ set_rr(unsigned long rr, unsigned long r
 	ia64_srlz_d();
 }
 
+#if VHPT_ENABLED
+DEFINE_PER_CPU(unsigned long, inserted_vhpt);
+#endif
+
 // validates and changes a single region register
 // in the currently executing domain
 // Passing a value of -1 is a (successful) no-op
@@ -260,6 +265,9 @@ int set_one_rr(unsigned long rr, unsigne
 		if (!PSCB(v,metaphysical_mode))
 			set_rr(rr,newrrv.rrval);
 	} else if (rreg == 7) {
+#if VHPT_ENABLED
+		__get_cpu_var(inserted_vhpt) = __va_ul(vcpu_vhpt_maddr(v));
+#endif
 		ia64_new_rr7(vmMangleRID(newrrv.rrval),v->domain->shared_info,
 			     v->arch.privregs, v->domain->arch.shared_info_va,
 		             __va_ul(vcpu_vhpt_maddr(v)));
