aboutsummaryrefslogtreecommitdiffstats
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
145 145
146config PAGE_SIZE_4KB 146config PAGE_SIZE_4KB
147 bool "4kB" 147 bool "4kB"
148 depends on !X2TLB 148 depends on !MMU || !X2TLB
149 help 149 help
150 This is the default page size used by all SuperH CPUs. 150 This is the default page size used by all SuperH CPUs.
151 151
152config PAGE_SIZE_8KB 152config PAGE_SIZE_8KB
153 bool "8kB" 153 bool "8kB"
154 depends on X2TLB 154 depends on !MMU || X2TLB
155 help 155 help
156 This enables 8kB pages as supported by SH-X2 and later MMUs. 156 This enables 8kB pages as supported by SH-X2 and later MMUs.
157 157
158config PAGE_SIZE_16KB
159 bool "16kB"
160 depends on !MMU
161 help
162 This enables 16kB pages on MMU-less SH systems.
163
158config PAGE_SIZE_64KB 164config PAGE_SIZE_64KB
159 bool "64kB" 165 bool "64kB"
160 depends on CPU_SH4 || CPU_SH5 166 depends on !MMU || CPU_SH4 || CPU_SH5
161 help 167 help
162 This enables support for 64kB pages, possible on all SH-4 168 This enables support for 64kB pages, possible on all SH-4
163 CPUs and later. 169 CPUs and later.
164 170
165endchoice 171endchoice
166 172
173config ENTRY_OFFSET
174 hex
175 default "0x00001000" if PAGE_SIZE_4KB
176 default "0x00002000" if PAGE_SIZE_8KB
177 default "0x00004000" if PAGE_SIZE_16KB
178 default "0x00010000" if PAGE_SIZE_64KB
179 default "0x00000000"
180
167choice 181choice
168 prompt "HugeTLB page size" 182 prompt "HugeTLB page size"
169 depends on HUGETLB_PAGE && (CPU_SH4 || CPU_SH5) && MMU 183 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 = {
120 .open = cache_debugfs_open, 120 .open = cache_debugfs_open,
121 .read = seq_read, 121 .read = seq_read,
122 .llseek = seq_lseek, 122 .llseek = seq_lseek,
123 .release = seq_release, 123 .release = single_release,
124}; 124};
125 125
126static int __init cache_debugfs_init(void) 126static 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 @@
4 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka 4 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
5 * Copyright (C) 2001 - 2007 Paul Mundt 5 * Copyright (C) 2001 - 2007 Paul Mundt
6 * Copyright (C) 2003 Richard Curnow 6 * Copyright (C) 2003 Richard Curnow
7 * Copyright (c) 2007 STMicroelectronics (R&D) Ltd.
7 * 8 *
8 * This file is subject to the terms and conditions of the GNU General Public 9 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive 10 * License. See the file "COPYING" in the main directory of this archive
@@ -22,6 +23,7 @@
22 * entirety. 23 * entirety.
23 */ 24 */
24#define MAX_DCACHE_PAGES 64 /* XXX: Tune for ways */ 25#define MAX_DCACHE_PAGES 64 /* XXX: Tune for ways */
26#define MAX_ICACHE_PAGES 32
25 27
26static void __flush_dcache_segment_1way(unsigned long start, 28static void __flush_dcache_segment_1way(unsigned long start,
27 unsigned long extent); 29 unsigned long extent);
@@ -178,42 +180,45 @@ void __flush_invalidate_region(void *start, int size)
178/* 180/*
179 * Write back the range of D-cache, and purge the I-cache. 181 * Write back the range of D-cache, and purge the I-cache.
180 * 182 *
181 * Called from kernel/module.c:sys_init_module and routine for a.out format. 183 * Called from kernel/module.c:sys_init_module and routine for a.out format,
184 * signal handler code and kprobes code
182 */ 185 */
183void flush_icache_range(unsigned long start, unsigned long end) 186void flush_icache_range(unsigned long start, unsigned long end)
184{ 187{
185 flush_cache_all(); 188 int icacheaddr;
186} 189 unsigned long flags, v;
187
188/*
189 * Write back the D-cache and purge the I-cache for signal trampoline.
190 * .. which happens to be the same behavior as flush_icache_range().
191 * So, we simply flush out a line.
192 */
193void __uses_jump_to_uncached flush_cache_sigtramp(unsigned long addr)
194{
195 unsigned long v, index;
196 unsigned long flags;
197 int i; 190 int i;
198 191
199 v = addr & ~(L1_CACHE_BYTES-1); 192 /* If there are too many pages then just blow the caches */
200 asm volatile("ocbwb %0" 193 if (((end - start) >> PAGE_SHIFT) >= MAX_ICACHE_PAGES) {
201 : /* no output */ 194 flush_cache_all();
202 : "m" (__m(v))); 195 } else {
203 196 /* selectively flush d-cache then invalidate the i-cache */
204 index = CACHE_IC_ADDRESS_ARRAY | 197 /* this is inefficient, so only use for small ranges */
205 (v & boot_cpu_data.icache.entry_mask); 198 start &= ~(L1_CACHE_BYTES-1);
206 199 end += L1_CACHE_BYTES-1;
207 local_irq_save(flags); 200 end &= ~(L1_CACHE_BYTES-1);
208 jump_to_uncached(); 201
209 202 local_irq_save(flags);
210 for (i = 0; i < boot_cpu_data.icache.ways; 203 jump_to_uncached();
211 i++, index += boot_cpu_data.icache.way_incr) 204
212 ctrl_outl(0, index); /* Clear out Valid-bit */ 205 for (v = start; v < end; v+=L1_CACHE_BYTES) {
213 206 asm volatile("ocbwb %0"
214 back_to_cached(); 207 : /* no output */
215 wmb(); 208 : "m" (__m(v)));
216 local_irq_restore(flags); 209
210 icacheaddr = CACHE_IC_ADDRESS_ARRAY | (
211 v & cpu_data->icache.entry_mask);
212
213 for (i = 0; i < cpu_data->icache.ways;
214 i++, icacheaddr += cpu_data->icache.way_incr)
215 /* Clear i-cache line valid-bit */
216 ctrl_outl(0, icacheaddr);
217 }
218
219 back_to_cached();
220 local_irq_restore(flags);
221 }
217} 222}
218 223
219static inline void flush_cache_4096(unsigned long start, 224static 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 @@
10 * for more details. 10 * for more details.
11 */ 11 */
12#include <linux/mm.h> 12#include <linux/mm.h>
13#include <linux/platform_device.h>
13#include <linux/dma-mapping.h> 14#include <linux/dma-mapping.h>
14#include <asm/cacheflush.h> 15#include <asm/cacheflush.h>
15#include <asm/addrspace.h> 16#include <asm/addrspace.h>
@@ -185,3 +186,32 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
185 } 186 }
186} 187}
187EXPORT_SYMBOL(dma_cache_sync); 188EXPORT_SYMBOL(dma_cache_sync);
189
190int platform_resource_setup_memory(struct platform_device *pdev,
191 char *name, unsigned long memsize)
192{
193 struct resource *r;
194 dma_addr_t dma_handle;
195 void *buf;
196
197 r = pdev->resource + pdev->num_resources - 1;
198 if (r->flags) {
199 pr_warning("%s: unable to find empty space for resource\n",
200 name);
201 return -EINVAL;
202 }
203
204 buf = dma_alloc_coherent(NULL, memsize, &dma_handle, GFP_KERNEL);
205 if (!buf) {
206 pr_warning("%s: unable to allocate memory\n", name);
207 return -ENOMEM;
208 }
209
210 memset(buf, 0, memsize);
211
212 r->flags = IORESOURCE_MEM;
213 r->start = dma_handle;
214 r->end = r->start + memsize - 1;
215 r->name = name;
216 return 0;
217}
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,
37 int fault; 37 int fault;
38 siginfo_t info; 38 siginfo_t info;
39 39
40 trace_hardirqs_on();
41 local_irq_enable();
42
43#ifdef CONFIG_SH_KGDB 40#ifdef CONFIG_SH_KGDB
44 if (kgdb_nofault && kgdb_bus_err_hook) 41 if (kgdb_nofault && kgdb_bus_err_hook)
45 kgdb_bus_err_hook(); 42 kgdb_bus_err_hook();
46#endif 43#endif
47 44
48 tsk = current; 45 tsk = current;
49 mm = tsk->mm;
50 si_code = SEGV_MAPERR; 46 si_code = SEGV_MAPERR;
51 47
52 if (unlikely(address >= TASK_SIZE)) { 48 if (unlikely(address >= TASK_SIZE)) {
@@ -88,6 +84,14 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
88 return; 84 return;
89 } 85 }
90 86
87 /* Only enable interrupts if they were on before the fault */
88 if ((regs->sr & SR_IMASK) != SR_IMASK) {
89 trace_hardirqs_on();
90 local_irq_enable();
91 }
92
93 mm = tsk->mm;
94
91 /* 95 /*
92 * If we're in an interrupt or have no user 96 * If we're in an interrupt or have no user
93 * context, we must not take the fault.. 97 * 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);
111/* 111/*
112 * For SH-4, we have our own implementation for ptep_get_and_clear 112 * For SH-4, we have our own implementation for ptep_get_and_clear
113 */ 113 */
114inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) 114pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
115{ 115{
116 pte_t pte = *ptep; 116 pte_t pte = *ptep;
117 117
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
118 * For SH7705, we have our own implementation for ptep_get_and_clear 118 * For SH7705, we have our own implementation for ptep_get_and_clear
119 * Copied from pg-sh4.c 119 * Copied from pg-sh4.c
120 */ 120 */
121inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) 121pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
122{ 122{
123 pte_t pte = *ptep; 123 pte_t pte = *ptep;
124 124
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 = {
385 .open = pmb_debugfs_open, 385 .open = pmb_debugfs_open,
386 .read = seq_read, 386 .read = seq_read,
387 .llseek = seq_lseek, 387 .llseek = seq_lseek,
388 .release = seq_release, 388 .release = single_release,
389}; 389};
390 390
391static int __init pmb_debugfs_init(void) 391static int __init pmb_debugfs_init(void)