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