diff options
author | vetch <vetch97@gmail.com> | 2019-12-10 15:32:22 +0100 |
---|---|---|
committer | vetch <vetch97@gmail.com> | 2019-12-10 15:32:22 +0100 |
commit | 5662aacc5688bba4873367ed9ab51fb83fbd1feb (patch) | |
tree | 429aae32ff3163bf8472fcb52f3ba444c14e374c | |
parent | b0a6351d52af8bdf6fa9cca0d313df323249a520 (diff) | |
parent | c76b34db77f06450ba1c957e87a0b1df3c6c29b4 (diff) | |
download | rpi-MMU-example-5662aacc5688bba4873367ed9ab51fb83fbd1feb.tar.gz rpi-MMU-example-5662aacc5688bba4873367ed9ab51fb83fbd1feb.zip |
Merge branch 'bob' of https://repo.or.cz/RPi-MMU-example into alice
-rw-r--r-- | Makefile | 12 | ||||
-rw-r--r-- | PL0_test.c | 3 | ||||
-rw-r--r-- | PL0_test.ld | 5 | ||||
-rw-r--r-- | demo_functionality.c | 96 | ||||
-rw-r--r-- | demo_functionality.h | 4 | ||||
-rw-r--r-- | kernel.c | 6 | ||||
-rw-r--r-- | linker.ld | 41 | ||||
-rw-r--r-- | memory.h | 28 |
8 files changed, 162 insertions, 33 deletions
@@ -3,6 +3,10 @@ ELFFLAGS=-ffreestanding -O2 -nostdlib -lgcc -I. ARM_OBJECTS=kernel.o paging.o demo_functionality.o PL0_test.o uart.o loader_stage1.o loader_stage2.o +EMBEDDABLE_OBJECTS=PL_0_test_embeddable.o loader_stage2_embeddable.o + +RENAME_FLAGS=--rename-section .data=.renamed_data --rename-section .rodata=.renamed_rodata --rename-section .text=.renamed_text --rename-section .bss=.renamed_bss + all : kernel7.img %.o : %.c @@ -17,10 +21,16 @@ 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) $^ $@ + 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 +kernel.elf : boot.o kernel.o uart.o PL_0_test_embeddable.o demo_functionality.o paging.o libkernel_renamed.o arm-none-eabi-gcc -T linker.ld -o $@ $(ELFFLAGS) $^ loader_stage2.elf : loader_stage2.o uart.o @@ -5,9 +5,6 @@ void PL0_main(void) { uart_puts("hello PL0! Switching to user mode!\n\r"); - asm("cps #0b10000\n\r" - "isb" ::: "memory"); - // if all went correct, Success! gets printed uart_puts("Success!\n\r"); diff --git a/PL0_test.ld b/PL0_test.ld index 430e098..45bee5e 100644 --- a/PL0_test.ld +++ b/PL0_test.ld @@ -4,6 +4,11 @@ SECTIONS { /* 0b10101010101000000000000000000000 */ . = 0xaaa00000; + + /* For some reason ld warns when _start is not defined. */ + /* Other .elf files link ok - only PL0_test.elf seems to */ + /* expect _start to be deifned. */ + _start = .; __start = .; __text_start = .; .text : diff --git a/demo_functionality.c b/demo_functionality.c index 7bba6a6..fbf5eb4 100644 --- a/demo_functionality.c +++ b/demo_functionality.c @@ -2,6 +2,7 @@ #include "psr.h" #include "memory.h" #include "translation_table_descriptors.h" +#include "libkernel.h" void demo_paging_support(void) { @@ -55,35 +56,73 @@ void demo_mode_to_system(void) set_system_mode(); } +#define TRANSLATION_TABLE \ + ((short_section_descriptor_t volatile*) TRANSLATION_TABLE_BASE) + +extern char + __renamed_start, + __renamed_end, + __renamed_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) &__renamed_size; i++) + ((volatile char*) LIBKERNEL_SECTION_START)[i] = + (&__renamed_start)[i]; +} + extern char _binary_PL_0_test_img_start, _binary_PL_0_test_img_end, _binary_PL_0_test_img_size; -void demo_go_unprivileged(void) +void demo_setup_PL0(void) { - short_section_descriptor_t *translation_table = - (short_section_descriptor_t*) TRANSLATION_TABLE_BASE; + short_section_descriptor_t volatile *PL0_section_entry = + &TRANSLATION_TABLE[PL0_SECTION_NUMBER]; + short_section_descriptor_t volatile *UART_memory_section_entry = + &TRANSLATION_TABLE[((uint32_t) GPIO_BASE) >> 20]; - volatile short_section_descriptor_t *PL0_section = - &translation_table[PL0_SECTION_NUMBER]; - volatile short_section_descriptor_t *UART_memory_section = - &translation_table[((uint32_t) GPIO_BASE) >> 20]; + short_section_descriptor_t + PL0_section = *PL0_section_entry, + UART_memory_section = *UART_memory_section_entry; - PL0_section->SECTION_BASE_ADDRESS_31_20 = + // set up address of PL0 section + PL0_section.SECTION_BASE_ADDRESS_31_20 = UNPRIVILEGED_MEMORY_START >> 20; // make the selected section and uart section available for PL0 - PL0_section->ACCESS_PERMISSIONS_2 = + PL0_section.ACCESS_PERMISSIONS_2 = AP_2_0_MODEL_RW_ALL >> 2; - PL0_section->ACCESS_PERMISSIONS_1_0 = + PL0_section.ACCESS_PERMISSIONS_1_0 = AP_2_0_MODEL_RW_ALL & 0b011; - UART_memory_section->ACCESS_PERMISSIONS_2 = + UART_memory_section.ACCESS_PERMISSIONS_2 = AP_2_0_MODEL_RW_ALL >> 2; - UART_memory_section->ACCESS_PERMISSIONS_1_0 = + UART_memory_section.ACCESS_PERMISSIONS_1_0 = AP_2_0_MODEL_RW_ALL & 0b011; - + + *PL0_section_entry = PL0_section; + *UART_memory_section_entry = UART_memory_section; // invalidate main Translation Lookup Buffer (just in case) asm("mcr p15, 0, %0, c8, c7, 0\n\r" @@ -99,17 +138,30 @@ void demo_go_unprivileged(void) uart_puts((char*) VIRTUAL_PL0_MEMORY_START); - // now paste a userspace program to that section, jump to it and - // switch to PL0 + // now paste a userspace program to that section for (size_t i = 0; i < (size_t) &_binary_PL_0_test_img_size; i++) ((volatile char*) VIRTUAL_PL0_MEMORY_START)[i] = (&_binary_PL_0_test_img_start)[i]; - // jump to that copied code (switch to PL0 is done by that code) - asm volatile("mov r5, #0\n\r" - "movt r5, #"PL0_SECTION_NUMBER_STR"1111\n\r" - "mov sp, r5\n\r" // setting stack is important :D - "mov r5, #0\n\r" - "movt r5, #"PL0_SECTION_NUMBER_STR"0000\n\r" - "blx r5\n\r"); + uart_puts("copied PL0 and libkernel code to their sections"); +} + +void demo_go_unprivileged(void) +{ + size_t call_unprivileged_offset = + (size_t) &call_unprivileged - (size_t) &__renamed_start; + + void *call_unprivileged_new_location = + (void*) (LIBKERNEL_SECTION_START + call_unprivileged_offset); + + // 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"); } diff --git a/demo_functionality.h b/demo_functionality.h index c8b163f..5d6e659 100644 --- a/demo_functionality.h +++ b/demo_functionality.h @@ -5,6 +5,10 @@ void demo_paging_support(void); void demo_mode_to_system(void); +void demo_setup_libkernel(void); + +void demo_setup_PL0(void); + void demo_go_unprivileged(void); #endif // DEMO_FUNCTIONALITY_H @@ -29,6 +29,12 @@ 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_go_unprivileged(); + // prints some info and sets up a section for PL0 code, loads a blob // there and jumps to it... never, ever, ever returns demo_go_unprivileged(); @@ -49,5 +49,46 @@ SECTIONS . = ALIGN(4096); /* align to page size */ __bss_end = .; __bss_size = __bss_end - __bss_start; + + + + /* Here come the definitions for renamed sections */ + __renamed_start = .; + __renamed_text_start = .; + .renamed_text : + { + *(.renamed_text) + } + . = ALIGN(4096); /* align to page size */ + __renamed_text_end = .; + + __renamed_rodata_start = .; + .renamed_rodata : + { + *(.renamed_rodata) + } + . = ALIGN(4096); /* align to page size */ + __renamed_rodata_end = .; + + __renamed_data_start = .; + .renamed_data : + { + *(.renamed_data) + } + . = ALIGN(4096); /* align to page size */ + __renamed_data_end = .; + + __renamed_bss_start = .; + .renamed_bss : + { + renamed_bss = .; + *(.renamed_bss) + } + . = ALIGN(4096); /* align to page size */ + __renamed_bss_end = .; + __renamed_bss_size = __renamed_bss_end - __renamed_bss_start; + __renamed_end = .; + __renamed_size = __renamed_end - __renamed_start; + __end = .; } @@ -1,13 +1,17 @@ #ifndef MEMORY_H #define MEMORY_H +#include "paging.h" + +#define SECTION_SIZE (((uint32_t) 1) << 20) + #define INTERRUPT_VECTOR_TABLE_START ((uint32_t) 0x0) #define STACK_START ((uint32_t) 0x4000) #define STACK_END ((uint32_t) 0x8000) -extern char __end; -extern char __start; +extern const char __end; +extern const char __start; #define KERNEL_START ((uint32_t) &__start) #define KERNEL_END ((uint32_t) &__end) @@ -20,11 +24,21 @@ extern char __start; #define TRANSLATION_TABLE_END \ (TRANSLATION_TABLE_BASE + (uint32_t) (4096 * 4)) -#define PRIVILEGED_MEMORY_END TRANSLATION_TABLE_END +#define LIBKERNEL_SECTION_START \ + (((TRANSLATION_TABLE_END - (uint32_t) 1) & ~((uint32_t) 0xfffff)) \ + + SECTION_SIZE) + +#define LIBKERNEL_SECTION_END \ + (LIBKERNEL_SECTION_START + SECTION_SIZE) -#define UNPRIVILEGED_MEMORY_START \ - (((PRIVILEGED_MEMORY_END - (uint32_t) 1) & ~((uint32_t) 0xfffff)) \ - + (uint32_t) 0x100000) +// 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" @@ -32,4 +46,4 @@ extern char __start; #define VIRTUAL_PL0_MEMORY_START (PL0_SECTION_NUMBER << 20) #endif // MEMORY_H - + |