diff options
Diffstat (limited to 'arch/powerpc/mm/fsl_booke_mmu.c')
-rw-r--r-- | arch/powerpc/mm/fsl_booke_mmu.c | 42 |
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 |
255 | notrace void __init relocate_init(phys_addr_t start) | 255 | int __initdata is_second_reloc; |
256 | notrace 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 |