public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Rusty Russell <rusty@rustcorp.com.au>
To: Russell King <linux@arm.linux.org.uk>,
	linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH 4/8] ARM: KVM: split cp15 mrc/mcr and mrrc/mcrr handling.
Date: Fri, 09 Mar 2012 14:56:52 +1030	[thread overview]
Message-ID: <1331267212.23398.rusty@rustcorp.com.au> (raw)


From: Rusty Russell <rusty@rustcorp.com.au>

The hardware has separate traps for the two cases, so don't prematurely
unify them.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
 arch/arm/include/asm/kvm_emulate.h |    3 +
 arch/arm/kvm/arm.c                 |    4 +
 arch/arm/kvm/emulate.c             |  102 ++++++++++++++++++++----------------
 3 files changed, 62 insertions(+), 47 deletions(-)

diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h
index 029f45f..fa54247 100644
--- a/arch/arm/include/asm/kvm_emulate.h
+++ b/arch/arm/include/asm/kvm_emulate.h
@@ -44,7 +44,8 @@ int kvm_handle_cp10_id(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int kvm_handle_cp_0_13_access(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run);
-int kvm_handle_cp15_access(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int kvm_handle_wfi(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int kvm_emulate_mmio_ls(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 			unsigned long instr);
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index f27a96b..a6cf02b 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -377,8 +377,8 @@ static int handle_dabt_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
 
 static int (*arm_exit_handlers[])(struct kvm_vcpu *vcpu, struct kvm_run *r) = {
 	[HSR_EC_WFI]		= kvm_handle_wfi,
-	[HSR_EC_CP15_32]	= kvm_handle_cp15_access,
-	[HSR_EC_CP15_64]	= kvm_handle_cp15_access,
+	[HSR_EC_CP15_32]	= kvm_handle_cp15_32,
+	[HSR_EC_CP15_64]	= kvm_handle_cp15_64,
 	[HSR_EC_CP14_MR]	= kvm_handle_cp14_access,
 	[HSR_EC_CP14_LS]	= kvm_handle_cp14_load_store,
 	[HSR_EC_CP14_64]	= kvm_handle_cp14_access,
diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c
index 87a1141..88c6493 100644
--- a/arch/arm/kvm/emulate.c
+++ b/arch/arm/kvm/emulate.c
@@ -304,62 +304,31 @@ static int emulate_cp15_c15_access(struct kvm_vcpu *vcpu,
 	return 0;
 }
 
-/**
- * kvm_handle_cp15_access -- handles a trap on a guest CP15 access
- * @vcpu: The VCPU pointer
- * @run:  The kvm_run struct
- *
- * Investigates the CRn/CRm and wether this was mcr/mrc or mcrr/mrrc and either
- * simply errors out if the operation was not supported (should maybe raise
- * undefined to guest instead?) and otherwise emulated access.
- */
-int kvm_handle_cp15_access(struct kvm_vcpu *vcpu, struct kvm_run *run)
+static int emulate_cp15(struct kvm_vcpu *vcpu,
+			const struct coproc_params *params)
 {
-	unsigned long hsr_ec, instr_len;
-	struct coproc_params params;
-	int ret = 0;
-
-	hsr_ec = vcpu->arch.hsr >> HSR_EC_SHIFT;
-	params.CRm = (vcpu->arch.hsr >> 1) & 0xf;
-	params.Rt1 = (vcpu->arch.hsr >> 5) & 0xf;
-	BUG_ON(params.Rt1 >= 15);
-	params.is_write = ((vcpu->arch.hsr & 1) == 0);
-	params.is_64bit = (hsr_ec == HSR_EC_CP15_64);
-
-	if (params.is_64bit) {
-		/* mrrc, mccr operation */
-		params.Op1 = (vcpu->arch.hsr >> 16) & 0xf;
-		params.Op2 = 0;
-		params.Rt2 = (vcpu->arch.hsr >> 10) & 0xf;
-		BUG_ON(params.Rt2 >= 15);
-		params.CRn = 0;
-	} else {
-		params.CRn = (vcpu->arch.hsr >> 10) & 0xf;
-		params.Op1 = (vcpu->arch.hsr >> 14) & 0x7;
-		params.Op2 = (vcpu->arch.hsr >> 17) & 0x7;
-		params.Rt2 = 0;
-	}
+	unsigned long instr_len;
+	int ret;
 
 	/* So far no mrrc/mcrr accesses are emulated */
-	if (params.is_64bit)
+	if (params->is_64bit)
 		goto unsupp_err_out;
 
-	switch (params.CRn) {
+	switch (params->CRn) {
 	case 9:
-		ret = emulate_cp15_c9_access(vcpu, &params);
+		ret = emulate_cp15_c9_access(vcpu, params);
 		break;
 	case 10:
-		ret = emulate_cp15_c10_access(vcpu, &params);
+		ret = emulate_cp15_c10_access(vcpu, params);
 		break;
 	case 15:
-		ret = emulate_cp15_c15_access(vcpu, &params);
+		ret = emulate_cp15_c15_access(vcpu, params);
 		break;
 	default:
 		ret = -EINVAL;
-		break;
 	}
 
-	if (ret)
+	if (ret != 0)
 		goto unsupp_err_out;
 
 	/* Skip instruction, since it was emulated */
@@ -367,10 +336,55 @@ int kvm_handle_cp15_access(struct kvm_vcpu *vcpu, struct kvm_run *run)
 	*vcpu_reg(vcpu, 15) += instr_len;
 
 	return ret;
-unsupp_err_out:
+
+unsupp_err_out:	
 	kvm_err("Unsupported guest CP15 access at: %08x\n", vcpu->arch.regs.pc);
-	print_cp_instr(&params);
-	return -EINVAL;
+	print_cp_instr(params);
+	return ret;
+}
+
+/**
+ * kvm_handle_cp15_64 -- handles a mrrc/mcrr trap on a guest CP15 access
+ * @vcpu: The VCPU pointer
+ * @run:  The kvm_run struct
+ */
+int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+	struct coproc_params params;
+
+	params.CRm = (vcpu->arch.hsr >> 1) & 0xf;
+	params.Rt1 = (vcpu->arch.hsr >> 5) & 0xf;
+	params.is_write = ((vcpu->arch.hsr & 1) == 0);
+	params.is_64bit = true;
+
+	params.Op1 = (vcpu->arch.hsr >> 16) & 0xf;
+	params.Op2 = 0;
+	params.Rt2 = (vcpu->arch.hsr >> 10) & 0xf;
+	params.CRn = 0;
+
+	return emulate_cp15(vcpu, &params);
+}
+
+/**
+ * kvm_handle_cp15_32 -- handles a mrc/mcr trap on a guest CP15 access
+ * @vcpu: The VCPU pointer
+ * @run:  The kvm_run struct
+ */
+int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+	struct coproc_params params;
+
+	params.CRm = (vcpu->arch.hsr >> 1) & 0xf;
+	params.Rt1 = (vcpu->arch.hsr >> 5) & 0xf;
+	params.is_write = ((vcpu->arch.hsr & 1) == 0);
+	params.is_64bit = false;
+
+	params.CRn = (vcpu->arch.hsr >> 10) & 0xf;
+	params.Op1 = (vcpu->arch.hsr >> 14) & 0x7;
+	params.Op2 = (vcpu->arch.hsr >> 17) & 0x7;
+	params.Rt2 = 0;
+
+	return emulate_cp15(vcpu, &params);
 }
 
 /**


                 reply	other threads:[~2012-03-09  4:43 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=1331267212.23398.rusty@rustcorp.com.au \
    --to=rusty@rustcorp.com.au \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@arm.linux.org.uk \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox