summaryrefslogtreecommitdiff
path: root/src/arch/arm/interrupts.cc
diff options
context:
space:
mode:
authorARM gem5 Developers <none@none>2014-01-24 15:29:34 -0600
committerARM gem5 Developers <none@none>2014-01-24 15:29:34 -0600
commit612f8f074fa1099cf70faf495d46cc647762a031 (patch)
treebd1e99c43bf15292395eadd4b7ae3f5c823545c3 /src/arch/arm/interrupts.cc
parentf3585c841e964c98911784a187fc4f081a02a0a6 (diff)
downloadgem5-612f8f074fa1099cf70faf495d46cc647762a031.tar.xz
arm: Add support for ARMv8 (AArch64 & AArch32)
Note: AArch64 and AArch32 interworking is not supported. If you use an AArch64 kernel you are restricted to AArch64 user-mode binaries. This will be addressed in a later patch. Note: Virtualization is only supported in AArch32 mode. This will also be fixed in a later patch. Contributors: Giacomo Gabrielli (TrustZone, LPAE, system-level AArch64, AArch64 NEON, validation) Thomas Grocutt (AArch32 Virtualization, AArch64 FP, validation) Mbou Eyole (AArch64 NEON, validation) Ali Saidi (AArch64 Linux support, code integration, validation) Edmund Grimley-Evans (AArch64 FP) William Wang (AArch64 Linux support) Rene De Jong (AArch64 Linux support, performance opt.) Matt Horsnell (AArch64 MP, validation) Matt Evans (device models, code integration, validation) Chris Adeniyi-Jones (AArch64 syscall-emulation) Prakash Ramrakhyani (validation) Dam Sunwoo (validation) Chander Sudanthi (validation) Stephan Diestelhorst (validation) Andreas Hansson (code integration, performance opt.) Eric Van Hensbergen (performance opt.) Gabe Black
Diffstat (limited to 'src/arch/arm/interrupts.cc')
-rw-r--r--src/arch/arm/interrupts.cc121
1 files changed, 120 insertions, 1 deletions
diff --git a/src/arch/arm/interrupts.cc b/src/arch/arm/interrupts.cc
index c05ae984e..6682b75a0 100644
--- a/src/arch/arm/interrupts.cc
+++ b/src/arch/arm/interrupts.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009 ARM Limited
+ * Copyright (c) 2009, 2012-2013 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
@@ -38,9 +38,128 @@
*/
#include "arch/arm/interrupts.hh"
+#include "arch/arm/system.hh"
ArmISA::Interrupts *
ArmInterruptsParams::create()
{
return new ArmISA::Interrupts(this);
}
+
+bool
+ArmISA::Interrupts::takeInt(ThreadContext *tc, InterruptTypes int_type) const
+{
+ // Table G1-17~19 of ARM V8 ARM
+ InterruptMask mask;
+ bool highest_el_is_64 = ArmSystem::highestELIs64(tc);
+
+ CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
+ SCR scr;
+ HCR hcr;
+ hcr = tc->readMiscReg(MISCREG_HCR);
+ ExceptionLevel el = (ExceptionLevel) ((uint32_t) cpsr.el);
+ bool cpsr_mask_bit, scr_routing_bit, scr_fwaw_bit, hcr_mask_override_bit;
+
+ if (!highest_el_is_64)
+ scr = tc->readMiscReg(MISCREG_SCR);
+ else
+ scr = tc->readMiscReg(MISCREG_SCR_EL3);
+
+ bool is_secure = inSecureState(scr, cpsr);
+
+ switch(int_type) {
+ case INT_FIQ:
+ cpsr_mask_bit = cpsr.f;
+ scr_routing_bit = scr.fiq;
+ scr_fwaw_bit = scr.fw;
+ hcr_mask_override_bit = hcr.fmo;
+ break;
+ case INT_IRQ:
+ cpsr_mask_bit = cpsr.i;
+ scr_routing_bit = scr.irq;
+ scr_fwaw_bit = 1;
+ hcr_mask_override_bit = hcr.imo;
+ break;
+ case INT_ABT:
+ cpsr_mask_bit = cpsr.a;
+ scr_routing_bit = scr.ea;
+ scr_fwaw_bit = scr.aw;
+ hcr_mask_override_bit = hcr.amo;
+ break;
+ default:
+ panic("Unhandled interrupt type!");
+ }
+
+ if (hcr.tge)
+ hcr_mask_override_bit = 1;
+
+ if (!highest_el_is_64) {
+ // AArch32
+ if (!scr_routing_bit) {
+ // SCR IRQ == 0
+ if (!hcr_mask_override_bit)
+ mask = INT_MASK_M;
+ else {
+ if (!is_secure && (el == EL0 || el == EL1))
+ mask = INT_MASK_T;
+ else
+ mask = INT_MASK_M;
+ }
+ } else {
+ // SCR IRQ == 1
+ if ((!is_secure) &&
+ (hcr_mask_override_bit ||
+ (!scr_fwaw_bit && !hcr_mask_override_bit)))
+ mask = INT_MASK_T;
+ else
+ mask = INT_MASK_M;
+ }
+ } else {
+ // AArch64
+ if (!scr_routing_bit) {
+ // SCR IRQ == 0
+ if (!scr.rw) {
+ // SCR RW == 0
+ if (!hcr_mask_override_bit) {
+ if (el == EL3)
+ mask = INT_MASK_P;
+ else
+ mask = INT_MASK_M;
+ } else {
+ if (el == EL3)
+ mask = INT_MASK_T;
+ else if (is_secure || el == EL2)
+ mask = INT_MASK_M;
+ else
+ mask = INT_MASK_T;
+ }
+ } else {
+ // SCR RW == 1
+ if (!hcr_mask_override_bit) {
+ if (el == EL3 || el == EL2)
+ mask = INT_MASK_P;
+ else
+ mask = INT_MASK_M;
+ } else {
+ if (el == EL3)
+ mask = INT_MASK_P;
+ else if (is_secure || el == EL2)
+ mask = INT_MASK_M;
+ else
+ mask = INT_MASK_T;
+ }
+ }
+ } else {
+ // SCR IRQ == 1
+ if (el == EL3)
+ mask = INT_MASK_M;
+ else
+ mask = INT_MASK_T;
+ }
+ }
+
+ return ((mask == INT_MASK_T) ||
+ ((mask == INT_MASK_M) && !cpsr_mask_bit)) &&
+ (mask != INT_MASK_P);
+}
+