[IA64] kexec: Unpin the correct VHPT TR in ia64_do_tlb_purge
authorIsaku Yamahata <yamahata@valinux.co.jp>
Tue, 22 Jul 2008 03:15:02 +0000 (12:15 +0900)
committerIsaku Yamahata <yamahata@valinux.co.jp>
Tue, 22 Jul 2008 03:15:02 +0000 (12:15 +0900)
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>
xen/arch/ia64/linux-xen/mca_asm.S
xen/arch/ia64/vmx/vmx_vcpu.c
xen/arch/ia64/xen/regionreg.c
xen/include/asm-ia64/regionreg.h

index 44bb6edd774fb1431252eba2af657ce7bcdb1143..f5ce6a136951319f2cd603a1a85f2f829ff71b5d 100644 (file)
@@ -321,8 +321,13 @@ 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);;
+       ;;
+       cmp.eq p7,p0=r2,r0
+       ;;
+(p7)   br.cond.sptk .vhpt_not_mapped
        dep r16=0,r2,0,IA64_GRANULE_SHIFT
        mov r18=IA64_GRANULE_SHIFT<<2
        ;;
@@ -330,7 +335,7 @@ ia64_do_tlb_purge:
        ;;
        srlz.d
        ;;
-#endif
+.vhpt_not_mapped:
 #endif
        // Now branch away to caller.
        br.sptk.many b1
index 93e31fe62132a381a0c1f32f5bf34af3a003294d..0b44bf936fd16ad366a5db66c761d3fcc9ac179b 100644 (file)
@@ -199,6 +199,7 @@ void vmx_vcpu_set_rr_fast(VCPU *vcpu, u64 reg, u64 val)
 void vmx_switch_rr7(unsigned long rid, void *guest_vhpt,
                     void *pal_vaddr, void *shared_arch_info)
 {
+    __get_cpu_var(inserted_vhpt) = (unsigned long)guest_vhpt;
     __vmx_switch_rr7(rid, guest_vhpt, pal_vaddr, shared_arch_info);
 }
 
index aa3d9b94e83b1b31c9a3dc8509f2ef98e70c5e61..d7442d640390bd8b27c62a2f15cd8a7789288cac 100644 (file)
@@ -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);
@@ -47,6 +48,8 @@ extern void ia64_new_rr7(unsigned long rid, void *shared_info, void *shared_arch
 static unsigned int domain_rid_bits_default = IA64_MIN_IMPL_RID_BITS;
 integer_param("dom_rid_bits", domain_rid_bits_default); 
 
+DEFINE_PER_CPU(unsigned long, inserted_vhpt);
+
 #if 0
 // following already defined in include/asm-ia64/gcc_intrin.h
 // it should probably be ifdef'd out from there to ensure all region
@@ -260,6 +263,9 @@ int set_one_rr(unsigned long rr, unsigned long val)
                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)));
index 0eea1b1342e2bea49a1492bf6bc7df5961ff1b2e..1d728235cd577de16be6572c187648657aa69856 100644 (file)
@@ -36,6 +36,7 @@ typedef union ia64_rr {
 #define RR_RID(arg)     (((arg) & 0x0000000000ffffff) << 8)
 #define RR_RID_MASK     0x00000000ffffff00L
 
+DECLARE_PER_CPU(unsigned long, inserted_vhpt);
 
 int set_one_rr(unsigned long rr, unsigned long val);