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
This commit is contained in:
Martin Stein 2015-11-02 14:36:01 +01:00 committed by Christian Helmuth
parent 0b39b22e14
commit 85ba3259f8
4 changed files with 37 additions and 8 deletions

View File

@ -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_ */

View File

@ -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 **
*************/

View File

@ -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);

View File

@ -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);