diff options
Diffstat (limited to 'arch/sh/mm')
| -rw-r--r-- | arch/sh/mm/Kconfig | 20 | ||||
| -rw-r--r-- | arch/sh/mm/cache-debugfs.c | 2 | ||||
| -rw-r--r-- | arch/sh/mm/cache-sh4.c | 67 | ||||
| -rw-r--r-- | arch/sh/mm/consistent.c | 30 | ||||
| -rw-r--r-- | arch/sh/mm/fault_32.c | 12 | ||||
| -rw-r--r-- | arch/sh/mm/pg-sh4.c | 2 | ||||
| -rw-r--r-- | arch/sh/mm/pg-sh7705.c | 2 | ||||
| -rw-r--r-- | arch/sh/mm/pmb.c | 2 |
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 | ||
| 146 | config PAGE_SIZE_4KB | 146 | config 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 | ||
| 152 | config PAGE_SIZE_8KB | 152 | config 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 | ||
| 158 | config PAGE_SIZE_16KB | ||
| 159 | bool "16kB" | ||
| 160 | depends on !MMU | ||
| 161 | help | ||
| 162 | This enables 16kB pages on MMU-less SH systems. | ||
| 163 | |||
| 158 | config PAGE_SIZE_64KB | 164 | config 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 | ||
| 165 | endchoice | 171 | endchoice |
| 166 | 172 | ||
| 173 | config 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 | |||
| 167 | choice | 181 | choice |
| 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 | ||
| 126 | static int __init cache_debugfs_init(void) | 126 | 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 @@ | |||
| 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 | ||
| 26 | static void __flush_dcache_segment_1way(unsigned long start, | 28 | static 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 | */ |
| 183 | void flush_icache_range(unsigned long start, unsigned long end) | 186 | void 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 | */ | ||
| 193 | void __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 | ||
| 219 | static inline void flush_cache_4096(unsigned long start, | 224 | 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 @@ | |||
| 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 | } |
| 187 | EXPORT_SYMBOL(dma_cache_sync); | 188 | EXPORT_SYMBOL(dma_cache_sync); |
| 189 | |||
| 190 | int 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 | */ |
| 114 | inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | 114 | pte_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 | */ |
| 121 | inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | 121 | pte_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 | ||
| 391 | static int __init pmb_debugfs_init(void) | 391 | static int __init pmb_debugfs_init(void) |
