aboutsummaryrefslogtreecommitdiffstats
path: root/arch/microblaze/kernel/head.S
diff options
context:
space:
mode:
authorMichal Simek <monstr@monstr.eu>2010-02-08 16:41:38 +0100
committerMichal Simek <monstr@monstr.eu>2012-03-23 09:28:19 +0100
commite02db0aa3e1976ae4e23a66077d252a2f3ba74c7 (patch)
treeed16439c89abca6be4770f654c7c458ff0f6512f /arch/microblaze/kernel/head.S
parentmicroblaze: Introduce TLB skip size (diff)
downloadlinux-dev-e02db0aa3e1976ae4e23a66077d252a2f3ba74c7.tar.xz
linux-dev-e02db0aa3e1976ae4e23a66077d252a2f3ba74c7.zip
microblaze: Handle TLB skip size dynamically
This patch fix the problem with rootfs on JFFS2 with early printk console turned on. The origin version used TLB63 for temporary early printk mapping. The code expect that kernel is not able to use all 64 TLB entries till early printk console is remapped by ioremap. After that temporary mapping on TLB63 is silently lost. This expectation give the opportunity to have early console pretty early. Microblaze systems with JFFS2 rootfs with early printk console turned on used more than 64 TLB entries before kernel can remap early console. Based on that kernel does access to bad area because early printk mapping is rewritten. This patch introduces tlb_skip variable which dynamically stores number of skipped TLB entries from the TLB0. skip_tlb=2 means that TLB0 and TLB1 should be skipped. MICROBLAZE_TLB_SKIP defines how many TLB is skipped at the kernel start. They can be used for user purpose. TLB 63 is used for temporary LMB mapping (MICROBLAZE_LMB_TLB_ID). Also clean TLBLO when kernel starts. For specific kernel sizes kernel can use just one TLB. Detect this case and use the second TLB for general purpose. Change _tlbia function to flush TLB entries from tlb_skip to TLB_SIZE. Export tlb_skip size through debugfs. Signed-off-by: Michal Simek <monstr@monstr.eu>
Diffstat (limited to 'arch/microblaze/kernel/head.S')
-rw-r--r--arch/microblaze/kernel/head.S42
1 files changed, 27 insertions, 15 deletions
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:
_invalidate:
mts rtlbx, r3
mts rtlbhi, r0 /* flush: ensure V is clear */
+ mts rtlblo, r0
bgtid r3, _invalidate /* loop for all entries */
addik r3, r3, -1
/* sync */
@@ -224,8 +225,14 @@ tlb_end:
andi r4,r4,0xfffffc00 /* Mask off the real page number */
ori r4,r4,(TLB_WR | TLB_EX) /* Set the write and execute bits */
- /* TLB0 can be zeroes that's why we not setup it */
- beqi r9, jump_over
+ /*
+ * TLB0 is always used - check if is not zero (r9 stores TLB0 value)
+ * if is use TLB1 value and clear it (r10 stores TLB1 value)
+ */
+ bnei r9, tlb0_not_zero
+ add r9, r10, r0
+ add r10, r0, r0
+tlb0_not_zero:
/* look at the code below */
ori r30, r0, 0x200
@@ -239,18 +246,21 @@ tlb_end:
bneid r29, 1f
addik r30, r30, 0x80
1:
- ori r11, r30, 0
-
andi r3,r3,0xfffffc00 /* Mask off the effective page number */
ori r3,r3,(TLB_VALID)
- or r3, r3, r11
+ or r3, r3, r30
- mts rtlbx,r0 /* TLB slow 0 */
+ /* Load tlb_skip size value which is index to first unused TLB entry */
+ lwi r11, r0, TOPHYS(tlb_skip)
+ mts rtlbx,r11 /* TLB slow 0 */
mts rtlblo,r4 /* Load the data portion of the entry */
mts rtlbhi,r3 /* Load the tag portion of the entry */
-jump_over:
+ /* Increase tlb_skip size */
+ addik r11, r11, 1
+ swi r11, r0, TOPHYS(tlb_skip)
+
/* TLB1 can be zeroes that's why we not setup it */
beqi r10, jump_over2
@@ -266,27 +276,30 @@ jump_over:
bneid r29, 1f
addik r30, r30, 0x80
1:
- ori r12, r30, 0
-
addk r4, r4, r9 /* previous addr + TLB0 size */
addk r3, r3, r9
andi r3,r3,0xfffffc00 /* Mask off the effective page number */
ori r3,r3,(TLB_VALID)
- or r3, r3, r12
+ or r3, r3, r30
- ori r6,r0,1 /* TLB slot 1 */
- mts rtlbx,r6
+ lwi r11, r0, TOPHYS(tlb_skip)
+ mts rtlbx, r11 /* r11 is used from TLB0 */
mts rtlblo,r4 /* Load the data portion of the entry */
mts rtlbhi,r3 /* Load the tag portion of the entry */
+ /* Increase tlb_skip size */
+ addik r11, r11, 1
+ swi r11, r0, TOPHYS(tlb_skip)
+
jump_over2:
/*
* Load a TLB entry for LMB, since we need access to
* the exception vectors, using a 4k real==virtual mapping.
*/
- ori r6,r0,3 /* TLB slot 3 */
+ /* Use temporary TLB_ID for LMB - clear this temporary mapping later */
+ ori r6, r0, MICROBLAZE_LMB_TLB_ID
mts rtlbx,r6
ori r4,r0,(TLB_WR | TLB_EX)
@@ -355,8 +368,7 @@ start_here:
/* Load up the kernel context */
kernel_load_context:
- # Keep entry 0 and 1 valid. Entry 3 mapped to LMB can go away.
- ori r5,r0,3
+ ori r5, r0, MICROBLAZE_LMB_TLB_ID
mts rtlbx,r5
nop
mts rtlbhi,r0