| .. | .. |
|---|
| 37 | 37 | #include <linux/slab.h> |
|---|
| 38 | 38 | #include <linux/rcupdate.h> |
|---|
| 39 | 39 | |
|---|
| 40 | | -#include <asm/pgtable.h> |
|---|
| 41 | 40 | #include <linux/uaccess.h> |
|---|
| 42 | 41 | #include <asm/io.h> |
|---|
| 43 | 42 | #include <asm/processor.h> |
|---|
| .. | .. |
|---|
| 51 | 50 | |
|---|
| 52 | 51 | extern void ret_from_fork(void); |
|---|
| 53 | 52 | extern void ret_from_kernel_thread(void); |
|---|
| 54 | | - |
|---|
| 55 | | -struct task_struct *current_set[NR_CPUS] = {&init_task, }; |
|---|
| 56 | 53 | |
|---|
| 57 | 54 | void (*pm_power_off)(void) = NULL; |
|---|
| 58 | 55 | EXPORT_SYMBOL(pm_power_off); |
|---|
| .. | .. |
|---|
| 87 | 84 | } |
|---|
| 88 | 85 | |
|---|
| 89 | 86 | ti->cpenable = cpenable; |
|---|
| 90 | | - coprocessor_clear_cpenable(); |
|---|
| 87 | + if (ti == current_thread_info()) |
|---|
| 88 | + xtensa_set_sr(0, cpenable); |
|---|
| 91 | 89 | |
|---|
| 92 | 90 | preempt_enable(); |
|---|
| 93 | 91 | } |
|---|
| .. | .. |
|---|
| 99 | 97 | |
|---|
| 100 | 98 | preempt_disable(); |
|---|
| 101 | 99 | |
|---|
| 102 | | - RSR_CPENABLE(old_cpenable); |
|---|
| 100 | + old_cpenable = xtensa_get_sr(cpenable); |
|---|
| 103 | 101 | cpenable = ti->cpenable; |
|---|
| 104 | | - WSR_CPENABLE(cpenable); |
|---|
| 102 | + xtensa_set_sr(cpenable, cpenable); |
|---|
| 105 | 103 | |
|---|
| 106 | 104 | for (i = 0; i < XCHAL_CP_MAX; i++) { |
|---|
| 107 | 105 | if ((cpenable & 1) != 0 && coprocessor_owner[i] == ti) |
|---|
| 108 | 106 | coprocessor_flush(ti, i); |
|---|
| 109 | 107 | cpenable >>= 1; |
|---|
| 110 | 108 | } |
|---|
| 111 | | - WSR_CPENABLE(old_cpenable); |
|---|
| 109 | + xtensa_set_sr(old_cpenable, cpenable); |
|---|
| 112 | 110 | |
|---|
| 113 | 111 | preempt_enable(); |
|---|
| 114 | 112 | } |
|---|
| .. | .. |
|---|
| 204 | 202 | */ |
|---|
| 205 | 203 | |
|---|
| 206 | 204 | int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, |
|---|
| 207 | | - unsigned long thread_fn_arg, struct task_struct *p) |
|---|
| 205 | + unsigned long thread_fn_arg, struct task_struct *p, |
|---|
| 206 | + unsigned long tls) |
|---|
| 208 | 207 | { |
|---|
| 209 | 208 | struct pt_regs *childregs = task_pt_regs(p); |
|---|
| 210 | 209 | |
|---|
| .. | .. |
|---|
| 218 | 217 | |
|---|
| 219 | 218 | p->thread.sp = (unsigned long)childregs; |
|---|
| 220 | 219 | |
|---|
| 221 | | - if (!(p->flags & PF_KTHREAD)) { |
|---|
| 220 | + if (!(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { |
|---|
| 222 | 221 | struct pt_regs *regs = current_pt_regs(); |
|---|
| 223 | 222 | unsigned long usp = usp_thread_fn ? |
|---|
| 224 | 223 | usp_thread_fn : regs->areg[1]; |
|---|
| .. | .. |
|---|
| 265 | 264 | ®s->areg[XCHAL_NUM_AREGS - len/4], len); |
|---|
| 266 | 265 | } |
|---|
| 267 | 266 | |
|---|
| 268 | | - /* The thread pointer is passed in the '4th argument' (= a5) */ |
|---|
| 267 | + childregs->syscall = regs->syscall; |
|---|
| 268 | + |
|---|
| 269 | 269 | if (clone_flags & CLONE_SETTLS) |
|---|
| 270 | | - childregs->threadptr = childregs->areg[5]; |
|---|
| 270 | + childregs->threadptr = tls; |
|---|
| 271 | 271 | } else { |
|---|
| 272 | 272 | p->thread.ra = MAKE_RA_FOR_CALL( |
|---|
| 273 | 273 | (unsigned long)ret_from_kernel_thread, 1); |
|---|
| .. | .. |
|---|
| 323 | 323 | pc = MAKE_PC_FROM_RA(SPILL_SLOT(sp, 0), sp); |
|---|
| 324 | 324 | sp = SPILL_SLOT(sp, 1); |
|---|
| 325 | 325 | } while (count++ < 16); |
|---|
| 326 | | - return 0; |
|---|
| 327 | | -} |
|---|
| 328 | | - |
|---|
| 329 | | -/* |
|---|
| 330 | | - * xtensa_gregset_t and 'struct pt_regs' are vastly different formats |
|---|
| 331 | | - * of processor registers. Besides different ordering, |
|---|
| 332 | | - * xtensa_gregset_t contains non-live register information that |
|---|
| 333 | | - * 'struct pt_regs' does not. Exception handling (primarily) uses |
|---|
| 334 | | - * 'struct pt_regs'. Core files and ptrace use xtensa_gregset_t. |
|---|
| 335 | | - * |
|---|
| 336 | | - */ |
|---|
| 337 | | - |
|---|
| 338 | | -void xtensa_elf_core_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs) |
|---|
| 339 | | -{ |
|---|
| 340 | | - unsigned long wb, ws, wm; |
|---|
| 341 | | - int live, last; |
|---|
| 342 | | - |
|---|
| 343 | | - wb = regs->windowbase; |
|---|
| 344 | | - ws = regs->windowstart; |
|---|
| 345 | | - wm = regs->wmask; |
|---|
| 346 | | - ws = ((ws >> wb) | (ws << (WSBITS - wb))) & ((1 << WSBITS) - 1); |
|---|
| 347 | | - |
|---|
| 348 | | - /* Don't leak any random bits. */ |
|---|
| 349 | | - |
|---|
| 350 | | - memset(elfregs, 0, sizeof(*elfregs)); |
|---|
| 351 | | - |
|---|
| 352 | | - /* Note: PS.EXCM is not set while user task is running; its |
|---|
| 353 | | - * being set in regs->ps is for exception handling convenience. |
|---|
| 354 | | - */ |
|---|
| 355 | | - |
|---|
| 356 | | - elfregs->pc = regs->pc; |
|---|
| 357 | | - elfregs->ps = (regs->ps & ~(1 << PS_EXCM_BIT)); |
|---|
| 358 | | - elfregs->lbeg = regs->lbeg; |
|---|
| 359 | | - elfregs->lend = regs->lend; |
|---|
| 360 | | - elfregs->lcount = regs->lcount; |
|---|
| 361 | | - elfregs->sar = regs->sar; |
|---|
| 362 | | - elfregs->windowstart = ws; |
|---|
| 363 | | - |
|---|
| 364 | | - live = (wm & 2) ? 4 : (wm & 4) ? 8 : (wm & 8) ? 12 : 16; |
|---|
| 365 | | - last = XCHAL_NUM_AREGS - (wm >> 4) * 4; |
|---|
| 366 | | - memcpy(elfregs->a, regs->areg, live * 4); |
|---|
| 367 | | - memcpy(elfregs->a + last, regs->areg + last, (wm >> 4) * 16); |
|---|
| 368 | | -} |
|---|
| 369 | | - |
|---|
| 370 | | -int dump_fpu(void) |
|---|
| 371 | | -{ |
|---|
| 372 | 326 | return 0; |
|---|
| 373 | 327 | } |
|---|