From: Marc Zyngier <maz@kernel.org>
To: Will Deacon <will@kernel.org>
Cc: kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
Oliver Upton <oupton@kernel.org>, Joey Gouly <joey.gouly@arm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Zenghui Yu <yuzenghui@huawei.com>,
Catalin Marinas <catalin.marinas@arm.com>,
Quentin Perret <qperret@google.com>,
Fuad Tabba <tabba@google.com>,
Vincent Donnefort <vdonnefort@google.com>,
Mostafa Saleh <smostafa@google.com>,
Alexandru Elisei <alexandru.elisei@arm.com>
Subject: Re: [PATCH v3 26/36] KVM: arm64: Return -EFAULT from VCPU_RUN on access to a poisoned pte
Date: Fri, 20 Mar 2026 16:35:44 +0000 [thread overview]
Message-ID: <86341u5uhr.wl-maz@kernel.org> (raw)
In-Reply-To: <20260305144351.17071-27-will@kernel.org>
On Thu, 05 Mar 2026 14:43:39 +0000,
Will Deacon <will@kernel.org> wrote:
>
> If a protected vCPU faults on an IPA which appears to be mapped, query
> the hypervisor to determine whether or not the faulting pte has been
> poisoned by a forceful reclaim. If the pte has been poisoned, return
> -EFAULT back to userspace rather than retrying the instruction forever.
>
> Signed-off-by: Will Deacon <will@kernel.org>
> ---
> arch/arm64/include/asm/kvm_asm.h | 1 +
> arch/arm64/kvm/hyp/include/nvhe/mem_protect.h | 1 +
> arch/arm64/kvm/hyp/nvhe/hyp-main.c | 10 +++++
> arch/arm64/kvm/hyp/nvhe/mem_protect.c | 43 +++++++++++++++++++
> arch/arm64/kvm/pkvm.c | 9 ++--
> 5 files changed, 61 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
> index 04a230e906a7..6c79f7504d80 100644
> --- a/arch/arm64/include/asm/kvm_asm.h
> +++ b/arch/arm64/include/asm/kvm_asm.h
> @@ -90,6 +90,7 @@ enum __kvm_host_smccc_func {
> __KVM_HOST_SMCCC_FUNC___pkvm_unreserve_vm,
> __KVM_HOST_SMCCC_FUNC___pkvm_init_vm,
> __KVM_HOST_SMCCC_FUNC___pkvm_init_vcpu,
> + __KVM_HOST_SMCCC_FUNC___pkvm_vcpu_in_poison_fault,
> __KVM_HOST_SMCCC_FUNC___pkvm_force_reclaim_guest_page,
> __KVM_HOST_SMCCC_FUNC___pkvm_reclaim_dying_guest_page,
> __KVM_HOST_SMCCC_FUNC___pkvm_start_teardown_vm,
> diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
> index f27b037abaf3..5e6cdafcdd69 100644
> --- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
> +++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
> @@ -41,6 +41,7 @@ int __pkvm_hyp_donate_host(u64 pfn, u64 nr_pages);
> int __pkvm_host_share_ffa(u64 pfn, u64 nr_pages);
> int __pkvm_host_unshare_ffa(u64 pfn, u64 nr_pages);
> int __pkvm_host_donate_guest(u64 pfn, u64 gfn, struct pkvm_hyp_vcpu *vcpu);
> +int __pkvm_vcpu_in_poison_fault(struct pkvm_hyp_vcpu *hyp_vcpu);
> int __pkvm_host_force_reclaim_page_guest(phys_addr_t phys);
> int __pkvm_host_reclaim_page_guest(u64 gfn, struct pkvm_hyp_vm *vm);
> int __pkvm_host_share_guest(u64 pfn, u64 gfn, u64 nr_pages, struct pkvm_hyp_vcpu *vcpu,
> diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> index 456c83207717..90e3b14fe287 100644
> --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> @@ -573,6 +573,15 @@ static void handle___pkvm_init_vcpu(struct kvm_cpu_context *host_ctxt)
> cpu_reg(host_ctxt, 1) = __pkvm_init_vcpu(handle, host_vcpu, vcpu_hva);
> }
>
> +static void handle___pkvm_vcpu_in_poison_fault(struct kvm_cpu_context *host_ctxt)
> +{
> + int ret;
> + struct pkvm_hyp_vcpu *hyp_vcpu = pkvm_get_loaded_hyp_vcpu();
> +
> + ret = hyp_vcpu ? __pkvm_vcpu_in_poison_fault(hyp_vcpu) : -EINVAL;
> + cpu_reg(host_ctxt, 1) = ret;
> +}
> +
> static void handle___pkvm_force_reclaim_guest_page(struct kvm_cpu_context *host_ctxt)
> {
> DECLARE_REG(phys_addr_t, phys, host_ctxt, 1);
> @@ -641,6 +650,7 @@ static const hcall_t host_hcall[] = {
> HANDLE_FUNC(__pkvm_unreserve_vm),
> HANDLE_FUNC(__pkvm_init_vm),
> HANDLE_FUNC(__pkvm_init_vcpu),
> + HANDLE_FUNC(__pkvm_vcpu_in_poison_fault),
> HANDLE_FUNC(__pkvm_force_reclaim_guest_page),
> HANDLE_FUNC(__pkvm_reclaim_dying_guest_page),
> HANDLE_FUNC(__pkvm_start_teardown_vm),
> diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> index 4ff31947579b..7f705f662c40 100644
> --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> @@ -890,6 +890,49 @@ static int get_valid_guest_pte(struct pkvm_hyp_vm *vm, u64 ipa, kvm_pte_t *ptep,
> return 0;
> }
>
> +int __pkvm_vcpu_in_poison_fault(struct pkvm_hyp_vcpu *hyp_vcpu)
> +{
> + struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(hyp_vcpu);
> + kvm_pte_t pte;
> + s8 level;
> + u64 ipa;
> + int ret;
> +
> + switch (kvm_vcpu_trap_get_class(&hyp_vcpu->vcpu)) {
> + case ESR_ELx_EC_DABT_LOW:
> + case ESR_ELx_EC_IABT_LOW:
> + if (kvm_vcpu_trap_is_translation_fault(&hyp_vcpu->vcpu))
> + break;
> + fallthrough;
> + default:
> + return -EINVAL;
> + }
> +
> + /*
> + * The host has the faulting IPA when it calls us from the guest
> + * fault handler but we retrieve it ourselves from the FAR so as
> + * to avoid exposing an "oracle" that could reveal data access
> + * patterns of the guest after initial donation of its pages.
> + */
> + ipa = kvm_vcpu_get_fault_ipa(&hyp_vcpu->vcpu);
> + ipa |= kvm_vcpu_get_hfar(&hyp_vcpu->vcpu) & GENMASK(11, 0);
nit: we now have FAR_TO_FIPA_OFFSET() for this.
> +
> + guest_lock_component(vm);
> + ret = kvm_pgtable_get_leaf(&vm->pgt, ipa, &pte, &level);
> + if (ret)
> + goto unlock;
> +
> + if (level != KVM_PGTABLE_LAST_LEVEL) {
> + ret = -EINVAL;
> + goto unlock;
> + }
> +
> + ret = guest_pte_is_poisoned(pte);
> +unlock:
> + guest_unlock_component(vm);
> + return ret;
> +}
> +
> int __pkvm_host_share_hyp(u64 pfn)
> {
> u64 phys = hyp_pfn_to_phys(pfn);
> diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
> index 32294bd21dde..da0a45dab203 100644
> --- a/arch/arm64/kvm/pkvm.c
> +++ b/arch/arm64/kvm/pkvm.c
> @@ -417,10 +417,13 @@ int pkvm_pgtable_stage2_map(struct kvm_pgtable *pgt, u64 addr, u64 size,
> return -EINVAL;
>
> /*
> - * We raced with another vCPU.
> + * We either raced with another vCPU or the guest PTE
> + * has been poisoned by an erroneous host access.
> */
> - if (mapping)
> - return -EAGAIN;
> + if (mapping) {
> + ret = kvm_call_hyp_nvhe(__pkvm_vcpu_in_poison_fault);
> + return ret ? -EFAULT : -EAGAIN;
> + }
I guess this considers that racing against another vcpu is an unlikely
situation, because calling back into EL2 and walking the PTs isn't
exactly cheap.
I wonder if there is a mechanism we could use to directly return this
information to the host at the point of the guest fault. The only
things I can figure out would require the PTE to be valid (access or
permission faults, for example), and that'd break the "full PTE
dedicated to annotations"...
M.
--
Without deviation from the norm, progress is not possible.
next prev parent reply other threads:[~2026-03-20 16:35 UTC|newest]
Thread overview: 63+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-05 14:43 [PATCH v3 00/36] KVM: arm64: Add support for protected guest memory with pKVM Will Deacon
2026-03-05 14:43 ` [PATCH v3 01/36] KVM: arm64: Don't leak stage-2 page-table if VM fails to init under pKVM Will Deacon
2026-03-11 12:48 ` Fuad Tabba
2026-03-05 14:43 ` [PATCH v3 02/36] KVM: arm64: Move handle check into pkvm_pgtable_stage2_destroy_range() Will Deacon
2026-03-11 10:15 ` Fuad Tabba
2026-03-05 14:43 ` [PATCH v3 03/36] KVM: arm64: Rename __pkvm_pgtable_stage2_unmap() Will Deacon
2026-03-11 12:49 ` Fuad Tabba
2026-03-05 14:43 ` [PATCH v3 04/36] KVM: arm64: Don't advertise unsupported features for protected guests Will Deacon
2026-03-11 10:15 ` Fuad Tabba
2026-03-05 14:43 ` [PATCH v3 05/36] KVM: arm64: Expose self-hosted debug regs as RAZ/WI " Will Deacon
2026-03-05 14:43 ` [PATCH v3 06/36] KVM: arm64: Remove is_protected_kvm_enabled() checks from hypercalls Will Deacon
2026-03-11 10:16 ` Fuad Tabba
2026-03-05 14:43 ` [PATCH v3 07/36] KVM: arm64: Ignore MMU notifier callbacks for protected VMs Will Deacon
2026-03-11 12:50 ` Fuad Tabba
2026-03-05 14:43 ` [PATCH v3 08/36] KVM: arm64: Prevent unsupported memslot operations on " Will Deacon
2026-03-11 10:16 ` Fuad Tabba
2026-03-05 14:43 ` [PATCH v3 09/36] KVM: arm64: Ignore -EAGAIN when mapping in pages for the pKVM host Will Deacon
2026-03-11 10:10 ` Fuad Tabba
2026-03-05 14:43 ` [PATCH v3 10/36] KVM: arm64: Split teardown hypercall into two phases Will Deacon
2026-03-11 10:22 ` Fuad Tabba
2026-03-05 14:43 ` [PATCH v3 11/36] KVM: arm64: Introduce __pkvm_host_donate_guest() Will Deacon
2026-03-20 12:38 ` Marc Zyngier
2026-03-23 14:55 ` Will Deacon
2026-03-05 14:43 ` [PATCH v3 12/36] KVM: arm64: Hook up donation hypercall to pkvm_pgtable_stage2_map() Will Deacon
2026-03-05 14:43 ` [PATCH v3 13/36] KVM: arm64: Handle aborts from protected VMs Will Deacon
2026-03-11 10:22 ` Fuad Tabba
2026-03-05 14:43 ` [PATCH v3 14/36] KVM: arm64: Introduce __pkvm_reclaim_dying_guest_page() Will Deacon
2026-03-05 14:43 ` [PATCH v3 15/36] KVM: arm64: Hook up reclaim hypercall to pkvm_pgtable_stage2_destroy() Will Deacon
2026-03-05 14:43 ` [PATCH v3 16/36] KVM: arm64: Factor out pKVM host exception injection logic Will Deacon
2026-03-11 10:12 ` Fuad Tabba
2026-03-05 14:43 ` [PATCH v3 17/36] KVM: arm64: Support translation faults in inject_host_exception() Will Deacon
2026-03-11 10:12 ` Fuad Tabba
2026-03-05 14:43 ` [PATCH v3 18/36] KVM: arm64: Inject SIGSEGV on illegal accesses Will Deacon
2026-03-11 10:13 ` Fuad Tabba
2026-03-05 14:43 ` [PATCH v3 19/36] KVM: arm64: Avoid pointless annotation when mapping host-owned pages Will Deacon
2026-03-05 14:43 ` [PATCH v3 20/36] KVM: arm64: Generalise kvm_pgtable_stage2_set_owner() Will Deacon
2026-03-05 14:43 ` [PATCH v3 21/36] KVM: arm64: Introduce host_stage2_set_owner_metadata_locked() Will Deacon
2026-03-05 14:43 ` [PATCH v3 22/36] KVM: arm64: Change 'pkvm_handle_t' to u16 Will Deacon
2026-03-05 14:43 ` [PATCH v3 23/36] KVM: arm64: Annotate guest donations with handle and gfn in host stage-2 Will Deacon
2026-03-05 14:43 ` [PATCH v3 24/36] KVM: arm64: Introduce hypercall to force reclaim of a protected page Will Deacon
2026-03-05 14:43 ` [PATCH v3 25/36] KVM: arm64: Reclaim faulting page from pKVM in spurious fault handler Will Deacon
2026-03-20 16:20 ` Marc Zyngier
2026-03-21 9:39 ` Marc Zyngier
2026-03-23 14:58 ` Will Deacon
2026-03-05 14:43 ` [PATCH v3 26/36] KVM: arm64: Return -EFAULT from VCPU_RUN on access to a poisoned pte Will Deacon
2026-03-20 16:35 ` Marc Zyngier [this message]
2026-03-23 14:58 ` Will Deacon
2026-03-05 14:43 ` [PATCH v3 27/36] KVM: arm64: Add hvc handler at EL2 for hypercalls from protected VMs Will Deacon
2026-03-05 14:43 ` [PATCH v3 28/36] KVM: arm64: Implement the MEM_SHARE hypercall for " Will Deacon
2026-03-05 14:43 ` [PATCH v3 29/36] KVM: arm64: Implement the MEM_UNSHARE " Will Deacon
2026-03-05 14:43 ` [PATCH v3 30/36] KVM: arm64: Allow userspace to create protected VMs when pKVM is enabled Will Deacon
2026-03-11 10:25 ` Fuad Tabba
2026-03-20 13:22 ` Marc Zyngier
2026-03-23 15:00 ` Will Deacon
2026-03-05 14:43 ` [PATCH v3 31/36] KVM: arm64: Add some initial documentation for pKVM Will Deacon
2026-03-11 10:25 ` Fuad Tabba
2026-03-05 14:43 ` [PATCH v3 32/36] KVM: arm64: Extend pKVM page ownership selftests to cover guest donation Will Deacon
2026-03-05 14:43 ` [PATCH v3 33/36] KVM: arm64: Register 'selftest_vm' in the VM table Will Deacon
2026-03-05 14:43 ` [PATCH v3 34/36] KVM: arm64: Extend pKVM page ownership selftests to cover forced reclaim Will Deacon
2026-03-05 14:43 ` [PATCH v3 35/36] KVM: arm64: Extend pKVM page ownership selftests to cover guest hvcs Will Deacon
2026-03-05 14:43 ` [PATCH v3 36/36] KVM: arm64: Rename PKVM_PAGE_STATE_MASK Will Deacon
2026-03-11 10:26 ` Fuad Tabba
2026-03-11 10:07 ` [PATCH v3 00/36] KVM: arm64: Add support for protected guest memory with pKVM Fuad Tabba
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=86341u5uhr.wl-maz@kernel.org \
--to=maz@kernel.org \
--cc=alexandru.elisei@arm.com \
--cc=catalin.marinas@arm.com \
--cc=joey.gouly@arm.com \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=oupton@kernel.org \
--cc=qperret@google.com \
--cc=smostafa@google.com \
--cc=suzuki.poulose@arm.com \
--cc=tabba@google.com \
--cc=vdonnefort@google.com \
--cc=will@kernel.org \
--cc=yuzenghui@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.