diff options
author | Wojtek Kosior <kwojtus@protonmail.com> | 2019-12-31 13:50:14 +0100 |
---|---|---|
committer | Wojtek Kosior <kwojtus@protonmail.com> | 2019-12-31 13:50:14 +0100 |
commit | 7dcea5fdafe66d8bcf1eeacbaf3f3f3b1c258dfc (patch) | |
tree | b56d111955ab45215caf11bd3b2ba6560d14c171 | |
parent | 3387b288a53422131f22f1fc96168a128edc9902 (diff) | |
download | rpi-MMU-example-7dcea5fdafe66d8bcf1eeacbaf3f3f3b1c258dfc.tar.gz rpi-MMU-example-7dcea5fdafe66d8bcf1eeacbaf3f3f3b1c258dfc.zip |
implement basic memory section allocation for processes
-rw-r--r-- | kernel_stage2.ld | 12 | ||||
-rw-r--r-- | memory.h | 6 | ||||
-rw-r--r-- | paging.c | 132 | ||||
-rw-r--r-- | paging.h | 8 |
4 files changed, 157 insertions, 1 deletions
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 = .; @@ -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) @@ -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; +} @@ -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 |