From 3f1cd2050271dbf548e053f0a67e365b277cfcb3 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Tue, 10 Dec 2019 16:46:56 +0100 Subject: re-enter system mode on invalid data access from PL0 code --- Makefile | 2 +- demo_functionality.c | 22 ++++++++++++++++++++++ demo_functionality.h | 2 ++ interrupt_vector.S | 20 ++++++++++++++++++++ interrupts.c | 13 ++++++++++++- kernel.c | 2 +- linker.ld | 13 +++++++++++++ 7 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 interrupt_vector.S 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 = .; } -- cgit v1.2.3 From d0d9f0280879f8c43131256aa5e82012ec84716f Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Tue, 10 Dec 2019 17:23:00 +0100 Subject: Clean up flags in Makefile a bit.; -fPIC... -fPIC EVERYWHERE --- Makefile | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 377ba18..0796ac8 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -CFLAGS=-mcpu=cortex-a7 -ffreestanding -std=gnu11 -Wall -Wextra -I. -ELFFLAGS=-ffreestanding -O2 -nostdlib -lgcc -I. +CFLAGS=-mcpu=cortex-a7 -ffreestanding -std=gnu11 -Wall -Wextra -O2 -fPIC -I. +ELFFLAGS=-nostdlib -lgcc ARM_OBJECTS=kernel.o paging.o demo_functionality.o PL0_test.o uart.o loader_stage1.o loader_stage2.o @@ -21,9 +21,6 @@ all : kernel7.img %_embeddable.o : %.img arm-none-eabi-objcopy -I binary -O elf32-littlearm -B arm --rename-section .data=.rodata $^ $@ -libkernel.o : libkernel.c - arm-none-eabi-gcc $(CFLAGS) -fPIC -c $^ -o $@ - libkernel_renamed.o : libkernel.o arm-none-eabi-objcopy $(RENAME_FLAGS) $^ $@ -- cgit v1.2.3 From 9c5e76f1087e0d868f7330d003e17181ecd8706b Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Tue, 10 Dec 2019 17:36:33 +0100 Subject: remove old, unneeded uart_puts() call --- PL0_test.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/PL0_test.c b/PL0_test.c index 1b93024..32addf8 100644 --- a/PL0_test.c +++ b/PL0_test.c @@ -3,8 +3,6 @@ void PL0_main(void) { - uart_puts("hello PL0! Switching to user mode!\n\r"); - // if all went correct, Success! gets printed uart_puts("Success!\n\r"); -- cgit v1.2.3 From 1a75b3f08e28876896ea90f85b1e8101ef55dd5d Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Tue, 10 Dec 2019 17:50:15 +0100 Subject: update TODOs --- TODOs | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/TODOs b/TODOs index 5b78455..23c3458 100644 --- a/TODOs +++ b/TODOs @@ -1,4 +1,4 @@ -* Remove duplications in Makefile... i.e. use generic recipes for .c -> .o compilations and many other things, that can be shortened this was +* DONE * Remove duplications in Makefile... i.e. use generic recipes for .c -> .o compilations and many other things, that can be shortened this was * Implement some basic utilities for us to use (memcpy, printf, etc...) @@ -7,16 +7,32 @@ - What if wiki.osdev was wrong about this and objcopy includes .bss in it's output image? Then also no work needs to be done - Stage2 gets loaded between 0x4000 and 0x8000, so that piece of memory could be zeroed-out before by stage1 and that would solve the issue -* Add sanity-check at build-time, that stage2 blob is smaller than 0x4000 in size +* DONE * Add sanity-check at build-time, that stage2 blob is smaller than 0x4000 in size * Races might occur, when one processor starts overwriting stuff at image load address before other processors execute the initial piece of code that puts them to sleep... This should be fixed in bootloader and will need to be taken into account when we develop the actual kernel to manage it's own memory * Real RPi firmware would jump to the kernel on all cores after loading it from SD... So it'd be good if bootloader did a simillar thing - i.e. bootloader, when started, first shuts off all cores but one, it loads it's stage2, which downloads the kernel by uart, turns all cores back on and jumps to kernel on all of them... Additional kudos if U make this race-free (see, TODO above) -* Finally, the most important thing - move forward and start working with the MMU already! +* DOOOONE * Finally, the most important thing - move forward and start working with the MMU already! -* Start doing this on hardware already... (Hey, whole making of a bootloader was with this in mind!) +* DOOOONE * Start doing this on hardware already... (Hey, whole making of a bootloader was with this in mind!) * Fix piping with pipe_image -* write some procedures for dumping registers and other stuff (for use in debugging) \ No newline at end of file +* write some procedures for dumping registers and other stuff (for use in debugging) + +* learn some asm and write exception handlers withour gcc's "interrupt" function attribute (this is so that we see what's happening - right now gcc hides some things from us...) + +* write better uart (using interrupts, maybe DMA?); the current one is sopy-pasted from wiki osdev which is lame + +* boot.S is also copy-pasted from wiki-osdev (very lame) + +* shorten linker script... (I think I don't have to tell You where it's original version was copy-pasted from...) + +* write documentation for what we've already done (yea, there's HISTORY.md, but we also want something that gives technical details of how MMU gets set up (writes to SCTLR, DACR and others), etc.) + +* develop userspace process supervision (handling of interrupt caused by svc instruction, proper handling of other data abort, undefined instruction, etc.) + +* get external interrupts work + +* find a way to make management of binary pieces less messy (in the entire project there're currently about 5 places where code is being copied by other code...) \ No newline at end of file -- cgit v1.2.3