Documentation/virt/kvm/devices/vm.rst | 11 ++++++++++ arch/arm64/kvm/hypercalls.c | 39 +++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+)
With protected VMs, forwarding guest HVC/SMCs happens at two interfaces:
pKVM [EL2] <--> KVM [EL1] <--> VMM [EL0]
so it might be possible for EL0 to successfully register with EL1 to
handle guest SMCCC calls but never see the KVM_EXIT_HYPERCALL, even if
the calls are properly issued by the guest, due to EL2 handling them so
that (host) EL1 never gets a chance to exit to EL0.
Instead, avoid that confusing situation and make userspace fail early by
disallowing KVM_ARM_VM_SMCCC_FILTER-ing calls from protected guests in
the KVM FID range (which pKVM re-uses).
DEN0028 defines 65536 "Vendor Specific Hypervisor Service Calls":
- the first ARM_SMCCC_KVM_NUM_FUNCS (128) can be custom-defined
- the following 3 are currently standardized
- the rest is "reserved for future expansion"
so reserve them all, like commit 821d935c87bc ("KVM: arm64: Introduce
support for userspace SMCCC filtering") with the Arm Architecture Calls.
Alternatively, we could have only reserved the ARM_SMCCC_KVM_NUM_FUNCS
(or even a subset of it) and the "Call UID Query" but that would have
risked future conflicts between that uAPI and an extension of the SMCCC
or of the pKVM ABI.
Signed-off-by: Pierre-Clément Tosi <ptosi@google.com>
---
Documentation/virt/kvm/devices/vm.rst | 11 ++++++++++
arch/arm64/kvm/hypercalls.c | 39 +++++++++++++++++++++++++++++++++++
2 files changed, 50 insertions(+)
diff --git a/Documentation/virt/kvm/devices/vm.rst b/Documentation/virt/kvm/devices/vm.rst
index a4d39fa1b0834b090318250db3b670b0b3174259..9ed4b7afe022023346d4835d33a901e557fc4765 100644
--- a/Documentation/virt/kvm/devices/vm.rst
+++ b/Documentation/virt/kvm/devices/vm.rst
@@ -400,3 +400,14 @@ will reject attempts to define a filter for any portion of these ranges:
0x8000_0000 0x8000_FFFF
0xC000_0000 0xC000_FFFF
=========== ===============
+
+Protected KVM (pKVM) reserves the 'Vendor Specific Hypervisor Service Calls'
+range of function IDs and will reject attempts to define a filter for any
+portion of these ranges for a protected VM (``KVM_VM_TYPE_ARM_PROTECTED``):
+
+ =========== ===============
+ Start End (inclusive)
+ =========== ===============
+ 0x8600_0000 0x8600_FFFF
+ 0xC600_0000 0xC600_FFFF
+ =========== ===============
diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c
index 58c5fe7d757274d9079606fcc378485980c6c0f8..5ddcdd70a6b280914048e7683dafb778d0f24658 100644
--- a/arch/arm64/kvm/hypercalls.c
+++ b/arch/arm64/kvm/hypercalls.c
@@ -135,6 +135,21 @@ static bool kvm_smccc_test_fw_bmap(struct kvm_vcpu *vcpu, u32 func_id)
ARM_SMCCC_SMC_64, \
0, ARM_SMCCC_FUNC_MASK)
+#define SMC32_VHYP_RANGE_BEGIN ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID
+#define SMC32_VHYP_RANGE_END ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
+ ARM_SMCCC_SMC_32, \
+ ARM_SMCCC_OWNER_VENDOR_HYP, \
+ ARM_SMCCC_FUNC_MASK)
+
+#define SMC64_VHYP_RANGE_BEGIN ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
+ ARM_SMCCC_SMC_64, \
+ ARM_SMCCC_OWNER_VENDOR_HYP, \
+ 0)
+#define SMC64_VHYP_RANGE_END ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
+ ARM_SMCCC_SMC_64, \
+ ARM_SMCCC_OWNER_VENDOR_HYP, \
+ ARM_SMCCC_FUNC_MASK)
+
static int kvm_smccc_filter_insert_reserved(struct kvm *kvm)
{
int r;
@@ -158,6 +173,30 @@ static int kvm_smccc_filter_insert_reserved(struct kvm *kvm)
if (r)
goto out_destroy;
+ /*
+ * Prevent userspace from registering to handle any SMCCC call in the
+ * vendor hypervisor range for pVMs, avoiding the confusion of guest
+ * calls seemingly not resulting in KVM_RUN exits because pKVM handles
+ * them without ever returning to the host. This is NOT for security.
+ */
+ if (kvm_vm_is_protected(kvm)) {
+ r = mtree_insert_range(&kvm->arch.smccc_filter,
+ SMC32_VHYP_RANGE_BEGIN,
+ SMC32_VHYP_RANGE_END,
+ xa_mk_value(KVM_SMCCC_FILTER_HANDLE),
+ GFP_KERNEL_ACCOUNT);
+ if (r)
+ goto out_destroy;
+
+ r = mtree_insert_range(&kvm->arch.smccc_filter,
+ SMC64_VHYP_RANGE_BEGIN,
+ SMC64_VHYP_RANGE_END,
+ xa_mk_value(KVM_SMCCC_FILTER_HANDLE),
+ GFP_KERNEL_ACCOUNT);
+ if (r)
+ goto out_destroy;
+ }
+
return 0;
out_destroy:
mtree_destroy(&kvm->arch.smccc_filter);
---
base-commit: 7d0a66e4bb9081d75c82ec4957c50034cb0ea449
change-id: 20251201-smccc-filter-588ddf12b355
Best regards,
--
Pierre-Clément Tosi <ptosi@google.com>
On Mon, 01 Dec 2025 18:19:52 +0000,
"=?utf-8?q?Pierre-Cl=C3=A9ment_Tosi?=" <ptosi@google.com> wrote:
>
> With protected VMs, forwarding guest HVC/SMCs happens at two interfaces:
>
> pKVM [EL2] <--> KVM [EL1] <--> VMM [EL0]
>
> so it might be possible for EL0 to successfully register with EL1 to
> handle guest SMCCC calls but never see the KVM_EXIT_HYPERCALL, even if
> the calls are properly issued by the guest, due to EL2 handling them so
> that (host) EL1 never gets a chance to exit to EL0.
>
> Instead, avoid that confusing situation and make userspace fail early by
> disallowing KVM_ARM_VM_SMCCC_FILTER-ing calls from protected guests in
> the KVM FID range (which pKVM re-uses).
>
> DEN0028 defines 65536 "Vendor Specific Hypervisor Service Calls":
>
> - the first ARM_SMCCC_KVM_NUM_FUNCS (128) can be custom-defined
> - the following 3 are currently standardized
> - the rest is "reserved for future expansion"
>
> so reserve them all, like commit 821d935c87bc ("KVM: arm64: Introduce
> support for userspace SMCCC filtering") with the Arm Architecture Calls.
I don't think preventing all hypercalls from reaching userspace is
acceptable from an API perspective. For example, it is highly expected
that the hypercall that exposes the various MIDR/REVIDR/AIDR that the
guest can be expected to run on is handled in userspace.
Given that this hypercall is critical to the correct behaviour of a
guest in an asymmetric system, you can't really forbid it. If you
don't want it, that's fine -- don't implement it in your VMM.
But I fully expect pKVM to inherit the existing APIs by virtue of
being a KVM backend.
> Alternatively, we could have only reserved the ARM_SMCCC_KVM_NUM_FUNCS
> (or even a subset of it) and the "Call UID Query" but that would have
> risked future conflicts between that uAPI and an extension of the SMCCC
> or of the pKVM ABI.
I disagree. The only ones you can legitimately block are the ones that
are earmarked for pKVM itself (2-63), and only these. Everything else
should make it to userspace if the guest and the VMM agree to do so.
This is part of the KVM ABI, and pKVM should be fixed.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
Hi Marc,
Thanks for your quick review!
On Mon, Dec 01, 2025 at 06:48:48PM +0000, Marc Zyngier wrote:
> On Mon, 01 Dec 2025 18:19:52 +0000,
> "=?utf-8?q?Pierre-Cl=C3=A9ment_Tosi?=" <ptosi@google.com> wrote:
> >
> > With protected VMs, forwarding guest HVC/SMCs happens at two interfaces:
> >
> > pKVM [EL2] <--> KVM [EL1] <--> VMM [EL0]
> >
> > so it might be possible for EL0 to successfully register with EL1 to
> > handle guest SMCCC calls but never see the KVM_EXIT_HYPERCALL, even if
> > the calls are properly issued by the guest, due to EL2 handling them so
> > that (host) EL1 never gets a chance to exit to EL0.
> >
> > Instead, avoid that confusing situation and make userspace fail early by
> > disallowing KVM_ARM_VM_SMCCC_FILTER-ing calls from protected guests in
> > the KVM FID range (which pKVM re-uses).
> >
> > DEN0028 defines 65536 "Vendor Specific Hypervisor Service Calls":
> >
> > - the first ARM_SMCCC_KVM_NUM_FUNCS (128) can be custom-defined
> > - the following 3 are currently standardized
> > - the rest is "reserved for future expansion"
> >
> > so reserve them all, like commit 821d935c87bc ("KVM: arm64: Introduce
> > support for userspace SMCCC filtering") with the Arm Architecture Calls.
>
> I don't think preventing all hypercalls from reaching userspace is
> acceptable from an API perspective. For example, it is highly expected
> that the hypercall that exposes the various MIDR/REVIDR/AIDR that the
> guest can be expected to run on is handled in userspace.
>
> Given that this hypercall is critical to the correct behaviour of a
> guest in an asymmetric system, you can't really forbid it. If you
> don't want it, that's fine -- don't implement it in your VMM.
>
> But I fully expect pKVM to inherit the existing APIs by virtue of
> being a KVM backend.
>
> > Alternatively, we could have only reserved the ARM_SMCCC_KVM_NUM_FUNCS
> > (or even a subset of it) and the "Call UID Query" but that would have
> > risked future conflicts between that uAPI and an extension of the SMCCC
> > or of the pKVM ABI.
>
> I disagree. The only ones you can legitimately block are the ones that
> are earmarked for pKVM itself (2-63), and only these. Everything else
> should make it to userspace if the guest and the VMM agree to do so.
Sounds good, I'll limit v2 to these FIDs and the "Call UID Query" (unavoidable).
>
> This is part of the KVM ABI, and pKVM should be fixed.
I agree. In particular on not restricting {S,G}ET_ONE_REG to a point where the
KVM uAPI for SMCCC filtering can't be supported, as some experimental Linux
forks might [1] have done! I couldn't find the corresponding patches on LKML to
contribute this feedback to, so something to keep in mind when they come in :)
[1]: https://r.android.com/q/I1c7bc93ebe0bfb597cca5c4284ceb7fd53e4713c
>
> Thanks,
>
> M.
>
> --
> Without deviation from the norm, progress is not possible.
Thanks!
--
Pierre
© 2016 - 2025 Red Hat, Inc.