aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/head_8xx.S29
-rw-r--r--arch/powerpc/mm/8xx_mmu.c56
-rw-r--r--arch/powerpc/mm/mmu_decl.h3
3 files changed, 86 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 378a1858687d..44f4edbd5dee 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -384,6 +384,27 @@ InstructionTLBMiss:
384 EXCEPTION_EPILOG_0 384 EXCEPTION_EPILOG_0
385 rfi 385 rfi
386 386
387/*
388 * Bottom part of DataStoreTLBMiss handler for IMMR area
389 * not enough space in the DataStoreTLBMiss area
390 */
391DTLBMissIMMR:
392 mtcr r3
393 /* Set 512k byte guarded page and mark it valid */
394 li r10, MD_PS512K | MD_GUARDED | MD_SVALID
395 MTSPR_CPU6(SPRN_MD_TWC, r10, r3)
396 mfspr r10, SPRN_IMMR /* Get current IMMR */
397 rlwinm r10, r10, 0, 0xfff80000 /* Get 512 kbytes boundary */
398 ori r10, r10, 0xf0 | MD_SPS16K | _PAGE_SHARED | _PAGE_DIRTY | \
399 _PAGE_PRESENT | _PAGE_NO_CACHE
400 MTSPR_CPU6(SPRN_MD_RPN, r10, r3) /* Update TLB entry */
401
402 li r11, RPN_PATTERN
403 mfspr r3, SPRN_SPRG_SCRATCH2
404 mtspr SPRN_DAR, r11 /* Tag DAR */
405 EXCEPTION_EPILOG_0
406 rfi
407
387 . = 0x1200 408 . = 0x1200
388DataStoreTLBMiss: 409DataStoreTLBMiss:
389 mtspr SPRN_SPRG_SCRATCH2, r3 410 mtspr SPRN_SPRG_SCRATCH2, r3
@@ -397,6 +418,14 @@ DataStoreTLBMiss:
397 IS_KERNEL(r11, r10) 418 IS_KERNEL(r11, r10)
398 mfspr r11, SPRN_M_TW /* Get level 1 table */ 419 mfspr r11, SPRN_M_TW /* Get level 1 table */
399 BRANCH_UNLESS_KERNEL(3f) 420 BRANCH_UNLESS_KERNEL(3f)
421
422 rlwinm r11, r10, 16, 0xfff8
423#ifndef CONFIG_PIN_TLB
424 cmpli cr0, r11, VIRT_IMMR_BASE@h
425_ENTRY(DTLBMiss_jmp)
426 beq- DTLBMissIMMR
427#endif
428
400 lis r11, (swapper_pg_dir-PAGE_OFFSET)@ha 429 lis r11, (swapper_pg_dir-PAGE_OFFSET)@ha
4013: 4303:
402 431
diff --git a/arch/powerpc/mm/8xx_mmu.c b/arch/powerpc/mm/8xx_mmu.c
index 949100577db5..220772579113 100644
--- a/arch/powerpc/mm/8xx_mmu.c
+++ b/arch/powerpc/mm/8xx_mmu.c
@@ -13,10 +13,43 @@
13 */ 13 */
14 14
15#include <linux/memblock.h> 15#include <linux/memblock.h>
16#include <asm/fixmap.h>
17#include <asm/code-patching.h>
16 18
17#include "mmu_decl.h" 19#include "mmu_decl.h"
18 20
21#define IMMR_SIZE (FIX_IMMR_SIZE << PAGE_SHIFT)
22
19extern int __map_without_ltlbs; 23extern int __map_without_ltlbs;
24
25/*
26 * Return PA for this VA if it is in IMMR area, or 0
27 */
28phys_addr_t v_block_mapped(unsigned long va)
29{
30 unsigned long p = PHYS_IMMR_BASE;
31
32 if (__map_without_ltlbs)
33 return 0;
34 if (va >= VIRT_IMMR_BASE && va < VIRT_IMMR_BASE + IMMR_SIZE)
35 return p + va - VIRT_IMMR_BASE;
36 return 0;
37}
38
39/*
40 * Return VA for a given PA or 0 if not mapped
41 */
42unsigned long p_block_mapped(phys_addr_t pa)
43{
44 unsigned long p = PHYS_IMMR_BASE;
45
46 if (__map_without_ltlbs)
47 return 0;
48 if (pa >= p && pa < p + IMMR_SIZE)
49 return VIRT_IMMR_BASE + pa - p;
50 return 0;
51}
52
20/* 53/*
21 * MMU_init_hw does the chip-specific initialization of the MMU hardware. 54 * MMU_init_hw does the chip-specific initialization of the MMU hardware.
22 */ 55 */
@@ -29,6 +62,22 @@ void __init MMU_init_hw(void)
29#define LARGE_PAGE_SIZE_8M (1<<23) 62#define LARGE_PAGE_SIZE_8M (1<<23)
30#define LARGE_PAGE_SIZE_64M (1<<26) 63#define LARGE_PAGE_SIZE_64M (1<<26)
31 64
65static void mmu_mapin_immr(void)
66{
67 unsigned long p = PHYS_IMMR_BASE;
68 unsigned long v = VIRT_IMMR_BASE;
69 unsigned long f = pgprot_val(PAGE_KERNEL_NCG);
70 int offset;
71
72 for (offset = 0; offset < IMMR_SIZE; offset += PAGE_SIZE)
73 map_page(v + offset, p + offset, f);
74}
75
76/* Address of instructions to patch */
77#ifndef CONFIG_PIN_TLB
78extern unsigned int DTLBMiss_jmp;
79#endif
80
32unsigned long __init mmu_mapin_ram(unsigned long top) 81unsigned long __init mmu_mapin_ram(unsigned long top)
33{ 82{
34 unsigned long v, s, mapped; 83 unsigned long v, s, mapped;
@@ -38,8 +87,13 @@ unsigned long __init mmu_mapin_ram(unsigned long top)
38 p = 0; 87 p = 0;
39 s = top; 88 s = top;
40 89
41 if (__map_without_ltlbs) 90 if (__map_without_ltlbs) {
91 mmu_mapin_immr();
92#ifndef CONFIG_PIN_TLB
93 patch_instruction(&DTLBMiss_jmp, PPC_INST_NOP);
94#endif
42 return 0; 95 return 0;
96 }
43 97
44#ifdef CONFIG_PPC_4K_PAGES 98#ifdef CONFIG_PPC_4K_PAGES
45 while (s >= LARGE_PAGE_SIZE_8M) { 99 while (s >= LARGE_PAGE_SIZE_8M) {
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index 6af65327c993..f988db655e5b 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -154,9 +154,10 @@ struct tlbcam {
154}; 154};
155#endif 155#endif
156 156
157#if defined(CONFIG_6xx) || defined(CONFIG_FSL_BOOKE) 157#if defined(CONFIG_6xx) || defined(CONFIG_FSL_BOOKE) || defined(CONFIG_PPC_8xx)
158/* 6xx have BATS */ 158/* 6xx have BATS */
159/* FSL_BOOKE have TLBCAM */ 159/* FSL_BOOKE have TLBCAM */
160/* 8xx have LTLB */
160phys_addr_t v_block_mapped(unsigned long va); 161phys_addr_t v_block_mapped(unsigned long va);
161unsigned long p_block_mapped(phys_addr_t pa); 162unsigned long p_block_mapped(phys_addr_t pa);
162#else 163#else