1#include <machine/asm.h> 2#include <ucontextoffsets.h> 3 4 5IMPORT(getuctx) 6IMPORT(setuctx) 7IMPORT(resumecontext) 8 9 10/* int getcontext(ucontext_t *ucp) 11 * Initialise the structure pointed to by ucp to the current user context 12 * of the calling thread. */ 13ENTRY(getcontext) 14ENTRY(_getcontext) 15 /* In case a process does not use the FPU and is neither interested in 16 * saving its signal mask, then we can skip the context switch to 17 * PM and kernel altogether and only save general-purpose registers. */ 18 19 mov r3, lr /* Save return address: 20 * When setcontext or swapcontext is called, 21 * we jump to this address and continue 22 * running. */ 23 24 /* r0 = ucp */ 25 26 /* Check null pointer */ 27 cmp r0, #0 /* ucp == NULL? */ 28 bne 3f /* Not null, continue */ 29 mov r1, #EFAULT 30 ldr r2, =_C_LABEL(errno) 31 str r1, [r2] /* errno = EFAULT */ 32 mov r0, #-1 /* return -1 */ 33 bx lr 34 353: /* Check flags */ 36 ldr r1, [r0, #UC_FLAGS] /* r1 = ucp->uc_flags */ 37 and r1, r1, #[_UC_IGNFPU|_UC_IGNSIGM] 38 cmp r1, #[_UC_IGNFPU|_UC_IGNSIGM] /* Allowed to ignore both? */ 39 beq 1f /* If so, skip getuctx */ 40 410: 42 push {r0, r3} 43 bl _C_LABEL(getuctx) /* getuctx(ucp) */ 44 pop {r0, r3} 45 461: 47 /* Save the context */ 48 mov lr, r3 /* Restore lr */ 49 str lr, [r0, #LRREG] /* Save lr */ 50 str lr, [r0, #PCREG] /* Save real RTA in mcp struct */ 51 str sp, [r0, #SPREG] /* Save stack pointer */ 52 str fp, [r0, #FPREG] /* Save fp */ 53 str r4, [r0, #REG4] /* Save r4 */ 54 str r5, [r0, #REG5] /* Save r5 */ 55 str r6, [r0, #REG6] /* Save r6 */ 56 str r7, [r0, #REG7] /* Save r7 */ 57 str r8, [r0, #REG8] /* Save r8 */ 58 str r9, [r0, #REG9] /* Save r9 */ 59 str r10, [r0, #REG10] /* Save r10 */ 60 61 ldr r1, =MCF_MAGIC 62 str r1, [r0, #MAGIC] /* Set magic value */ 63 64 mov r1, #0 65 str r1, [r0, #REG0] /* Return 0 */ 66 mov r0, #0 /* Return 0 */ 67 682: 69 bx lr /* Restore return address */ 70 71 72/* int setcontext(const ucontext_t *ucp) 73 * Restore the user context pointed to by ucp. A successful call to 74 * setcontext does not return; program execution resumes at the point 75 * specified by the ucp argument. If ucp was created with getcontext(), 76 * program execution continues as if the corresponding call of getcontext() 77 * had just returned. If ucp was created with makecontext(), program 78 * execution continues with the function passed to makecontext(). */ 79ENTRY(setcontext) 80 /* In case a process does not use the FPU and is neither interested in 81 * restoring its signal mask, then we can skip the context switch to 82 * PM and kernel altogether and restore state here. */ 83 84 /* r0 = ucp */ 85 86 /* Check null pointer */ 87 cmp r0, #0 /* ucp == NULL? */ 88 bne 3f /* Not null, continue */ 89 mov r1, #EFAULT 90 ldr r2, =_C_LABEL(errno) 91 str r1, [r2] /* errno = EFAULT */ 92 mov r0, #-1 /* return -1 */ 93 bx lr 94 953: /* Check flags */ 96 ldr r1, [r0, #MAGIC] /* r1 = ucp->mc_context.mc_magic */ 97 ldr r2, =MCF_MAGIC 98 cmp r1, r2 /* is the magic value set (is context valid)?*/ 99 beq 4f /* is set, proceed */ 100 mov r1, #EINVAL /* not set, return error code */ 101 ldr r2, =_C_LABEL(errno) 102 str r1, [r2] /* errno = EINVAL */ 103 mov r0, #-1 /* return -1 */ 104 bx lr 105 106 1074: ldr r1, [r0, #UC_FLAGS] /* r1 = ucp->uc_flags */ 108 and r1, r1, #[_UC_IGNFPU|_UC_IGNSIGM] 109 cmp r1, #[_UC_IGNFPU|_UC_IGNSIGM] /* Allowed to ignore both? */ 110 beq 1f /* Neither are set, so don't bother restoring FPU 111 * state and signal mask */ 112 113 push {r0, r3} 1140: bl _C_LABEL(setuctx) /* setuctx(ucp) */ 115 pop {r0, r3} 116 1171: /* Restore the registers */ 118 ldr r4, [r0, #REG4] /* Restore r4 */ 119 ldr r5, [r0, #REG5] /* Restore r5 */ 120 ldr r6, [r0, #REG6] /* Restore r6 */ 121 ldr r7, [r0, #REG7] /* Restore r7 */ 122 ldr r8, [r0, #REG8] /* Restore r8 */ 123 ldr r9, [r0, #REG9] /* Restore r9 */ 124 ldr r10, [r0, #REG10] /* Restore r10 */ 125 ldr r12, [r0, #REG12] /* Restore r12 */ 126 ldr fp, [r0, #FPREG] /* Restore fp */ 127 ldr sp, [r0, #SPREG] /* Restore sp */ 128 ldr lr, [r0, #LRREG] /* Restore lr */ 129 mov r3, r0 130 ldr r0, [r3, #REG0] /* Restore r0 */ 1312: 132 ldr pc, [r3, #PCREG] /* Restore pc */ 133 134 135/* void ctx_start() 136 * A wrapper to call resumecontext. Makecontext puts the ucp in r4. 137 * This function moves the ucp into r0 so that the ucp is the first 138 * parameter for resumecontext. The call to resumecontext will start 139 * the next context in the linked list (or exit the program if there 140 * is no context). */ 141ENTRY(ctx_start) 142 mov r0, r4 143 b _C_LABEL(resumecontext) 144