From: "Aneesh Kumar K.V" <aneesh.ku...@linux.vnet.ibm.com>

We need to make sure that we don't have higher bits of kernel effective
address set. That would result in multiple kernel segments having same
proto vsid. Add debug code to make sure we capture this.

Signed-off-by: Aneesh Kumar K.V <aneesh.ku...@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/mmu-hash64.h |   49 +++++++++++++++++++++++++++++----
 1 file changed, 43 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/include/asm/mmu-hash64.h 
b/arch/powerpc/include/asm/mmu-hash64.h
index 0e08252..3e297ea 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -22,6 +22,13 @@
  */
 #include <asm/pgtable-ppc64.h>
 
+#ifdef CONFIG_DEBUG_VM
+#ifndef __ASSEMBLY__
+#include <asm/udbg.h>
+#include <asm/bug.h>
+#endif
+#endif
+
 /*
  * Segment table
  */
@@ -522,11 +529,32 @@ static inline int user_segment_size(unsigned long addr)
 static inline unsigned long get_vsid(unsigned long context, unsigned long ea,
                                     int ssize)
 {
-       if (ssize == MMU_SEGSIZE_256M)
-               return vsid_scramble((context << USER_ESID_BITS)
-                                    | (ea >> SID_SHIFT), 256M);
-       return vsid_scramble((context << USER_ESID_BITS_1T)
-                            | (ea >> SID_SHIFT_1T), 1T);
+       if (ssize == MMU_SEGSIZE_256M) {
+               context = context << USER_ESID_BITS;
+               ea = ea >> SID_SHIFT;
+#ifdef CONFIG_DEBUG_VM
+               /*
+                * context and ea should not overlap.
+                */
+               if (context & ea) {
+                       udbg_printf("Overlapping bits %lx %lx\n", context, ea);
+                       WARN_ON(1);
+               }
+#endif
+               return vsid_scramble(context | ea, 256M);
+       }
+       context = context << USER_ESID_BITS_1T;
+       ea = ea >> SID_SHIFT_1T;
+#ifdef CONFIG_DEBUG_VM
+       /*
+        * context and ea should not overlap.
+        */
+       if (context & ea) {
+               udbg_printf("Overlapping bits for 1T %lx %lx\n", context, ea);
+               WARN_ON(1);
+       }
+#endif
+       return vsid_scramble(context | ea, 1T);
 }
 
 /*
@@ -540,11 +568,20 @@ static inline unsigned long get_vsid(unsigned long 
context, unsigned long ea,
  */
 static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize)
 {
+       unsigned int c_index;
        unsigned long context;
        /*
         * kernel take the top 4 context from the available range
         */
-       context = (MAX_CONTEXT - 4) +  ((ea >> 60) - 0xc);
+       c_index =   ((ea >> 60) - 0xc);
+       context = (MAX_CONTEXT - 4) + c_index;
+#ifdef CONFIG_DEBUG_VM
+       /*
+        * Drop the c_index related bits from ea, so we get
+        * non overlapping context and ea.
+        */
+       ea = ea - ((0xcUL + c_index) << 60);
+#endif
        return get_vsid(context, ea, ssize);
 }
 #endif /* __ASSEMBLY__ */
-- 
1.7.10

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to