aboutsummaryrefslogtreecommitdiff
path: root/demo_functionality.c
diff options
context:
space:
mode:
Diffstat (limited to 'demo_functionality.c')
-rw-r--r--demo_functionality.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/demo_functionality.c b/demo_functionality.c
new file mode 100644
index 0000000..53035b7
--- /dev/null
+++ b/demo_functionality.c
@@ -0,0 +1,115 @@
+#include "uart.h"
+#include "psr.h"
+#include "memory.h"
+#include "translation_table_descriptors.h"
+
+void demo_paging_support(void)
+{
+ uint32_t ID_MMFR0;
+ // get contents of coprocessor register to check for paging support
+ asm("mrc p15, 0, %0, c0, c1, 4" : "=r" (ID_MMFR0));
+
+ char *paging;
+
+ 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";
+ }
+
+ uart_puts(paging);
+}
+
+void demo_mode_to_system(void)
+{
+
+ // get content of current program status register to check the current
+ // processor mode
+ PSR_t CPSR = read_CPSR();
+
+ char *mode_name;
+
+ 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;
+ }
+
+ uart_puts("current mode: ");
+ uart_puts(mode_name);
+
+ uart_puts("setting mode to system (PL1)...\r\n");
+ set_system_mode();
+}
+
+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)
+{
+ short_section_descriptor_t *translation_table =
+ (short_section_descriptor_t*) TRANSLATION_TABLE_BASE;
+
+ volatile short_section_descriptor_t *PL0_code_section =
+ &translation_table[PL0_SECTION_NUMBER];
+ volatile short_section_descriptor_t *UART_memory_section =
+ &translation_table[((uint32_t) GPIO_BASE) >> 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*) 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");
+}