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/mm.h>
15#include <linux/fs.h>
16#include <linux/unistd.h>
17#include <linux/ptrace.h>
18#include <linux/slab.h>
19#include <linux/syscalls.h>
20#include <linux/elf.h>
21#include <linux/tick.h>
22
23SYSCALL_DEFINE1(arc_settls, void *, user_tls_data_ptr)
24{
25 task_thread_info(current)->thr_ptr = (unsigned int)user_tls_data_ptr;
26 return 0;
27}
28
29
30
31
32
33
34
35
36
37
38
39SYSCALL_DEFINE0(arc_gettls)
40{
41 return task_thread_info(current)->thr_ptr;
42}
43
44void arch_cpu_idle(void)
45{
46
47 __asm__("sleep 0x3");
48}
49
50asmlinkage void ret_from_fork(void);
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83int copy_thread(unsigned long clone_flags,
84 unsigned long usp, unsigned long arg,
85 struct task_struct *p)
86{
87 struct pt_regs *c_regs;
88 unsigned long *childksp;
89 struct callee_regs *c_callee;
90 struct callee_regs *parent_callee;
91 struct pt_regs *regs = current_pt_regs();
92
93
94 c_regs = task_pt_regs(p);
95 childksp = (unsigned long *)c_regs - 2;
96 c_callee = ((struct callee_regs *)childksp) - 1;
97
98
99
100
101
102
103
104
105
106 p->thread.ksp = (unsigned long)c_callee;
107
108
109 childksp[0] = 0;
110 childksp[1] = (unsigned long)ret_from_fork;
111
112 if (unlikely(p->flags & PF_KTHREAD)) {
113 memset(c_regs, 0, sizeof(struct pt_regs));
114
115 c_callee->r13 = arg;
116 c_callee->r14 = usp;
117
118 return 0;
119 }
120
121
122
123
124 childksp[0] = 0;
125 childksp[1] = (unsigned long)ret_from_fork;
126
127
128 *c_regs = *regs;
129
130 if (usp)
131 c_regs->sp = usp;
132
133 c_regs->r0 = 0;
134
135 parent_callee = ((struct callee_regs *)regs) - 1;
136 *c_callee = *parent_callee;
137
138 if (unlikely(clone_flags & CLONE_SETTLS)) {
139
140
141
142
143 task_thread_info(p)->thr_ptr = regs->r3;
144 } else {
145
146 task_thread_info(p)->thr_ptr =
147 task_thread_info(current)->thr_ptr;
148 }
149
150 return 0;
151}
152
153
154
155
156void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long usp)
157{
158 set_fs(USER_DS);
159
160 regs->sp = usp;
161 regs->ret = pc;
162
163
164
165
166
167
168 regs->status32 = STATUS_U_MASK | STATUS_L_MASK |
169 STATUS_E1_MASK | STATUS_E2_MASK;
170
171
172 regs->lp_start = 0x10;
173 regs->lp_end = 0x80;
174}
175
176
177
178
179void flush_thread(void)
180{
181}
182
183
184
185
186void exit_thread(void)
187{
188}
189
190int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
191{
192 return 0;
193}
194
195
196
197
198
199
200unsigned long thread_saved_pc(struct task_struct *t)
201{
202 struct pt_regs *regs = task_pt_regs(t);
203 unsigned long blink = 0;
204
205
206
207
208
209
210
211
212 if (t != current && t->state != TASK_RUNNING)
213 blink = *((unsigned int *)regs - 1);
214
215 return blink;
216}
217
218int elf_check_arch(const struct elf32_hdr *x)
219{
220 unsigned int eflags;
221
222 if (x->e_machine != EM_ARCOMPACT)
223 return 0;
224
225 eflags = x->e_flags;
226 if ((eflags & EF_ARC_OSABI_MSK) < EF_ARC_OSABI_CURRENT) {
227 pr_err("ABI mismatch - you need newer toolchain\n");
228 force_sigsegv(SIGSEGV, current);
229 return 0;
230 }
231
232 return 1;
233}
234EXPORT_SYMBOL(elf_check_arch);
235