| .. | .. |
|---|
| 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); |
|---|