1
2
3
4
5
6
7
8
9
10
11#include <linux/errno.h>
12#include <linux/module.h>
13#include <linux/sched.h>
14#include <linux/sched/task.h>
15#include <linux/sched/task_stack.h>
16
17#include <linux/mm.h>
18#include <linux/fs.h>
19#include <linux/unistd.h>
20#include <linux/ptrace.h>
21#include <linux/slab.h>
22#include <linux/syscalls.h>
23#include <linux/elf.h>
24#include <linux/tick.h>
25
26SYSCALL_DEFINE1(arc_settls, void *, user_tls_data_ptr)
27{
28 task_thread_info(current)->thr_ptr = (unsigned int)user_tls_data_ptr;
29 return 0;
30}
31
32
33
34
35
36
37
38
39
40
41
42SYSCALL_DEFINE0(arc_gettls)
43{
44 return task_thread_info(current)->thr_ptr;
45}
46
47SYSCALL_DEFINE3(arc_usr_cmpxchg, int *, uaddr, int, expected, int, new)
48{
49 struct pt_regs *regs = current_pt_regs();
50 int uval = -EFAULT;
51
52
53
54
55
56
57
58 WARN_ON_ONCE(IS_ENABLED(CONFIG_SMP));
59
60
61 regs->status32 &= ~STATUS_Z_MASK;
62
63 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
64 return -EFAULT;
65
66 preempt_disable();
67
68 if (__get_user(uval, uaddr))
69 goto done;
70
71 if (uval == expected) {
72 if (!__put_user(new, uaddr))
73 regs->status32 |= STATUS_Z_MASK;
74 }
75
76done:
77 preempt_enable();
78
79 return uval;
80}
81
82#ifdef CONFIG_ISA_ARCV2
83
84void arch_cpu_idle(void)
85{
86
87 const unsigned int arg = 0x10 | ARCV2_IRQ_DEF_PRIO;
88
89 __asm__ __volatile__(
90 "sleep %0 \n"
91 :
92 :"I"(arg));
93}
94
95#elif defined(CONFIG_EZNPS_MTM_EXT)
96
97void arch_cpu_idle(void)
98{
99
100 __asm__ __volatile__(
101 ".word %0 \n"
102 :
103 :"i"(CTOP_INST_HWSCHD_WFT_IE12));
104}
105
106#else
107
108void arch_cpu_idle(void)
109{
110
111 __asm__ __volatile__("sleep 0x3 \n");
112}
113
114#endif
115
116asmlinkage void ret_from_fork(void);
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152int copy_thread(unsigned long clone_flags,
153 unsigned long usp, unsigned long kthread_arg,
154 struct task_struct *p)
155{
156 struct pt_regs *c_regs;
157 unsigned long *childksp;
158 struct callee_regs *c_callee;
159 struct callee_regs *parent_callee;
160 struct pt_regs *regs = current_pt_regs();
161
162
163 c_regs = task_pt_regs(p);
164 childksp = (unsigned long *)c_regs - 2;
165 c_callee = ((struct callee_regs *)childksp) - 1;
166
167
168
169
170
171
172
173
174
175 p->thread.ksp = (unsigned long)c_callee;
176
177
178 childksp[0] = 0;
179 childksp[1] = (unsigned long)ret_from_fork;
180
181 if (unlikely(p->flags & PF_KTHREAD)) {
182 memset(c_regs, 0, sizeof(struct pt_regs));
183
184 c_callee->r13 = kthread_arg;
185 c_callee->r14 = usp;
186
187 return 0;
188 }
189
190
191
192
193 childksp[0] = 0;
194 childksp[1] = (unsigned long)ret_from_fork;
195
196
197 *c_regs = *regs;
198
199 if (usp)
200 c_regs->sp = usp;
201
202 c_regs->r0 = 0;
203
204 parent_callee = ((struct callee_regs *)regs) - 1;
205 *c_callee = *parent_callee;
206
207 if (unlikely(clone_flags & CLONE_SETTLS)) {
208
209
210
211
212 task_thread_info(p)->thr_ptr = regs->r3;
213 } else {
214
215 task_thread_info(p)->thr_ptr =
216 task_thread_info(current)->thr_ptr;
217 }
218
219 return 0;
220}
221
222
223
224
225void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long usp)
226{
227 regs->sp = usp;
228 regs->ret = pc;
229
230
231
232
233
234
235 regs->status32 = STATUS_U_MASK | STATUS_L_MASK | ISA_INIT_STATUS_BITS;
236
237#ifdef CONFIG_EZNPS_MTM_EXT
238 regs->eflags = 0;
239#endif
240
241
242 regs->lp_start = 0x10;
243 regs->lp_end = 0x80;
244}
245
246
247
248
249void flush_thread(void)
250{
251}
252
253int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
254{
255 return 0;
256}
257
258int elf_check_arch(const struct elf32_hdr *x)
259{
260 unsigned int eflags;
261
262 if (x->e_machine != EM_ARC_INUSE) {
263 pr_err("ELF not built for %s ISA\n",
264 is_isa_arcompact() ? "ARCompact":"ARCv2");
265 return 0;
266 }
267
268 eflags = x->e_flags;
269 if ((eflags & EF_ARC_OSABI_MSK) != EF_ARC_OSABI_CURRENT) {
270 pr_err("ABI mismatch - you need newer toolchain\n");
271 force_sigsegv(SIGSEGV, current);
272 return 0;
273 }
274
275 return 1;
276}
277EXPORT_SYMBOL(elf_check_arch);
278