hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/arch/riscv/kernel/process.c
....@@ -1,25 +1,13 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
34 * Chen Liqin <liqin.chen@sunplusct.com>
45 * Lennox Wu <lennox.wu@sunplusct.com>
56 * Copyright (C) 2012 Regents of the University of California
67 * Copyright (C) 2017 SiFive
7
- *
8
- * This program is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License as published by
10
- * the Free Software Foundation; either version 2 of the License, or
11
- * (at your option) any later version.
12
- *
13
- * This program is distributed in the hope that it will be useful,
14
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- * GNU General Public License for more details.
17
- *
18
- * You should have received a copy of the GNU General Public License
19
- * along with this program; if not, see the file COPYING, or write
20
- * to the Free Software Foundation, Inc.,
218 */
229
10
+#include <linux/cpu.h>
2311 #include <linux/kernel.h>
2412 #include <linux/sched.h>
2513 #include <linux/sched/task_stack.h>
....@@ -32,6 +20,15 @@
3220 #include <asm/csr.h>
3321 #include <asm/string.h>
3422 #include <asm/switch_to.h>
23
+#include <asm/thread_info.h>
24
+
25
+register unsigned long gp_in_global __asm__("gp");
26
+
27
+#ifdef CONFIG_STACKPROTECTOR
28
+#include <linux/stackprotector.h>
29
+unsigned long __stack_chk_guard __read_mostly;
30
+EXPORT_SYMBOL(__stack_chk_guard);
31
+#endif
3532
3633 extern asmlinkage void ret_from_fork(void);
3734 extern asmlinkage void ret_from_kernel_thread(void);
....@@ -39,15 +36,15 @@
3936 void arch_cpu_idle(void)
4037 {
4138 wait_for_interrupt();
42
- local_irq_enable();
39
+ raw_local_irq_enable();
4340 }
4441
4542 void show_regs(struct pt_regs *regs)
4643 {
4744 show_regs_print_info(KERN_DEFAULT);
4845
49
- pr_cont("sepc: " REG_FMT " ra : " REG_FMT " sp : " REG_FMT "\n",
50
- regs->sepc, regs->ra, regs->sp);
46
+ pr_cont("epc: " REG_FMT " ra : " REG_FMT " sp : " REG_FMT "\n",
47
+ regs->epc, regs->ra, regs->sp);
5148 pr_cont(" gp : " REG_FMT " tp : " REG_FMT " t0 : " REG_FMT "\n",
5249 regs->gp, regs->tp, regs->t0);
5350 pr_cont(" t1 : " REG_FMT " t2 : " REG_FMT " s0 : " REG_FMT "\n",
....@@ -69,27 +66,37 @@
6966 pr_cont(" t5 : " REG_FMT " t6 : " REG_FMT "\n",
7067 regs->t5, regs->t6);
7168
72
- pr_cont("sstatus: " REG_FMT " sbadaddr: " REG_FMT " scause: " REG_FMT "\n",
73
- regs->sstatus, regs->sbadaddr, regs->scause);
69
+ pr_cont("status: " REG_FMT " badaddr: " REG_FMT " cause: " REG_FMT "\n",
70
+ regs->status, regs->badaddr, regs->cause);
7471 }
7572
7673 void start_thread(struct pt_regs *regs, unsigned long pc,
7774 unsigned long sp)
7875 {
79
- regs->sstatus = SR_SPIE /* User mode, irqs on */ | SR_FS_INITIAL;
80
- regs->sepc = pc;
76
+ regs->status = SR_PIE;
77
+ if (has_fpu) {
78
+ regs->status |= SR_FS_INITIAL;
79
+ /*
80
+ * Restore the initial value to the FP register
81
+ * before starting the user program.
82
+ */
83
+ fstate_restore(current, regs);
84
+ }
85
+ regs->epc = pc;
8186 regs->sp = sp;
82
- set_fs(USER_DS);
8387 }
8488
8589 void flush_thread(void)
8690 {
91
+#ifdef CONFIG_FPU
8792 /*
88
- * Reset FPU context
93
+ * Reset FPU state and context
8994 * frm: round to nearest, ties to even (IEEE default)
9095 * fflags: accrued exceptions cleared
9196 */
97
+ fstate_off(current, task_pt_regs(current));
9298 memset(&current->thread.fstate, 0, sizeof(current->thread.fstate));
99
+#endif
93100 }
94101
95102 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
....@@ -99,18 +106,20 @@
99106 return 0;
100107 }
101108
102
-int copy_thread(unsigned long clone_flags, unsigned long usp,
103
- unsigned long arg, struct task_struct *p)
109
+int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg,
110
+ struct task_struct *p, unsigned long tls)
104111 {
105112 struct pt_regs *childregs = task_pt_regs(p);
106113
114
+ memset(&p->thread.s, 0, sizeof(p->thread.s));
115
+
107116 /* p->thread holds context to be restored by __switch_to() */
108
- if (unlikely(p->flags & PF_KTHREAD)) {
117
+ if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
109118 /* Kernel thread */
110
- const register unsigned long gp __asm__ ("gp");
111119 memset(childregs, 0, sizeof(struct pt_regs));
112
- childregs->gp = gp;
113
- childregs->sstatus = SR_SPP | SR_SPIE; /* Supervisor, irqs on */
120
+ childregs->gp = gp_in_global;
121
+ /* Supervisor/Machine, irqs on: */
122
+ childregs->status = SR_PP | SR_PIE;
114123
115124 p->thread.ra = (unsigned long)ret_from_kernel_thread;
116125 p->thread.s[0] = usp; /* fn */
....@@ -120,7 +129,7 @@
120129 if (usp) /* User fork */
121130 childregs->sp = usp;
122131 if (clone_flags & CLONE_SETTLS)
123
- childregs->tp = childregs->a5;
132
+ childregs->tp = tls;
124133 childregs->a0 = 0; /* Return value of fork() */
125134 p->thread.ra = (unsigned long)ret_from_fork;
126135 }