Merge tag 'powerpc-4.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[cascardo/linux.git] / arch / powerpc / mm / pgtable-radix.c
index af897d9..ed7bddc 100644 (file)
@@ -294,6 +294,32 @@ found:
        return;
 }
 
+static void update_hid_for_radix(void)
+{
+       unsigned long hid0;
+       unsigned long rb = 3UL << PPC_BITLSHIFT(53); /* IS = 3 */
+
+       asm volatile("ptesync": : :"memory");
+       /* prs = 0, ric = 2, rs = 0, r = 1 is = 3 */
+       asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1)
+                    : : "r"(rb), "i"(1), "i"(0), "i"(2), "r"(0) : "memory");
+       /* prs = 1, ric = 2, rs = 0, r = 1 is = 3 */
+       asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1)
+                    : : "r"(rb), "i"(1), "i"(1), "i"(2), "r"(0) : "memory");
+       asm volatile("eieio; tlbsync; ptesync; isync; slbia": : :"memory");
+       /*
+        * now switch the HID
+        */
+       hid0  = mfspr(SPRN_HID0);
+       hid0 |= HID0_POWER9_RADIX;
+       mtspr(SPRN_HID0, hid0);
+       asm volatile("isync": : :"memory");
+
+       /* Wait for it to happen */
+       while (!(mfspr(SPRN_HID0) & HID0_POWER9_RADIX))
+               cpu_relax();
+}
+
 void __init radix__early_init_mmu(void)
 {
        unsigned long lpcr;
@@ -345,6 +371,8 @@ void __init radix__early_init_mmu(void)
 
        if (!firmware_has_feature(FW_FEATURE_LPAR)) {
                radix_init_native();
+               if (cpu_has_feature(CPU_FTR_POWER9_DD1))
+                       update_hid_for_radix();
                lpcr = mfspr(SPRN_LPCR);
                mtspr(SPRN_LPCR, lpcr | LPCR_UPRT | LPCR_HR);
                radix_init_partition_table();
@@ -368,6 +396,18 @@ void radix__early_init_mmu_secondary(void)
        }
 }
 
+void radix__mmu_cleanup_all(void)
+{
+       unsigned long lpcr;
+
+       if (!firmware_has_feature(FW_FEATURE_LPAR)) {
+               lpcr = mfspr(SPRN_LPCR);
+               mtspr(SPRN_LPCR, lpcr & ~LPCR_UPRT);
+               mtspr(SPRN_PTCR, 0);
+               radix__flush_tlb_all();
+       }
+}
+
 void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,
                                phys_addr_t first_memblock_size)
 {