diff options
author | Maciej W. Rozycki <macro@linux-mips.org> | 2007-10-17 06:51:39 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2007-10-29 15:35:36 -0400 |
commit | 21b2aecaae3a46a13dbe775639e7d060bec033bd (patch) | |
tree | d0a1bed8b37ec3cf79ff08a47ebb1a820158ef90 /arch/mips/mm/c-r3k.c | |
parent | 62b14c24b10033591bbab16dea165d696a616f37 (diff) |
[MIPS] c-r3k: Implement flush_cache_range()
Contrary to the belief of some, the R3000 and related processors did have
caches, both a data and an instruction cache. Here is an implementation
of r3k_flush_cache_page(), which is the processor-specific back-end for
flush_cache_range(), done according to the spec in
Documentation/cachetlb.txt.
While at it, remove an unused local function: get_phys_page(), do some
trivial formatting fixes and modernise debugging facilities.
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/mm/c-r3k.c')
-rw-r--r-- | arch/mips/mm/c-r3k.c | 60 |
1 files changed, 32 insertions, 28 deletions
diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c index c55312f6fd3a..562abb77d1d5 100644 --- a/arch/mips/mm/c-r3k.c +++ b/arch/mips/mm/c-r3k.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * Tx39XX R4k style caches added. HK | 7 | * Tx39XX R4k style caches added. HK |
8 | * Copyright (C) 1998, 1999, 2000 Harald Koerfgen | 8 | * Copyright (C) 1998, 1999, 2000 Harald Koerfgen |
9 | * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov | 9 | * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov |
10 | * Copyright (C) 2001, 2004 Maciej W. Rozycki | 10 | * Copyright (C) 2001, 2004, 2007 Maciej W. Rozycki |
11 | */ | 11 | */ |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
@@ -26,8 +26,6 @@ | |||
26 | static unsigned long icache_size, dcache_size; /* Size in bytes */ | 26 | static unsigned long icache_size, dcache_size; /* Size in bytes */ |
27 | static unsigned long icache_lsize, dcache_lsize; /* Size in bytes */ | 27 | static unsigned long icache_lsize, dcache_lsize; /* Size in bytes */ |
28 | 28 | ||
29 | #undef DEBUG_CACHE | ||
30 | |||
31 | unsigned long __init r3k_cache_size(unsigned long ca_flags) | 29 | unsigned long __init r3k_cache_size(unsigned long ca_flags) |
32 | { | 30 | { |
33 | unsigned long flags, status, dummy, size; | 31 | unsigned long flags, status, dummy, size; |
@@ -217,26 +215,6 @@ static void r3k_flush_dcache_range(unsigned long start, unsigned long end) | |||
217 | write_c0_status(flags); | 215 | write_c0_status(flags); |
218 | } | 216 | } |
219 | 217 | ||
220 | static inline unsigned long get_phys_page(unsigned long addr, | ||
221 | struct mm_struct *mm) | ||
222 | { | ||
223 | pgd_t *pgd; | ||
224 | pud_t *pud; | ||
225 | pmd_t *pmd; | ||
226 | pte_t *pte; | ||
227 | unsigned long physpage; | ||
228 | |||
229 | pgd = pgd_offset(mm, addr); | ||
230 | pud = pud_offset(pgd, addr); | ||
231 | pmd = pmd_offset(pud, addr); | ||
232 | pte = pte_offset(pmd, addr); | ||
233 | |||
234 | if ((physpage = pte_val(*pte)) & _PAGE_VALID) | ||
235 | return KSEG0ADDR(physpage & PAGE_MASK); | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | static inline void r3k_flush_cache_all(void) | 218 | static inline void r3k_flush_cache_all(void) |
241 | { | 219 | { |
242 | } | 220 | } |
@@ -252,12 +230,40 @@ static void r3k_flush_cache_mm(struct mm_struct *mm) | |||
252 | } | 230 | } |
253 | 231 | ||
254 | static void r3k_flush_cache_range(struct vm_area_struct *vma, | 232 | static void r3k_flush_cache_range(struct vm_area_struct *vma, |
255 | unsigned long start, unsigned long end) | 233 | unsigned long start, unsigned long end) |
256 | { | 234 | { |
257 | } | 235 | } |
258 | 236 | ||
259 | static void r3k_flush_cache_page(struct vm_area_struct *vma, unsigned long page, unsigned long pfn) | 237 | static void r3k_flush_cache_page(struct vm_area_struct *vma, |
238 | unsigned long addr, unsigned long pfn) | ||
260 | { | 239 | { |
240 | unsigned long kaddr = KSEG0ADDR(pfn << PAGE_SHIFT); | ||
241 | int exec = vma->vm_flags & VM_EXEC; | ||
242 | struct mm_struct *mm = vma->vm_mm; | ||
243 | pgd_t *pgdp; | ||
244 | pud_t *pudp; | ||
245 | pmd_t *pmdp; | ||
246 | pte_t *ptep; | ||
247 | |||
248 | pr_debug("cpage[%08lx,%08lx]\n", | ||
249 | cpu_context(smp_processor_id(), mm), addr); | ||
250 | |||
251 | /* No ASID => no such page in the cache. */ | ||
252 | if (cpu_context(smp_processor_id(), mm) == 0) | ||
253 | return; | ||
254 | |||
255 | pgdp = pgd_offset(mm, addr); | ||
256 | pudp = pud_offset(pgdp, addr); | ||
257 | pmdp = pmd_offset(pudp, addr); | ||
258 | ptep = pte_offset(pmdp, addr); | ||
259 | |||
260 | /* Invalid => no such page in the cache. */ | ||
261 | if (!(pte_val(*ptep) & _PAGE_PRESENT)) | ||
262 | return; | ||
263 | |||
264 | r3k_flush_dcache_range(kaddr, kaddr + PAGE_SIZE); | ||
265 | if (exec) | ||
266 | r3k_flush_icache_range(kaddr, kaddr + PAGE_SIZE); | ||
261 | } | 267 | } |
262 | 268 | ||
263 | static void local_r3k_flush_data_cache_page(void *addr) | 269 | static void local_r3k_flush_data_cache_page(void *addr) |
@@ -272,9 +278,7 @@ static void r3k_flush_cache_sigtramp(unsigned long addr) | |||
272 | { | 278 | { |
273 | unsigned long flags; | 279 | unsigned long flags; |
274 | 280 | ||
275 | #ifdef DEBUG_CACHE | 281 | pr_debug("csigtramp[%08lx]\n", addr); |
276 | printk("csigtramp[%08lx]", addr); | ||
277 | #endif | ||
278 | 282 | ||
279 | flags = read_c0_status(); | 283 | flags = read_c0_status(); |
280 | 284 | ||