Blame view
arch/avr32/mm/cache.c
3.73 KB
5f97f7f94 [PATCH] avr32 arc... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/* * Copyright (C) 2004-2006 Atmel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/highmem.h> #include <linux/unistd.h> #include <asm/cacheflush.h> #include <asm/cachectl.h> #include <asm/processor.h> #include <asm/uaccess.h> |
c80ce2d52 avr32: Introducin... |
16 |
#include <asm/syscalls.h> |
5f97f7f94 [PATCH] avr32 arc... |
17 18 19 20 21 22 23 24 25 |
/* * If you attempt to flush anything more than this, you need superuser * privileges. The value is completely arbitrary. */ #define CACHEFLUSH_MAX_LEN 1024 void invalidate_dcache_region(void *start, size_t size) { |
212868d38 [AVR32] Fix incor... |
26 |
unsigned long v, begin, end, linesz, mask; |
5f97f7f94 [PATCH] avr32 arc... |
27 28 |
linesz = boot_cpu_data.dcache.linesz; |
212868d38 [AVR32] Fix incor... |
29 |
mask = linesz - 1; |
5f97f7f94 [PATCH] avr32 arc... |
30 |
|
212868d38 [AVR32] Fix incor... |
31 32 33 34 |
/* when first and/or last cachelines are shared, flush them * instead of invalidating ... never discard valid data! */ begin = (unsigned long)start; |
ab61f7d21 [AVR32] Fix bug i... |
35 |
end = begin + size; |
5f97f7f94 [PATCH] avr32 arc... |
36 |
|
212868d38 [AVR32] Fix incor... |
37 38 39 |
if (begin & mask) { flush_dcache_line(start); begin += linesz; |
212868d38 [AVR32] Fix incor... |
40 |
} |
ab61f7d21 [AVR32] Fix bug i... |
41 |
if (end & mask) { |
212868d38 [AVR32] Fix incor... |
42 |
flush_dcache_line((void *)end); |
ab61f7d21 [AVR32] Fix bug i... |
43 |
end &= ~mask; |
212868d38 [AVR32] Fix incor... |
44 |
} |
5f97f7f94 [PATCH] avr32 arc... |
45 |
|
212868d38 [AVR32] Fix incor... |
46 |
/* remaining cachelines only need invalidation */ |
ab61f7d21 [AVR32] Fix bug i... |
47 |
for (v = begin; v < end; v += linesz) |
5f97f7f94 [PATCH] avr32 arc... |
48 |
invalidate_dcache_line((void *)v); |
ab61f7d21 [AVR32] Fix bug i... |
49 |
flush_write_buffer(); |
5f97f7f94 [PATCH] avr32 arc... |
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
} void clean_dcache_region(void *start, size_t size) { unsigned long v, begin, end, linesz; linesz = boot_cpu_data.dcache.linesz; begin = (unsigned long)start & ~(linesz - 1); end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1); for (v = begin; v < end; v += linesz) clean_dcache_line((void *)v); flush_write_buffer(); } void flush_dcache_region(void *start, size_t size) { unsigned long v, begin, end, linesz; linesz = boot_cpu_data.dcache.linesz; begin = (unsigned long)start & ~(linesz - 1); end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1); for (v = begin; v < end; v += linesz) flush_dcache_line((void *)v); flush_write_buffer(); } void invalidate_icache_region(void *start, size_t size) { unsigned long v, begin, end, linesz; linesz = boot_cpu_data.icache.linesz; begin = (unsigned long)start & ~(linesz - 1); end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1); for (v = begin; v < end; v += linesz) invalidate_icache_line((void *)v); } static inline void __flush_icache_range(unsigned long start, unsigned long end) { unsigned long v, linesz; linesz = boot_cpu_data.dcache.linesz; for (v = start; v < end; v += linesz) { clean_dcache_line((void *)v); invalidate_icache_line((void *)v); } flush_write_buffer(); } /* * This one is called after a module has been loaded. */ void flush_icache_range(unsigned long start, unsigned long end) { unsigned long linesz; linesz = boot_cpu_data.dcache.linesz; __flush_icache_range(start & ~(linesz - 1), (end + linesz - 1) & ~(linesz - 1)); } /* |
a335b2e17 mm: Fix out-of-da... |
116 |
* This one is called from __do_fault() and do_swap_page(). |
5f97f7f94 [PATCH] avr32 arc... |
117 118 119 120 |
*/ void flush_icache_page(struct vm_area_struct *vma, struct page *page) { if (vma->vm_flags & VM_EXEC) { |
28c1d39db [AVR32] Don't use... |
121 |
void *v = page_address(page); |
5f97f7f94 [PATCH] avr32 arc... |
122 |
__flush_icache_range((unsigned long)v, (unsigned long)v + PAGE_SIZE); |
5f97f7f94 [PATCH] avr32 arc... |
123 124 |
} } |
5f97f7f94 [PATCH] avr32 arc... |
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
asmlinkage int sys_cacheflush(int operation, void __user *addr, size_t len) { int ret; if (len > CACHEFLUSH_MAX_LEN) { ret = -EPERM; if (!capable(CAP_SYS_ADMIN)) goto out; } ret = -EFAULT; if (!access_ok(VERIFY_WRITE, addr, len)) goto out; switch (operation) { case CACHE_IFLUSH: flush_icache_range((unsigned long)addr, (unsigned long)addr + len); ret = 0; break; default: ret = -EINVAL; } out: return ret; } |
68ca3e537 [AVR32] Fix copy_... |
152 153 154 155 156 157 158 159 160 161 |
void copy_to_user_page(struct vm_area_struct *vma, struct page *page, unsigned long vaddr, void *dst, const void *src, unsigned long len) { memcpy(dst, src, len); if (vma->vm_flags & VM_EXEC) flush_icache_range((unsigned long)dst, (unsigned long)dst + len); } |