[RFC PATCH part-7 07/12] pkvm: x86: Implement __pkvm_hyp_donate_host()

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

 



From: Shaoqin Huang <shaoqin.huang@xxxxxxxxx>

Provide __pkvm_hyp_donate_host() to transfer the page ownership from
hypervisor to host. This will be used later when pKVM return memory
back to host.

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

diff --git a/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.c b/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.c
index b040a109f87d..fad81f91794c 100644
--- a/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.c
+++ b/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.c
@@ -30,6 +30,7 @@ struct pkvm_mem_trans_desc {
 			u64	addr;
 		} hyp;
 	};
+	u64			prot;
 };
 
 struct pkvm_mem_transition {
@@ -64,6 +65,11 @@ static int host_ept_set_owner_locked(phys_addr_t addr, u64 size, pkvm_id owner_i
 	return ret;
 }
 
+static int host_ept_create_idmap_locked(u64 addr, u64 size, int pgsz_mask, u64 prot)
+{
+	return pkvm_pgtable_map(pkvm_hyp->host_vm.ept, addr, addr, size, pgsz_mask, prot);
+}
+
 static int
 __check_page_state_walker(struct pkvm_pgtable *pgt, unsigned long vaddr,
 			  unsigned long vaddr_end, int level, void *ptep,
@@ -120,6 +126,14 @@ static int host_request_donation(const struct pkvm_mem_transition *tx)
 	return __host_check_page_state_range(addr, size, PKVM_PAGE_OWNED);
 }
 
+static int host_ack_donation(const struct pkvm_mem_transition *tx)
+{
+	u64 addr = tx->completer.host.addr;
+	u64 size = tx->size;
+
+	return __host_check_page_state_range(addr, size, PKVM_NOPAGE);
+}
+
 static int check_donation(const struct pkvm_mem_transition *tx)
 {
 	int ret;
@@ -128,6 +142,9 @@ static int check_donation(const struct pkvm_mem_transition *tx)
 	case PKVM_ID_HOST:
 		ret = host_request_donation(tx);
 		break;
+	case PKVM_ID_HYP:
+		ret = 0;
+		break;
 	default:
 		ret = -EINVAL;
 	}
@@ -136,6 +153,9 @@ static int check_donation(const struct pkvm_mem_transition *tx)
 		return ret;
 
 	switch (tx->completer.id) {
+	case PKVM_ID_HOST:
+		ret = host_ack_donation(tx);
+		break;
 	case PKVM_ID_HYP:
 		ret = 0;
 		break;
@@ -158,6 +178,15 @@ static int host_initiate_donation(const struct pkvm_mem_transition *tx)
 		return host_ept_set_owner_locked(addr, size, owner_id);
 }
 
+static int host_complete_donation(const struct pkvm_mem_transition *tx)
+{
+	u64 addr = tx->completer.host.addr;
+	u64 size = tx->size;
+	u64 prot = pkvm_mkstate(tx->completer.prot, PKVM_PAGE_OWNED);
+
+	return host_ept_create_idmap_locked(addr, size, 0, prot);
+}
+
 static int __do_donate(const struct pkvm_mem_transition *tx)
 {
 	int ret;
@@ -166,6 +195,9 @@ static int __do_donate(const struct pkvm_mem_transition *tx)
 	case PKVM_ID_HOST:
 		ret = host_initiate_donation(tx);
 		break;
+	case PKVM_ID_HYP:
+		ret = 0;
+		break;
 	default:
 		ret = -EINVAL;
 	}
@@ -174,6 +206,9 @@ static int __do_donate(const struct pkvm_mem_transition *tx)
 		return ret;
 
 	switch (tx->completer.id) {
+	case PKVM_ID_HOST:
+		ret = host_complete_donation(tx);
+		break;
 	case PKVM_ID_HYP:
 		ret = 0;
 		break;
@@ -233,3 +268,33 @@ int __pkvm_host_donate_hyp(u64 hpa, u64 size)
 
 	return ret;
 }
+
+int __pkvm_hyp_donate_host(u64 hpa, u64 size)
+{
+	int ret;
+	u64 hyp_addr = (u64)__pkvm_va(hpa);
+	struct pkvm_mem_transition donation = {
+		.size		= size,
+		.initiator	= {
+			.id	= PKVM_ID_HYP,
+			.hyp	= {
+				.addr	= hyp_addr,
+			},
+		},
+		.completer	= {
+			.id	= PKVM_ID_HOST,
+			.host	= {
+				.addr	= hpa,
+			},
+			.prot	= HOST_EPT_DEF_MEM_PROT,
+		},
+	};
+
+	host_ept_lock();
+
+	ret = do_donate(&donation);
+
+	host_ept_unlock();
+
+	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 e7e632270688..efb3b3895f58 100644
--- a/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.h
+++ b/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.h
@@ -68,4 +68,18 @@ typedef u32 pkvm_id;
  */
 int __pkvm_host_donate_hyp(u64 hpa, u64 size);
 
+/*
+ * __pkvm_hyp_donate_host() - Donate pages from hyp to host, then host can
+ * access these pages.
+ *
+ * @hpa:	Start hpa of being donated pages, must be continuous.
+ * @size:	The size of memory to be donated.
+ *
+ * A range of pages [hpa, hpa + size) will be donated from hyp to host. This
+ * will create mapping in host ept for these pages, and nothing to do with hyp
+ * mmu. This is paired with __pkvm_host_donate_hyp(), and same as host reclaiming
+ * these pages back.
+ */
+int __pkvm_hyp_donate_host(u64 hpa, u64 size);
+
 #endif
-- 
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