Skip to content

Commit b130a8f

Browse files
Marc Zyngierwilldeacon
authored andcommitted
KVM: arm64: Check advertised Stage-2 page size capability
With ARMv8.5-GTG, the hardware (or more likely a hypervisor) can advertise the supported Stage-2 page sizes. Let's check this at boot time. Reviewed-by: Suzuki K Poulose <[email protected]> Reviewed-by: Alexandru Elisei <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Signed-off-by: Will Deacon <[email protected]>
1 parent 3577dd3 commit b130a8f

File tree

5 files changed

+58
-6
lines changed

5 files changed

+58
-6
lines changed

arch/arm64/include/asm/kvm_host.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ static inline int kvm_arm_have_ssbd(void)
670670
void kvm_vcpu_load_sysregs(struct kvm_vcpu *vcpu);
671671
void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu);
672672

673-
void kvm_set_ipa_limit(void);
673+
int kvm_set_ipa_limit(void);
674674

675675
#define __KVM_HAVE_ARCH_VM_ALLOC
676676
struct kvm *kvm_arch_alloc_vm(void);

arch/arm64/include/asm/sysreg.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,9 @@
703703
#define ID_AA64ZFR0_SVEVER_SVE2 0x1
704704

705705
/* id_aa64mmfr0 */
706+
#define ID_AA64MMFR0_TGRAN4_2_SHIFT 40
707+
#define ID_AA64MMFR0_TGRAN64_2_SHIFT 36
708+
#define ID_AA64MMFR0_TGRAN16_2_SHIFT 32
706709
#define ID_AA64MMFR0_TGRAN4_SHIFT 28
707710
#define ID_AA64MMFR0_TGRAN64_SHIFT 24
708711
#define ID_AA64MMFR0_TGRAN16_SHIFT 20

arch/arm64/kernel/cpufeature.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,24 @@ static const struct arm64_ftr_bits ftr_id_aa64zfr0[] = {
267267
};
268268

269269
static const struct arm64_ftr_bits ftr_id_aa64mmfr0[] = {
270+
/*
271+
* Page size not being supported at Stage-2 is not fatal. You
272+
* just give up KVM if PAGE_SIZE isn't supported there. Go fix
273+
* your favourite nesting hypervisor.
274+
*
275+
* There is a small corner case where the hypervisor explicitly
276+
* advertises a given granule size at Stage-2 (value 2) on some
277+
* vCPUs, and uses the fallback to Stage-1 (value 0) for other
278+
* vCPUs. Although this is not forbidden by the architecture, it
279+
* indicates that the hypervisor is being silly (or buggy).
280+
*
281+
* We make no effort to cope with this and pretend that if these
282+
* fields are inconsistent across vCPUs, then it isn't worth
283+
* trying to bring KVM up.
284+
*/
285+
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN4_2_SHIFT, 4, 1),
286+
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN64_2_SHIFT, 4, 1),
287+
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN16_2_SHIFT, 4, 1),
270288
/*
271289
* We already refuse to boot CPUs that don't support our configured
272290
* page size, so we can only detect mismatches for a page size other

arch/arm64/kvm/reset.c

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,14 +337,45 @@ u32 get_kvm_ipa_limit(void)
337337
return kvm_ipa_limit;
338338
}
339339

340-
void kvm_set_ipa_limit(void)
340+
int kvm_set_ipa_limit(void)
341341
{
342-
unsigned int ipa_max, pa_max, va_max, parange;
342+
unsigned int ipa_max, pa_max, va_max, parange, tgran_2;
343343
u64 mmfr0;
344344

345345
mmfr0 = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1);
346346
parange = cpuid_feature_extract_unsigned_field(mmfr0,
347347
ID_AA64MMFR0_PARANGE_SHIFT);
348+
349+
/*
350+
* Check with ARMv8.5-GTG that our PAGE_SIZE is supported at
351+
* Stage-2. If not, things will stop very quickly.
352+
*/
353+
switch (PAGE_SIZE) {
354+
default:
355+
case SZ_4K:
356+
tgran_2 = ID_AA64MMFR0_TGRAN4_2_SHIFT;
357+
break;
358+
case SZ_16K:
359+
tgran_2 = ID_AA64MMFR0_TGRAN16_2_SHIFT;
360+
break;
361+
case SZ_64K:
362+
tgran_2 = ID_AA64MMFR0_TGRAN64_2_SHIFT;
363+
break;
364+
}
365+
366+
switch (cpuid_feature_extract_unsigned_field(mmfr0, tgran_2)) {
367+
default:
368+
case 1:
369+
kvm_err("PAGE_SIZE not supported at Stage-2, giving up\n");
370+
return -EINVAL;
371+
case 0:
372+
kvm_debug("PAGE_SIZE supported at Stage-2 (default)\n");
373+
break;
374+
case 2:
375+
kvm_debug("PAGE_SIZE supported at Stage-2 (advertised)\n");
376+
break;
377+
}
378+
348379
pa_max = id_aa64mmfr0_parange_to_phys_shift(parange);
349380

350381
/* Clamp the IPA limit to the PA size supported by the kernel */
@@ -378,6 +409,8 @@ void kvm_set_ipa_limit(void)
378409
"KVM IPA limit (%d bit) is smaller than default size\n", ipa_max);
379410
kvm_ipa_limit = ipa_max;
380411
kvm_info("IPA Size Limit: %dbits\n", kvm_ipa_limit);
412+
413+
return 0;
381414
}
382415

383416
/*

virt/kvm/arm/arm.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,9 +1387,7 @@ static inline void hyp_cpu_pm_exit(void)
13871387

13881388
static int init_common_resources(void)
13891389
{
1390-
kvm_set_ipa_limit();
1391-
1392-
return 0;
1390+
return kvm_set_ipa_limit();
13931391
}
13941392

13951393
static int init_subsystems(void)

0 commit comments

Comments
 (0)