[PATCH v2 2/2] KVM: arm64: Pin the host vCPU before adjusting its PC under pKVM
From: Fuad Tabba
Date: Tue Sep 15 2026 - 03:06:04 EST
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.
+ */
+ 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)
--
2.39.5