linux/arch/arm/include/asm/kvm_emulate.h
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
   3 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License, version 2, as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program; if not, write to the Free Software
  16 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  17 */
  18
  19#ifndef __ARM_KVM_EMULATE_H__
  20#define __ARM_KVM_EMULATE_H__
  21
  22#include <linux/kvm_host.h>
  23#include <asm/kvm_asm.h>
  24#include <asm/kvm_mmio.h>
  25#include <asm/kvm_arm.h>
  26#include <asm/cputype.h>
  27
  28unsigned long *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num);
  29unsigned long *vcpu_spsr(struct kvm_vcpu *vcpu);
  30
  31static inline unsigned long vcpu_get_reg(struct kvm_vcpu *vcpu,
  32                                         u8 reg_num)
  33{
  34        return *vcpu_reg(vcpu, reg_num);
  35}
  36
  37static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num,
  38                                unsigned long val)
  39{
  40        *vcpu_reg(vcpu, reg_num) = val;
  41}
  42
  43bool kvm_condition_valid(struct kvm_vcpu *vcpu);
  44void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr);
  45void kvm_inject_undefined(struct kvm_vcpu *vcpu);
  46void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr);
  47void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);
  48
  49static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
  50{
  51        vcpu->arch.hcr = HCR_GUEST_MASK;
  52}
  53
  54static inline unsigned long vcpu_get_hcr(struct kvm_vcpu *vcpu)
  55{
  56        return vcpu->arch.hcr;
  57}
  58
  59static inline void vcpu_set_hcr(struct kvm_vcpu *vcpu, unsigned long hcr)
  60{
  61        vcpu->arch.hcr = hcr;
  62}
  63
  64static inline bool vcpu_mode_is_32bit(struct kvm_vcpu *vcpu)
  65{
  66        return 1;
  67}
  68
  69static inline unsigned long *vcpu_pc(struct kvm_vcpu *vcpu)
  70{
  71        return &vcpu->arch.ctxt.gp_regs.usr_regs.ARM_pc;
  72}
  73
  74static inline unsigned long *vcpu_cpsr(struct kvm_vcpu *vcpu)
  75{
  76        return &vcpu->arch.ctxt.gp_regs.usr_regs.ARM_cpsr;
  77}
  78
  79static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
  80{
  81        *vcpu_cpsr(vcpu) |= PSR_T_BIT;
  82}
  83
  84static inline bool mode_has_spsr(struct kvm_vcpu *vcpu)
  85{
  86        unsigned long cpsr_mode = vcpu->arch.ctxt.gp_regs.usr_regs.ARM_cpsr & MODE_MASK;
  87        return (cpsr_mode > USR_MODE && cpsr_mode < SYSTEM_MODE);
  88}
  89
  90static inline bool vcpu_mode_priv(struct kvm_vcpu *vcpu)
  91{
  92        unsigned long cpsr_mode = vcpu->arch.ctxt.gp_regs.usr_regs.ARM_cpsr & MODE_MASK;
  93        return cpsr_mode > USR_MODE;;
  94}
  95
  96static inline u32 kvm_vcpu_get_hsr(struct kvm_vcpu *vcpu)
  97{
  98        return vcpu->arch.fault.hsr;
  99}
 100
 101static inline unsigned long kvm_vcpu_get_hfar(struct kvm_vcpu *vcpu)
 102{
 103        return vcpu->arch.fault.hxfar;
 104}
 105
 106static inline phys_addr_t kvm_vcpu_get_fault_ipa(struct kvm_vcpu *vcpu)
 107{
 108        return ((phys_addr_t)vcpu->arch.fault.hpfar & HPFAR_MASK) << 8;
 109}
 110
 111static inline bool kvm_vcpu_dabt_isvalid(struct kvm_vcpu *vcpu)
 112{
 113        return kvm_vcpu_get_hsr(vcpu) & HSR_ISV;
 114}
 115
 116static inline bool kvm_vcpu_dabt_iswrite(struct kvm_vcpu *vcpu)
 117{
 118        return kvm_vcpu_get_hsr(vcpu) & HSR_WNR;
 119}
 120
 121static inline bool kvm_vcpu_dabt_issext(struct kvm_vcpu *vcpu)
 122{
 123        return kvm_vcpu_get_hsr(vcpu) & HSR_SSE;
 124}
 125
 126static inline int kvm_vcpu_dabt_get_rd(struct kvm_vcpu *vcpu)
 127{
 128        return (kvm_vcpu_get_hsr(vcpu) & HSR_SRT_MASK) >> HSR_SRT_SHIFT;
 129}
 130
 131static inline bool kvm_vcpu_dabt_isextabt(struct kvm_vcpu *vcpu)
 132{
 133        return kvm_vcpu_get_hsr(vcpu) & HSR_DABT_EA;
 134}
 135
 136static inline bool kvm_vcpu_dabt_iss1tw(struct kvm_vcpu *vcpu)
 137{
 138        return kvm_vcpu_get_hsr(vcpu) & HSR_DABT_S1PTW;
 139}
 140
 141static inline bool kvm_vcpu_dabt_is_cm(struct kvm_vcpu *vcpu)
 142{
 143        return !!(kvm_vcpu_get_hsr(vcpu) & HSR_DABT_CM);
 144}
 145
 146/* Get Access Size from a data abort */
 147static inline int kvm_vcpu_dabt_get_as(struct kvm_vcpu *vcpu)
 148{
 149        switch ((kvm_vcpu_get_hsr(vcpu) >> 22) & 0x3) {
 150        case 0:
 151                return 1;
 152        case 1:
 153                return 2;
 154        case 2:
 155                return 4;
 156        default:
 157                kvm_err("Hardware is weird: SAS 0b11 is reserved\n");
 158                return -EFAULT;
 159        }
 160}
 161
 162/* This one is not specific to Data Abort */
 163static inline bool kvm_vcpu_trap_il_is32bit(struct kvm_vcpu *vcpu)
 164{
 165        return kvm_vcpu_get_hsr(vcpu) & HSR_IL;
 166}
 167
 168static inline u8 kvm_vcpu_trap_get_class(struct kvm_vcpu *vcpu)
 169{
 170        return kvm_vcpu_get_hsr(vcpu) >> HSR_EC_SHIFT;
 171}
 172
 173static inline bool kvm_vcpu_trap_is_iabt(struct kvm_vcpu *vcpu)
 174{
 175        return kvm_vcpu_trap_get_class(vcpu) == HSR_EC_IABT;
 176}
 177
 178static inline u8 kvm_vcpu_trap_get_fault(struct kvm_vcpu *vcpu)
 179{
 180        return kvm_vcpu_get_hsr(vcpu) & HSR_FSC;
 181}
 182
 183static inline u8 kvm_vcpu_trap_get_fault_type(struct kvm_vcpu *vcpu)
 184{
 185        return kvm_vcpu_get_hsr(vcpu) & HSR_FSC_TYPE;
 186}
 187
 188static inline u32 kvm_vcpu_hvc_get_imm(struct kvm_vcpu *vcpu)
 189{
 190        return kvm_vcpu_get_hsr(vcpu) & HSR_HVC_IMM_MASK;
 191}
 192
 193static inline unsigned long kvm_vcpu_get_mpidr_aff(struct kvm_vcpu *vcpu)
 194{
 195        return vcpu_cp15(vcpu, c0_MPIDR) & MPIDR_HWID_BITMASK;
 196}
 197
 198static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
 199{
 200        *vcpu_cpsr(vcpu) |= PSR_E_BIT;
 201}
 202
 203static inline bool kvm_vcpu_is_be(struct kvm_vcpu *vcpu)
 204{
 205        return !!(*vcpu_cpsr(vcpu) & PSR_E_BIT);
 206}
 207
 208static inline unsigned long vcpu_data_guest_to_host(struct kvm_vcpu *vcpu,
 209                                                    unsigned long data,
 210                                                    unsigned int len)
 211{
 212        if (kvm_vcpu_is_be(vcpu)) {
 213                switch (len) {
 214                case 1:
 215                        return data & 0xff;
 216                case 2:
 217                        return be16_to_cpu(data & 0xffff);
 218                default:
 219                        return be32_to_cpu(data);
 220                }
 221        } else {
 222                switch (len) {
 223                case 1:
 224                        return data & 0xff;
 225                case 2:
 226                        return le16_to_cpu(data & 0xffff);
 227                default:
 228                        return le32_to_cpu(data);
 229                }
 230        }
 231}
 232
 233static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu,
 234                                                    unsigned long data,
 235                                                    unsigned int len)
 236{
 237        if (kvm_vcpu_is_be(vcpu)) {
 238                switch (len) {
 239                case 1:
 240                        return data & 0xff;
 241                case 2:
 242                        return cpu_to_be16(data & 0xffff);
 243                default:
 244                        return cpu_to_be32(data);
 245                }
 246        } else {
 247                switch (len) {
 248                case 1:
 249                        return data & 0xff;
 250                case 2:
 251                        return cpu_to_le16(data & 0xffff);
 252                default:
 253                        return cpu_to_le32(data);
 254                }
 255        }
 256}
 257
 258#endif /* __ARM_KVM_EMULATE_H__ */
 259