[RFC PATCH part-7 03/12] pkvm: x86: Use SW bits to track page state

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

 



From: Shaoqin Huang <shaoqin.huang@xxxxxxxxx>

pKVM already had a mechnism to record page ownership in host EPT, it
still needs a place to record page state based on the ownership; the page
state is used to identify the exact state of corresponding page:

- PKVM_NOPAGE: the page has no mapping in page table (also invalid pte).
               And under this page state, host EPT is using the pte
	       ignored bits to record owner_id.
- PKVM_PAGE_OWNED: the page is owned exclusively by the page-table owner.
- PKVM_PAGE_SHARED_OWNED: the page is owned by the page-table owner, but
			  is shared with another entity.
- PKVM_PAGE_SHARED_BORROWED: the page is shared with, but not owned by
			     the page-table owner.

The bit[56,57] of a EPT page table are ignored in the PTE, so use these
two bits as SW bits to record the page state.

Signed-off-by: Shaoqin Huang <shaoqin.huang@xxxxxxxxx>
---
 arch/x86/kvm/vmx/pkvm/hyp/mem_protect.c | 13 ++++++++-
 arch/x86/kvm/vmx/pkvm/hyp/mem_protect.h | 39 +++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.c b/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.c
index a6554a039468..625c138addfb 100644
--- a/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.c
+++ b/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.c
@@ -10,7 +10,9 @@
 
 static u64 pkvm_init_invalid_leaf_owner(pkvm_id owner_id)
 {
-	return FIELD_PREP(PKVM_INVALID_PTE_OWNER_MASK, owner_id);
+	/* the page owned by others also means NOPAGE in page state */
+	return FIELD_PREP(PKVM_INVALID_PTE_OWNER_MASK, owner_id) |
+		FIELD_PREP(PKVM_PAGE_STATE_PROT_MASK, PKVM_NOPAGE);
 }
 
 static int host_ept_set_owner_locked(phys_addr_t addr, u64 size, pkvm_id owner_id)
@@ -18,6 +20,15 @@ static int host_ept_set_owner_locked(phys_addr_t addr, u64 size, pkvm_id owner_i
 	u64 annotation = pkvm_init_invalid_leaf_owner(owner_id);
 	int ret;
 
+
+	/*
+	 * The memory [addr, addr + size) will be unmapped from host ept. At the
+	 * same time, the annotation with a NOPAGE flag will be put in the
+	 * invalid pte that has been unmapped. And the information shows that
+	 * the page has been used by some guest and its id can be read from
+	 * annotation. Also when later these pages are back to host, the annotation
+	 * will be helpful to check the right page transition.
+	 */
 	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
index 728de3ac62dd..6b5e0fcbdda0 100644
--- a/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.h
+++ b/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.h
@@ -5,9 +5,48 @@
 #ifndef __PKVM_MEM_PROTECT_H__
 #define __PKVM_MEM_PROTECT_H__
 
+/*
+ * enum pkvm_pgtable_prot - The ignored bits in page-table.
+ * pkvm will use these ignored bits as software bits to
+ * identify the page status.
+ */
+enum pkvm_pgtable_prot {
+	PKVM_PGTABLE_PROT_SW0		= BIT(56),
+	PKVM_PGTABLE_PROT_SW1		= BIT(57),
+};
+
+/*
+ * Using the ignored bits in page-table as SW bits.
+ * SW bits 0-1 are used to track the memory ownership state of each page:
+ *   00: The page has no mapping in page table (also invalid pte). And under
+ *   this page state, host ept is using the pte ignored bits to record owner_id.
+ *   01: The page is owned exclusively by the page-table owner.
+ *   10: The page is owned by the page-table owner, but is shared
+ *   	with another entity.
+ *   11: The page is shared with, but not owned by the page-table owner.
+ */
+enum pkvm_page_state {
+	PKVM_NOPAGE			= 0ULL,
+	PKVM_PAGE_OWNED			= PKVM_PGTABLE_PROT_SW0,
+	PKVM_PAGE_SHARED_OWNED		= PKVM_PGTABLE_PROT_SW1,
+	PKVM_PAGE_SHARED_BORROWED	= PKVM_PGTABLE_PROT_SW0 |
+					  PKVM_PGTABLE_PROT_SW1,
+};
+
+#define PKVM_PAGE_STATE_PROT_MASK	(PKVM_PGTABLE_PROT_SW0 | PKVM_PGTABLE_PROT_SW1)
 /* use 20 bits[12~31] - not conflict w/ low 12 bits pte prot */
 #define PKVM_INVALID_PTE_OWNER_MASK	GENMASK(31, 12)
 
+static inline u64 pkvm_mkstate(u64 prot, enum pkvm_page_state state)
+{
+	return (prot & ~PKVM_PAGE_STATE_PROT_MASK) | state;
+}
+
+static inline enum pkvm_page_state pkvm_getstate(u64 pte)
+{
+	return pte & PKVM_PAGE_STATE_PROT_MASK;
+}
+
 typedef u32 pkvm_id;
 
 #define OWNER_ID_HYP	0UL
-- 
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