aboutsummaryrefslogtreecommitdiff
path: root/kernel.c
diff options
context:
space:
mode:
authorvetch <vetch97@gmail.com>2019-11-12 15:59:13 +0100
committervetch <vetch97@gmail.com>2019-11-12 15:59:13 +0100
commitfd7c31aacae16695cb612772c1c279273122e541 (patch)
treee2144f6eea7d351ccde17d081c761f7a0c48109d /kernel.c
parent2beaa82a116a7e855327d3702999c371920fb410 (diff)
parentc9a43be4dbabad0d6f51712e60f2ff0834eed36a (diff)
downloadrpi-MMU-example-fd7c31aacae16695cb612772c1c279273122e541.tar.gz
rpi-MMU-example-fd7c31aacae16695cb612772c1c279273122e541.zip
merge bob
Diffstat (limited to 'kernel.c')
-rw-r--r--kernel.c153
1 files changed, 140 insertions, 13 deletions
diff --git a/kernel.c b/kernel.c
index dbc45e4..8a06565 100644
--- a/kernel.c
+++ b/kernel.c
@@ -1,6 +1,13 @@
#include "uart.h"
#include "cpsr.h"
+#include "strings.h"
+#include "translation_table_descriptors.h"
+#include "cp_regs.h"
+extern char __end;
+
+void enabling_code_from_the_net(void);
+
void kernel_main(uint32_t r0, uint32_t r1, uint32_t atags)
{
// Declare as unused
@@ -39,26 +46,146 @@ void kernel_main(uint32_t r0, uint32_t r1, uint32_t atags)
// processor mode
asm("mrs %0, cpsr" : "=r" (CPSR) :: "memory");
- char *mode;
+ char *mode_name;
switch(read_processor_mode())
{
- case 0x10 : mode = "User (PL0)\r\n"; break;
- case 0x11 : mode = "FIQ (PL1)\r\n"; break;
- case 0x12 : mode = "IRQ (PL1)\r\n"; break;
- case 0x13 : mode = "Supervisor (PL1)\r\n"; break;
- case 0x16 : mode = "Monitor (PL1)\r\n"; break;
- case 0x17 : mode = "Abort (PL1)\r\n"; break;
- case 0x1a : mode = "Hyp (PL2)\r\n"; break;
- case 0x1b : mode = "Undefined (PL1)\r\n"; break;
- case 0x1f : mode = "System (PL1)\r\n"; break;
- default : mode = "Unknown mode\r\n"; break;
+ case MODE_USER : mode_name = "User (PL0)\r\n"; break;
+ case MODE_FIQ : mode_name = "FIQ (PL1)\r\n"; break;
+ case MODE_IRQ : mode_name = "IRQ (PL1)\r\n"; break;
+ case MODE_SUPERVISOR : mode_name = "Supervisor (PL1)\r\n"; break;
+ case MODE_MONITOR : mode_name = "Monitor (PL1)\r\n"; break;
+ case MODE_ABORT : mode_name = "Abort (PL1)\r\n"; break;
+ case MODE_HYPERVISOR : mode_name = "Hyp (PL2)\r\n"; break;
+ case MODE_UNDEFINED : mode_name = "Undefined (PL1)\r\n"; break;
+ case MODE_SYSTEM : mode_name = "System (PL1)\r\n"; break;
+ default : mode_name = "Unknown mode\r\n"; break;
}
+ uart_puts("current mode: ");
+ uart_puts(mode_name);
+
+ uart_puts("setting mode to system (PL1)...\r\n");
set_system_mode();
- uart_puts(mode);
+ 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_t kernel_end = (uint32_t) &__end;
+ uint32_t translation_table_base =
+ ((kernel_end - 1) & ~((uint32_t) 0x3fff)) + (uint32_t) 0x4000;
+
+ 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_t *translation_table =
+ (short_descriptor_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_2 =
+ 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.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");
while (1)
- uart_putc(uart_getc());
+ {
+ char c;
+ switch(c = uart_getc())
+ {
+ case '\r':
+ uart_putc('\n');
+ default:
+ uart_putc(c);
+ }
+ }
}