aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile14
-rw-r--r--PL0_test.c18
-rw-r--r--PL0_test.ld44
-rw-r--r--kernel.c57
4 files changed, 131 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index bb8d06e..6f2600e 100644
--- a/Makefile
+++ b/Makefile
@@ -7,13 +7,25 @@ all : kernel7.img
kernel.o : kernel.c
arm-none-eabi-gcc $(CFLAGS) -c $^ -o $@
+PL0_test.o : PL0_test.c
+ arm-none-eabi-gcc $(CFLAGS) -c $^ -o $@
+
+PL_0_test.elf : PL0_test.o uart.o
+ arm-none-eabi-gcc -T PL0_test.ld -o $@ $(ELFFLAGS) $^
+
+PL_0_test.img : PL_0_test.elf
+ arm-none-eabi-objcopy $^ -O binary $@
+
+PL_0_test_embeddable.o : PL_0_test.img
+ arm-none-eabi-objcopy -I binary -O elf32-littlearm -B arm --rename-section .data=.rodata $^ $@
+
uart.o : uart.c
arm-none-eabi-gcc $(CFLAGS) -c $^ -o $@
boot.o : boot.S
arm-none-eabi-as -mcpu=cortex-a7 $^ -o $@
-kernel.elf : boot.o kernel.o uart.o
+kernel.elf : boot.o kernel.o uart.o PL0_test.o PL_0_test_embeddable.o
arm-none-eabi-gcc -T linker.ld -o $@ $(ELFFLAGS) $^
kernel7.img : kernel.elf
diff --git a/PL0_test.c b/PL0_test.c
new file mode 100644
index 0000000..1a3d49d
--- /dev/null
+++ b/PL0_test.c
@@ -0,0 +1,18 @@
+#include "uart.h"
+
+void PL0_main(void)
+{
+ uart_puts("hello PL0!\n\r");
+
+ while (1)
+ {
+ char c;
+ switch(c = uart_getc())
+ {
+ case '\r':
+ uart_putc('\n');
+ default:
+ uart_putc(c);
+ }
+ }
+}
diff --git a/PL0_test.ld b/PL0_test.ld
new file mode 100644
index 0000000..430e098
--- /dev/null
+++ b/PL0_test.ld
@@ -0,0 +1,44 @@
+ENTRY(_start)
+
+SECTIONS
+{
+ /* 0b10101010101000000000000000000000 */
+ . = 0xaaa00000;
+ __start = .;
+ __text_start = .;
+ .text :
+ {
+ /* have entry point at the beginning */
+ KEEP(*(.text.PL0main))
+ *(.text)
+ }
+ . = ALIGN(4096); /* align to page size */
+ __text_end = .;
+
+ __rodata_start = .;
+ .rodata :
+ {
+ *(.rodata)
+ }
+ . = ALIGN(4096); /* align to page size */
+ __rodata_end = .;
+
+ __data_start = .;
+ .data :
+ {
+ *(.data)
+ }
+ . = ALIGN(4096); /* align to page size */
+ __data_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ bss = .;
+ *(.bss)
+ }
+ . = ALIGN(4096); /* align to page size */
+ __bss_end = .;
+ __bss_size = __bss_end - __bss_start;
+ __end = .;
+}
diff --git a/kernel.c b/kernel.c
index 7a10b24..bd4426d 100644
--- a/kernel.c
+++ b/kernel.c
@@ -6,6 +6,11 @@
extern char __end;
+extern char
+ _binary_PL_0_test_img_start,
+ _binary_PL_0_test_img_end,
+ _binary_PL_0_test_img_size;
+
void enabling_code_from_the_net(void);
void kernel_main(uint32_t r0, uint32_t r1, uint32_t atags)
@@ -85,7 +90,7 @@ void kernel_main(uint32_t r0, uint32_t r1, uint32_t atags)
// flat map all memory
uart_puts("preparing translation table\n\r");
- short_descriptor_lvl1_t *translation_table =
+ short_descriptor_lvl1_t volatile *translation_table =
(short_descriptor_lvl1_t*) translation_table_base;
for (uint32_t i = 0; i < 4096; i++)
@@ -178,6 +183,56 @@ void kernel_main(uint32_t r0, uint32_t r1, uint32_t atags)
asm("mcr p15, 0, %0, c1, c0, 0\n\r"
"isb" :: "r" (SCTLR.raw) : "memory");
+ volatile short_section_descriptor_t *PL0_code_section =
+ &translation_table[0b101010101010].section_fields;
+ volatile short_section_descriptor_t *UART_memory_section =
+ &translation_table[((uint32_t) GPIO_BASE) >> 20].section_fields;
+
+ // map code section to the memory right after out kernel
+ uint32_t kernel_memory_end = (uint32_t) (translation_table + 4096);
+ uint32_t unprivileged_memory_start =
+ (((kernel_memory_end - 1) >> 20) + 1) << 20;
+
+ PL0_code_section->SECTION_BASE_ADDRESS_31_20 =
+ unprivileged_memory_start >> 20;
+
+ // make the selected section and uart section available for PL0
+ PL0_code_section->ACCESS_PERMISSIONS_2 =
+ AP_2_0_MODEL_RW_ALL >> 2;
+ PL0_code_section->ACCESS_PERMISSIONS_1_0 =
+ AP_2_0_MODEL_RW_ALL & 0b011;
+
+ UART_memory_section->ACCESS_PERMISSIONS_2 =
+ AP_2_0_MODEL_RW_ALL >> 2;
+ UART_memory_section->ACCESS_PERMISSIONS_1_0 =
+ AP_2_0_MODEL_RW_ALL & 0b011;
+
+
+ // invalidate main Translation Lookup Buffer (just in case)
+ asm("mcr p15, 0, %0, c8, c7, 0\n\r"
+ "isb" :: "r" (0) : "memory");
+
+ // check that translation works... by copying a string using one
+ // mapping and reading it using other :D
+ char message[] = "mapped sections for PL0 code\n\r";
+
+ unsigned int i;
+ for (i = 0; i < sizeof(message); i++)
+ ((volatile char*) unprivileged_memory_start)[i] = message[i];
+
+ uart_puts((char*) (((uint32_t) 0b101010101010) << 20));
+
+ // now paste a userspace program to that section, jump to it and
+ // switch to PL0
+ for (size_t i = 0; i < (size_t) &_binary_PL_0_test_img_size; i++)
+ ((char*) (((uint32_t) 0b101010101010) << 20))[i] =
+ (&_binary_PL_0_test_img_start)[i];
+
+ // jump to that copied code (no switch to PL0 yet, just testing)
+ ((void(*)(void)) (((uint32_t) 0b101010101010) << 20))();
+
+ while(1);
+
while (1)
{
char c;