Skip to content

Commit

Permalink
sh: Migrate SH-4 cacheflush ops to function pointers.
Browse files Browse the repository at this point in the history
This paves the way for allowing individual CPUs to overload the
individual flushing routines that they care about without having to
depend on weak aliases. SH-4 is converted over initially, as it wires
up pretty much everything. The majority of the other CPUs will simply use
the default no-op implementation with their own region flushers wired up.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
  • Loading branch information
Paul Mundt committed Aug 15, 2009
1 parent 916e978 commit 37443ef
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 135 deletions.
37 changes: 1 addition & 36 deletions arch/sh/include/asm/cacheflush.h
Original file line number Diff line number Diff line change
@@ -1,46 +1,11 @@
#ifndef __ASM_SH_CACHEFLUSH_H
#define __ASM_SH_CACHEFLUSH_H

#include <linux/mm.h>

#ifdef __KERNEL__

#ifdef CONFIG_CACHE_OFF
/*
* Nothing to do when the cache is disabled, initial flush and explicit
* disabling is handled at CPU init time.
*
* See arch/sh/kernel/cpu/init.c:cache_init().
*/
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_icache_range(start, end) do { } while (0)
#define flush_icache_page(vma,pg) do { } while (0)
#define flush_cache_sigtramp(vaddr) do { } while (0)
#define __flush_wback_region(start, size) do { (void)(start); } while (0)
#define __flush_purge_region(start, size) do { (void)(start); } while (0)
#define __flush_invalidate_region(start, size) do { (void)(start); } while (0)
#else
#include <linux/mm.h>
#include <cpu/cacheflush.h>

/*
* Consistent DMA requires that the __flush_xxx() primitives must be set
* for any of the enabled non-coherent caches (most of the UP CPUs),
* regardless of PIPT or VIPT cache configurations.
*/

/* Flush (write-back only) a region (smaller than a page) */
extern void __flush_wback_region(void *start, int size);
/* Flush (write-back & invalidate) a region (smaller than a page) */
extern void __flush_purge_region(void *start, int size);
/* Flush (invalidate only) a region (smaller than a page) */
extern void __flush_invalidate_region(void *start, int size);
#endif

#define ARCH_HAS_FLUSH_ANON_PAGE
extern void __flush_anon_page(struct page *page, unsigned long);

Expand Down
37 changes: 20 additions & 17 deletions arch/sh/include/cpu-common/cpu/cacheflush.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
/*
* include/asm-sh/cpu-sh2/cacheflush.h
*
* Copyright (C) 2003 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#ifndef __ASM_CPU_SH2_CACHEFLUSH_H
#define __ASM_CPU_SH2_CACHEFLUSH_H
#ifndef __ASM_CPU_SH_CACHEFLUSH_H
#define __ASM_CPU_SH_CACHEFLUSH_H

/*
* Cache flushing:
Expand All @@ -22,18 +20,23 @@
* - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
* - flush_icache_range(start, end) flushes(invalidates) a range for icache
* - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
*
* Caches are indexed (effectively) by physical address on SH-2, so
* we don't need them.
* - flush_cache_sigtramp(vaddr) flushes the signal trampoline
*/
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_icache_range(start, end) do { } while (0)
#define flush_icache_page(vma,pg) do { } while (0)
#define flush_cache_sigtramp(vaddr) do { } while (0)
extern void (*flush_cache_all)(void);
extern void (*flush_cache_mm)(struct mm_struct *mm);
extern void (*flush_cache_dup_mm)(struct mm_struct *mm);
extern void (*flush_cache_page)(struct vm_area_struct *vma,
unsigned long addr, unsigned long pfn);
extern void (*flush_cache_range)(struct vm_area_struct *vma,
unsigned long start, unsigned long end);
extern void (*flush_dcache_page)(struct page *page);
extern void (*flush_icache_range)(unsigned long start, unsigned long end);
extern void (*flush_icache_page)(struct vm_area_struct *vma,
struct page *page);
extern void (*flush_cache_sigtramp)(unsigned long address);

extern void (*__flush_wback_region)(void *start, int size);
extern void (*__flush_purge_region)(void *start, int size);
extern void (*__flush_invalidate_region)(void *start, int size);

#endif /* __ASM_CPU_SH2_CACHEFLUSH_H */
#endif /* __ASM_CPU_SH_CACHEFLUSH_H */
31 changes: 0 additions & 31 deletions arch/sh/include/cpu-sh4/cpu/cacheflush.h

This file was deleted.

10 changes: 5 additions & 5 deletions arch/sh/include/cpu-sh5/cpu/cacheflush.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@

#ifndef __ASSEMBLY__

struct vm_area_struct;
struct page;
struct mm_struct;

extern void flush_cache_all(void);
extern void flush_cache_mm(struct mm_struct *mm);
extern void flush_cache_sigtramp(unsigned long vaddr);
Expand All @@ -16,10 +12,14 @@ extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, uns
extern void flush_dcache_page(struct page *pg);
extern void flush_icache_range(unsigned long start, unsigned long end);

/* XXX .. */
extern void (*__flush_wback_region)(void *start, int size);
extern void (*__flush_purge_region)(void *start, int size);
extern void (*__flush_invalidate_region)(void *start, int size);

#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
#define flush_icache_page(vma, page) do { } while (0)

#endif /* __ASSEMBLY__ */

#endif /* __ASM_SH_CPU_SH5_CACHEFLUSH_H */

87 changes: 46 additions & 41 deletions arch/sh/mm/cache-sh4.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,6 @@
#define MAX_DCACHE_PAGES 64 /* XXX: Tune for ways */
#define MAX_ICACHE_PAGES 32

static void __flush_dcache_segment_1way(unsigned long start,
unsigned long extent);
static void __flush_dcache_segment_2way(unsigned long start,
unsigned long extent);
static void __flush_dcache_segment_4way(unsigned long start,
unsigned long extent);

static void __flush_cache_4096(unsigned long addr, unsigned long phys,
unsigned long exec_offset);

Expand All @@ -44,39 +37,13 @@ static void __flush_cache_4096(unsigned long addr, unsigned long phys,
static void (*__flush_dcache_segment_fn)(unsigned long, unsigned long) =
(void (*)(unsigned long, unsigned long))0xdeadbeef;

/*
* SH-4 has virtually indexed and physically tagged cache.
*/
void __init sh4_cache_init(void)
{
printk("PVR=%08x CVR=%08x PRR=%08x\n",
ctrl_inl(CCN_PVR),
ctrl_inl(CCN_CVR),
ctrl_inl(CCN_PRR));

switch (boot_cpu_data.dcache.ways) {
case 1:
__flush_dcache_segment_fn = __flush_dcache_segment_1way;
break;
case 2:
__flush_dcache_segment_fn = __flush_dcache_segment_2way;
break;
case 4:
__flush_dcache_segment_fn = __flush_dcache_segment_4way;
break;
default:
panic("unknown number of cache ways\n");
break;
}
}

/*
* Write back the range of D-cache, and purge the I-cache.
*
* Called from kernel/module.c:sys_init_module and routine for a.out format,
* signal handler code and kprobes code
*/
void flush_icache_range(unsigned long start, unsigned long end)
static void sh4_flush_icache_range(unsigned long start, unsigned long end)
{
int icacheaddr;
unsigned long flags, v;
Expand Down Expand Up @@ -137,7 +104,7 @@ static inline void flush_cache_4096(unsigned long start,
* Write back & invalidate the D-cache of the page.
* (To avoid "alias" issues)
*/
void flush_dcache_page(struct page *page)
static void sh4_flush_dcache_page(struct page *page)
{
struct address_space *mapping = page_mapping(page);

Expand Down Expand Up @@ -188,7 +155,7 @@ static inline void flush_dcache_all(void)
wmb();
}

void flush_cache_all(void)
static void sh4_flush_cache_all(void)
{
flush_dcache_all();
flush_icache_all();
Expand Down Expand Up @@ -280,7 +247,7 @@ static void __flush_cache_mm(struct mm_struct *mm, unsigned long start,
*
* Caller takes mm->mmap_sem.
*/
void flush_cache_mm(struct mm_struct *mm)
static void sh4_flush_cache_mm(struct mm_struct *mm)
{
if (cpu_context(smp_processor_id(), mm) == NO_CONTEXT)
return;
Expand Down Expand Up @@ -320,8 +287,8 @@ void flush_cache_mm(struct mm_struct *mm)
* ADDR: Virtual Address (U0 address)
* PFN: Physical page number
*/
void flush_cache_page(struct vm_area_struct *vma, unsigned long address,
unsigned long pfn)
static void sh4_flush_cache_page(struct vm_area_struct *vma,
unsigned long address, unsigned long pfn)
{
unsigned long phys = pfn << PAGE_SHIFT;
unsigned int alias_mask;
Expand Down Expand Up @@ -368,8 +335,8 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long address,
* Flushing the cache lines for U0 only isn't enough.
* We need to flush for P1 too, which may contain aliases.
*/
void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end)
static void sh4_flush_cache_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)
{
if (cpu_context(smp_processor_id(), vma->vm_mm) == NO_CONTEXT)
return;
Expand Down Expand Up @@ -668,3 +635,41 @@ static void __flush_dcache_segment_4way(unsigned long start,
a3 += linesz;
} while (a0 < a0e);
}

extern void __weak sh4__flush_region_init(void);

/*
* SH-4 has virtually indexed and physically tagged cache.
*/
void __init sh4_cache_init(void)
{
printk("PVR=%08x CVR=%08x PRR=%08x\n",
ctrl_inl(CCN_PVR),
ctrl_inl(CCN_CVR),
ctrl_inl(CCN_PRR));

switch (boot_cpu_data.dcache.ways) {
case 1:
__flush_dcache_segment_fn = __flush_dcache_segment_1way;
break;
case 2:
__flush_dcache_segment_fn = __flush_dcache_segment_2way;
break;
case 4:
__flush_dcache_segment_fn = __flush_dcache_segment_4way;
break;
default:
panic("unknown number of cache ways\n");
break;
}

flush_icache_range = sh4_flush_icache_range;
flush_dcache_page = sh4_flush_dcache_page;
flush_cache_all = sh4_flush_cache_all;
flush_cache_mm = sh4_flush_cache_mm;
flush_cache_dup_mm = sh4_flush_cache_mm;
flush_cache_page = sh4_flush_cache_page;
flush_cache_range = sh4_flush_cache_range;

sh4__flush_region_init();
}
4 changes: 4 additions & 0 deletions arch/sh/mm/cache-sh5.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,17 @@
#include <asm/uaccess.h>
#include <asm/mmu_context.h>

extern void __weak sh4__flush_region_init(void);

/* Wired TLB entry for the D-cache */
static unsigned long long dtlb_cache_slot;

void __init cpu_cache_init(void)
{
/* Reserve a slot for dcache colouring in the DTLB */
dtlb_cache_slot = sh64_get_wired_dtlb_entry();

sh4__flush_region_init();
}

void __init kmap_coherent_init(void)
Expand Down
Loading

0 comments on commit 37443ef

Please sign in to comment.