From c9e045dc2170a99c9f32386e3e53aee9e01a8e7c Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Mon, 30 Dec 2019 17:34:23 +0100 Subject: io api rework --- paging.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) (limited to 'paging.c') diff --git a/paging.c b/paging.c index 7c2a9de..2985e7e 100644 --- a/paging.c +++ b/paging.c @@ -1,24 +1,21 @@ #include "cp_regs.h" -#include "uart.h" #include "strings.h" #include "memory.h" #include "translation_table_descriptors.h" +#include "io.h" void setup_flat_map(void) { - char bits[33]; // for printing uint32_t bit values - // compute translation table base address // translation table shall start at first 2^14-bytes aligned // address after the kernel image - uint32_to_bits(TRANSLATION_TABLE_BASE, bits); - uart_puts("binary representation of chosen" - " lvl1 translation table address: "); - uart_puts(bits); uart_puts("\n\r"); + prints("chosen lvl1 translation table address: 0x"); + printhex(TRANSLATION_TABLE_BASE); + puts(""); // flat map all memory - uart_puts("preparing translation table\n\r"); + puts("preparing translation table"); short_descriptor_lvl1_t volatile *translation_table = (short_descriptor_lvl1_t*) TRANSLATION_TABLE_BASE; @@ -35,8 +32,7 @@ void setup_flat_map(void) }; // meddle with domain settings - uart_puts("setting domain0 to client access" - " and blocking other domains\n\r"); + puts("setting domain0 to client access and blocking other domains"); DACR_t DACR = 0; DACR = set_domain_permissions(DACR, 0, DOMAIN_CLIENT_ACCESS); @@ -55,7 +51,7 @@ void setup_flat_map(void) // we also disable data and instruction caches and the MMU // some of this is redundant (i.e. MMU should already be disabled) - uart_puts("setting C, I, AFE and TRE to 0 in SCTLR\n\r"); + puts("setting C, I, AFE and TRE to 0 in SCTLR"); SCTLR_t SCTLR; asm("mrc p15, 0, %0, c1, c0, 0" : "=r" (SCTLR.raw)); @@ -70,8 +66,8 @@ void setup_flat_map(void) // TODO: move invalidation instructions to some header as inlines - uart_puts("invalidating instruction cache, branch prediction," - " and entire main TLB\n\r"); + puts("invalidating instruction cache, branch prediction," + " and entire main TLB"); // invalidate instruction cache asm("mcr p15, 0, r0, c7, c5, 0\n\r" // r0 gets ignored @@ -86,8 +82,7 @@ void setup_flat_map(void) "isb" :: "r" (0) : "memory"); // now set TTBCR to use TTBR0 exclusively - uart_puts("Setting TTBCR.N to 0, so that" - " TTBR0 is used everywhere\n\r"); + puts("Setting TTBCR.N to 0, so that TTBR0 is used everywhere"); uint32_t TTBCR = 0; asm("mcr p15, 0, %0, c2, c0, 2" :: "r" (TTBCR)); @@ -102,7 +97,7 @@ void setup_flat_map(void) asm("mcr p15, 0, %0, c2, c0, 0" :: "r" (TTBR0.raw)); // enable MMU - uart_puts("enabling the MMU\n\r"); + puts("enabling the MMU"); // redundant - we already have SCTLR contents in the variable // asm("mrc p15, 0, %0, c1, c0, 0" : "=r" (SCTLR.raw)); -- 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 'paging.c') 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 ff405d15e20b360afe93af5c23d6972f28fc38b9 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Tue, 31 Dec 2019 17:21:01 +0100 Subject: print info about completed initialization of kernel's paging structures --- paging.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'paging.c') diff --git a/paging.c b/paging.c index 0de63b8..6560047 100644 --- a/paging.c +++ b/paging.c @@ -164,6 +164,10 @@ void setup_pager_structures(uint32_t available_mem) }; first_free_section = kernel_sections_count; + + puts("Initialized kernel's internal structures for paging"); + prints("We have "); printdect(free_sections_count); + puts(" free sections left for use"); } // return section number or CLAIM_FAILURE in case of failure -- cgit v1.2.3 From d2d7ebbea19d55fb2a292ca766d95b197691b941 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Tue, 31 Dec 2019 17:28:26 +0100 Subject: introduce SECTION_NULL --- demo_functionality.c | 2 +- paging.c | 30 +++++++++++++++++------------- paging.h | 4 ++-- 3 files changed, 20 insertions(+), 16 deletions(-) (limited to 'paging.c') diff --git a/demo_functionality.c b/demo_functionality.c index 366edd7..3cf5b8f 100644 --- a/demo_functionality.c +++ b/demo_functionality.c @@ -79,7 +79,7 @@ void demo_setup_PL0(void) uint16_t physical_section_number = claim_and_map_section ((void*) 5, PL0_SECTION_NUMBER, AP_2_0_MODEL_RW_ALL); - if (physical_section_number == CLAIM_FAILURE) + if (physical_section_number == SECTION_NULL) { puts("Couldn't claim memory section for unprivileged code :("); while(1); diff --git a/paging.c b/paging.c index 6560047..771c681 100644 --- a/paging.c +++ b/paging.c @@ -122,7 +122,7 @@ struct section_node 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; + // end of list is marked by reference to SECTION_NULL; // we use offsets into sections_list array instead of pointers; uint16_t prev, next; }; @@ -133,7 +133,7 @@ static uint16_t all_sections_count, kernel_sections_count, split_sections_count, free_sections_count; -// those are undefined when the corresponding count is 0; +// those are SECTION_NULL when the corresponding count is 0; static uint16_t first_free_section, first_kernel_section, first_split_section; @@ -146,11 +146,13 @@ void setup_pager_structures(uint32_t available_mem) sections_list = (struct section_node*) SECTIONS_LIST_START; + first_split_section = SECTION_NULL; + 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 + .prev = i == 0 ? SECTION_NULL : i - 1, + .next = i == kernel_sections_count - 1 ? SECTION_NULL : i + 1 }; first_kernel_section = 0; @@ -159,8 +161,8 @@ void setup_pager_structures(uint32_t available_mem) 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 + .prev = i == kernel_sections_count ? SECTION_NULL : i - 1, + .next = i == all_sections_count - 1 ? SECTION_NULL : i + 1 }; first_free_section = kernel_sections_count; @@ -170,11 +172,11 @@ void setup_pager_structures(uint32_t available_mem) puts(" free sections left for use"); } -// return section number or CLAIM_FAILURE in case of failure +// return section number or SECTION_NULL in case of failure static uint16_t claim_section(void *owner) { if (!free_sections_count) - return CLAIM_FAILURE; // failure + return SECTION_NULL; // failure uint16_t section = first_free_section; @@ -183,10 +185,12 @@ static uint16_t claim_section(void *owner) uint16_t next; next = sections_list[section].next; - sections_list[next].prev = next; + sections_list[next].prev = SECTION_NULL; first_free_section = next; } + else + first_free_section = SECTION_NULL; if (owner == OWNER_KERNEL) { @@ -194,7 +198,7 @@ static uint16_t claim_section(void *owner) sections_list[section] = (struct section_node) { .owner = owner, - .prev = section, + .prev = SECTION_NULL, .next = first_kernel_section }; @@ -205,8 +209,8 @@ static uint16_t claim_section(void *owner) else sections_list[section] = (struct section_node) { .owner = owner, - .prev = section, - .next = section + .prev = SECTION_NULL, + .next = SECTION_NULL }; return section; @@ -218,7 +222,7 @@ uint16_t claim_and_map_section { uint16_t section = claim_section(owner); - if (section == CLAIM_FAILURE) + if (section == SECTION_NULL) return section; short_section_descriptor_t volatile *section_entry = diff --git a/paging.h b/paging.h index 1715a6e..4ac8efa 100644 --- a/paging.h +++ b/paging.h @@ -5,9 +5,9 @@ void setup_flat_map(void); void setup_pager_structures(uint32_t available_mem); -#define CLAIM_FAILURE 0xffff +#define SECTION_NULL 0xffff -// returns section number or CLAIM_FAILURE in case of failure +// returns section number or SECTION_NULL in case of failure uint16_t claim_and_map_section (void *owner, uint16_t where_to_map, uint8_t access_permissions); -- cgit v1.2.3