From 39145f6d1b8c57abe2bc0167b2b413970d0dfdb6 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Tue, 19 Nov 2019 17:49:20 +0100 Subject: split kernel into more files --- paging.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 paging.c (limited to 'paging.c') 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"); +} -- cgit v1.2.3