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