diff options
-rw-r--r-- | Documentation/sh/register-banks.txt | 33 | ||||
-rw-r--r-- | include/asm-sh/system.h | 17 | ||||
-rw-r--r-- | include/asm-sh/thread_info.h | 17 |
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 | |||
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) | ||
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 */ |
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 | 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 | ||
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 | static __inline__ void local_irq_disable(void) | 168 | static __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 */ |
52 | static inline struct thread_info *current_thread_info(void) | 54 | static 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 | ||