xref: /minix3/minix/lib/libc/arch/arm/sys/ucontext.S (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
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