From patchwork Wed Oct 24 11:25:15 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rusty Russell X-Patchwork-Id: 1637731 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 17D99DFABE for ; Wed, 24 Oct 2012 11:31:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758435Ab2JXLbd (ORCPT ); Wed, 24 Oct 2012 07:31:33 -0400 Received: from ozlabs.org ([203.10.76.45]:47635 "EHLO ozlabs.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758264Ab2JXL34 (ORCPT ); Wed, 24 Oct 2012 07:29:56 -0400 Received: by ozlabs.org (Postfix, from userid 1011) id BA1A72C01C2; Wed, 24 Oct 2012 22:29:54 +1100 (EST) From: Rusty Russell To: Will Deacon Cc: Christoffer Dall , "kvm@vger.kernel.org" , dave.martin@linaro.org, Rusty Russell Subject: [PATCH 02/10] kvm: split out instruction decode from emulation. Date: Wed, 24 Oct 2012 21:55:15 +1030 Message-Id: <1351077923-17977-3-git-send-email-rusty@rustcorp.com.au> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1351077923-17977-1-git-send-email-rusty@rustcorp.com.au> References: <20121022174555.GD26619@mudshark.cambridge.arm.com> <1351077923-17977-1-git-send-email-rusty@rustcorp.com.au> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Rusty Russell This adds more fields which we need to store in the struct arm_insn, so execute() knows what to do. Signed-off-by: Rusty Russell --- arch/arm/kvm/emulate.c | 80 ++++++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c index e4fc12b..05b534f 100644 --- a/arch/arm/kvm/emulate.c +++ b/arch/arm/kvm/emulate.c @@ -303,11 +303,12 @@ struct arm_insn { u8 type; u8 Rt, Rn, Rm; u8 shift_n; + u32 offset_addr; /* Common decoding */ u8 len; bool sign_extend; - bool w; + bool w, W, U, P; }; struct arm_decode { @@ -315,7 +316,7 @@ struct arm_decode { u32 opc; u32 opc_mask; - bool (*decode)(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio, + bool (*decode)(struct kvm_vcpu *vcpu, unsigned long instr, struct arm_insn *ai); struct arm_insn template; @@ -385,31 +386,24 @@ u32 shift(u32 value, u8 N, enum SRType type, u8 amount, bool carry_in) return value & mask; } -static bool decode_arm_wb(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio, - unsigned long instr, const struct arm_insn *ai) +static bool decode_arm_wb(struct kvm_vcpu *vcpu, unsigned long instr, + struct arm_insn *ai) { - u8 Rt = (instr >> 12) & 0xf; - u8 Rn = (instr >> 16) & 0xf; - u8 W = (instr >> 21) & 1; - u8 U = (instr >> 23) & 1; - u8 P = (instr >> 24) & 1; - u32 base_addr = *vcpu_reg(vcpu, Rn); - u32 offset_addr, offset; + u32 base_addr, offset; - /* - * Technically this is allowed in certain circumstances, - * but we don't support it. - */ - if (Rt == 15 || Rn == 15) - return false; + ai->Rt = (instr >> 12) & 0xf; + ai->Rn = (instr >> 16) & 0xf; + ai->W = (instr >> 21) & 1; + ai->U = (instr >> 23) & 1; + ai->P = (instr >> 24) & 1; + + base_addr = *vcpu_reg(vcpu, ai->Rn); - if (P && !W) { + if (ai->P && !ai->W) { kvm_err("Decoding operation with valid ISV?\n"); return false; } - vcpu->arch.mmio.rd = Rt; - if (ai->register_form) { /* Register operation */ enum SRType s_type; @@ -425,46 +419,56 @@ static bool decode_arm_wb(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio, } /* Handle Writeback */ - if (U) - offset_addr = base_addr + offset; + if (ai->U) + ai->offset_addr = base_addr + offset; else - offset_addr = base_addr - offset; - *vcpu_reg(vcpu, Rn) = offset_addr; + ai->offset_addr = base_addr - offset; return true; } -static bool decode_arm_ls(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio, +static bool decode_arm_ls(struct kvm_vcpu *vcpu, unsigned long instr, struct arm_insn *ai) { u8 A = (instr >> 25) & 1; - mmio->is_write = ai->w; - mmio->len = ai->len; - vcpu->arch.mmio.sign_extend = false; - ai->register_form = A; ai->imm = instr & 0xfff; ai->Rm = instr & 0xf; ai->type = (instr >> 5) & 0x3; ai->shift_n = (instr >> 7) & 0x1f; - return decode_arm_wb(vcpu, mmio, instr, ai); + return decode_arm_wb(vcpu, instr, ai); } -static bool decode_arm_extra(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio, +static bool decode_arm_extra(struct kvm_vcpu *vcpu, unsigned long instr, struct arm_insn *ai) { - mmio->is_write = ai->w; - mmio->len = ai->len; - vcpu->arch.mmio.sign_extend = ai->sign_extend; - ai->register_form = !((instr >> 22) & 1); ai->imm = ((instr >> 4) & 0xf0) | (instr & 0xf); ai->Rm = instr & 0xf; ai->type = 0; /* SRType_LSL */ ai->shift_n = 0; - return decode_arm_wb(vcpu, mmio, instr, ai); + return decode_arm_wb(vcpu, instr, ai); +} + +static bool execute(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio, + const struct arm_insn *ai) +{ + /* + * Technically this is allowed in certain circumstances, + * but we don't support it. + */ + if (ai->Rt == 15 || ai->Rn == 15) + return false; + + mmio->is_write = ai->w; + mmio->len = ai->len; + vcpu->arch.mmio.sign_extend = ai->sign_extend; + + vcpu->arch.mmio.rd = ai->Rt; + *vcpu_reg(vcpu, ai->Rn) = ai->offset_addr; + return true; } /* @@ -553,7 +557,9 @@ static bool kvm_decode_arm_ls(struct kvm_vcpu *vcpu, unsigned long instr, const struct arm_decode *d = &arm_decode[i]; if ((instr & d->opc_mask) == d->opc) { struct arm_insn ai = d->template; - return d->decode(vcpu, mmio, instr, &ai); + if (!d->decode(vcpu, instr, &ai)) + return false; + return execute(vcpu, mmio, &ai); } } return false;