127b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier/* 227b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * (not much of an) Emulation layer for 32bit guests. 327b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * 427b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * Copyright (C) 2012,2013 - ARM Ltd 527b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * Author: Marc Zyngier <marc.zyngier@arm.com> 627b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * 727b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * based on arch/arm/kvm/emulate.c 827b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * Copyright (C) 2012 - Virtual Open Systems and Columbia University 927b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * Author: Christoffer Dall <c.dall@virtualopensystems.com> 1027b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * 1127b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * This program is free software: you can redistribute it and/or modify 1227b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * it under the terms of the GNU General Public License version 2 as 1327b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * published by the Free Software Foundation. 1427b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * 1527b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * This program is distributed in the hope that it will be useful, 1627b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * but WITHOUT ANY WARRANTY; without even the implied warranty of 1727b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1827b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * GNU General Public License for more details. 1927b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * 2027b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * You should have received a copy of the GNU General Public License 2127b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * along with this program. If not, see <http://www.gnu.org/licenses/>. 2227b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier */ 2327b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 2427b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier#include <linux/kvm_host.h> 2527b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier#include <asm/kvm_emulate.h> 2627b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 2727b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier/* 2827b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * stolen from arch/arm/kernel/opcodes.c 2927b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * 3027b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * condition code lookup table 3127b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * index into the table is test code: EQ, NE, ... LT, GT, AL, NV 3227b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * 3327b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * bit position in short is condition code: NZCV 3427b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier */ 3527b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngierstatic const unsigned short cc_map[16] = { 3627b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 0xF0F0, /* EQ == Z set */ 3727b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 0x0F0F, /* NE */ 3827b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 0xCCCC, /* CS == C set */ 3927b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 0x3333, /* CC */ 4027b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 0xFF00, /* MI == N set */ 4127b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 0x00FF, /* PL */ 4227b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 0xAAAA, /* VS == V set */ 4327b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 0x5555, /* VC */ 4427b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 0x0C0C, /* HI == C set && Z clear */ 4527b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 0xF3F3, /* LS == C clear || Z set */ 4627b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 0xAA55, /* GE == (N==V) */ 4727b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 0x55AA, /* LT == (N!=V) */ 4827b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 0x0A05, /* GT == (!Z && (N==V)) */ 4927b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 0xF5FA, /* LE == (Z || (N!=V)) */ 5027b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 0xFFFF, /* AL always */ 5127b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 0 /* NV */ 5227b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier}; 5327b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 5427b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngierstatic int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu) 5527b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier{ 5627b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier u32 esr = kvm_vcpu_get_hsr(vcpu); 5727b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 5827b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier if (esr & ESR_EL2_CV) 5927b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier return (esr & ESR_EL2_COND) >> ESR_EL2_COND_SHIFT; 6027b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 6127b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier return -1; 6227b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier} 6327b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 6427b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier/* 6527b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * Check if a trapped instruction should have been executed or not. 6627b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier */ 6727b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngierbool kvm_condition_valid32(const struct kvm_vcpu *vcpu) 6827b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier{ 6927b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier unsigned long cpsr; 7027b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier u32 cpsr_cond; 7127b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier int cond; 7227b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 7327b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier /* Top two bits non-zero? Unconditional. */ 7427b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier if (kvm_vcpu_get_hsr(vcpu) >> 30) 7527b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier return true; 7627b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 7727b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier /* Is condition field valid? */ 7827b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier cond = kvm_vcpu_get_condition(vcpu); 7927b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier if (cond == 0xE) 8027b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier return true; 8127b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 8227b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier cpsr = *vcpu_cpsr(vcpu); 8327b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 8427b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier if (cond < 0) { 8527b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier /* This can happen in Thumb mode: examine IT state. */ 8627b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier unsigned long it; 8727b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 8827b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier it = ((cpsr >> 8) & 0xFC) | ((cpsr >> 25) & 0x3); 8927b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 9027b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier /* it == 0 => unconditional. */ 9127b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier if (it == 0) 9227b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier return true; 9327b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 9427b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier /* The cond for this insn works out as the top 4 bits. */ 9527b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier cond = (it >> 4); 9627b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier } 9727b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 9827b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier cpsr_cond = cpsr >> 28; 9927b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 10027b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier if (!((cc_map[cond] >> cpsr_cond) & 1)) 10127b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier return false; 10227b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 10327b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier return true; 10427b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier} 10527b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 10627b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier/** 10727b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * adjust_itstate - adjust ITSTATE when emulating instructions in IT-block 10827b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * @vcpu: The VCPU pointer 10927b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * 11027b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * When exceptions occur while instructions are executed in Thumb IF-THEN 11127b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * blocks, the ITSTATE field of the CPSR is not advanced (updated), so we have 11227b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * to do this little bit of work manually. The fields map like this: 11327b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * 11427b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * IT[7:0] -> CPSR[26:25],CPSR[15:10] 11527b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier */ 11627b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngierstatic void kvm_adjust_itstate(struct kvm_vcpu *vcpu) 11727b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier{ 11827b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier unsigned long itbits, cond; 11927b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier unsigned long cpsr = *vcpu_cpsr(vcpu); 12027b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier bool is_arm = !(cpsr & COMPAT_PSR_T_BIT); 12127b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 12227b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier BUG_ON(is_arm && (cpsr & COMPAT_PSR_IT_MASK)); 12327b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 12427b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier if (!(cpsr & COMPAT_PSR_IT_MASK)) 12527b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier return; 12627b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 12727b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier cond = (cpsr & 0xe000) >> 13; 12827b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier itbits = (cpsr & 0x1c00) >> (10 - 2); 12927b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier itbits |= (cpsr & (0x3 << 25)) >> 25; 13027b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 13127b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier /* Perform ITAdvance (see page A2-52 in ARM DDI 0406C) */ 13227b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier if ((itbits & 0x7) == 0) 13327b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier itbits = cond = 0; 13427b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier else 13527b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier itbits = (itbits << 1) & 0x1f; 13627b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 13727b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier cpsr &= ~COMPAT_PSR_IT_MASK; 13827b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier cpsr |= cond << 13; 13927b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier cpsr |= (itbits & 0x1c) << (10 - 2); 14027b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier cpsr |= (itbits & 0x3) << 25; 14127b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier *vcpu_cpsr(vcpu) = cpsr; 14227b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier} 14327b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 14427b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier/** 14527b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * kvm_skip_instr - skip a trapped instruction and proceed to the next 14627b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier * @vcpu: The vcpu pointer 14727b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier */ 14827b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngiervoid kvm_skip_instr32(struct kvm_vcpu *vcpu, bool is_wide_instr) 14927b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier{ 15027b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier bool is_thumb; 15127b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier 15227b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier is_thumb = !!(*vcpu_cpsr(vcpu) & COMPAT_PSR_T_BIT); 15327b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier if (is_thumb && !is_wide_instr) 15427b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier *vcpu_pc(vcpu) += 2; 15527b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier else 15627b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier *vcpu_pc(vcpu) += 4; 15727b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier kvm_adjust_itstate(vcpu); 15827b190bd9fbfee34536cb858f0b5924d294aac38Marc Zyngier} 159