diff options
author | Wojtek Kosior <kwojtus@protonmail.com> | 2019-12-28 15:55:29 +0100 |
---|---|---|
committer | Wojtek Kosior <kwojtus@protonmail.com> | 2019-12-28 15:55:29 +0100 |
commit | c374eaacbc0d16983bbd1112fefa74dbe88e1e53 (patch) | |
tree | c6930675e0200a4aed724fd65947853f2b4f274f | |
parent | 7062b101197c03c7f4806d83b8d79cf34d3b6a42 (diff) | |
download | rpi-MMU-example-c374eaacbc0d16983bbd1112fefa74dbe88e1e53.tar.gz rpi-MMU-example-c374eaacbc0d16983bbd1112fefa74dbe88e1e53.zip |
use ldm instruction instead of libkernel for entering user mode; get rid of libkernel (no longer needed)
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | demo_functionality.c | 69 | ||||
-rw-r--r-- | kernel.c | 2 | ||||
-rw-r--r-- | libkernel.c | 12 | ||||
-rw-r--r-- | libkernel.h | 6 | ||||
-rw-r--r-- | linker.ld | 11 | ||||
-rw-r--r-- | memory.h | 13 | ||||
-rw-r--r-- | psr.h | 15 |
8 files changed, 40 insertions, 90 deletions
@@ -24,7 +24,7 @@ all : kernel7.img 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 demo_functionality.o paging.o libkernel.o interrupt_vector.o interrupts.o ramfs_embeddable.o ramfs.o +kernel.elf : boot.o kernel.o uart.o demo_functionality.o paging.o interrupt_vector.o interrupts.o ramfs_embeddable.o ramfs.o arm-none-eabi-gcc -T linker.ld -o $@ $(ELFFLAGS) $^ loader.elf : boot.o loader_stage1.o loader_stage2.o uart.o diff --git a/demo_functionality.c b/demo_functionality.c index 206dd2b..4b002d6 100644 --- a/demo_functionality.c +++ b/demo_functionality.c @@ -2,7 +2,6 @@ #include "psr.h" #include "memory.h" #include "translation_table_descriptors.h" -#include "libkernel.h" #include "ramfs.h" void demo_paging_support(void) @@ -58,37 +57,6 @@ void demo_current_mode(void) ((short_section_descriptor_t volatile*) TRANSLATION_TABLE_BASE) extern char - __libkernel_start, - __libkernel_end, - __libkernel_size; - -void demo_setup_libkernel(void) { - short_section_descriptor_t volatile *libkernel_section_entry = - &TRANSLATION_TABLE[LIBKERNEL_SECTION_NUMBER]; - - short_section_descriptor_t - libkernel_section = *libkernel_section_entry; - - // make libkernel section executable and read-only for - // unprivileged code - libkernel_section.ACCESS_PERMISSIONS_2 = - AP_2_0_MODEL_RW_PL1_RO_PL0 >> 2; - libkernel_section.ACCESS_PERMISSIONS_1_0 = - AP_2_0_MODEL_RW_PL1_RO_PL0 & 0b011; - - *libkernel_section_entry = libkernel_section; - - // invalidate main Translation Lookup Buffer (just in case) - asm("mcr p15, 0, %0, c8, c7, 0\n\r" - "isb" :: "r" (0) : "memory"); - - // copy libkernel code to libkernel section - for (size_t i = 0; i < (size_t) &__libkernel_size; i++) - ((volatile char*) LIBKERNEL_SECTION_START)[i] = - (&__libkernel_start)[i]; -} - -extern char _binary_ramfs_img_start, _binary_ramfs_img_end, _binary_ramfs_img_size; @@ -151,27 +119,34 @@ void demo_setup_PL0(void) ((volatile char*) VIRTUAL_PL0_MEMORY_START)[i] = PL_0_test_img.file_contents[i]; - uart_puts("copied PL0 and libkernel code to their sections\n\r"); + uart_puts("copied PL0 code to it's section\n\r"); +} + +// needed for array initialization in demo_go_unprivileged() +void *memset(void *s, int c, size_t n) +{ + char *mem = s; + + for (size_t i = 0; i < n; i++) + mem[i] = c; + + return s; } void demo_go_unprivileged(void) { - size_t call_unprivileged_offset = - (size_t) &call_unprivileged - (size_t) &__libkernel_start; + uint32_t PL0_regs[16] = {0}; + PL0_regs[15] = VIRTUAL_PL0_MEMORY_START; // the new pc + PL0_regs[13] = (PL0_SECTION_NUMBER + 1) << 20; // the new sp + + PSR_t new_SPSR = read_CPSR(); + new_SPSR.fields.PSR_MODE_4_0 = MODE_USER; + write_SPSR(new_SPSR); - void *call_unprivileged_new_location = - (void*) (LIBKERNEL_SECTION_START + call_unprivileged_offset); + uart_puts("All ready, jumping to PL0 code\n\r"); - // call call_unprivileged from libkernel - asm volatile("mov r5, %0\n\r" - "mov r0, %1\n\r" - "mov r4, #0\n\r" - "movt r4, #"PL0_SECTION_NUMBER_STR"1111\n\r" - "mov sp, r4\n\r" // setting stack is important :D - "blx r5\n\r" :: - "r" (call_unprivileged_new_location), - "r" (VIRTUAL_PL0_MEMORY_START) - : "memory", "r4", "r5", "r0"); + asm volatile("ldm %0, {r0 - r15} ^" :: + "r" (PL0_regs)); } extern char @@ -27,8 +27,6 @@ void kernel_main(uint32_t r0, uint32_t r1, uint32_t atags) // prints some info and sets upp translation table, turns on MMU setup_flat_map(); - demo_setup_libkernel(); - demo_setup_PL0(); demo_setup_interrupts(); diff --git a/libkernel.c b/libkernel.c deleted file mode 100644 index 0955e0e..0000000 --- a/libkernel.c +++ /dev/null @@ -1,12 +0,0 @@ -// This is the privileged code, that gets placed somewhere in -// unprivileged process' address space. It's compiled as relocatable, -// so it can be loaded at different address for different processes. - -void call_unprivileged(void (*address) (void)) { - // switch to PL0 - asm("cps #0b10000\n\r" - "isb" ::: "memory"); - - // jump to that unprivileged code - address(); -} diff --git a/libkernel.h b/libkernel.h deleted file mode 100644 index a8af348..0000000 --- a/libkernel.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef LIBKERNEL_H -#define LIBKERNEL_H - -void call_unprivileged(void (*address) (void)); - -#endif // LIBKERNEL_H @@ -30,17 +30,6 @@ SECTIONS } __kernel_size = __kernel_end - __kernel_start; - - /* libkernel */ - .libkernel : - { - __libkernel_start = .; - libkernel.o - __libkernel_end = .; - } - __libkernel_size = __libkernel_end - __libkernel_start; - - .interrupts : { __interrupts_start = .; @@ -24,24 +24,15 @@ extern const char __start; #define TRANSLATION_TABLE_END \ (TRANSLATION_TABLE_BASE + (uint32_t) (4096 * 4)) -#define LIBKERNEL_SECTION_START \ - (((TRANSLATION_TABLE_END - (uint32_t) 1) & ~((uint32_t) 0xfffff)) \ +#define PRIVILEGED_MEMORY_END \ + (((TRANSLATION_TABLE_END - (uint32_t) 1) & ~((uint32_t) 0xfffff)) \ + SECTION_SIZE) -#define LIBKERNEL_SECTION_END \ - (LIBKERNEL_SECTION_START + SECTION_SIZE) - -// section for libkernel is flat-mapped -#define LIBKERNEL_SECTION_NUMBER (LIBKERNEL_SECTION_START >> 20) - -#define PRIVILEGED_MEMORY_END LIBKERNEL_SECTION_END - #define UNPRIVILEGED_MEMORY_START PRIVILEGED_MEMORY_END #define UNPRIVILEGED_MEMORY_END \ (UNPRIVILEGED_MEMORY_START + SECTION_SIZE) #define PL0_SECTION_NUMBER ((uint32_t) 0b101010101010) -#define PL0_SECTION_NUMBER_STR "0b101010101010" #define VIRTUAL_PL0_MEMORY_START (PL0_SECTION_NUMBER << 20) @@ -64,4 +64,19 @@ inline static PSR_t read_CPSR(void) return CPSR; } +inline static PSR_t read_SPSR(void) +{ + PSR_t SPSR; + // get content of saved program status register + asm("mrs %0, spsr" : "=r" (SPSR.raw) :: "memory"); + + return SPSR; +} + +inline static void write_SPSR(PSR_t SPSR) +{ + // set content of saved program status register + asm("msr spsr, %0" :: "r" (SPSR.raw)); +} + #endif // PSR_H |