diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/microblaze/include/asm/mmu.h | 13 | ||||
-rw-r--r-- | arch/microblaze/kernel/early_printk.c | 14 | ||||
-rw-r--r-- | arch/microblaze/kernel/head.S | 42 | ||||
-rw-r--r-- | arch/microblaze/kernel/hw_exception_handler.S | 10 | ||||
-rw-r--r-- | arch/microblaze/kernel/misc.S | 13 | ||||
-rw-r--r-- | arch/microblaze/kernel/setup.c | 13 |
6 files changed, 83 insertions, 22 deletions
diff --git a/arch/microblaze/include/asm/mmu.h b/arch/microblaze/include/asm/mmu.h index 5198de8b1224..1f9edddf7f4b 100644 --- a/arch/microblaze/include/asm/mmu.h +++ b/arch/microblaze/include/asm/mmu.h | |||
@@ -56,6 +56,12 @@ typedef struct _SEGREG { | |||
56 | 56 | ||
57 | extern void _tlbie(unsigned long va); /* invalidate a TLB entry */ | 57 | extern void _tlbie(unsigned long va); /* invalidate a TLB entry */ |
58 | extern void _tlbia(void); /* invalidate all TLB entries */ | 58 | extern void _tlbia(void); /* invalidate all TLB entries */ |
59 | |||
60 | /* | ||
61 | * tlb_skip size stores actual number skipped TLBs from TLB0 - every directy TLB | ||
62 | * mapping has to increase tlb_skip size. | ||
63 | */ | ||
64 | extern u32 tlb_skip; | ||
59 | # endif /* __ASSEMBLY__ */ | 65 | # endif /* __ASSEMBLY__ */ |
60 | 66 | ||
61 | /* | 67 | /* |
@@ -68,7 +74,12 @@ extern void _tlbia(void); /* invalidate all TLB entries */ | |||
68 | */ | 74 | */ |
69 | 75 | ||
70 | # define MICROBLAZE_TLB_SIZE 64 | 76 | # define MICROBLAZE_TLB_SIZE 64 |
71 | # define MICROBLAZE_TLB_SKIP 2 | 77 | |
78 | /* For cases when you want to skip some TLB entries */ | ||
79 | # define MICROBLAZE_TLB_SKIP 0 | ||
80 | |||
81 | /* Use the last TLB for temporary access to LMB */ | ||
82 | # define MICROBLAZE_LMB_TLB_ID 63 | ||
72 | 83 | ||
73 | /* | 84 | /* |
74 | * TLB entries are defined by a "high" tag portion and a "low" data | 85 | * TLB entries are defined by a "high" tag portion and a "low" data |
diff --git a/arch/microblaze/kernel/early_printk.c b/arch/microblaze/kernel/early_printk.c index 742c247792ce..ec485876d0d0 100644 --- a/arch/microblaze/kernel/early_printk.c +++ b/arch/microblaze/kernel/early_printk.c | |||
@@ -175,6 +175,20 @@ void __init remap_early_printk(void) | |||
175 | base_addr); | 175 | base_addr); |
176 | base_addr = (u32) ioremap(base_addr, PAGE_SIZE); | 176 | base_addr = (u32) ioremap(base_addr, PAGE_SIZE); |
177 | printk(KERN_CONT "0x%x\n", base_addr); | 177 | printk(KERN_CONT "0x%x\n", base_addr); |
178 | |||
179 | /* | ||
180 | * Early console is on the top of skipped TLB entries | ||
181 | * decrease tlb_skip size ensure that hardcoded TLB entry will be | ||
182 | * used by generic algorithm | ||
183 | * FIXME check if early console mapping is on the top by rereading | ||
184 | * TLB entry and compare baseaddr | ||
185 | * mts rtlbx, (tlb_skip - 1) | ||
186 | * nop | ||
187 | * mfs rX, rtlblo | ||
188 | * nop | ||
189 | * cmp rX, orig_base_addr | ||
190 | */ | ||
191 | tlb_skip -= 1; | ||
178 | } | 192 | } |
179 | 193 | ||
180 | void __init disable_early_printk(void) | 194 | void __init disable_early_printk(void) |
diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S index 49dd48f9e6ec..98b17f9f904b 100644 --- a/arch/microblaze/kernel/head.S +++ b/arch/microblaze/kernel/head.S | |||
@@ -149,6 +149,7 @@ _copy_bram: | |||
149 | _invalidate: | 149 | _invalidate: |
150 | mts rtlbx, r3 | 150 | mts rtlbx, r3 |
151 | mts rtlbhi, r0 /* flush: ensure V is clear */ | 151 | mts rtlbhi, r0 /* flush: ensure V is clear */ |
152 | mts rtlblo, r0 | ||
152 | bgtid r3, _invalidate /* loop for all entries */ | 153 | bgtid r3, _invalidate /* loop for all entries */ |
153 | addik r3, r3, -1 | 154 | addik r3, r3, -1 |
154 | /* sync */ | 155 | /* sync */ |
@@ -224,8 +225,14 @@ tlb_end: | |||
224 | andi r4,r4,0xfffffc00 /* Mask off the real page number */ | 225 | andi r4,r4,0xfffffc00 /* Mask off the real page number */ |
225 | ori r4,r4,(TLB_WR | TLB_EX) /* Set the write and execute bits */ | 226 | ori r4,r4,(TLB_WR | TLB_EX) /* Set the write and execute bits */ |
226 | 227 | ||
227 | /* TLB0 can be zeroes that's why we not setup it */ | 228 | /* |
228 | beqi r9, jump_over | 229 | * TLB0 is always used - check if is not zero (r9 stores TLB0 value) |
230 | * if is use TLB1 value and clear it (r10 stores TLB1 value) | ||
231 | */ | ||
232 | bnei r9, tlb0_not_zero | ||
233 | add r9, r10, r0 | ||
234 | add r10, r0, r0 | ||
235 | tlb0_not_zero: | ||
229 | 236 | ||
230 | /* look at the code below */ | 237 | /* look at the code below */ |
231 | ori r30, r0, 0x200 | 238 | ori r30, r0, 0x200 |
@@ -239,18 +246,21 @@ tlb_end: | |||
239 | bneid r29, 1f | 246 | bneid r29, 1f |
240 | addik r30, r30, 0x80 | 247 | addik r30, r30, 0x80 |
241 | 1: | 248 | 1: |
242 | ori r11, r30, 0 | ||
243 | |||
244 | andi r3,r3,0xfffffc00 /* Mask off the effective page number */ | 249 | andi r3,r3,0xfffffc00 /* Mask off the effective page number */ |
245 | ori r3,r3,(TLB_VALID) | 250 | ori r3,r3,(TLB_VALID) |
246 | or r3, r3, r11 | 251 | or r3, r3, r30 |
247 | 252 | ||
248 | mts rtlbx,r0 /* TLB slow 0 */ | 253 | /* Load tlb_skip size value which is index to first unused TLB entry */ |
254 | lwi r11, r0, TOPHYS(tlb_skip) | ||
255 | mts rtlbx,r11 /* TLB slow 0 */ | ||
249 | 256 | ||
250 | mts rtlblo,r4 /* Load the data portion of the entry */ | 257 | mts rtlblo,r4 /* Load the data portion of the entry */ |
251 | mts rtlbhi,r3 /* Load the tag portion of the entry */ | 258 | mts rtlbhi,r3 /* Load the tag portion of the entry */ |
252 | 259 | ||
253 | jump_over: | 260 | /* Increase tlb_skip size */ |
261 | addik r11, r11, 1 | ||
262 | swi r11, r0, TOPHYS(tlb_skip) | ||
263 | |||
254 | /* TLB1 can be zeroes that's why we not setup it */ | 264 | /* TLB1 can be zeroes that's why we not setup it */ |
255 | beqi r10, jump_over2 | 265 | beqi r10, jump_over2 |
256 | 266 | ||
@@ -266,27 +276,30 @@ jump_over: | |||
266 | bneid r29, 1f | 276 | bneid r29, 1f |
267 | addik r30, r30, 0x80 | 277 | addik r30, r30, 0x80 |
268 | 1: | 278 | 1: |
269 | ori r12, r30, 0 | ||
270 | |||
271 | addk r4, r4, r9 /* previous addr + TLB0 size */ | 279 | addk r4, r4, r9 /* previous addr + TLB0 size */ |
272 | addk r3, r3, r9 | 280 | addk r3, r3, r9 |
273 | 281 | ||
274 | andi r3,r3,0xfffffc00 /* Mask off the effective page number */ | 282 | andi r3,r3,0xfffffc00 /* Mask off the effective page number */ |
275 | ori r3,r3,(TLB_VALID) | 283 | ori r3,r3,(TLB_VALID) |
276 | or r3, r3, r12 | 284 | or r3, r3, r30 |
277 | 285 | ||
278 | ori r6,r0,1 /* TLB slot 1 */ | 286 | lwi r11, r0, TOPHYS(tlb_skip) |
279 | mts rtlbx,r6 | 287 | mts rtlbx, r11 /* r11 is used from TLB0 */ |
280 | 288 | ||
281 | mts rtlblo,r4 /* Load the data portion of the entry */ | 289 | mts rtlblo,r4 /* Load the data portion of the entry */ |
282 | mts rtlbhi,r3 /* Load the tag portion of the entry */ | 290 | mts rtlbhi,r3 /* Load the tag portion of the entry */ |
283 | 291 | ||
292 | /* Increase tlb_skip size */ | ||
293 | addik r11, r11, 1 | ||
294 | swi r11, r0, TOPHYS(tlb_skip) | ||
295 | |||
284 | jump_over2: | 296 | jump_over2: |
285 | /* | 297 | /* |
286 | * Load a TLB entry for LMB, since we need access to | 298 | * Load a TLB entry for LMB, since we need access to |
287 | * the exception vectors, using a 4k real==virtual mapping. | 299 | * the exception vectors, using a 4k real==virtual mapping. |
288 | */ | 300 | */ |
289 | ori r6,r0,3 /* TLB slot 3 */ | 301 | /* Use temporary TLB_ID for LMB - clear this temporary mapping later */ |
302 | ori r6, r0, MICROBLAZE_LMB_TLB_ID | ||
290 | mts rtlbx,r6 | 303 | mts rtlbx,r6 |
291 | 304 | ||
292 | ori r4,r0,(TLB_WR | TLB_EX) | 305 | ori r4,r0,(TLB_WR | TLB_EX) |
@@ -355,8 +368,7 @@ start_here: | |||
355 | 368 | ||
356 | /* Load up the kernel context */ | 369 | /* Load up the kernel context */ |
357 | kernel_load_context: | 370 | kernel_load_context: |
358 | # Keep entry 0 and 1 valid. Entry 3 mapped to LMB can go away. | 371 | ori r5, r0, MICROBLAZE_LMB_TLB_ID |
359 | ori r5,r0,3 | ||
360 | mts rtlbx,r5 | 372 | mts rtlbx,r5 |
361 | nop | 373 | nop |
362 | mts rtlbhi,r0 | 374 | mts rtlbhi,r0 |
diff --git a/arch/microblaze/kernel/hw_exception_handler.S b/arch/microblaze/kernel/hw_exception_handler.S index b7249f4215a2..aa510f450ac6 100644 --- a/arch/microblaze/kernel/hw_exception_handler.S +++ b/arch/microblaze/kernel/hw_exception_handler.S | |||
@@ -820,9 +820,15 @@ ex_handler_done: | |||
820 | * Upon exit, we reload everything and RFI. | 820 | * Upon exit, we reload everything and RFI. |
821 | * A common place to load the TLB. | 821 | * A common place to load the TLB. |
822 | */ | 822 | */ |
823 | .section .data | ||
824 | .align 4 | ||
825 | .global tlb_skip | ||
826 | tlb_skip: | ||
827 | .long MICROBLAZE_TLB_SKIP | ||
823 | tlb_index: | 828 | tlb_index: |
824 | /* MS: storing last used tlb index */ | 829 | /* MS: storing last used tlb index */ |
825 | .long (MICROBLAZE_TLB_SKIP - 1) | 830 | .long MICROBLAZE_TLB_SIZE/2 |
831 | .previous | ||
826 | finish_tlb_load: | 832 | finish_tlb_load: |
827 | /* MS: load the last used TLB index. */ | 833 | /* MS: load the last used TLB index. */ |
828 | lwi r5, r0, TOPHYS(tlb_index) | 834 | lwi r5, r0, TOPHYS(tlb_index) |
@@ -833,7 +839,7 @@ ex_handler_done: | |||
833 | ori r6, r0, 1 | 839 | ori r6, r0, 1 |
834 | cmp r31, r5, r6 | 840 | cmp r31, r5, r6 |
835 | blti r31, ex12 | 841 | blti r31, ex12 |
836 | addik r5, r6, MICROBLAZE_TLB_SKIP - 1 | 842 | lwi r5, r0, TOPHYS(tlb_skip) |
837 | ex12: | 843 | ex12: |
838 | /* MS: save back current TLB index */ | 844 | /* MS: save back current TLB index */ |
839 | swi r5, r0, TOPHYS(tlb_index) | 845 | swi r5, r0, TOPHYS(tlb_index) |
diff --git a/arch/microblaze/kernel/misc.S b/arch/microblaze/kernel/misc.S index c9090d7973f6..1dafddeb8a0b 100644 --- a/arch/microblaze/kernel/misc.S +++ b/arch/microblaze/kernel/misc.S | |||
@@ -29,16 +29,16 @@ | |||
29 | .type _tlbia, @function | 29 | .type _tlbia, @function |
30 | .align 4; | 30 | .align 4; |
31 | _tlbia: | 31 | _tlbia: |
32 | addik r12, r0, MICROBLAZE_TLB_SIZE - 1 /* flush all entries (63 - 3) */ | 32 | lwi r12, r0, tlb_skip; |
33 | /* isync */ | 33 | /* isync */ |
34 | _tlbia_1: | 34 | _tlbia_1: |
35 | mts rtlbx, r12 | 35 | mts rtlbx, r12 |
36 | nop | 36 | nop |
37 | mts rtlbhi, r0 /* flush: ensure V is clear */ | 37 | mts rtlbhi, r0 /* flush: ensure V is clear */ |
38 | nop | 38 | nop |
39 | addik r11, r12, -MICROBLAZE_TLB_SKIP | 39 | rsubi r11, r12, MICROBLAZE_TLB_SIZE - 1 |
40 | bneid r11, _tlbia_1 /* loop for all entries */ | 40 | bneid r11, _tlbia_1 /* loop for all entries */ |
41 | addik r12, r12, -1 | 41 | addik r12, r12, 1 |
42 | /* sync */ | 42 | /* sync */ |
43 | rtsd r15, 8 | 43 | rtsd r15, 8 |
44 | nop | 44 | nop |
@@ -75,7 +75,7 @@ early_console_reg_tlb_alloc: | |||
75 | * Load a TLB entry for the UART, so that microblaze_progress() can use | 75 | * Load a TLB entry for the UART, so that microblaze_progress() can use |
76 | * the UARTs nice and early. We use a 4k real==virtual mapping. | 76 | * the UARTs nice and early. We use a 4k real==virtual mapping. |
77 | */ | 77 | */ |
78 | ori r4, r0, 63 | 78 | lwi r4, r0, tlb_skip |
79 | mts rtlbx, r4 /* TLB slot 63 */ | 79 | mts rtlbx, r4 /* TLB slot 63 */ |
80 | 80 | ||
81 | or r4,r5,r0 | 81 | or r4,r5,r0 |
@@ -89,6 +89,11 @@ early_console_reg_tlb_alloc: | |||
89 | nop | 89 | nop |
90 | mts rtlbhi,r5 /* Load the tag portion of the entry */ | 90 | mts rtlbhi,r5 /* Load the tag portion of the entry */ |
91 | nop | 91 | nop |
92 | |||
93 | lwi r5, r0, tlb_skip | ||
94 | addik r5, r5, 1 | ||
95 | swi r5, r0, tlb_skip | ||
96 | |||
92 | rtsd r15, 8 | 97 | rtsd r15, 8 |
93 | nop | 98 | nop |
94 | 99 | ||
diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index a1fa2a5813bf..e4f5956ee13c 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c | |||
@@ -208,6 +208,19 @@ static int microblaze_debugfs_init(void) | |||
208 | return of_debugfs_root == NULL; | 208 | return of_debugfs_root == NULL; |
209 | } | 209 | } |
210 | arch_initcall(microblaze_debugfs_init); | 210 | arch_initcall(microblaze_debugfs_init); |
211 | |||
212 | static int __init debugfs_tlb(void) | ||
213 | { | ||
214 | struct dentry *d; | ||
215 | |||
216 | if (!of_debugfs_root) | ||
217 | return -ENODEV; | ||
218 | |||
219 | d = debugfs_create_u32("tlb_skip", S_IRUGO, of_debugfs_root, &tlb_skip); | ||
220 | if (!d) | ||
221 | return -ENOMEM; | ||
222 | } | ||
223 | device_initcall(debugfs_tlb); | ||
211 | #endif | 224 | #endif |
212 | 225 | ||
213 | static int dflt_bus_notify(struct notifier_block *nb, | 226 | static int dflt_bus_notify(struct notifier_block *nb, |