1f4672752SMarc Zyngier /* 2f4672752SMarc Zyngier * Copyright (C) 2012,2013 - ARM Ltd 3f4672752SMarc Zyngier * Author: Marc Zyngier <marc.zyngier@arm.com> 4f4672752SMarc Zyngier * 5f4672752SMarc Zyngier * Derived from arch/arm/kvm/reset.c 6f4672752SMarc Zyngier * Copyright (C) 2012 - Virtual Open Systems and Columbia University 7f4672752SMarc Zyngier * Author: Christoffer Dall <c.dall@virtualopensystems.com> 8f4672752SMarc Zyngier * 9f4672752SMarc Zyngier * This program is free software; you can redistribute it and/or modify 10f4672752SMarc Zyngier * it under the terms of the GNU General Public License, version 2, as 11f4672752SMarc Zyngier * published by the Free Software Foundation. 12f4672752SMarc Zyngier * 13f4672752SMarc Zyngier * This program is distributed in the hope that it will be useful, 14f4672752SMarc Zyngier * but WITHOUT ANY WARRANTY; without even the implied warranty of 15f4672752SMarc Zyngier * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16f4672752SMarc Zyngier * GNU General Public License for more details. 17f4672752SMarc Zyngier * 18f4672752SMarc Zyngier * You should have received a copy of the GNU General Public License 19f4672752SMarc Zyngier * along with this program. If not, see <http://www.gnu.org/licenses/>. 20f4672752SMarc Zyngier */ 21f4672752SMarc Zyngier 22f4672752SMarc Zyngier #include <linux/errno.h> 23f4672752SMarc Zyngier #include <linux/kvm_host.h> 24f4672752SMarc Zyngier #include <linux/kvm.h> 25834bf887SAlex Bennée #include <linux/hw_breakpoint.h> 26f4672752SMarc Zyngier 27003300deSMarc Zyngier #include <kvm/arm_arch_timer.h> 28003300deSMarc Zyngier 29f4672752SMarc Zyngier #include <asm/cputype.h> 30f4672752SMarc Zyngier #include <asm/ptrace.h> 31f4672752SMarc Zyngier #include <asm/kvm_arm.h> 3267f69197SAKASHI Takahiro #include <asm/kvm_asm.h> 33f4672752SMarc Zyngier #include <asm/kvm_coproc.h> 3467f69197SAKASHI Takahiro #include <asm/kvm_mmu.h> 35f4672752SMarc Zyngier 36f4672752SMarc Zyngier /* 37f4672752SMarc Zyngier * ARMv8 Reset Values 38f4672752SMarc Zyngier */ 39f4672752SMarc Zyngier static const struct kvm_regs default_regs_reset = { 40f4672752SMarc Zyngier .regs.pstate = (PSR_MODE_EL1h | PSR_A_BIT | PSR_I_BIT | 41f4672752SMarc Zyngier PSR_F_BIT | PSR_D_BIT), 42f4672752SMarc Zyngier }; 43f4672752SMarc Zyngier 440d854a60SMarc Zyngier static const struct kvm_regs default_regs_reset32 = { 450d854a60SMarc Zyngier .regs.pstate = (COMPAT_PSR_MODE_SVC | COMPAT_PSR_A_BIT | 460d854a60SMarc Zyngier COMPAT_PSR_I_BIT | COMPAT_PSR_F_BIT), 470d854a60SMarc Zyngier }; 480d854a60SMarc Zyngier 490d854a60SMarc Zyngier static bool cpu_has_32bit_el1(void) 500d854a60SMarc Zyngier { 510d854a60SMarc Zyngier u64 pfr0; 520d854a60SMarc Zyngier 5346823dd1SDave Martin pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1); 540d854a60SMarc Zyngier return !!(pfr0 & 0x20); 550d854a60SMarc Zyngier } 560d854a60SMarc Zyngier 57834bf887SAlex Bennée /** 58834bf887SAlex Bennée * kvm_arch_dev_ioctl_check_extension 59834bf887SAlex Bennée * 60834bf887SAlex Bennée * We currently assume that the number of HW registers is uniform 61834bf887SAlex Bennée * across all CPUs (see cpuinfo_sanity_check). 62834bf887SAlex Bennée */ 63b46f01ceSAndre Przywara int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) 64f4672752SMarc Zyngier { 65f4672752SMarc Zyngier int r; 66f4672752SMarc Zyngier 67f4672752SMarc Zyngier switch (ext) { 680d854a60SMarc Zyngier case KVM_CAP_ARM_EL1_32BIT: 690d854a60SMarc Zyngier r = cpu_has_32bit_el1(); 700d854a60SMarc Zyngier break; 71834bf887SAlex Bennée case KVM_CAP_GUEST_DEBUG_HW_BPS: 72834bf887SAlex Bennée r = get_num_brps(); 73834bf887SAlex Bennée break; 74834bf887SAlex Bennée case KVM_CAP_GUEST_DEBUG_HW_WPS: 75834bf887SAlex Bennée r = get_num_wrps(); 76834bf887SAlex Bennée break; 77808e7381SShannon Zhao case KVM_CAP_ARM_PMU_V3: 78808e7381SShannon Zhao r = kvm_arm_support_pmu_v3(); 79808e7381SShannon Zhao break; 80834bf887SAlex Bennée case KVM_CAP_SET_GUEST_DEBUG: 81f577f6c2SShannon Zhao case KVM_CAP_VCPU_ATTRIBUTES: 82834bf887SAlex Bennée r = 1; 83834bf887SAlex Bennée break; 84f4672752SMarc Zyngier default: 85f4672752SMarc Zyngier r = 0; 86f4672752SMarc Zyngier } 87f4672752SMarc Zyngier 88f4672752SMarc Zyngier return r; 89f4672752SMarc Zyngier } 90f4672752SMarc Zyngier 91f4672752SMarc Zyngier /** 92f4672752SMarc Zyngier * kvm_reset_vcpu - sets core registers and sys_regs to reset value 93f4672752SMarc Zyngier * @vcpu: The VCPU pointer 94f4672752SMarc Zyngier * 95f4672752SMarc Zyngier * This function finds the right table above and sets the registers on 96edce2292SAndrea Gelmini * the virtual CPU struct to their architecturally defined reset 97f4672752SMarc Zyngier * values. 98f4672752SMarc Zyngier */ 99f4672752SMarc Zyngier int kvm_reset_vcpu(struct kvm_vcpu *vcpu) 100f4672752SMarc Zyngier { 101f4672752SMarc Zyngier const struct kvm_regs *cpu_reset; 102f4672752SMarc Zyngier 103f4672752SMarc Zyngier switch (vcpu->arch.target) { 104f4672752SMarc Zyngier default: 1050d854a60SMarc Zyngier if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) { 1060d854a60SMarc Zyngier if (!cpu_has_32bit_el1()) 1070d854a60SMarc Zyngier return -EINVAL; 1080d854a60SMarc Zyngier cpu_reset = &default_regs_reset32; 1090d854a60SMarc Zyngier } else { 110f4672752SMarc Zyngier cpu_reset = &default_regs_reset; 1110d854a60SMarc Zyngier } 1120d854a60SMarc Zyngier 113f4672752SMarc Zyngier break; 114f4672752SMarc Zyngier } 115f4672752SMarc Zyngier 116f4672752SMarc Zyngier /* Reset core registers */ 117f4672752SMarc Zyngier memcpy(vcpu_gp_regs(vcpu), cpu_reset, sizeof(*cpu_reset)); 118f4672752SMarc Zyngier 119f4672752SMarc Zyngier /* Reset system registers */ 120f4672752SMarc Zyngier kvm_reset_sys_regs(vcpu); 121f4672752SMarc Zyngier 1222aa36e98SShannon Zhao /* Reset PMU */ 1232aa36e98SShannon Zhao kvm_pmu_vcpu_reset(vcpu); 1242aa36e98SShannon Zhao 1255d81f7dcSMarc Zyngier /* Default workaround setup is enabled (if supported) */ 1265d81f7dcSMarc Zyngier if (kvm_arm_have_ssbd() == KVM_SSBD_KERNEL) 1275d81f7dcSMarc Zyngier vcpu->arch.workaround_flags |= VCPU_WORKAROUND_2_FLAG; 1285d81f7dcSMarc Zyngier 129003300deSMarc Zyngier /* Reset timer */ 13085e69ad7SChristoffer Dall return kvm_timer_vcpu_reset(vcpu); 131f4672752SMarc Zyngier } 132