powerpc/powernv: Initialise nest mmu
authorAlistair Popple <alistair@popple.id.au>
Wed, 14 Dec 2016 02:36:51 +0000 (13:36 +1100)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 30 Jan 2017 09:24:33 +0000 (20:24 +1100)
POWER9 contains an off core mmu called the nest mmu (NMMU). This is
used by other hardware units on the chip to translate virtual
addresses into real addresses. The unit attempting an address
translation provides the majority of the context required for the
translation request except for the base address of the partition table
(ie. the PTCR) which needs to be programmed into the NMMU.

This patch adds a call to OPAL to set the PTCR for the nest mmu in
opal_init().

Signed-off-by: Alistair Popple <alistair@popple.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/include/asm/opal-api.h
arch/powerpc/include/asm/opal.h
arch/powerpc/include/asm/powernv.h [new file with mode: 0644]
arch/powerpc/mm/pgtable-radix.c
arch/powerpc/mm/pgtable_64.c
arch/powerpc/platforms/powernv/opal-wrappers.S
arch/powerpc/platforms/powernv/opal.c

index 0e2e57bcab5089467b7e2c8a834b4b88c5d42cea..a0aa285869b58503dcfa99e2e0d72040b723f1f3 100644 (file)
 #define OPAL_INT_EOI                           124
 #define OPAL_INT_SET_MFRR                      125
 #define OPAL_PCI_TCE_KILL                      126
-#define OPAL_LAST                              126
+#define OPAL_NMMU_SET_PTCR                     127
+#define OPAL_LAST                              127
 
 /* Device tree flags */
 
index 5c7db0f1a7087290f5b0610d9a492987222f0a1e..08ddea966601b1ad81737e7ce8d0458fd6a50f0a 100644 (file)
@@ -232,6 +232,7 @@ int64_t opal_pci_tce_kill(uint64_t phb_id, uint32_t kill_type,
 int64_t opal_rm_pci_tce_kill(uint64_t phb_id, uint32_t kill_type,
                             uint32_t pe_num, uint32_t tce_size,
                             uint64_t dma_addr, uint32_t npages);
+int64_t opal_nmmu_set_ptcr(uint64_t chip_id, uint64_t ptcr);
 
 /* Internal functions */
 extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
diff --git a/arch/powerpc/include/asm/powernv.h b/arch/powerpc/include/asm/powernv.h
new file mode 100644 (file)
index 0000000..0e9c240
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2017 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _ASM_POWERNV_H
+#define _ASM_POWERNV_H
+
+#ifdef CONFIG_PPC_POWERNV
+extern void powernv_set_nmmu_ptcr(unsigned long ptcr);
+#else
+static inline void powernv_set_nmmu_ptcr(unsigned long ptcr) { }
+#endif
+
+#endif /* _ASM_POWERNV_H */
index cfa53ccc8bafc908e80532a4a64e44ad358dffc7..086522b7c60f488ac599a6d8a50ed4abd568855f 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/machdep.h>
 #include <asm/mmu.h>
 #include <asm/firmware.h>
+#include <asm/powernv.h>
 
 #include <trace/events/thp.h>
 
@@ -438,6 +439,7 @@ void radix__mmu_cleanup_all(void)
                lpcr = mfspr(SPRN_LPCR);
                mtspr(SPRN_LPCR, lpcr & ~LPCR_UPRT);
                mtspr(SPRN_PTCR, 0);
+               powernv_set_nmmu_ptcr(0);
                radix__flush_tlb_all();
        }
 }
index 8bca7f58afc4678a167fb05ff00b6874c062c1fd..4ee9c9d18760e29074548d36a71e21fb526b0c04 100644 (file)
@@ -52,6 +52,7 @@
 #include <asm/sections.h>
 #include <asm/firmware.h>
 #include <asm/dma.h>
+#include <asm/powernv.h>
 
 #include "mmu_decl.h"
 
@@ -436,6 +437,7 @@ void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift)
 void __init mmu_partition_table_init(void)
 {
        unsigned long patb_size = 1UL << PATB_SIZE_SHIFT;
+       unsigned long ptcr;
 
        BUILD_BUG_ON_MSG((PATB_SIZE_SHIFT > 36), "Partition table size too large.");
        partition_tb = __va(memblock_alloc_base(patb_size, patb_size,
@@ -448,7 +450,9 @@ void __init mmu_partition_table_init(void)
         * update partition table control register,
         * 64 K size.
         */
-       mtspr(SPRN_PTCR, __pa(partition_tb) | (PATB_SIZE_SHIFT - 12));
+       ptcr = __pa(partition_tb) | (PATB_SIZE_SHIFT - 12);
+       mtspr(SPRN_PTCR, ptcr);
+       powernv_set_nmmu_ptcr(ptcr);
 }
 
 void mmu_partition_table_set_entry(unsigned int lpid, unsigned long dw0,
index 3aa40f1b20f510647acf6aa64e7e74f7e6af137b..f7c19c9c57ed9f4bc1e0762332d79f20e4e1308e 100644 (file)
@@ -311,4 +311,5 @@ OPAL_CALL_REAL(opal_rm_int_eoi,                     OPAL_INT_EOI);
 OPAL_CALL(opal_int_set_mfrr,                   OPAL_INT_SET_MFRR);
 OPAL_CALL_REAL(opal_rm_int_set_mfrr,           OPAL_INT_SET_MFRR);
 OPAL_CALL(opal_pci_tce_kill,                   OPAL_PCI_TCE_KILL);
+OPAL_CALL(opal_nmmu_set_ptcr,                  OPAL_NMMU_SET_PTCR);
 OPAL_CALL_REAL(opal_rm_pci_tce_kill,           OPAL_PCI_TCE_KILL);
index 282293572dc82a61ed9c39a607bd69cf47910d5b..86d9fde93c175f86dac6f40de0d68aff2455b0c6 100644 (file)
@@ -875,6 +875,17 @@ int opal_error_code(int rc)
        }
 }
 
+void powernv_set_nmmu_ptcr(unsigned long ptcr)
+{
+       int rc;
+
+       if (firmware_has_feature(FW_FEATURE_OPAL)) {
+               rc = opal_nmmu_set_ptcr(-1UL, ptcr);
+               if (rc != OPAL_SUCCESS && rc != OPAL_UNSUPPORTED)
+                       pr_warn("%s: Unable to set nest mmu ptcr\n", __func__);
+       }
+}
+
 EXPORT_SYMBOL_GPL(opal_poll_events);
 EXPORT_SYMBOL_GPL(opal_rtc_read);
 EXPORT_SYMBOL_GPL(opal_rtc_write);