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.c128
-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, 98 insertions, 137 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..b2ce014401b5 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>
@@ -27,21 +28,10 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
27 dma_addr_t *dma_handle, gfp_t gfp) 28 dma_addr_t *dma_handle, gfp_t gfp)
28{ 29{
29 void *ret, *ret_nocache; 30 void *ret, *ret_nocache;
30 struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
31 int order = get_order(size); 31 int order = get_order(size);
32 32
33 if (mem) { 33 if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
34 int page = bitmap_find_free_region(mem->bitmap, mem->size, 34 return ret;
35 order);
36 if (page >= 0) {
37 *dma_handle = mem->device_base + (page << PAGE_SHIFT);
38 ret = mem->virt_base + (page << PAGE_SHIFT);
39 memset(ret, 0, size);
40 return ret;
41 }
42 if (mem->flags & DMA_MEMORY_EXCLUSIVE)
43 return NULL;
44 }
45 35
46 ret = (void *)__get_free_pages(gfp, order); 36 ret = (void *)__get_free_pages(gfp, order);
47 if (!ret) 37 if (!ret)
@@ -71,11 +61,7 @@ void dma_free_coherent(struct device *dev, size_t size,
71 struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; 61 struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
72 int order = get_order(size); 62 int order = get_order(size);
73 63
74 if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) { 64 if (!dma_release_from_coherent(dev, order, vaddr)) {
75 int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
76
77 bitmap_release_region(mem->bitmap, page, order);
78 } else {
79 WARN_ON(irqs_disabled()); /* for portability */ 65 WARN_ON(irqs_disabled()); /* for portability */
80 BUG_ON(mem && mem->flags & DMA_MEMORY_EXCLUSIVE); 66 BUG_ON(mem && mem->flags & DMA_MEMORY_EXCLUSIVE);
81 free_pages((unsigned long)phys_to_virt(dma_handle), order); 67 free_pages((unsigned long)phys_to_virt(dma_handle), order);
@@ -84,83 +70,6 @@ void dma_free_coherent(struct device *dev, size_t size,
84} 70}
85EXPORT_SYMBOL(dma_free_coherent); 71EXPORT_SYMBOL(dma_free_coherent);
86 72
87int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
88 dma_addr_t device_addr, size_t size, int flags)
89{
90 void __iomem *mem_base = NULL;
91 int pages = size >> PAGE_SHIFT;
92 int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
93
94 if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
95 goto out;
96 if (!size)
97 goto out;
98 if (dev->dma_mem)
99 goto out;
100
101 /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
102
103 mem_base = ioremap_nocache(bus_addr, size);
104 if (!mem_base)
105 goto out;
106
107 dev->dma_mem = kmalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
108 if (!dev->dma_mem)
109 goto out;
110 dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
111 if (!dev->dma_mem->bitmap)
112 goto free1_out;
113
114 dev->dma_mem->virt_base = mem_base;
115 dev->dma_mem->device_base = device_addr;
116 dev->dma_mem->size = pages;
117 dev->dma_mem->flags = flags;
118
119 if (flags & DMA_MEMORY_MAP)
120 return DMA_MEMORY_MAP;
121
122 return DMA_MEMORY_IO;
123
124 free1_out:
125 kfree(dev->dma_mem);
126 out:
127 if (mem_base)
128 iounmap(mem_base);
129 return 0;
130}
131EXPORT_SYMBOL(dma_declare_coherent_memory);
132
133void dma_release_declared_memory(struct device *dev)
134{
135 struct dma_coherent_mem *mem = dev->dma_mem;
136
137 if (!mem)
138 return;
139 dev->dma_mem = NULL;
140 iounmap(mem->virt_base);
141 kfree(mem->bitmap);
142 kfree(mem);
143}
144EXPORT_SYMBOL(dma_release_declared_memory);
145
146void *dma_mark_declared_memory_occupied(struct device *dev,
147 dma_addr_t device_addr, size_t size)
148{
149 struct dma_coherent_mem *mem = dev->dma_mem;
150 int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
151 int pos, err;
152
153 if (!mem)
154 return ERR_PTR(-EINVAL);
155
156 pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
157 err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
158 if (err != 0)
159 return ERR_PTR(err);
160 return mem->virt_base + (pos << PAGE_SHIFT);
161}
162EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
163
164void dma_cache_sync(struct device *dev, void *vaddr, size_t size, 73void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
165 enum dma_data_direction direction) 74 enum dma_data_direction direction)
166{ 75{
@@ -185,3 +94,32 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
185 } 94 }
186} 95}
187EXPORT_SYMBOL(dma_cache_sync); 96EXPORT_SYMBOL(dma_cache_sync);
97
98int platform_resource_setup_memory(struct platform_device *pdev,
99 char *name, unsigned long memsize)
100{
101 struct resource *r;
102 dma_addr_t dma_handle;
103 void *buf;
104
105 r = pdev->resource + pdev->num_resources - 1;
106 if (r->flags) {
107 pr_warning("%s: unable to find empty space for resource\n",
108 name);
109 return -EINVAL;
110 }
111
112 buf = dma_alloc_coherent(NULL, memsize, &dma_handle, GFP_KERNEL);
113 if (!buf) {
114 pr_warning("%s: unable to allocate memory\n", name);
115 return -ENOMEM;
116 }
117
118 memset(buf, 0, memsize);
119
120 r->flags = IORESOURCE_MEM;
121 r->start = dma_handle;
122 r->end = r->start + memsize - 1;
123 r->name = name;
124 return 0;
125}
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)