From: Rusty Russell <rusty@rustcorp.com.au>
To: Will Deacon <will.deacon@arm.com>
Cc: Christoffer Dall <c.dall@virtualopensystems.com>,
"kvm@vger.kernel.org" <kvm@vger.kernel.org>,
dave.martin@linaro.org, Rusty Russell <rusty.russell@linaro.org>
Subject: [PATCH 03/10] kvm: split out instruction decode from emulation (thumb instructions).
Date: Wed, 24 Oct 2012 21:55:16 +1030 [thread overview]
Message-ID: <1351077923-17977-4-git-send-email-rusty@rustcorp.com.au> (raw)
In-Reply-To: <1351077923-17977-1-git-send-email-rusty@rustcorp.com.au>
From: Rusty Russell <rusty.russell@linaro.org>
Add thumb info to struct arm_insn, and use that to store decode
information for later handling in execute_thumb().
Signed-off-by: Rusty Russell <rusty.russell@linaro.org>
---
arch/arm/kvm/emulate.c | 120 +++++++++++++++++++++++++++++-------------------
1 file changed, 74 insertions(+), 46 deletions(-)
diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c
index 05b534f..882db33 100644
--- a/arch/arm/kvm/emulate.c
+++ b/arch/arm/kvm/emulate.c
@@ -301,7 +301,7 @@ struct arm_insn {
bool register_form;
u32 imm;
u8 type;
- u8 Rt, Rn, Rm;
+ u8 Rt, Rn, Rm, Rd;
u8 shift_n;
u32 offset_addr;
@@ -309,6 +309,21 @@ struct arm_insn {
u8 len;
bool sign_extend;
bool w, W, U, P;
+
+ /* Thumb encoding */
+ bool is_thumb, is_thumb32;
+ union {
+ struct {
+ u8 opcode;
+ u8 mask;
+ } t16;
+
+ struct {
+ u8 op1;
+ u8 op2;
+ u8 op2_mask;
+ } t32;
+ };
};
struct arm_decode {
@@ -565,7 +580,7 @@ static bool kvm_decode_arm_ls(struct kvm_vcpu *vcpu, unsigned long instr,
return false;
}
-struct thumb_instr {
+struct thumb_decode {
bool is32;
union {
@@ -581,86 +596,95 @@ struct thumb_instr {
} t32;
};
- bool (*decode)(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio,
- unsigned long instr, const struct thumb_instr *ti);
+ bool (*decode)(struct kvm_vcpu *vcpu,
+ unsigned long instr, struct arm_insn *ti);
};
-static bool decode_thumb_wb(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio,
- unsigned long instr)
+static bool decode_thumb_wb(struct kvm_vcpu *vcpu,
+ unsigned long instr, struct arm_insn *ti)
{
- bool P = (instr >> 10) & 1;
- bool U = (instr >> 9) & 1;
u8 imm8 = instr & 0xff;
u32 offset_addr = vcpu->arch.hxfar;
- u8 Rn = (instr >> 16) & 0xf;
-
- vcpu->arch.mmio.rd = (instr >> 12) & 0xf;
- if (kvm_vcpu_reg_is_pc(vcpu, Rn))
- return false;
+ ti->P = (instr >> 10) & 1;
+ ti->U = (instr >> 9) & 1;
+ ti->Rn = (instr >> 16) & 0xf;
+ ti->Rd = (instr >> 12) & 0xf;
/* Handle Writeback */
- if (!P && U)
- *vcpu_reg(vcpu, Rn) = offset_addr + imm8;
- else if (!P && !U)
- *vcpu_reg(vcpu, Rn) = offset_addr - imm8;
+ if (!ti->P && ti->U)
+ ti->offset_addr = offset_addr + imm8;
+ else if (!ti->P && !ti->U)
+ ti->offset_addr = offset_addr - imm8;
return true;
}
-static bool decode_thumb_str(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio,
- unsigned long instr, const struct thumb_instr *ti)
+static bool decode_thumb_str(struct kvm_vcpu *vcpu,
+ unsigned long instr, struct arm_insn *ti)
{
u8 op1 = (instr >> (16 + 5)) & 0x7;
u8 op2 = (instr >> 6) & 0x3f;
- mmio->is_write = true;
- vcpu->arch.mmio.sign_extend = false;
+ ti->W = true;
+ ti->sign_extend = false;
switch (op1) {
- case 0x0: mmio->len = 1; break;
- case 0x1: mmio->len = 2; break;
- case 0x2: mmio->len = 4; break;
+ case 0x0: ti->len = 1; break;
+ case 0x1: ti->len = 2; break;
+ case 0x2: ti->len = 4; break;
default:
return false; /* Only register write-back versions! */
}
if ((op2 & 0x24) == 0x24) {
/* STRB (immediate, thumb, W=1) */
- return decode_thumb_wb(vcpu, mmio, instr);
+ return decode_thumb_wb(vcpu, instr, ti);
}
return false;
}
-static bool decode_thumb_ldr(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio,
- unsigned long instr, const struct thumb_instr *ti)
+static bool decode_thumb_ldr(struct kvm_vcpu *vcpu,
+ unsigned long instr, struct arm_insn *ti)
{
u8 op1 = (instr >> (16 + 7)) & 0x3;
u8 op2 = (instr >> 6) & 0x3f;
- mmio->is_write = false;
+ ti->W = false;
switch (ti->t32.op2 & 0x7) {
- case 0x1: mmio->len = 1; break;
- case 0x3: mmio->len = 2; break;
- case 0x5: mmio->len = 4; break;
+ case 0x1: ti->len = 1; break;
+ case 0x3: ti->len = 2; break;
+ case 0x5: ti->len = 4; break;
}
if (op1 == 0x0)
- vcpu->arch.mmio.sign_extend = false;
+ ti->sign_extend = false;
else if (op1 == 0x2 && (ti->t32.op2 & 0x7) != 0x5)
- vcpu->arch.mmio.sign_extend = true;
+ ti->sign_extend = true;
else
return false; /* Only register write-back versions! */
if ((op2 & 0x24) == 0x24) {
/* LDR{S}X (immediate, thumb, W=1) */
- return decode_thumb_wb(vcpu, mmio, instr);
+ return decode_thumb_wb(vcpu, instr, ti);
}
return false;
}
+static bool execute_thumb(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio,
+ const struct arm_insn *ti)
+{
+ if (kvm_vcpu_reg_is_pc(vcpu, ti->Rn))
+ return false;
+
+ if (!ti->P)
+ *vcpu_reg(vcpu, ti->Rn) = ti->offset_addr;
+ vcpu->arch.mmio.sign_extend = ti->sign_extend;
+ return true;
+}
+
/*
* We only support instruction decoding for valid reasonable MMIO operations
* where trapping them do not provide sufficient information in the HSR (no
@@ -673,7 +697,7 @@ static bool decode_thumb_ldr(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio,
* - any load/store dual
* - anything with the PC as the dest register
*/
-static const struct thumb_instr thumb_instr[] = {
+static const struct thumb_decode thumb_decode[] = {
/**************** 32-bit Thumb instructions **********************/
/* Store single data item: Op1 == 11, Op2 == 000xxx0 */
{ .is32 = true, .t32 = { 3, 0x00, 0x71}, decode_thumb_str },
@@ -686,15 +710,17 @@ static const struct thumb_instr thumb_instr[] = {
};
-
static bool kvm_decode_thumb_ls(struct kvm_vcpu *vcpu, unsigned long instr,
struct kvm_exit_mmio *mmio)
{
- bool is32 = is_wide_instruction(instr);
- bool is16 = !is32;
- struct thumb_instr tinstr; /* re-use to pass on already decoded info */
+ struct arm_insn tinstr; /* re-use to pass on already decoded info */
+ bool is16;
int i;
+ tinstr.is_thumb = true;
+ tinstr.is_thumb32 = is_wide_instruction(instr);
+
+ is16 = !tinstr.is_thumb32;
if (is16) {
tinstr.t16.opcode = (instr >> 10) & 0x3f;
} else {
@@ -702,22 +728,24 @@ static bool kvm_decode_thumb_ls(struct kvm_vcpu *vcpu, unsigned long instr,
tinstr.t32.op2 = (instr >> (16 + 4)) & 0x7f;
}
- for (i = 0; i < ARRAY_SIZE(thumb_instr); i++) {
- const struct thumb_instr *ti = &thumb_instr[i];
- if (ti->is32 != is32)
+ for (i = 0; i < ARRAY_SIZE(thumb_decode); i++) {
+ const struct thumb_decode *td = &thumb_decode[i];
+ if (td->is32 != tinstr.is_thumb32)
continue;
if (is16) {
- if ((tinstr.t16.opcode & ti->t16.mask) != ti->t16.opcode)
+ if ((tinstr.t16.opcode & td->t16.mask) != td->t16.opcode)
continue;
} else {
- if (ti->t32.op1 != tinstr.t32.op1)
+ if (td->t32.op1 != tinstr.t32.op1)
continue;
- if ((ti->t32.op2_mask & tinstr.t32.op2) != ti->t32.op2)
+ if ((td->t32.op2_mask & tinstr.t32.op2) != td->t32.op2)
continue;
}
- return ti->decode(vcpu, mmio, instr, &tinstr);
+ if (!td->decode(vcpu, instr, &tinstr))
+ return false;
+ return execute_thumb(vcpu, mmio, &tinstr);
}
return false;
--
1.7.10.4
next prev parent reply other threads:[~2012-10-24 11:29 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-09-05 7:58 [PATCH 0/3] KVM_VCPU_GET_REG_LIST API Rusty Russell
2012-09-05 7:58 ` [PATCH 1/3] KVM: Move KVM_SET_ONE_REG/KVM_GET_ONE_REG to generic code Rusty Russell
2012-09-19 14:17 ` Alexander Graf
2012-09-05 7:58 ` [PATCH 2/3] KVM: Add KVM_REG_SIZE() helper Rusty Russell
2012-09-19 14:18 ` Alexander Graf
2012-09-05 7:58 ` [PATCH 3/3] KVM: Add KVM_VCPU_GET_REG_LIST/KVM_CAP_REG_LIST Rusty Russell
2012-09-19 14:22 ` Alexander Graf
2012-10-10 18:12 ` Marcelo Tosatti
2012-10-11 8:11 ` Rusty Russell
2012-10-18 14:45 ` [PATCH 0/3] KVM_VCPU_GET_REG_LIST API Avi Kivity
2012-10-19 0:36 ` Rusty Russell
2012-10-19 6:19 ` Rusty Russell
2012-10-19 16:06 ` Christoffer Dall
2012-10-22 3:09 ` Rusty Russell
2012-10-22 17:45 ` Will Deacon
2012-10-22 18:11 ` Christoffer Dall
2012-10-24 11:25 ` RFC: Move kvm's instruction decoding into generic code Rusty Russell
2012-10-24 11:25 ` [PATCH 01/10] kvm: split out instruction structure from decoding method Rusty Russell
2012-10-24 11:25 ` [PATCH 02/10] kvm: split out instruction decode from emulation Rusty Russell
2012-10-24 11:25 ` Rusty Russell [this message]
2012-10-24 11:25 ` [PATCH 04/10] kvm: completely separate decoding from execution Rusty Russell
2012-10-24 11:25 ` [PATCH 05/10] kvm: move instruction copying inside kvm_decode() Rusty Russell
2012-10-24 11:25 ` [PATCH 06/10] kvm: cleanup use of instr Rusty Russell
2012-10-24 11:25 ` [PATCH 07/10] kvm: clean up use of is_wide_instruction() Rusty Russell
2012-10-24 11:25 ` [PATCH 08/10] kvm: avoid using vcpu_cpsr() by passing down PSR Rusty Russell
2012-10-24 11:25 ` [PATCH 09/10] kvm: avoid reference vcpu->arch.hxfar by making thumb offset_addr relative Rusty Russell
2012-10-24 11:25 ` [PATCH 10/10] opcode: move generic instruction decode out of KVM Rusty Russell
2012-10-24 16:27 ` RFC: Move kvm's instruction decoding into generic code Dave Martin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1351077923-17977-4-git-send-email-rusty@rustcorp.com.au \
--to=rusty@rustcorp.com.au \
--cc=c.dall@virtualopensystems.com \
--cc=dave.martin@linaro.org \
--cc=kvm@vger.kernel.org \
--cc=rusty.russell@linaro.org \
--cc=will.deacon@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.