Skip to content

Commit f83c41f

Browse files
Marc Zyngieroupton
authored andcommitted
KVM: arm64: Allow userspace to limit NV support to nVHE
NV is hard. No kidding. In order to make things simpler, we have established that NV would support two mutually exclusive configurations: - VHE-only, and supporting recursive virtualisation - nVHE-only, and not supporting recursive virtualisation For that purpose, introduce a new vcpu feature flag that denotes the second configuration. We use this flag to limit the idregs further. Signed-off-by: Marc Zyngier <maz@kernel.org> Reviewed-by: Joey Gouly <joey.gouly@arm.com> Link: https://lore.kernel.org/r/20250220134907.554085-11-maz@kernel.org Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
1 parent 94f296d commit f83c41f

File tree

2 files changed

+27
-2
lines changed

2 files changed

+27
-2
lines changed

arch/arm64/include/uapi/asm/kvm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ struct kvm_regs {
105105
#define KVM_ARM_VCPU_PTRAUTH_ADDRESS 5 /* VCPU uses address authentication */
106106
#define KVM_ARM_VCPU_PTRAUTH_GENERIC 6 /* VCPU uses generic authentication */
107107
#define KVM_ARM_VCPU_HAS_EL2 7 /* Support nested virtualization */
108+
#define KVM_ARM_VCPU_HAS_EL2_E2H0 8 /* Limit NV support to E2H RES0 */
108109

109110
struct kvm_vcpu_init {
110111
__u32 target;

arch/arm64/kvm/nested.c

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ int kvm_vcpu_init_nested(struct kvm_vcpu *vcpu)
5151
struct kvm_s2_mmu *tmp;
5252
int num_mmus, ret = 0;
5353

54+
if (test_bit(KVM_ARM_VCPU_HAS_EL2_E2H0, kvm->arch.vcpu_features) &&
55+
!cpus_have_final_cap(ARM64_HAS_HCR_NV1))
56+
return -EINVAL;
57+
5458
/*
5559
* Let's treat memory allocation failures as benign: If we fail to
5660
* allocate anything, return an error and keep the allocated array
@@ -894,6 +898,9 @@ u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 val)
894898
ID_AA64MMFR1_EL1_HPDS |
895899
ID_AA64MMFR1_EL1_VH |
896900
ID_AA64MMFR1_EL1_VMIDBits);
901+
/* FEAT_E2H0 implies no VHE */
902+
if (test_bit(KVM_ARM_VCPU_HAS_EL2_E2H0, kvm->arch.vcpu_features))
903+
val &= ~ID_AA64MMFR1_EL1_VH;
897904
break;
898905

899906
case SYS_ID_AA64MMFR2_EL1:
@@ -909,8 +916,25 @@ u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 val)
909916
break;
910917

911918
case SYS_ID_AA64MMFR4_EL1:
912-
val = SYS_FIELD_PREP_ENUM(ID_AA64MMFR4_EL1, NV_frac, NV2_ONLY);
913-
val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR4_EL1, E2H0, NI_NV1);
919+
/*
920+
* You get EITHER
921+
*
922+
* - FEAT_VHE without FEAT_E2H0
923+
* - FEAT_NV limited to FEAT_NV2
924+
* - HCR_EL2.NV1 being RES0
925+
*
926+
* OR
927+
*
928+
* - FEAT_E2H0 without FEAT_VHE nor FEAT_NV
929+
*
930+
* Life is too short for anything else.
931+
*/
932+
if (test_bit(KVM_ARM_VCPU_HAS_EL2_E2H0, kvm->arch.vcpu_features)) {
933+
val = 0;
934+
} else {
935+
val = SYS_FIELD_PREP_ENUM(ID_AA64MMFR4_EL1, NV_frac, NV2_ONLY);
936+
val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR4_EL1, E2H0, NI_NV1);
937+
}
914938
break;
915939

916940
case SYS_ID_AA64DFR0_EL1:

0 commit comments

Comments
 (0)