diff options
| author | Rex Feany <RFeany@mrv.com> | 2009-09-23 10:45:52 -0400 |
|---|---|---|
| committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-09-24 01:56:30 -0400 |
| commit | e0908085fc2391c85b85fb814ae1df377c8e0dcb (patch) | |
| tree | 46560ab77e41c84ff15c05b5753d7512f8850ba8 | |
| parent | daf8f40391b2a1978ea2071c20959d91fade6b1a (diff) | |
powerpc/8xx: Fix regression introduced by cache coherency rewrite
After upgrading to the latest kernel on my mpc875 userspace started
running incredibly slow (hours to get to a shell, even!).
I tracked it down to commit 8d30c14cab30d405a05f2aaceda1e9ad57800f36,
that patch removed a work-around for the 8xx. Adding it
back makes my problem go away.
Signed-off-by: Rex Feany <rfeany@mrv.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
| -rw-r--r-- | arch/powerpc/mm/pgtable.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c index 83f1551ec2c9..53040931de32 100644 --- a/arch/powerpc/mm/pgtable.c +++ b/arch/powerpc/mm/pgtable.c | |||
| @@ -30,6 +30,8 @@ | |||
| 30 | #include <asm/tlbflush.h> | 30 | #include <asm/tlbflush.h> |
| 31 | #include <asm/tlb.h> | 31 | #include <asm/tlb.h> |
| 32 | 32 | ||
| 33 | #include "mmu_decl.h" | ||
| 34 | |||
| 33 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | 35 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); |
| 34 | 36 | ||
| 35 | #ifdef CONFIG_SMP | 37 | #ifdef CONFIG_SMP |
| @@ -166,7 +168,7 @@ struct page * maybe_pte_to_page(pte_t pte) | |||
| 166 | * support falls into the same category. | 168 | * support falls into the same category. |
| 167 | */ | 169 | */ |
| 168 | 170 | ||
| 169 | static pte_t set_pte_filter(pte_t pte) | 171 | static pte_t set_pte_filter(pte_t pte, unsigned long addr) |
| 170 | { | 172 | { |
| 171 | pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); | 173 | pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); |
| 172 | if (pte_looks_normal(pte) && !(cpu_has_feature(CPU_FTR_COHERENT_ICACHE) || | 174 | if (pte_looks_normal(pte) && !(cpu_has_feature(CPU_FTR_COHERENT_ICACHE) || |
| @@ -175,6 +177,17 @@ static pte_t set_pte_filter(pte_t pte) | |||
| 175 | if (!pg) | 177 | if (!pg) |
| 176 | return pte; | 178 | return pte; |
| 177 | if (!test_bit(PG_arch_1, &pg->flags)) { | 179 | if (!test_bit(PG_arch_1, &pg->flags)) { |
| 180 | #ifdef CONFIG_8xx | ||
| 181 | /* On 8xx, cache control instructions (particularly | ||
| 182 | * "dcbst" from flush_dcache_icache) fault as write | ||
| 183 | * operation if there is an unpopulated TLB entry | ||
| 184 | * for the address in question. To workaround that, | ||
| 185 | * we invalidate the TLB here, thus avoiding dcbst | ||
| 186 | * misbehaviour. | ||
| 187 | */ | ||
| 188 | /* 8xx doesn't care about PID, size or ind args */ | ||
| 189 | _tlbil_va(addr, 0, 0, 0); | ||
| 190 | #endif /* CONFIG_8xx */ | ||
| 178 | flush_dcache_icache_page(pg); | 191 | flush_dcache_icache_page(pg); |
| 179 | set_bit(PG_arch_1, &pg->flags); | 192 | set_bit(PG_arch_1, &pg->flags); |
| 180 | } | 193 | } |
| @@ -194,7 +207,7 @@ static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma, | |||
| 194 | * as we don't have two bits to spare for _PAGE_EXEC and _PAGE_HWEXEC so | 207 | * as we don't have two bits to spare for _PAGE_EXEC and _PAGE_HWEXEC so |
| 195 | * instead we "filter out" the exec permission for non clean pages. | 208 | * instead we "filter out" the exec permission for non clean pages. |
| 196 | */ | 209 | */ |
| 197 | static pte_t set_pte_filter(pte_t pte) | 210 | static pte_t set_pte_filter(pte_t pte, unsigned long addr) |
| 198 | { | 211 | { |
| 199 | struct page *pg; | 212 | struct page *pg; |
| 200 | 213 | ||
| @@ -276,7 +289,7 @@ void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, | |||
| 276 | * this context might not have been activated yet when this | 289 | * this context might not have been activated yet when this |
| 277 | * is called. | 290 | * is called. |
| 278 | */ | 291 | */ |
| 279 | pte = set_pte_filter(pte); | 292 | pte = set_pte_filter(pte, addr); |
| 280 | 293 | ||
| 281 | /* Perform the setting of the PTE */ | 294 | /* Perform the setting of the PTE */ |
| 282 | __set_pte_at(mm, addr, ptep, pte, 0); | 295 | __set_pte_at(mm, addr, ptep, pte, 0); |
