1/* 2 * Copyright (c) 2008 Travis Geiselbrecht 3 * 4 * Use of this source code is governed by a MIT-style 5 * license that can be found in the LICENSE file or at 6 * https://opensource.org/licenses/MIT 7 */ 8#include <lk/asm.h> 9#include <arch/arm/cores.h> 10 11 /* context switch frame is as follows: 12 * lr 13 * r11 14 * r10 15 * r9 16 * r8 17 * r7 18 * r6 19 * r5 20 * r4 21 */ 22/* arm_context_switch(addr_t *old_sp, addr_t new_sp) */ 23FUNCTION(arm_context_switch) 24 /* save non callee trashed supervisor registers */ 25 /* spsr and user mode registers are saved and restored in the iframe by exceptions.S */ 26 push { r4-r11, lr } 27 28 /* save old sp */ 29 str sp, [r0] 30 31 /* clear any exlusive locks that the old thread holds */ 32#if ARM_ARCH_LEVEL >= 7 33 /* can clear it directly */ 34 clrex 35#elif ARM_ARCH_LEVEL == 6 36 /* have to do a fake strex to clear it */ 37 ldr r0, =strex_spot 38 strex r3, r2, [r0] 39#endif 40 41 /* load new regs */ 42 mov sp, r1 43 pop { r4-r11, lr } 44 bx lr 45 46.ltorg 47 48#if ARM_ARCH_LEVEL == 6 49.data 50strex_spot: 51 .word 0 52#endif 53 54.text 55 56FUNCTION(arm_save_mode_regs) 57 mrs r1, cpsr 58 59 stmia r0, { r13, r14 }^ /* usr */ 60 add r0, #8 61 62 cps #0x11 /* fiq */ 63 str r13, [r0], #4 64 str r14, [r0], #4 65 66 cps #0x12 /* irq */ 67 str r13, [r0], #4 68 str r14, [r0], #4 69 70 cps #0x13 /* svc */ 71 str r13, [r0], #4 72 str r14, [r0], #4 73 74 cps #0x17 /* abt */ 75 str r13, [r0], #4 76 str r14, [r0], #4 77 78 cps #0x1b /* und */ 79 str r13, [r0], #4 80 str r14, [r0], #4 81 82 cps #0x1f /* sys */ 83 str r13, [r0], #4 84 str r14, [r0], #4 85 86 msr cpsr_c, r1 87 88 bx lr 89 90.text 91 92/* void arm_chain_load(paddr_t entry, ulong arg0, ulong arg1, ulong arg2, ulong arg3) __NO_RETURN; */ 93/* shut down the system, branching into the secondary system */ 94FUNCTION(arm_chain_load) 95 /* shuffle the args around */ 96 mov r4, r0 /* r4 = entry point */ 97 mov r0, r1 98 mov r1, r2 99 mov r2, r3 100 ldr r3, [sp] 101 102#if WITH_KERNEL_VM 103/* The MMU is initialized and running at this point, so we'll need to 104 * make sure we can disable it and continue to run. The caller should 105 * have built a identity map for us and branched to our identity mapping, 106 * so it will be safe to just disable the mmu and branch to the entry 107 * point in physical space. 108 */ 109 /* Read SCTLR */ 110 mrc p15, 0, r12, c1, c0, 0 111 112 /* Turn off the MMU */ 113 bic r12, #0x1 114 115 /* Write back SCTLR */ 116 mcr p15, 0, r12, c1, c0, 0 117 isb 118 119#endif // WITH_KERNEL_VM 120 121 /* call the entry point */ 122 bx r4 123