1/* 2 * Copyright 2013, winocm. <winocm@icloud.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * Redistributions in binary form must reproduce the above copyright notice, this 12 * list of conditions and the following disclaimer in the documentation and/or 13 * other materials provided with the distribution. 14 * 15 * If you are going to use this software in any form that does not involve 16 * releasing the source to this project or improving it, let me know beforehand. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29/* 30 * ARM context switching. 31 */ 32 33#include <arm/arch.h> 34#include <arm/asm_help.h> 35#include <assym.s> 36#include <mach/arm/asm.h> 37 38/** 39 * Call_continuation 40 * 41 * Switch the current context to the thread continuation and terminate on return. 42 */ 43EnterARM(Call_continuation) 44 /* Set the new stack pointer. */ 45 LoadThreadRegister(r9) 46 ldr sp, [r9, TH_PCB_ISS] 47 48 /* Zero out frame pointer */ 49 mov r7, #0 50 51 /* Set arguments */ 52 mov r6, r0 53 mov r0, r1 54 mov r1, r2 55 56 /* Branch to continuation. */ 57 blx r6 58 59 /* Terminate thread. */ 60 mrc p15, 0, r0, c13, c0, 4 61 blx _thread_terminate 62 b . 63 64/** 65 * Switch_context 66 * 67 * Switch the current processor context to that of the new thread. 68 * Does not switch r0-r3 function argument registers. 69 */ 70EnterARM(Switch_context) 71 /* Switch context to the new thread and save the continuation. */ 72 teq r1, #0 73 strne r1, [r0, TH_CONTINUATION] 74 75 /* Only store registers if there is a continuation */ 76 ldreq r3, [r0, TH_PCB_ISS] 77 addeq r3, r3, #16 78 stmiaeq r3, {r4-lr} 79 80 /* Save current thread */ 81 LOAD_ADDR(r4, CurrentThread) 82 str r2, [r4] 83 84 /* Set old/new threads */ 85 mcr p15, 0, r2, c13, c0, 4 86 87 ldr r3, [r2, MACHINE_THREAD_CTHREAD_SELF] 88 mcr p15, 0, r3, c13, c0, 3 89 90 /* Load registers and go. */ 91 ldr r3, [r2, TH_PCB_ISS] 92 add r3, r3, #16 93 ldmia r3!, {r4-lr} 94 bx lr 95 96/** 97 * machine_load_context 98 * 99 * Load the registers and prepare for a context switch. 100 */ 101EnterARM(machine_load_context) 102 /* Save current thread */ 103 LOAD_ADDR(r4, CurrentThread) 104 str r0, [r4] 105 106 /* Set thread */ 107 mcr p15, 0, r0, c13, c0, 4 108 109 /* Set cthread value */ 110 ldr r1, [r0, MACHINE_THREAD_CTHREAD_SELF] 111 mrc p15, 0, r2, c13, c0, 3 112 113 /* Load registers and go. */ 114 ldr r3, [r0, TH_PCB_ISS] 115 mov r0, #0 116 117 add r3, r3, #16 118 ldmia r3!, {r4-lr} 119 bx lr 120 121/** 122 * thread_syscall_return 123 */ 124EnterARM(thread_syscall_return) 125 cpsid i 126 LoadThreadRegister(r9) 127 ldr r4, [r9, TH_PCB_USS] 128 str r0, [r4] 129 b thread_return_join 130 131/** 132 * thread_exception_return 133 * 134 * Used to bootstrap a user thread. 135 */ 136EnterARM(thread_exception_return) 137EnterARM(thread_bootstrap_return) 138 /* Disable interrupts */ 139 cpsid i 140 141thread_return_join: 142 /* Check for pending ast */ 143 mrc p15, 0, r9, c13, c0, 4 144 145 ldr r8, [r9, MACHINE_THREAD_CPU_DATA] 146 ldr r5, [r8, CPU_PENDING_AST] 147 148 cmp r5, #0 149 beq return_to_user 150 151 /* There's an ast. */ 152 153 mov r0, r5 154 mov r1, #1 155 blx _ast_taken 156 157 b _thread_exception_return 158 159return_to_user: 160 /* Restore registers */ 161 LoadThreadRegister(r5) 162 ldr sp, [r5, TH_PCB_USS] 163 ldr r0, [sp, #0x40] 164 165 msr spsr_cxsf, r0 166#ifdef _ARM_ARCH_7 167 clrex 168#endif 169 ldr lr, [sp, #0x3C] 170 171 ldmfd sp, {r0-lr}^ 172 movs pc, lr 173 174LOAD_ADDR_GEN_DEF(CurrentThread) 175