aboutsummaryrefslogtreecommitdiff
path: root/demo_functionality.c
diff options
context:
space:
mode:
Diffstat (limited to 'demo_functionality.c')
-rw-r--r--demo_functionality.c179
1 files changed, 93 insertions, 86 deletions
diff --git a/demo_functionality.c b/demo_functionality.c
index 691cdb1..1ef91a1 100644
--- a/demo_functionality.c
+++ b/demo_functionality.c
@@ -1,7 +1,11 @@
-#include "uart.h"
+#include "io.h"
#include "psr.h"
#include "memory.h"
#include "translation_table_descriptors.h"
+#include "ramfs.h"
+#include "strings.h"
+#include "paging.h"
+#include "armclock.h"
void demo_paging_support(void)
{
@@ -13,16 +17,16 @@ void demo_paging_support(void)
switch(ID_MMFR0 & 0xf) /* lowest 4 bits indicate VMSA support */
{
- case 0 : paging = "no paging\n\r"; break;
- case 1 : paging = "implementation defined paging\n\r"; break;
- case 2 : paging = "VMSAv6, with cache and TLB type registers\n\r"; break;
- case 3 : paging = "VMSAv7, with support for remapping and access flag\n\r"; break;
- case 4 : paging = "VMSAv7 with PXN bit supported\n\r"; break;
- case 5 : paging = "VMSAv7, PXN and long format descriptors. EPAE is supported.\n\r"; break;
- default : paging = "?_? unknown paging ?_?\n\r";
+ case 0 : paging = "no paging"; break;
+ case 1 : paging = "implementation defined paging"; break;
+ case 2 : paging = "VMSAv6, with cache and TLB type registers"; break;
+ case 3 : paging = "VMSAv7, with support for remapping and access flag"; break;
+ case 4 : paging = "VMSAv7 with PXN bit supported"; break;
+ case 5 : paging = "VMSAv7, PXN and long format descriptors. EPAE is supported."; break;
+ default : paging = "?_? unknown paging ?_?";
}
- uart_puts(paging);
+ puts(paging);
}
void demo_current_mode(void)
@@ -36,99 +40,102 @@ void demo_current_mode(void)
switch(CPSR.fields.PSR_MODE_4_0)
{
- 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;
+ case MODE_USER : mode_name = "User (PL0)"; break;
+ case MODE_FIQ : mode_name = "FIQ (PL1)"; break;
+ case MODE_IRQ : mode_name = "IRQ (PL1)"; break;
+ case MODE_SUPERVISOR : mode_name = "Supervisor (PL1)"; break;
+ case MODE_MONITOR : mode_name = "Monitor (PL1)"; break;
+ case MODE_ABORT : mode_name = "Abort (PL1)"; break;
+ case MODE_HYPERVISOR : mode_name = "Hyp (PL2)"; break;
+ case MODE_UNDEFINED : mode_name = "Undefined (PL1)"; break;
+ case MODE_SYSTEM : mode_name = "System (PL1)"; break;
+ default : mode_name = "Unknown mode"; break;
}
- uart_puts("current mode: ");
- uart_puts(mode_name);
+ prints("current mode: ");
+ puts(mode_name);
}
+#define TRANSLATION_TABLE \
+ ((short_section_descriptor_t volatile*) TRANSLATION_TABLE_BASE)
+
extern char
- _binary_PL_0_test_img_start,
- _binary_PL_0_test_img_end,
- _binary_PL_0_test_img_size;
+ _binary_ramfs_img_start,
+ _binary_ramfs_img_end,
+ _binary_ramfs_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;
-
- 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];
-
- 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 =
- AP_2_0_MODEL_RW_ALL >> 2;
- PL0_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;
-
+ // find PL_0_test.img im ramfs
+ struct ramfile PL_0_test_img;
+
+ if (find_file(&_binary_ramfs_img_start, "PL_0_test.img",
+ &PL_0_test_img))
+ {
+ puts("PL_0_test.img not found :(");
+ asm volatile ("wfi");
+ }
- // invalidate main Translation Lookup Buffer (just in case)
- asm("mcr p15, 0, %0, c8, c7, 0\n\r"
- "isb" :: "r" (0) : "memory");
+ // dummy value 5 for now, as we haven't implemented processes yet
+ uint16_t physical_section_number = claim_and_map_section
+ ((void*) 5, PL0_SECTION_NUMBER, AP_2_0_MODEL_RW_ALL);
+ if (physical_section_number == SECTION_NULL)
+ {
+ puts("Couldn't claim memory section for unprivileged code :(");
+ while(1);
+ }
+
+ size_t physical_section_start =
+ (((size_t) physical_section_number) << 20);
+
// 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*) VIRTUAL_PL0_MEMORY_START);
-
- // 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++)
- ((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");
-}
+ char str_part1[] = "mapped section for PL0 code (0x";
+ char str_part2[] = " -> 0x";
+ char str_part3[] = ")";
-extern char
- __interrupt_vectors_start,
- __interrupt_vectors_end,
- __interrupt_vectors_size;
+ char *string_end = (char*) physical_section_start;
-extern void (*volatile system_reentry_point)(void);
+ memcpy(string_end, str_part1, sizeof(str_part1) - 1);
+ uint32_to_hex(VIRTUAL_PL0_MEMORY_START,
+ string_end += sizeof(str_part1) - 1);
+ memcpy(string_end += 8, str_part2, sizeof(str_part2) - 1);
+ uint32_to_hex(physical_section_start,
+ string_end += sizeof(str_part2) - 1);
+ memcpy(string_end += 8, str_part3, sizeof(str_part3));
-void system_reentry(void)
-{
- uart_puts("re-entered system");
- while(1);
+ puts((char*) VIRTUAL_PL0_MEMORY_START);
+
+ // now paste a userspace program to that section
+ memcpy((void*) VIRTUAL_PL0_MEMORY_START,
+ PL_0_test_img.file_contents, PL_0_test_img.file_size);
+
+ puts("copied PL0 code to it's section");
}
-void demo_setup_interrupts(void)
+void demo_go_unprivileged(void)
{
- system_reentry_point = system_reentry;
+ uint32_t PL0_regs[14] = {0};
+ PL0_regs[13] = VIRTUAL_PL0_MEMORY_START; // the new pc
+
+ PSR_t new_SPSR = read_CPSR();
+ new_SPSR.fields.PSR_MODE_4_0 = MODE_USER;
+ new_SPSR.fields.PSR_IRQ_MASK_BIT = 0;
+ write_SPSR(new_SPSR);
- for (size_t i = 0; i < (size_t) &__interrupt_vectors_size; i++)
- ((volatile char*) 0)[i] =
- (&__interrupt_vectors_start)[i];
+ puts("All ready, jumping to PL0 code");
+
+ armclk_irq_settimeout(0x00100000);
+
+ asm volatile("cps %[sysmode]\n\r"
+ "mov sp, %[stackaddr]\n\r"
+ "cps %[supmode]\n\r"
+ "ldm %[contextaddr], {r0 - r12, pc} ^" ::
+ [sysmode]"I" (MODE_SYSTEM),
+ [supmode]"I" (MODE_SUPERVISOR),
+ [stackaddr]"r" ((PL0_SECTION_NUMBER + 1) << 20),
+ [contextaddr]"r" (PL0_regs) : "memory");
+
+ __builtin_unreachable();
}