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
  28/* arm64 compatibility macros */
  29#define COMPAT_PSR_MODE_ABT     ABT_MODE
  30#define COMPAT_PSR_MODE_UND     UND_MODE
  31#define COMPAT_PSR_T_BIT        PSR_T_BIT
  32#define COMPAT_PSR_I_BIT        PSR_I_BIT
  33#define COMPAT_PSR_A_BIT        PSR_A_BIT
  34#define COMPAT_PSR_E_BIT        PSR_E_BIT
  35#define COMPAT_PSR_IT_MASK      PSR_IT_MASK
  36
  37unsigned long *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num);
  38
  39static inline unsigned long *vcpu_reg32(struct kvm_vcpu *vcpu, u8 reg_num)
  40{
  41        return vcpu_reg(vcpu, reg_num);
  42}
  43
  44unsigned long *__vcpu_spsr(struct kvm_vcpu *vcpu);
  45
  46static inline unsigned long vpcu_read_spsr(struct kvm_vcpu *vcpu)
  47{
  48        return *__vcpu_spsr(vcpu);
  49}
  50
  51static inline void vcpu_write_spsr(struct kvm_vcpu *vcpu, unsigned long v)
  52{
  53        *__vcpu_spsr(vcpu) = v;
  54}
  55
  56static inline unsigned long vcpu_get_reg(struct kvm_vcpu *vcpu,
  57                                         u8 reg_num)
  58{
  59        return *vcpu_reg(vcpu, reg_num);
  60}
  61
  62static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num,
  63                                unsigned long val)
  64{
  65        *vcpu_reg(vcpu, reg_num) = val;
  66}
  67
  68bool kvm_condition_valid32(const struct kvm_vcpu *vcpu);
  69void kvm_skip_instr32(struct kvm_vcpu *vcpu, bool is_wide_instr);
  70void kvm_inject_undef32(struct kvm_vcpu *vcpu);
  71void kvm_inject_dabt32(struct kvm_vcpu *vcpu, unsigned long addr);
  72void kvm_inject_pabt32(struct kvm_vcpu *vcpu, unsigned long addr);
  73void kvm_inject_vabt(struct kvm_vcpu *vcpu);
  74
  75static inline void kvm_inject_undefined(struct kvm_vcpu *vcpu)
  76{
  77        kvm_inject_undef32(vcpu);
  78}
  79
  80static inline void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr)
  81{
  82        kvm_inject_dabt32(vcpu, addr);
  83}
  84
  85static inline void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr)
  86{
  87        kvm_inject_pabt32(vcpu, addr);
  88}
  89
  90static inline bool kvm_condition_valid(const struct kvm_vcpu *vcpu)
  91{
  92        return kvm_condition_valid32(vcpu);
  93}
  94
  95static inline void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr)
  96{
  97        kvm_skip_instr32(vcpu, is_wide_instr);
  98}
  99
 100static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
 101{
 102        vcpu->arch.hcr = HCR_GUEST_MASK;
 103}
 104
 105static inline unsigned long *vcpu_hcr(const struct kvm_vcpu *vcpu)
 106{
 107        return (unsigned long *)&vcpu->arch.hcr;
 108}
 109
 110static inline bool vcpu_mode_is_32bit(const struct kvm_vcpu *vcpu)
 111{
 112        return 1;
 113}
 114
 115static inline unsigned long *vcpu_pc(struct kvm_vcpu *vcpu)
 116{
 117        return &vcpu->arch.ctxt.gp_regs.usr_regs.ARM_pc;
 118}
 119
 120static inline unsigned long *vcpu_cpsr(const struct kvm_vcpu *vcpu)
 121{
 122        return (unsigned long *)&vcpu->arch.ctxt.gp_regs.usr_regs.ARM_cpsr;
 123}
 124
 125static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
 126{
 127        *vcpu_cpsr(vcpu) |= PSR_T_BIT;
 128}
 129
 130static inline bool mode_has_spsr(struct kvm_vcpu *vcpu)
 131{
 132        unsigned long cpsr_mode = vcpu->arch.ctxt.gp_regs.usr_regs.ARM_cpsr & MODE_MASK;
 133        return (cpsr_mode > USR_MODE && cpsr_mode < SYSTEM_MODE);
 134}
 135
 136static inline bool vcpu_mode_priv(struct kvm_vcpu *vcpu)
 137{
 138        unsigned long cpsr_mode = vcpu->arch.ctxt.gp_regs.usr_regs.ARM_cpsr & MODE_MASK;
 139        return cpsr_mode > USR_MODE;
 140}
 141
 142static inline u32 kvm_vcpu_get_hsr(const struct kvm_vcpu *vcpu)
 143{
 144        return vcpu->arch.fault.hsr;
 145}
 146
 147static inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu)
 148{
 149        u32 hsr = kvm_vcpu_get_hsr(vcpu);
 150
 151        if (hsr & HSR_CV)
 152                return (hsr & HSR_COND) >> HSR_COND_SHIFT;
 153
 154        return -1;
 155}
 156
 157static inline unsigned long kvm_vcpu_get_hfar(struct kvm_vcpu *vcpu)
 158{
 159        return vcpu->arch.fault.hxfar;
 160}
 161
 162static inline phys_addr_t kvm_vcpu_get_fault_ipa(struct kvm_vcpu *vcpu)
 163{
 164        return ((phys_addr_t)vcpu->arch.fault.hpfar & HPFAR_MASK) << 8;
 165}
 166
 167static inline bool kvm_vcpu_dabt_isvalid(struct kvm_vcpu *vcpu)
 168{
 169        return kvm_vcpu_get_hsr(vcpu) & HSR_ISV;
 170}
 171
 172static inline bool kvm_vcpu_dabt_iswrite(struct kvm_vcpu *vcpu)
 173{
 174        return kvm_vcpu_get_hsr(vcpu) & HSR_WNR;
 175}
 176
 177static inline bool kvm_vcpu_dabt_issext(struct kvm_vcpu *vcpu)
 178{
 179        return kvm_vcpu_get_hsr(vcpu) & HSR_SSE;
 180}
 181
 182static inline int kvm_vcpu_dabt_get_rd(struct kvm_vcpu *vcpu)
 183{
 184        return (kvm_vcpu_get_hsr(vcpu) & HSR_SRT_MASK) >> HSR_SRT_SHIFT;
 185}
 186
 187static inline bool kvm_vcpu_dabt_iss1tw(struct kvm_vcpu *vcpu)
 188{
 189        return kvm_vcpu_get_hsr(vcpu) & HSR_DABT_S1PTW;
 190}
 191
 192static inline bool kvm_vcpu_dabt_is_cm(struct kvm_vcpu *vcpu)
 193{
 194        return !!(kvm_vcpu_get_hsr(vcpu) & HSR_DABT_CM);
 195}
 196
 197/* Get Access Size from a data abort */
 198static inline int kvm_vcpu_dabt_get_as(struct kvm_vcpu *vcpu)
 199{
 200        switch ((kvm_vcpu_get_hsr(vcpu) >> 22) & 0x3) {
 201        case 0:
 202                return 1;
 203        case 1:
 204                return 2;
 205        case 2:
 206                return 4;
 207        default:
 208                kvm_err("Hardware is weird: SAS 0b11 is reserved\n");
 209                return -EFAULT;
 210        }
 211}
 212
 213/* This one is not specific to Data Abort */
 214static inline bool kvm_vcpu_trap_il_is32bit(struct kvm_vcpu *vcpu)
 215{
 216        return kvm_vcpu_get_hsr(vcpu) & HSR_IL;
 217}
 218
 219static inline u8 kvm_vcpu_trap_get_class(struct kvm_vcpu *vcpu)
 220{
 221        return kvm_vcpu_get_hsr(vcpu) >> HSR_EC_SHIFT;
 222}
 223
 224static inline bool kvm_vcpu_trap_is_iabt(struct kvm_vcpu *vcpu)
 225{
 226        return kvm_vcpu_trap_get_class(vcpu) == HSR_EC_IABT;
 227}
 228
 229static inline u8 kvm_vcpu_trap_get_fault(struct kvm_vcpu *vcpu)
 230{
 231        return kvm_vcpu_get_hsr(vcpu) & HSR_FSC;
 232}
 233
 234static inline u8 kvm_vcpu_trap_get_fault_type(struct kvm_vcpu *vcpu)
 235{
 236        return kvm_vcpu_get_hsr(vcpu) & HSR_FSC_TYPE;
 237}
 238
 239static inline bool kvm_vcpu_dabt_isextabt(struct kvm_vcpu *vcpu)
 240{
 241        switch (kvm_vcpu_trap_get_fault(vcpu)) {
 242        case FSC_SEA:
 243        case FSC_SEA_TTW0:
 244        case FSC_SEA_TTW1:
 245        case FSC_SEA_TTW2:
 246        case FSC_SEA_TTW3:
 247        case FSC_SECC:
 248        case FSC_SECC_TTW0:
 249        case FSC_SECC_TTW1:
 250        case FSC_SECC_TTW2:
 251        case FSC_SECC_TTW3:
 252                return true;
 253        default:
 254                return false;
 255        }
 256}
 257
 258static inline u32 kvm_vcpu_hvc_get_imm(struct kvm_vcpu *vcpu)
 259{
 260        return kvm_vcpu_get_hsr(vcpu) & HSR_HVC_IMM_MASK;
 261}
 262
 263static inline unsigned long kvm_vcpu_get_mpidr_aff(struct kvm_vcpu *vcpu)
 264{
 265        return vcpu_cp15(vcpu, c0_MPIDR) & MPIDR_HWID_BITMASK;
 266}
 267
 268static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
 269{
 270        *vcpu_cpsr(vcpu) |= PSR_E_BIT;
 271}
 272
 273static inline bool kvm_vcpu_is_be(struct kvm_vcpu *vcpu)
 274{
 275        return !!(*vcpu_cpsr(vcpu) & PSR_E_BIT);
 276}
 277
 278static inline unsigned long vcpu_data_guest_to_host(struct kvm_vcpu *vcpu,
 279                                                    unsigned long data,
 280                                                    unsigned int len)
 281{
 282        if (kvm_vcpu_is_be(vcpu)) {
 283                switch (len) {
 284                case 1:
 285                        return data & 0xff;
 286                case 2:
 287                        return be16_to_cpu(data & 0xffff);
 288                default:
 289                        return be32_to_cpu(data);
 290                }
 291        } else {
 292                switch (len) {
 293                case 1:
 294                        return data & 0xff;
 295                case 2:
 296                        return le16_to_cpu(data & 0xffff);
 297                default:
 298                        return le32_to_cpu(data);
 299                }
 300        }
 301}
 302
 303static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu,
 304                                                    unsigned long data,
 305                                                    unsigned int len)
 306{
 307        if (kvm_vcpu_is_be(vcpu)) {
 308                switch (len) {
 309                case 1:
 310                        return data & 0xff;
 311                case 2:
 312                        return cpu_to_be16(data & 0xffff);
 313                default:
 314                        return cpu_to_be32(data);
 315                }
 316        } else {
 317                switch (len) {
 318                case 1:
 319                        return data & 0xff;
 320                case 2:
 321                        return cpu_to_le16(data & 0xffff);
 322                default:
 323                        return cpu_to_le32(data);
 324                }
 325        }
 326}
 327
 328#endif /* __ARM_KVM_EMULATE_H__ */
 329