aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvetch <vetch97@gmail.com>2019-12-10 15:32:22 +0100
committervetch <vetch97@gmail.com>2019-12-10 15:32:22 +0100
commit5662aacc5688bba4873367ed9ab51fb83fbd1feb (patch)
tree429aae32ff3163bf8472fcb52f3ba444c14e374c
parentb0a6351d52af8bdf6fa9cca0d313df323249a520 (diff)
parentc76b34db77f06450ba1c957e87a0b1df3c6c29b4 (diff)
downloadrpi-MMU-example-5662aacc5688bba4873367ed9ab51fb83fbd1feb.tar.gz
rpi-MMU-example-5662aacc5688bba4873367ed9ab51fb83fbd1feb.zip
Merge branch 'bob' of https://repo.or.cz/RPi-MMU-example into alice
-rw-r--r--Makefile12
-rw-r--r--PL0_test.c3
-rw-r--r--PL0_test.ld5
-rw-r--r--demo_functionality.c96
-rw-r--r--demo_functionality.h4
-rw-r--r--kernel.c6
-rw-r--r--linker.ld41
-rw-r--r--memory.h28
8 files changed, 162 insertions, 33 deletions
diff --git a/Makefile b/Makefile
index ce29a19..f07bced 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,10 @@ ELFFLAGS=-ffreestanding -O2 -nostdlib -lgcc -I.
ARM_OBJECTS=kernel.o paging.o demo_functionality.o PL0_test.o uart.o loader_stage1.o loader_stage2.o
+EMBEDDABLE_OBJECTS=PL_0_test_embeddable.o loader_stage2_embeddable.o
+
+RENAME_FLAGS=--rename-section .data=.renamed_data --rename-section .rodata=.renamed_rodata --rename-section .text=.renamed_text --rename-section .bss=.renamed_bss
+
all : kernel7.img
%.o : %.c
@@ -17,10 +21,16 @@ all : kernel7.img
%_embeddable.o : %.img
arm-none-eabi-objcopy -I binary -O elf32-littlearm -B arm --rename-section .data=.rodata $^ $@
+libkernel.o : libkernel.c
+ arm-none-eabi-gcc $(CFLAGS) -fPIC -c $^ -o $@
+
+libkernel_renamed.o : libkernel.o
+ arm-none-eabi-objcopy $(RENAME_FLAGS) $^ $@
+
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 PL_0_test_embeddable.o demo_functionality.o paging.o
+kernel.elf : boot.o kernel.o uart.o PL_0_test_embeddable.o demo_functionality.o paging.o libkernel_renamed.o
arm-none-eabi-gcc -T linker.ld -o $@ $(ELFFLAGS) $^
loader_stage2.elf : loader_stage2.o uart.o
diff --git a/PL0_test.c b/PL0_test.c
index 2216436..1b93024 100644
--- a/PL0_test.c
+++ b/PL0_test.c
@@ -5,9 +5,6 @@ void PL0_main(void)
{
uart_puts("hello PL0! Switching to user mode!\n\r");
- asm("cps #0b10000\n\r"
- "isb" ::: "memory");
-
// if all went correct, Success! gets printed
uart_puts("Success!\n\r");
diff --git a/PL0_test.ld b/PL0_test.ld
index 430e098..45bee5e 100644
--- a/PL0_test.ld
+++ b/PL0_test.ld
@@ -4,6 +4,11 @@ SECTIONS
{
/* 0b10101010101000000000000000000000 */
. = 0xaaa00000;
+
+ /* For some reason ld warns when _start is not defined. */
+ /* Other .elf files link ok - only PL0_test.elf seems to */
+ /* expect _start to be deifned. */
+ _start = .;
__start = .;
__text_start = .;
.text :
diff --git a/demo_functionality.c b/demo_functionality.c
index 7bba6a6..fbf5eb4 100644
--- a/demo_functionality.c
+++ b/demo_functionality.c
@@ -2,6 +2,7 @@
#include "psr.h"
#include "memory.h"
#include "translation_table_descriptors.h"
+#include "libkernel.h"
void demo_paging_support(void)
{
@@ -55,35 +56,73 @@ void demo_mode_to_system(void)
set_system_mode();
}
+#define TRANSLATION_TABLE \
+ ((short_section_descriptor_t volatile*) TRANSLATION_TABLE_BASE)
+
+extern char
+ __renamed_start,
+ __renamed_end,
+ __renamed_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) &__renamed_size; i++)
+ ((volatile char*) LIBKERNEL_SECTION_START)[i] =
+ (&__renamed_start)[i];
+}
+
extern char
_binary_PL_0_test_img_start,
_binary_PL_0_test_img_end,
_binary_PL_0_test_img_size;
-void demo_go_unprivileged(void)
+void demo_setup_PL0(void)
{
- short_section_descriptor_t *translation_table =
- (short_section_descriptor_t*) TRANSLATION_TABLE_BASE;
+ short_section_descriptor_t volatile *PL0_section_entry =
+ &TRANSLATION_TABLE[PL0_SECTION_NUMBER];
+ short_section_descriptor_t volatile *UART_memory_section_entry =
+ &TRANSLATION_TABLE[((uint32_t) GPIO_BASE) >> 20];
- volatile short_section_descriptor_t *PL0_section =
- &translation_table[PL0_SECTION_NUMBER];
- volatile short_section_descriptor_t *UART_memory_section =
- &translation_table[((uint32_t) GPIO_BASE) >> 20];
+ short_section_descriptor_t
+ PL0_section = *PL0_section_entry,
+ UART_memory_section = *UART_memory_section_entry;
- PL0_section->SECTION_BASE_ADDRESS_31_20 =
+ // set up address of PL0 section
+ PL0_section.SECTION_BASE_ADDRESS_31_20 =
UNPRIVILEGED_MEMORY_START >> 20;
// make the selected section and uart section available for PL0
- PL0_section->ACCESS_PERMISSIONS_2 =
+ PL0_section.ACCESS_PERMISSIONS_2 =
AP_2_0_MODEL_RW_ALL >> 2;
- PL0_section->ACCESS_PERMISSIONS_1_0 =
+ PL0_section.ACCESS_PERMISSIONS_1_0 =
AP_2_0_MODEL_RW_ALL & 0b011;
- UART_memory_section->ACCESS_PERMISSIONS_2 =
+ UART_memory_section.ACCESS_PERMISSIONS_2 =
AP_2_0_MODEL_RW_ALL >> 2;
- UART_memory_section->ACCESS_PERMISSIONS_1_0 =
+ UART_memory_section.ACCESS_PERMISSIONS_1_0 =
AP_2_0_MODEL_RW_ALL & 0b011;
-
+
+ *PL0_section_entry = PL0_section;
+ *UART_memory_section_entry = UART_memory_section;
// invalidate main Translation Lookup Buffer (just in case)
asm("mcr p15, 0, %0, c8, c7, 0\n\r"
@@ -99,17 +138,30 @@ void demo_go_unprivileged(void)
uart_puts((char*) VIRTUAL_PL0_MEMORY_START);
- // now paste a userspace program to that section, jump to it and
- // switch to PL0
+ // now paste a userspace program to that section
for (size_t i = 0; i < (size_t) &_binary_PL_0_test_img_size; i++)
((volatile char*) VIRTUAL_PL0_MEMORY_START)[i] =
(&_binary_PL_0_test_img_start)[i];
- // jump to that copied code (switch to PL0 is done by that code)
- asm volatile("mov r5, #0\n\r"
- "movt r5, #"PL0_SECTION_NUMBER_STR"1111\n\r"
- "mov sp, r5\n\r" // setting stack is important :D
- "mov r5, #0\n\r"
- "movt r5, #"PL0_SECTION_NUMBER_STR"0000\n\r"
- "blx r5\n\r");
+ uart_puts("copied PL0 and libkernel code to their sections");
+}
+
+void demo_go_unprivileged(void)
+{
+ size_t call_unprivileged_offset =
+ (size_t) &call_unprivileged - (size_t) &__renamed_start;
+
+ void *call_unprivileged_new_location =
+ (void*) (LIBKERNEL_SECTION_START + call_unprivileged_offset);
+
+ // 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");
}
diff --git a/demo_functionality.h b/demo_functionality.h
index c8b163f..5d6e659 100644
--- a/demo_functionality.h
+++ b/demo_functionality.h
@@ -5,6 +5,10 @@ void demo_paging_support(void);
void demo_mode_to_system(void);
+void demo_setup_libkernel(void);
+
+void demo_setup_PL0(void);
+
void demo_go_unprivileged(void);
#endif // DEMO_FUNCTIONALITY_H
diff --git a/kernel.c b/kernel.c
index 81d261f..3c2f4f9 100644
--- a/kernel.c
+++ b/kernel.c
@@ -29,6 +29,12 @@ 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_go_unprivileged();
+
// prints some info and sets up a section for PL0 code, loads a blob
// there and jumps to it... never, ever, ever returns
demo_go_unprivileged();
diff --git a/linker.ld b/linker.ld
index e7bfdb8..199cc0f 100644
--- a/linker.ld
+++ b/linker.ld
@@ -49,5 +49,46 @@ SECTIONS
. = ALIGN(4096); /* align to page size */
__bss_end = .;
__bss_size = __bss_end - __bss_start;
+
+
+
+ /* Here come the definitions for renamed sections */
+ __renamed_start = .;
+ __renamed_text_start = .;
+ .renamed_text :
+ {
+ *(.renamed_text)
+ }
+ . = ALIGN(4096); /* align to page size */
+ __renamed_text_end = .;
+
+ __renamed_rodata_start = .;
+ .renamed_rodata :
+ {
+ *(.renamed_rodata)
+ }
+ . = ALIGN(4096); /* align to page size */
+ __renamed_rodata_end = .;
+
+ __renamed_data_start = .;
+ .renamed_data :
+ {
+ *(.renamed_data)
+ }
+ . = ALIGN(4096); /* align to page size */
+ __renamed_data_end = .;
+
+ __renamed_bss_start = .;
+ .renamed_bss :
+ {
+ renamed_bss = .;
+ *(.renamed_bss)
+ }
+ . = ALIGN(4096); /* align to page size */
+ __renamed_bss_end = .;
+ __renamed_bss_size = __renamed_bss_end - __renamed_bss_start;
+ __renamed_end = .;
+ __renamed_size = __renamed_end - __renamed_start;
+
__end = .;
}
diff --git a/memory.h b/memory.h
index 1472a8b..1c9ae35 100644
--- a/memory.h
+++ b/memory.h
@@ -1,13 +1,17 @@
#ifndef MEMORY_H
#define MEMORY_H
+#include "paging.h"
+
+#define SECTION_SIZE (((uint32_t) 1) << 20)
+
#define INTERRUPT_VECTOR_TABLE_START ((uint32_t) 0x0)
#define STACK_START ((uint32_t) 0x4000)
#define STACK_END ((uint32_t) 0x8000)
-extern char __end;
-extern char __start;
+extern const char __end;
+extern const char __start;
#define KERNEL_START ((uint32_t) &__start)
#define KERNEL_END ((uint32_t) &__end)
@@ -20,11 +24,21 @@ extern char __start;
#define TRANSLATION_TABLE_END \
(TRANSLATION_TABLE_BASE + (uint32_t) (4096 * 4))
-#define PRIVILEGED_MEMORY_END TRANSLATION_TABLE_END
+#define LIBKERNEL_SECTION_START \
+ (((TRANSLATION_TABLE_END - (uint32_t) 1) & ~((uint32_t) 0xfffff)) \
+ + SECTION_SIZE)
+
+#define LIBKERNEL_SECTION_END \
+ (LIBKERNEL_SECTION_START + SECTION_SIZE)
-#define UNPRIVILEGED_MEMORY_START \
- (((PRIVILEGED_MEMORY_END - (uint32_t) 1) & ~((uint32_t) 0xfffff)) \
- + (uint32_t) 0x100000)
+// 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"
@@ -32,4 +46,4 @@ extern char __start;
#define VIRTUAL_PL0_MEMORY_START (PL0_SECTION_NUMBER << 20)
#endif // MEMORY_H
-
+