linux/arch/arm64/include/asm/kvm_emulate.h
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2012,2013 - ARM Ltd
   3 * Author: Marc Zyngier <marc.zyngier@arm.com>
   4 *
   5 * Derived from arch/arm/include/kvm_emulate.h
   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#ifndef __ARM64_KVM_EMULATE_H__
  23#define __ARM64_KVM_EMULATE_H__
  24
  25#include <linux/kvm_host.h>
  26#include <asm/kvm_asm.h>
  27#include <asm/kvm_arm.h>
  28#include <asm/kvm_mmio.h>
  29#include <asm/ptrace.h>
  30
  31unsigned long *vcpu_reg32(const struct kvm_vcpu *vcpu, u8 reg_num);
  32unsigned long *vcpu_spsr32(const struct kvm_vcpu *vcpu);
  33
  34bool kvm_condition_valid32(const struct kvm_vcpu *vcpu);
  35void kvm_skip_instr32(struct kvm_vcpu *vcpu, bool is_wide_instr);
  36
  37void kvm_inject_undefined(struct kvm_vcpu *vcpu);
  38void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr);
  39void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);
  40
  41static inline unsigned long *vcpu_pc(const struct kvm_vcpu *vcpu)
  42{
  43        return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.pc;
  44}
  45
  46static inline unsigned long *vcpu_elr_el1(const struct kvm_vcpu *vcpu)
  47{
  48        return (unsigned long *)&vcpu_gp_regs(vcpu)->elr_el1;
  49}
  50
  51static inline unsigned long *vcpu_cpsr(const struct kvm_vcpu *vcpu)
  52{
  53        return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.pstate;
  54}
  55
  56static inline bool vcpu_mode_is_32bit(const struct kvm_vcpu *vcpu)
  57{
  58        return !!(*vcpu_cpsr(vcpu) & PSR_MODE32_BIT);
  59}
  60
  61static inline bool kvm_condition_valid(const struct kvm_vcpu *vcpu)
  62{
  63        if (vcpu_mode_is_32bit(vcpu))
  64                return kvm_condition_valid32(vcpu);
  65
  66        return true;
  67}
  68
  69static inline void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr)
  70{
  71        if (vcpu_mode_is_32bit(vcpu))
  72                kvm_skip_instr32(vcpu, is_wide_instr);
  73        else
  74                *vcpu_pc(vcpu) += 4;
  75}
  76
  77static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
  78{
  79        *vcpu_cpsr(vcpu) |= COMPAT_PSR_T_BIT;
  80}
  81
  82static inline unsigned long *vcpu_reg(const struct kvm_vcpu *vcpu, u8 reg_num)
  83{
  84        if (vcpu_mode_is_32bit(vcpu))
  85                return vcpu_reg32(vcpu, reg_num);
  86
  87        return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.regs[reg_num];
  88}
  89
  90/* Get vcpu SPSR for current mode */
  91static inline unsigned long *vcpu_spsr(const struct kvm_vcpu *vcpu)
  92{
  93        if (vcpu_mode_is_32bit(vcpu))
  94                return vcpu_spsr32(vcpu);
  95
  96        return (unsigned long *)&vcpu_gp_regs(vcpu)->spsr[KVM_SPSR_EL1];
  97}
  98
  99static inline bool vcpu_mode_priv(const struct kvm_vcpu *vcpu)
 100{
 101        u32 mode = *vcpu_cpsr(vcpu) & PSR_MODE_MASK;
 102
 103        if (vcpu_mode_is_32bit(vcpu))
 104                return mode > COMPAT_PSR_MODE_USR;
 105
 106        return mode != PSR_MODE_EL0t;
 107}
 108
 109static inline u32 kvm_vcpu_get_hsr(const struct kvm_vcpu *vcpu)
 110{
 111        return vcpu->arch.fault.esr_el2;
 112}
 113
 114static inline unsigned long kvm_vcpu_get_hfar(const struct kvm_vcpu *vcpu)
 115{
 116        return vcpu->arch.fault.far_el2;
 117}
 118
 119static inline phys_addr_t kvm_vcpu_get_fault_ipa(const struct kvm_vcpu *vcpu)
 120{
 121        return ((phys_addr_t)vcpu->arch.fault.hpfar_el2 & HPFAR_MASK) << 8;
 122}
 123
 124static inline bool kvm_vcpu_dabt_isvalid(const struct kvm_vcpu *vcpu)
 125{
 126        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_EL2_ISV);
 127}
 128
 129static inline bool kvm_vcpu_dabt_iswrite(const struct kvm_vcpu *vcpu)
 130{
 131        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_EL2_WNR);
 132}
 133
 134static inline bool kvm_vcpu_dabt_issext(const struct kvm_vcpu *vcpu)
 135{
 136        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_EL2_SSE);
 137}
 138
 139static inline int kvm_vcpu_dabt_get_rd(const struct kvm_vcpu *vcpu)
 140{
 141        return (kvm_vcpu_get_hsr(vcpu) & ESR_EL2_SRT_MASK) >> ESR_EL2_SRT_SHIFT;
 142}
 143
 144static inline bool kvm_vcpu_dabt_isextabt(const struct kvm_vcpu *vcpu)
 145{
 146        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_EL2_EA);
 147}
 148
 149static inline bool kvm_vcpu_dabt_iss1tw(const struct kvm_vcpu *vcpu)
 150{
 151        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_EL2_S1PTW);
 152}
 153
 154static inline int kvm_vcpu_dabt_get_as(const struct kvm_vcpu *vcpu)
 155{
 156        return 1 << ((kvm_vcpu_get_hsr(vcpu) & ESR_EL2_SAS) >> ESR_EL2_SAS_SHIFT);
 157}
 158
 159/* This one is not specific to Data Abort */
 160static inline bool kvm_vcpu_trap_il_is32bit(const struct kvm_vcpu *vcpu)
 161{
 162        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_EL2_IL);
 163}
 164
 165static inline u8 kvm_vcpu_trap_get_class(const struct kvm_vcpu *vcpu)
 166{
 167        return kvm_vcpu_get_hsr(vcpu) >> ESR_EL2_EC_SHIFT;
 168}
 169
 170static inline bool kvm_vcpu_trap_is_iabt(const struct kvm_vcpu *vcpu)
 171{
 172        return kvm_vcpu_trap_get_class(vcpu) == ESR_EL2_EC_IABT;
 173}
 174
 175static inline u8 kvm_vcpu_trap_get_fault(const struct kvm_vcpu *vcpu)
 176{
 177        return kvm_vcpu_get_hsr(vcpu) & ESR_EL2_FSC_TYPE;
 178}
 179
 180#endif /* __ARM64_KVM_EMULATE_H__ */
 181