From 39145f6d1b8c57abe2bc0167b2b413970d0dfdb6 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Tue, 19 Nov 2019 17:49:20 +0100 Subject: split kernel into more files --- demo_functionality.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 demo_functionality.c (limited to 'demo_functionality.c') 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"); +} -- cgit v1.2.3