aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ubicom32/files/arch/ubicom32/include/asm/thread.h
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/ubicom32/files/arch/ubicom32/include/asm/thread.h')
-rw-r--r--target/linux/ubicom32/files/arch/ubicom32/include/asm/thread.h320
1 files changed, 320 insertions, 0 deletions
diff --git a/target/linux/ubicom32/files/arch/ubicom32/include/asm/thread.h b/target/linux/ubicom32/files/arch/ubicom32/include/asm/thread.h
new file mode 100644
index 000000000..69c925ea4
--- /dev/null
+++ b/target/linux/ubicom32/files/arch/ubicom32/include/asm/thread.h
@@ -0,0 +1,320 @@
+/*
+ * arch/ubicom32/include/asm/thread.h
+ * Ubicom32 architecture specific thread definitions.
+ *
+ * (C) Copyright 2009, Ubicom, Inc.
+ *
+ * This file is part of the Ubicom32 Linux Kernel Port.
+ *
+ * The Ubicom32 Linux Kernel Port is free software: you can redistribute
+ * it and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * The Ubicom32 Linux Kernel Port is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Ubicom32 Linux Kernel Port. If not,
+ * see <http://www.gnu.org/licenses/>.
+ *
+ * Ubicom32 implementation derived from (with many thanks):
+ * arch/m68knommu
+ * arch/blackfin
+ * arch/parisc
+ */
+#ifndef _ASM_UBICOM32_THREAD_H
+#define _ASM_UBICOM32_THREAD_H
+
+#if !defined(__ASSEMBLY__)
+
+#include <asm/ptrace.h>
+#include <asm/ubicom32-common.h>
+
+typedef int thread_t;
+typedef unsigned char thread_type_t;
+typedef void (*thread_exec_fn_t)(void *arg);
+
+#define THREAD_NULL 0x40
+#define THREAD_TYPE_HRT (1 << 0)
+#define THREAD_TYPE_SPECIAL 0
+#define THREAD_TYPE_NORMAL 0
+#define THREAD_TYPE_BACKGROUND (1 << 1)
+
+/*
+ * This is the upper bound on the maximum hardware threads that one will find
+ * on a Ubicom processor. It is used to size per hardware thread data structures.
+ */
+#define THREAD_ARCHITECTURAL_MAX 16
+
+/*
+ * TODO: Rename this at some point to be thread_
+ */
+extern unsigned int sw_ksp[THREAD_ARCHITECTURAL_MAX];
+
+
+/*
+ * thread_get_self()
+ */
+static inline thread_t thread_get_self(void)
+{
+ thread_t result;
+
+ /*
+ * Note that ROSR has zeroes in bits 6 through 31 and so we don't need
+ * to do any additional bit masking here.
+ */
+ asm (
+ "lsr.4 %0, ROSR, #2 \n\t"
+ : "=d" (result)
+ :
+ : "cc"
+ );
+
+ return result;
+}
+
+/*
+ * thread_suspend()
+ */
+static inline void thread_suspend(void)
+{
+ asm volatile (
+ "suspend\n\t"
+ :
+ :
+ );
+}
+
+/*
+ * thread_resume()
+ */
+static inline void thread_resume(thread_t thread)
+{
+ asm volatile (
+ "move.4 MT_ACTIVE_SET, %0 \n\t"
+ "pipe_flush 0 \n\t"
+ "pipe_flush 0 \n\t"
+ :
+ : "d" (1 << thread)
+ );
+}
+
+
+
+/*
+ * thread_enable_mask()
+ * Enable all threads in the mask.
+ *
+ * All writes to MT_EN must be protected by the MT_EN_LOCK bit
+ */
+static inline void thread_enable_mask(unsigned int mask)
+{
+ /*
+ * must flush the pipeline twice.
+ * first pipe_flush is to ensure write to MT_EN is completed
+ * second one is to ensure any new instructions from
+ * the targeted thread (the one being disabled), that
+ * are issued while the write to MT_EN is being executed,
+ * are completed.
+ */
+ UBICOM32_LOCK(MT_EN_LOCK_BIT);
+ asm volatile (
+ "or.4 MT_EN, MT_EN, %0 \n\t"
+ "pipe_flush 0 \n\t"
+ "pipe_flush 0 \n\t"
+ :
+ : "d" (mask)
+ : "cc"
+ );
+ UBICOM32_UNLOCK(MT_EN_LOCK_BIT);
+}
+
+/*
+ * thread_enable()
+ */
+static inline void thread_enable(thread_t thread)
+{
+ thread_enable_mask(1 << thread);
+}
+
+/*
+ * thread_disable_mask()
+ * Disable all threads in the mask.
+ *
+ * All writes to MT_EN must be protected by the MT_EN_LOCK bit
+ */
+static inline void thread_disable_mask(unsigned int mask)
+{
+ /*
+ * must flush the pipeline twice.
+ * first pipe_flush is to ensure write to MT_EN is completed
+ * second one is to ensure any new instructions from
+ * the targeted thread (the one being disabled), that
+ * are issued while the write to MT_EN is being executed,
+ * are completed.
+ */
+ UBICOM32_LOCK(MT_EN_LOCK_BIT);
+ asm volatile (
+ "and.4 MT_EN, MT_EN, %0 \n\t"
+ "pipe_flush 0 \n\t"
+ "pipe_flush 0 \n\t"
+ :
+ : "d" (~mask)
+ : "cc"
+ );
+ UBICOM32_UNLOCK(MT_EN_LOCK_BIT);
+}
+
+/*
+ * thread_disable()
+ */
+static inline void thread_disable(thread_t thread)
+{
+ thread_disable_mask(1 << thread);
+}
+
+/*
+ * thread_disable_others()
+ * Disable all other threads
+ */
+static inline void thread_disable_others(void)
+{
+ thread_t self = thread_get_self();
+ thread_disable_mask(~(1 << self));
+}
+
+/*
+ * thread_is_trapped()
+ * Is the specified tid trapped?
+ */
+static inline int thread_is_trapped(thread_t tid)
+{
+ int thread_mask = (1 << tid);
+ int trap_thread;
+
+ asm (
+ "move.4 %0, MT_TRAP \n\t"
+ : "=d" (trap_thread)
+ :
+ );
+ return (trap_thread & thread_mask);
+}
+
+/*
+ * thread_is_enabled()
+ * Is the specified tid enabled?
+ */
+static inline int thread_is_enabled(thread_t tid)
+{
+ int thread_mask = (1 << tid);
+ int enabled_threads;
+
+ asm (
+ "move.4 %0, MT_EN \n\t"
+ : "=d" (enabled_threads)
+ :
+ );
+ return (enabled_threads & thread_mask);
+}
+
+/*
+ * thread_get_instruction_count()
+ */
+static inline unsigned int thread_get_instruction_count(void)
+{
+ unsigned int result;
+ asm (
+ "move.4 %0, INST_CNT \n\t"
+ : "=r" (result)
+ );
+ return result;
+}
+
+/*
+ * thread_get_pc()
+ * pc could point to a speculative and cancelled instruction unless thread is disabled
+ */
+static inline void *thread_get_pc(thread_t thread)
+{
+ void *result;
+ asm (
+ "move.4 csr, %1 \n\t"
+ "setcsr_flush 0 \n\t"
+ "move.4 %0, pc \n\t"
+ "move.4 csr, #0 \n\t"
+ "setcsr_flush 0 \n\t"
+ : "=r" (result)
+ : "r" ((thread << 9) | (1 << 8))
+ );
+ return result;
+}
+
+/*
+ * thread_get_trap_cause()
+ * This should be called only when the thread is not running
+ */
+static inline unsigned int thread_get_trap_cause(thread_t thread)
+{
+ unsigned int result;
+ asm (
+ "move.4 csr, %1 \n\t"
+ "setcsr_flush 0 \n\t"
+ "move.4 %0, trap_cause \n\t"
+ "move.4 csr, #0 \n\t"
+ "setcsr_flush 0 \n\t"
+ : "=r" (result)
+ : "r" ((thread << 9) | (1 << 8))
+ );
+ return result;
+}
+
+/*
+ * THREAD_STALL macro.
+ */
+#define THREAD_STALL \
+ asm volatile ( \
+ "move.4 mt_dbg_active_clr, #-1 \n\t" \
+ "pipe_flush 0 \n\t" \
+ : \
+ : \
+ )
+
+extern unsigned int thread_get_mainline(void);
+extern void thread_set_mainline(thread_t tid);
+extern thread_t thread_alloc(void);
+extern thread_t thread_start(thread_t thread, thread_exec_fn_t exec, void *arg, unsigned int *sp_high, thread_type_t type);
+
+/*
+ * asm macros
+ */
+asm (
+/*
+ * thread_get_self
+ * Read and shift the current thread into reg
+ *
+ * Note that we don't need to mask the result as bits 6 through 31 of the
+ * ROSR are zeroes.
+ */
+".macro thread_get_self reg \n\t"
+" lsr.4 \\reg, ROSR, #2 \n\t"
+".endm \n\t"
+
+/*
+ * thread_get_self_mask
+ * Read and shift the current thread mask into reg
+ */
+".macro thread_get_self_mask reg \n\t"
+" lsr.4 \\reg, ROSR, #2 \n\t"
+" lsl.4 \\reg, #1, \\reg \n\t" /* Thread bit */
+".endm \n\t"
+);
+
+#else /* __ASSEMBLY__ */
+
+#include <asm/thread-asm.h>
+
+#endif /* __ASSEMBLY__ */
+#endif /* _ASM_UBICOM32_THREAD_H */