diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-07-08 01:54:40 -0400 |
---|---|---|
committer | Josh Boyer <jwboyer@linux.vnet.ibm.com> | 2008-07-09 13:36:17 -0400 |
commit | 1bc54c03117b90716e0dedd7abb2a20405de65df (patch) | |
tree | 8e82fd610abaff36f1e20b5aaaf7bdeaee883aac /arch/powerpc/mm | |
parent | beae4c03c0fe69cf7d57518aa0572ad21730b8be (diff) |
powerpc: rework 4xx PTE access and TLB miss
This is some preliminary work to improve TLB management on SW loaded
TLB powerpc platforms. This introduce support for non-atomic PTE
operations in pgtable-ppc32.h and removes write back to the PTE from
the TLB miss handlers. In addition, the DSI interrupt code no longer
tries to fixup write permission, this is left to generic code, and
_PAGE_HWWRITE is gone.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Diffstat (limited to 'arch/powerpc/mm')
-rw-r--r-- | arch/powerpc/mm/44x_mmu.c | 29 | ||||
-rw-r--r-- | arch/powerpc/mm/fault.c | 3 |
2 files changed, 30 insertions, 2 deletions
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c index 953fb919eb06..98052ac96580 100644 --- a/arch/powerpc/mm/44x_mmu.c +++ b/arch/powerpc/mm/44x_mmu.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <asm/mmu.h> | 27 | #include <asm/mmu.h> |
28 | #include <asm/system.h> | 28 | #include <asm/system.h> |
29 | #include <asm/page.h> | 29 | #include <asm/page.h> |
30 | #include <asm/cacheflush.h> | ||
30 | 31 | ||
31 | #include "mmu_decl.h" | 32 | #include "mmu_decl.h" |
32 | 33 | ||
@@ -37,11 +38,35 @@ unsigned int tlb_44x_index; /* = 0 */ | |||
37 | unsigned int tlb_44x_hwater = PPC44x_TLB_SIZE - 1 - PPC44x_EARLY_TLBS; | 38 | unsigned int tlb_44x_hwater = PPC44x_TLB_SIZE - 1 - PPC44x_EARLY_TLBS; |
38 | int icache_44x_need_flush; | 39 | int icache_44x_need_flush; |
39 | 40 | ||
41 | static void __init ppc44x_update_tlb_hwater(void) | ||
42 | { | ||
43 | extern unsigned int tlb_44x_patch_hwater_D[]; | ||
44 | extern unsigned int tlb_44x_patch_hwater_I[]; | ||
45 | |||
46 | /* The TLB miss handlers hard codes the watermark in a cmpli | ||
47 | * instruction to improve performances rather than loading it | ||
48 | * from the global variable. Thus, we patch the instructions | ||
49 | * in the 2 TLB miss handlers when updating the value | ||
50 | */ | ||
51 | tlb_44x_patch_hwater_D[0] = (tlb_44x_patch_hwater_D[0] & 0xffff0000) | | ||
52 | tlb_44x_hwater; | ||
53 | flush_icache_range((unsigned long)&tlb_44x_patch_hwater_D[0], | ||
54 | (unsigned long)&tlb_44x_patch_hwater_D[1]); | ||
55 | tlb_44x_patch_hwater_I[0] = (tlb_44x_patch_hwater_I[0] & 0xffff0000) | | ||
56 | tlb_44x_hwater; | ||
57 | flush_icache_range((unsigned long)&tlb_44x_patch_hwater_I[0], | ||
58 | (unsigned long)&tlb_44x_patch_hwater_I[1]); | ||
59 | } | ||
60 | |||
40 | /* | 61 | /* |
41 | * "Pins" a 256MB TLB entry in AS0 for kernel lowmem | 62 | * "Pins" a 256MB TLB entry in AS0 for kernel lowmem |
42 | */ | 63 | */ |
43 | static void __init ppc44x_pin_tlb(unsigned int virt, unsigned int phys) | 64 | static void __init ppc44x_pin_tlb(unsigned int virt, unsigned int phys) |
44 | { | 65 | { |
66 | unsigned int entry = tlb_44x_hwater--; | ||
67 | |||
68 | ppc44x_update_tlb_hwater(); | ||
69 | |||
45 | __asm__ __volatile__( | 70 | __asm__ __volatile__( |
46 | "tlbwe %2,%3,%4\n" | 71 | "tlbwe %2,%3,%4\n" |
47 | "tlbwe %1,%3,%5\n" | 72 | "tlbwe %1,%3,%5\n" |
@@ -50,7 +75,7 @@ static void __init ppc44x_pin_tlb(unsigned int virt, unsigned int phys) | |||
50 | : "r" (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G), | 75 | : "r" (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G), |
51 | "r" (phys), | 76 | "r" (phys), |
52 | "r" (virt | PPC44x_TLB_VALID | PPC44x_TLB_256M), | 77 | "r" (virt | PPC44x_TLB_VALID | PPC44x_TLB_256M), |
53 | "r" (tlb_44x_hwater--), /* slot for this TLB entry */ | 78 | "r" (entry), |
54 | "i" (PPC44x_TLB_PAGEID), | 79 | "i" (PPC44x_TLB_PAGEID), |
55 | "i" (PPC44x_TLB_XLAT), | 80 | "i" (PPC44x_TLB_XLAT), |
56 | "i" (PPC44x_TLB_ATTRIB)); | 81 | "i" (PPC44x_TLB_ATTRIB)); |
@@ -58,6 +83,8 @@ static void __init ppc44x_pin_tlb(unsigned int virt, unsigned int phys) | |||
58 | 83 | ||
59 | void __init MMU_init_hw(void) | 84 | void __init MMU_init_hw(void) |
60 | { | 85 | { |
86 | ppc44x_update_tlb_hwater(); | ||
87 | |||
61 | flush_instruction_cache(); | 88 | flush_instruction_cache(); |
62 | } | 89 | } |
63 | 90 | ||
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 7b2510799266..1707d00331fc 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
@@ -306,7 +306,8 @@ good_area: | |||
306 | flush_dcache_icache_page(page); | 306 | flush_dcache_icache_page(page); |
307 | set_bit(PG_arch_1, &page->flags); | 307 | set_bit(PG_arch_1, &page->flags); |
308 | } | 308 | } |
309 | pte_update(ptep, 0, _PAGE_HWEXEC); | 309 | pte_update(ptep, 0, _PAGE_HWEXEC | |
310 | _PAGE_ACCESSED); | ||
310 | _tlbie(address, mm->context.id); | 311 | _tlbie(address, mm->context.id); |
311 | pte_unmap_unlock(ptep, ptl); | 312 | pte_unmap_unlock(ptep, ptl); |
312 | up_read(&mm->mmap_sem); | 313 | up_read(&mm->mmap_sem); |