Commit f1517494407b1f1ca0063a756cc30d75e96d433c
1 parent
5283ecb5cc
sh: Cleanup and document register bank usage.
Initial register bank cleanup. Make SR.RB configurable, and add some preliminary documentation on register bank usage within the kernel. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Showing 3 changed files with 64 additions and 3 deletions Side-by-side Diff
Documentation/sh/register-banks.txt
1 | + Notes on register bank usage in the kernel | |
2 | + ========================================== | |
3 | + | |
4 | +Introduction | |
5 | +------------ | |
6 | + | |
7 | +The SH-3 and SH-4 CPU families traditionally include a single partial register | |
8 | +bank (selected by SR.RB, only r0 ... r7 are banked), whereas other families | |
9 | +may have more full-featured banking or simply no such capabilities at all. | |
10 | + | |
11 | +SR.RB banking | |
12 | +------------- | |
13 | + | |
14 | +In the case of this type of banking, banked registers are mapped directly to | |
15 | +r0 ... r7 if SR.RB is set to the bank we are interested in, otherwise ldc/stc | |
16 | +can still be used to reference the banked registers (as r0_bank ... r7_bank) | |
17 | +when in the context of another bank. The developer must keep the SR.RB value | |
18 | +in mind when writing code that utilizes these banked registers, for obvious | |
19 | +reasons. Userspace is also not able to poke at the bank1 values, so these can | |
20 | +be used rather effectively as scratch registers by the kernel. | |
21 | + | |
22 | +Presently 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) |
include/asm-sh/system.h
... | ... | @@ -136,7 +136,8 @@ |
136 | 136 | #define set_mb(var, value) do { xchg(&var, value); } while (0) |
137 | 137 | |
138 | 138 | /* Interrupt Control */ |
139 | -static __inline__ void local_irq_enable(void) | |
139 | +#ifdef CONFIG_CPU_HAS_SR_RB | |
140 | +static inline void local_irq_enable(void) | |
140 | 141 | { |
141 | 142 | unsigned long __dummy0, __dummy1; |
142 | 143 | |
... | ... | @@ -149,6 +150,20 @@ |
149 | 150 | : "1" (~0x000000f0) |
150 | 151 | : "memory"); |
151 | 152 | } |
153 | +#else | |
154 | +static 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 | |
153 | 168 | static __inline__ void local_irq_disable(void) |
154 | 169 | { |
include/asm-sh/thread_info.h
... | ... | @@ -48,16 +48,29 @@ |
48 | 48 | #define init_thread_info (init_thread_union.thread_info) |
49 | 49 | #define init_stack (init_thread_union.stack) |
50 | 50 | |
51 | +#define THREAD_SIZE (2*PAGE_SIZE) | |
52 | + | |
51 | 53 | /* how to get the thread information struct from C */ |
52 | 54 | static inline struct thread_info *current_thread_info(void) |
53 | 55 | { |
54 | 56 | struct thread_info *ti; |
57 | +#ifdef CONFIG_CPU_HAS_SR_RB | |
55 | 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 | 70 | return ti; |
57 | 71 | } |
58 | 72 | |
59 | 73 | /* thread information allocation */ |
60 | -#define THREAD_SIZE (2*PAGE_SIZE) | |
61 | 74 | #define alloc_thread_info(ti) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1)) |
62 | 75 | #define free_thread_info(ti) free_pages((unsigned long) (ti), 1) |
63 | 76 | |
... | ... | @@ -65,7 +78,7 @@ |
65 | 78 | |
66 | 79 | /* how to get the thread information struct from ASM */ |
67 | 80 | #define GET_THREAD_INFO(reg) \ |
68 | - stc r7_bank, reg | |
81 | + stc r7_bank, reg | |
69 | 82 | |
70 | 83 | #endif |
71 | 84 |