1 #include <machine/asm.h>
2 #include <ucontextoffsets.h>
10 /* int getcontext(ucontext_t *ucp)
11 * Initialise the structure pointed to by ucp to the current user context
12 * of the calling thread. */
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. */
19 mov r3, lr /* Save return address:
20 * When setcontext or swapcontext is called,
21 * we jump to this address and continue
26 /* Check null pointer */
27 cmp r0, #0 /* ucp == NULL? */
28 bne 3f /* Not null, continue */
30 ldr r2, =_C_LABEL(errno)
31 str r1, [r2] /* errno = EFAULT */
32 mov r0, #-1 /* return -1 */
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 */
43 bl _C_LABEL(getuctx) /* getuctx(ucp) */
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 */
62 str r1, [r0, #MAGIC] /* Set magic value */
65 str r1, [r0, #REG0] /* Return 0 */
66 mov r0, #0 /* Return 0 */
69 bx lr /* Restore return address */
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(). */
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. */
86 /* Check null pointer */
87 cmp r0, #0 /* ucp == NULL? */
88 bne 3f /* Not null, continue */
90 ldr r2, =_C_LABEL(errno)
91 str r1, [r2] /* errno = EFAULT */
92 mov r0, #-1 /* return -1 */
96 ldr r1, [r0, #MAGIC] /* r1 = ucp->mc_context.mc_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 */
107 4: 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 */
114 0: bl _C_LABEL(setuctx) /* setuctx(ucp) */
117 1: /* 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 */
130 ldr r0, [r3, #REG0] /* Restore r0 */
132 ldr pc, [r3, #PCREG] /* Restore pc */
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
143 b _C_LABEL(resumecontext)