aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/mm
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@linux-mips.org>2007-10-17 06:51:39 -0400
committerRalf Baechle <ralf@linux-mips.org>2007-10-29 15:35:36 -0400
commit21b2aecaae3a46a13dbe775639e7d060bec033bd (patch)
treed0a1bed8b37ec3cf79ff08a47ebb1a820158ef90 /arch/mips/mm
parent62b14c24b10033591bbab16dea165d696a616f37 (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')
-rw-r--r--arch/mips/mm/c-r3k.c60
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 @@
26static unsigned long icache_size, dcache_size; /* Size in bytes */ 26static unsigned long icache_size, dcache_size; /* Size in bytes */
27static unsigned long icache_lsize, dcache_lsize; /* Size in bytes */ 27static unsigned long icache_lsize, dcache_lsize; /* Size in bytes */
28 28
29#undef DEBUG_CACHE
30
31unsigned long __init r3k_cache_size(unsigned long ca_flags) 29unsigned 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
220static 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
240static inline void r3k_flush_cache_all(void) 218static 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
254static void r3k_flush_cache_range(struct vm_area_struct *vma, 232static 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
259static void r3k_flush_cache_page(struct vm_area_struct *vma, unsigned long page, unsigned long pfn) 237static 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
263static void local_r3k_flush_data_cache_page(void *addr) 269static 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