aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWojtek Kosior <kwojtus@protonmail.com>2019-12-28 15:55:29 +0100
committerWojtek Kosior <kwojtus@protonmail.com>2019-12-28 15:55:29 +0100
commitc374eaacbc0d16983bbd1112fefa74dbe88e1e53 (patch)
treec6930675e0200a4aed724fd65947853f2b4f274f
parent7062b101197c03c7f4806d83b8d79cf34d3b6a42 (diff)
downloadrpi-MMU-example-c374eaacbc0d16983bbd1112fefa74dbe88e1e53.tar.gz
rpi-MMU-example-c374eaacbc0d16983bbd1112fefa74dbe88e1e53.zip
use ldm instruction instead of libkernel for entering user mode; get rid of libkernel (no longer needed)
-rw-r--r--Makefile2
-rw-r--r--demo_functionality.c69
-rw-r--r--kernel.c2
-rw-r--r--libkernel.c12
-rw-r--r--libkernel.h6
-rw-r--r--linker.ld11
-rw-r--r--memory.h13
-rw-r--r--psr.h15
8 files changed, 40 insertions, 90 deletions
diff --git a/Makefile b/Makefile
index b8800cc..55d0d1b 100644
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@ all : kernel7.img
PL_0_test.elf : PL0_test.o uart.o
arm-none-eabi-gcc -T PL0_test.ld -o $@ $(ELFFLAGS) $^
-kernel.elf : boot.o kernel.o uart.o demo_functionality.o paging.o libkernel.o interrupt_vector.o interrupts.o ramfs_embeddable.o ramfs.o
+kernel.elf : boot.o kernel.o uart.o demo_functionality.o paging.o interrupt_vector.o interrupts.o ramfs_embeddable.o ramfs.o
arm-none-eabi-gcc -T linker.ld -o $@ $(ELFFLAGS) $^
loader.elf : boot.o loader_stage1.o loader_stage2.o uart.o
diff --git a/demo_functionality.c b/demo_functionality.c
index 206dd2b..4b002d6 100644
--- a/demo_functionality.c
+++ b/demo_functionality.c
@@ -2,7 +2,6 @@
#include "psr.h"
#include "memory.h"
#include "translation_table_descriptors.h"
-#include "libkernel.h"
#include "ramfs.h"
void demo_paging_support(void)
@@ -58,37 +57,6 @@ void demo_current_mode(void)
((short_section_descriptor_t volatile*) TRANSLATION_TABLE_BASE)
extern char
- __libkernel_start,
- __libkernel_end,
- __libkernel_size;
-
-void demo_setup_libkernel(void) {
- short_section_descriptor_t volatile *libkernel_section_entry =
- &TRANSLATION_TABLE[LIBKERNEL_SECTION_NUMBER];
-
- short_section_descriptor_t
- libkernel_section = *libkernel_section_entry;
-
- // make libkernel section executable and read-only for
- // unprivileged code
- libkernel_section.ACCESS_PERMISSIONS_2 =
- AP_2_0_MODEL_RW_PL1_RO_PL0 >> 2;
- libkernel_section.ACCESS_PERMISSIONS_1_0 =
- AP_2_0_MODEL_RW_PL1_RO_PL0 & 0b011;
-
- *libkernel_section_entry = libkernel_section;
-
- // invalidate main Translation Lookup Buffer (just in case)
- asm("mcr p15, 0, %0, c8, c7, 0\n\r"
- "isb" :: "r" (0) : "memory");
-
- // copy libkernel code to libkernel section
- for (size_t i = 0; i < (size_t) &__libkernel_size; i++)
- ((volatile char*) LIBKERNEL_SECTION_START)[i] =
- (&__libkernel_start)[i];
-}
-
-extern char
_binary_ramfs_img_start,
_binary_ramfs_img_end,
_binary_ramfs_img_size;
@@ -151,27 +119,34 @@ void demo_setup_PL0(void)
((volatile char*) VIRTUAL_PL0_MEMORY_START)[i] =
PL_0_test_img.file_contents[i];
- uart_puts("copied PL0 and libkernel code to their sections\n\r");
+ uart_puts("copied PL0 code to it's section\n\r");
+}
+
+// needed for array initialization in demo_go_unprivileged()
+void *memset(void *s, int c, size_t n)
+{
+ char *mem = s;
+
+ for (size_t i = 0; i < n; i++)
+ mem[i] = c;
+
+ return s;
}
void demo_go_unprivileged(void)
{
- size_t call_unprivileged_offset =
- (size_t) &call_unprivileged - (size_t) &__libkernel_start;
+ uint32_t PL0_regs[16] = {0};
+ PL0_regs[15] = VIRTUAL_PL0_MEMORY_START; // the new pc
+ PL0_regs[13] = (PL0_SECTION_NUMBER + 1) << 20; // the new sp
+
+ PSR_t new_SPSR = read_CPSR();
+ new_SPSR.fields.PSR_MODE_4_0 = MODE_USER;
+ write_SPSR(new_SPSR);
- void *call_unprivileged_new_location =
- (void*) (LIBKERNEL_SECTION_START + call_unprivileged_offset);
+ uart_puts("All ready, jumping to PL0 code\n\r");
- // call call_unprivileged from libkernel
- asm volatile("mov r5, %0\n\r"
- "mov r0, %1\n\r"
- "mov r4, #0\n\r"
- "movt r4, #"PL0_SECTION_NUMBER_STR"1111\n\r"
- "mov sp, r4\n\r" // setting stack is important :D
- "blx r5\n\r" ::
- "r" (call_unprivileged_new_location),
- "r" (VIRTUAL_PL0_MEMORY_START)
- : "memory", "r4", "r5", "r0");
+ asm volatile("ldm %0, {r0 - r15} ^" ::
+ "r" (PL0_regs));
}
extern char
diff --git a/kernel.c b/kernel.c
index fc629e1..9cdb82a 100644
--- a/kernel.c
+++ b/kernel.c
@@ -27,8 +27,6 @@ void kernel_main(uint32_t r0, uint32_t r1, uint32_t atags)
// prints some info and sets upp translation table, turns on MMU
setup_flat_map();
- demo_setup_libkernel();
-
demo_setup_PL0();
demo_setup_interrupts();
diff --git a/libkernel.c b/libkernel.c
deleted file mode 100644
index 0955e0e..0000000
--- a/libkernel.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// This is the privileged code, that gets placed somewhere in
-// unprivileged process' address space. It's compiled as relocatable,
-// so it can be loaded at different address for different processes.
-
-void call_unprivileged(void (*address) (void)) {
- // switch to PL0
- asm("cps #0b10000\n\r"
- "isb" ::: "memory");
-
- // jump to that unprivileged code
- address();
-}
diff --git a/libkernel.h b/libkernel.h
deleted file mode 100644
index a8af348..0000000
--- a/libkernel.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef LIBKERNEL_H
-#define LIBKERNEL_H
-
-void call_unprivileged(void (*address) (void));
-
-#endif // LIBKERNEL_H
diff --git a/linker.ld b/linker.ld
index 7b585dc..673d7e2 100644
--- a/linker.ld
+++ b/linker.ld
@@ -30,17 +30,6 @@ SECTIONS
}
__kernel_size = __kernel_end - __kernel_start;
-
- /* libkernel */
- .libkernel :
- {
- __libkernel_start = .;
- libkernel.o
- __libkernel_end = .;
- }
- __libkernel_size = __libkernel_end - __libkernel_start;
-
-
.interrupts :
{
__interrupts_start = .;
diff --git a/memory.h b/memory.h
index 1c9ae35..d369694 100644
--- a/memory.h
+++ b/memory.h
@@ -24,24 +24,15 @@ extern const char __start;
#define TRANSLATION_TABLE_END \
(TRANSLATION_TABLE_BASE + (uint32_t) (4096 * 4))
-#define LIBKERNEL_SECTION_START \
- (((TRANSLATION_TABLE_END - (uint32_t) 1) & ~((uint32_t) 0xfffff)) \
+#define PRIVILEGED_MEMORY_END \
+ (((TRANSLATION_TABLE_END - (uint32_t) 1) & ~((uint32_t) 0xfffff)) \
+ SECTION_SIZE)
-#define LIBKERNEL_SECTION_END \
- (LIBKERNEL_SECTION_START + SECTION_SIZE)
-
-// section for libkernel is flat-mapped
-#define LIBKERNEL_SECTION_NUMBER (LIBKERNEL_SECTION_START >> 20)
-
-#define PRIVILEGED_MEMORY_END LIBKERNEL_SECTION_END
-
#define UNPRIVILEGED_MEMORY_START PRIVILEGED_MEMORY_END
#define UNPRIVILEGED_MEMORY_END \
(UNPRIVILEGED_MEMORY_START + SECTION_SIZE)
#define PL0_SECTION_NUMBER ((uint32_t) 0b101010101010)
-#define PL0_SECTION_NUMBER_STR "0b101010101010"
#define VIRTUAL_PL0_MEMORY_START (PL0_SECTION_NUMBER << 20)
diff --git a/psr.h b/psr.h
index 9809fc4..b2adafb 100644
--- a/psr.h
+++ b/psr.h
@@ -64,4 +64,19 @@ inline static PSR_t read_CPSR(void)
return CPSR;
}
+inline static PSR_t read_SPSR(void)
+{
+ PSR_t SPSR;
+ // get content of saved program status register
+ asm("mrs %0, spsr" : "=r" (SPSR.raw) :: "memory");
+
+ return SPSR;
+}
+
+inline static void write_SPSR(PSR_t SPSR)
+{
+ // set content of saved program status register
+ asm("msr spsr, %0" :: "r" (SPSR.raw));
+}
+
#endif // PSR_H