Re: [PATCH v2 2/2] KVM: arm64: Pin the host vCPU before adjusting its PC under pKVM
From: Joey Gouly
Date: Tue Sep 15 2026 - 07:16:36 EST
Hi,
On Tue, Sep 15, 2026 at 08:04:18AM +0100, Fuad Tabba wrote:
> Under pKVM, a page the host shares with EL2 is mapped at EL2 only while
> it's pinned, and the host vCPU is pinned at its first KVM_RUN.
> KVM_SET_VCPU_EVENTS with ext_dabt_pending reaches __kvm_adjust_pc() at
> EL2 before that, and dereferencing the unmapped host vCPU panics the
> hypervisor. Any process holding /dev/kvm on a pKVM host can trigger it.
>
> Pin the host vCPU around the adjustment when no hyp vCPU is loaded for
> it. A loaded hyp vCPU implies it's pinned. A pin fails only for memory
> the host never shared, and the request is then dropped like any other
> bad host pointer.
>
> Fixes: efa1368ba9f4b ("KVM: arm64: Commit exceptions from KVM_SET_VCPU_EVENTS immediately")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Fuad Tabba <fuad.tabba@xxxxxxxxx>
> ---
> arch/arm64/kvm/hyp/nvhe/hyp-main.c | 19 ++++++++++++++++++-
> 1 file changed, 18 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> index 9a3b92e626adb..4cb7347db2514 100644
> --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> @@ -542,8 +542,25 @@ static void handle___pkvm_host_mkyoung_guest(struct kvm_cpu_context *host_ctxt)
> static void handle___kvm_adjust_pc(struct kvm_cpu_context *host_ctxt)
> {
> DECLARE_REG(struct kvm_vcpu *, vcpu, host_ctxt, 1);
> + struct pkvm_hyp_vcpu *hyp_vcpu;
> + struct kvm_vcpu *host_vcpu;
>
> - __kvm_adjust_pc(kern_hyp_va(vcpu));
> + host_vcpu = __get_host_hyp_vcpus(vcpu, &hyp_vcpu);
> + if (host_vcpu) {
> + __kvm_adjust_pc(host_vcpu);
> + return;
> + }
> +
> + /*
> + * With no hyp vCPU loaded for it, the host vCPU may be unpinned,
> + * and so unmapped at EL2: its first run pins it.
* A pin only fails if the memory was never shared, drop the request if
* it is a bad host pointer.
Or something like the commit message says.
> + */
> + host_vcpu = kern_hyp_va(vcpu);
> + if (hyp_pin_shared_mem(host_vcpu, host_vcpu + 1))
> + return;
> +
> + __kvm_adjust_pc(host_vcpu);
> + hyp_unpin_shared_mem(host_vcpu, host_vcpu + 1);
> }
>
> static void handle___kvm_flush_vm_context(struct kvm_cpu_context *host_ctxt)
Reviewed-by: Joey Gouly <joey.gouly@xxxxxxx>
Thanks,
Joey