1
1
#include <machine/asm.h>
2
2
#include <ucontextoffsets.h>
3
3
4
- #ifdef __ACK__
5
- .text
6
- begtext:
7
- #ifdef __ACK__
8
- .rom
9
- #else
10
- .data
11
- #endif
12
- begrom:
13
- .data
14
- begdata:
15
- .bss
16
- begbss:
17
- #endif
18
-
19
-
20
4
IMPORT(getuctx)
21
5
IMPORT(setuctx)
22
6
IMPORT(resumecontext)
23
7
8
+ .globl _C_LABEL(__errno)
24
9
25
10
/* MCF_MAGIC value from <mcontext.h> */
26
11
#define MCF_MAGIC 0xc0ffee
@@ -29,7 +14,6 @@ IMPORT(resumecontext)
29
14
#define UCF_IGNFPU 0x002
30
15
#define UCF_IGNSIGM 0x004
31
16
32
-
33
17
/* EINVAL from errno.h */
34
18
#define EFAULT 14
35
19
#define EINVAL 22
@@ -43,59 +27,44 @@ ENTRY(getcontext)
43
27
* saving its signal mask, then we can skip the context switch to
44
28
* PM and kernel altogether and only save general-purpose registers. */
45
29
46
- mov (%esp ), %ecx /* Save return address:
47
- * When setcontext or swapcontext is called,
48
- * we jump to this address and continue
49
- * running. */
50
-
51
30
mov 4 (%esp ), %edx /* edx = ucp */
52
31
/* Check null pointer */
53
32
cmp $0 , %edx /* edx == NULL? */
54
33
jne 3f /* Not null, continue */
55
- movl $EFAULT, (_C_LABEL(errno))
34
+ PIC_PROLOGUE
35
+ call PIC_PLT(_C_LABEL(__errno))
36
+ PIC_EPILOGUE
37
+ movl $EFAULT, (%eax )
56
38
xor %eax , %eax
57
39
dec %eax /* return -1 */
58
40
ret
59
41
60
42
3: /* Check flags */
61
- push %ecx /* save ecx */
62
- push %ebx /* save ebx */
63
- lea UC_FLAGS(%edx ), %ebx /* ebx = &(ucp->uc_flags) */
64
- mov (%ebx ), %ecx /* ecx = ucp->uc_flags */
65
- mov $UCF_IGNFPU, %eax
66
- or $UCF_IGNSIGM, %eax
67
- cmp %eax , %ecx /* is UCF_IGNFPU or UCF_IGNSIGM set? */
68
- pop %ebx /* restore ebx */
69
- pop %ecx /* restore ecx */
70
- jz 1f /* Both are set, skip getuctx */
71
-
72
- 0:
73
- push %ecx /* Save ecx */
43
+ mov UC_FLAGS(%edx ), %eax /* eax = ucp->uc_flags */
44
+ #if 0
45
+ and $~[UCF_IGNFPU|UCF_IGNSIGM], %eax /* check only those flags */
46
+ #endif
47
+ xor $[UCF_IGNFPU|UCF_IGNSIGM], %eax /* toggle both flags */
48
+ jz 5f /* Both were set, skip getuctx */
49
+ PIC_PROLOGUE
74
50
push %edx
75
- call _C_LABEL(getuctx) /* getuctx(ucp) */
51
+ call PIC_PLT( _C_LABEL(getuctx)) /* getuctx(ucp) */
76
52
pop %edx /* clean up stack and restore edx */
77
- pop %ecx /* Restore ecx */
53
+ PIC_EPILOGUE
78
54
79
- 1:
55
+ 5:
80
56
/* Save the context */
81
- mov 4 (%esp ), %edx /* edx = ucp */
82
- pop %eax /* retaddr */
83
- mov %eax , PC(%edx ) /* Save real RTA in mcp struct */
57
+ pop PC(%edx ) /* Save real RTA in mcp struct */
84
58
mov %esp , SP(%edx ) /* Save stack pointer (now pointing to ucp) */
85
- /* Save GP registers */
59
+ /* Save GP registers (except EAX and EDX) */
86
60
mov %ebp , BP(%edx ) /* Save EBP */
87
61
mov %esi , SI(%edx ) /* Save ESI */
88
62
mov %edi , DI(%edx ) /* Save EDI */
89
63
mov %ebx , BX(%edx ) /* Save EBX */
90
64
mov %ecx , CX(%edx ) /* Save ECX */
91
65
movl $MCF_MAGIC, MAGIC(%edx ) /* Set magic value */
92
- push %eax /* Restore retaddr */
93
-
94
66
xor %eax , %eax /* Return 0 */
95
-
96
- 2:
97
- add $4 , %esp /* Remove stale (setcontext) RTA */
98
- jmp *%ecx /* Restore return address */
67
+ jmp *PC(%edx ) /* Return return address */
99
68
100
69
101
70
/* int setcontext(const ucontext_t *ucp)
@@ -115,60 +84,60 @@ ENTRY(setcontext)
115
84
/* Check null pointer */
116
85
cmp $0 , %edx /* edx == NULL? */
117
86
jnz 3f /* Not null, continue */
118
- movl $EFAULT, (_C_LABEL(errno))
87
+ movl $EFAULT, %edx
88
+ 0: PIC_PROLOGUE
89
+ call PIC_PLT(_C_LABEL(__errno))
90
+ PIC_EPILOGUE
91
+ movl %edx , (%eax )
119
92
xor %eax , %eax
120
93
dec %eax /* return -1 */
121
94
ret
122
95
123
96
3: /* Check flags */
124
- push %ebx /* save ebx */
125
- lea MAGIC(%edx ), %ebx /* ebx = &(ucp->mc_context.mc_magic) */
126
- mov (%ebx ), %ecx /* ecx = ucp->mc_context.mc_magic */
127
- pop %ebx /* restore ebx */
128
- cmp $MCF_MAGIC, %ecx /* is the magic value set (is context valid)?*/
97
+ cmpl $MCF_MAGIC, MAGIC(%edx ) /* is the magic value set (is context valid)?*/
129
98
jz 4f /* is set, proceed */
130
- movl $EINVAL, (_C_LABEL(errno)) /* not set, return error code */
131
- xor %eax , %eax
132
- dec %eax /* return -1 */
133
- ret
99
+ movl $EINVAL, %edx /* not set, return error code */
100
+ jmp 0b
134
101
135
102
136
- 4: push %ebx /* save ebx */
137
- lea UC_FLAGS(%edx ), %ebx /* ebx = &(ucp->uc_flags) */
138
- mov (%ebx ), %ecx /* ecx = ucp->uc_flags */
139
- pop %ebx /* restore ebx */
140
- mov $UCF_IGNFPU, %eax
141
- or $UCF_IGNSIGM, %eax
142
- cmp %eax , %ecx /* Are UCF_IGNFPU and UCF_IGNSIGM flags set? */
143
- jz 1f /* Both are set, so don't bother restoring FPU
103
+ 4: mov UC_FLAGS(%edx ), %eax /* eax = ucp->uc_flags */
104
+ #if 0
105
+ and $~[UCF_IGNFPU|UCF_IGNSIGM], %eax /* check only those flags */
106
+ #endif
107
+ xor $[UCF_IGNFPU|UCF_IGNSIGM], %eax /* toggle both flags */
108
+ jz 5f /* Both are set, so don't bother restoring FPU
144
109
* state and signal mask */
145
110
146
- 0: push %ecx /* Save ecx */
111
+ PIC_PROLOGUE
147
112
push %edx
148
- call _C_LABEL(setuctx) /* setuctx(ucp) */
113
+ call PIC_PLT( _C_LABEL(setuctx)) /* setuctx(ucp) */
149
114
pop %edx /* Clean up stack and restore edx */
150
- pop %ecx /* Restore ecx */
115
+ PIC_EPILOGUE
151
116
152
- 1: /* Restore the registers */
153
- mov 4 (%esp ), %edx /* edx = ucp */
117
+ 5: /* Restore the registers (except EAX and EDX) */
154
118
mov CX(%edx ), %ecx /* Restore ECX */
155
119
mov BX(%edx ), %ebx /* Restore EBX */
156
120
mov DI(%edx ), %edi /* Restore EDI */
157
121
mov SI(%edx ), %esi /* Restore ESI */
158
122
mov BP(%edx ), %ebp /* Restore EBP */
159
123
mov SP(%edx ), %esp /* Restore stack pointer */
160
-
161
- 2:
124
+ #if 0
162
125
jmp *PC(%edx ) /* Push RTA onto stack so we can return to it */
163
-
126
+ #else
127
+ jmp *PC(%edx ) /* Return to RTA */
128
+ #endif
164
129
165
130
/* void ctx_start((void *func)(int arg1, ..., argn), arg1, ..., argn,
166
131
* ucontext_t *ucp)
167
132
* A wrapper to start function `func'. ESI register will contain a pointer
168
133
* to ucp on the stack. By setting ESP to ESI, we effectively 'remove' all
169
134
* arguments to `func' from the stack. Finally, a call to resumecontext
170
135
* will start the next context in the linked list (or exit the program if
171
- * there is no context). */
136
+ * there is no context).
137
+ *
138
+ * Since PIC needs the EBX register, which is pushed on the stack by
139
+ * PIC_PROLOGUE, we need an extra of salsa here.
140
+ */
172
141
ENTRY(ctx_start)
173
142
/* 0(esp) -> func
174
143
* 4(esp) -> arg1
@@ -178,9 +147,10 @@ ENTRY(ctx_start)
178
147
179
148
pop %eax /* eax = func */
180
149
call *%eax /* func(arg1, ..., argn) */
181
- mov %esi , %esp /* Clean up stack */
150
+ PIC_PROLOGUE /* may push %ebx, but we do not care */
151
+ mov %esi , %esp /* Clean up stack, keep %ebx = &GOT */
182
152
/* ucp is now at the top of the stack again */
183
- call _C_LABEL(resumecontext) /* resumecontext(ucp) */
153
+ call PIC_PLT( _C_LABEL(resumecontext) ) /* resumecontext(ucp) */
184
154
ret /* never reached */
185
155
186
156
0 commit comments