aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWojtek Kosior <kwojtus@protonmail.com>2019-12-31 13:50:14 +0100
committerWojtek Kosior <kwojtus@protonmail.com>2019-12-31 13:50:14 +0100
commit7dcea5fdafe66d8bcf1eeacbaf3f3f3b1c258dfc (patch)
treeb56d111955ab45215caf11bd3b2ba6560d14c171
parent3387b288a53422131f22f1fc96168a128edc9902 (diff)
downloadrpi-MMU-example-7dcea5fdafe66d8bcf1eeacbaf3f3f3b1c258dfc.tar.gz
rpi-MMU-example-7dcea5fdafe66d8bcf1eeacbaf3f3f3b1c258dfc.zip
implement basic memory section allocation for processes
-rw-r--r--kernel_stage2.ld12
-rw-r--r--memory.h6
-rw-r--r--paging.c132
-rw-r--r--paging.h8
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 = .;
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