Re: [PATCH v21 05/23] KVM: arm64: Track the type of VM in kvm_arch
From: Marc Zyngier
Date: Fri Oct 02 2026 - 09:41:50 EST
On Fri, 02 Oct 2026 14:05:17 +0100,
Fuad Tabba <tabba@xxxxxxxxxx> wrote:
>
> Hi Marc,
>
> On Fri, 02 Oct 2026 13:57:11 +0100, Marc Zyngier <maz@xxxxxxxxxx> wrote:
> [...]
> > Just to make sure. Is that what you had in mind?
>
> A diff is worth a thousand words :) Yes, that's it. With that, every
> remaining hyp user of vcpu_is_protected() only runs with pKVM, so the
> kern_hyp_va() case in the macro can go too.
Not just that. The whole macro can go, see below (only tested a with
non-protected guest).
M.
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 9e1fa00d96f7c..84703a65bfdd4 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -1520,25 +1520,12 @@ struct kvm *kvm_arch_alloc_vm(void);
#define __KVM_HAVE_ARCH_FLUSH_REMOTE_TLBS_RANGE
#define kvm_vm_is_protected(kvm) ((kvm)->arch.vm_flavor >= __VM_PROTECTED)
-/*
- * Accessing vcpu->kvm from nVHE hyp stub is tricky, as we need to convert the
- * pointer to the hyp VA. With pKVM, the nVHE code runs with the hyp_vcpu,
- * which is populated correctly.
- */
-#define vcpu_is_protected(vcpu) \
- ({ \
- struct kvm *__kvm = READ_ONCE((vcpu)->kvm); \
- bool __protected = false; \
- \
- if (__kvm) { \
- if (is_nvhe_hyp_code() && \
- !is_protected_kvm_enabled()) \
- __kvm = kern_hyp_va(__kvm); \
- \
- __protected = kvm_vm_is_protected(__kvm); \
- } \
- __protected; \
- })
+
+#ifdef __KVM_NVHE_HYPERVISOR__
+#define vcpu_is_protected(vcpu) BUILD_BUG_ON(1)
+#else
+#define vcpu_is_protected(vcpu) kvm_vm_is_protected(vcpu->kvm)
+#endif
#define kvm_vm_is_protected_pkvm(kvm) \
(is_protected_kvm_enabled() && ((kvm)->arch.vm_flavor == VM_PROTECTED_PKVM))
diff --git a/arch/arm64/kvm/hyp/include/nvhe/pkvm.h b/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
index c904647d2f760..ffc99d25955a1 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
@@ -57,7 +57,7 @@ pkvm_hyp_vcpu_to_hyp_vm(struct pkvm_hyp_vcpu *hyp_vcpu)
static inline bool pkvm_hyp_vcpu_is_protected(struct pkvm_hyp_vcpu *hyp_vcpu)
{
- return vcpu_is_protected(&hyp_vcpu->vcpu);
+ return kvm_vm_is_protected(hyp_vcpu->vcpu.kvm);
}
static inline bool pkvm_hyp_vm_is_protected(struct pkvm_hyp_vm *hyp_vm)
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index 7318e3e6a5f36..2a3e6d83682d5 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -217,7 +217,7 @@ static const exit_handler_fn pvm_exit_handlers[] = {
static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu)
{
- if (unlikely(vcpu_is_protected(vcpu)))
+ if (unlikely(vcpu_is_protected_pkvm(vcpu)))
return pvm_exit_handlers;
return hyp_exit_handlers;
@@ -238,7 +238,7 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
* it. The check below is based on the one in
* kvm_arch_vcpu_ioctl_run().
*/
- if (unlikely(vcpu_is_protected(vcpu) && vcpu_mode_is_32bit(vcpu))) {
+ if (unlikely(vcpu_is_protected_pkvm(vcpu) && vcpu_mode_is_32bit(vcpu))) {
/*
* As we have caught the guest red-handed, decide that it isn't
* fit for purpose anymore by making the vcpu invalid. The VMM
diff --git a/arch/arm64/kvm/hyp/nvhe/timer-sr.c b/arch/arm64/kvm/hyp/nvhe/timer-sr.c
index 9930657169133..17bd1ff621ab6 100644
--- a/arch/arm64/kvm/hyp/nvhe/timer-sr.c
+++ b/arch/arm64/kvm/hyp/nvhe/timer-sr.c
@@ -48,7 +48,7 @@ void __timer_enable_traps(struct kvm_vcpu *vcpu)
* or running a protected VM (we don't offset anything in this case).
*/
clr = CNTHCTL_EL1PCEN;
- if (vcpu_is_protected(vcpu) ||
+ if (vcpu_is_protected_pkvm(vcpu) ||
!timer_get_offset(vcpu_ptimer(vcpu)))
set |= CNTHCTL_EL1PCTEN;
else
--
Without deviation from the norm, progress is not possible.