disable sstrip when using musl
[openwrt/openwrt.git] / target / linux / ubicom32 / files / arch / ubicom32 / include / asm / thread.h
1 /*
2 * arch/ubicom32/include/asm/thread.h
3 * Ubicom32 architecture specific thread definitions.
4 *
5 * (C) Copyright 2009, Ubicom, Inc.
6 *
7 * This file is part of the Ubicom32 Linux Kernel Port.
8 *
9 * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10 * it and/or modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation, either version 2 of the
12 * License, or (at your option) any later version.
13 *
14 * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with the Ubicom32 Linux Kernel Port. If not,
21 * see <http://www.gnu.org/licenses/>.
22 *
23 * Ubicom32 implementation derived from (with many thanks):
24 * arch/m68knommu
25 * arch/blackfin
26 * arch/parisc
27 */
28 #ifndef _ASM_UBICOM32_THREAD_H
29 #define _ASM_UBICOM32_THREAD_H
30
31 #if !defined(__ASSEMBLY__)
32
33 #include <asm/ptrace.h>
34 #include <asm/ubicom32-common.h>
35
36 typedef int thread_t;
37 typedef unsigned char thread_type_t;
38 typedef void (*thread_exec_fn_t)(void *arg);
39
40 #define THREAD_NULL 0x40
41 #define THREAD_TYPE_HRT (1 << 0)
42 #define THREAD_TYPE_SPECIAL 0
43 #define THREAD_TYPE_NORMAL 0
44 #define THREAD_TYPE_BACKGROUND (1 << 1)
45
46 /*
47 * This is the upper bound on the maximum hardware threads that one will find
48 * on a Ubicom processor. It is used to size per hardware thread data structures.
49 */
50 #define THREAD_ARCHITECTURAL_MAX 16
51
52 /*
53 * TODO: Rename this at some point to be thread_
54 */
55 extern unsigned int sw_ksp[THREAD_ARCHITECTURAL_MAX];
56
57
58 /*
59 * thread_get_self()
60 */
61 static inline thread_t thread_get_self(void)
62 {
63 thread_t result;
64
65 /*
66 * Note that ROSR has zeroes in bits 6 through 31 and so we don't need
67 * to do any additional bit masking here.
68 */
69 asm (
70 "lsr.4 %0, ROSR, #2 \n\t"
71 : "=d" (result)
72 :
73 : "cc"
74 );
75
76 return result;
77 }
78
79 /*
80 * thread_suspend()
81 */
82 static inline void thread_suspend(void)
83 {
84 asm volatile (
85 "suspend\n\t"
86 :
87 :
88 );
89 }
90
91 /*
92 * thread_resume()
93 */
94 static inline void thread_resume(thread_t thread)
95 {
96 asm volatile (
97 "move.4 MT_ACTIVE_SET, %0 \n\t"
98 "pipe_flush 0 \n\t"
99 "pipe_flush 0 \n\t"
100 :
101 : "d" (1 << thread)
102 );
103 }
104
105
106
107 /*
108 * thread_enable_mask()
109 * Enable all threads in the mask.
110 *
111 * All writes to MT_EN must be protected by the MT_EN_LOCK bit
112 */
113 static inline void thread_enable_mask(unsigned int mask)
114 {
115 /*
116 * must flush the pipeline twice.
117 * first pipe_flush is to ensure write to MT_EN is completed
118 * second one is to ensure any new instructions from
119 * the targeted thread (the one being disabled), that
120 * are issued while the write to MT_EN is being executed,
121 * are completed.
122 */
123 UBICOM32_LOCK(MT_EN_LOCK_BIT);
124 asm volatile (
125 "or.4 MT_EN, MT_EN, %0 \n\t"
126 "pipe_flush 0 \n\t"
127 "pipe_flush 0 \n\t"
128 :
129 : "d" (mask)
130 : "cc"
131 );
132 UBICOM32_UNLOCK(MT_EN_LOCK_BIT);
133 }
134
135 /*
136 * thread_enable()
137 */
138 static inline void thread_enable(thread_t thread)
139 {
140 thread_enable_mask(1 << thread);
141 }
142
143 /*
144 * thread_disable_mask()
145 * Disable all threads in the mask.
146 *
147 * All writes to MT_EN must be protected by the MT_EN_LOCK bit
148 */
149 static inline void thread_disable_mask(unsigned int mask)
150 {
151 /*
152 * must flush the pipeline twice.
153 * first pipe_flush is to ensure write to MT_EN is completed
154 * second one is to ensure any new instructions from
155 * the targeted thread (the one being disabled), that
156 * are issued while the write to MT_EN is being executed,
157 * are completed.
158 */
159 UBICOM32_LOCK(MT_EN_LOCK_BIT);
160 asm volatile (
161 "and.4 MT_EN, MT_EN, %0 \n\t"
162 "pipe_flush 0 \n\t"
163 "pipe_flush 0 \n\t"
164 :
165 : "d" (~mask)
166 : "cc"
167 );
168 UBICOM32_UNLOCK(MT_EN_LOCK_BIT);
169 }
170
171 /*
172 * thread_disable()
173 */
174 static inline void thread_disable(thread_t thread)
175 {
176 thread_disable_mask(1 << thread);
177 }
178
179 /*
180 * thread_disable_others()
181 * Disable all other threads
182 */
183 static inline void thread_disable_others(void)
184 {
185 thread_t self = thread_get_self();
186 thread_disable_mask(~(1 << self));
187 }
188
189 /*
190 * thread_is_trapped()
191 * Is the specified tid trapped?
192 */
193 static inline int thread_is_trapped(thread_t tid)
194 {
195 int thread_mask = (1 << tid);
196 int trap_thread;
197
198 asm (
199 "move.4 %0, MT_TRAP \n\t"
200 : "=d" (trap_thread)
201 :
202 );
203 return (trap_thread & thread_mask);
204 }
205
206 /*
207 * thread_is_enabled()
208 * Is the specified tid enabled?
209 */
210 static inline int thread_is_enabled(thread_t tid)
211 {
212 int thread_mask = (1 << tid);
213 int enabled_threads;
214
215 asm (
216 "move.4 %0, MT_EN \n\t"
217 : "=d" (enabled_threads)
218 :
219 );
220 return (enabled_threads & thread_mask);
221 }
222
223 /*
224 * thread_get_instruction_count()
225 */
226 static inline unsigned int thread_get_instruction_count(void)
227 {
228 unsigned int result;
229 asm (
230 "move.4 %0, INST_CNT \n\t"
231 : "=r" (result)
232 );
233 return result;
234 }
235
236 /*
237 * thread_get_pc()
238 * pc could point to a speculative and cancelled instruction unless thread is disabled
239 */
240 static inline void *thread_get_pc(thread_t thread)
241 {
242 void *result;
243 asm (
244 "move.4 csr, %1 \n\t"
245 "setcsr_flush 0 \n\t"
246 "move.4 %0, pc \n\t"
247 "move.4 csr, #0 \n\t"
248 "setcsr_flush 0 \n\t"
249 : "=r" (result)
250 : "r" ((thread << 9) | (1 << 8))
251 );
252 return result;
253 }
254
255 /*
256 * thread_get_trap_cause()
257 * This should be called only when the thread is not running
258 */
259 static inline unsigned int thread_get_trap_cause(thread_t thread)
260 {
261 unsigned int result;
262 asm (
263 "move.4 csr, %1 \n\t"
264 "setcsr_flush 0 \n\t"
265 "move.4 %0, trap_cause \n\t"
266 "move.4 csr, #0 \n\t"
267 "setcsr_flush 0 \n\t"
268 : "=r" (result)
269 : "r" ((thread << 9) | (1 << 8))
270 );
271 return result;
272 }
273
274 /*
275 * THREAD_STALL macro.
276 */
277 #define THREAD_STALL \
278 asm volatile ( \
279 "move.4 mt_dbg_active_clr, #-1 \n\t" \
280 "pipe_flush 0 \n\t" \
281 : \
282 : \
283 )
284
285 extern unsigned int thread_get_mainline(void);
286 extern void thread_set_mainline(thread_t tid);
287 extern thread_t thread_alloc(void);
288 extern thread_t thread_start(thread_t thread, thread_exec_fn_t exec, void *arg, unsigned int *sp_high, thread_type_t type);
289
290 /*
291 * asm macros
292 */
293 asm (
294 /*
295 * thread_get_self
296 * Read and shift the current thread into reg
297 *
298 * Note that we don't need to mask the result as bits 6 through 31 of the
299 * ROSR are zeroes.
300 */
301 ".macro thread_get_self reg \n\t"
302 " lsr.4 \\reg, ROSR, #2 \n\t"
303 ".endm \n\t"
304
305 /*
306 * thread_get_self_mask
307 * Read and shift the current thread mask into reg
308 */
309 ".macro thread_get_self_mask reg \n\t"
310 " lsr.4 \\reg, ROSR, #2 \n\t"
311 " lsl.4 \\reg, #1, \\reg \n\t" /* Thread bit */
312 ".endm \n\t"
313 );
314
315 #else /* __ASSEMBLY__ */
316
317 #include <asm/thread-asm.h>
318
319 #endif /* __ASSEMBLY__ */
320 #endif /* _ASM_UBICOM32_THREAD_H */