summaryrefslogtreecommitdiff
path: root/arch/sh/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/mm')
-rw-r--r--arch/sh/mm/Kconfig20
-rw-r--r--arch/sh/mm/cache-debugfs.c2
-rw-r--r--arch/sh/mm/cache-sh4.c67
-rw-r--r--arch/sh/mm/consistent.c30
-rw-r--r--arch/sh/mm/fault_32.c12
-rw-r--r--arch/sh/mm/pg-sh4.c2
-rw-r--r--arch/sh/mm/pg-sh7705.c2
-rw-r--r--arch/sh/mm/pmb.c2
8 files changed, 95 insertions, 42 deletions
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index 5fd218430b19..56d0a7daa34b 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -145,25 +145,39 @@ choice
config PAGE_SIZE_4KB
bool "4kB"
- depends on !X2TLB
+ depends on !MMU || !X2TLB
help
This is the default page size used by all SuperH CPUs.
config PAGE_SIZE_8KB
bool "8kB"
- depends on X2TLB
+ depends on !MMU || X2TLB
help
This enables 8kB pages as supported by SH-X2 and later MMUs.
+config PAGE_SIZE_16KB
+ bool "16kB"
+ depends on !MMU
+ help
+ This enables 16kB pages on MMU-less SH systems.
+
config PAGE_SIZE_64KB
bool "64kB"
- depends on CPU_SH4 || CPU_SH5
+ depends on !MMU || CPU_SH4 || CPU_SH5
help
This enables support for 64kB pages, possible on all SH-4
CPUs and later.
endchoice
+config ENTRY_OFFSET
+ hex
+ default "0x00001000" if PAGE_SIZE_4KB
+ default "0x00002000" if PAGE_SIZE_8KB
+ default "0x00004000" if PAGE_SIZE_16KB
+ default "0x00010000" if PAGE_SIZE_64KB
+ default "0x00000000"
+
choice
prompt "HugeTLB page size"
depends on HUGETLB_PAGE && (CPU_SH4 || CPU_SH5) && MMU
diff --git a/arch/sh/mm/cache-debugfs.c b/arch/sh/mm/cache-debugfs.c
index c5b56d52b7d2..0e189ccd4a77 100644
--- a/arch/sh/mm/cache-debugfs.c
+++ b/arch/sh/mm/cache-debugfs.c
@@ -120,7 +120,7 @@ static const struct file_operations cache_debugfs_fops = {
.open = cache_debugfs_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release,
+ .release = single_release,
};
static int __init cache_debugfs_init(void)
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index 43d7ff6b6ec7..1fdc8d90254a 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -4,6 +4,7 @@
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
* Copyright (C) 2001 - 2007 Paul Mundt
* Copyright (C) 2003 Richard Curnow
+ * Copyright (c) 2007 STMicroelectronics (R&D) Ltd.
*
* 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
@@ -22,6 +23,7 @@
* entirety.
*/
#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);
@@ -178,42 +180,45 @@ void __flush_invalidate_region(void *start, int size)
/*
* 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.
+ * 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)
{
- flush_cache_all();
-}
-
-/*
- * Write back the D-cache and purge the I-cache for signal trampoline.
- * .. which happens to be the same behavior as flush_icache_range().
- * So, we simply flush out a line.
- */
-void __uses_jump_to_uncached flush_cache_sigtramp(unsigned long addr)
-{
- unsigned long v, index;
- unsigned long flags;
+ int icacheaddr;
+ unsigned long flags, v;
int i;
- v = addr & ~(L1_CACHE_BYTES-1);
- asm volatile("ocbwb %0"
- : /* no output */
- : "m" (__m(v)));
-
- index = CACHE_IC_ADDRESS_ARRAY |
- (v & boot_cpu_data.icache.entry_mask);
-
- local_irq_save(flags);
- jump_to_uncached();
-
- for (i = 0; i < boot_cpu_data.icache.ways;
- i++, index += boot_cpu_data.icache.way_incr)
- ctrl_outl(0, index); /* Clear out Valid-bit */
-
- back_to_cached();
- wmb();
- local_irq_restore(flags);
+ /* If there are too many pages then just blow the caches */
+ if (((end - start) >> PAGE_SHIFT) >= MAX_ICACHE_PAGES) {
+ flush_cache_all();
+ } else {
+ /* selectively flush d-cache then invalidate the i-cache */
+ /* this is inefficient, so only use for small ranges */
+ start &= ~(L1_CACHE_BYTES-1);
+ end += L1_CACHE_BYTES-1;
+ end &= ~(L1_CACHE_BYTES-1);
+
+ local_irq_save(flags);
+ jump_to_uncached();
+
+ for (v = start; v < end; v+=L1_CACHE_BYTES) {
+ asm volatile("ocbwb %0"
+ : /* no output */
+ : "m" (__m(v)));
+
+ icacheaddr = CACHE_IC_ADDRESS_ARRAY | (
+ v & cpu_data->icache.entry_mask);
+
+ for (i = 0; i < cpu_data->icache.ways;
+ i++, icacheaddr += cpu_data->icache.way_incr)
+ /* Clear i-cache line valid-bit */
+ ctrl_outl(0, icacheaddr);
+ }
+
+ back_to_cached();
+ local_irq_restore(flags);
+ }
}
static inline void flush_cache_4096(unsigned long start,
diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c
index d3c33fc5b1c2..8277982d0938 100644
--- a/arch/sh/mm/consistent.c
+++ b/arch/sh/mm/consistent.c
@@ -10,6 +10,7 @@
* for more details.
*/
#include <linux/mm.h>
+#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <asm/cacheflush.h>
#include <asm/addrspace.h>
@@ -185,3 +186,32 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
}
}
EXPORT_SYMBOL(dma_cache_sync);
+
+int platform_resource_setup_memory(struct platform_device *pdev,
+ char *name, unsigned long memsize)
+{
+ struct resource *r;
+ dma_addr_t dma_handle;
+ void *buf;
+
+ r = pdev->resource + pdev->num_resources - 1;
+ if (r->flags) {
+ pr_warning("%s: unable to find empty space for resource\n",
+ name);
+ return -EINVAL;
+ }
+
+ buf = dma_alloc_coherent(NULL, memsize, &dma_handle, GFP_KERNEL);
+ if (!buf) {
+ pr_warning("%s: unable to allocate memory\n", name);
+ return -ENOMEM;
+ }
+
+ memset(buf, 0, memsize);
+
+ r->flags = IORESOURCE_MEM;
+ r->start = dma_handle;
+ r->end = r->start + memsize - 1;
+ r->name = name;
+ return 0;
+}
diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c
index d1fa27594c6e..0c776fdfbdda 100644
--- a/arch/sh/mm/fault_32.c
+++ b/arch/sh/mm/fault_32.c
@@ -37,16 +37,12 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
int fault;
siginfo_t info;
- trace_hardirqs_on();
- local_irq_enable();
-
#ifdef CONFIG_SH_KGDB
if (kgdb_nofault && kgdb_bus_err_hook)
kgdb_bus_err_hook();
#endif
tsk = current;
- mm = tsk->mm;
si_code = SEGV_MAPERR;
if (unlikely(address >= TASK_SIZE)) {
@@ -88,6 +84,14 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
return;
}
+ /* Only enable interrupts if they were on before the fault */
+ if ((regs->sr & SR_IMASK) != SR_IMASK) {
+ trace_hardirqs_on();
+ local_irq_enable();
+ }
+
+ mm = tsk->mm;
+
/*
* If we're in an interrupt or have no user
* context, we must not take the fault..
diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c
index 8c7a9ca79879..38870e0fc182 100644
--- a/arch/sh/mm/pg-sh4.c
+++ b/arch/sh/mm/pg-sh4.c
@@ -111,7 +111,7 @@ EXPORT_SYMBOL(copy_user_highpage);
/*
* For SH-4, we have our own implementation for ptep_get_and_clear
*/
-inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
pte_t pte = *ptep;
diff --git a/arch/sh/mm/pg-sh7705.c b/arch/sh/mm/pg-sh7705.c
index 7f885b7f8aff..eaf25147194c 100644
--- a/arch/sh/mm/pg-sh7705.c
+++ b/arch/sh/mm/pg-sh7705.c
@@ -118,7 +118,7 @@ void copy_user_page(void *to, void *from, unsigned long address, struct page *pg
* For SH7705, we have our own implementation for ptep_get_and_clear
* Copied from pg-sh4.c
*/
-inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
pte_t pte = *ptep;
diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
index 46911bcbf17b..cef727669c87 100644
--- a/arch/sh/mm/pmb.c
+++ b/arch/sh/mm/pmb.c
@@ -385,7 +385,7 @@ static const struct file_operations pmb_debugfs_fops = {
.open = pmb_debugfs_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release,
+ .release = single_release,
};
static int __init pmb_debugfs_init(void)