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