powerpc/mm/radix: Add mmu context handling callback for radix
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Fri, 29 Apr 2016 13:26:02 +0000 (23:26 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Sun, 1 May 2016 08:33:05 +0000 (18:33 +1000)
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/include/asm/mmu_context.h
arch/powerpc/mm/mmu_context_hash64.c

index 4e2a294..9d2cd0c 100644 (file)
@@ -37,10 +37,14 @@ extern void switch_slb(struct task_struct *tsk, struct mm_struct *mm);
 extern void set_context(unsigned long id, pgd_t *pgd);
 
 #ifdef CONFIG_PPC_BOOK3S_64
+extern void radix__switch_mmu_context(struct mm_struct *prev,
+                                    struct mm_struct *next);
 static inline void switch_mmu_context(struct mm_struct *prev,
                                      struct mm_struct *next,
                                      struct task_struct *tsk)
 {
+       if (radix_enabled())
+               return radix__switch_mmu_context(prev, next);
        return switch_slb(tsk, next);
 }
 
index 9ca6fe1..b5288b4 100644 (file)
@@ -58,6 +58,17 @@ again:
        return index;
 }
 EXPORT_SYMBOL_GPL(__init_new_context);
+static int radix__init_new_context(struct mm_struct *mm, int index)
+{
+       unsigned long rts_field;
+
+       /*
+        * set the process table entry,
+        */
+       rts_field = 3ull << PPC_BITLSHIFT(2);
+       process_tb[index].prtb0 = cpu_to_be64(rts_field | __pa(mm->pgd) | RADIX_PGD_INDEX_SIZE);
+       return 0;
+}
 
 int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
@@ -67,13 +78,18 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
        if (index < 0)
                return index;
 
-       /* The old code would re-promote on fork, we don't do that
-        * when using slices as it could cause problem promoting slices
-        * that have been forced down to 4K
-        */
-       if (slice_mm_new_context(mm))
-               slice_set_user_psize(mm, mmu_virtual_psize);
-       subpage_prot_init_new_context(mm);
+       if (radix_enabled()) {
+               radix__init_new_context(mm, index);
+       } else {
+
+               /* The old code would re-promote on fork, we don't do that
+                * when using slices as it could cause problem promoting slices
+                * that have been forced down to 4K
+                */
+               if (slice_mm_new_context(mm))
+                       slice_set_user_psize(mm, mmu_virtual_psize);
+               subpage_prot_init_new_context(mm);
+       }
        mm->context.id = index;
 #ifdef CONFIG_PPC_ICSWX
        mm->context.cop_lockp = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
@@ -144,8 +160,19 @@ void destroy_context(struct mm_struct *mm)
        mm->context.cop_lockp = NULL;
 #endif /* CONFIG_PPC_ICSWX */
 
+       if (radix_enabled())
+               process_tb[mm->context.id].prtb1 = 0;
+       else
+               subpage_prot_free(mm);
        destroy_pagetable_page(mm);
        __destroy_context(mm->context.id);
-       subpage_prot_free(mm);
        mm->context.id = MMU_NO_CONTEXT;
 }
+
+#ifdef CONFIG_PPC_RADIX_MMU
+void radix__switch_mmu_context(struct mm_struct *prev, struct mm_struct *next)
+{
+       mtspr(SPRN_PID, next->context.id);
+       asm volatile("isync": : :"memory");
+}
+#endif