aboutsummaryrefslogtreecommitdiff
path: root/paging.c
diff options
context:
space:
mode:
authorWojtek Kosior <kwojtus@protonmail.com>2019-11-19 17:49:20 +0100
committerWojtek Kosior <kwojtus@protonmail.com>2019-11-19 17:49:20 +0100
commit39145f6d1b8c57abe2bc0167b2b413970d0dfdb6 (patch)
tree2e2a76590e749579676720505aa38c57f85a95a4 /paging.c
parent11541f1d1eaaefebd6d01b42e92a65606e4bc382 (diff)
downloadrpi-MMU-example-39145f6d1b8c57abe2bc0167b2b413970d0dfdb6.tar.gz
rpi-MMU-example-39145f6d1b8c57abe2bc0167b2b413970d0dfdb6.zip
split kernel into more files
Diffstat (limited to 'paging.c')
-rw-r--r--paging.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/paging.c b/paging.c
new file mode 100644
index 0000000..7c2a9de
--- /dev/null
+++ b/paging.c
@@ -0,0 +1,114 @@
+#include "cp_regs.h"
+#include "uart.h"
+#include "strings.h"
+#include "memory.h"
+#include "translation_table_descriptors.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");
+
+ // flat map all memory
+ uart_puts("preparing translation table\n\r");
+ short_descriptor_lvl1_t volatile *translation_table =
+ (short_descriptor_lvl1_t*) TRANSLATION_TABLE_BASE;
+
+ for (uint32_t i = 0; i < 4096; i++)
+ translation_table[i].section_fields =
+ (short_section_descriptor_t) {
+ .SECTION_BASE_ADDRESS_31_20 = i,
+ .SECTION_OR_SUPERSECTION_BIT = DESCRIBES_SECTION,
+ .ACCESS_PERMISSIONS_2 = AP_2_0_MODEL_RW_PL1 >> 2,
+ .ACCESS_PERMISSIONS_1_0 = AP_2_0_MODEL_RW_PL1 & 0b011,
+ .DESCRIPTOR_TYPE_1 =
+ SHORT_DESCRIPTOR_SECTION_OR_SUPERSECTION >> 1,
+ // rest of fields are 0s
+ };
+
+ // meddle with domain settings
+ uart_puts("setting domain0 to client access"
+ " and blocking other domains\n\r");
+
+ DACR_t DACR = 0;
+ DACR = set_domain_permissions(DACR, 0, DOMAIN_CLIENT_ACCESS);
+ for (int i = 1; i < 16; i++)
+ DACR = set_domain_permissions(DACR, i, DOMAIN_NO_ACCESS);
+
+ // the above should do the same as this:
+ // DACR = 1;
+
+ asm("mcr p15, 0, %0, c3, c0, 0" :: "r" (DACR));
+
+ // meddle with SCTLR, which determines how some bits in
+ // table descriptors work and also controls caches
+ // we don't want to use access flag, so we set AFE to 0
+ // we don't want TEX remap, so we set TRE to 0
+ // 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");
+
+ SCTLR_t SCTLR;
+ asm("mrc p15, 0, %0, c1, c0, 0" : "=r" (SCTLR.raw));
+
+ SCTLR.fields.M = 0; // disable MMU
+ SCTLR.fields.C = 0; // disable data cache
+ SCTLR.fields.I = 0; // disable instruction cache
+ SCTLR.fields.TRE = 0; // disable TEX remap
+ SCTLR.fields.AFE = 0; // disable access flag usage
+ asm("mcr p15, 0, %0, c1, c0, 0\n\r"
+ "isb" :: "r" (SCTLR.raw) : "memory");
+
+ // TODO: move invalidation instructions to some header as inlines
+
+ uart_puts("invalidating instruction cache, branch prediction,"
+ " and entire main TLB\n\r");
+
+ // invalidate instruction cache
+ asm("mcr p15, 0, r0, c7, c5, 0\n\r" // r0 gets ignored
+ "isb" ::: "memory");
+
+ // invalidate branch-prediction
+ asm("mcr p15, 0, r0, c7, c5, 6\n\r" // r0 - same as above
+ "isb" ::: "memory");
+
+ // invalidate main Translation Lookup Buffer
+ asm("mcr p15, 0, %0, c8, c7, 0\n\r"
+ "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");
+
+ uint32_t TTBCR = 0;
+ asm("mcr p15, 0, %0, c2, c0, 2" :: "r" (TTBCR));
+
+ // Now do stuff with TTBR0
+ TTBR_t TTBR0;
+ TTBR0.raw = 0;
+ TTBR0.fields.TTBR_TRANSLATION_TABLE_BASE_ADDRESS =
+ TRANSLATION_TABLE_BASE >> 14;
+ // rest of TTBR0 remains 0s
+
+ asm("mcr p15, 0, %0, c2, c0, 0" :: "r" (TTBR0.raw));
+
+ // enable MMU
+ uart_puts("enabling the MMU\n\r");
+
+ // redundant - we already have SCTLR contents in the variable
+ // asm("mrc p15, 0, %0, c1, c0, 0" : "=r" (SCTLR.raw));
+
+ SCTLR.fields.M = 1;
+
+ asm("mcr p15, 0, %0, c1, c0, 0\n\r"
+ "isb" :: "r" (SCTLR.raw) : "memory");
+}