[RFC PATCH part-7 02/12] pkvm: x86: Use host EPT to track page ownership

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

 



From: Shaoqin Huang <shaoqin.huang@xxxxxxxxx>

Provide host_ept_set_owner_locked() which allows to modify the ownership
of pages in the host EPT through pkvm_pgtable_annotate(). This API is
used when caller hold host EPT lock.

The page owner id is 20 bits, take use of host EPT PTE bits[12~31], and
different owner are defined as the following:
- pKVM hypervisor: 0
- host:		   1
- guest:	   2 ~ 1 << 20 - 1
The guest's owner id is actually reused from shadow_vm_handle, so also
limit MAX_SHADOW_VMS based on page owner id mask.

TODO: now pKVM set owner in host EPT based on 4K pages, it means host
EPT may finally be broken into small pages. In the future, can consider
to support set owner based on huge pages.

Signed-off-by: Shaoqin Huang <shaoqin.huang@xxxxxxxxx>
Signed-off-by: Jason Chen CJ <jason.cj.chen@xxxxxxxxx>
---
 arch/x86/kvm/vmx/pkvm/hyp/Makefile      |  2 +-
 arch/x86/kvm/vmx/pkvm/hyp/mem_protect.c | 24 ++++++++++++++++++++++++
 arch/x86/kvm/vmx/pkvm/hyp/mem_protect.h | 17 +++++++++++++++++
 arch/x86/kvm/vmx/pkvm/hyp/pkvm.c        | 11 +++++++++--
 4 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/vmx/pkvm/hyp/Makefile b/arch/x86/kvm/vmx/pkvm/hyp/Makefile
index fc75cdd9fc79..807e6bfbae0f 100644
--- a/arch/x86/kvm/vmx/pkvm/hyp/Makefile
+++ b/arch/x86/kvm/vmx/pkvm/hyp/Makefile
@@ -12,7 +12,7 @@ ccflags-y += -D__PKVM_HYP__
 virt-dir	:= ../../../../../../$(KVM_PKVM)
 
 pkvm-hyp-y	:= vmx_asm.o vmexit.o memory.o early_alloc.o pgtable.o mmu.o pkvm.o \
-		   init_finalise.o ept.o idt.o irq.o nested.o vmx.o vmsr.o
+		   init_finalise.o ept.o idt.o irq.o nested.o vmx.o vmsr.o mem_protect.o
 
 ifndef CONFIG_PKVM_INTEL_DEBUG
 lib-dir		:= lib
diff --git a/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.c b/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.c
new file mode 100644
index 000000000000..a6554a039468
--- /dev/null
+++ b/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022 Intel Corporation
+ */
+#include <linux/bitfield.h>
+#include <pkvm.h>
+#include "pkvm_hyp.h"
+#include "mem_protect.h"
+#include "pgtable.h"
+
+static u64 pkvm_init_invalid_leaf_owner(pkvm_id owner_id)
+{
+	return FIELD_PREP(PKVM_INVALID_PTE_OWNER_MASK, owner_id);
+}
+
+static int host_ept_set_owner_locked(phys_addr_t addr, u64 size, pkvm_id owner_id)
+{
+	u64 annotation = pkvm_init_invalid_leaf_owner(owner_id);
+	int ret;
+
+	ret = pkvm_pgtable_annotate(pkvm_hyp->host_vm.ept, addr, size, annotation);
+
+	return ret;
+}
diff --git a/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.h b/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.h
new file mode 100644
index 000000000000..728de3ac62dd
--- /dev/null
+++ b/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.h
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022 Intel Corporation
+ */
+#ifndef __PKVM_MEM_PROTECT_H__
+#define __PKVM_MEM_PROTECT_H__
+
+/* use 20 bits[12~31] - not conflict w/ low 12 bits pte prot */
+#define PKVM_INVALID_PTE_OWNER_MASK	GENMASK(31, 12)
+
+typedef u32 pkvm_id;
+
+#define OWNER_ID_HYP	0UL
+#define OWNER_ID_HOST	1UL
+#define OWNER_ID_INV	(~(u32)0UL)
+
+#endif
diff --git a/arch/x86/kvm/vmx/pkvm/hyp/pkvm.c b/arch/x86/kvm/vmx/pkvm/hyp/pkvm.c
index e18688b1a235..63004ed6e90e 100644
--- a/arch/x86/kvm/vmx/pkvm/hyp/pkvm.c
+++ b/arch/x86/kvm/vmx/pkvm/hyp/pkvm.c
@@ -8,6 +8,7 @@
 
 #include "pkvm_hyp.h"
 #include "ept.h"
+#include "mem_protect.h"
 
 struct pkvm_hyp *pkvm_hyp;
 
@@ -37,8 +38,14 @@ static int allocate_shadow_vm_handle(struct pkvm_shadow_vm *vm)
 	struct shadow_vm_ref *vm_ref;
 	int handle;
 
-	/* The shadow_vm_handle is an int so cannot exceed the INT_MAX */
-	BUILD_BUG_ON(MAX_SHADOW_VMS > INT_MAX);
+	/*
+	 * The shadow_vm_handle is an int so cannot exceed the INT_MAX.
+	 * Meanwhile shadow_vm_handle will also be used as owner_id in
+	 * the page state machine so it also cannot exceed the max
+	 * owner_id.
+	 */
+	BUILD_BUG_ON(MAX_SHADOW_VMS >
+		     min(INT_MAX, ((1 << hweight_long(PKVM_INVALID_PTE_OWNER_MASK)) - 1)));
 
 	pkvm_spin_lock(&shadow_vms_lock);
 
-- 
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