@@ -15,6 +15,9 @@
#define U_SUCCESS H_SUCCESS
#define U_FUNCTION H_FUNCTION
#define U_PARAMETER H_PARAMETER
+#define U_PERMISSION H_PERMISSION
-#endif /* _ASM_POWERPC_ULTRAVISOR_API_H */
+/* opcodes */
+#define UV_WRITE_PATE 0xF104
+#endif /* _ASM_POWERPC_ULTRAVISOR_API_H */
@@ -12,6 +12,8 @@
#if !defined(__ASSEMBLY__)
+#include <linux/types.h>
+
/* Internal functions */
extern int early_init_dt_scan_ultravisor(unsigned long node, const char *uname,
int depth, void *data);
@@ -28,8 +30,20 @@ extern int early_init_dt_scan_ultravisor(unsigned long node, const char *uname,
*/
#if defined(CONFIG_PPC_UV)
long ucall(unsigned long opcode, unsigned long *retbuf, ...);
+#else
+static long ucall(unsigned long opcode, unsigned long *retbuf, ...)
+{
+ return U_NOT_AVAILABLE;
+}
#endif
+static inline int uv_register_pate(u64 lpid, u64 dw0, u64 dw1)
+{
+ unsigned long retbuf[UCALL_BUFSIZE];
+
+ return ucall(UV_WRITE_PATE, retbuf, lpid, dw0, dw1);
+}
+
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_POWERPC_ULTRAVISOR_H */
@@ -1080,9 +1080,10 @@ void hash__early_init_mmu_secondary(void)
if (!cpu_has_feature(CPU_FTR_ARCH_300))
mtspr(SPRN_SDR1, _SDR1);
- else
+ else if (!firmware_has_feature(FW_FEATURE_ULTRAVISOR))
mtspr(SPRN_PTCR,
__pa(partition_tb) | (PATB_SIZE_SHIFT - 12));
+
}
/* Initialize SLB */
slb_initialize();
@@ -16,6 +16,8 @@
#include <asm/tlb.h>
#include <asm/trace.h>
#include <asm/powernv.h>
+#include <asm/firmware.h>
+#include <asm/ultravisor.h>
#include <mm/mmu_decl.h>
#include <trace/events/thp.h>
@@ -206,12 +208,25 @@ void __init mmu_partition_table_init(void)
* 64 K size.
*/
ptcr = __pa(partition_tb) | (PATB_SIZE_SHIFT - 12);
- mtspr(SPRN_PTCR, ptcr);
+ /*
+ * If ultravisor is available, it is responsible for creating and
+ * managing partition table
+ */
+ if (!firmware_has_feature(FW_FEATURE_ULTRAVISOR))
+ mtspr(SPRN_PTCR, ptcr);
+
+ /*
+ * Since nestMMU cannot access secure memory. Create
+ * and manage our own partition table. This table
+ * contains entries for nonsecure and hypervisor
+ * partition.
+ */
powernv_set_nmmu_ptcr(ptcr);
}
-void mmu_partition_table_set_entry(unsigned int lpid, unsigned long dw0,
- unsigned long dw1)
+static void __mmu_partition_table_set_entry(unsigned int lpid,
+ unsigned long dw0,
+ unsigned long dw1)
{
unsigned long old = be64_to_cpu(partition_tb[lpid].patb0);
@@ -238,6 +253,19 @@ void mmu_partition_table_set_entry(unsigned int lpid, unsigned long dw0,
/* do we need fixup here ?*/
asm volatile("eieio; tlbsync; ptesync" : : : "memory");
}
+
+void mmu_partition_table_set_entry(unsigned int lpid, unsigned long dw0,
+ unsigned long dw1)
+{
+ __mmu_partition_table_set_entry(lpid, dw0, dw1);
+
+ if (firmware_has_feature(FW_FEATURE_ULTRAVISOR)) {
+ uv_register_pate(lpid, dw0, dw1);
+ pr_info("PATE registered by ultravisor: dw0 = 0x%lx, dw1 = 0x%lx\n",
+ dw0, dw1);
+ }
+}
+
EXPORT_SYMBOL_GPL(mmu_partition_table_set_entry);
static pmd_t *get_pmd_from_cache(struct mm_struct *mm)
@@ -655,8 +655,10 @@ void radix__early_init_mmu_secondary(void)
lpcr = mfspr(SPRN_LPCR);
mtspr(SPRN_LPCR, lpcr | LPCR_UPRT | LPCR_HR);
- mtspr(SPRN_PTCR,
- __pa(partition_tb) | (PATB_SIZE_SHIFT - 12));
+ if (!firmware_has_feature(FW_FEATURE_ULTRAVISOR))
+ mtspr(SPRN_PTCR, __pa(partition_tb) |
+ (PATB_SIZE_SHIFT - 12));
+
radix_init_amor();
}
@@ -672,7 +674,8 @@ void radix__mmu_cleanup_all(void)
if (!firmware_has_feature(FW_FEATURE_LPAR)) {
lpcr = mfspr(SPRN_LPCR);
mtspr(SPRN_LPCR, lpcr & ~LPCR_UPRT);
- mtspr(SPRN_PTCR, 0);
+ if (!firmware_has_feature(FW_FEATURE_ULTRAVISOR))
+ mtspr(SPRN_PTCR, 0);
powernv_set_nmmu_ptcr(0);
radix__flush_tlb_all();
}