diff options
Diffstat (limited to 'arch/parisc/kernel/process.c')
-rw-r--r-- | arch/parisc/kernel/process.c | 145 |
1 files changed, 51 insertions, 94 deletions
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index ecc5c2771208..ed93bd8c1545 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -17,9 +17,6 @@ * Copyright (C) 2001-2014 Helge Deller <deller@gmx.de> * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org> */ - -#include <stdarg.h> - #include <linux/elf.h> #include <linux/errno.h> #include <linux/kernel.h> @@ -29,6 +26,7 @@ #include <linux/module.h> #include <linux/personality.h> #include <linux/ptrace.h> +#include <linux/reboot.h> #include <linux/sched.h> #include <linux/sched/debug.h> #include <linux/sched/task.h> @@ -41,15 +39,16 @@ #include <linux/rcupdate.h> #include <linux/random.h> #include <linux/nmi.h> +#include <linux/sched/hotplug.h> #include <asm/io.h> #include <asm/asm-offsets.h> #include <asm/assembly.h> #include <asm/pdc.h> #include <asm/pdc_chassis.h> -#include <asm/pgalloc.h> #include <asm/unwind.h> #include <asm/sections.h> +#include <asm/cacheflush.h> #define COMMAND_GLOBAL F_EXTEND(0xfffe0030) #define CMD_RESET 5 /* reset any module */ @@ -98,18 +97,12 @@ void machine_restart(char *cmd) } -void (*chassis_power_off)(void); - /* * This routine is called from sys_reboot to actually turn off the * machine */ void machine_power_off(void) { - /* If there is a registered power off handler, call it. */ - if (chassis_power_off) - chassis_power_off(); - /* Put the soft power button back under hardware control. * If the user had already pressed the power button, the * following call will immediately power off. */ @@ -118,19 +111,23 @@ void machine_power_off(void) pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN); /* ipmi_poweroff may have been installed. */ - if (pm_power_off) - pm_power_off(); + do_kernel_power_off(); /* It seems we have no way to power the system off via * software. The user has to press the button himself. */ - printk(KERN_EMERG "System shut down completed.\n" - "Please power this system off now."); + printk("Power off or press RETURN to reboot.\n"); /* prevent soft lockup/stalled CPU messages for endless loop. */ rcu_sysrq_start(); lockup_detector_soft_poweroff(); - for (;;); + while (1) { + /* reboot if user presses RETURN key */ + if (pdc_iodc_getc() == 13) { + printk("Rebooting...\n"); + machine_restart(NULL); + } + } } void (*pm_power_off)(void); @@ -148,29 +145,6 @@ void flush_thread(void) */ } -void release_thread(struct task_struct *dead_task) -{ -} - -/* - * Fill in the FPU structure for a core dump. - */ - -int dump_fpu (struct pt_regs * regs, elf_fpregset_t *r) -{ - if (regs == NULL) - return 0; - - memcpy(r, regs->fr, sizeof *r); - return 1; -} - -int dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *r) -{ - memcpy(r, tsk->thread.regs.fr, sizeof(*r)); - return 1; -} - /* * Idle thread support * @@ -181,16 +155,33 @@ int dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *r) int running_on_qemu __ro_after_init; EXPORT_SYMBOL(running_on_qemu); -void __cpuidle arch_cpu_idle_dead(void) +/* + * Called from the idle thread for the CPU which has been shutdown. + */ +void __noreturn arch_cpu_idle_dead(void) { - /* nop on real hardware, qemu will offline CPU. */ - asm volatile("or %%r31,%%r31,%%r31\n":::); +#ifdef CONFIG_HOTPLUG_CPU + idle_task_exit(); + + local_irq_disable(); + + /* Tell the core that this CPU is now safe to dispose of. */ + cpuhp_ap_report_dead(); + + /* Ensure that the cache lines are written out. */ + flush_cache_all_local(); + flush_tlb_all_local(NULL); + + /* Let PDC firmware put CPU into firmware idle loop. */ + __pdc_cpu_rendezvous(); + + pr_warn("PDC does not provide rendezvous function.\n"); +#endif + while (1); } void __cpuidle arch_cpu_idle(void) { - local_irq_enable(); - /* nop on real hardware, qemu will idle sleep. */ asm volatile("or %%r10,%%r10,%%r10\n":::); } @@ -208,9 +199,11 @@ arch_initcall(parisc_idle_init); * Copy architecture-specific thread state */ int -copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long kthread_arg, struct task_struct *p) +copy_thread(struct task_struct *p, const struct kernel_clone_args *args) { + unsigned long clone_flags = args->flags; + unsigned long usp = args->stack; + unsigned long tls = args->tls; struct pt_regs *cregs = &(p->thread.regs); void *stack = task_stack_page(p); @@ -220,27 +213,27 @@ copy_thread(unsigned long clone_flags, unsigned long usp, extern void * const ret_from_kernel_thread; extern void * const child_return; - if (unlikely(p->flags & PF_KTHREAD)) { + if (unlikely(args->fn)) { /* kernel thread */ memset(cregs, 0, sizeof(struct pt_regs)); - if (!usp) /* idle thread */ + if (args->idle) /* idle thread */ return 0; /* Must exit via ret_from_kernel_thread in order * to call schedule_tail() */ - cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE; + cregs->ksp = (unsigned long) stack + FRAME_SIZE + PT_SZ_ALGN; cregs->kpc = (unsigned long) &ret_from_kernel_thread; /* * Copy function and argument to be called from * ret_from_kernel_thread. */ #ifdef CONFIG_64BIT - cregs->gr[27] = ((unsigned long *)usp)[3]; - cregs->gr[26] = ((unsigned long *)usp)[2]; + cregs->gr[27] = ((unsigned long *)args->fn)[3]; + cregs->gr[26] = ((unsigned long *)args->fn)[2]; #else - cregs->gr[26] = usp; + cregs->gr[26] = (unsigned long) args->fn; #endif - cregs->gr[25] = kthread_arg; + cregs->gr[25] = (unsigned long) args->fn_arg; } else { /* user thread */ /* usp must be word aligned. This also prevents users from @@ -251,27 +244,24 @@ copy_thread(unsigned long clone_flags, unsigned long usp, if (likely(usp)) cregs->gr[30] = usp; } - cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE; + cregs->ksp = (unsigned long) stack + FRAME_SIZE; cregs->kpc = (unsigned long) &child_return; - /* Setup thread TLS area from the 4th parameter in clone */ + /* Setup thread TLS area */ if (clone_flags & CLONE_SETTLS) - cregs->cr27 = cregs->gr[23]; + cregs->cr27 = tls; } return 0; } unsigned long -get_wchan(struct task_struct *p) +__get_wchan(struct task_struct *p) { struct unwind_frame_info info; unsigned long ip; int count = 0; - if (!p || p == current || p->state == TASK_RUNNING) - return 0; - /* * These bracket the sleeping functions.. */ @@ -280,44 +270,11 @@ get_wchan(struct task_struct *p) do { if (unwind_once(&info) < 0) return 0; + if (task_is_running(p)) + return 0; ip = info.ip; if (!in_sched_functions(ip)) return ip; } while (count++ < MAX_UNWIND_ENTRIES); return 0; } - -#ifdef CONFIG_64BIT -void *dereference_function_descriptor(void *ptr) -{ - Elf64_Fdesc *desc = ptr; - void *p; - - if (!probe_kernel_address(&desc->addr, p)) - ptr = p; - return ptr; -} - -void *dereference_kernel_function_descriptor(void *ptr) -{ - if (ptr < (void *)__start_opd || - ptr >= (void *)__end_opd) - return ptr; - - return dereference_function_descriptor(ptr); -} -#endif - -static inline unsigned long brk_rnd(void) -{ - return (get_random_int() & BRK_RND_MASK) << PAGE_SHIFT; -} - -unsigned long arch_randomize_brk(struct mm_struct *mm) -{ - unsigned long ret = PAGE_ALIGN(mm->brk + brk_rnd()); - - if (ret < mm->brk) - return mm->brk; - return ret; -} |