aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/sh/register-banks.txt33
-rw-r--r--include/asm-sh/system.h17
-rw-r--r--include/asm-sh/thread_info.h17
3 files changed, 64 insertions, 3 deletions
diff --git a/Documentation/sh/register-banks.txt b/Documentation/sh/register-banks.txt
new file mode 100644
index 000000000000..a6719f2f6594
--- /dev/null
+++ b/Documentation/sh/register-banks.txt
@@ -0,0 +1,33 @@
1 Notes on register bank usage in the kernel
2 ==========================================
3
4Introduction
5------------
6
7The SH-3 and SH-4 CPU families traditionally include a single partial register
8bank (selected by SR.RB, only r0 ... r7 are banked), whereas other families
9may have more full-featured banking or simply no such capabilities at all.
10
11SR.RB banking
12-------------
13
14In the case of this type of banking, banked registers are mapped directly to
15r0 ... r7 if SR.RB is set to the bank we are interested in, otherwise ldc/stc
16can still be used to reference the banked registers (as r0_bank ... r7_bank)
17when in the context of another bank. The developer must keep the SR.RB value
18in mind when writing code that utilizes these banked registers, for obvious
19reasons. Userspace is also not able to poke at the bank1 values, so these can
20be used rather effectively as scratch registers by the kernel.
21
22Presently the kernel uses several of these registers.
23
24 - r0_bank, r1_bank (referenced as k0 and k1, used for scratch
25 registers when doing exception handling).
26 - r2_bank (used to track the EXPEVT/INTEVT code)
27 - Used by do_IRQ() and friends for doing irq mapping based off
28 of the interrupt exception vector jump table offset
29 - r6_bank (global interrupt mask)
30 - The SR.IMASK interrupt handler makes use of this to set the
31 interrupt priority level (used by local_irq_enable())
32 - r7_bank (current)
33
diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h
index 1630a5411e5f..198d17e3069a 100644
--- a/include/asm-sh/system.h
+++ b/include/asm-sh/system.h
@@ -136,7 +136,8 @@ extern void __xchg_called_with_bad_pointer(void);
136#define set_mb(var, value) do { xchg(&var, value); } while (0) 136#define set_mb(var, value) do { xchg(&var, value); } while (0)
137 137
138/* Interrupt Control */ 138/* Interrupt Control */
139static __inline__ void local_irq_enable(void) 139#ifdef CONFIG_CPU_HAS_SR_RB
140static inline void local_irq_enable(void)
140{ 141{
141 unsigned long __dummy0, __dummy1; 142 unsigned long __dummy0, __dummy1;
142 143
@@ -149,6 +150,20 @@ static __inline__ void local_irq_enable(void)
149 : "1" (~0x000000f0) 150 : "1" (~0x000000f0)
150 : "memory"); 151 : "memory");
151} 152}
153#else
154static inline void local_irq_enable(void)
155{
156 unsigned long __dummy0, __dummy1;
157
158 __asm__ __volatile__ (
159 "stc sr, %0\n\t"
160 "and %1, %0\n\t"
161 "ldc %0, sr\n\t"
162 : "=&r" (__dummy0), "=r" (__dummy1)
163 : "1" (~0x000000f0)
164 : "memory");
165}
166#endif
152 167
153static __inline__ void local_irq_disable(void) 168static __inline__ void local_irq_disable(void)
154{ 169{
diff --git a/include/asm-sh/thread_info.h b/include/asm-sh/thread_info.h
index 7345350d98c0..f64dd803a014 100644
--- a/include/asm-sh/thread_info.h
+++ b/include/asm-sh/thread_info.h
@@ -48,16 +48,29 @@ struct thread_info {
48#define init_thread_info (init_thread_union.thread_info) 48#define init_thread_info (init_thread_union.thread_info)
49#define init_stack (init_thread_union.stack) 49#define init_stack (init_thread_union.stack)
50 50
51#define THREAD_SIZE (2*PAGE_SIZE)
52
51/* how to get the thread information struct from C */ 53/* how to get the thread information struct from C */
52static inline struct thread_info *current_thread_info(void) 54static inline struct thread_info *current_thread_info(void)
53{ 55{
54 struct thread_info *ti; 56 struct thread_info *ti;
57#ifdef CONFIG_CPU_HAS_SR_RB
55 __asm__("stc r7_bank, %0" : "=r" (ti)); 58 __asm__("stc r7_bank, %0" : "=r" (ti));
59#else
60 unsigned long __dummy;
61
62 __asm__ __volatile__ (
63 "mov r15, %0\n\t"
64 "and %1, %0\n\t"
65 : "=&r" (ti), "=r" (__dummy)
66 : "1" (~(THREAD_SIZE - 1))
67 : "memory");
68#endif
69
56 return ti; 70 return ti;
57} 71}
58 72
59/* thread information allocation */ 73/* thread information allocation */
60#define THREAD_SIZE (2*PAGE_SIZE)
61#define alloc_thread_info(ti) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1)) 74#define alloc_thread_info(ti) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
62#define free_thread_info(ti) free_pages((unsigned long) (ti), 1) 75#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
63 76
@@ -65,7 +78,7 @@ static inline struct thread_info *current_thread_info(void)
65 78
66/* how to get the thread information struct from ASM */ 79/* how to get the thread information struct from ASM */
67#define GET_THREAD_INFO(reg) \ 80#define GET_THREAD_INFO(reg) \
68 stc r7_bank, reg 81 stc r7_bank, reg
69 82
70#endif 83#endif
71 84