linux/arch/arm64/kvm/reset.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2012,2013 - ARM Ltd
   3 * Author: Marc Zyngier <marc.zyngier@arm.com>
   4 *
   5 * Derived from arch/arm/kvm/reset.c
   6 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
   7 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License, version 2, as
  11 * published by the Free Software Foundation.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21
  22#include <linux/errno.h>
  23#include <linux/kvm_host.h>
  24#include <linux/kvm.h>
  25
  26#include <kvm/arm_arch_timer.h>
  27
  28#include <asm/cputype.h>
  29#include <asm/ptrace.h>
  30#include <asm/kvm_arm.h>
  31#include <asm/kvm_coproc.h>
  32
  33/*
  34 * ARMv8 Reset Values
  35 */
  36static const struct kvm_regs default_regs_reset = {
  37        .regs.pstate = (PSR_MODE_EL1h | PSR_A_BIT | PSR_I_BIT |
  38                        PSR_F_BIT | PSR_D_BIT),
  39};
  40
  41static const struct kvm_regs default_regs_reset32 = {
  42        .regs.pstate = (COMPAT_PSR_MODE_SVC | COMPAT_PSR_A_BIT |
  43                        COMPAT_PSR_I_BIT | COMPAT_PSR_F_BIT),
  44};
  45
  46static const struct kvm_irq_level default_vtimer_irq = {
  47        .irq    = 27,
  48        .level  = 1,
  49};
  50
  51static bool cpu_has_32bit_el1(void)
  52{
  53        u64 pfr0;
  54
  55        pfr0 = read_cpuid(ID_AA64PFR0_EL1);
  56        return !!(pfr0 & 0x20);
  57}
  58
  59int kvm_arch_dev_ioctl_check_extension(long ext)
  60{
  61        int r;
  62
  63        switch (ext) {
  64        case KVM_CAP_ARM_EL1_32BIT:
  65                r = cpu_has_32bit_el1();
  66                break;
  67        default:
  68                r = 0;
  69        }
  70
  71        return r;
  72}
  73
  74/**
  75 * kvm_reset_vcpu - sets core registers and sys_regs to reset value
  76 * @vcpu: The VCPU pointer
  77 *
  78 * This function finds the right table above and sets the registers on
  79 * the virtual CPU struct to their architectually defined reset
  80 * values.
  81 */
  82int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
  83{
  84        const struct kvm_irq_level *cpu_vtimer_irq;
  85        const struct kvm_regs *cpu_reset;
  86
  87        switch (vcpu->arch.target) {
  88        default:
  89                if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) {
  90                        if (!cpu_has_32bit_el1())
  91                                return -EINVAL;
  92                        cpu_reset = &default_regs_reset32;
  93                        vcpu->arch.hcr_el2 &= ~HCR_RW;
  94                } else {
  95                        cpu_reset = &default_regs_reset;
  96                }
  97
  98                cpu_vtimer_irq = &default_vtimer_irq;
  99                break;
 100        }
 101
 102        /* Reset core registers */
 103        memcpy(vcpu_gp_regs(vcpu), cpu_reset, sizeof(*cpu_reset));
 104
 105        /* Reset system registers */
 106        kvm_reset_sys_regs(vcpu);
 107
 108        /* Reset timer */
 109        kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq);
 110
 111        return 0;
 112}
 113