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
83
84
85
86int copy_thread(unsigned long clone_flags,
87 unsigned long usp, unsigned long kthread_arg,
88 struct task_struct *p)
89{
90 struct pt_regs *c_regs;
91 unsigned long *childksp;
92 struct callee_regs *c_callee;
93 struct callee_regs *parent_callee;
94 struct pt_regs *regs = current_pt_regs();
95
96
97 c_regs = task_pt_regs(p);
98 childksp = (unsigned long *)c_regs - 2;
99 c_callee = ((struct callee_regs *)childksp) - 1;
100
101
102
103
104
105
106
107
108
109 p->thread.ksp = (unsigned long)c_callee;
110
111
112 childksp[0] = 0;
113 childksp[1] = (unsigned long)ret_from_fork;
114
115 if (unlikely(p->flags & PF_KTHREAD)) {
116 memset(c_regs, 0, sizeof(struct pt_regs));
117
118 c_callee->r13 = kthread_arg;
119 c_callee->r14 = usp;
120
121 return 0;
122 }
123
124
125
126
127 childksp[0] = 0;
128 childksp[1] = (unsigned long)ret_from_fork;
129
130
131 *c_regs = *regs;
132
133 if (usp)
134 c_regs->sp = usp;
135
136 c_regs->r0 = 0;
137
138 parent_callee = ((struct callee_regs *)regs) - 1;
139 *c_callee = *parent_callee;
140
141 if (unlikely(clone_flags & CLONE_SETTLS)) {
142
143
144
145
146 task_thread_info(p)->thr_ptr = regs->r3;
147 } else {
148
149 task_thread_info(p)->thr_ptr =
150 task_thread_info(current)->thr_ptr;
151 }
152
153 return 0;
154}
155
156
157
158
159void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long usp)
160{
161 regs->sp = usp;
162 regs->ret = pc;
163
164
165
166
167
168
169 regs->status32 = STATUS_U_MASK | STATUS_L_MASK |
170 STATUS_E1_MASK | STATUS_E2_MASK;
171
172
173 regs->lp_start = 0x10;
174 regs->lp_end = 0x80;
175}
176
177
178
179
180void flush_thread(void)
181{
182}
183
184
185
186
187void exit_thread(void)
188{
189}
190
191int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
192{
193 return 0;
194}
195
196int elf_check_arch(const struct elf32_hdr *x)
197{
198 unsigned int eflags;
199
200 if (x->e_machine != EM_ARCOMPACT)
201 return 0;
202
203 eflags = x->e_flags;
204 if ((eflags & EF_ARC_OSABI_MSK) < EF_ARC_OSABI_CURRENT) {
205 pr_err("ABI mismatch - you need newer toolchain\n");
206 force_sigsegv(SIGSEGV, current);
207 return 0;
208 }
209
210 return 1;
211}
212EXPORT_SYMBOL(elf_check_arch);
213