aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--demo_functionality.c22
-rw-r--r--demo_functionality.h2
-rw-r--r--interrupt_vector.S20
-rw-r--r--interrupts.c13
-rw-r--r--kernel.c2
-rw-r--r--linker.ld13
7 files changed, 71 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index f07bced..377ba18 100644
--- a/Makefile
+++ b/Makefile
@@ -30,7 +30,7 @@ libkernel_renamed.o : libkernel.o
PL_0_test.elf : PL0_test.o uart.o
arm-none-eabi-gcc -T PL0_test.ld -o $@ $(ELFFLAGS) $^
-kernel.elf : boot.o kernel.o uart.o PL_0_test_embeddable.o demo_functionality.o paging.o libkernel_renamed.o
+kernel.elf : boot.o kernel.o uart.o PL_0_test_embeddable.o demo_functionality.o paging.o libkernel_renamed.o interrupt_vector.o interrupts.o
arm-none-eabi-gcc -T linker.ld -o $@ $(ELFFLAGS) $^
loader_stage2.elf : loader_stage2.o uart.o
diff --git a/demo_functionality.c b/demo_functionality.c
index fbf5eb4..60b0bfa 100644
--- a/demo_functionality.c
+++ b/demo_functionality.c
@@ -165,3 +165,25 @@ void demo_go_unprivileged(void)
"r" (VIRTUAL_PL0_MEMORY_START)
: "memory", "r4", "r5", "r0");
}
+
+extern char
+ __interrupt_vectors_start,
+ __interrupt_vectors_end,
+ __interrupt_vectors_size;
+
+extern void (*volatile system_reentry_point)(void);
+
+void system_reentry(void)
+{
+ uart_puts("re-entered system");
+ while(1);
+}
+
+void demo_setup_interrupts(void)
+{
+ system_reentry_point = system_reentry;
+
+ for (size_t i = 0; i < (size_t) &__interrupt_vectors_size; i++)
+ ((volatile char*) 0)[i] =
+ (&__interrupt_vectors_start)[i];
+}
diff --git a/demo_functionality.h b/demo_functionality.h
index 5d6e659..73a284b 100644
--- a/demo_functionality.h
+++ b/demo_functionality.h
@@ -11,4 +11,6 @@ void demo_setup_PL0(void);
void demo_go_unprivileged(void);
+void demo_setup_interrupts(void);
+
#endif // DEMO_FUNCTIONALITY_H
diff --git a/interrupt_vector.S b/interrupt_vector.S
new file mode 100644
index 0000000..f71330b
--- /dev/null
+++ b/interrupt_vector.S
@@ -0,0 +1,20 @@
+.section ".interrupt_vectors.text"
+
+.global abort_handler
+.local generic_handler
+.global _interrupt_vectors
+_interrupt_vectors:
+ b generic_handler
+ b generic_handler
+ b generic_handler
+ b abort_handler_caller
+ b abort_handler_caller
+ b generic_handler
+ b generic_handler
+
+generic_handler:
+ b generic_handler
+abort_handler_caller:
+ mov sp, #0x8000
+ ldr r5, =abort_handler
+ bx r5
diff --git a/interrupts.c b/interrupts.c
index 3dc3d6f..191ce40 100644
--- a/interrupts.c
+++ b/interrupts.c
@@ -12,4 +12,15 @@ void __attribute__((interrupt("UNDEF"))) undefined_instruction_vector(void)
{
/* Do Nothing! */
}
-} \ No newline at end of file
+}
+
+void __attribute__((section(".interrupt_vectors.data")))
+(*system_reentry_point) (void);
+
+void
+__attribute__((interrupt("ABORT")))
+__attribute__((section(".interrupt_vectors.text")))
+abort_handler(void)
+{
+ system_reentry_point();
+}
diff --git a/kernel.c b/kernel.c
index 1a3b87d..eb3e811 100644
--- a/kernel.c
+++ b/kernel.c
@@ -31,7 +31,7 @@ void kernel_main(uint32_t r0, uint32_t r1, uint32_t atags)
demo_setup_PL0();
- demo_go_unprivileged();
+ demo_setup_interrupts();
// prints some info and sets up a section for PL0 code, loads a blob
// there and jumps to it... never, ever, ever returns
diff --git a/linker.ld b/linker.ld
index 199cc0f..01eda35 100644
--- a/linker.ld
+++ b/linker.ld
@@ -89,6 +89,19 @@ SECTIONS
__renamed_bss_size = __renamed_bss_end - __renamed_bss_start;
__renamed_end = .;
__renamed_size = __renamed_end - __renamed_start;
+
+
+ . = ALIGN(4096); /* align to page size */
+ __interrupt_vectors_start = .;
+ .interrupt_vectors :
+ {
+ interrupt_vectors = .;
+ *(.interrupt_vectors.text)
+ *(.interrupt_vectors.data)
+ }
+ . = ALIGN(4096); /* align to page size */
+ __interrupt_vectors_end = .;
+ __interrupt_vectors_size = __interrupt_vectors_end - __interrupt_vectors_start;
__end = .;
}