14 #include <linux/kvm_host.h>
15 #include <asm/kvm_emulate.h>
16 #include <asm/kvm_mmu.h>
17 #include <asm/kvm_nested.h>
19 #if !defined (__KVM_NVHE_HYPERVISOR__) && !defined (__KVM_VHE_HYPERVISOR__)
20 #error Hypervisor code only!
27 if (unlikely(vcpu_has_nv(vcpu)))
29 else if (__vcpu_read_sys_reg_from_cpu(reg, &val))
32 return __vcpu_sys_reg(vcpu, reg);
37 if (unlikely(vcpu_has_nv(vcpu)))
39 else if (!__vcpu_write_sys_reg_to_cpu(val, reg))
40 __vcpu_sys_reg(vcpu, reg) = val;
46 if (unlikely(vcpu_has_nv(vcpu))) {
47 if (target_mode == PSR_MODE_EL1h)
51 }
else if (has_vhe()) {
52 write_sysreg_el1(val, SYS_SPSR);
54 __vcpu_sys_reg(vcpu, SPSR_EL1) = val;
61 write_sysreg(val, spsr_abt);
63 vcpu->arch.ctxt.spsr_abt = val;
69 write_sysreg(val, spsr_und);
71 vcpu->arch.ctxt.spsr_und = val;
92 enum exception_type type)
94 unsigned long sctlr, vbar, old,
new, mode;
97 mode = *vcpu_cpsr(vcpu) & (PSR_MODE_MASK | PSR_MODE32_BIT);
99 if (mode == target_mode)
100 exc_offset = CURRENT_EL_SP_ELx_VECTOR;
101 else if ((mode | PSR_MODE_THREAD_BIT) == target_mode)
102 exc_offset = CURRENT_EL_SP_EL0_VECTOR;
103 else if (!(mode & PSR_MODE32_BIT))
104 exc_offset = LOWER_EL_AArch64_VECTOR;
106 exc_offset = LOWER_EL_AArch32_VECTOR;
108 switch (target_mode) {
124 *vcpu_pc(vcpu) = vbar + exc_offset + type;
126 old = *vcpu_cpsr(vcpu);
129 new |= (old & PSR_N_BIT);
130 new |= (old & PSR_Z_BIT);
131 new |= (old & PSR_C_BIT);
132 new |= (old & PSR_V_BIT);
134 if (kvm_has_mte(kern_hyp_va(vcpu->kvm)))
137 new |= (old & PSR_DIT_BIT);
145 new |= (old & PSR_PAN_BIT);
146 if (!(sctlr & SCTLR_EL1_SPAN))
157 if (sctlr & SCTLR_ELx_DSSBS)
170 *vcpu_cpsr(vcpu) =
new;
195 unsigned long old,
new;
197 old = *vcpu_cpsr(vcpu);
200 new |= (old & PSR_AA32_N_BIT);
201 new |= (old & PSR_AA32_Z_BIT);
202 new |= (old & PSR_AA32_C_BIT);
203 new |= (old & PSR_AA32_V_BIT);
204 new |= (old & PSR_AA32_Q_BIT);
210 new |= (old & PSR_AA32_DIT_BIT);
215 new |= PSR_AA32_SSBS_BIT;
220 new |= (old & PSR_AA32_PAN_BIT);
221 if (!(sctlr & BIT(23)))
222 new |= PSR_AA32_PAN_BIT;
229 new |= (old & PSR_AA32_GE_MASK);
238 new |= PSR_AA32_E_BIT;
244 new |= (old & PSR_AA32_A_BIT);
245 if (mode != PSR_AA32_MODE_UND && mode != PSR_AA32_MODE_SVC)
246 new |= PSR_AA32_A_BIT;
251 new |= PSR_AA32_I_BIT;
257 new |= (old & PSR_AA32_F_BIT);
258 if (mode == PSR_AA32_MODE_FIQ)
259 new |= PSR_AA32_F_BIT;
265 new |= PSR_AA32_T_BIT;
288 unsigned long spsr = *vcpu_cpsr(vcpu);
289 bool is_thumb = (spsr & PSR_AA32_T_BIT);
294 return_address = *vcpu_pc(vcpu);
299 case PSR_AA32_MODE_ABT:
301 vcpu_gp_regs(vcpu)->compat_lr_abt = return_address;
304 case PSR_AA32_MODE_UND:
306 vcpu_gp_regs(vcpu)->compat_lr_und = return_address;
311 if (sctlr & (1 << 13))
312 vect_offset += 0xffff0000;
316 *vcpu_pc(vcpu) = vect_offset;
321 if (vcpu_el1_is_32bit(vcpu)) {
322 switch (vcpu_get_flag(vcpu, EXCEPT_MASK)) {
323 case unpack_vcpu_flag(EXCEPT_AA32_UND):
326 case unpack_vcpu_flag(EXCEPT_AA32_IABT):
329 case unpack_vcpu_flag(EXCEPT_AA32_DABT):
337 switch (vcpu_get_flag(vcpu, EXCEPT_MASK)) {
338 case unpack_vcpu_flag(EXCEPT_AA64_EL1_SYNC):
342 case unpack_vcpu_flag(EXCEPT_AA64_EL2_SYNC):
346 case unpack_vcpu_flag(EXCEPT_AA64_EL2_IRQ):
367 if (vcpu_get_flag(vcpu, PENDING_EXCEPTION)) {
369 vcpu_clear_flag(vcpu, PENDING_EXCEPTION);
370 vcpu_clear_flag(vcpu, EXCEPT_MASK);
371 }
else if (vcpu_get_flag(vcpu, INCREMENT_PC)) {
373 vcpu_clear_flag(vcpu, INCREMENT_PC);
static void kvm_skip_instr(struct kvm_vcpu *vcpu)
static void enter_exception64(struct kvm_vcpu *vcpu, unsigned long target_mode, enum exception_type type)
static void __vcpu_write_spsr_abt(struct kvm_vcpu *vcpu, u64 val)
static const u8 return_offsets[8][2]
static void kvm_inject_exception(struct kvm_vcpu *vcpu)
void __kvm_adjust_pc(struct kvm_vcpu *vcpu)
static void enter_exception32(struct kvm_vcpu *vcpu, u32 mode, u32 vect_offset)
static void __vcpu_write_spsr(struct kvm_vcpu *vcpu, unsigned long target_mode, u64 val)
static void __vcpu_write_spsr_und(struct kvm_vcpu *vcpu, u64 val)
static void __vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg)
static u64 __vcpu_read_sys_reg(const struct kvm_vcpu *vcpu, int reg)
static unsigned long get_except32_cpsr(struct kvm_vcpu *vcpu, u32 mode)
u64 vcpu_read_sys_reg(const struct kvm_vcpu *vcpu, int reg)
void vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg)