aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm/fsl_booke_mmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/mm/fsl_booke_mmu.c')
-rw-r--r--arch/powerpc/mm/fsl_booke_mmu.c42
1 files changed, 36 insertions, 6 deletions
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c
index ca956c83e3a2..95deb9fdf92f 100644
--- a/arch/powerpc/mm/fsl_booke_mmu.c
+++ b/arch/powerpc/mm/fsl_booke_mmu.c
@@ -231,7 +231,7 @@ void __init adjust_total_lowmem(void)
231 231
232 i = switch_to_as1(); 232 i = switch_to_as1();
233 __max_low_memory = map_mem_in_cams(ram, CONFIG_LOWMEM_CAM_NUM); 233 __max_low_memory = map_mem_in_cams(ram, CONFIG_LOWMEM_CAM_NUM);
234 restore_to_as0(i); 234 restore_to_as0(i, 0, 0);
235 235
236 pr_info("Memory CAM mapping: "); 236 pr_info("Memory CAM mapping: ");
237 for (i = 0; i < tlbcam_index - 1; i++) 237 for (i = 0; i < tlbcam_index - 1; i++)
@@ -252,17 +252,25 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base,
252} 252}
253 253
254#ifdef CONFIG_RELOCATABLE 254#ifdef CONFIG_RELOCATABLE
255notrace void __init relocate_init(phys_addr_t start) 255int __initdata is_second_reloc;
256notrace void __init relocate_init(u64 dt_ptr, phys_addr_t start)
256{ 257{
257 unsigned long base = KERNELBASE; 258 unsigned long base = KERNELBASE;
258 259
260 kernstart_addr = start;
261 if (is_second_reloc) {
262 virt_phys_offset = PAGE_OFFSET - memstart_addr;
263 return;
264 }
265
259 /* 266 /*
260 * Relocatable kernel support based on processing of dynamic 267 * Relocatable kernel support based on processing of dynamic
261 * relocation entries. 268 * relocation entries. Before we get the real memstart_addr,
262 * Compute the virt_phys_offset : 269 * We will compute the virt_phys_offset like this:
263 * virt_phys_offset = stext.run - kernstart_addr 270 * virt_phys_offset = stext.run - kernstart_addr
264 * 271 *
265 * stext.run = (KERNELBASE & ~0x3ffffff) + (kernstart_addr & 0x3ffffff) 272 * stext.run = (KERNELBASE & ~0x3ffffff) +
273 * (kernstart_addr & 0x3ffffff)
266 * When we relocate, we have : 274 * When we relocate, we have :
267 * 275 *
268 * (kernstart_addr & 0x3ffffff) = (stext.run & 0x3ffffff) 276 * (kernstart_addr & 0x3ffffff) = (stext.run & 0x3ffffff)
@@ -272,10 +280,32 @@ notrace void __init relocate_init(phys_addr_t start)
272 * (kernstart_addr & ~0x3ffffff) 280 * (kernstart_addr & ~0x3ffffff)
273 * 281 *
274 */ 282 */
275 kernstart_addr = start;
276 start &= ~0x3ffffff; 283 start &= ~0x3ffffff;
277 base &= ~0x3ffffff; 284 base &= ~0x3ffffff;
278 virt_phys_offset = base - start; 285 virt_phys_offset = base - start;
286 early_get_first_memblock_info(__va(dt_ptr), NULL);
287 /*
288 * We now get the memstart_addr, then we should check if this
289 * address is the same as what the PAGE_OFFSET map to now. If
290 * not we have to change the map of PAGE_OFFSET to memstart_addr
291 * and do a second relocation.
292 */
293 if (start != memstart_addr) {
294 int n;
295 long offset = start - memstart_addr;
296
297 is_second_reloc = 1;
298 n = switch_to_as1();
299 /* map a 64M area for the second relocation */
300 if (memstart_addr > start)
301 map_mem_in_cams(0x4000000, CONFIG_LOWMEM_CAM_NUM);
302 else
303 map_mem_in_cams_addr(start, PAGE_OFFSET + offset,
304 0x4000000, CONFIG_LOWMEM_CAM_NUM);
305 restore_to_as0(n, offset, __va(dt_ptr));
306 /* We should never reach here */
307 panic("Relocation error");
308 }
279} 309}
280#endif 310#endif
281#endif 311#endif