All of lore.kernel.org
 help / color / mirror / Atom feed
From: rusty@rustcorp.com.au (Rusty Russell)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 7/8] ARM: KVM: guest_didnt_mean_it()
Date: Fri, 09 Mar 2012 14:56:52 +1030	[thread overview]
Message-ID: <1331267212.26948.rusty@rustcorp.com.au> (raw)


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

Conditional instructions may trap even if the condition isn't true, so a good
hypervisor will check this.  The same can happen with undefined instructions,
so the kernel should be doing this dance already (it isn't).

(See p1206 of ARMv7-A ARM)

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
 arch/arm/include/asm/kvm_arm.h     |    4 +++
 arch/arm/include/asm/kvm_emulate.h |    2 +
 arch/arm/kvm/Makefile              |    2 +
 arch/arm/kvm/arm.c                 |    3 ++
 arch/arm/kvm/emulate.c             |   41 +++++++++++++++++++++++++++
 arch/arm/kvm/kvm_cond_match.S      |   54 ++++++++++++++++++++++++++++++++++++
 6 files changed, 105 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/kvm/kvm_cond_match.S

diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h
index 1769187..156284a 100644
--- a/arch/arm/include/asm/kvm_arm.h
+++ b/arch/arm/include/asm/kvm_arm.h
@@ -107,6 +107,10 @@
 #define HSR_ISS		(HSR_IL - 1)
 #define HSR_ISV_SHIFT	(24)
 #define HSR_ISV		(1U << HSR_ISV_SHIFT)
+#define HSR_CV_SHIFT	(24)
+#define HSR_CV		(1U << HSR_CV_SHIFT)
+#define HSR_COND_SHIFT	(20)
+#define HSR_COND	(0xfU << HSR_COND_SHIFT)
 
 #define HSR_EC_UNKNOWN	(0x00)
 #define HSR_EC_WFI	(0x01)
diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h
index fa54247..fe21e86 100644
--- a/arch/arm/include/asm/kvm_emulate.h
+++ b/arch/arm/include/asm/kvm_emulate.h
@@ -49,6 +49,8 @@ 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);
+bool kvm_should_not_have_trapped(struct kvm_vcpu *vcpu);
+bool kvm_cond_match(u32 flags, u32 cond);
 
 /*
  * Return the SPSR for the specified mode of the virtual CPU.
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index e69a8e1..68f05b9 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -12,6 +12,6 @@ obj-$(CONFIG_KVM_ARM_HOST) += init.o interrupts.o exports.o
 
 kvm-arm-y += $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
 
-kvm-arm-y += arm.o guest.o mmu.o emulate.o
+kvm-arm-y += arm.o guest.o mmu.o emulate.o kvm_cond_match.o
 
 obj-$(CONFIG_KVM) += kvm-arm.o
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index a6cf02b..1724657 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -414,6 +414,9 @@ static inline int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
 		BUG();
 	}
 
+	if (kvm_should_not_have_trapped(vcpu))
+		return 0;
+
 	return arm_exit_handlers[hsr_ec](vcpu, run);
 }
 
diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c
index bd2c3dc..11e2dab 100644
--- a/arch/arm/kvm/emulate.c
+++ b/arch/arm/kvm/emulate.c
@@ -659,3 +659,44 @@ int kvm_emulate_mmio_ls(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 	*vcpu_reg(vcpu, 15) += 4;
 	return 0;
 }
+
+/* Some implementations may not check condition codes before trapping! */
+bool kvm_should_not_have_trapped(struct kvm_vcpu *vcpu)
+{
+	unsigned long spsr, cond, flags;
+
+	/*
+	 * Exception Code 0 can only happen if we set HCR.TGE to 1, to
+	 * catch undefined instructions, and then we won't get past
+	 * the arm_exit_handlers test anyway.
+	 */
+	BUG_ON(((vcpu->arch.hsr & HSR_EC) >> HSR_EC_SHIFT) == 0);
+
+	/* Top two bits non-zero?  Unconditional. */
+	if (vcpu->arch.hsr >> 30)
+		return false;
+
+	spsr = *vcpu_spsr(vcpu);
+
+	/* Is condition field valid? */
+	if ((vcpu->arch.hsr & HSR_CV) >> HSR_CV_SHIFT)
+		cond = (vcpu->arch.hsr & HSR_COND) >> HSR_COND_SHIFT;
+	else {
+		/* This can happen in Thumb mode: examine IT state. */
+		unsigned long it;
+		
+		it = ((spsr >> 8) & 0xFC)
+			| ((spsr >> 25) & 0x3);
+
+		/* it == 0 => unconditional. */
+		if (it == 0)
+			return false;
+
+		/* The cond for this insn works out as the top 4 bits. */
+		cond = (it >> 4);
+	}
+
+	flags = spsr & ~0x07FFFFFF;
+
+	return !kvm_cond_match(flags, cond);
+}
diff --git a/arch/arm/kvm/kvm_cond_match.S b/arch/arm/kvm/kvm_cond_match.S
new file mode 100644
index 0000000..cf48786
--- /dev/null
+++ b/arch/arm/kvm/kvm_cond_match.S
@@ -0,0 +1,54 @@
+#include <linux/linkage.h>
+
+/* extern bool kvm_cond_match(u32 flags, u32 cond); */
+ENTRY(kvm_cond_match)
+.arm
+	/* First, set our condition flags to the arg. */
+	mrs	r2, cpsr
+	and	r2, r2, #0x07FFFFFF
+	orr	r2, r2, r0
+	msr	cpsr, r2
+
+	/* Now, jump to table depending on cond, return via there. */
+	mov	r0, #0
+	add	r2, r0, r1, LSL #3
+	sub	r2, #4
+	add	pc, r2
+
+/* This is "mov<cond>	r0, #1" */
+#define COND_MOVEQ_R0_1(cond) .word	((cond << 28) | 0x03a00001)
+
+cond_table:
+	COND_MOVEQ_R0_1(0)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(1)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(2)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(3)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(4)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(5)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(6)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(7)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(8)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(9)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(10)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(11)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(12)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(13)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(14)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(15)
+	mov	pc, lr
+ENDPROC(kvm_cond_match)

WARNING: multiple messages have this Message-ID (diff)
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 7/8] ARM: KVM: guest_didnt_mean_it()
Date: Fri, 09 Mar 2012 14:56:52 +1030	[thread overview]
Message-ID: <1331267212.26948.rusty@rustcorp.com.au> (raw)


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

Conditional instructions may trap even if the condition isn't true, so a good
hypervisor will check this.  The same can happen with undefined instructions,
so the kernel should be doing this dance already (it isn't).

(See p1206 of ARMv7-A ARM)

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
 arch/arm/include/asm/kvm_arm.h     |    4 +++
 arch/arm/include/asm/kvm_emulate.h |    2 +
 arch/arm/kvm/Makefile              |    2 +
 arch/arm/kvm/arm.c                 |    3 ++
 arch/arm/kvm/emulate.c             |   41 +++++++++++++++++++++++++++
 arch/arm/kvm/kvm_cond_match.S      |   54 ++++++++++++++++++++++++++++++++++++
 6 files changed, 105 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/kvm/kvm_cond_match.S

diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h
index 1769187..156284a 100644
--- a/arch/arm/include/asm/kvm_arm.h
+++ b/arch/arm/include/asm/kvm_arm.h
@@ -107,6 +107,10 @@
 #define HSR_ISS		(HSR_IL - 1)
 #define HSR_ISV_SHIFT	(24)
 #define HSR_ISV		(1U << HSR_ISV_SHIFT)
+#define HSR_CV_SHIFT	(24)
+#define HSR_CV		(1U << HSR_CV_SHIFT)
+#define HSR_COND_SHIFT	(20)
+#define HSR_COND	(0xfU << HSR_COND_SHIFT)
 
 #define HSR_EC_UNKNOWN	(0x00)
 #define HSR_EC_WFI	(0x01)
diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h
index fa54247..fe21e86 100644
--- a/arch/arm/include/asm/kvm_emulate.h
+++ b/arch/arm/include/asm/kvm_emulate.h
@@ -49,6 +49,8 @@ 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);
+bool kvm_should_not_have_trapped(struct kvm_vcpu *vcpu);
+bool kvm_cond_match(u32 flags, u32 cond);
 
 /*
  * Return the SPSR for the specified mode of the virtual CPU.
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index e69a8e1..68f05b9 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -12,6 +12,6 @@ obj-$(CONFIG_KVM_ARM_HOST) += init.o interrupts.o exports.o
 
 kvm-arm-y += $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
 
-kvm-arm-y += arm.o guest.o mmu.o emulate.o
+kvm-arm-y += arm.o guest.o mmu.o emulate.o kvm_cond_match.o
 
 obj-$(CONFIG_KVM) += kvm-arm.o
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index a6cf02b..1724657 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -414,6 +414,9 @@ static inline int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
 		BUG();
 	}
 
+	if (kvm_should_not_have_trapped(vcpu))
+		return 0;
+
 	return arm_exit_handlers[hsr_ec](vcpu, run);
 }
 
diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c
index bd2c3dc..11e2dab 100644
--- a/arch/arm/kvm/emulate.c
+++ b/arch/arm/kvm/emulate.c
@@ -659,3 +659,44 @@ int kvm_emulate_mmio_ls(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 	*vcpu_reg(vcpu, 15) += 4;
 	return 0;
 }
+
+/* Some implementations may not check condition codes before trapping! */
+bool kvm_should_not_have_trapped(struct kvm_vcpu *vcpu)
+{
+	unsigned long spsr, cond, flags;
+
+	/*
+	 * Exception Code 0 can only happen if we set HCR.TGE to 1, to
+	 * catch undefined instructions, and then we won't get past
+	 * the arm_exit_handlers test anyway.
+	 */
+	BUG_ON(((vcpu->arch.hsr & HSR_EC) >> HSR_EC_SHIFT) == 0);
+
+	/* Top two bits non-zero?  Unconditional. */
+	if (vcpu->arch.hsr >> 30)
+		return false;
+
+	spsr = *vcpu_spsr(vcpu);
+
+	/* Is condition field valid? */
+	if ((vcpu->arch.hsr & HSR_CV) >> HSR_CV_SHIFT)
+		cond = (vcpu->arch.hsr & HSR_COND) >> HSR_COND_SHIFT;
+	else {
+		/* This can happen in Thumb mode: examine IT state. */
+		unsigned long it;
+		
+		it = ((spsr >> 8) & 0xFC)
+			| ((spsr >> 25) & 0x3);
+
+		/* it == 0 => unconditional. */
+		if (it == 0)
+			return false;
+
+		/* The cond for this insn works out as the top 4 bits. */
+		cond = (it >> 4);
+	}
+
+	flags = spsr & ~0x07FFFFFF;
+
+	return !kvm_cond_match(flags, cond);
+}
diff --git a/arch/arm/kvm/kvm_cond_match.S b/arch/arm/kvm/kvm_cond_match.S
new file mode 100644
index 0000000..cf48786
--- /dev/null
+++ b/arch/arm/kvm/kvm_cond_match.S
@@ -0,0 +1,54 @@
+#include <linux/linkage.h>
+
+/* extern bool kvm_cond_match(u32 flags, u32 cond); */
+ENTRY(kvm_cond_match)
+.arm
+	/* First, set our condition flags to the arg. */
+	mrs	r2, cpsr
+	and	r2, r2, #0x07FFFFFF
+	orr	r2, r2, r0
+	msr	cpsr, r2
+
+	/* Now, jump to table depending on cond, return via there. */
+	mov	r0, #0
+	add	r2, r0, r1, LSL #3
+	sub	r2, #4
+	add	pc, r2
+
+/* This is "mov<cond>	r0, #1" */
+#define COND_MOVEQ_R0_1(cond) .word	((cond << 28) | 0x03a00001)
+
+cond_table:
+	COND_MOVEQ_R0_1(0)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(1)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(2)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(3)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(4)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(5)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(6)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(7)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(8)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(9)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(10)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(11)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(12)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(13)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(14)
+	mov	pc, lr
+	COND_MOVEQ_R0_1(15)
+	mov	pc, lr
+ENDPROC(kvm_cond_match)


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

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-03-09  4:26 Rusty Russell [this message]
2012-03-09  4:26 ` [PATCH 7/8] ARM: KVM: guest_didnt_mean_it() Rusty Russell

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.26948.rusty@rustcorp.com.au \
    --to=rusty@rustcorp.com.au \
    --cc=linux-arm-kernel@lists.infradead.org \
    /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.