1 #include <machine/asm.h>
2 #include <ucontextoffsets.h>
10 /* MCF_MAGIC value from <mcontext.h> */
11 #define MCF_MAGIC 0xc0ffee
13 /* Values from <sys/ucontext.h> */
14 #define UCF_IGNFPU 0x002
15 #define UCF_IGNSIGM 0x004
18 /* EINVAL from errno.h */
22 /* int getcontext(ucontext_t *ucp)
23 * Initialise the structure pointed to by ucp to the current user context
24 * of the calling thread. */
26 /* In case a process does not use the FPU and is neither interested in
27 * saving its signal mask, then we can skip the context switch to
28 * PM and kernel altogether and only save general-purpose registers. */
30 mov r3, lr /* Save return address:
31 * When setcontext or swapcontext is called,
32 * we jump to this address and continue
37 /* Check null pointer */
38 cmp r0, #0 /* ucp == NULL? */
39 bne 3f /* Not null, continue */
41 ldr r2, =_C_LABEL(errno)
42 str r1, [r2] /* errno = EFAULT */
43 mov r0, #-1 /* return -1 */
47 ldr r1, [r0, #UC_FLAGS] /* r1 = ucp->uc_flags */
48 mov r2, #(UCF_IGNFPU | UCF_IGNSIGM)
49 cmp r1, r2 /* is UCF_IGNFPU or UCF_IGNSIGM set? */
50 beq 1f /* Both are set, skip getuctx */
54 bl _C_LABEL(getuctx) /* getuctx(ucp) */
58 /* Save the context */
59 mov lr, r3 /* Restore lr */
60 str lr, [r0, #LRREG] /* Save lr */
61 str lr, [r0, #PCREG] /* Save real RTA in mcp struct */
62 str sp, [r0, #SPREG] /* Save stack pointer */
63 str fp, [r0, #FPREG] /* Save fp */
64 str r4, [r0, #REG4] /* Save r4 */
65 str r5, [r0, #REG5] /* Save r5 */
66 str r6, [r0, #REG6] /* Save r6 */
67 str r7, [r0, #REG7] /* Save r7 */
68 str r8, [r0, #REG8] /* Save r8 */
69 str r9, [r0, #REG9] /* Save r9 */
70 str r10, [r0, #REG10] /* Save r10 */
73 str r1, [r0, #MAGIC] /* Set magic value */
76 str r1, [r0, #REG0] /* Return 0 */
77 mov r0, #0 /* Return 0 */
80 bx lr /* Restore return address */
83 /* int setcontext(const ucontext_t *ucp)
84 * Restore the user context pointed to by ucp. A successful call to
85 * setcontext does not return; program execution resumes at the point
86 * specified by the ucp argument. If ucp was created with getcontext(),
87 * program execution continues as if the corresponding call of getcontext()
88 * had just returned. If ucp was created with makecontext(), program
89 * execution continues with the function passed to makecontext(). */
91 /* In case a process does not use the FPU and is neither interested in
92 * restoring its signal mask, then we can skip the context switch to
93 * PM and kernel altogether and restore state here. */
97 /* Check null pointer */
98 cmp r0, #0 /* ucp == NULL? */
99 bne 3f /* Not null, continue */
101 ldr r2, =_C_LABEL(errno)
102 str r1, [r2] /* errno = EFAULT */
103 mov r0, #-1 /* return -1 */
107 ldr r1, [r0, #MAGIC] /* r1 = ucp->mc_context.mc_magic */
109 cmp r1, r2 /* is the magic value set (is context valid)?*/
110 beq 4f /* is set, proceed */
111 mov r1, #EINVAL /* not set, return error code */
112 ldr r2, =_C_LABEL(errno)
113 str r1, [r2] /* errno = EINVAL */
114 mov r0, #-1 /* return -1 */
118 4: ldr r1, [r0, #UC_FLAGS] /* r1 = ucp->uc_flags */
119 mov r2, #(UCF_IGNFPU | UCF_IGNSIGM)
120 cmp r1, r2 /* Are UCF_IGNFPU and UCF_IGNSIGM flags set? */
121 beq 1f /* Both are set, so don't bother restoring FPU
122 * state and signal mask */
125 0: bl _C_LABEL(setuctx) /* setuctx(ucp) */
128 1: /* Restore the registers */
129 ldr r1, [r0, #REG1] /* Restore r1 */
130 ldr r2, [r0, #REG2] /* Restore r2 */
131 ldr r3, [r0, #REG3] /* Restore r3 */
132 ldr r4, [r0, #REG4] /* Restore r4 */
133 ldr r5, [r0, #REG5] /* Restore r5 */
134 ldr r6, [r0, #REG6] /* Restore r6 */
135 ldr r7, [r0, #REG7] /* Restore r7 */
136 ldr r8, [r0, #REG8] /* Restore r8 */
137 ldr r9, [r0, #REG9] /* Restore r9 */
138 ldr r10, [r0, #REG10] /* Restore r10 */
139 ldr r12, [r0, #REG12] /* Restore r12 */
140 ldr fp, [r0, #FPREG] /* Restore fp */
141 ldr sp, [r0, #SPREG] /* Restore sp */
142 ldr lr, [r0, #LRREG] /* Restore lr */
144 ldr r0, [r4, #REG0] /* Restore r0 */
146 ldr pc, [r4, #PCREG] /* Restore pc */
150 * A wrapper to call resumecontext. Makecontext puts the ucp in r4.
151 * This function moves the ucp into r0 so that the ucp is the first
152 * parameter for resumecontext. The call to resumecontext will start
153 * the next context in the linked list (or exit the program if there
157 b _C_LABEL(resumecontext)