/* * Copyright 2011, François Revol . * All rights reserved. Distributed under the terms of the MIT License. */ #include .arch_extension virt .text /* status_t arch_enter_kernel(uint32_t ttbr, struct kernel_args *kernelArgs, addr_t kernelEntry, addr_t kernelStackTop); r0 - ttbr r1 - kernelArgs r2 - kernelEntry r3 - kernelStackTop */ FUNCTION(arch_enter_kernel): // check whether we are running in HYP mode mrs r9, cpsr and r9, r9, #0x1f // proceed to _pl1_entry if we're not in HYP mode cmp r9, #0x1a bne _pl1_entry // set SVC mode in SPSR mrs r9, cpsr bic r9, r9, #0x1f orr r9, r9, #0x13 msr spsr_cxsf, r9 // load PL1 entry point address adr lr, _pl1_entry msr elr_hyp, lr // drop to PL1 SVC mode eret _pl1_entry: mov r5,r0 mov r4,r2 // set up kernel _start args mov r0,r1 // kernelArgs mov r1,#0 // currentCPU=0 // enable full access for coprocessors P10, P11 // by setting the required flags in Access Control Register MRC p15, #0, r9, c1, c0, #2 orr r9, r9, #0x00f00000 MCR p15, #0, r9, c1, c0, #2 // flush prefetch buffer mov r9, #0 MCR p15, #0, r9, c7, c5, #4 // enable FPU mov r9, #0x40000000 FMXR FPEXC, r9 // flush TLB MCR p15, 0, r1, c8, c7, 0 // set TTBR0 // cacheability attributes for the page tables are: // Normal Memory, Inner/Outer Write-Back no Write-Allocate Cacheable // Note that this relies on ARMv7 multiprocessing extensions // on uniprocessors we need only the flag 0x01 i.e. Inner Cacheable orr r5, r5, #0x59 mcr p15, 0, r5, c2, c0, 0 // initialize TTBCR to zero (no LPAE, use only TTBR0) MCR p15, 0, r1, c2, c0, 2 // flush TLB (again) MCR p15, 0, r1, c8, c7, 0 // write DACR mov r9, #0x00000001 mcr p15, 0, r9, c3, c0, 0 // enable MMU and caches mrc p15, 0, r9, c1, c0, 0 bic r9, r9, #0x20000000 // access flag disabled bic r9, r9, #0x10000000 // TEX remap disabled orr r9, r9, #0x00001000 // i-cache enabled orr r9, r9, #0x00000004 // d-cache enabled orr r9, r9, #0x00000001 // MMU enabled mcr p15, 0, r9, c1, c0, 0 // set the kernel stack mov sp,r3 // call the kernel mov pc,r4 // return mov r0,#-1 // B_ERROR mov pc,lr FUNCTION_END(arch_enter_kernel)