aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/xtensa/kernel/process.c')
-rw-r--r--arch/xtensa/kernel/process.c63
1 files changed, 6 insertions, 57 deletions
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
index f53d7bd9dfb2..026138d641a4 100644
--- a/arch/xtensa/kernel/process.c
+++ b/arch/xtensa/kernel/process.c
@@ -194,51 +194,18 @@ unsigned long get_wchan(struct task_struct *p)
194void do_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs, 194void do_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs,
195 struct task_struct *tsk) 195 struct task_struct *tsk)
196{ 196{
197 int i, n, wb_offset;
198
199 elfregs->xchal_config_id0 = XCHAL_HW_CONFIGID0;
200 elfregs->xchal_config_id1 = XCHAL_HW_CONFIGID1;
201
202 __asm__ __volatile__ ("rsr %0, 176\n" : "=a" (i));
203 elfregs->cpux = i;
204 __asm__ __volatile__ ("rsr %0, 208\n" : "=a" (i));
205 elfregs->cpuy = i;
206
207 /* Note: PS.EXCM is not set while user task is running; its 197 /* Note: PS.EXCM is not set while user task is running; its
208 * being set in regs->ps is for exception handling convenience. 198 * being set in regs->ps is for exception handling convenience.
209 */ 199 */
210 200
211 elfregs->pc = regs->pc; 201 elfregs->pc = regs->pc;
212 elfregs->ps = (regs->ps & ~(1 << PS_EXCM_BIT)); 202 elfregs->ps = (regs->ps & ~(1 << PS_EXCM_BIT));
213 elfregs->exccause = regs->exccause;
214 elfregs->excvaddr = regs->excvaddr;
215 elfregs->windowbase = regs->windowbase;
216 elfregs->windowstart = regs->windowstart;
217 elfregs->lbeg = regs->lbeg; 203 elfregs->lbeg = regs->lbeg;
218 elfregs->lend = regs->lend; 204 elfregs->lend = regs->lend;
219 elfregs->lcount = regs->lcount; 205 elfregs->lcount = regs->lcount;
220 elfregs->sar = regs->sar; 206 elfregs->sar = regs->sar;
221 elfregs->syscall = regs->syscall;
222
223 /* Copy register file.
224 * The layout looks like this:
225 *
226 * | a0 ... a15 | Z ... Z | arX ... arY |
227 * current window unused saved frames
228 */
229
230 memset (elfregs->ar, 0, sizeof(elfregs->ar));
231
232 wb_offset = regs->windowbase * 4;
233 n = (regs->wmask&1)? 4 : (regs->wmask&2)? 8 : (regs->wmask&4)? 12 : 16;
234
235 for (i = 0; i < n; i++)
236 elfregs->ar[(wb_offset + i) % XCHAL_NUM_AREGS] = regs->areg[i];
237 207
238 n = (regs->wmask >> 4) * 4; 208 memcpy (elfregs->a, regs->areg, sizeof(elfregs->a));
239
240 for (i = XCHAL_NUM_AREGS - n; n > 0; i++, n--)
241 elfregs->ar[(wb_offset + i) % XCHAL_NUM_AREGS] = regs->areg[i];
242} 209}
243 210
244void xtensa_elf_core_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs) 211void xtensa_elf_core_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs)
@@ -252,40 +219,22 @@ void xtensa_elf_core_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs)
252void do_restore_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs, 219void do_restore_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs,
253 struct task_struct *tsk) 220 struct task_struct *tsk)
254{ 221{
255 int i, n, wb_offset; 222 const unsigned long ps_mask = PS_CALLINC_MASK | PS_OWB_MASK;
223 unsigned long ps;
256 224
257 /* Note: PS.EXCM is not set while user task is running; it 225 /* Note: PS.EXCM is not set while user task is running; it
258 * needs to be set in regs->ps is for exception handling convenience. 226 * needs to be set in regs->ps is for exception handling convenience.
259 */ 227 */
260 228
229 ps = (regs->ps & ~ps_mask) | (elfregs->ps & ps_mask) | (1<<PS_EXCM_BIT);
230 regs->ps = ps;
261 regs->pc = elfregs->pc; 231 regs->pc = elfregs->pc;
262 regs->ps = (elfregs->ps | (1 << PS_EXCM_BIT));
263 regs->exccause = elfregs->exccause;
264 regs->excvaddr = elfregs->excvaddr;
265 regs->windowbase = elfregs->windowbase;
266 regs->windowstart = elfregs->windowstart;
267 regs->lbeg = elfregs->lbeg; 232 regs->lbeg = elfregs->lbeg;
268 regs->lend = elfregs->lend; 233 regs->lend = elfregs->lend;
269 regs->lcount = elfregs->lcount; 234 regs->lcount = elfregs->lcount;
270 regs->sar = elfregs->sar; 235 regs->sar = elfregs->sar;
271 regs->syscall = elfregs->syscall;
272
273 /* Clear everything. */
274
275 memset (regs->areg, 0, sizeof(regs->areg));
276
277 /* Copy regs from live window frame. */
278
279 wb_offset = regs->windowbase * 4;
280 n = (regs->wmask&1)? 4 : (regs->wmask&2)? 8 : (regs->wmask&4)? 12 : 16;
281
282 for (i = 0; i < n; i++)
283 regs->areg[(wb_offset+i) % XCHAL_NUM_AREGS] = elfregs->ar[i];
284
285 n = (regs->wmask >> 4) * 4;
286 236
287 for (i = XCHAL_NUM_AREGS - n; n > 0; i++, n--) 237 memcpy (regs->areg, elfregs->a, sizeof(regs->areg));
288 regs->areg[(wb_offset+i) % XCHAL_NUM_AREGS] = elfregs->ar[i];
289} 238}
290 239
291/* 240/*