1
/* Copyright (C) 2011 Free Software Foundation, Inc.
2
This file is part of the GNU C Library.
3
Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
5
The GNU C Library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Lesser General Public
7
License as published by the Free Software Foundation; either
8
version 2.1 of the License, or (at your option) any later version.
10
The GNU C Library is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
Lesser General Public License for more details.
15
You should have received a copy of the GNU Lesser General Public
16
License along with the GNU C Library; if not, write to the Free
17
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21
#include <asm/errno.h>
22
#include <arch/spr_def.h>
25
#include "ucontext_i.h"
27
/* PL to return to via iret in setcontext */
30
/* int setcontext (const ucontext_t *ucp) */
34
FEEDBACK_ENTER(__setcontext)
36
/* See if this is a true signal context (flags == 0).
37
If so, restore by invoking rt_sigreturn(). */
38
#if UC_FLAGS_OFFSET != 0
39
# error "Add offset to r0 prior to load."
44
addi r10, r10, -1 /* Confirm that it has value "1". */
46
BNEZ r10, .Lbadcontext
48
/* Save lr and r0 briefly on the stack and set the signal mask:
49
rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, NULL, _NSIG / 8). */
52
ADDI_PTR r11, sp, -(2 * REGSIZE)
58
ADDI_PTR r10, sp, -REGSIZE
59
ADDI_PTR sp, sp, -(3 * REGSIZE)
61
cfi_def_cfa_offset (3 * REGSIZE)
64
ADDLI_PTR r1, r0, UC_SIGMASK_OFFSET
66
cfi_offset (r0, -REGSIZE)
73
moveli TREG_SYSCALL_NR_NAME, __NR_rt_sigprocmask
77
ADDI_PTR sp, sp, 3 * REGSIZE
78
ADDI_PTR r11, sp, 2 * REGSIZE /* Restore uc_context to r11. */
80
cfi_def_cfa_offset (0)
84
ADDI_PTR r10, r11, UC_REG(0)
85
BNEZ r1, .Lsyscall_error
88
/* Restore the argument registers; note they will be random
89
unless makecontext() has been called. */
90
{ LD r0, r10; ADDI_PTR r10, r10, REGSIZE }
91
{ LD r1, r10; ADDI_PTR r10, r10, REGSIZE }
92
{ LD r2, r10; ADDI_PTR r10, r10, REGSIZE }
93
{ LD r3, r10; ADDI_PTR r10, r10, REGSIZE }
94
{ LD r4, r10; ADDI_PTR r10, r10, REGSIZE }
95
{ LD r5, r10; ADDI_PTR r10, r10, REGSIZE }
96
{ LD r6, r10; ADDI_PTR r10, r10, REGSIZE }
97
{ LD r7, r10; ADDI_PTR r10, r10, REGSIZE }
98
{ LD r8, r10; ADDI_PTR r10, r10, REGSIZE }
99
{ LD r9, r10; ADDLI_PTR r10, r10, UC_REG(30) - UC_REG(9) }
101
/* Restore the callee-saved GPRs. */
102
{ LD r30, r10; ADDI_PTR r10, r10, REGSIZE }
103
{ LD r31, r10; ADDI_PTR r10, r10, REGSIZE }
104
{ LD r32, r10; ADDI_PTR r10, r10, REGSIZE }
105
{ LD r33, r10; ADDI_PTR r10, r10, REGSIZE }
106
{ LD r34, r10; ADDI_PTR r10, r10, REGSIZE }
107
{ LD r35, r10; ADDI_PTR r10, r10, REGSIZE }
108
{ LD r36, r10; ADDI_PTR r10, r10, REGSIZE }
109
{ LD r37, r10; ADDI_PTR r10, r10, REGSIZE }
110
{ LD r38, r10; ADDI_PTR r10, r10, REGSIZE }
111
{ LD r39, r10; ADDI_PTR r10, r10, REGSIZE }
112
{ LD r40, r10; ADDI_PTR r10, r10, REGSIZE }
113
{ LD r41, r10; ADDI_PTR r10, r10, REGSIZE }
114
{ LD r42, r10; ADDI_PTR r10, r10, REGSIZE }
115
{ LD r43, r10; ADDI_PTR r10, r10, REGSIZE }
116
{ LD r44, r10; ADDI_PTR r10, r10, REGSIZE }
117
{ LD r45, r10; ADDI_PTR r10, r10, REGSIZE }
118
{ LD r46, r10; ADDI_PTR r10, r10, REGSIZE }
119
{ LD r47, r10; ADDI_PTR r10, r10, REGSIZE }
120
{ LD r48, r10; ADDI_PTR r10, r10, REGSIZE }
121
{ LD r49, r10; ADDI_PTR r10, r10, REGSIZE }
122
{ LD r50, r10; ADDI_PTR r10, r10, REGSIZE }
123
{ LD r51, r10; ADDI_PTR r10, r10, REGSIZE }
124
{ LD r52, r10; ADDI_PTR r10, r10, REGSIZE * 2 }
125
/* Skip tp since it must not change for a given thread. */
126
{ LD sp, r10; ADDI_PTR r10, r10, REGSIZE }
127
{ LD lr, r10; ADDI_PTR r10, r10, REGSIZE }
128
{ LD r11, r10; ADDI_PTR r10, r10, REGSIZE }
130
/* Construct an iret context; we set ICS so we can validly load
131
EX_CONTEXT for iret without being interrupted halfway through. */
137
mtspr INTERRUPT_CRITICAL_SECTION, r13
138
shli r12, r12, SPR_EX_CONTEXT_0_1__ICS_SHIFT
141
mtspr EX_CONTEXT_0_0, r11
142
ori r12, r12, RETURN_PL
144
mtspr EX_CONTEXT_0_1, r12
146
jrp lr /* keep the backtracer happy */
149
/* This is a context obtained from a signal handler.
150
Perform a full restore by pushing the context
151
passed onto a simulated signal frame on the stack
152
and call the signal return syscall as if a signal
153
handler exited normally. */
155
ADDLI_PTR sp, sp, -(C_ABI_SAVE_AREA_SIZE + SI_MAX_SIZE + UC_SIZE)
156
ADDLI_PTR r1, sp, -UC_SIZE
158
cfi_def_cfa_offset (C_ABI_SAVE_AREA_SIZE + SI_MAX_SIZE + UC_SIZE)
159
moveli r2, UC_SIZE / REGSIZE
162
ADDI_PTR r0, r0, REGSIZE
166
ADDI_PTR r1, r1, REGSIZE
170
moveli TREG_SYSCALL_NR_NAME, __NR_rt_sigreturn
173
/* Restore the stack and fall through to the error
174
path. Successful rt_sigreturn never returns to
175
its calling place. */
176
ADDLI_PTR sp, sp, (C_ABI_SAVE_AREA_SIZE + SI_MAX_SIZE + UC_SIZE)
177
cfi_def_cfa_offset (0)
191
weak_alias (__setcontext, setcontext)
193
ENTRY (__startcontext)
194
FEEDBACK_ENTER(__startcontext)
200
1: j HIDDEN_JUMPTARGET(exit)
202
.hidden __startcontext