Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.17.
  1// SPDX-License-Identifier: GPL-2.0
  2// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
  3
  4#include <linux/module.h>
  5#include <linux/version.h>
  6#include <linux/sched.h>
  7#include <linux/sched/task_stack.h>
  8#include <linux/sched/debug.h>
  9#include <linux/delay.h>
 10#include <linux/kallsyms.h>
 11#include <linux/uaccess.h>
 12#include <linux/ptrace.h>
 13
 14#include <asm/elf.h>
 15#include <abi/reg_ops.h>
 16
 17struct cpuinfo_csky cpu_data[NR_CPUS];
 18
 19asmlinkage void ret_from_fork(void);
 20asmlinkage void ret_from_kernel_thread(void);
 21
 22/*
 23 * Some archs flush debug and FPU info here
 24 */
 25void flush_thread(void){}
 26
 27/*
 28 * Return saved PC from a blocked thread
 29 */
 30unsigned long thread_saved_pc(struct task_struct *tsk)
 31{
 32	struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
 33
 34	return sw->r15;
 35}
 36
 37int copy_thread(unsigned long clone_flags,
 38		unsigned long usp,
 39		unsigned long kthread_arg,
 40		struct task_struct *p)
 41{
 42	struct switch_stack *childstack;
 43	struct pt_regs *childregs = task_pt_regs(p);
 44
 45#ifdef CONFIG_CPU_HAS_FPU
 46	save_to_user_fp(&p->thread.user_fp);
 47#endif
 48
 49	childstack = ((struct switch_stack *) childregs) - 1;
 50	memset(childstack, 0, sizeof(struct switch_stack));
 51
 52	/* setup ksp for switch_to !!! */
 53	p->thread.ksp = (unsigned long)childstack;
 54
 55	if (unlikely(p->flags & PF_KTHREAD)) {
 56		memset(childregs, 0, sizeof(struct pt_regs));
 57		childstack->r15 = (unsigned long) ret_from_kernel_thread;
 58		childstack->r10 = kthread_arg;
 59		childstack->r9 = usp;
 60		childregs->sr = mfcr("psr");
 61	} else {
 62		*childregs = *(current_pt_regs());
 63		if (usp)
 64			childregs->usp = usp;
 65		if (clone_flags & CLONE_SETTLS)
 66			task_thread_info(p)->tp_value = childregs->tls
 67						      = childregs->regs[0];
 68
 69		childregs->a0 = 0;
 70		childstack->r15 = (unsigned long) ret_from_fork;
 71	}
 72
 73	return 0;
 74}
 75
 76/* Fill in the fpu structure for a core dump.  */
 77int dump_fpu(struct pt_regs *regs, struct user_fp *fpu)
 78{
 79	memcpy(fpu, &current->thread.user_fp, sizeof(*fpu));
 80	return 1;
 81}
 82EXPORT_SYMBOL(dump_fpu);
 83
 84int dump_task_regs(struct task_struct *tsk, elf_gregset_t *pr_regs)
 85{
 86	struct pt_regs *regs = task_pt_regs(tsk);
 87
 88	/* NOTE: usp is error value. */
 89	ELF_CORE_COPY_REGS((*pr_regs), regs)
 90
 91	return 1;
 92}
 93
 94unsigned long get_wchan(struct task_struct *p)
 95{
 96	unsigned long lr;
 97	unsigned long *fp, *stack_start, *stack_end;
 98	int count = 0;
 99
100	if (!p || p == current || p->state == TASK_RUNNING)
101		return 0;
102
103	stack_start = (unsigned long *)end_of_stack(p);
104	stack_end = (unsigned long *)(task_stack_page(p) + THREAD_SIZE);
105
106	fp = (unsigned long *) thread_saved_fp(p);
107	do {
108		if (fp < stack_start || fp > stack_end)
109			return 0;
110#ifdef CONFIG_STACKTRACE
111		lr = fp[1];
112		fp = (unsigned long *)fp[0];
113#else
114		lr = *fp++;
115#endif
116		if (!in_sched_functions(lr) &&
117		    __kernel_text_address(lr))
118			return lr;
119	} while (count++ < 16);
120
121	return 0;
122}
123EXPORT_SYMBOL(get_wchan);
124
125#ifndef CONFIG_CPU_PM_NONE
126void arch_cpu_idle(void)
127{
128#ifdef CONFIG_CPU_PM_WAIT
129	asm volatile("wait\n");
130#endif
131
132#ifdef CONFIG_CPU_PM_DOZE
133	asm volatile("doze\n");
134#endif
135
136#ifdef CONFIG_CPU_PM_STOP
137	asm volatile("stop\n");
138#endif
139	local_irq_enable();
140}
141#endif