[PATCH 04/13] KVM: PPC: Ultravisor: Use UV_WRITE_PATE ucall to register a PATE

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Michael Anderson <andmike@xxxxxxxxxxxxx>

The Nest_MMU needs to know the address of the Partition table (PT).
However the PT is in secure memory, and nestMMU cannot access secure
memory.  Hence hypevisor will continue to use a Partition table of
its own. It will have PATE entries for HV and for Normal virtual
machines. The same entries are also in the UV's PT.  The HV's PT
is programmed with the nest MMU.

Suggested-by: Ryan Grimm <grimm@xxxxxxxxxxxxxxxxxx>
Signed-off-by: Madhavan Srinivasan <maddy@xxxxxxxxxxxxxxxxxx>
[device node name to ibm,ultravisor]
Signed-off-by: Michael Anderson <andmike@xxxxxxxxxxxxx>
Signed-off-by: Ram Pai <linuxram@xxxxxxxxxx>
---
 arch/powerpc/include/asm/ucall-api.h        | 30 +++++++++++++++++++++++++++++
 arch/powerpc/include/uapi/asm/uapi_uvcall.h |  2 ++
 arch/powerpc/mm/hash_utils_64.c             |  4 +++-
 arch/powerpc/mm/pgtable-book3s64.c          | 29 ++++++++++++++++++++++++++--
 arch/powerpc/mm/pgtable-radix.c             | 10 +++++++---
 5 files changed, 69 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/include/asm/ucall-api.h b/arch/powerpc/include/asm/ucall-api.h
index 3833b55..f411dcb 100644
--- a/arch/powerpc/include/asm/ucall-api.h
+++ b/arch/powerpc/include/asm/ucall-api.h
@@ -1,5 +1,35 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 #ifndef _ASM_POWERPC_UCALL_API_H
 #define _ASM_POWERPC_UCALL_API_H
+
 #include <uapi/asm/uapi_uvcall.h>
+
+#ifndef __ASSEMBLY__
+
+#include <linux/of_fdt.h>
+#include <linux/libfdt.h>
+
+extern unsigned int smf_state;
+static inline bool smf_enabled(void)
+{
+	unsigned long smf;
+
+	if (!smf_state) {
+		smf = of_get_flat_dt_subnode_by_name(0, "ibm,ultravisor");
+		smf_state = (smf == -FDT_ERR_NOTFOUND) ? 1 : 2;
+	}
+	return (smf_state == 2);
+}
+
+#define PLPAR_UCALL_BUFSIZE 4
+long plpar_ucall(unsigned long opcode, unsigned long *retbuf, ...);
+
+static inline int uv_register_pate(u64 lpid, u64 dw0, u64 dw1)
+{
+	unsigned long retbuf[PLPAR_UCALL_BUFSIZE];
+
+	return plpar_ucall(UV_WRITE_PATE, retbuf, lpid, dw0, dw1);
+}
+
+#endif /* __ASSEMBLY__ */
 #endif	/* _ASM_POWERPC_UCALL_API_H */
diff --git a/arch/powerpc/include/uapi/asm/uapi_uvcall.h b/arch/powerpc/include/uapi/asm/uapi_uvcall.h
index 7e213a1..7f018cf 100644
--- a/arch/powerpc/include/uapi/asm/uapi_uvcall.h
+++ b/arch/powerpc/include/uapi/asm/uapi_uvcall.h
@@ -7,4 +7,6 @@
  */
 #ifndef UAPI_UC_H
 #define UAPI_UC_H
+
+#define UV_WRITE_PATE 	0xf104
 #endif /* #ifndef UAPI_UC_H */
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 0cc7fbc..6d0eef6 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -64,6 +64,7 @@
 #include <asm/ps3.h>
 #include <asm/pte-walk.h>
 #include <asm/asm-prototypes.h>
+#include <asm/ucall-api.h>
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -1051,9 +1052,10 @@ void hash__early_init_mmu_secondary(void)
 
 		if (!cpu_has_feature(CPU_FTR_ARCH_300))
 			mtspr(SPRN_SDR1, _SDR1);
-		else
+		else if (!smf_enabled())
 			mtspr(SPRN_PTCR,
 			      __pa(partition_tb) | (PATB_SIZE_SHIFT - 12));
+
 	}
 	/* Initialize SLB */
 	slb_initialize();
diff --git a/arch/powerpc/mm/pgtable-book3s64.c b/arch/powerpc/mm/pgtable-book3s64.c
index f3c31f5..ba6b34d 100644
--- a/arch/powerpc/mm/pgtable-book3s64.c
+++ b/arch/powerpc/mm/pgtable-book3s64.c
@@ -16,6 +16,7 @@
 #include <asm/tlb.h>
 #include <asm/trace.h>
 #include <asm/powernv.h>
+#include <asm/ucall-api.h>
 
 #include "mmu_decl.h"
 #include <trace/events/thp.h>
@@ -206,11 +207,23 @@ void __init mmu_partition_table_init(void)
 	 * 64 K size.
 	 */
 	ptcr = __pa(partition_tb) | (PATB_SIZE_SHIFT - 12);
-	mtspr(SPRN_PTCR, ptcr);
+	/*
+	 * Ultravisor creates and manages partition table if SMF
+	 * is enabled.
+	 */
+	if (!smf_enabled())
+		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,
+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 +251,18 @@ 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)
+{
+	pr_info("%s: SMF Regitered PATE for Hypervisor dw0 = 0x%lx dw1 = 0x%lx ", __func__, dw0, dw1);
+	if (smf_enabled())
+		uv_register_pate(lpid, dw0, dw1);
+
+	__mmu_partition_table_set_entry(lpid, dw0, dw1);
+	return;
+}
+
 EXPORT_SYMBOL_GPL(mmu_partition_table_set_entry);
 
 static pmd_t *get_pmd_from_cache(struct mm_struct *mm)
diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c
index 9311560..bcc8398 100644
--- a/arch/powerpc/mm/pgtable-radix.c
+++ b/arch/powerpc/mm/pgtable-radix.c
@@ -29,11 +29,13 @@
 #include <asm/powernv.h>
 #include <asm/sections.h>
 #include <asm/trace.h>
+#include <asm/ucall-api.h>
 
 #include <trace/events/thp.h>
 
 unsigned int mmu_pid_bits;
 unsigned int mmu_base_pid;
+unsigned int smf_state;
 
 static int native_register_process_table(unsigned long base, unsigned long pg_sz,
 					 unsigned long table_size)
@@ -623,8 +625,9 @@ 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 (!smf_enabled())
+			mtspr(SPRN_PTCR, __pa(partition_tb) | (PATB_SIZE_SHIFT - 12));
+
 		radix_init_amor();
 	}
 	radix_init_iamr();
@@ -641,7 +644,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 (!smf_enabled())
+			mtspr(SPRN_PTCR, 0);
 		powernv_set_nmmu_ptcr(0);
 		radix__flush_tlb_all();
 	}
-- 
1.8.3.1




[Index of Archives]     [KVM Development]     [KVM ARM]     [KVM ia64]     [Linux Virtualization]     [Linux USB Devel]     [Linux Video]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux