From 7dbdf1ee0a064e9b2c5fedd7bd4e2b67f0532b09 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Tue, 17 Dec 2019 17:01:41 +0100 Subject: make things work again on real hw (setting system mode moved to boot.S) --- Makefile | 4 ++-- boot.S | 6 +++++- demo_functionality.c | 7 ++----- demo_functionality.h | 2 +- kernel.c | 6 +++--- psr.h | 55 ---------------------------------------------------- 6 files changed, 13 insertions(+), 67 deletions(-) diff --git a/Makefile b/Makefile index 0796ac8..d1d66fa 100644 --- a/Makefile +++ b/Makefile @@ -47,9 +47,9 @@ qemu-elf : kernel.elf qemu-bin : loader.elf kernel.img pipe_image ./pipe_image --stdout | qemu-system-arm -m 256 -M raspi2 -serial stdio -kernel $< -run-on-rpi : kernel7.img pipe_image +run-on-rpi : kernel.img pipe_image ./pipe_image --stdout | sudo socat FILE:/dev/ttyUSB0,b115200,raw - -# screen /dev/ttyUSB0 115200,cs8,-parenb,-cstopb,-hupcl + screen /dev/ttyUSB0 115200,cs8,-parenb,-cstopb,-hupcl pipe_image : pipe_image.c lib/rs232/rs232.c gcc -Wall -std=gnu99 -O3 $^ -o $@ diff --git a/boot.S b/boot.S index 5cce37c..5e510f8 100644 --- a/boot.S +++ b/boot.S @@ -20,7 +20,11 @@ _start: and r5, r5, #3 cmp r5, #0 bne halt - + + // go to system mode + cps #0b11111 + isb + // Setup the stack. // It shall be directly below our kernel image ldr r5, =__start diff --git a/demo_functionality.c b/demo_functionality.c index 60b0bfa..3375550 100644 --- a/demo_functionality.c +++ b/demo_functionality.c @@ -26,11 +26,11 @@ void demo_paging_support(void) uart_puts(paging); } -void demo_mode_to_system(void) +void demo_current_mode(void) { // get content of current program status register to check the current - // processor mode + // processor mode (should be system, as we set it in boot.S) PSR_t CPSR = read_CPSR(); char *mode_name; @@ -51,9 +51,6 @@ void demo_mode_to_system(void) uart_puts("current mode: "); uart_puts(mode_name); - - uart_puts("setting mode to system (PL1)...\r\n"); - set_system_mode(); } #define TRANSLATION_TABLE \ diff --git a/demo_functionality.h b/demo_functionality.h index 73a284b..12f5807 100644 --- a/demo_functionality.h +++ b/demo_functionality.h @@ -3,7 +3,7 @@ void demo_paging_support(void); -void demo_mode_to_system(void); +void demo_current_mode(void); void demo_setup_libkernel(void); diff --git a/kernel.c b/kernel.c index eb3e811..fc629e1 100644 --- a/kernel.c +++ b/kernel.c @@ -14,15 +14,15 @@ void kernel_main(uint32_t r0, uint32_t r1, uint32_t atags) // When we attach screen session after loading kernel with socat // we miss kernel's greeting... So we'll make the kernel wait for // one char we're going to send from within screen - // uart_getc(); + uart_getc(); uart_puts("Hello, kernel World!\r\n"); // prints some info demo_paging_support(); - // prints some info and switches to system mode - demo_mode_to_system(); + // prints some info + demo_current_mode(); // prints some info and sets upp translation table, turns on MMU setup_flat_map(); diff --git a/psr.h b/psr.h index dfbb878..9809fc4 100644 --- a/psr.h +++ b/psr.h @@ -64,59 +64,4 @@ inline static PSR_t read_CPSR(void) return CPSR; } -//// Write function not working for some reason... Assembly from gcc -//// looks ok. Needs checking on real hw. - -//inline static void write_CPSR(PSR_t CPSR) -//{ - // write to current program status register and synchronize context - // asm("msr cpsr, %0\n\r" - // "isb" :: "r" (CPSR.raw) : "memory"); -//} - -inline static void set_system_mode(void) -{ - // hack to fix an unexplained bug; volatile needed in case of - // compilation with optimizations - volatile PSR_t CPSR __attribute__((unused)) = read_CPSR(); - - //// there are 2 ways of changing mode, both with the same - //// problem (see the long comment below) - - //// way 1 - // CPSR.fields.M_4_0 = MODE_SYSTEM; - // write to current program status register and synchronize context - // asm("msr cpsr, %0\n\r" - // "isb":: "r" (CPSR.raw) : "memory"); - - //// way 2 - asm("cps #0b11111\n\r" - "isb" ::: "memory"); -} - -// The thing with writing to cpsr is weird. I used to have a single -// function that would set the system mode by: -// 1. reading the cpsr -// 2. modifying the value using bit shifts and logical or -// 3. writing the value back -// When introducing structs and bitfields I wanted to have separate -// functions for reading and writing the cpsr and have code up the -// call stack handle value modification. For some reason this didn't -// work - all would just hang when writing the CPSR. It turned out -// everything works if i call read_CPSR() from the same function, in -// which i write to cpsr. And I don't even need to use the value -// I read. I can just discard it (we're compiling without -// optimizations, so read_CPSR() is still called) and use the value -// passed as argument. I noticed an even weirder thing: the 2nd way -// of changing mode (cps instruction) doesn't work normally, but, -// just as msr, it does work when I call read_CPSR() before it. Even -// weirder - I cannot replace read_CPSR() with the actual assembly it -// does, because it stops working again! Asm generated by gcc looks -// ok, so Idk, maybe its some qemu issue (haven't tested on real RPi -// yet). I seem to have experienced uart printing inserted here and -// there do the same magic read_CPSR() does (but, again, not always). -// Unfortunately, nop repeated several hundreds times (or a recursive -// nop function, that just calls itself a given number of times) -// doesn't have this magical property :( - #endif // PSR_H -- cgit v1.2.3