xref: /kernel/linux/linux-5.10/arch/arm64/kvm/reset.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2012,2013 - ARM Ltd
48c2ecf20Sopenharmony_ci * Author: Marc Zyngier <marc.zyngier@arm.com>
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Derived from arch/arm/kvm/reset.c
78c2ecf20Sopenharmony_ci * Copyright (C) 2012 - Virtual Open Systems and Columbia University
88c2ecf20Sopenharmony_ci * Author: Christoffer Dall <c.dall@virtualopensystems.com>
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/errno.h>
128c2ecf20Sopenharmony_ci#include <linux/kernel.h>
138c2ecf20Sopenharmony_ci#include <linux/kvm_host.h>
148c2ecf20Sopenharmony_ci#include <linux/kvm.h>
158c2ecf20Sopenharmony_ci#include <linux/hw_breakpoint.h>
168c2ecf20Sopenharmony_ci#include <linux/slab.h>
178c2ecf20Sopenharmony_ci#include <linux/string.h>
188c2ecf20Sopenharmony_ci#include <linux/types.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#include <kvm/arm_arch_timer.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include <asm/cpufeature.h>
238c2ecf20Sopenharmony_ci#include <asm/cputype.h>
248c2ecf20Sopenharmony_ci#include <asm/fpsimd.h>
258c2ecf20Sopenharmony_ci#include <asm/ptrace.h>
268c2ecf20Sopenharmony_ci#include <asm/kvm_arm.h>
278c2ecf20Sopenharmony_ci#include <asm/kvm_asm.h>
288c2ecf20Sopenharmony_ci#include <asm/kvm_coproc.h>
298c2ecf20Sopenharmony_ci#include <asm/kvm_emulate.h>
308c2ecf20Sopenharmony_ci#include <asm/kvm_mmu.h>
318c2ecf20Sopenharmony_ci#include <asm/virt.h>
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci/* Maximum phys_shift supported for any VM on this host */
348c2ecf20Sopenharmony_cistatic u32 kvm_ipa_limit;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci/*
378c2ecf20Sopenharmony_ci * ARMv8 Reset Values
388c2ecf20Sopenharmony_ci */
398c2ecf20Sopenharmony_ci#define VCPU_RESET_PSTATE_EL1	(PSR_MODE_EL1h | PSR_A_BIT | PSR_I_BIT | \
408c2ecf20Sopenharmony_ci				 PSR_F_BIT | PSR_D_BIT)
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci#define VCPU_RESET_PSTATE_SVC	(PSR_AA32_MODE_SVC | PSR_AA32_A_BIT | \
438c2ecf20Sopenharmony_ci				 PSR_AA32_I_BIT | PSR_AA32_F_BIT)
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cistatic bool system_has_full_ptr_auth(void)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	return system_supports_address_auth() && system_supports_generic_auth();
488c2ecf20Sopenharmony_ci}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci/**
518c2ecf20Sopenharmony_ci * kvm_arch_vm_ioctl_check_extension
528c2ecf20Sopenharmony_ci *
538c2ecf20Sopenharmony_ci * We currently assume that the number of HW registers is uniform
548c2ecf20Sopenharmony_ci * across all CPUs (see cpuinfo_sanity_check).
558c2ecf20Sopenharmony_ci */
568c2ecf20Sopenharmony_ciint kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)
578c2ecf20Sopenharmony_ci{
588c2ecf20Sopenharmony_ci	int r;
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	switch (ext) {
618c2ecf20Sopenharmony_ci	case KVM_CAP_ARM_EL1_32BIT:
628c2ecf20Sopenharmony_ci		r = cpus_have_const_cap(ARM64_HAS_32BIT_EL1);
638c2ecf20Sopenharmony_ci		break;
648c2ecf20Sopenharmony_ci	case KVM_CAP_GUEST_DEBUG_HW_BPS:
658c2ecf20Sopenharmony_ci		r = get_num_brps();
668c2ecf20Sopenharmony_ci		break;
678c2ecf20Sopenharmony_ci	case KVM_CAP_GUEST_DEBUG_HW_WPS:
688c2ecf20Sopenharmony_ci		r = get_num_wrps();
698c2ecf20Sopenharmony_ci		break;
708c2ecf20Sopenharmony_ci	case KVM_CAP_ARM_PMU_V3:
718c2ecf20Sopenharmony_ci		r = kvm_arm_support_pmu_v3();
728c2ecf20Sopenharmony_ci		break;
738c2ecf20Sopenharmony_ci	case KVM_CAP_ARM_INJECT_SERROR_ESR:
748c2ecf20Sopenharmony_ci		r = cpus_have_const_cap(ARM64_HAS_RAS_EXTN);
758c2ecf20Sopenharmony_ci		break;
768c2ecf20Sopenharmony_ci	case KVM_CAP_SET_GUEST_DEBUG:
778c2ecf20Sopenharmony_ci	case KVM_CAP_VCPU_ATTRIBUTES:
788c2ecf20Sopenharmony_ci		r = 1;
798c2ecf20Sopenharmony_ci		break;
808c2ecf20Sopenharmony_ci	case KVM_CAP_ARM_VM_IPA_SIZE:
818c2ecf20Sopenharmony_ci		r = kvm_ipa_limit;
828c2ecf20Sopenharmony_ci		break;
838c2ecf20Sopenharmony_ci	case KVM_CAP_ARM_SVE:
848c2ecf20Sopenharmony_ci		r = system_supports_sve();
858c2ecf20Sopenharmony_ci		break;
868c2ecf20Sopenharmony_ci	case KVM_CAP_ARM_PTRAUTH_ADDRESS:
878c2ecf20Sopenharmony_ci	case KVM_CAP_ARM_PTRAUTH_GENERIC:
888c2ecf20Sopenharmony_ci		r = system_has_full_ptr_auth();
898c2ecf20Sopenharmony_ci		break;
908c2ecf20Sopenharmony_ci	default:
918c2ecf20Sopenharmony_ci		r = 0;
928c2ecf20Sopenharmony_ci	}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	return r;
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ciunsigned int kvm_sve_max_vl;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ciint kvm_arm_init_sve(void)
1008c2ecf20Sopenharmony_ci{
1018c2ecf20Sopenharmony_ci	if (system_supports_sve()) {
1028c2ecf20Sopenharmony_ci		kvm_sve_max_vl = sve_max_virtualisable_vl;
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci		/*
1058c2ecf20Sopenharmony_ci		 * The get_sve_reg()/set_sve_reg() ioctl interface will need
1068c2ecf20Sopenharmony_ci		 * to be extended with multiple register slice support in
1078c2ecf20Sopenharmony_ci		 * order to support vector lengths greater than
1088c2ecf20Sopenharmony_ci		 * SVE_VL_ARCH_MAX:
1098c2ecf20Sopenharmony_ci		 */
1108c2ecf20Sopenharmony_ci		if (WARN_ON(kvm_sve_max_vl > SVE_VL_ARCH_MAX))
1118c2ecf20Sopenharmony_ci			kvm_sve_max_vl = SVE_VL_ARCH_MAX;
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci		/*
1148c2ecf20Sopenharmony_ci		 * Don't even try to make use of vector lengths that
1158c2ecf20Sopenharmony_ci		 * aren't available on all CPUs, for now:
1168c2ecf20Sopenharmony_ci		 */
1178c2ecf20Sopenharmony_ci		if (kvm_sve_max_vl < sve_max_vl)
1188c2ecf20Sopenharmony_ci			pr_warn("KVM: SVE vector length for guests limited to %u bytes\n",
1198c2ecf20Sopenharmony_ci				kvm_sve_max_vl);
1208c2ecf20Sopenharmony_ci	}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	return 0;
1238c2ecf20Sopenharmony_ci}
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_cistatic int kvm_vcpu_enable_sve(struct kvm_vcpu *vcpu)
1268c2ecf20Sopenharmony_ci{
1278c2ecf20Sopenharmony_ci	if (!system_supports_sve())
1288c2ecf20Sopenharmony_ci		return -EINVAL;
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	/* Verify that KVM startup enforced this when SVE was detected: */
1318c2ecf20Sopenharmony_ci	if (WARN_ON(!has_vhe()))
1328c2ecf20Sopenharmony_ci		return -EINVAL;
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	vcpu->arch.sve_max_vl = kvm_sve_max_vl;
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	/*
1378c2ecf20Sopenharmony_ci	 * Userspace can still customize the vector lengths by writing
1388c2ecf20Sopenharmony_ci	 * KVM_REG_ARM64_SVE_VLS.  Allocation is deferred until
1398c2ecf20Sopenharmony_ci	 * kvm_arm_vcpu_finalize(), which freezes the configuration.
1408c2ecf20Sopenharmony_ci	 */
1418c2ecf20Sopenharmony_ci	vcpu->arch.flags |= KVM_ARM64_GUEST_HAS_SVE;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	return 0;
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci/*
1478c2ecf20Sopenharmony_ci * Finalize vcpu's maximum SVE vector length, allocating
1488c2ecf20Sopenharmony_ci * vcpu->arch.sve_state as necessary.
1498c2ecf20Sopenharmony_ci */
1508c2ecf20Sopenharmony_cistatic int kvm_vcpu_finalize_sve(struct kvm_vcpu *vcpu)
1518c2ecf20Sopenharmony_ci{
1528c2ecf20Sopenharmony_ci	void *buf;
1538c2ecf20Sopenharmony_ci	unsigned int vl;
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	vl = vcpu->arch.sve_max_vl;
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	/*
1588c2ecf20Sopenharmony_ci	 * Responsibility for these properties is shared between
1598c2ecf20Sopenharmony_ci	 * kvm_arm_init_arch_resources(), kvm_vcpu_enable_sve() and
1608c2ecf20Sopenharmony_ci	 * set_sve_vls().  Double-check here just to be sure:
1618c2ecf20Sopenharmony_ci	 */
1628c2ecf20Sopenharmony_ci	if (WARN_ON(!sve_vl_valid(vl) || vl > sve_max_virtualisable_vl ||
1638c2ecf20Sopenharmony_ci		    vl > SVE_VL_ARCH_MAX))
1648c2ecf20Sopenharmony_ci		return -EIO;
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	buf = kzalloc(SVE_SIG_REGS_SIZE(sve_vq_from_vl(vl)), GFP_KERNEL);
1678c2ecf20Sopenharmony_ci	if (!buf)
1688c2ecf20Sopenharmony_ci		return -ENOMEM;
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	vcpu->arch.sve_state = buf;
1718c2ecf20Sopenharmony_ci	vcpu->arch.flags |= KVM_ARM64_VCPU_SVE_FINALIZED;
1728c2ecf20Sopenharmony_ci	return 0;
1738c2ecf20Sopenharmony_ci}
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ciint kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu, int feature)
1768c2ecf20Sopenharmony_ci{
1778c2ecf20Sopenharmony_ci	switch (feature) {
1788c2ecf20Sopenharmony_ci	case KVM_ARM_VCPU_SVE:
1798c2ecf20Sopenharmony_ci		if (!vcpu_has_sve(vcpu))
1808c2ecf20Sopenharmony_ci			return -EINVAL;
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci		if (kvm_arm_vcpu_sve_finalized(vcpu))
1838c2ecf20Sopenharmony_ci			return -EPERM;
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci		return kvm_vcpu_finalize_sve(vcpu);
1868c2ecf20Sopenharmony_ci	}
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	return -EINVAL;
1898c2ecf20Sopenharmony_ci}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_cibool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu)
1928c2ecf20Sopenharmony_ci{
1938c2ecf20Sopenharmony_ci	if (vcpu_has_sve(vcpu) && !kvm_arm_vcpu_sve_finalized(vcpu))
1948c2ecf20Sopenharmony_ci		return false;
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	return true;
1978c2ecf20Sopenharmony_ci}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_civoid kvm_arm_vcpu_destroy(struct kvm_vcpu *vcpu)
2008c2ecf20Sopenharmony_ci{
2018c2ecf20Sopenharmony_ci	kfree(vcpu->arch.sve_state);
2028c2ecf20Sopenharmony_ci}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_cistatic void kvm_vcpu_reset_sve(struct kvm_vcpu *vcpu)
2058c2ecf20Sopenharmony_ci{
2068c2ecf20Sopenharmony_ci	if (vcpu_has_sve(vcpu))
2078c2ecf20Sopenharmony_ci		memset(vcpu->arch.sve_state, 0, vcpu_sve_state_size(vcpu));
2088c2ecf20Sopenharmony_ci}
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_cistatic int kvm_vcpu_enable_ptrauth(struct kvm_vcpu *vcpu)
2118c2ecf20Sopenharmony_ci{
2128c2ecf20Sopenharmony_ci	/*
2138c2ecf20Sopenharmony_ci	 * For now make sure that both address/generic pointer authentication
2148c2ecf20Sopenharmony_ci	 * features are requested by the userspace together and the system
2158c2ecf20Sopenharmony_ci	 * supports these capabilities.
2168c2ecf20Sopenharmony_ci	 */
2178c2ecf20Sopenharmony_ci	if (!test_bit(KVM_ARM_VCPU_PTRAUTH_ADDRESS, vcpu->arch.features) ||
2188c2ecf20Sopenharmony_ci	    !test_bit(KVM_ARM_VCPU_PTRAUTH_GENERIC, vcpu->arch.features) ||
2198c2ecf20Sopenharmony_ci	    !system_has_full_ptr_auth())
2208c2ecf20Sopenharmony_ci		return -EINVAL;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	vcpu->arch.flags |= KVM_ARM64_GUEST_HAS_PTRAUTH;
2238c2ecf20Sopenharmony_ci	return 0;
2248c2ecf20Sopenharmony_ci}
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_cistatic bool vcpu_allowed_register_width(struct kvm_vcpu *vcpu)
2278c2ecf20Sopenharmony_ci{
2288c2ecf20Sopenharmony_ci	struct kvm_vcpu *tmp;
2298c2ecf20Sopenharmony_ci	bool is32bit;
2308c2ecf20Sopenharmony_ci	int i;
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	is32bit = vcpu_has_feature(vcpu, KVM_ARM_VCPU_EL1_32BIT);
2338c2ecf20Sopenharmony_ci	if (!cpus_have_const_cap(ARM64_HAS_32BIT_EL1) && is32bit)
2348c2ecf20Sopenharmony_ci		return false;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	/* Check that the vcpus are either all 32bit or all 64bit */
2378c2ecf20Sopenharmony_ci	kvm_for_each_vcpu(i, tmp, vcpu->kvm) {
2388c2ecf20Sopenharmony_ci		if (vcpu_has_feature(tmp, KVM_ARM_VCPU_EL1_32BIT) != is32bit)
2398c2ecf20Sopenharmony_ci			return false;
2408c2ecf20Sopenharmony_ci	}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	return true;
2438c2ecf20Sopenharmony_ci}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci/**
2468c2ecf20Sopenharmony_ci * kvm_reset_vcpu - sets core registers and sys_regs to reset value
2478c2ecf20Sopenharmony_ci * @vcpu: The VCPU pointer
2488c2ecf20Sopenharmony_ci *
2498c2ecf20Sopenharmony_ci * This function finds the right table above and sets the registers on
2508c2ecf20Sopenharmony_ci * the virtual CPU struct to their architecturally defined reset
2518c2ecf20Sopenharmony_ci * values, except for registers whose reset is deferred until
2528c2ecf20Sopenharmony_ci * kvm_arm_vcpu_finalize().
2538c2ecf20Sopenharmony_ci *
2548c2ecf20Sopenharmony_ci * Note: This function can be called from two paths: The KVM_ARM_VCPU_INIT
2558c2ecf20Sopenharmony_ci * ioctl or as part of handling a request issued by another VCPU in the PSCI
2568c2ecf20Sopenharmony_ci * handling code.  In the first case, the VCPU will not be loaded, and in the
2578c2ecf20Sopenharmony_ci * second case the VCPU will be loaded.  Because this function operates purely
2588c2ecf20Sopenharmony_ci * on the memory-backed values of system registers, we want to do a full put if
2598c2ecf20Sopenharmony_ci * we were loaded (handling a request) and load the values back at the end of
2608c2ecf20Sopenharmony_ci * the function.  Otherwise we leave the state alone.  In both cases, we
2618c2ecf20Sopenharmony_ci * disable preemption around the vcpu reset as we would otherwise race with
2628c2ecf20Sopenharmony_ci * preempt notifiers which also call put/load.
2638c2ecf20Sopenharmony_ci */
2648c2ecf20Sopenharmony_ciint kvm_reset_vcpu(struct kvm_vcpu *vcpu)
2658c2ecf20Sopenharmony_ci{
2668c2ecf20Sopenharmony_ci	struct vcpu_reset_state reset_state;
2678c2ecf20Sopenharmony_ci	int ret;
2688c2ecf20Sopenharmony_ci	bool loaded;
2698c2ecf20Sopenharmony_ci	u32 pstate;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	mutex_lock(&vcpu->kvm->lock);
2728c2ecf20Sopenharmony_ci	reset_state = vcpu->arch.reset_state;
2738c2ecf20Sopenharmony_ci	WRITE_ONCE(vcpu->arch.reset_state.reset, false);
2748c2ecf20Sopenharmony_ci	mutex_unlock(&vcpu->kvm->lock);
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	/* Reset PMU outside of the non-preemptible section */
2778c2ecf20Sopenharmony_ci	kvm_pmu_vcpu_reset(vcpu);
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	preempt_disable();
2808c2ecf20Sopenharmony_ci	loaded = (vcpu->cpu != -1);
2818c2ecf20Sopenharmony_ci	if (loaded)
2828c2ecf20Sopenharmony_ci		kvm_arch_vcpu_put(vcpu);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	if (!kvm_arm_vcpu_sve_finalized(vcpu)) {
2858c2ecf20Sopenharmony_ci		if (test_bit(KVM_ARM_VCPU_SVE, vcpu->arch.features)) {
2868c2ecf20Sopenharmony_ci			ret = kvm_vcpu_enable_sve(vcpu);
2878c2ecf20Sopenharmony_ci			if (ret)
2888c2ecf20Sopenharmony_ci				goto out;
2898c2ecf20Sopenharmony_ci		}
2908c2ecf20Sopenharmony_ci	} else {
2918c2ecf20Sopenharmony_ci		kvm_vcpu_reset_sve(vcpu);
2928c2ecf20Sopenharmony_ci	}
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	if (test_bit(KVM_ARM_VCPU_PTRAUTH_ADDRESS, vcpu->arch.features) ||
2958c2ecf20Sopenharmony_ci	    test_bit(KVM_ARM_VCPU_PTRAUTH_GENERIC, vcpu->arch.features)) {
2968c2ecf20Sopenharmony_ci		if (kvm_vcpu_enable_ptrauth(vcpu)) {
2978c2ecf20Sopenharmony_ci			ret = -EINVAL;
2988c2ecf20Sopenharmony_ci			goto out;
2998c2ecf20Sopenharmony_ci		}
3008c2ecf20Sopenharmony_ci	}
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	if (!vcpu_allowed_register_width(vcpu)) {
3038c2ecf20Sopenharmony_ci		ret = -EINVAL;
3048c2ecf20Sopenharmony_ci		goto out;
3058c2ecf20Sopenharmony_ci	}
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	switch (vcpu->arch.target) {
3088c2ecf20Sopenharmony_ci	default:
3098c2ecf20Sopenharmony_ci		if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) {
3108c2ecf20Sopenharmony_ci			pstate = VCPU_RESET_PSTATE_SVC;
3118c2ecf20Sopenharmony_ci		} else {
3128c2ecf20Sopenharmony_ci			pstate = VCPU_RESET_PSTATE_EL1;
3138c2ecf20Sopenharmony_ci		}
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci		break;
3168c2ecf20Sopenharmony_ci	}
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	/* Reset core registers */
3198c2ecf20Sopenharmony_ci	memset(vcpu_gp_regs(vcpu), 0, sizeof(*vcpu_gp_regs(vcpu)));
3208c2ecf20Sopenharmony_ci	memset(&vcpu->arch.ctxt.fp_regs, 0, sizeof(vcpu->arch.ctxt.fp_regs));
3218c2ecf20Sopenharmony_ci	vcpu->arch.ctxt.spsr_abt = 0;
3228c2ecf20Sopenharmony_ci	vcpu->arch.ctxt.spsr_und = 0;
3238c2ecf20Sopenharmony_ci	vcpu->arch.ctxt.spsr_irq = 0;
3248c2ecf20Sopenharmony_ci	vcpu->arch.ctxt.spsr_fiq = 0;
3258c2ecf20Sopenharmony_ci	vcpu_gp_regs(vcpu)->pstate = pstate;
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	/* Reset system registers */
3288c2ecf20Sopenharmony_ci	kvm_reset_sys_regs(vcpu);
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	/*
3318c2ecf20Sopenharmony_ci	 * Additional reset state handling that PSCI may have imposed on us.
3328c2ecf20Sopenharmony_ci	 * Must be done after all the sys_reg reset.
3338c2ecf20Sopenharmony_ci	 */
3348c2ecf20Sopenharmony_ci	if (reset_state.reset) {
3358c2ecf20Sopenharmony_ci		unsigned long target_pc = reset_state.pc;
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci		/* Gracefully handle Thumb2 entry point */
3388c2ecf20Sopenharmony_ci		if (vcpu_mode_is_32bit(vcpu) && (target_pc & 1)) {
3398c2ecf20Sopenharmony_ci			target_pc &= ~1UL;
3408c2ecf20Sopenharmony_ci			vcpu_set_thumb(vcpu);
3418c2ecf20Sopenharmony_ci		}
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci		/* Propagate caller endianness */
3448c2ecf20Sopenharmony_ci		if (reset_state.be)
3458c2ecf20Sopenharmony_ci			kvm_vcpu_set_be(vcpu);
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci		*vcpu_pc(vcpu) = target_pc;
3488c2ecf20Sopenharmony_ci		vcpu_set_reg(vcpu, 0, reset_state.r0);
3498c2ecf20Sopenharmony_ci	}
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	/* Reset timer */
3528c2ecf20Sopenharmony_ci	ret = kvm_timer_vcpu_reset(vcpu);
3538c2ecf20Sopenharmony_ciout:
3548c2ecf20Sopenharmony_ci	if (loaded)
3558c2ecf20Sopenharmony_ci		kvm_arch_vcpu_load(vcpu, smp_processor_id());
3568c2ecf20Sopenharmony_ci	preempt_enable();
3578c2ecf20Sopenharmony_ci	return ret;
3588c2ecf20Sopenharmony_ci}
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ciu32 get_kvm_ipa_limit(void)
3618c2ecf20Sopenharmony_ci{
3628c2ecf20Sopenharmony_ci	return kvm_ipa_limit;
3638c2ecf20Sopenharmony_ci}
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ciint kvm_set_ipa_limit(void)
3668c2ecf20Sopenharmony_ci{
3678c2ecf20Sopenharmony_ci	unsigned int parange, tgran_2;
3688c2ecf20Sopenharmony_ci	u64 mmfr0;
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	mmfr0 = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1);
3718c2ecf20Sopenharmony_ci	parange = cpuid_feature_extract_unsigned_field(mmfr0,
3728c2ecf20Sopenharmony_ci				ID_AA64MMFR0_PARANGE_SHIFT);
3738c2ecf20Sopenharmony_ci	/*
3748c2ecf20Sopenharmony_ci	 * IPA size beyond 48 bits could not be supported
3758c2ecf20Sopenharmony_ci	 * on either 4K or 16K page size. Hence let's cap
3768c2ecf20Sopenharmony_ci	 * it to 48 bits, in case it's reported as larger
3778c2ecf20Sopenharmony_ci	 * on the system.
3788c2ecf20Sopenharmony_ci	 */
3798c2ecf20Sopenharmony_ci	if (PAGE_SIZE != SZ_64K)
3808c2ecf20Sopenharmony_ci		parange = min(parange, (unsigned int)ID_AA64MMFR0_PARANGE_48);
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	/*
3838c2ecf20Sopenharmony_ci	 * Check with ARMv8.5-GTG that our PAGE_SIZE is supported at
3848c2ecf20Sopenharmony_ci	 * Stage-2. If not, things will stop very quickly.
3858c2ecf20Sopenharmony_ci	 */
3868c2ecf20Sopenharmony_ci	switch (PAGE_SIZE) {
3878c2ecf20Sopenharmony_ci	default:
3888c2ecf20Sopenharmony_ci	case SZ_4K:
3898c2ecf20Sopenharmony_ci		tgran_2 = ID_AA64MMFR0_TGRAN4_2_SHIFT;
3908c2ecf20Sopenharmony_ci		break;
3918c2ecf20Sopenharmony_ci	case SZ_16K:
3928c2ecf20Sopenharmony_ci		tgran_2 = ID_AA64MMFR0_TGRAN16_2_SHIFT;
3938c2ecf20Sopenharmony_ci		break;
3948c2ecf20Sopenharmony_ci	case SZ_64K:
3958c2ecf20Sopenharmony_ci		tgran_2 = ID_AA64MMFR0_TGRAN64_2_SHIFT;
3968c2ecf20Sopenharmony_ci		break;
3978c2ecf20Sopenharmony_ci	}
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	switch (cpuid_feature_extract_unsigned_field(mmfr0, tgran_2)) {
4008c2ecf20Sopenharmony_ci	case ID_AA64MMFR0_TGRAN_2_SUPPORTED_NONE:
4018c2ecf20Sopenharmony_ci		kvm_err("PAGE_SIZE not supported at Stage-2, giving up\n");
4028c2ecf20Sopenharmony_ci		return -EINVAL;
4038c2ecf20Sopenharmony_ci	case ID_AA64MMFR0_TGRAN_2_SUPPORTED_DEFAULT:
4048c2ecf20Sopenharmony_ci		kvm_debug("PAGE_SIZE supported at Stage-2 (default)\n");
4058c2ecf20Sopenharmony_ci		break;
4068c2ecf20Sopenharmony_ci	case ID_AA64MMFR0_TGRAN_2_SUPPORTED_MIN ... ID_AA64MMFR0_TGRAN_2_SUPPORTED_MAX:
4078c2ecf20Sopenharmony_ci		kvm_debug("PAGE_SIZE supported at Stage-2 (advertised)\n");
4088c2ecf20Sopenharmony_ci		break;
4098c2ecf20Sopenharmony_ci	default:
4108c2ecf20Sopenharmony_ci		kvm_err("Unsupported value for TGRAN_2, giving up\n");
4118c2ecf20Sopenharmony_ci		return -EINVAL;
4128c2ecf20Sopenharmony_ci	}
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	kvm_ipa_limit = id_aa64mmfr0_parange_to_phys_shift(parange);
4158c2ecf20Sopenharmony_ci	kvm_info("IPA Size Limit: %d bits%s\n", kvm_ipa_limit,
4168c2ecf20Sopenharmony_ci		 ((kvm_ipa_limit < KVM_PHYS_SHIFT) ?
4178c2ecf20Sopenharmony_ci		  " (Reduced IPA size, limited VM/VMM compatibility)" : ""));
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	return 0;
4208c2ecf20Sopenharmony_ci}
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci/*
4238c2ecf20Sopenharmony_ci * Configure the VTCR_EL2 for this VM. The VTCR value is common
4248c2ecf20Sopenharmony_ci * across all the physical CPUs on the system. We use system wide
4258c2ecf20Sopenharmony_ci * sanitised values to fill in different fields, except for Hardware
4268c2ecf20Sopenharmony_ci * Management of Access Flags. HA Flag is set unconditionally on
4278c2ecf20Sopenharmony_ci * all CPUs, as it is safe to run with or without the feature and
4288c2ecf20Sopenharmony_ci * the bit is RES0 on CPUs that don't support it.
4298c2ecf20Sopenharmony_ci */
4308c2ecf20Sopenharmony_ciint kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type)
4318c2ecf20Sopenharmony_ci{
4328c2ecf20Sopenharmony_ci	u64 vtcr = VTCR_EL2_FLAGS, mmfr0;
4338c2ecf20Sopenharmony_ci	u32 parange, phys_shift;
4348c2ecf20Sopenharmony_ci	u8 lvls;
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	if (type & ~KVM_VM_TYPE_ARM_IPA_SIZE_MASK)
4378c2ecf20Sopenharmony_ci		return -EINVAL;
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	phys_shift = KVM_VM_TYPE_ARM_IPA_SIZE(type);
4408c2ecf20Sopenharmony_ci	if (phys_shift) {
4418c2ecf20Sopenharmony_ci		if (phys_shift > kvm_ipa_limit ||
4428c2ecf20Sopenharmony_ci		    phys_shift < 32)
4438c2ecf20Sopenharmony_ci			return -EINVAL;
4448c2ecf20Sopenharmony_ci	} else {
4458c2ecf20Sopenharmony_ci		phys_shift = KVM_PHYS_SHIFT;
4468c2ecf20Sopenharmony_ci		if (phys_shift > kvm_ipa_limit) {
4478c2ecf20Sopenharmony_ci			pr_warn_once("%s using unsupported default IPA limit, upgrade your VMM\n",
4488c2ecf20Sopenharmony_ci				     current->comm);
4498c2ecf20Sopenharmony_ci			return -EINVAL;
4508c2ecf20Sopenharmony_ci		}
4518c2ecf20Sopenharmony_ci	}
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	mmfr0 = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1);
4548c2ecf20Sopenharmony_ci	parange = cpuid_feature_extract_unsigned_field(mmfr0,
4558c2ecf20Sopenharmony_ci				ID_AA64MMFR0_PARANGE_SHIFT);
4568c2ecf20Sopenharmony_ci	if (parange > ID_AA64MMFR0_PARANGE_MAX)
4578c2ecf20Sopenharmony_ci		parange = ID_AA64MMFR0_PARANGE_MAX;
4588c2ecf20Sopenharmony_ci	vtcr |= parange << VTCR_EL2_PS_SHIFT;
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci	vtcr |= VTCR_EL2_T0SZ(phys_shift);
4618c2ecf20Sopenharmony_ci	/*
4628c2ecf20Sopenharmony_ci	 * Use a minimum 2 level page table to prevent splitting
4638c2ecf20Sopenharmony_ci	 * host PMD huge pages at stage2.
4648c2ecf20Sopenharmony_ci	 */
4658c2ecf20Sopenharmony_ci	lvls = stage2_pgtable_levels(phys_shift);
4668c2ecf20Sopenharmony_ci	if (lvls < 2)
4678c2ecf20Sopenharmony_ci		lvls = 2;
4688c2ecf20Sopenharmony_ci	vtcr |= VTCR_EL2_LVLS_TO_SL0(lvls);
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	/*
4718c2ecf20Sopenharmony_ci	 * Enable the Hardware Access Flag management, unconditionally
4728c2ecf20Sopenharmony_ci	 * on all CPUs. The features is RES0 on CPUs without the support
4738c2ecf20Sopenharmony_ci	 * and must be ignored by the CPUs.
4748c2ecf20Sopenharmony_ci	 */
4758c2ecf20Sopenharmony_ci	vtcr |= VTCR_EL2_HA;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	/* Set the vmid bits */
4788c2ecf20Sopenharmony_ci	vtcr |= (kvm_get_vmid_bits() == 16) ?
4798c2ecf20Sopenharmony_ci		VTCR_EL2_VS_16BIT :
4808c2ecf20Sopenharmony_ci		VTCR_EL2_VS_8BIT;
4818c2ecf20Sopenharmony_ci	kvm->arch.vtcr = vtcr;
4828c2ecf20Sopenharmony_ci	return 0;
4838c2ecf20Sopenharmony_ci}
484