#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" #include "scheduler.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"; 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 ?_?"; } puts(paging); } void demo_current_mode(void) { // get content of current program status register to check the current // processor mode (should be system, as we set it in boot.S) PSR_t CPSR = read_CPSR(); char *mode_name; switch(CPSR.fields.PSR_MODE_4_0) { 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; } prints("current mode: "); puts(mode_name); } #define TRANSLATION_TABLE \ ((short_section_descriptor_t volatile*) TRANSLATION_TABLE_BASE) extern char _binary_ramfs_img_start, _binary_ramfs_img_end, _binary_ramfs_img_size; void __attribute__((noreturn)) demo_setup_PL0(void) { // 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"); } // 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 str_part1[] = "mapped section for PL0 code (0x"; char str_part2[] = " -> 0x"; char str_part3[] = ")"; char *string_end = (char*) physical_section_start; 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)); 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"); puts("All ready! scheduling!"); schedule_new(VIRTUAL_PL0_MEMORY_START, // the new pc VIRTUAL_PL0_MEMORY_END); // the new sp }