xref: /kernel/linux/linux-6.6/arch/arm64/kvm/reset.c (revision 62306a36)
162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2012,2013 - ARM Ltd
462306a36Sopenharmony_ci * Author: Marc Zyngier <marc.zyngier@arm.com>
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Derived from arch/arm/kvm/reset.c
762306a36Sopenharmony_ci * Copyright (C) 2012 - Virtual Open Systems and Columbia University
862306a36Sopenharmony_ci * Author: Christoffer Dall <c.dall@virtualopensystems.com>
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/errno.h>
1262306a36Sopenharmony_ci#include <linux/kernel.h>
1362306a36Sopenharmony_ci#include <linux/kvm_host.h>
1462306a36Sopenharmony_ci#include <linux/kvm.h>
1562306a36Sopenharmony_ci#include <linux/hw_breakpoint.h>
1662306a36Sopenharmony_ci#include <linux/slab.h>
1762306a36Sopenharmony_ci#include <linux/string.h>
1862306a36Sopenharmony_ci#include <linux/types.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#include <kvm/arm_arch_timer.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#include <asm/cpufeature.h>
2362306a36Sopenharmony_ci#include <asm/cputype.h>
2462306a36Sopenharmony_ci#include <asm/fpsimd.h>
2562306a36Sopenharmony_ci#include <asm/ptrace.h>
2662306a36Sopenharmony_ci#include <asm/kvm_arm.h>
2762306a36Sopenharmony_ci#include <asm/kvm_asm.h>
2862306a36Sopenharmony_ci#include <asm/kvm_emulate.h>
2962306a36Sopenharmony_ci#include <asm/kvm_mmu.h>
3062306a36Sopenharmony_ci#include <asm/kvm_nested.h>
3162306a36Sopenharmony_ci#include <asm/virt.h>
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/* Maximum phys_shift supported for any VM on this host */
3462306a36Sopenharmony_cistatic u32 __ro_after_init kvm_ipa_limit;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci/*
3762306a36Sopenharmony_ci * ARMv8 Reset Values
3862306a36Sopenharmony_ci */
3962306a36Sopenharmony_ci#define VCPU_RESET_PSTATE_EL1	(PSR_MODE_EL1h | PSR_A_BIT | PSR_I_BIT | \
4062306a36Sopenharmony_ci				 PSR_F_BIT | PSR_D_BIT)
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#define VCPU_RESET_PSTATE_EL2	(PSR_MODE_EL2h | PSR_A_BIT | PSR_I_BIT | \
4362306a36Sopenharmony_ci				 PSR_F_BIT | PSR_D_BIT)
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#define VCPU_RESET_PSTATE_SVC	(PSR_AA32_MODE_SVC | PSR_AA32_A_BIT | \
4662306a36Sopenharmony_ci				 PSR_AA32_I_BIT | PSR_AA32_F_BIT)
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ciunsigned int __ro_after_init kvm_sve_max_vl;
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ciint __init kvm_arm_init_sve(void)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	if (system_supports_sve()) {
5362306a36Sopenharmony_ci		kvm_sve_max_vl = sve_max_virtualisable_vl();
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci		/*
5662306a36Sopenharmony_ci		 * The get_sve_reg()/set_sve_reg() ioctl interface will need
5762306a36Sopenharmony_ci		 * to be extended with multiple register slice support in
5862306a36Sopenharmony_ci		 * order to support vector lengths greater than
5962306a36Sopenharmony_ci		 * VL_ARCH_MAX:
6062306a36Sopenharmony_ci		 */
6162306a36Sopenharmony_ci		if (WARN_ON(kvm_sve_max_vl > VL_ARCH_MAX))
6262306a36Sopenharmony_ci			kvm_sve_max_vl = VL_ARCH_MAX;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci		/*
6562306a36Sopenharmony_ci		 * Don't even try to make use of vector lengths that
6662306a36Sopenharmony_ci		 * aren't available on all CPUs, for now:
6762306a36Sopenharmony_ci		 */
6862306a36Sopenharmony_ci		if (kvm_sve_max_vl < sve_max_vl())
6962306a36Sopenharmony_ci			pr_warn("KVM: SVE vector length for guests limited to %u bytes\n",
7062306a36Sopenharmony_ci				kvm_sve_max_vl);
7162306a36Sopenharmony_ci	}
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	return 0;
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistatic int kvm_vcpu_enable_sve(struct kvm_vcpu *vcpu)
7762306a36Sopenharmony_ci{
7862306a36Sopenharmony_ci	if (!system_supports_sve())
7962306a36Sopenharmony_ci		return -EINVAL;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	vcpu->arch.sve_max_vl = kvm_sve_max_vl;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	/*
8462306a36Sopenharmony_ci	 * Userspace can still customize the vector lengths by writing
8562306a36Sopenharmony_ci	 * KVM_REG_ARM64_SVE_VLS.  Allocation is deferred until
8662306a36Sopenharmony_ci	 * kvm_arm_vcpu_finalize(), which freezes the configuration.
8762306a36Sopenharmony_ci	 */
8862306a36Sopenharmony_ci	vcpu_set_flag(vcpu, GUEST_HAS_SVE);
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	return 0;
9162306a36Sopenharmony_ci}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci/*
9462306a36Sopenharmony_ci * Finalize vcpu's maximum SVE vector length, allocating
9562306a36Sopenharmony_ci * vcpu->arch.sve_state as necessary.
9662306a36Sopenharmony_ci */
9762306a36Sopenharmony_cistatic int kvm_vcpu_finalize_sve(struct kvm_vcpu *vcpu)
9862306a36Sopenharmony_ci{
9962306a36Sopenharmony_ci	void *buf;
10062306a36Sopenharmony_ci	unsigned int vl;
10162306a36Sopenharmony_ci	size_t reg_sz;
10262306a36Sopenharmony_ci	int ret;
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	vl = vcpu->arch.sve_max_vl;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	/*
10762306a36Sopenharmony_ci	 * Responsibility for these properties is shared between
10862306a36Sopenharmony_ci	 * kvm_arm_init_sve(), kvm_vcpu_enable_sve() and
10962306a36Sopenharmony_ci	 * set_sve_vls().  Double-check here just to be sure:
11062306a36Sopenharmony_ci	 */
11162306a36Sopenharmony_ci	if (WARN_ON(!sve_vl_valid(vl) || vl > sve_max_virtualisable_vl() ||
11262306a36Sopenharmony_ci		    vl > VL_ARCH_MAX))
11362306a36Sopenharmony_ci		return -EIO;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	reg_sz = vcpu_sve_state_size(vcpu);
11662306a36Sopenharmony_ci	buf = kzalloc(reg_sz, GFP_KERNEL_ACCOUNT);
11762306a36Sopenharmony_ci	if (!buf)
11862306a36Sopenharmony_ci		return -ENOMEM;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	ret = kvm_share_hyp(buf, buf + reg_sz);
12162306a36Sopenharmony_ci	if (ret) {
12262306a36Sopenharmony_ci		kfree(buf);
12362306a36Sopenharmony_ci		return ret;
12462306a36Sopenharmony_ci	}
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	vcpu->arch.sve_state = buf;
12762306a36Sopenharmony_ci	vcpu_set_flag(vcpu, VCPU_SVE_FINALIZED);
12862306a36Sopenharmony_ci	return 0;
12962306a36Sopenharmony_ci}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ciint kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu, int feature)
13262306a36Sopenharmony_ci{
13362306a36Sopenharmony_ci	switch (feature) {
13462306a36Sopenharmony_ci	case KVM_ARM_VCPU_SVE:
13562306a36Sopenharmony_ci		if (!vcpu_has_sve(vcpu))
13662306a36Sopenharmony_ci			return -EINVAL;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci		if (kvm_arm_vcpu_sve_finalized(vcpu))
13962306a36Sopenharmony_ci			return -EPERM;
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci		return kvm_vcpu_finalize_sve(vcpu);
14262306a36Sopenharmony_ci	}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	return -EINVAL;
14562306a36Sopenharmony_ci}
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_cibool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu)
14862306a36Sopenharmony_ci{
14962306a36Sopenharmony_ci	if (vcpu_has_sve(vcpu) && !kvm_arm_vcpu_sve_finalized(vcpu))
15062306a36Sopenharmony_ci		return false;
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	return true;
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_civoid kvm_arm_vcpu_destroy(struct kvm_vcpu *vcpu)
15662306a36Sopenharmony_ci{
15762306a36Sopenharmony_ci	void *sve_state = vcpu->arch.sve_state;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	kvm_vcpu_unshare_task_fp(vcpu);
16062306a36Sopenharmony_ci	kvm_unshare_hyp(vcpu, vcpu + 1);
16162306a36Sopenharmony_ci	if (sve_state)
16262306a36Sopenharmony_ci		kvm_unshare_hyp(sve_state, sve_state + vcpu_sve_state_size(vcpu));
16362306a36Sopenharmony_ci	kfree(sve_state);
16462306a36Sopenharmony_ci	kfree(vcpu->arch.ccsidr);
16562306a36Sopenharmony_ci}
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_cistatic void kvm_vcpu_reset_sve(struct kvm_vcpu *vcpu)
16862306a36Sopenharmony_ci{
16962306a36Sopenharmony_ci	if (vcpu_has_sve(vcpu))
17062306a36Sopenharmony_ci		memset(vcpu->arch.sve_state, 0, vcpu_sve_state_size(vcpu));
17162306a36Sopenharmony_ci}
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_cistatic int kvm_vcpu_enable_ptrauth(struct kvm_vcpu *vcpu)
17462306a36Sopenharmony_ci{
17562306a36Sopenharmony_ci	/*
17662306a36Sopenharmony_ci	 * For now make sure that both address/generic pointer authentication
17762306a36Sopenharmony_ci	 * features are requested by the userspace together and the system
17862306a36Sopenharmony_ci	 * supports these capabilities.
17962306a36Sopenharmony_ci	 */
18062306a36Sopenharmony_ci	if (!test_bit(KVM_ARM_VCPU_PTRAUTH_ADDRESS, vcpu->arch.features) ||
18162306a36Sopenharmony_ci	    !test_bit(KVM_ARM_VCPU_PTRAUTH_GENERIC, vcpu->arch.features) ||
18262306a36Sopenharmony_ci	    !system_has_full_ptr_auth())
18362306a36Sopenharmony_ci		return -EINVAL;
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	vcpu_set_flag(vcpu, GUEST_HAS_PTRAUTH);
18662306a36Sopenharmony_ci	return 0;
18762306a36Sopenharmony_ci}
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci/**
19062306a36Sopenharmony_ci * kvm_reset_vcpu - sets core registers and sys_regs to reset value
19162306a36Sopenharmony_ci * @vcpu: The VCPU pointer
19262306a36Sopenharmony_ci *
19362306a36Sopenharmony_ci * This function sets the registers on the virtual CPU struct to their
19462306a36Sopenharmony_ci * architecturally defined reset values, except for registers whose reset is
19562306a36Sopenharmony_ci * deferred until kvm_arm_vcpu_finalize().
19662306a36Sopenharmony_ci *
19762306a36Sopenharmony_ci * Note: This function can be called from two paths: The KVM_ARM_VCPU_INIT
19862306a36Sopenharmony_ci * ioctl or as part of handling a request issued by another VCPU in the PSCI
19962306a36Sopenharmony_ci * handling code.  In the first case, the VCPU will not be loaded, and in the
20062306a36Sopenharmony_ci * second case the VCPU will be loaded.  Because this function operates purely
20162306a36Sopenharmony_ci * on the memory-backed values of system registers, we want to do a full put if
20262306a36Sopenharmony_ci * we were loaded (handling a request) and load the values back at the end of
20362306a36Sopenharmony_ci * the function.  Otherwise we leave the state alone.  In both cases, we
20462306a36Sopenharmony_ci * disable preemption around the vcpu reset as we would otherwise race with
20562306a36Sopenharmony_ci * preempt notifiers which also call put/load.
20662306a36Sopenharmony_ci */
20762306a36Sopenharmony_ciint kvm_reset_vcpu(struct kvm_vcpu *vcpu)
20862306a36Sopenharmony_ci{
20962306a36Sopenharmony_ci	struct vcpu_reset_state reset_state;
21062306a36Sopenharmony_ci	int ret;
21162306a36Sopenharmony_ci	bool loaded;
21262306a36Sopenharmony_ci	u32 pstate;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	spin_lock(&vcpu->arch.mp_state_lock);
21562306a36Sopenharmony_ci	reset_state = vcpu->arch.reset_state;
21662306a36Sopenharmony_ci	vcpu->arch.reset_state.reset = false;
21762306a36Sopenharmony_ci	spin_unlock(&vcpu->arch.mp_state_lock);
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	/* Reset PMU outside of the non-preemptible section */
22062306a36Sopenharmony_ci	kvm_pmu_vcpu_reset(vcpu);
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	preempt_disable();
22362306a36Sopenharmony_ci	loaded = (vcpu->cpu != -1);
22462306a36Sopenharmony_ci	if (loaded)
22562306a36Sopenharmony_ci		kvm_arch_vcpu_put(vcpu);
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	/* Disallow NV+SVE for the time being */
22862306a36Sopenharmony_ci	if (vcpu_has_nv(vcpu) && vcpu_has_feature(vcpu, KVM_ARM_VCPU_SVE)) {
22962306a36Sopenharmony_ci		ret = -EINVAL;
23062306a36Sopenharmony_ci		goto out;
23162306a36Sopenharmony_ci	}
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	if (!kvm_arm_vcpu_sve_finalized(vcpu)) {
23462306a36Sopenharmony_ci		if (test_bit(KVM_ARM_VCPU_SVE, vcpu->arch.features)) {
23562306a36Sopenharmony_ci			ret = kvm_vcpu_enable_sve(vcpu);
23662306a36Sopenharmony_ci			if (ret)
23762306a36Sopenharmony_ci				goto out;
23862306a36Sopenharmony_ci		}
23962306a36Sopenharmony_ci	} else {
24062306a36Sopenharmony_ci		kvm_vcpu_reset_sve(vcpu);
24162306a36Sopenharmony_ci	}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	if (test_bit(KVM_ARM_VCPU_PTRAUTH_ADDRESS, vcpu->arch.features) ||
24462306a36Sopenharmony_ci	    test_bit(KVM_ARM_VCPU_PTRAUTH_GENERIC, vcpu->arch.features)) {
24562306a36Sopenharmony_ci		if (kvm_vcpu_enable_ptrauth(vcpu)) {
24662306a36Sopenharmony_ci			ret = -EINVAL;
24762306a36Sopenharmony_ci			goto out;
24862306a36Sopenharmony_ci		}
24962306a36Sopenharmony_ci	}
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	if (vcpu_el1_is_32bit(vcpu))
25262306a36Sopenharmony_ci		pstate = VCPU_RESET_PSTATE_SVC;
25362306a36Sopenharmony_ci	else if (vcpu_has_nv(vcpu))
25462306a36Sopenharmony_ci		pstate = VCPU_RESET_PSTATE_EL2;
25562306a36Sopenharmony_ci	else
25662306a36Sopenharmony_ci		pstate = VCPU_RESET_PSTATE_EL1;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	if (kvm_vcpu_has_pmu(vcpu) && !kvm_arm_support_pmu_v3()) {
25962306a36Sopenharmony_ci		ret = -EINVAL;
26062306a36Sopenharmony_ci		goto out;
26162306a36Sopenharmony_ci	}
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	/* Reset core registers */
26462306a36Sopenharmony_ci	memset(vcpu_gp_regs(vcpu), 0, sizeof(*vcpu_gp_regs(vcpu)));
26562306a36Sopenharmony_ci	memset(&vcpu->arch.ctxt.fp_regs, 0, sizeof(vcpu->arch.ctxt.fp_regs));
26662306a36Sopenharmony_ci	vcpu->arch.ctxt.spsr_abt = 0;
26762306a36Sopenharmony_ci	vcpu->arch.ctxt.spsr_und = 0;
26862306a36Sopenharmony_ci	vcpu->arch.ctxt.spsr_irq = 0;
26962306a36Sopenharmony_ci	vcpu->arch.ctxt.spsr_fiq = 0;
27062306a36Sopenharmony_ci	vcpu_gp_regs(vcpu)->pstate = pstate;
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	/* Reset system registers */
27362306a36Sopenharmony_ci	kvm_reset_sys_regs(vcpu);
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	/*
27662306a36Sopenharmony_ci	 * Additional reset state handling that PSCI may have imposed on us.
27762306a36Sopenharmony_ci	 * Must be done after all the sys_reg reset.
27862306a36Sopenharmony_ci	 */
27962306a36Sopenharmony_ci	if (reset_state.reset) {
28062306a36Sopenharmony_ci		unsigned long target_pc = reset_state.pc;
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci		/* Gracefully handle Thumb2 entry point */
28362306a36Sopenharmony_ci		if (vcpu_mode_is_32bit(vcpu) && (target_pc & 1)) {
28462306a36Sopenharmony_ci			target_pc &= ~1UL;
28562306a36Sopenharmony_ci			vcpu_set_thumb(vcpu);
28662306a36Sopenharmony_ci		}
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci		/* Propagate caller endianness */
28962306a36Sopenharmony_ci		if (reset_state.be)
29062306a36Sopenharmony_ci			kvm_vcpu_set_be(vcpu);
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci		*vcpu_pc(vcpu) = target_pc;
29362306a36Sopenharmony_ci		vcpu_set_reg(vcpu, 0, reset_state.r0);
29462306a36Sopenharmony_ci	}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	/* Reset timer */
29762306a36Sopenharmony_ci	ret = kvm_timer_vcpu_reset(vcpu);
29862306a36Sopenharmony_ciout:
29962306a36Sopenharmony_ci	if (loaded)
30062306a36Sopenharmony_ci		kvm_arch_vcpu_load(vcpu, smp_processor_id());
30162306a36Sopenharmony_ci	preempt_enable();
30262306a36Sopenharmony_ci	return ret;
30362306a36Sopenharmony_ci}
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ciu32 get_kvm_ipa_limit(void)
30662306a36Sopenharmony_ci{
30762306a36Sopenharmony_ci	return kvm_ipa_limit;
30862306a36Sopenharmony_ci}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ciint __init kvm_set_ipa_limit(void)
31162306a36Sopenharmony_ci{
31262306a36Sopenharmony_ci	unsigned int parange;
31362306a36Sopenharmony_ci	u64 mmfr0;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	mmfr0 = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1);
31662306a36Sopenharmony_ci	parange = cpuid_feature_extract_unsigned_field(mmfr0,
31762306a36Sopenharmony_ci				ID_AA64MMFR0_EL1_PARANGE_SHIFT);
31862306a36Sopenharmony_ci	/*
31962306a36Sopenharmony_ci	 * IPA size beyond 48 bits could not be supported
32062306a36Sopenharmony_ci	 * on either 4K or 16K page size. Hence let's cap
32162306a36Sopenharmony_ci	 * it to 48 bits, in case it's reported as larger
32262306a36Sopenharmony_ci	 * on the system.
32362306a36Sopenharmony_ci	 */
32462306a36Sopenharmony_ci	if (PAGE_SIZE != SZ_64K)
32562306a36Sopenharmony_ci		parange = min(parange, (unsigned int)ID_AA64MMFR0_EL1_PARANGE_48);
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	/*
32862306a36Sopenharmony_ci	 * Check with ARMv8.5-GTG that our PAGE_SIZE is supported at
32962306a36Sopenharmony_ci	 * Stage-2. If not, things will stop very quickly.
33062306a36Sopenharmony_ci	 */
33162306a36Sopenharmony_ci	switch (cpuid_feature_extract_unsigned_field(mmfr0, ID_AA64MMFR0_EL1_TGRAN_2_SHIFT)) {
33262306a36Sopenharmony_ci	case ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_NONE:
33362306a36Sopenharmony_ci		kvm_err("PAGE_SIZE not supported at Stage-2, giving up\n");
33462306a36Sopenharmony_ci		return -EINVAL;
33562306a36Sopenharmony_ci	case ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_DEFAULT:
33662306a36Sopenharmony_ci		kvm_debug("PAGE_SIZE supported at Stage-2 (default)\n");
33762306a36Sopenharmony_ci		break;
33862306a36Sopenharmony_ci	case ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_MIN ... ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_MAX:
33962306a36Sopenharmony_ci		kvm_debug("PAGE_SIZE supported at Stage-2 (advertised)\n");
34062306a36Sopenharmony_ci		break;
34162306a36Sopenharmony_ci	default:
34262306a36Sopenharmony_ci		kvm_err("Unsupported value for TGRAN_2, giving up\n");
34362306a36Sopenharmony_ci		return -EINVAL;
34462306a36Sopenharmony_ci	}
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	kvm_ipa_limit = id_aa64mmfr0_parange_to_phys_shift(parange);
34762306a36Sopenharmony_ci	kvm_info("IPA Size Limit: %d bits%s\n", kvm_ipa_limit,
34862306a36Sopenharmony_ci		 ((kvm_ipa_limit < KVM_PHYS_SHIFT) ?
34962306a36Sopenharmony_ci		  " (Reduced IPA size, limited VM/VMM compatibility)" : ""));
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	return 0;
35262306a36Sopenharmony_ci}
353