diff options
Diffstat (limited to 'arch/xtensa/kernel')
-rw-r--r-- | arch/xtensa/kernel/asm-offsets.c | 1 | ||||
-rw-r--r-- | arch/xtensa/kernel/entry.S | 12 | ||||
-rw-r--r-- | arch/xtensa/kernel/process.c | 5 | ||||
-rw-r--r-- | arch/xtensa/kernel/ptrace.c | 2 | ||||
-rw-r--r-- | arch/xtensa/kernel/signal.c | 6 |
5 files changed, 21 insertions, 5 deletions
diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c index 0701fad170db..1915c7c889ba 100644 --- a/arch/xtensa/kernel/asm-offsets.c +++ b/arch/xtensa/kernel/asm-offsets.c | |||
@@ -42,6 +42,7 @@ int main(void) | |||
42 | DEFINE(PT_ICOUNTLEVEL, offsetof (struct pt_regs, icountlevel)); | 42 | DEFINE(PT_ICOUNTLEVEL, offsetof (struct pt_regs, icountlevel)); |
43 | DEFINE(PT_SYSCALL, offsetof (struct pt_regs, syscall)); | 43 | DEFINE(PT_SYSCALL, offsetof (struct pt_regs, syscall)); |
44 | DEFINE(PT_SCOMPARE1, offsetof(struct pt_regs, scompare1)); | 44 | DEFINE(PT_SCOMPARE1, offsetof(struct pt_regs, scompare1)); |
45 | DEFINE(PT_THREADPTR, offsetof(struct pt_regs, threadptr)); | ||
45 | DEFINE(PT_AREG, offsetof (struct pt_regs, areg[0])); | 46 | DEFINE(PT_AREG, offsetof (struct pt_regs, areg[0])); |
46 | DEFINE(PT_AREG0, offsetof (struct pt_regs, areg[0])); | 47 | DEFINE(PT_AREG0, offsetof (struct pt_regs, areg[0])); |
47 | DEFINE(PT_AREG1, offsetof (struct pt_regs, areg[1])); | 48 | DEFINE(PT_AREG1, offsetof (struct pt_regs, areg[1])); |
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 70d5a9e33573..63845f950792 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S | |||
@@ -130,6 +130,11 @@ _user_exception: | |||
130 | s32i a3, a1, PT_SAR | 130 | s32i a3, a1, PT_SAR |
131 | s32i a2, a1, PT_ICOUNTLEVEL | 131 | s32i a2, a1, PT_ICOUNTLEVEL |
132 | 132 | ||
133 | #if XCHAL_HAVE_THREADPTR | ||
134 | rur a2, threadptr | ||
135 | s32i a2, a1, PT_THREADPTR | ||
136 | #endif | ||
137 | |||
133 | /* Rotate ws so that the current windowbase is at bit0. */ | 138 | /* Rotate ws so that the current windowbase is at bit0. */ |
134 | /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */ | 139 | /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */ |
135 | 140 | ||
@@ -510,6 +515,11 @@ user_exception_exit: | |||
510 | * (if we have restored WSBITS-1 frames). | 515 | * (if we have restored WSBITS-1 frames). |
511 | */ | 516 | */ |
512 | 517 | ||
518 | #if XCHAL_HAVE_THREADPTR | ||
519 | l32i a3, a1, PT_THREADPTR | ||
520 | wur a3, threadptr | ||
521 | #endif | ||
522 | |||
513 | 2: j common_exception_exit | 523 | 2: j common_exception_exit |
514 | 524 | ||
515 | /* This is the kernel exception exit. | 525 | /* This is the kernel exception exit. |
@@ -1955,7 +1965,7 @@ ENTRY(_switch_to) | |||
1955 | s32i a6, a3, EXC_TABLE_FIXUP | 1965 | s32i a6, a3, EXC_TABLE_FIXUP |
1956 | s32i a7, a3, EXC_TABLE_KSTK | 1966 | s32i a7, a3, EXC_TABLE_KSTK |
1957 | 1967 | ||
1958 | /* restore context of the task that 'next' addresses */ | 1968 | /* restore context of the task 'next' */ |
1959 | 1969 | ||
1960 | l32i a0, a13, THREAD_RA # restore return address | 1970 | l32i a0, a13, THREAD_RA # restore return address |
1961 | l32i a1, a13, THREAD_SP # restore stack pointer | 1971 | l32i a1, a13, THREAD_SP # restore stack pointer |
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 0dd5784416d3..5cd82e9f601c 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c | |||
@@ -259,9 +259,10 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, | |||
259 | memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4], | 259 | memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4], |
260 | ®s->areg[XCHAL_NUM_AREGS - len/4], len); | 260 | ®s->areg[XCHAL_NUM_AREGS - len/4], len); |
261 | } | 261 | } |
262 | // FIXME: we need to set THREADPTR in thread_info... | 262 | |
263 | /* The thread pointer is passed in the '4th argument' (= a5) */ | ||
263 | if (clone_flags & CLONE_SETTLS) | 264 | if (clone_flags & CLONE_SETTLS) |
264 | childregs->areg[2] = childregs->areg[6]; | 265 | childregs->threadptr = childregs->areg[5]; |
265 | } else { | 266 | } else { |
266 | p->thread.ra = MAKE_RA_FOR_CALL( | 267 | p->thread.ra = MAKE_RA_FOR_CALL( |
267 | (unsigned long)ret_from_kernel_thread, 1); | 268 | (unsigned long)ret_from_kernel_thread, 1); |
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c index a8b0d5795571..562fac664751 100644 --- a/arch/xtensa/kernel/ptrace.c +++ b/arch/xtensa/kernel/ptrace.c | |||
@@ -66,6 +66,7 @@ int ptrace_getregs(struct task_struct *child, void __user *uregs) | |||
66 | __put_user(regs->lcount, &gregset->lcount); | 66 | __put_user(regs->lcount, &gregset->lcount); |
67 | __put_user(regs->windowstart, &gregset->windowstart); | 67 | __put_user(regs->windowstart, &gregset->windowstart); |
68 | __put_user(regs->windowbase, &gregset->windowbase); | 68 | __put_user(regs->windowbase, &gregset->windowbase); |
69 | __put_user(regs->threadptr, &gregset->threadptr); | ||
69 | 70 | ||
70 | for (i = 0; i < XCHAL_NUM_AREGS; i++) | 71 | for (i = 0; i < XCHAL_NUM_AREGS; i++) |
71 | __put_user(regs->areg[i], | 72 | __put_user(regs->areg[i], |
@@ -92,6 +93,7 @@ int ptrace_setregs(struct task_struct *child, void __user *uregs) | |||
92 | __get_user(regs->lcount, &gregset->lcount); | 93 | __get_user(regs->lcount, &gregset->lcount); |
93 | __get_user(ws, &gregset->windowstart); | 94 | __get_user(ws, &gregset->windowstart); |
94 | __get_user(wb, &gregset->windowbase); | 95 | __get_user(wb, &gregset->windowbase); |
96 | __get_user(regs->threadptr, &gregset->threadptr); | ||
95 | 97 | ||
96 | regs->ps = (regs->ps & ~ps_mask) | (ps & ps_mask) | (1 << PS_EXCM_BIT); | 98 | regs->ps = (regs->ps & ~ps_mask) | (ps & ps_mask) | (1 << PS_EXCM_BIT); |
97 | 99 | ||
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c index de34d6be91cd..6952d8959236 100644 --- a/arch/xtensa/kernel/signal.c +++ b/arch/xtensa/kernel/signal.c | |||
@@ -337,7 +337,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
337 | struct rt_sigframe *frame; | 337 | struct rt_sigframe *frame; |
338 | int err = 0; | 338 | int err = 0; |
339 | int signal; | 339 | int signal; |
340 | unsigned long sp, ra; | 340 | unsigned long sp, ra, tp; |
341 | 341 | ||
342 | sp = regs->areg[1]; | 342 | sp = regs->areg[1]; |
343 | 343 | ||
@@ -395,7 +395,8 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
395 | * Return context not modified until this point. | 395 | * Return context not modified until this point. |
396 | */ | 396 | */ |
397 | 397 | ||
398 | /* Set up registers for signal handler */ | 398 | /* Set up registers for signal handler; preserve the threadptr */ |
399 | tp = regs->threadptr; | ||
399 | start_thread(regs, (unsigned long) ka->sa.sa_handler, | 400 | start_thread(regs, (unsigned long) ka->sa.sa_handler, |
400 | (unsigned long) frame); | 401 | (unsigned long) frame); |
401 | 402 | ||
@@ -406,6 +407,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
406 | regs->areg[6] = (unsigned long) signal; | 407 | regs->areg[6] = (unsigned long) signal; |
407 | regs->areg[7] = (unsigned long) &frame->info; | 408 | regs->areg[7] = (unsigned long) &frame->info; |
408 | regs->areg[8] = (unsigned long) &frame->uc; | 409 | regs->areg[8] = (unsigned long) &frame->uc; |
410 | regs->threadptr = tp; | ||
409 | 411 | ||
410 | /* Set access mode to USER_DS. Nomenclature is outdated, but | 412 | /* Set access mode to USER_DS. Nomenclature is outdated, but |
411 | * functionality is used in uaccess.h | 413 | * functionality is used in uaccess.h |