[RFC PATCH part-3 01/22] pkvm: x86: Define hypervisor runtime VA/PA APIs

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

 



pKVM has its own MMU page table, to maintain the mapping between VA &
PA under hypervisor runtime (VMX root mode).

Setup the translation between VA & PA for hypervisor runtime:
keep same direct mapping as Linux kernel based on __page_base_offset.
also keep same pkvm symbol mapping as Linux kernel based on
__symbol_base_offset.

direct mapping translation:
- pkvm_phys_to_virt: phys + __page_base_offset
- pkvm_virt_to_phys: virt - __page_base_offset
symbol mapping translation:
- pkvm_virt_to_symbol_phys: virt - __symbol_base_offset

The following patches will setup pKVM's MMU page table based on above
translation.

Signed-off-by: Shaoqin Huang <shaoqin.huang@xxxxxxxxx>
Signed-off-by: Chuanxiao Dong <chuanxiao.dong@xxxxxxxxx>
Signed-off-by: Jason Chen CJ <jason.cj.chen@xxxxxxxxx>
---
 arch/x86/include/asm/kvm_pkvm.h      | 18 ++++++++++++++++++
 arch/x86/kvm/vmx/pkvm/hyp/Makefile   |  2 +-
 arch/x86/kvm/vmx/pkvm/hyp/memory.c   | 24 ++++++++++++++++++++++++
 arch/x86/kvm/vmx/pkvm/hyp/memory.h   | 13 +++++++++++++
 arch/x86/kvm/vmx/pkvm/hyp/vmx_ops.h  |  5 +++--
 arch/x86/kvm/vmx/pkvm/include/pkvm.h |  5 +++++
 arch/x86/kvm/vmx/pkvm/pkvm_host.c    | 19 +++++++++++++++++++
 7 files changed, 83 insertions(+), 3 deletions(-)

diff --git a/arch/x86/include/asm/kvm_pkvm.h b/arch/x86/include/asm/kvm_pkvm.h
new file mode 100644
index 000000000000..224143567aaa
--- /dev/null
+++ b/arch/x86/include/asm/kvm_pkvm.h
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022 Intel Corporation
+ */
+
+#ifndef _ASM_X86_KVM_PKVM_H
+#define _ASM_X86_KVM_PKVM_H
+
+#ifdef CONFIG_PKVM_INTEL
+
+void *pkvm_phys_to_virt(unsigned long phys);
+unsigned long pkvm_virt_to_phys(void *virt);
+
+#define __pkvm_pa(virt)	pkvm_virt_to_phys((void *)(virt))
+#define __pkvm_va(phys)	pkvm_phys_to_virt((unsigned long)(phys))
+#endif
+
+#endif
diff --git a/arch/x86/kvm/vmx/pkvm/hyp/Makefile b/arch/x86/kvm/vmx/pkvm/hyp/Makefile
index 5a92067ab05a..970341ab63a3 100644
--- a/arch/x86/kvm/vmx/pkvm/hyp/Makefile
+++ b/arch/x86/kvm/vmx/pkvm/hyp/Makefile
@@ -8,7 +8,7 @@ ccflags-y += -D__PKVM_HYP__
 
 lib-dir		:= lib
 
-pkvm-hyp-y	:= vmx_asm.o vmexit.o
+pkvm-hyp-y	:= vmx_asm.o vmexit.o memory.o
 
 pkvm-hyp-$(CONFIG_RETPOLINE)	+= $(lib-dir)/retpoline.o
 pkvm-hyp-$(CONFIG_DEBUG_LIST)	+= $(lib-dir)/list_debug.o
diff --git a/arch/x86/kvm/vmx/pkvm/hyp/memory.c b/arch/x86/kvm/vmx/pkvm/hyp/memory.c
new file mode 100644
index 000000000000..62dd80947d8e
--- /dev/null
+++ b/arch/x86/kvm/vmx/pkvm/hyp/memory.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022 Intel Corporation
+ */
+
+#include <linux/types.h>
+
+unsigned long __page_base_offset;
+unsigned long __symbol_base_offset;
+
+void *pkvm_phys_to_virt(unsigned long phys)
+{
+	return (void *)__page_base_offset + phys;
+}
+
+unsigned long pkvm_virt_to_phys(void *virt)
+{
+	return (unsigned long)virt - __page_base_offset;
+}
+
+unsigned long pkvm_virt_to_symbol_phys(void *virt)
+{
+	return (unsigned long)virt - __symbol_base_offset;
+}
diff --git a/arch/x86/kvm/vmx/pkvm/hyp/memory.h b/arch/x86/kvm/vmx/pkvm/hyp/memory.h
new file mode 100644
index 000000000000..c2eee487687a
--- /dev/null
+++ b/arch/x86/kvm/vmx/pkvm/hyp/memory.h
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022 Intel Corporation
+ */
+#ifndef _PKVM_MEMORY_H_
+#define _PKVM_MEMORY_H_
+
+#include <asm/kvm_pkvm.h>
+
+unsigned long pkvm_virt_to_symbol_phys(void *virt);
+#define __pkvm_pa_symbol(x) pkvm_virt_to_symbol_phys((void *)x)
+
+#endif
diff --git a/arch/x86/kvm/vmx/pkvm/hyp/vmx_ops.h b/arch/x86/kvm/vmx/pkvm/hyp/vmx_ops.h
index 1692870ee00c..5fc049e4b487 100644
--- a/arch/x86/kvm/vmx/pkvm/hyp/vmx_ops.h
+++ b/arch/x86/kvm/vmx/pkvm/hyp/vmx_ops.h
@@ -5,6 +5,7 @@
 #ifndef _PKVM_VMX_OPS_H_
 #define _PKVM_VMX_OPS_H_
 
+#include "memory.h"
 #include "debug.h"
 
 #ifdef asm_volatile_goto
@@ -170,14 +171,14 @@ static __always_inline void vmcs_set_bits(unsigned long field, u32 mask)
 
 static inline void vmcs_clear(struct vmcs *vmcs)
 {
-	u64 phys_addr = __pa(vmcs);
+	u64 phys_addr = __pkvm_pa(vmcs);
 
 	vmx_asm1(vmclear, "m"(phys_addr), vmcs, phys_addr);
 }
 
 static inline void vmcs_load(struct vmcs *vmcs)
 {
-	u64 phys_addr = __pa(vmcs);
+	u64 phys_addr = __pkvm_pa(vmcs);
 
 	vmx_asm1(vmptrld, "m"(phys_addr), vmcs, phys_addr);
 }
diff --git a/arch/x86/kvm/vmx/pkvm/include/pkvm.h b/arch/x86/kvm/vmx/pkvm/include/pkvm.h
index 59ef09230700..b344165511f7 100644
--- a/arch/x86/kvm/vmx/pkvm/include/pkvm.h
+++ b/arch/x86/kvm/vmx/pkvm/include/pkvm.h
@@ -48,6 +48,11 @@ struct pkvm_hyp {
 #define PKVM_PCPU_PAGES (ALIGN(sizeof(struct pkvm_pcpu), PAGE_SIZE) >> PAGE_SHIFT)
 #define PKVM_HOST_VCPU_PAGES (ALIGN(sizeof(struct pkvm_host_vcpu), PAGE_SIZE) >> PAGE_SHIFT)
 
+extern char __pkvm_text_start[], __pkvm_text_end[];
+
+extern unsigned long pkvm_sym(__page_base_offset);
+extern unsigned long pkvm_sym(__symbol_base_offset);
+
 PKVM_DECLARE(void, __pkvm_vmx_vmexit(void));
 PKVM_DECLARE(int, pkvm_main(struct kvm_vcpu *vcpu));
 
diff --git a/arch/x86/kvm/vmx/pkvm/pkvm_host.c b/arch/x86/kvm/vmx/pkvm/pkvm_host.c
index 1fa273396b9b..9705aebaab2e 100644
--- a/arch/x86/kvm/vmx/pkvm/pkvm_host.c
+++ b/arch/x86/kvm/vmx/pkvm/pkvm_host.c
@@ -440,6 +440,21 @@ static __init int pkvm_host_check_and_setup_vmx_cap(struct pkvm_hyp *pkvm)
 	return ret;
 }
 
+static __init int pkvm_init_mmu(void)
+{
+	/*
+	 * __page_base_offset stores the offset for pkvm
+	 * to translate VA to a PA.
+	 *
+	 * __symbol_base_offset stores the offset for pkvm
+	 * to translate its symbole's VA to a PA.
+	 */
+	pkvm_sym(__page_base_offset) = (unsigned long)__va(0);
+	pkvm_sym(__symbol_base_offset) = (unsigned long)__pkvm_text_start - __pa_symbol(__pkvm_text_start);
+
+	return 0;
+}
+
 static __init void init_gdt(struct pkvm_pcpu *pcpu)
 {
 	pcpu->gdt_page = pkvm_gdt_page;
@@ -693,6 +708,10 @@ __init int pkvm_init(void)
 	if (ret)
 		goto out_free_pkvm;
 
+	ret = pkvm_init_mmu();
+	if (ret)
+		goto out_free_pkvm;
+
 	for_each_possible_cpu(cpu) {
 		ret = pkvm_setup_pcpu(pkvm, cpu);
 		if (ret)
-- 
2.25.1




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux