[PATCH v2 06/22] KVM: arm64: Add a range to __pkvm_host_share/unshare_hyp()
From: Vincent Donnefort <hidden>
Date: 2026-09-11 13:51:10
Also in:
kvmarm
Subsystem:
arm64 port (aarch64 architecture), kernel virtual machine for arm64 (kvm/arm64), the rest · Maintainers:
Catalin Marinas, Will Deacon, Marc Zyngier, Oliver Upton, Linus Torvalds
Nothing prevents the host/hyp sharing transition from working on a range. In preparation for testing huge mappings with the pKVM ownership selftest, add a range to these hypercalls to allow them to be tested just like the others without any special case. Signed-off-by: Vincent Donnefort <redacted> --- arch/arm64/kvm/hyp/include/nvhe/mem_protect.h | 4 +- arch/arm64/kvm/hyp/nvhe/ffa.c | 12 ++--- arch/arm64/kvm/hyp/nvhe/hyp-main.c | 4 +- arch/arm64/kvm/hyp/nvhe/mem_protect.c | 50 +++++++++++-------- 4 files changed, 38 insertions(+), 32 deletions(-)
diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
index e2a5d7ffec7d..1f70162fa625 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h@@ -31,10 +31,10 @@ enum pkvm_component_id { }; int __pkvm_prot_finalize(void); -int __pkvm_host_share_hyp(u64 pfn); +int __pkvm_host_share_hyp(u64 pfn, u64 nr_pages); int __pkvm_guest_share_host(struct pkvm_hyp_vcpu *vcpu, u64 gfn); int __pkvm_guest_unshare_host(struct pkvm_hyp_vcpu *vcpu, u64 gfn); -int __pkvm_host_unshare_hyp(u64 pfn); +int __pkvm_host_unshare_hyp(u64 pfn, u64 nr_pages); int __pkvm_host_donate_hyp(u64 pfn, u64 nr_pages); int __pkvm_hyp_donate_host(u64 pfn, u64 nr_pages); int __pkvm_host_share_ffa(u64 pfn, u64 nr_pages);
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index a327c2bbb6b6..a6e12f240c50 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c@@ -263,13 +263,13 @@ static void do_ffa_rxtx_map(struct arm_smccc_1_2_regs *res, if (ret) goto out_unlock; - ret = __pkvm_host_share_hyp(hyp_phys_to_pfn(tx)); + ret = __pkvm_host_share_hyp(hyp_phys_to_pfn(tx), 1); if (ret) { ret = FFA_RET_INVALID_PARAMETERS; goto err_unmap; } - ret = __pkvm_host_share_hyp(hyp_phys_to_pfn(rx)); + ret = __pkvm_host_share_hyp(hyp_phys_to_pfn(rx), 1); if (ret) { ret = FFA_RET_INVALID_PARAMETERS; goto err_unshare_tx;
@@ -301,9 +301,9 @@ static void do_ffa_rxtx_map(struct arm_smccc_1_2_regs *res, err_unpin_tx: hyp_unpin_shared_mem(tx_virt, tx_virt + 1); err_unshare_rx: - __pkvm_host_unshare_hyp(hyp_phys_to_pfn(rx)); + __pkvm_host_unshare_hyp(hyp_phys_to_pfn(rx), 1); err_unshare_tx: - __pkvm_host_unshare_hyp(hyp_phys_to_pfn(tx)); + __pkvm_host_unshare_hyp(hyp_phys_to_pfn(tx), 1); err_unmap: ffa_unmap_hyp_buffers(); goto out_unlock;
@@ -327,11 +327,11 @@ static void do_ffa_rxtx_unmap(struct arm_smccc_1_2_regs *res, } hyp_unpin_shared_mem(host_buffers.tx, host_buffers.tx + 1); - WARN_ON(__pkvm_host_unshare_hyp(hyp_virt_to_pfn(host_buffers.tx))); + WARN_ON(__pkvm_host_unshare_hyp(hyp_virt_to_pfn(host_buffers.tx), 1)); host_buffers.tx = NULL; hyp_unpin_shared_mem(host_buffers.rx, host_buffers.rx + 1); - WARN_ON(__pkvm_host_unshare_hyp(hyp_virt_to_pfn(host_buffers.rx))); + WARN_ON(__pkvm_host_unshare_hyp(hyp_virt_to_pfn(host_buffers.rx), 1)); host_buffers.rx = NULL; ffa_unmap_hyp_buffers();
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 9fbe703fc595..bb23006e60c4 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c@@ -716,14 +716,14 @@ static void handle___pkvm_host_share_hyp(struct kvm_cpu_context *host_ctxt) { DECLARE_REG(u64, pfn, host_ctxt, 1); - cpu_reg(host_ctxt, 1) = __pkvm_host_share_hyp(pfn); + cpu_reg(host_ctxt, 1) = __pkvm_host_share_hyp(pfn, 1); } static void handle___pkvm_host_unshare_hyp(struct kvm_cpu_context *host_ctxt) { DECLARE_REG(u64, pfn, host_ctxt, 1); - cpu_reg(host_ctxt, 1) = __pkvm_host_unshare_hyp(pfn); + cpu_reg(host_ctxt, 1) = __pkvm_host_unshare_hyp(pfn, 1); } static void handle___pkvm_create_private_mapping(struct kvm_cpu_context *host_ctxt)
diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
index 183ecd7058cf..fb01f6129217 100644
--- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
+++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c@@ -969,12 +969,15 @@ int __pkvm_vcpu_in_poison_fault(struct pkvm_hyp_vcpu *hyp_vcpu) return ret; } -int __pkvm_host_share_hyp(u64 pfn) +int __pkvm_host_share_hyp(u64 pfn, u64 nr_pages) { u64 phys = hyp_pfn_to_phys(pfn); - u64 size = PAGE_SIZE; + u64 size = PAGE_SIZE * nr_pages; int ret; + if (!pfn_range_is_valid(pfn, nr_pages)) + return -EINVAL; + host_lock_component(); hyp_lock_component();
@@ -1061,12 +1064,15 @@ int __pkvm_guest_unshare_host(struct pkvm_hyp_vcpu *vcpu, u64 gfn) return ret; } -int __pkvm_host_unshare_hyp(u64 pfn) +int __pkvm_host_unshare_hyp(u64 pfn, u64 nr_pages) { u64 phys = hyp_pfn_to_phys(pfn); - u64 size = PAGE_SIZE; + u64 size = PAGE_SIZE * nr_pages; int ret; + if (!pfn_range_is_valid(pfn, nr_pages)) + return -EINVAL; + host_lock_component(); hyp_lock_component();
@@ -1784,8 +1790,8 @@ int __pkvm_ownership_selftest(u64 pfn, u64 pgtable_pfn, unsigned long pgtable_nr selftest_state.guest[0] = selftest_state.guest[1] = PKVM_NOPAGE; assert_page_state(); assert_transition_res(-EPERM, __pkvm_host_donate_hyp, pfn, 1); - assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn); - assert_transition_res(-EPERM, __pkvm_host_unshare_hyp, pfn); + assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn, 1); + assert_transition_res(-EPERM, __pkvm_host_unshare_hyp, pfn, 1); assert_transition_res(-EPERM, __pkvm_host_share_ffa, pfn, 1); assert_transition_res(-EPERM, __pkvm_host_unshare_ffa, pfn, 1); assert_transition_res(-EPERM, hyp_pin_shared_mem, virt, virt + size);
@@ -1797,15 +1803,15 @@ int __pkvm_ownership_selftest(u64 pfn, u64 pgtable_pfn, unsigned long pgtable_nr selftest_state.hyp = PKVM_NOPAGE; assert_transition_res(0, __pkvm_hyp_donate_host, pfn, 1); assert_transition_res(-EPERM, __pkvm_hyp_donate_host, pfn, 1); - assert_transition_res(-EPERM, __pkvm_host_unshare_hyp, pfn); + assert_transition_res(-EPERM, __pkvm_host_unshare_hyp, pfn, 1); assert_transition_res(-EPERM, __pkvm_host_unshare_ffa, pfn, 1); assert_transition_res(-ENOENT, __pkvm_host_unshare_guest, gfn, 1, vm); assert_transition_res(-EPERM, hyp_pin_shared_mem, virt, virt + size); selftest_state.host = PKVM_PAGE_SHARED_OWNED; selftest_state.hyp = PKVM_PAGE_SHARED_BORROWED; - assert_transition_res(0, __pkvm_host_share_hyp, pfn); - assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn); + assert_transition_res(0, __pkvm_host_share_hyp, pfn, 1); + assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn, 1); assert_transition_res(-EPERM, __pkvm_host_donate_hyp, pfn, 1); assert_transition_res(-EPERM, __pkvm_host_share_ffa, pfn, 1); assert_transition_res(-EPERM, __pkvm_hyp_donate_host, pfn, 1);
@@ -1817,8 +1823,8 @@ int __pkvm_ownership_selftest(u64 pfn, u64 pgtable_pfn, unsigned long pgtable_nr assert_transition_res(0, hyp_pin_shared_mem, virt, virt + size); hyp_unpin_shared_mem(virt, virt + size); WARN_ON(hyp_page_count(virt) != 1); - assert_transition_res(-EBUSY, __pkvm_host_unshare_hyp, pfn); - assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn); + assert_transition_res(-EBUSY, __pkvm_host_unshare_hyp, pfn, 1); + assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn, 1); assert_transition_res(-EPERM, __pkvm_host_donate_hyp, pfn, 1); assert_transition_res(-EPERM, __pkvm_host_share_ffa, pfn, 1); assert_transition_res(-EPERM, __pkvm_hyp_donate_host, pfn, 1);
@@ -1832,15 +1838,15 @@ int __pkvm_ownership_selftest(u64 pfn, u64 pgtable_pfn, unsigned long pgtable_nr selftest_state.host = PKVM_PAGE_OWNED; selftest_state.hyp = PKVM_NOPAGE; - assert_transition_res(0, __pkvm_host_unshare_hyp, pfn); + assert_transition_res(0, __pkvm_host_unshare_hyp, pfn, 1); selftest_state.host = PKVM_PAGE_SHARED_OWNED; selftest_state.hyp = PKVM_NOPAGE; assert_transition_res(0, __pkvm_host_share_ffa, pfn, 1); assert_transition_res(-EPERM, __pkvm_host_share_ffa, pfn, 1); assert_transition_res(-EPERM, __pkvm_host_donate_hyp, pfn, 1); - assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn); - assert_transition_res(-EPERM, __pkvm_host_unshare_hyp, pfn); + assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn, 1); + assert_transition_res(-EPERM, __pkvm_host_unshare_hyp, pfn, 1); assert_transition_res(-EPERM, __pkvm_hyp_donate_host, pfn, 1); assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, 1, vcpu, prot); assert_transition_res(-ENOENT, __pkvm_host_unshare_guest, gfn, 1, vm);
@@ -1858,8 +1864,8 @@ int __pkvm_ownership_selftest(u64 pfn, u64 pgtable_pfn, unsigned long pgtable_nr assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, 1, vcpu, prot); assert_transition_res(-EPERM, __pkvm_host_share_ffa, pfn, 1); assert_transition_res(-EPERM, __pkvm_host_donate_hyp, pfn, 1); - assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn); - assert_transition_res(-EPERM, __pkvm_host_unshare_hyp, pfn); + assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn, 1); + assert_transition_res(-EPERM, __pkvm_host_unshare_hyp, pfn, 1); assert_transition_res(-EPERM, __pkvm_hyp_donate_host, pfn, 1); assert_transition_res(-EPERM, __pkvm_host_donate_guest, pfn, gfn, vcpu); assert_transition_res(-EPERM, hyp_pin_shared_mem, virt, virt + size);
@@ -1884,8 +1890,8 @@ int __pkvm_ownership_selftest(u64 pfn, u64 pgtable_pfn, unsigned long pgtable_nr assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn + 1, 1, vcpu, prot); assert_transition_res(-EPERM, __pkvm_host_share_ffa, pfn, 1); assert_transition_res(-EPERM, __pkvm_host_donate_hyp, pfn, 1); - assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn); - assert_transition_res(-EPERM, __pkvm_host_unshare_hyp, pfn); + assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn, 1); + assert_transition_res(-EPERM, __pkvm_host_unshare_hyp, pfn, 1); assert_transition_res(-EPERM, __pkvm_hyp_donate_host, pfn, 1); selftest_state.host = PKVM_PAGE_SHARED_BORROWED;
@@ -1898,8 +1904,8 @@ int __pkvm_ownership_selftest(u64 pfn, u64 pgtable_pfn, unsigned long pgtable_nr assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn + 1, 1, vcpu, prot); assert_transition_res(-EPERM, __pkvm_host_share_ffa, pfn, 1); assert_transition_res(-EPERM, __pkvm_host_donate_hyp, pfn, 1); - assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn); - assert_transition_res(-EPERM, __pkvm_host_unshare_hyp, pfn); + assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn, 1); + assert_transition_res(-EPERM, __pkvm_host_unshare_hyp, pfn, 1); assert_transition_res(-EPERM, __pkvm_hyp_donate_host, pfn, 1); selftest_state.host = PKVM_NOPAGE;
@@ -1912,8 +1918,8 @@ int __pkvm_ownership_selftest(u64 pfn, u64 pgtable_pfn, unsigned long pgtable_nr assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn + 1, 1, vcpu, prot); assert_transition_res(-EPERM, __pkvm_host_share_ffa, pfn, 1); assert_transition_res(-EPERM, __pkvm_host_donate_hyp, pfn, 1); - assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn); - assert_transition_res(-EPERM, __pkvm_host_unshare_hyp, pfn); + assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn, 1); + assert_transition_res(-EPERM, __pkvm_host_unshare_hyp, pfn, 1); assert_transition_res(-EPERM, __pkvm_hyp_donate_host, pfn, 1); selftest_state.host = PKVM_PAGE_OWNED;
--
2.55.0.1007.g17ff1f9808-goog