diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/microblaze/Kconfig | 4 | ||||
-rw-r--r-- | arch/microblaze/include/asm/setup.h | 3 | ||||
-rw-r--r-- | arch/microblaze/include/asm/system.h | 1 | ||||
-rw-r--r-- | arch/microblaze/kernel/head.S | 98 | ||||
-rw-r--r-- | arch/microblaze/kernel/setup.c | 11 | ||||
-rw-r--r-- | arch/microblaze/mm/init.c | 14 |
6 files changed, 120 insertions, 11 deletions
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index 86ae27871f41..d64c10093b40 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig | |||
@@ -259,6 +259,10 @@ config MICROBLAZE_32K_PAGES | |||
259 | 259 | ||
260 | endchoice | 260 | endchoice |
261 | 261 | ||
262 | config KERNEL_PAD | ||
263 | hex "Kernel PAD for unpacking" if ADVANCED_OPTIONS | ||
264 | default "0x80000" if MMU | ||
265 | |||
262 | endmenu | 266 | endmenu |
263 | 267 | ||
264 | source "mm/Kconfig" | 268 | source "mm/Kconfig" |
diff --git a/arch/microblaze/include/asm/setup.h b/arch/microblaze/include/asm/setup.h index 6c72ed7eba98..9f195c094731 100644 --- a/arch/microblaze/include/asm/setup.h +++ b/arch/microblaze/include/asm/setup.h | |||
@@ -39,7 +39,8 @@ extern void of_platform_reset_gpio_probe(void); | |||
39 | void time_init(void); | 39 | void time_init(void); |
40 | void init_IRQ(void); | 40 | void init_IRQ(void); |
41 | void machine_early_init(const char *cmdline, unsigned int ram, | 41 | void machine_early_init(const char *cmdline, unsigned int ram, |
42 | unsigned int fdt, unsigned int msr); | 42 | unsigned int fdt, unsigned int msr, unsigned int tlb0, |
43 | unsigned int tlb1); | ||
43 | 44 | ||
44 | void machine_restart(char *cmd); | 45 | void machine_restart(char *cmd); |
45 | void machine_shutdown(void); | 46 | void machine_shutdown(void); |
diff --git a/arch/microblaze/include/asm/system.h b/arch/microblaze/include/asm/system.h index 5a433cbaafb3..01228d2b1351 100644 --- a/arch/microblaze/include/asm/system.h +++ b/arch/microblaze/include/asm/system.h | |||
@@ -83,6 +83,7 @@ void default_idle(void); | |||
83 | void free_init_pages(char *what, unsigned long begin, unsigned long end); | 83 | void free_init_pages(char *what, unsigned long begin, unsigned long end); |
84 | void free_initmem(void); | 84 | void free_initmem(void); |
85 | extern char *klimit; | 85 | extern char *klimit; |
86 | extern unsigned long kernel_tlb; | ||
86 | extern void ret_from_fork(void); | 87 | extern void ret_from_fork(void); |
87 | 88 | ||
88 | extern void *alloc_maybe_bootmem(size_t size, gfp_t mask); | 89 | extern void *alloc_maybe_bootmem(size_t size, gfp_t mask); |
diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S index 441dad80558c..49dd48f9e6ec 100644 --- a/arch/microblaze/kernel/head.S +++ b/arch/microblaze/kernel/head.S | |||
@@ -168,6 +168,53 @@ _invalidate: | |||
168 | addik r3,r0, CONFIG_KERNEL_START /* Load the kernel virtual address */ | 168 | addik r3,r0, CONFIG_KERNEL_START /* Load the kernel virtual address */ |
169 | tophys(r4,r3) /* Load the kernel physical address */ | 169 | tophys(r4,r3) /* Load the kernel physical address */ |
170 | 170 | ||
171 | /* start to do TLB calculation */ | ||
172 | addik r12, r0, _end | ||
173 | rsub r12, r3, r12 | ||
174 | addik r12, r12, CONFIG_KERNEL_PAD /* that's the pad */ | ||
175 | |||
176 | or r9, r0, r0 /* TLB0 = 0 */ | ||
177 | or r10, r0, r0 /* TLB1 = 0 */ | ||
178 | |||
179 | addik r11, r12, -0x1000000 | ||
180 | bgei r11, GT16 /* size is greater than 16MB */ | ||
181 | addik r11, r12, -0x0800000 | ||
182 | bgei r11, GT8 /* size is greater than 8MB */ | ||
183 | addik r11, r12, -0x0400000 | ||
184 | bgei r11, GT4 /* size is greater than 4MB */ | ||
185 | /* size is less than 4MB */ | ||
186 | addik r11, r12, -0x0200000 | ||
187 | bgei r11, GT2 /* size is greater than 2MB */ | ||
188 | addik r9, r0, 0x0100000 /* TLB0 must be 1MB */ | ||
189 | addik r11, r12, -0x0100000 | ||
190 | bgei r11, GT1 /* size is greater than 1MB */ | ||
191 | /* TLB1 is 0 which is setup above */ | ||
192 | bri tlb_end | ||
193 | GT4: /* r11 contains the rest - will be either 1 or 4 */ | ||
194 | ori r9, r0, 0x400000 /* TLB0 is 4MB */ | ||
195 | bri TLB1 | ||
196 | GT16: /* TLB0 is 16MB */ | ||
197 | addik r9, r0, 0x1000000 /* means TLB0 is 16MB */ | ||
198 | TLB1: | ||
199 | /* must be used r2 because of substract if failed */ | ||
200 | addik r2, r11, -0x0400000 | ||
201 | bgei r2, GT20 /* size is greater than 16MB */ | ||
202 | /* size is >16MB and <20MB */ | ||
203 | addik r11, r11, -0x0100000 | ||
204 | bgei r11, GT17 /* size is greater than 17MB */ | ||
205 | /* kernel is >16MB and < 17MB */ | ||
206 | GT1: | ||
207 | addik r10, r0, 0x0100000 /* means TLB1 is 1MB */ | ||
208 | bri tlb_end | ||
209 | GT2: /* TLB0 is 0 and TLB1 will be 4MB */ | ||
210 | GT17: /* TLB1 is 4MB - kernel size <20MB */ | ||
211 | addik r10, r0, 0x0400000 /* means TLB1 is 4MB */ | ||
212 | bri tlb_end | ||
213 | GT8: /* TLB0 is still zero that's why I can use only TLB1 */ | ||
214 | GT20: /* TLB1 is 16MB - kernel size >20MB */ | ||
215 | addik r10, r0, 0x1000000 /* means TLB1 is 16MB */ | ||
216 | tlb_end: | ||
217 | |||
171 | /* | 218 | /* |
172 | * Configure and load two entries into TLB slots 0 and 1. | 219 | * Configure and load two entries into TLB slots 0 and 1. |
173 | * In case we are pinning TLBs, these are reserved in by the | 220 | * In case we are pinning TLBs, these are reserved in by the |
@@ -177,16 +224,56 @@ _invalidate: | |||
177 | andi r4,r4,0xfffffc00 /* Mask off the real page number */ | 224 | andi r4,r4,0xfffffc00 /* Mask off the real page number */ |
178 | ori r4,r4,(TLB_WR | TLB_EX) /* Set the write and execute bits */ | 225 | ori r4,r4,(TLB_WR | TLB_EX) /* Set the write and execute bits */ |
179 | 226 | ||
227 | /* TLB0 can be zeroes that's why we not setup it */ | ||
228 | beqi r9, jump_over | ||
229 | |||
230 | /* look at the code below */ | ||
231 | ori r30, r0, 0x200 | ||
232 | andi r29, r9, 0x100000 | ||
233 | bneid r29, 1f | ||
234 | addik r30, r30, 0x80 | ||
235 | andi r29, r9, 0x400000 | ||
236 | bneid r29, 1f | ||
237 | addik r30, r30, 0x80 | ||
238 | andi r29, r9, 0x1000000 | ||
239 | bneid r29, 1f | ||
240 | addik r30, r30, 0x80 | ||
241 | 1: | ||
242 | ori r11, r30, 0 | ||
243 | |||
180 | andi r3,r3,0xfffffc00 /* Mask off the effective page number */ | 244 | andi r3,r3,0xfffffc00 /* Mask off the effective page number */ |
181 | ori r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_16M)) | 245 | ori r3,r3,(TLB_VALID) |
246 | or r3, r3, r11 | ||
182 | 247 | ||
183 | mts rtlbx,r0 /* TLB slow 0 */ | 248 | mts rtlbx,r0 /* TLB slow 0 */ |
184 | 249 | ||
185 | mts rtlblo,r4 /* Load the data portion of the entry */ | 250 | mts rtlblo,r4 /* Load the data portion of the entry */ |
186 | mts rtlbhi,r3 /* Load the tag portion of the entry */ | 251 | mts rtlbhi,r3 /* Load the tag portion of the entry */ |
187 | 252 | ||
188 | addik r4, r4, 0x01000000 /* Map next 16 M entries */ | 253 | jump_over: |
189 | addik r3, r3, 0x01000000 | 254 | /* TLB1 can be zeroes that's why we not setup it */ |
255 | beqi r10, jump_over2 | ||
256 | |||
257 | /* look at the code below */ | ||
258 | ori r30, r0, 0x200 | ||
259 | andi r29, r10, 0x100000 | ||
260 | bneid r29, 1f | ||
261 | addik r30, r30, 0x80 | ||
262 | andi r29, r10, 0x400000 | ||
263 | bneid r29, 1f | ||
264 | addik r30, r30, 0x80 | ||
265 | andi r29, r10, 0x1000000 | ||
266 | bneid r29, 1f | ||
267 | addik r30, r30, 0x80 | ||
268 | 1: | ||
269 | ori r12, r30, 0 | ||
270 | |||
271 | addk r4, r4, r9 /* previous addr + TLB0 size */ | ||
272 | addk r3, r3, r9 | ||
273 | |||
274 | andi r3,r3,0xfffffc00 /* Mask off the effective page number */ | ||
275 | ori r3,r3,(TLB_VALID) | ||
276 | or r3, r3, r12 | ||
190 | 277 | ||
191 | ori r6,r0,1 /* TLB slot 1 */ | 278 | ori r6,r0,1 /* TLB slot 1 */ |
192 | mts rtlbx,r6 | 279 | mts rtlbx,r6 |
@@ -194,6 +281,7 @@ _invalidate: | |||
194 | mts rtlblo,r4 /* Load the data portion of the entry */ | 281 | mts rtlblo,r4 /* Load the data portion of the entry */ |
195 | mts rtlbhi,r3 /* Load the tag portion of the entry */ | 282 | mts rtlbhi,r3 /* Load the tag portion of the entry */ |
196 | 283 | ||
284 | jump_over2: | ||
197 | /* | 285 | /* |
198 | * Load a TLB entry for LMB, since we need access to | 286 | * Load a TLB entry for LMB, since we need access to |
199 | * the exception vectors, using a 4k real==virtual mapping. | 287 | * the exception vectors, using a 4k real==virtual mapping. |
@@ -237,8 +325,8 @@ start_here: | |||
237 | * Please see $(ARCH)/mach-$(SUBARCH)/setup.c for | 325 | * Please see $(ARCH)/mach-$(SUBARCH)/setup.c for |
238 | * the function. | 326 | * the function. |
239 | */ | 327 | */ |
240 | addik r9, r0, machine_early_init | 328 | addik r11, r0, machine_early_init |
241 | brald r15, r9 | 329 | brald r15, r11 |
242 | nop | 330 | nop |
243 | 331 | ||
244 | #ifndef CONFIG_MMU | 332 | #ifndef CONFIG_MMU |
diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index 604cd9dd1333..a1fa2a5813bf 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c | |||
@@ -97,8 +97,11 @@ inline unsigned get_romfs_len(unsigned *addr) | |||
97 | } | 97 | } |
98 | #endif /* CONFIG_MTD_UCLINUX_EBSS */ | 98 | #endif /* CONFIG_MTD_UCLINUX_EBSS */ |
99 | 99 | ||
100 | unsigned long kernel_tlb; | ||
101 | |||
100 | void __init machine_early_init(const char *cmdline, unsigned int ram, | 102 | void __init machine_early_init(const char *cmdline, unsigned int ram, |
101 | unsigned int fdt, unsigned int msr) | 103 | unsigned int fdt, unsigned int msr, unsigned int tlb0, |
104 | unsigned int tlb1) | ||
102 | { | 105 | { |
103 | unsigned long *src, *dst; | 106 | unsigned long *src, *dst; |
104 | unsigned int offset = 0; | 107 | unsigned int offset = 0; |
@@ -145,6 +148,12 @@ void __init machine_early_init(const char *cmdline, unsigned int ram, | |||
145 | setup_early_printk(NULL); | 148 | setup_early_printk(NULL); |
146 | #endif | 149 | #endif |
147 | 150 | ||
151 | /* setup kernel_tlb after BSS cleaning | ||
152 | * Maybe worth to move to asm code */ | ||
153 | kernel_tlb = tlb0 + tlb1; | ||
154 | /* printk("TLB1 0x%08x, TLB0 0x%08x, tlb 0x%x\n", tlb0, | ||
155 | tlb1, kernel_tlb); */ | ||
156 | |||
148 | printk("Ramdisk addr 0x%08x, ", ram); | 157 | printk("Ramdisk addr 0x%08x, ", ram); |
149 | if (fdt) | 158 | if (fdt) |
150 | printk("FDT at 0x%08x\n", fdt); | 159 | printk("FDT at 0x%08x\n", fdt); |
diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c index 95297b13dd9e..ce80823051ba 100644 --- a/arch/microblaze/mm/init.c +++ b/arch/microblaze/mm/init.c | |||
@@ -398,10 +398,16 @@ asmlinkage void __init mmu_init(void) | |||
398 | machine_restart(NULL); | 398 | machine_restart(NULL); |
399 | } | 399 | } |
400 | 400 | ||
401 | if ((u32) memblock.memory.regions[0].size < 0x1000000) { | 401 | if ((u32) memblock.memory.regions[0].size < 0x400000) { |
402 | printk(KERN_EMERG "Memory must be greater than 16MB\n"); | 402 | printk(KERN_EMERG "Memory must be greater than 4MB\n"); |
403 | machine_restart(NULL); | 403 | machine_restart(NULL); |
404 | } | 404 | } |
405 | |||
406 | if ((u32) memblock.memory.regions[0].size < kernel_tlb) { | ||
407 | printk(KERN_EMERG "Kernel size is greater than memory node\n"); | ||
408 | machine_restart(NULL); | ||
409 | } | ||
410 | |||
405 | /* Find main memory where the kernel is */ | 411 | /* Find main memory where the kernel is */ |
406 | memory_start = (u32) memblock.memory.regions[0].base; | 412 | memory_start = (u32) memblock.memory.regions[0].base; |
407 | lowmem_size = memory_size = (u32) memblock.memory.regions[0].size; | 413 | lowmem_size = memory_size = (u32) memblock.memory.regions[0].size; |
@@ -462,11 +468,11 @@ void __init *early_get_page(void) | |||
462 | p = alloc_bootmem_pages(PAGE_SIZE); | 468 | p = alloc_bootmem_pages(PAGE_SIZE); |
463 | } else { | 469 | } else { |
464 | /* | 470 | /* |
465 | * Mem start + 32MB -> here is limit | 471 | * Mem start + kernel_tlb -> here is limit |
466 | * because of mem mapping from head.S | 472 | * because of mem mapping from head.S |
467 | */ | 473 | */ |
468 | p = __va(memblock_alloc_base(PAGE_SIZE, PAGE_SIZE, | 474 | p = __va(memblock_alloc_base(PAGE_SIZE, PAGE_SIZE, |
469 | memory_start + 0x2000000)); | 475 | memory_start + kernel_tlb)); |
470 | } | 476 | } |
471 | return p; | 477 | return p; |
472 | } | 478 | } |