.. | .. |
---|
40 | 40 | #include <asm/elf.h> |
---|
41 | 41 | #include <asm/irq.h> |
---|
42 | 42 | #include <asm/kexec.h> |
---|
43 | | -#include <asm/pgalloc.h> |
---|
44 | 43 | #include <asm/processor.h> |
---|
45 | 44 | #include <asm/sal.h> |
---|
46 | 45 | #include <asm/switch_to.h> |
---|
.. | .. |
---|
48 | 47 | #include <linux/uaccess.h> |
---|
49 | 48 | #include <asm/unwind.h> |
---|
50 | 49 | #include <asm/user.h> |
---|
| 50 | +#include <asm/xtp.h> |
---|
51 | 51 | |
---|
52 | 52 | #include "entry.h" |
---|
53 | | - |
---|
54 | | -#ifdef CONFIG_PERFMON |
---|
55 | | -# include <asm/perfmon.h> |
---|
56 | | -#endif |
---|
57 | 53 | |
---|
58 | 54 | #include "sigframe.h" |
---|
59 | 55 | |
---|
.. | .. |
---|
64 | 60 | void (*pm_power_off) (void); |
---|
65 | 61 | EXPORT_SYMBOL(pm_power_off); |
---|
66 | 62 | |
---|
67 | | -void |
---|
| 63 | +static void |
---|
68 | 64 | ia64_do_show_stack (struct unw_frame_info *info, void *arg) |
---|
69 | 65 | { |
---|
70 | 66 | unsigned long ip, sp, bsp; |
---|
| 67 | + const char *loglvl = arg; |
---|
71 | 68 | |
---|
72 | | - printk("\nCall Trace:\n"); |
---|
| 69 | + printk("%s\nCall Trace:\n", loglvl); |
---|
73 | 70 | do { |
---|
74 | 71 | unw_get_ip(info, &ip); |
---|
75 | 72 | if (ip == 0) |
---|
.. | .. |
---|
77 | 74 | |
---|
78 | 75 | unw_get_sp(info, &sp); |
---|
79 | 76 | unw_get_bsp(info, &bsp); |
---|
80 | | - printk(" [<%016lx>] %pS\n" |
---|
| 77 | + printk("%s [<%016lx>] %pS\n" |
---|
81 | 78 | " sp=%016lx bsp=%016lx\n", |
---|
82 | | - ip, (void *)ip, sp, bsp); |
---|
| 79 | + loglvl, ip, (void *)ip, sp, bsp); |
---|
83 | 80 | } while (unw_unwind(info) >= 0); |
---|
84 | 81 | } |
---|
85 | 82 | |
---|
86 | 83 | void |
---|
87 | | -show_stack (struct task_struct *task, unsigned long *sp) |
---|
| 84 | +show_stack (struct task_struct *task, unsigned long *sp, const char *loglvl) |
---|
88 | 85 | { |
---|
89 | 86 | if (!task) |
---|
90 | | - unw_init_running(ia64_do_show_stack, NULL); |
---|
| 87 | + unw_init_running(ia64_do_show_stack, (void *)loglvl); |
---|
91 | 88 | else { |
---|
92 | 89 | struct unw_frame_info info; |
---|
93 | 90 | |
---|
94 | 91 | unw_init_from_blocked_task(&info, task); |
---|
95 | | - ia64_do_show_stack(&info, NULL); |
---|
| 92 | + ia64_do_show_stack(&info, (void *)loglvl); |
---|
96 | 93 | } |
---|
97 | 94 | } |
---|
98 | 95 | |
---|
.. | .. |
---|
150 | 147 | ((i == sof - 1) || (i % 3) == 2) ? "\n" : " "); |
---|
151 | 148 | } |
---|
152 | 149 | } else |
---|
153 | | - show_stack(NULL, NULL); |
---|
| 150 | + show_stack(NULL, NULL, KERN_DEFAULT); |
---|
154 | 151 | } |
---|
155 | 152 | |
---|
156 | 153 | /* local support for deprecated console_print */ |
---|
.. | .. |
---|
173 | 170 | return; |
---|
174 | 171 | } |
---|
175 | 172 | |
---|
176 | | -#ifdef CONFIG_PERFMON |
---|
177 | | - if (current->thread.pfm_needs_checking) |
---|
178 | | - /* |
---|
179 | | - * Note: pfm_handle_work() allow us to call it with interrupts |
---|
180 | | - * disabled, and may enable interrupts within the function. |
---|
181 | | - */ |
---|
182 | | - pfm_handle_work(); |
---|
183 | | -#endif |
---|
184 | | - |
---|
185 | 173 | /* deal with pending signal delivery */ |
---|
186 | | - if (test_thread_flag(TIF_SIGPENDING)) { |
---|
| 174 | + if (test_thread_flag(TIF_SIGPENDING) || |
---|
| 175 | + test_thread_flag(TIF_NOTIFY_SIGNAL)) { |
---|
187 | 176 | local_irq_enable(); /* force interrupt enable */ |
---|
188 | 177 | ia64_do_signal(scr, in_syscall); |
---|
189 | 178 | } |
---|
190 | 179 | |
---|
191 | | - if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) { |
---|
| 180 | + if (test_thread_flag(TIF_NOTIFY_RESUME)) { |
---|
192 | 181 | local_irq_enable(); /* force interrupt enable */ |
---|
193 | 182 | tracehook_notify_resume(&scr->pt); |
---|
194 | 183 | } |
---|
.. | .. |
---|
251 | 240 | if (mark_idle) |
---|
252 | 241 | (*mark_idle)(1); |
---|
253 | 242 | |
---|
254 | | - safe_halt(); |
---|
| 243 | + raw_safe_halt(); |
---|
255 | 244 | |
---|
256 | 245 | if (mark_idle) |
---|
257 | 246 | (*mark_idle)(0); |
---|
.. | .. |
---|
263 | 252 | void |
---|
264 | 253 | ia64_save_extra (struct task_struct *task) |
---|
265 | 254 | { |
---|
266 | | -#ifdef CONFIG_PERFMON |
---|
267 | | - unsigned long info; |
---|
268 | | -#endif |
---|
269 | | - |
---|
270 | 255 | if ((task->thread.flags & IA64_THREAD_DBG_VALID) != 0) |
---|
271 | 256 | ia64_save_debug_regs(&task->thread.dbr[0]); |
---|
272 | | - |
---|
273 | | -#ifdef CONFIG_PERFMON |
---|
274 | | - if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0) |
---|
275 | | - pfm_save_regs(task); |
---|
276 | | - |
---|
277 | | - info = __this_cpu_read(pfm_syst_info); |
---|
278 | | - if (info & PFM_CPUINFO_SYST_WIDE) |
---|
279 | | - pfm_syst_wide_update_task(task, info, 0); |
---|
280 | | -#endif |
---|
281 | 257 | } |
---|
282 | 258 | |
---|
283 | 259 | void |
---|
284 | 260 | ia64_load_extra (struct task_struct *task) |
---|
285 | 261 | { |
---|
286 | | -#ifdef CONFIG_PERFMON |
---|
287 | | - unsigned long info; |
---|
288 | | -#endif |
---|
289 | | - |
---|
290 | 262 | if ((task->thread.flags & IA64_THREAD_DBG_VALID) != 0) |
---|
291 | 263 | ia64_load_debug_regs(&task->thread.dbr[0]); |
---|
292 | | - |
---|
293 | | -#ifdef CONFIG_PERFMON |
---|
294 | | - if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0) |
---|
295 | | - pfm_load_regs(task); |
---|
296 | | - |
---|
297 | | - info = __this_cpu_read(pfm_syst_info); |
---|
298 | | - if (info & PFM_CPUINFO_SYST_WIDE) |
---|
299 | | - pfm_syst_wide_update_task(task, info, 1); |
---|
300 | | -#endif |
---|
301 | 264 | } |
---|
302 | 265 | |
---|
303 | 266 | /* |
---|
.. | .. |
---|
309 | 272 | * |
---|
310 | 273 | * <clone syscall> <some kernel call frames> |
---|
311 | 274 | * sys_clone : |
---|
312 | | - * do_fork do_fork |
---|
| 275 | + * kernel_clone kernel_clone |
---|
313 | 276 | * copy_thread copy_thread |
---|
314 | 277 | * |
---|
315 | 278 | * This means that the stack layout is as follows: |
---|
.. | .. |
---|
332 | 295 | * so there is nothing to worry about. |
---|
333 | 296 | */ |
---|
334 | 297 | int |
---|
335 | | -copy_thread(unsigned long clone_flags, |
---|
336 | | - unsigned long user_stack_base, unsigned long user_stack_size, |
---|
337 | | - struct task_struct *p) |
---|
| 298 | +copy_thread(unsigned long clone_flags, unsigned long user_stack_base, |
---|
| 299 | + unsigned long user_stack_size, struct task_struct *p, unsigned long tls) |
---|
338 | 300 | { |
---|
339 | 301 | extern char ia64_ret_from_clone; |
---|
340 | 302 | struct switch_stack *child_stack, *stack; |
---|
.. | .. |
---|
376 | 338 | |
---|
377 | 339 | ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */ |
---|
378 | 340 | |
---|
379 | | - if (unlikely(p->flags & PF_KTHREAD)) { |
---|
| 341 | + if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { |
---|
380 | 342 | if (unlikely(!user_stack_base)) { |
---|
381 | 343 | /* fork_idle() called us */ |
---|
382 | 344 | return 0; |
---|
.. | .. |
---|
415 | 377 | rbs_size = stack->ar_bspstore - rbs; |
---|
416 | 378 | memcpy((void *) child_rbs, (void *) rbs, rbs_size); |
---|
417 | 379 | if (clone_flags & CLONE_SETTLS) |
---|
418 | | - child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */ |
---|
| 380 | + child_ptregs->r13 = tls; |
---|
419 | 381 | if (user_stack_base) { |
---|
420 | 382 | child_ptregs->r12 = user_stack_base + user_stack_size - 16; |
---|
421 | 383 | child_ptregs->ar_bspstore = user_stack_base; |
---|
.. | .. |
---|
432 | 394 | */ |
---|
433 | 395 | child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) |
---|
434 | 396 | & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); |
---|
435 | | - |
---|
436 | | -#ifdef CONFIG_PERFMON |
---|
437 | | - if (current->thread.pfm_context) |
---|
438 | | - pfm_inherit(p, child_ptregs); |
---|
439 | | -#endif |
---|
440 | 397 | return retval; |
---|
| 398 | +} |
---|
| 399 | + |
---|
| 400 | +asmlinkage long ia64_clone(unsigned long clone_flags, unsigned long stack_start, |
---|
| 401 | + unsigned long stack_size, unsigned long parent_tidptr, |
---|
| 402 | + unsigned long child_tidptr, unsigned long tls) |
---|
| 403 | +{ |
---|
| 404 | + struct kernel_clone_args args = { |
---|
| 405 | + .flags = (lower_32_bits(clone_flags) & ~CSIGNAL), |
---|
| 406 | + .pidfd = (int __user *)parent_tidptr, |
---|
| 407 | + .child_tid = (int __user *)child_tidptr, |
---|
| 408 | + .parent_tid = (int __user *)parent_tidptr, |
---|
| 409 | + .exit_signal = (lower_32_bits(clone_flags) & CSIGNAL), |
---|
| 410 | + .stack = stack_start, |
---|
| 411 | + .stack_size = stack_size, |
---|
| 412 | + .tls = tls, |
---|
| 413 | + }; |
---|
| 414 | + |
---|
| 415 | + return kernel_clone(&args); |
---|
441 | 416 | } |
---|
442 | 417 | |
---|
443 | 418 | static void |
---|
444 | 419 | do_copy_task_regs (struct task_struct *task, struct unw_frame_info *info, void *arg) |
---|
445 | 420 | { |
---|
446 | 421 | unsigned long mask, sp, nat_bits = 0, ar_rnat, urbs_end, cfm; |
---|
447 | | - unsigned long uninitialized_var(ip); /* GCC be quiet */ |
---|
| 422 | + unsigned long ip; |
---|
448 | 423 | elf_greg_t *dst = arg; |
---|
449 | 424 | struct pt_regs *pt; |
---|
450 | 425 | char nat; |
---|
.. | .. |
---|
514 | 489 | } |
---|
515 | 490 | |
---|
516 | 491 | void |
---|
517 | | -do_dump_task_fpu (struct task_struct *task, struct unw_frame_info *info, void *arg) |
---|
518 | | -{ |
---|
519 | | - elf_fpreg_t *dst = arg; |
---|
520 | | - int i; |
---|
521 | | - |
---|
522 | | - memset(dst, 0, sizeof(elf_fpregset_t)); /* don't leak any "random" bits */ |
---|
523 | | - |
---|
524 | | - if (unw_unwind_to_user(info) < 0) |
---|
525 | | - return; |
---|
526 | | - |
---|
527 | | - /* f0 is 0.0, f1 is 1.0 */ |
---|
528 | | - |
---|
529 | | - for (i = 2; i < 32; ++i) |
---|
530 | | - unw_get_fr(info, i, dst + i); |
---|
531 | | - |
---|
532 | | - ia64_flush_fph(task); |
---|
533 | | - if ((task->thread.flags & IA64_THREAD_FPH_VALID) != 0) |
---|
534 | | - memcpy(dst + 32, task->thread.fph, 96*16); |
---|
535 | | -} |
---|
536 | | - |
---|
537 | | -void |
---|
538 | 492 | do_copy_regs (struct unw_frame_info *info, void *arg) |
---|
539 | 493 | { |
---|
540 | 494 | do_copy_task_regs(current, info, arg); |
---|
541 | 495 | } |
---|
542 | 496 | |
---|
543 | 497 | void |
---|
544 | | -do_dump_fpu (struct unw_frame_info *info, void *arg) |
---|
545 | | -{ |
---|
546 | | - do_dump_task_fpu(current, info, arg); |
---|
547 | | -} |
---|
548 | | - |
---|
549 | | -void |
---|
550 | 498 | ia64_elf_core_copy_regs (struct pt_regs *pt, elf_gregset_t dst) |
---|
551 | 499 | { |
---|
552 | 500 | unw_init_running(do_copy_regs, dst); |
---|
553 | | -} |
---|
554 | | - |
---|
555 | | -int |
---|
556 | | -dump_fpu (struct pt_regs *pt, elf_fpregset_t dst) |
---|
557 | | -{ |
---|
558 | | - unw_init_running(do_dump_fpu, dst); |
---|
559 | | - return 1; /* f0-f31 are always valid so we always return 1 */ |
---|
560 | 501 | } |
---|
561 | 502 | |
---|
562 | 503 | /* |
---|
.. | .. |
---|
579 | 520 | { |
---|
580 | 521 | |
---|
581 | 522 | ia64_drop_fpu(tsk); |
---|
582 | | -#ifdef CONFIG_PERFMON |
---|
583 | | - /* if needed, stop monitoring and flush state to perfmon context */ |
---|
584 | | - if (tsk->thread.pfm_context) |
---|
585 | | - pfm_exit_thread(tsk); |
---|
586 | | - |
---|
587 | | - /* free debug register resources */ |
---|
588 | | - if (tsk->thread.flags & IA64_THREAD_DBG_VALID) |
---|
589 | | - pfm_release_debug_registers(tsk); |
---|
590 | | -#endif |
---|
591 | 523 | } |
---|
592 | 524 | |
---|
593 | 525 | unsigned long |
---|
.. | .. |
---|
646 | 578 | |
---|
647 | 579 | void machine_shutdown(void) |
---|
648 | 580 | { |
---|
649 | | -#ifdef CONFIG_HOTPLUG_CPU |
---|
650 | | - int cpu; |
---|
| 581 | + smp_shutdown_nonboot_cpus(reboot_cpu); |
---|
651 | 582 | |
---|
652 | | - for_each_online_cpu(cpu) { |
---|
653 | | - if (cpu != smp_processor_id()) |
---|
654 | | - cpu_down(cpu); |
---|
655 | | - } |
---|
656 | | -#endif |
---|
657 | 583 | #ifdef CONFIG_KEXEC |
---|
658 | 584 | kexec_disable_iosapic(); |
---|
659 | 585 | #endif |
---|
.. | .. |
---|
681 | 607 | machine_halt(); |
---|
682 | 608 | } |
---|
683 | 609 | |
---|
| 610 | +EXPORT_SYMBOL(ia64_delay_loop); |
---|