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