From 85ba3259f8f15166d178cfebbc1dac573eaed873 Mon Sep 17 00:00:00 2001
From: Martin Stein <martin.stein@genode-labs.com>
Date: Mon, 2 Nov 2015 14:36:01 +0100
Subject: [PATCH] hw & imx53: IRQ injection via Vm::proceed

Enhance the VM state, that can be accessed by a VMM, by a member
'unsigned irq_injection'. In Kernel::Vm::proceed check, whether
irq_injection is set.  If so, check whether irq_injection is a
non-secure IRQ.  If so, let the PIC raise this IRQ in the VM and reset
irq_injection.

Ref #1497
---
 repos/base-hw/include/spec/imx53/vm_state.h   |  1 +
 .../base-hw/src/core/include/spec/imx53/pic.h | 13 ++++++++++++
 .../core/spec/arm_v7/trustzone/kernel/vm.cc   | 11 ++++++++++
 .../spec/imx53/trustzone/platform_support.cc  | 20 +++++++++++--------
 4 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/repos/base-hw/include/spec/imx53/vm_state.h b/repos/base-hw/include/spec/imx53/vm_state.h
index 0dcc0506b6..26dad041ce 100644
--- a/repos/base-hw/include/spec/imx53/vm_state.h
+++ b/repos/base-hw/include/spec/imx53/vm_state.h
@@ -31,6 +31,7 @@ struct Genode::Vm_state : Genode::Cpu_state_modes
 	Genode::addr_t dfar;
 	Genode::addr_t ttbr[2];
 	Genode::addr_t ttbrc;
+	Genode::addr_t irq_injection;
 };
 
 #endif /* _INCLUDE__SPEC__IMX53__VM_STATE_H_ */
diff --git a/repos/base-hw/src/core/include/spec/imx53/pic.h b/repos/base-hw/src/core/include/spec/imx53/pic.h
index ff0035ac30..92894899ae 100644
--- a/repos/base-hw/src/core/include/spec/imx53/pic.h
+++ b/repos/base-hw/src/core/include/spec/imx53/pic.h
@@ -43,6 +43,12 @@ class Genode::Pic : public Mmio
 
 	protected:
 
+		/**
+		 * Software Interrupt Trigger Register
+		 */
+		struct Swint : Register<0xf00, 32> {
+			struct Intid  : Bitfield<0,10> { }; };
+
 		/**
 		 * Interrupt control register
 		 */
@@ -154,6 +160,13 @@ class Genode::Pic : public Mmio
 			if (valid(i)) { write<Enclear::Clear_enable>(1, i); } }
 
 
+		/*
+		 * Trigger interrupt 'i' from software if possible
+		 */
+		void trigger(unsigned const i) {
+			write<Swint>(Swint::Intid::bits(i)); }
+
+
 		/*************
 		 ** Dummies **
 		 *************/
diff --git a/repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc b/repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc
index 41b57f554a..2e7e0d898b 100644
--- a/repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc
+++ b/repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc
@@ -56,8 +56,19 @@ void Vm::exception(unsigned const cpu)
 }
 
 
+bool secure_irq(unsigned const i);
+
 void Vm::proceed(unsigned const cpu)
 {
+	unsigned const irq = _state->irq_injection;
+	if (irq) {
+		if (secure_irq(irq)) {
+			PWRN("Refuse to inject secure IRQ into VM");
+		} else {
+			pic()->trigger(irq);
+			_state->irq_injection = 0;
+		}
+	}
 	mtc()->switch_to(reinterpret_cast<Cpu::Context*>(_state), cpu,
 	                 (addr_t)&_mt_nonsecure_entry_pic,
 	                 (addr_t)&_tz_client_context);
diff --git a/repos/base-hw/src/core/spec/imx53/trustzone/platform_support.cc b/repos/base-hw/src/core/spec/imx53/trustzone/platform_support.cc
index 846bf9bdb8..fd87e73274 100644
--- a/repos/base-hw/src/core/spec/imx53/trustzone/platform_support.cc
+++ b/repos/base-hw/src/core/spec/imx53/trustzone/platform_support.cc
@@ -26,6 +26,17 @@ using namespace Genode;
 /* monitor exception vector address */
 extern int _mon_kernel_entry;
 
+bool secure_irq(unsigned const i)
+{
+	if (i == Board::EPIT_1_IRQ)                           return true;
+	if (i == Board::EPIT_2_IRQ)                           return true;
+	if (i == Board::I2C_2_IRQ)                            return true;
+	if (i == Board::I2C_3_IRQ)                            return true;
+	if (i >= Board::GPIO1_IRQL && i <= Board::GPIO4_IRQH) return true;
+	if (i >= Board::GPIO5_IRQL && i <= Board::GPIO7_IRQH) return true;
+	return false;
+}
+
 
 void Kernel::init_trustzone(Pic * pic)
 {
@@ -47,14 +58,7 @@ void Kernel::init_trustzone(Pic * pic)
 
 	/* configure non-secure interrupts */
 	for (unsigned i = 0; i < Pic::NR_OF_IRQ; i++) {
-		if ((i != Board::EPIT_1_IRQ) &&
-			(i != Board::EPIT_2_IRQ) &&
-			(i != Board::I2C_2_IRQ)  &&
-			(i != Board::I2C_3_IRQ)  &&
-			(i < Board::GPIO1_IRQL || i > Board::GPIO4_IRQH) &&
-			(i < Board::GPIO5_IRQL || i > Board::GPIO7_IRQH))
-			pic->unsecure(i);
-	}
+		if (!secure_irq(i)) { pic->unsecure(i); } }
 
 	/* configure central security unit */
 	Genode::Csu csu(Board::CSU_BASE);