From 4c110d2802742fe1d37ba7280f374174fc45cbe1 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Tue, 24 Dec 2019 22:43:07 +0100 Subject: simplify linking of libkernel --- linker.ld | 63 ++++++++++++++++++--------------------------------------------- 1 file changed, 18 insertions(+), 45 deletions(-) (limited to 'linker.ld') diff --git a/linker.ld b/linker.ld index 01eda35..387e7c7 100644 --- a/linker.ld +++ b/linker.ld @@ -1,18 +1,21 @@ -ENTRY(_start) +ENTRY(_start) /* defined in boot.S */ SECTIONS { - /* Starts at LOADER_ADDR, which is 0x8000 - that's where RPis in */ - /* 32-bit mode load kernel at. */ + /* Starts at 0x8000 - that's where RPis in 32-bit mode load kernel at. */ /* My experiments do, however, show, that qemu emulating RPi2 */ /* loads the kernel at 0x10000! (took some pain to find out). */ - /* Since we're using a bootloader now, we can compile the kernel */ - /* for 0x8000 and bootloader will load it properly (although it */ - /* itself still has to be compiled for 0x10000) */ - /* rpi-open-firmware, ont he other hand, loads kernel at 0x2000000 */ - /* This issue is also to be avoided by the use of bootloader */ + /* rpi-open-firmware, on the other hand, loads kernel at 0x2000000! */ + /* This is not really a problem, since: */ + /* 1. We can use out bootloader to load the kernel at 0x8000 */ + /* 2. We compile kernel with -fPIC, so it should be able to work with */ + /* any load addr. + /* 3. In qemu, we can load kernel.elf instead of raw binary */ + /* (qemu will do the loading then) */ + . = 0x8000; - /* For AArch64, use . = 0x80000; Unless this too is wrong in qemu… */ + + /* For AArch64, use . = 0x80000 */ __start = .; __text_start = .; @@ -51,44 +54,14 @@ SECTIONS __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 : + /* libkernel */ + .libkernel : { - renamed_bss = .; - *(.renamed_bss) + __libkernel_start = .; + libkernel.o + __libkernel_end = .; } - . = 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; + __libkernel_size = __libkernel_end - __libkernel_start; . = ALIGN(4096); /* align to page size */ -- cgit v1.2.3 From 6a5684927d5a6d201b407ff30340307fe9813677 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Thu, 26 Dec 2019 17:55:15 +0100 Subject: fix linking of libkernel --- linker.ld | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'linker.ld') diff --git a/linker.ld b/linker.ld index 387e7c7..60387bf 100644 --- a/linker.ld +++ b/linker.ld @@ -22,7 +22,7 @@ SECTIONS .text : { KEEP(*(.text.boot)) - *(.text) + *(EXCLUDE_FILE (libkernel.o) .text) } . = ALIGN(4096); /* align to page size */ __text_end = .; @@ -30,7 +30,7 @@ SECTIONS __rodata_start = .; .rodata : { - *(.rodata) + *(EXCLUDE_FILE (libkernel.o) .rodata) } . = ALIGN(4096); /* align to page size */ __rodata_end = .; @@ -38,7 +38,7 @@ SECTIONS __data_start = .; .data : { - *(.data) + *(EXCLUDE_FILE (libkernel.o) .data) } . = ALIGN(4096); /* align to page size */ __data_end = .; @@ -47,7 +47,7 @@ SECTIONS .bss : { bss = .; - *(.bss) + *(EXCLUDE_FILE (libkernel.o) .bss) } . = ALIGN(4096); /* align to page size */ __bss_end = .; -- cgit v1.2.3 From 93a1c704c99a48803d118f66ac4fe08510fb4b89 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Thu, 26 Dec 2019 18:21:29 +0100 Subject: simplify linker script; rely on initially-zero memory to be included in binary image (no bss zeroing in assembly code) --- boot.S | 20 +------------------- linker.ld | 36 +++++++----------------------------- 2 files changed, 8 insertions(+), 48 deletions(-) (limited to 'linker.ld') diff --git a/boot.S b/boot.S index 5e510f8..a792c94 100644 --- a/boot.S +++ b/boot.S @@ -1,7 +1,7 @@ // armv7 mode // To keep this in the first portion of the binary. -.section ".text.boot" +.section ".boot" //.org 0x8000 @@ -30,24 +30,6 @@ _start: ldr r5, =__start mov sp, r5 - // Clear out bss. - ldr r4, =__bss_start - ldr r9, =__bss_end - mov r5, #0 - mov r6, #0 - mov r7, #0 - mov r8, #0 - b 2f - -1: - // store multiple at r4. - stmia r4!, {r5-r8} - - // If we are still below bss_end, loop. -2: - cmp r4, r9 - blo 1b - // Call kernel_main ldr r3, =kernel_main bx r3 diff --git a/linker.ld b/linker.ld index 60387bf..ed40054 100644 --- a/linker.ld +++ b/linker.ld @@ -18,40 +18,18 @@ SECTIONS /* For AArch64, use . = 0x80000 */ __start = .; - __text_start = .; - .text : + .boot : { - KEEP(*(.text.boot)) - *(EXCLUDE_FILE (libkernel.o) .text) + boot.o } - . = ALIGN(4096); /* align to page size */ - __text_end = .; - - __rodata_start = .; - .rodata : - { - *(EXCLUDE_FILE (libkernel.o) .rodata) - } - . = ALIGN(4096); /* align to page size */ - __rodata_end = .; - - __data_start = .; - .data : - { - *(EXCLUDE_FILE (libkernel.o) .data) - } - . = ALIGN(4096); /* align to page size */ - __data_end = .; - - __bss_start = .; - .bss : + __kernel_start = .; + .kernel : { - bss = .; - *(EXCLUDE_FILE (libkernel.o) .bss) + *(EXCLUDE_FILE (libkernel.o interrupt_vector.o interrupts.o) *) } . = ALIGN(4096); /* align to page size */ - __bss_end = .; - __bss_size = __bss_end - __bss_start; + __kernel_end = .; + __kernel_size = __kernel_end - __kernel_start; /* libkernel */ -- cgit v1.2.3 From 9d587f9f750253461314757f2f861c5214563120 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Thu, 26 Dec 2019 18:48:38 +0100 Subject: improve linking of interrupts --- demo_functionality.c | 10 +++++----- interrupt_vector.S | 4 +++- interrupts.c | 9 ++++++--- linker.ld | 18 +++++++++--------- 4 files changed, 23 insertions(+), 18 deletions(-) (limited to 'linker.ld') diff --git a/demo_functionality.c b/demo_functionality.c index aedab08..c6f7e5c 100644 --- a/demo_functionality.c +++ b/demo_functionality.c @@ -164,9 +164,9 @@ void demo_go_unprivileged(void) } extern char - __interrupt_vectors_start, - __interrupt_vectors_end, - __interrupt_vectors_size; + __interrupts_start, + __interrupts_end, + __interrupts_size; extern void (*volatile system_reentry_point)(void); @@ -180,7 +180,7 @@ void demo_setup_interrupts(void) { system_reentry_point = system_reentry; - for (size_t i = 0; i < (size_t) &__interrupt_vectors_size; i++) + for (size_t i = 0; i < (size_t) &__interrupts_size; i++) ((volatile char*) 0)[i] = - (&__interrupt_vectors_start)[i]; + (&__interrupts_start)[i]; } diff --git a/interrupt_vector.S b/interrupt_vector.S index f71330b..d20bf6d 100644 --- a/interrupt_vector.S +++ b/interrupt_vector.S @@ -1,4 +1,4 @@ -.section ".interrupt_vectors.text" +.section ".interrupts.vector" .global abort_handler .local generic_handler @@ -12,6 +12,8 @@ _interrupt_vectors: b generic_handler b generic_handler +.section ".interrupts.text" + generic_handler: b generic_handler abort_handler_caller: diff --git a/interrupts.c b/interrupts.c index 191ce40..6952f89 100644 --- a/interrupts.c +++ b/interrupts.c @@ -5,7 +5,10 @@ If an undefined instruction is encountered, the CPU will start executing this function. Just trap here as a debug solution. */ -void __attribute__((interrupt("UNDEF"))) undefined_instruction_vector(void) +void +__attribute__((interrupt("UNDEF"))) +__attribute__((section(".interrupts.text"))) +undefined_instruction_vector(void) { uart_puts("Undefined instruction occured"); while( 1 ) @@ -14,12 +17,12 @@ void __attribute__((interrupt("UNDEF"))) undefined_instruction_vector(void) } } -void __attribute__((section(".interrupt_vectors.data"))) +void __attribute__((section(".interrupts.data"))) (*system_reentry_point) (void); void __attribute__((interrupt("ABORT"))) -__attribute__((section(".interrupt_vectors.text"))) +__attribute__((section(".interrupts.text"))) abort_handler(void) { system_reentry_point(); diff --git a/linker.ld b/linker.ld index ed40054..5bdbfd2 100644 --- a/linker.ld +++ b/linker.ld @@ -42,17 +42,17 @@ SECTIONS __libkernel_size = __libkernel_end - __libkernel_start; - . = ALIGN(4096); /* align to page size */ - __interrupt_vectors_start = .; - .interrupt_vectors : + + .interrupts : { - interrupt_vectors = .; - *(.interrupt_vectors.text) - *(.interrupt_vectors.data) + __interrupts_start = .; + KEEP(*(.interrupts.vector)) + interrupt_vector.o + interrupts.o + __interrupts_end = .; } - . = ALIGN(4096); /* align to page size */ - __interrupt_vectors_end = .; - __interrupt_vectors_size = __interrupt_vectors_end - __interrupt_vectors_start; + + __interrupts_size = __interrupts_end - __interrupts_start; __end = .; } -- cgit v1.2.3 From 4d3cd9bd400b3d07d752d60ce2b3c425a53b72d6 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Thu, 26 Dec 2019 19:02:32 +0100 Subject: improve linking of initial boot code --- boot.S | 12 +++--------- linker.ld | 14 +++++--------- 2 files changed, 8 insertions(+), 18 deletions(-) (limited to 'linker.ld') diff --git a/boot.S b/boot.S index a792c94..ae56387 100644 --- a/boot.S +++ b/boot.S @@ -1,20 +1,14 @@ // armv7 mode -// To keep this in the first portion of the binary. -.section ".boot" - -//.org 0x8000 - -// Make _start global. -.globl _start - // Entry point for the kernel. // r15 -> should begin execution at 0x8000. // r0 -> 0x00000000 // r1 -> 0x00000C42 // r2 -> 0x00000100 - start of ATAGS // preserve these registers as argument for kernel_main -_start: + +.globl _boot // make entry point label global +_boot: // Shut off extra cores mrc p15, 0, r5, c0, c0, 5 and r5, r5, #3 diff --git a/linker.ld b/linker.ld index 5bdbfd2..a0ad1ae 100644 --- a/linker.ld +++ b/linker.ld @@ -1,4 +1,4 @@ -ENTRY(_start) /* defined in boot.S */ +ENTRY(_boot) /* defined in boot.S; qemu needs it to run elf file */ SECTIONS { @@ -15,20 +15,16 @@ SECTIONS . = 0x8000; - /* For AArch64, use . = 0x80000 */ + /* RPi in 64-bit mode uses address 0x80000 instead */ __start = .; - .boot : - { - boot.o - } - __kernel_start = .; .kernel : { + __kernel_start = .; + KEEP(boot.o) *(EXCLUDE_FILE (libkernel.o interrupt_vector.o interrupts.o) *) + __kernel_end = .; } - . = ALIGN(4096); /* align to page size */ - __kernel_end = .; __kernel_size = __kernel_end - __kernel_start; -- cgit v1.2.3 From d9ac897bd8aa7a8b6471bca1eb8a2bd314fdb133 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Thu, 26 Dec 2019 19:06:18 +0100 Subject: minor changes (comments, whitespace) --- linker.ld | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'linker.ld') diff --git a/linker.ld b/linker.ld index a0ad1ae..33ac68c 100644 --- a/linker.ld +++ b/linker.ld @@ -2,16 +2,17 @@ ENTRY(_boot) /* defined in boot.S; qemu needs it to run elf file */ SECTIONS { - /* Starts at 0x8000 - that's where RPis in 32-bit mode load kernel at. */ - /* My experiments do, however, show, that qemu emulating RPi2 */ - /* loads the kernel at 0x10000! (took some pain to find out). */ - /* rpi-open-firmware, on the other hand, loads kernel at 0x2000000! */ + /* Starts at 0x8000 - that's where RPis in 32-bit mode load */ + /* kernel at. My experiments do, however, show, that qemu */ + /* emulating RPi2 loads the kernel at 0x10000! (took some pain */ + /* to find out). rpi-open-firmware, on the other hand, loads */ + /* kernel at 0x2000000! */ /* This is not really a problem, since: */ - /* 1. We can use out bootloader to load the kernel at 0x8000 */ - /* 2. We compile kernel with -fPIC, so it should be able to work with */ - /* any load addr. + /* 1. We can use our bootloader to load the kernel at 0x8000 */ + /* 2. We compile kernel with -fPIC, so it should be able to */ + /* work with any load addr. */ /* 3. In qemu, we can load kernel.elf instead of raw binary */ - /* (qemu will do the loading then) */ + /* (qemu will do the right thing then) */ . = 0x8000; @@ -38,7 +39,6 @@ SECTIONS __libkernel_size = __libkernel_end - __libkernel_start; - .interrupts : { __interrupts_start = .; @@ -47,7 +47,6 @@ SECTIONS interrupts.o __interrupts_end = .; } - __interrupts_size = __interrupts_end - __interrupts_start; __end = .; -- cgit v1.2.3 From 19efd77944dd42c3451a19e60a6948a52bc9ccad Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Thu, 26 Dec 2019 19:22:24 +0100 Subject: minor changes to boot code --- boot.S | 18 ++++++++---------- linker.ld | 2 ++ 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'linker.ld') diff --git a/boot.S b/boot.S index be858ee..0cd0339 100644 --- a/boot.S +++ b/boot.S @@ -7,26 +7,24 @@ // r2 -> 0x00000100 - start of ATAGS // preserve these registers as argument for kernel_main -.globl _boot // make entry point label global +.global _boot // make entry point label global _boot: - // Shut off extra cores - mrc p15, 0, r5, c0, c0, 5 - and r5, r5, #3 - cmp r5, #0 + // Only let the first core execute + mrc p15, 0, r3, c0, c0, 5 + and r3, r3, #3 + cmp r3, #0 beq proceed // this is a kind of blef - races can theoretically still occur // when the main core overwrites this part of memory wfe proceed: - // go to system mode + // go to system mode (we had problems doing this later) cps #0b11111 isb - // Setup the stack. - // It shall be directly below our kernel image - ldr r5, =__start - mov sp, r5 + // Initialize the stack (_stack_top is defined in linker.ld) + ldr sp, =_stack_top // Call kernel_main ldr r3, =kernel_main diff --git a/linker.ld b/linker.ld index 33ac68c..e0e72b2 100644 --- a/linker.ld +++ b/linker.ld @@ -50,4 +50,6 @@ SECTIONS __interrupts_size = __interrupts_end - __interrupts_start; __end = .; + + _stack_top = __start; } -- cgit v1.2.3 From 826d5b3ba04a8b830c8a92a6f69ca4e223257c5b Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Sat, 28 Dec 2019 14:01:14 +0100 Subject: place PL_0_test.img in ramfs instead of embedding it directly --- Makefile | 7 ++++++- demo_functionality.c | 21 ++++++++++++++++----- linker.ld | 4 +++- 3 files changed, 25 insertions(+), 7 deletions(-) (limited to 'linker.ld') diff --git a/Makefile b/Makefile index 3d6b095..b8800cc 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,8 @@ ARM_OBJECTS=kernel.o paging.o demo_functionality.o PL0_test.o uart.o loader_stag EMBEDDABLE_OBJECTS=PL_0_test_embeddable.o loader_stage2_embeddable.o +RAMFS_FILES=PL_0_test.img + all : kernel7.img %.o : %.c @@ -22,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 PL_0_test_embeddable.o demo_functionality.o paging.o libkernel.o interrupt_vector.o interrupts.o +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 arm-none-eabi-gcc -T linker.ld -o $@ $(ELFFLAGS) $^ loader.elf : boot.o loader_stage1.o loader_stage2.o uart.o @@ -49,6 +51,9 @@ pipe_image : pipe_image.c lib/rs232/rs232.c makefs : makefs.c gcc -Wall -std=gnu99 -O3 $^ -o $@ +ramfs.img : makefs $(RAMFS_FILES) + ./makefs $(RAMFS_FILES) > $@ + clean : -rm *.img *.elf *.o pipe_image diff --git a/demo_functionality.c b/demo_functionality.c index c6f7e5c..206dd2b 100644 --- a/demo_functionality.c +++ b/demo_functionality.c @@ -3,6 +3,7 @@ #include "memory.h" #include "translation_table_descriptors.h" #include "libkernel.h" +#include "ramfs.h" void demo_paging_support(void) { @@ -88,12 +89,22 @@ void demo_setup_libkernel(void) { } extern char - _binary_PL_0_test_img_start, - _binary_PL_0_test_img_end, - _binary_PL_0_test_img_size; + _binary_ramfs_img_start, + _binary_ramfs_img_end, + _binary_ramfs_img_size; void demo_setup_PL0(void) { + // find PL_0_test.img im ramfs + struct ramfile PL_0_test_img; + + if (find_file(&_binary_ramfs_img_start, "PL_0_test.img", + &PL_0_test_img)) + { + uart_puts("PL_0_test.img not found :(\r\n"); + asm volatile ("wfi"); + } + short_section_descriptor_t volatile *PL0_section_entry = &TRANSLATION_TABLE[PL0_SECTION_NUMBER]; short_section_descriptor_t volatile *UART_memory_section_entry = @@ -136,9 +147,9 @@ void demo_setup_PL0(void) uart_puts((char*) VIRTUAL_PL0_MEMORY_START); // now paste a userspace program to that section - for (size_t i = 0; i < (size_t) &_binary_PL_0_test_img_size; i++) + for (uint32_t i = 0; i < PL_0_test_img.file_size; i++) ((volatile char*) VIRTUAL_PL0_MEMORY_START)[i] = - (&_binary_PL_0_test_img_start)[i]; + PL_0_test_img.file_contents[i]; uart_puts("copied PL0 and libkernel code to their sections\n\r"); } diff --git a/linker.ld b/linker.ld index e0e72b2..7b585dc 100644 --- a/linker.ld +++ b/linker.ld @@ -23,7 +23,9 @@ SECTIONS { __kernel_start = .; KEEP(boot.o) - *(EXCLUDE_FILE (libkernel.o interrupt_vector.o interrupts.o) *) + *(EXCLUDE_FILE (ramfs_embeddable.o libkernel.o interrupt_vector.o interrupts.o) *) + . = ALIGN(4); + ramfs_embeddable.o __kernel_end = .; } __kernel_size = __kernel_end - __kernel_start; -- cgit v1.2.3 From c374eaacbc0d16983bbd1112fefa74dbe88e1e53 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Sat, 28 Dec 2019 15:55:29 +0100 Subject: use ldm instruction instead of libkernel for entering user mode; get rid of libkernel (no longer needed) --- Makefile | 2 +- demo_functionality.c | 69 +++++++++++++++++----------------------------------- kernel.c | 2 -- libkernel.c | 12 --------- libkernel.h | 6 ----- linker.ld | 11 --------- memory.h | 13 ++-------- psr.h | 15 ++++++++++++ 8 files changed, 40 insertions(+), 90 deletions(-) delete mode 100644 libkernel.c delete mode 100644 libkernel.h (limited to 'linker.ld') diff --git a/Makefile b/Makefile index b8800cc..55d0d1b 100644 --- a/Makefile +++ b/Makefile @@ -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) @@ -57,37 +56,6 @@ void demo_current_mode(void) #define TRANSLATION_TABLE \ ((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, @@ -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 diff --git a/kernel.c b/kernel.c index fc629e1..9cdb82a 100644 --- a/kernel.c +++ b/kernel.c @@ -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 diff --git a/linker.ld b/linker.ld index 7b585dc..673d7e2 100644 --- a/linker.ld +++ b/linker.ld @@ -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 = .; diff --git a/memory.h b/memory.h index 1c9ae35..d369694 100644 --- a/memory.h +++ b/memory.h @@ -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) diff --git a/psr.h b/psr.h index 9809fc4..b2adafb 100644 --- a/psr.h +++ b/psr.h @@ -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 -- cgit v1.2.3 From 38afee0bfe051f1c1e5b9426395eb50b9d8a7bc2 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Sat, 28 Dec 2019 18:53:16 +0100 Subject: correct the notion of PIC in the comment --- linker.ld | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'linker.ld') diff --git a/linker.ld b/linker.ld index 673d7e2..444bbf6 100644 --- a/linker.ld +++ b/linker.ld @@ -9,8 +9,9 @@ SECTIONS /* kernel at 0x2000000! */ /* This is not really a problem, since: */ /* 1. We can use our bootloader to load the kernel at 0x8000 */ - /* 2. We compile kernel with -fPIC, so it should be able to */ - /* work with any load addr. */ + /* 2. Stage 1 of the bootloader is written in careful */ + /* assembly, so that the loader itself should work */ + /* regardless of where it is loaded. */ /* 3. In qemu, we can load kernel.elf instead of raw binary */ /* (qemu will do the right thing then) */ @@ -23,9 +24,9 @@ SECTIONS { __kernel_start = .; KEEP(boot.o) - *(EXCLUDE_FILE (ramfs_embeddable.o libkernel.o interrupt_vector.o interrupts.o) *) . = ALIGN(4); ramfs_embeddable.o + *(EXCLUDE_FILE (libkernel.o interrupt_vector.o interrupts.o) *) __kernel_end = .; } __kernel_size = __kernel_end - __kernel_start; -- cgit v1.2.3 From 700f4c412d42c9b9811269045c0e363a0331bba9 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Sat, 28 Dec 2019 21:54:42 +0100 Subject: split kernel into 2 stages; second stage gets copied to 0x0 and runs from there --- Makefile | 29 ++++++++++++++++++----- boot.S | 27 --------------------- demo_functionality.c | 26 ++------------------ interrupt_vector.S | 53 +++++++++++++++++++++++++++++------------ interrupts.c | 55 +++++++++++++++++++++++++++++++++++------- kernel.c | 44 ---------------------------------- kernel_stage1.S | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel_stage1.ld | 27 +++++++++++++++++++++ kernel_stage2.ld | 52 ++++++++++++++++++++++++++++++++++++++++ linker.ld | 47 ------------------------------------ memory.h | 43 ++++++++++++++++++++++----------- setup.c | 41 ++++++++++++++++++++++++++++++++ 12 files changed, 325 insertions(+), 186 deletions(-) delete mode 100644 boot.S delete mode 100644 kernel.c create mode 100644 kernel_stage1.S create mode 100644 kernel_stage1.ld create mode 100644 kernel_stage2.ld delete mode 100644 linker.ld create mode 100644 setup.c (limited to 'linker.ld') diff --git a/Makefile b/Makefile index 29efa86..68368a5 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,10 @@ -CFLAGS=-mcpu=cortex-a7 -ffreestanding -std=gnu11 -Wall -Wextra -O2 -fPIC -I. +CFLAGS=-mcpu=cortex-a7 -ffreestanding -std=gnu11 -Wall -Wextra -O2 -I. ELFFLAGS=-nostdlib -lgcc ARM_OBJECTS=kernel.o paging.o demo_functionality.o PL0_test.o uart.o loader_stage1.o loader_stage2.o +KERNEL_STAGE2_OBJECTS=setup.o interrupt_vector.o interrupts.o uart.o demo_functionality.o paging.o ramfs_embeddable.o ramfs.o + RAMFS_FILES=PL_0_test.img all : kernel.img @@ -10,20 +12,32 @@ all : kernel.img %.o : %.c arm-none-eabi-gcc $(CFLAGS) -c $^ -o $@ -%.o : %.S - arm-none-eabi-as -mcpu=cortex-a7 $^ -o $@ - %.img : %.elf arm-none-eabi-objcopy $^ -O binary $@ +%.o : %.S + arm-none-eabi-as -mcpu=cortex-a7 $^ -o $@ + %_embeddable.o : %.img arm-none-eabi-objcopy -I binary -O elf32-littlearm -B arm --rename-section .data=.rodata $^ $@ 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 interrupt_vector.o interrupts.o ramfs_embeddable.o ramfs.o - arm-none-eabi-gcc -T linker.ld -o $@ $(ELFFLAGS) $^ +kernel_stage1.o : kernel_stage1.S kernel_stage2.img + arm-none-eabi-as -mcpu=cortex-a7 $< -o $@ + +kernel.elf : kernel_stage1.ld kernel_stage1.o + arm-none-eabi-gcc -T $< -o $@ $(ELFFLAGS) kernel_stage1.o + +kernel.img : kernel.elf + arm-none-eabi-objcopy $^ -O binary $@ + +kernel_stage2.elf : kernel_stage2.ld $(KERNEL_STAGE2_OBJECTS) + arm-none-eabi-gcc -T $< -o $@ $(ELFFLAGS) $(KERNEL_STAGE2_OBJECTS) + +#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_stage2.elf : loader_stage2.o uart.o arm-none-eabi-gcc -T loader_stage2_linker.ld -o $@ $(ELFFLAGS) $^ @@ -42,6 +56,9 @@ loader.img : loader.elf qemu-elf : kernel.elf qemu-system-arm -m 256 -M raspi2 -serial stdio -kernel $^ +qemu-img : kernel.img + qemu-system-arm -m 256 -M raspi2 -serial stdio -kernel $^ + qemu-bin : loader.img kernel.img pipe_image ./pipe_image --stdout | qemu-system-arm -m 256 -M raspi2 -serial stdio -kernel $< diff --git a/boot.S b/boot.S deleted file mode 100644 index 593ed11..0000000 --- a/boot.S +++ /dev/null @@ -1,27 +0,0 @@ -// armv7 mode - -// Entry point for the kernel. -// r15 -> should begin execution at 0x8000. -// r0 -> 0x00000000 -// r1 -> 0x00000C42 -// r2 -> 0x00000100 - start of ATAGS -// preserve these registers as argument for kernel_main - -.global _boot // make entry point label global -_boot: - // Only let the first core execute - mrc p15, 0, r3, c0, c0, 5 - and r3, r3, #3 - cmp r3, #0 - beq proceed - // this is a kind of blef - races can theoretically still occur - // when the main core overwrites this part of memory - wfe - -proceed: - // Initialize the stack (_stack_top is defined in linker.ld) - ldr sp, =_stack_top - - // Call kernel_main - ldr r3, =kernel_main - bx r3 diff --git a/demo_functionality.c b/demo_functionality.c index 4b002d6..420639b 100644 --- a/demo_functionality.c +++ b/demo_functionality.c @@ -53,7 +53,7 @@ void demo_current_mode(void) uart_puts(mode_name); } -#define TRANSLATION_TABLE \ +#define TRANSLATION_TABLE \ ((short_section_descriptor_t volatile*) TRANSLATION_TABLE_BASE) extern char @@ -144,29 +144,7 @@ void demo_go_unprivileged(void) write_SPSR(new_SPSR); uart_puts("All ready, jumping to PL0 code\n\r"); - + asm volatile("ldm %0, {r0 - r15} ^" :: "r" (PL0_regs)); } - -extern char - __interrupts_start, - __interrupts_end, - __interrupts_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) &__interrupts_size; i++) - ((volatile char*) 0)[i] = - (&__interrupts_start)[i]; -} diff --git a/interrupt_vector.S b/interrupt_vector.S index d20bf6d..6037b7c 100644 --- a/interrupt_vector.S +++ b/interrupt_vector.S @@ -1,22 +1,45 @@ -.section ".interrupts.vector" - -.global abort_handler -.local generic_handler -.global _interrupt_vectors _interrupt_vectors: - b generic_handler - b generic_handler - b generic_handler + b reset_handler_caller + b undef_handler_caller + b svc_handler_caller b abort_handler_caller b abort_handler_caller - b generic_handler - b generic_handler - -.section ".interrupts.text" + b generic_handler_caller + b irq_handler_caller + b fiq_handler_caller + +reset_handler_caller: + ldr sp, =_stack_top + ldr r5, =reset_handler + bx r5 + +undef_handler_caller: + ldr sp, =_stack_top + ldr r5, =undefined_instruction_vector + bx r5 -generic_handler: - b generic_handler +svc_handler_caller: + ldr sp, =_stack_top + ldr r5, =supervisor_call_handler + bx r5 + abort_handler_caller: - mov sp, #0x8000 + ldr sp, =_stack_top ldr r5, =abort_handler bx r5 + +generic_handler_caller: + ldr sp, =_stack_top + ldr r5, =generic_handler + bx r5 + +irq_handler_caller: + ldr sp, =_stack_top + ldr r5, =irq_handler + bx r5 + +fiq_handler_caller: + ldr sp, =_stack_top + ldr r5, =fiq_handler + bx r5 + diff --git a/interrupts.c b/interrupts.c index 6952f89..1b0590a 100644 --- a/interrupts.c +++ b/interrupts.c @@ -1,10 +1,20 @@ #include "uart.h" -/** - @brief The undefined instruction interrupt handler - If an undefined instruction is encountered, the CPU will start - executing this function. Just trap here as a debug solution. -*/ +void setup(void); + +void reset_handler(void) +{ + static _Bool setup_done; + + if (!setup_done) + setup(); + + setup_done = 1; + + // TODO do something here + while(1); +} + void __attribute__((interrupt("UNDEF"))) __attribute__((section(".interrupts.text"))) @@ -17,13 +27,40 @@ undefined_instruction_vector(void) } } -void __attribute__((section(".interrupts.data"))) -(*system_reentry_point) (void); +void supervisor_call_handler(void) +{ + uart_puts("something svc happened\n\r"); + + while(1); +} void __attribute__((interrupt("ABORT"))) -__attribute__((section(".interrupts.text"))) abort_handler(void) { - system_reentry_point(); + uart_puts("re-entered system\n\r"); + + while(1); +} + +void generic_handler(void) +{ + uart_puts("something weird happened\n\r"); + + while(1); +} + +void irq_handler(void) +{ + uart_puts("irq happened\n\r"); + + while(1); +} + +void fiq_handler(void) +{ + uart_puts("fiq happened\n\r"); + + while(1); } + diff --git a/kernel.c b/kernel.c deleted file mode 100644 index 719ceff..0000000 --- a/kernel.c +++ /dev/null @@ -1,44 +0,0 @@ -#include "uart.h" -#include "demo_functionality.h" -#include "paging.h" - -void kernel_main(void) -{ - uart_init(); - - // 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_puts("Hello, kernel World!\r\n"); - - // prints some info - demo_paging_support(); - - // prints some info - demo_current_mode(); - - // prints some info and sets upp translation table, turns on MMU - setup_flat_map(); - - demo_setup_PL0(); - - 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 - demo_go_unprivileged(); - - while(1); - - while (1) - { - char c = uart_getc(); - - uart_putc(c); - - if (c == '\r') - uart_putc('\n'); - } -} diff --git a/kernel_stage1.S b/kernel_stage1.S new file mode 100644 index 0000000..1e0f614 --- /dev/null +++ b/kernel_stage1.S @@ -0,0 +1,67 @@ +/* arm mode, cortex-a7 compatibility + * + * _boot is entry point for the kernel. + * + * Kernel copies it's embedded stage 2 to address 0x0 and jumps to + * it (to the reset handler). Registers r0 - r2 are arguments for + * the kernel, but we're not using them for now. + * + * This file is based on (and almost identical with) loader_stage1.S + */ + +.global _boot +_boot: + // Only let the first core execute + mrc p15, 0, r3, c0, c0, 5 + and r3, r3, #3 + cmp r3, #0 + beq proceed + // this is a kind of blef - races can theoretically still + // occur when the main core overwrites this part of memory + wfe + +proceed: + // copy stage2 of the kernel to address 0x0 + + // first, load address of stage2_start to r3 (a PIC way) + adr r3, stage2_start + + // load destination address for stage2 code to r4 + mov r4, #0 + + // load blob size to r5 + // The size might get too big for an immediate value, so + // we load it from memory. + adr r5, blob_size + ldr r5, [r5] + + // r6 is the counter - counts the bytes copied + mov r6, #0 + + // This initial piece of code might get overwritten when we + // copy stage2, so the actual copying loop shall be after + // stage2 blob. We want this asm code to be PIC, so we're + // computing address of stage2_end into r7. + add r7, r3, r5 + bx r7 + +blob_size: + .word stage2_end - stage2_start + +.align 4 +stage2_start: + .incbin "kernel_stage2.img" +stage2_end: + + // each word of the blob is loaded to r7 and stored + // from r7 to it's destination in a loop +loop: + ldr r7, [r3, r6] + str r7, [r4, r6] + add r6, r6, #4 + cmp r6, r5 + blo loop + + // Call stage2 of the kernel (branch to 0x0, + // which is the reset handler). + bx r4 diff --git a/kernel_stage1.ld b/kernel_stage1.ld new file mode 100644 index 0000000..3130634 --- /dev/null +++ b/kernel_stage1.ld @@ -0,0 +1,27 @@ +ENTRY(_boot) /* defined in boot.S; qemu needs it to run elf file */ + +/* Code starts at 0x8000 - that's where RPis in 32-bit mode load + * kernel at. My experiments do, however, show, that qemu emulating + * RPi2 loads the kernel at 0x10000! (took some pain to find out). + * rpi-open-firmware, on the other hand, loads kernel at 0x2000000! + * This is not really a problem, since: + * 1. We can use our bootloader to load the kernel at 0x8000 + * 2. We've rewritten stage 1 of both bootloader and kernel in + * careful assembly, so that they should work regardless of + * where they are loaded. + * 3. In qemu, we can load kernel.elf instead of raw binary + * (qemu will do the right thing then) + */ + +SECTIONS +{ + + . = 0x8000; + + __start = .; + .kernel_stage1 : + { + KEEP(kernel_stage1.o) + } + __end = .; +} diff --git a/kernel_stage2.ld b/kernel_stage2.ld new file mode 100644 index 0000000..d3a23bf --- /dev/null +++ b/kernel_stage2.ld @@ -0,0 +1,52 @@ +/* This sesond stage of the kernel is run from address 0x0 */ + +TRANSLATION_TABLE_SIZE = 4096 * 4; +MMU_SECTION_SIZE = 1 << 20; + +SECTIONS +{ + + . = 0x0; + + __start = .; + .kernel_stage2 : + { + KEEP(interrupt_vector.o) + . = ALIGN(4); + ramfs_embeddable.o + (*) + } + __end = .; + + . = ALIGN(1 << 14); + + .translation_table (NOLOAD) : + { + _translation_table_start = .; + + . = . + TRANSLATION_TABLE_SIZE; + + _translation_table_end = .; + } + + . = ALIGN(1 << 20); + . = . + MMU_SECTION_SIZE; + + .stack (NOLOAD) : + { + _stack_start = .; + + . = . + MMU_SECTION_SIZE; + + _stack_top = .; + } + + .unprivileged_memory (NOLOAD) : + { + _unprivileged_memory_start = .; + + . = . + MMU_SECTION_SIZE; + + _unprivileged_memory_end = .; + } +} diff --git a/linker.ld b/linker.ld deleted file mode 100644 index 444bbf6..0000000 --- a/linker.ld +++ /dev/null @@ -1,47 +0,0 @@ -ENTRY(_boot) /* defined in boot.S; qemu needs it to run elf file */ - -SECTIONS -{ - /* Starts at 0x8000 - that's where RPis in 32-bit mode load */ - /* kernel at. My experiments do, however, show, that qemu */ - /* emulating RPi2 loads the kernel at 0x10000! (took some pain */ - /* to find out). rpi-open-firmware, on the other hand, loads */ - /* kernel at 0x2000000! */ - /* This is not really a problem, since: */ - /* 1. We can use our bootloader to load the kernel at 0x8000 */ - /* 2. Stage 1 of the bootloader is written in careful */ - /* assembly, so that the loader itself should work */ - /* regardless of where it is loaded. */ - /* 3. In qemu, we can load kernel.elf instead of raw binary */ - /* (qemu will do the right thing then) */ - - . = 0x8000; - - /* RPi in 64-bit mode uses address 0x80000 instead */ - - __start = .; - .kernel : - { - __kernel_start = .; - KEEP(boot.o) - . = ALIGN(4); - ramfs_embeddable.o - *(EXCLUDE_FILE (libkernel.o interrupt_vector.o interrupts.o) *) - __kernel_end = .; - } - __kernel_size = __kernel_end - __kernel_start; - - .interrupts : - { - __interrupts_start = .; - KEEP(*(.interrupts.vector)) - interrupt_vector.o - interrupts.o - __interrupts_end = .; - } - __interrupts_size = __interrupts_end - __interrupts_start; - - __end = .; - - _stack_top = __start; -} diff --git a/memory.h b/memory.h index e4493e2..adc3bc0 100644 --- a/memory.h +++ b/memory.h @@ -1,7 +1,10 @@ #ifndef MEMORY_H #define MEMORY_H -#define POWER_OF_2(EXP) (((uint32_t) 1) << EXP) +// These macros were heavily used b4 I moved all the address +// computation to the linker script. Now I'm just keeping them +// in case they're needed for something else :) +#define POWER_OF_2(EXP) (((size_t) 1) << EXP) #define ALIGN_POWER_OF_2(ADDR, EXP) \ (((ADDR - 1) & ~(POWER_OF_2(EXP) - 1)) + POWER_OF_2(EXP)) @@ -10,33 +13,45 @@ #define ALIGN_SECTION(ADDR) ALIGN_POWER_OF_2(ADDR, 20) -#define INTERRUPT_VECTOR_TABLE_START ((uint32_t) 0x0) -#define STACK_START ((uint32_t) 0x4000) -#define STACK_END ((uint32_t) 0x8000) +// memory layout + +#define INTERRUPT_VECTOR_TABLE_START ((uint32_t) 0x0) +// all those symbols are defined in the linker script extern const char __end; extern const char __start; +extern const char _translation_table_start; +extern const char _translation_table_end; +extern const char _stack_start; +extern const char _stack_top; +extern const char _unprivileged_memory_start; +extern const char _unprivileged_memory_end; -#define KERNEL_START ((uint32_t) &__start) // this is 0x8000 -#define KERNEL_END ((uint32_t) &__end) +#define KERNEL_START ((size_t) &__start) // this is 0x0 +#define KERNEL_END ((size_t) &__end) // first 2^14 aligned address after the kernel -#define TRANSLATION_TABLE_BASE ALIGN_POWER_OF_2(KERNEL_END, 14) - -#define TRANSLATION_TABLE_END \ - (TRANSLATION_TABLE_BASE + (uint32_t) (4096 * 4)) +#define TRANSLATION_TABLE_BASE ((size_t) &_translation_table_start) +#define TRANSLATION_TABLE_END ((size_t) &_translation_table_end) -#define PRIVILEGED_MEMORY_END ALIGN_SECTION(TRANSLATION_TABLE_END) +// first section after the translation table is left unused; +// the next section is used as the stack +#define STACK_START ((size_t) &_stack_start) +#define STACK_END ((size_t) &_stack_top) -#define UNPRIVILEGED_MEMORY_START PRIVILEGED_MEMORY_END +#define PRIVILEGED_MEMORY_END STACK_END +#define UNPRIVILEGED_MEMORY_START \ + ((size_t) &_unprivileged_memory_start) // equal to STACK_END #define UNPRIVILEGED_MEMORY_END \ - (UNPRIVILEGED_MEMORY_START + SECTION_SIZE) + ((size_t) &_unprivileged_memory_end) -#define PL0_SECTION_NUMBER ((uint32_t) 0b101010101010) +#define PL0_SECTION_NUMBER ((size_t) 0xaaa) #define VIRTUAL_PL0_MEMORY_START (PL0_SECTION_NUMBER << 20) +#define VIRTUAL_PL0_MEMORY_END \ + (VIRTUAL_PL0_MEMORY_START + SECTION_SIZE) #endif // MEMORY_H diff --git a/setup.c b/setup.c new file mode 100644 index 0000000..48df825 --- /dev/null +++ b/setup.c @@ -0,0 +1,41 @@ +#include "uart.h" +#include "demo_functionality.h" +#include "paging.h" + +void setup(void) +{ + uart_init(); + + // 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_puts("Hello, kernel World!\r\n"); + + // prints some info + demo_paging_support(); + + // prints some info + demo_current_mode(); + + // prints some info and sets upp translation table, turns on MMU + setup_flat_map(); + + // prints some info and sets up a section for PL0 code, + // loads a blob there + demo_setup_PL0(); + + // jumps to unprivileged code... never, ever, ever returns + demo_go_unprivileged(); + + while (1) + { + char c = uart_getc(); + + uart_putc(c); + + if (c == '\r') + uart_putc('\n'); + } +} -- cgit v1.2.3