2 * arch/ubicom32/kernel/thread.c
3 * Ubicom32 architecture hardware thread support.
5 * (C) Copyright 2009, Ubicom, Inc.
7 * This file is part of the Ubicom32 Linux Kernel Port.
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.
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.
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/>.
23 * Ubicom32 implementation derived from (with many thanks):
29 #include <linux/module.h>
30 #include <linux/kernel.h>
31 #include <linux/init.h>
32 #include <linux/sched.h>
33 #include <linux/interrupt.h>
34 #include <linux/irq.h>
35 #include <linux/profile.h>
36 #include <linux/clocksource.h>
37 #include <linux/types.h>
38 #include <asm/ip5000.h>
39 #include <asm/machdep.h>
40 #include <asm/asm-offsets.h>
41 #include <asm/thread.h>
44 * TODO: At some point change the name here to be thread_ksp
46 unsigned int sw_ksp
[THREAD_ARCHITECTURAL_MAX
];
48 static unsigned int thread_mask
= -1;
49 static unsigned int thread_mainline_mask
;
53 * Returning from the called function will disable the thread.
55 * This could be a naked call to allow for hwthreads that do not have stacks.
56 * However, with -O0, the code still writes to thex stack, and this was
57 * corrupting memory just after the callers stack.
59 static void thread_entry(void *arg
, thread_exec_fn_t exec
)
62 * Call thread function
67 * Complete => Disable self
69 thread_disable(thread_get_self());
74 * Start the specified function on the specified hardware thread.
76 thread_t
thread_start(thread_t thread
,
77 thread_exec_fn_t exec
,
79 unsigned int *sp_high
,
85 unsigned int enabled
, mask
, csr
;
87 "move.4 %0, MT_EN\n\t"
93 printk(KERN_WARNING
"request to enable a previously enabled thread\n");
100 csr
= (thread
<< 15) | (1 << 14);
103 "setcsr_flush 0 \n\t"
112 "move.4 SP, %4 \n\t" /* A7 is SP */
124 "move.4 D10, #0 \n\t"
125 "move.4 D11, #0 \n\t"
126 "move.4 D12, #0 \n\t"
127 "move.4 D13, #0 \n\t"
128 "move.4 D14, #0 \n\t"
129 "move.4 D15, #0 \n\t"
131 "move.4 INT_MASK0, #0 \n\t"
132 "move.4 INT_MASK1, #0 \n\t"
135 "setcsr_flush 0 \n\t"
137 : "r" (csr
), "r" (thread_entry
), "r" (exec
),
138 "r" (arg
), "r" (sp_high
)
144 if (type
& THREAD_TYPE_HRT
) {
146 "or.4 MT_HRT, MT_HRT, %0\n\t"
153 "and.4 MT_HRT, MT_HRT, %0\n\t"
164 "or.4 MT_HPRI, MT_HPRI, %0\n\t"
174 "move.4 MT_ACTIVE_SET, %0 \n\t"
178 thread_enable_mask(mask
);
183 * thread_get_mainline()
184 * Return a mask of those threads that are Linux mainline threads.
186 unsigned int thread_get_mainline(void)
188 return thread_mainline_mask
;
192 * thread_set_mainline()
193 * Indicate that the specified thread is a Linux mainline thread.
195 void thread_set_mainline(thread_t tid
)
197 thread_mainline_mask
|= (1 << tid
);
202 * Allocate an unused hardware thread.
204 thread_t
thread_alloc(void)
209 * If this is the first time we are here get the list of unused
210 * threads from the processor device tree node.
212 if (thread_mask
== -1) {
213 thread_mask
= processor_threads();
220 tid
= ffs(thread_mask
);
223 thread_mask
&= ~(1 << tid
);