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 31bool kvm_condition_valid(struct kvm_vcpu *vcpu); 32void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr); 33void kvm_inject_undefined(struct kvm_vcpu *vcpu); 34void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr); 35void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr); 36 37static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) 38{ 39 vcpu->arch.hcr = HCR_GUEST_MASK; 40} 41 42static inline unsigned long vcpu_get_hcr(struct kvm_vcpu *vcpu) 43{ 44 return vcpu->arch.hcr; 45} 46 47static inline void vcpu_set_hcr(struct kvm_vcpu *vcpu, unsigned long hcr) 48{ 49 vcpu->arch.hcr = hcr; 50} 51 52static inline bool vcpu_mode_is_32bit(struct kvm_vcpu *vcpu) 53{ 54 return 1; 55} 56 57static inline unsigned long *vcpu_pc(struct kvm_vcpu *vcpu) 58{ 59 return &vcpu->arch.regs.usr_regs.ARM_pc; 60} 61 62static inline unsigned long *vcpu_cpsr(struct kvm_vcpu *vcpu) 63{ 64 return &vcpu->arch.regs.usr_regs.ARM_cpsr; 65} 66 67static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu) 68{ 69 *vcpu_cpsr(vcpu) |= PSR_T_BIT; 70} 71 72static inline bool mode_has_spsr(struct kvm_vcpu *vcpu) 73{ 74 unsigned long cpsr_mode = vcpu->arch.regs.usr_regs.ARM_cpsr & MODE_MASK; 75 return (cpsr_mode > USR_MODE && cpsr_mode < SYSTEM_MODE); 76} 77 78static inline bool vcpu_mode_priv(struct kvm_vcpu *vcpu) 79{ 80 unsigned long cpsr_mode = vcpu->arch.regs.usr_regs.ARM_cpsr & MODE_MASK; 81 return cpsr_mode > USR_MODE;; 82} 83 84static inline u32 kvm_vcpu_get_hsr(struct kvm_vcpu *vcpu) 85{ 86 return vcpu->arch.fault.hsr; 87} 88 89static inline unsigned long kvm_vcpu_get_hfar(struct kvm_vcpu *vcpu) 90{ 91 return vcpu->arch.fault.hxfar; 92} 93 94static inline phys_addr_t kvm_vcpu_get_fault_ipa(struct kvm_vcpu *vcpu) 95{ 96 return ((phys_addr_t)vcpu->arch.fault.hpfar & HPFAR_MASK) << 8; 97} 98 99static inline unsigned long kvm_vcpu_get_hyp_pc(struct kvm_vcpu *vcpu) 100{ 101 return vcpu->arch.fault.hyp_pc; 102} 103 104static inline bool kvm_vcpu_dabt_isvalid(struct kvm_vcpu *vcpu) 105{ 106 return kvm_vcpu_get_hsr(vcpu) & HSR_ISV; 107} 108 109static inline bool kvm_vcpu_dabt_iswrite(struct kvm_vcpu *vcpu) 110{ 111 return kvm_vcpu_get_hsr(vcpu) & HSR_WNR; 112} 113 114static inline bool kvm_vcpu_dabt_issext(struct kvm_vcpu *vcpu) 115{ 116 return kvm_vcpu_get_hsr(vcpu) & HSR_SSE; 117} 118 119static inline int kvm_vcpu_dabt_get_rd(struct kvm_vcpu *vcpu) 120{ 121 return (kvm_vcpu_get_hsr(vcpu) & HSR_SRT_MASK) >> HSR_SRT_SHIFT; 122} 123 124static inline bool kvm_vcpu_dabt_isextabt(struct kvm_vcpu *vcpu) 125{ 126 return kvm_vcpu_get_hsr(vcpu) & HSR_DABT_EA; 127} 128 129static inline bool kvm_vcpu_dabt_iss1tw(struct kvm_vcpu *vcpu) 130{ 131 return kvm_vcpu_get_hsr(vcpu) & HSR_DABT_S1PTW; 132} 133 134/* Get Access Size from a data abort */ 135static inline int kvm_vcpu_dabt_get_as(struct kvm_vcpu *vcpu) 136{ 137 switch ((kvm_vcpu_get_hsr(vcpu) >> 22) & 0x3) { 138 case 0: 139 return 1; 140 case 1: 141 return 2; 142 case 2: 143 return 4; 144 default: 145 kvm_err("Hardware is weird: SAS 0b11 is reserved\n"); 146 return -EFAULT; 147 } 148} 149 150/* This one is not specific to Data Abort */ 151static inline bool kvm_vcpu_trap_il_is32bit(struct kvm_vcpu *vcpu) 152{ 153 return kvm_vcpu_get_hsr(vcpu) & HSR_IL; 154} 155 156static inline u8 kvm_vcpu_trap_get_class(struct kvm_vcpu *vcpu) 157{ 158 return kvm_vcpu_get_hsr(vcpu) >> HSR_EC_SHIFT; 159} 160 161static inline bool kvm_vcpu_trap_is_iabt(struct kvm_vcpu *vcpu) 162{ 163 return kvm_vcpu_trap_get_class(vcpu) == HSR_EC_IABT; 164} 165 166static inline u8 kvm_vcpu_trap_get_fault(struct kvm_vcpu *vcpu) 167{ 168 return kvm_vcpu_get_hsr(vcpu) & HSR_FSC; 169} 170 171static inline u8 kvm_vcpu_trap_get_fault_type(struct kvm_vcpu *vcpu) 172{ 173 return kvm_vcpu_get_hsr(vcpu) & HSR_FSC_TYPE; 174} 175 176static inline u32 kvm_vcpu_hvc_get_imm(struct kvm_vcpu *vcpu) 177{ 178 return kvm_vcpu_get_hsr(vcpu) & HSR_HVC_IMM_MASK; 179} 180 181static inline unsigned long kvm_vcpu_get_mpidr_aff(struct kvm_vcpu *vcpu) 182{ 183 return vcpu->arch.cp15[c0_MPIDR] & MPIDR_HWID_BITMASK; 184} 185 186static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu) 187{ 188 *vcpu_cpsr(vcpu) |= PSR_E_BIT; 189} 190 191static inline bool kvm_vcpu_is_be(struct kvm_vcpu *vcpu) 192{ 193 return !!(*vcpu_cpsr(vcpu) & PSR_E_BIT); 194} 195 196static inline unsigned long vcpu_data_guest_to_host(struct kvm_vcpu *vcpu, 197 unsigned long data, 198 unsigned int len) 199{ 200 if (kvm_vcpu_is_be(vcpu)) { 201 switch (len) { 202 case 1: 203 return data & 0xff; 204 case 2: 205 return be16_to_cpu(data & 0xffff); 206 default: 207 return be32_to_cpu(data); 208 } 209 } else { 210 switch (len) { 211 case 1: 212 return data & 0xff; 213 case 2: 214 return le16_to_cpu(data & 0xffff); 215 default: 216 return le32_to_cpu(data); 217 } 218 } 219} 220 221static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu, 222 unsigned long data, 223 unsigned int len) 224{ 225 if (kvm_vcpu_is_be(vcpu)) { 226 switch (len) { 227 case 1: 228 return data & 0xff; 229 case 2: 230 return cpu_to_be16(data & 0xffff); 231 default: 232 return cpu_to_be32(data); 233 } 234 } else { 235 switch (len) { 236 case 1: 237 return data & 0xff; 238 case 2: 239 return cpu_to_le16(data & 0xffff); 240 default: 241 return cpu_to_le32(data); 242 } 243 } 244} 245 246#endif /* __ARM_KVM_EMULATE_H__ */ 247