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 --- kernel_stage2.ld | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 kernel_stage2.ld (limited to 'kernel_stage2.ld') 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 = .; + } +} -- cgit v1.2.3 From ee8668f9fcd952e4952706789bdde7fd223dacb5 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Mon, 30 Dec 2019 13:29:04 +0100 Subject: fix the linking of embedded ramfs --- kernel_stage2.ld | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'kernel_stage2.ld') diff --git a/kernel_stage2.ld b/kernel_stage2.ld index d3a23bf..dce2d1f 100644 --- a/kernel_stage2.ld +++ b/kernel_stage2.ld @@ -9,12 +9,22 @@ SECTIONS . = 0x0; __start = .; - .kernel_stage2 : + .interrupt_vector : { KEEP(interrupt_vector.o) - . = ALIGN(4); + } + . = ALIGN(4); + .embedded_ramfs : + { ramfs_embeddable.o - (*) + } + .rest_of_kernel : + { + *(.text) + *(.data) + *(.rodata) + *(.bss) + *(/COMMON/) } __end = .; -- cgit v1.2.3 From 7dcea5fdafe66d8bcf1eeacbaf3f3f3b1c258dfc Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Tue, 31 Dec 2019 13:50:14 +0100 Subject: implement basic memory section allocation for processes --- kernel_stage2.ld | 12 ++++- memory.h | 6 +++ paging.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ paging.h | 8 ++++ 4 files changed, 157 insertions(+), 1 deletion(-) (limited to 'kernel_stage2.ld') diff --git a/kernel_stage2.ld b/kernel_stage2.ld index dce2d1f..a30105e 100644 --- a/kernel_stage2.ld +++ b/kernel_stage2.ld @@ -1,6 +1,7 @@ /* This sesond stage of the kernel is run from address 0x0 */ TRANSLATION_TABLE_SIZE = 4096 * 4; +SECTIONS_LIST_SIZE = 4096 * 8; MMU_SECTION_SIZE = 1 << 20; SECTIONS @@ -39,9 +40,18 @@ SECTIONS _translation_table_end = .; } + .sections_list (NOLOAD) : + { + _sections_list_start = .; + + . = . + SECTIONS_LIST_SIZE; + + _sections_list_end = .; + } + . = ALIGN(1 << 20); . = . + MMU_SECTION_SIZE; - + .stack (NOLOAD) : { _stack_start = .; diff --git a/memory.h b/memory.h index 7de556d..2ab5485 100644 --- a/memory.h +++ b/memory.h @@ -25,6 +25,8 @@ extern char __end; extern char __start; extern char _translation_table_start; extern char _translation_table_end; +extern char _sections_list_start; +extern char _sections_list_end; extern char _stack_start; extern char _stack_top; extern char _unprivileged_memory_start; @@ -37,6 +39,10 @@ extern char _unprivileged_memory_end; #define TRANSLATION_TABLE_BASE ((size_t) &_translation_table_start) #define TRANSLATION_TABLE_END ((size_t) &_translation_table_end) +// another 32KB after the translation table are used for sections list +#define SECTIONS_LIST_START ((size_t) &_sections_list_start) +#define SECTIONS_LIST_END ((size_t) &_sections_list_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) diff --git a/paging.c b/paging.c index 2985e7e..0de63b8 100644 --- a/paging.c +++ b/paging.c @@ -4,6 +4,8 @@ #include "translation_table_descriptors.h" #include "io.h" +#include "paging.h" + void setup_flat_map(void) { // compute translation table base address @@ -107,3 +109,133 @@ void setup_flat_map(void) asm("mcr p15, 0, %0, c1, c0, 0\n\r" "isb" :: "r" (SCTLR.raw) : "memory"); } + +#define OWNER_FREE ((void*) 0) +#define OWNER_KERNEL ((void*) 1) +#define OWNER_SPLIT ((void*) 2) + +// we want to maintain a list of free and used physical sections +struct section_node +{ + // we're going to add processes, process management and + // struct process. Then, owner will be struct process*. + void *owner; // 0 if free, 1 if used by kernel, 2 if split to pages + + // it's actually a 2-directional lists; + // end of list is marked by reference to itself; + // we use offsets into sections_list array instead of pointers; + uint16_t prev, next; +}; + +static struct section_node volatile *sections_list; + +static uint16_t + all_sections_count, kernel_sections_count, + split_sections_count, free_sections_count; + +// those are undefined when the corresponding count is 0; +static uint16_t + first_free_section, first_kernel_section, first_split_section; + +void setup_pager_structures(uint32_t available_mem) +{ + all_sections_count = available_mem / SECTION_SIZE; + kernel_sections_count = PRIVILEGED_MEMORY_END / SECTION_SIZE; + free_sections_count = all_sections_count - kernel_sections_count; + split_sections_count = 0; + + sections_list = (struct section_node*) SECTIONS_LIST_START; + + for (uint16_t i = 0; i < kernel_sections_count; i++) + sections_list[i] = (struct section_node) { + .owner = OWNER_KERNEL, + .prev = i == 0 ? i : i - 1, + .next = i == kernel_sections_count - 1 ? i : i + 1 + }; + + first_kernel_section = 0; + + for (uint16_t i = kernel_sections_count; + i < all_sections_count; i++) + sections_list[i] = (struct section_node) { + .owner = OWNER_FREE, + .prev = i == kernel_sections_count ? i : i - 1, + .next = i == all_sections_count - 1 ? i : i + 1 + }; + + first_free_section = kernel_sections_count; +} + +// return section number or CLAIM_FAILURE in case of failure +static uint16_t claim_section(void *owner) +{ + if (!free_sections_count) + return CLAIM_FAILURE; // failure + + uint16_t section = first_free_section; + + if (--free_sections_count) + { + uint16_t next; + + next = sections_list[section].next; + sections_list[next].prev = next; + + first_free_section = next; + } + + if (owner == OWNER_KERNEL) + { + sections_list[first_kernel_section].prev = section; + + sections_list[section] = (struct section_node) { + .owner = owner, + .prev = section, + .next = first_kernel_section + }; + + kernel_sections_count++; + + first_kernel_section = section; + } + else + sections_list[section] = (struct section_node) { + .owner = owner, + .prev = section, + .next = section + }; + + return section; +} + +// return values like claim_section() +uint16_t claim_and_map_section +(void *owner, uint16_t where_to_map, uint8_t access_permissions) +{ + uint16_t section = claim_section(owner); + + if (section == CLAIM_FAILURE) + return section; + + short_section_descriptor_t volatile *section_entry = + &((short_section_descriptor_t*) + TRANSLATION_TABLE_BASE)[where_to_map]; + + short_section_descriptor_t descriptor = *section_entry; + + // set up address of section + descriptor.SECTION_BASE_ADDRESS_31_20 = section; + + // set requested permissions on section + descriptor.ACCESS_PERMISSIONS_2 = access_permissions >> 2; + descriptor.ACCESS_PERMISSIONS_1_0 = access_permissions & 0b011; + + // write modified descriptor to the table + *section_entry = descriptor; + + // invalidate main Translation Lookup Buffer + asm("mcr p15, 0, r1, c8, c7, 0\n\r" + "isb" ::: "memory"); + + return section; +} diff --git a/paging.h b/paging.h index 1218fb8..1715a6e 100644 --- a/paging.h +++ b/paging.h @@ -3,4 +3,12 @@ void setup_flat_map(void); +void setup_pager_structures(uint32_t available_mem); + +#define CLAIM_FAILURE 0xffff + +// returns section number or CLAIM_FAILURE in case of failure +uint16_t claim_and_map_section +(void *owner, uint16_t where_to_map, uint8_t access_permissions); + #endif // PAGING_H -- cgit v1.2.3 From 030cc96003d4518463b40f20d4194e51b1745c86 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Tue, 31 Dec 2019 17:36:50 +0100 Subject: don't statically define the unprivileged section (we're going to have many dynamically-claimed unprivileged sections) --- kernel_stage2.ld | 9 --------- memory.h | 7 +------ setup.c | 3 ++- 3 files changed, 3 insertions(+), 16 deletions(-) (limited to 'kernel_stage2.ld') diff --git a/kernel_stage2.ld b/kernel_stage2.ld index a30105e..a3df063 100644 --- a/kernel_stage2.ld +++ b/kernel_stage2.ld @@ -60,13 +60,4 @@ SECTIONS _stack_top = .; } - - .unprivileged_memory (NOLOAD) : - { - _unprivileged_memory_start = .; - - . = . + MMU_SECTION_SIZE; - - _unprivileged_memory_end = .; - } } diff --git a/memory.h b/memory.h index 2ab5485..c7952f0 100644 --- a/memory.h +++ b/memory.h @@ -29,8 +29,6 @@ extern char _sections_list_start; extern char _sections_list_end; extern char _stack_start; extern char _stack_top; -extern char _unprivileged_memory_start; -extern char _unprivileged_memory_end; #define KERNEL_START ((size_t) &__start) // this is 0x0 #define KERNEL_END ((size_t) &__end) @@ -50,11 +48,8 @@ extern char _unprivileged_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 \ - ((size_t) &_unprivileged_memory_end) +// the following describes the virtual section for our PL0 programs #define PL0_SECTION_NUMBER ((size_t) 0xaaa) #define VIRTUAL_PL0_MEMORY_START (PL0_SECTION_NUMBER << 20) diff --git a/setup.c b/setup.c index b7acf60..63ca054 100644 --- a/setup.c +++ b/setup.c @@ -75,7 +75,8 @@ void setup(uint32_t r0, uint32_t machine_type, memory_size = 192 * POWER_OF_2(20); } - if (memory_size < UNPRIVILEGED_MEMORY_END) + // assume we need at least one section for PL0 + if (memory_size < PRIVILEGED_MEMORY_END + SECTION_SIZE) { puts("Not enough memory to continue"); while (1); -- cgit v1.2.3 From 0ec2016f80ffb5971362559b98b10744bb5bf893 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Tue, 31 Dec 2019 18:54:28 +0100 Subject: split stack into irq, fiq and supervisor stacks; add proper handling of those in interrupt handlers (asm code) --- interrupt_vector.S | 25 ++++++++++++++----------- kernel_stage2.ld | 22 +++++++++++++++++++--- memory.h | 18 +++++++++++++++--- 3 files changed, 48 insertions(+), 17 deletions(-) (limited to 'kernel_stage2.ld') diff --git a/interrupt_vector.S b/interrupt_vector.S index 88b32bf..af80eec 100644 --- a/interrupt_vector.S +++ b/interrupt_vector.S @@ -9,39 +9,42 @@ _interrupt_vectors: b fiq_handler_caller reset_handler_caller: - ldr sp, =_stack_top + ldr sp, =_supervisor_stack_top ldr r5, =reset_handler bx r5 undef_handler_caller: - ldr sp, =_stack_top + ldr sp, =_supervisor_stack_top ldr r5, =undefined_instruction_vector bx r5 svc_handler_caller: - ldr sp, =_stack_top + ldr sp, =_supervisor_stack_top + push {r5, lr} ldr r5, =supervisor_call_handler - push {lr} blx r5 - ldm sp!, {pc} ^ + ldm sp!, {r5, pc} ^ abort_handler_caller: - ldr sp, =_stack_top + ldr sp, =_supervisor_stack_top ldr r5, =abort_handler bx r5 generic_handler_caller: - ldr sp, =_stack_top + ldr sp, =_supervisor_stack_top ldr r5, =generic_handler bx r5 irq_handler_caller: - ldr sp, =_stack_top - ldr r5, =irq_handler - bx r5 + ldr sp, =_irq_stack_top + sub lr, #4 + push {r0-r3, lr} + ldr r3, =irq_handler + blx r3 + ldm sp!, {r0-r3, pc} ^ fiq_handler_caller: - ldr sp, =_stack_top + ldr sp, =_fiq_stack_top ldr r5, =fiq_handler bx r5 diff --git a/kernel_stage2.ld b/kernel_stage2.ld index a3df063..15b61ec 100644 --- a/kernel_stage2.ld +++ b/kernel_stage2.ld @@ -56,8 +56,24 @@ SECTIONS { _stack_start = .; - . = . + MMU_SECTION_SIZE; - - _stack_top = .; + _fiq_stack_start = .; + + . = . + (1 << 18); + + _fiq_stack_top = .; + + _irq_stack_start = .; + + . = . + (1 << 18); + + _irq_stack_top = .; + + _supervisor_stack_start = .; + + . = . + (1 << 19); + + _supervisor_stack_top = .; + + _stack_end = .; } } diff --git a/memory.h b/memory.h index c7952f0..bdeba52 100644 --- a/memory.h +++ b/memory.h @@ -28,7 +28,13 @@ extern char _translation_table_end; extern char _sections_list_start; extern char _sections_list_end; extern char _stack_start; -extern char _stack_top; +extern char _fiq_stack_start; +extern char _fiq_stack_top; +extern char _irq_stack_start; +extern char _irq_stack_top; +extern char _supervisor_stack_start; +extern char _supervisor_stack_top; +extern char _stack_end; #define KERNEL_START ((size_t) &__start) // this is 0x0 #define KERNEL_END ((size_t) &__end) @@ -43,8 +49,14 @@ extern char _stack_top; // 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 STACK_START ((size_t) &_stack_start) +#define FIQ_STACK_START ((size_t) &_fiq_stack_start) +#define FIQ_STACK_END ((size_t) &_fiq_stack_top) +#define IRQ_STACK_START ((size_t) &_irq_stack_start) +#define IRQ_STACK_END ((size_t) &_irq_stack_top) +#define SUPERVISOR_STACK_START ((size_t) &_supervisor_stack_start) +#define SUPERVISOR_STACK_END ((size_t) &_supervisor_stack_top) +#define STACK_END ((size_t) &_stack_end) #define PRIVILEGED_MEMORY_END STACK_END -- cgit v1.2.3