Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) // Copyright (C) 2005-2017 Andes Technology Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) #include <linux/sched/debug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <linux/sched/task_stack.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/kallsyms.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <asm/elf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <asm/proc-fns.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <asm/fpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/reboot.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #if IS_ENABLED(CONFIG_LAZY_FPU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) struct task_struct *last_task_used_math;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) extern void setup_mm_for_reboot(char mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) extern inline void arch_reset(char mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	if (mode == 's') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 		/* Use cpu handler, jump to 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 		cpu_reset(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) void (*pm_power_off) (void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) EXPORT_SYMBOL(pm_power_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) static char reboot_mode_nds32 = 'h';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) int __init reboot_setup(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	reboot_mode_nds32 = str[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) static int cpub_pwroff(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) __setup("reboot=", reboot_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) void machine_halt(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	cpub_pwroff();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) EXPORT_SYMBOL(machine_halt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) void machine_power_off(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	if (pm_power_off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		pm_power_off();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) EXPORT_SYMBOL(machine_power_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) void machine_restart(char *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	 * Clean and disable cache, and turn off interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	cpu_proc_fin();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	 * Tell the mm system that we are going to reboot -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	 * we may need it to insert some 1:1 mappings so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	 * soft boot works.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	setup_mm_for_reboot(reboot_mode_nds32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	/* Execute kernel restart handler call chain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	do_kernel_restart(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	 * Now call the architecture specific reboot code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	arch_reset(reboot_mode_nds32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	 * Whoops - the architecture was unable to reboot.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	 * Tell the user!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	mdelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	pr_info("Reboot failed -- System halted\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	while (1) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) EXPORT_SYMBOL(machine_restart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) void show_regs(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	printk("PC is at %pS\n", (void *)instruction_pointer(regs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	printk("LP is at %pS\n", (void *)regs->lp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	pr_info("pc : [<%08lx>]    lp : [<%08lx>]    %s\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		"sp : %08lx  fp : %08lx  gp : %08lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		instruction_pointer(regs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		regs->lp, print_tainted(), regs->sp, regs->fp, regs->gp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	pr_info("r25: %08lx  r24: %08lx\n", regs->uregs[25], regs->uregs[24]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	pr_info("r23: %08lx  r22: %08lx  r21: %08lx  r20: %08lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		regs->uregs[23], regs->uregs[22],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		regs->uregs[21], regs->uregs[20]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	pr_info("r19: %08lx  r18: %08lx  r17: %08lx  r16: %08lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		regs->uregs[19], regs->uregs[18],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		regs->uregs[17], regs->uregs[16]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	pr_info("r15: %08lx  r14: %08lx  r13: %08lx  r12: %08lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		regs->uregs[15], regs->uregs[14],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 		regs->uregs[13], regs->uregs[12]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	pr_info("r11: %08lx  r10: %08lx  r9 : %08lx  r8 : %08lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		regs->uregs[11], regs->uregs[10],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		regs->uregs[9], regs->uregs[8]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	pr_info("r7 : %08lx  r6 : %08lx  r5 : %08lx  r4 : %08lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		regs->uregs[7], regs->uregs[6], regs->uregs[5], regs->uregs[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	pr_info("r3 : %08lx  r2 : %08lx  r1 : %08lx  r0 : %08lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		regs->uregs[3], regs->uregs[2], regs->uregs[1], regs->uregs[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	pr_info("  IRQs o%s  Segment %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		interrupts_enabled(regs) ? "n" : "ff",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		uaccess_kernel() ? "kernel" : "user");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) EXPORT_SYMBOL(show_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) void exit_thread(struct task_struct *tsk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #if defined(CONFIG_FPU) && defined(CONFIG_LAZY_FPU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	if (last_task_used_math == tsk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		last_task_used_math = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) void flush_thread(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #if defined(CONFIG_FPU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	clear_fpu(task_pt_regs(current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	clear_used_math();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) # ifdef CONFIG_LAZY_FPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	if (last_task_used_math == current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		last_task_used_math = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) # endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) DEFINE_PER_CPU(struct task_struct *, __entry_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) int copy_thread(unsigned long clone_flags, unsigned long stack_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		unsigned long stk_sz, struct task_struct *p, unsigned long tls)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	struct pt_regs *childregs = task_pt_regs(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	if (unlikely(p->flags & PF_KTHREAD)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		memset(childregs, 0, sizeof(struct pt_regs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		/* kernel thread fn */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		p->thread.cpu_context.r6 = stack_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		/* kernel thread argument */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		p->thread.cpu_context.r7 = stk_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		*childregs = *current_pt_regs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		if (stack_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 			childregs->sp = stack_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		/* child get zero as ret. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		childregs->uregs[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		childregs->osp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		if (clone_flags & CLONE_SETTLS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 			childregs->uregs[25] = tls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	/* cpu context switching  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	p->thread.cpu_context.pc = (unsigned long)ret_from_fork;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	p->thread.cpu_context.sp = (unsigned long)childregs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #if IS_ENABLED(CONFIG_FPU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	if (used_math()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) # if !IS_ENABLED(CONFIG_LAZY_FPU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		unlazy_fpu(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) # else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		preempt_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		if (last_task_used_math == current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 			save_fpu(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		preempt_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) # endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		p->thread.fpu = current->thread.fpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		clear_fpu(task_pt_regs(p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		set_stopped_child_used_math(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) #ifdef CONFIG_HWZOL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	childregs->lb = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	childregs->le = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	childregs->lc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) #if IS_ENABLED(CONFIG_FPU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct task_struct *_switch_fpu(struct task_struct *prev, struct task_struct *next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) #if !IS_ENABLED(CONFIG_LAZY_FPU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	unlazy_fpu(prev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	if (!(next->flags & PF_KTHREAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 		clear_fpu(task_pt_regs(next));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	return prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)  * fill in the fpe structure for a core dump...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) int dump_fpu(struct pt_regs *regs, elf_fpregset_t * fpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	int fpvalid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) #if IS_ENABLED(CONFIG_FPU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	struct task_struct *tsk = current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	fpvalid = tsk_used_math(tsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	if (fpvalid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		lose_fpu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		memcpy(fpu, &tsk->thread.fpu, sizeof(*fpu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	return fpvalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) EXPORT_SYMBOL(dump_fpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) unsigned long get_wchan(struct task_struct *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	unsigned long fp, lr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	unsigned long stack_start, stack_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	int count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	if (!p || p == current || p->state == TASK_RUNNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	if (IS_ENABLED(CONFIG_FRAME_POINTER)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 		stack_start = (unsigned long)end_of_stack(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		stack_end = (unsigned long)task_stack_page(p) + THREAD_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		fp = thread_saved_fp(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 			if (fp < stack_start || fp > stack_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 			lr = ((unsigned long *)fp)[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 			if (!in_sched_functions(lr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 				return lr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 			fp = *(unsigned long *)(fp + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		} while (count++ < 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) EXPORT_SYMBOL(get_wchan);