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 | |
| 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>
| -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 | ||
