|
@@ -25,6 +25,8 @@
|
|
|
#include <asm/syscalls.h>
|
|
|
#include <asm/uaccess.h>
|
|
|
#include <asm/unistd.h>
|
|
|
+#include <asm/cacheflush.h>
|
|
|
+#include <asm/cachectl.h>
|
|
|
|
|
|
static inline long
|
|
|
do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
|
|
@@ -179,6 +181,47 @@ asmlinkage int sys_ipc(uint call, int first, int second,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+/* sys_cacheflush -- flush (part of) the processor cache. */
|
|
|
+asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len, int op)
|
|
|
+{
|
|
|
+ struct vm_area_struct *vma;
|
|
|
+
|
|
|
+ if ((op < 0) || (op > (CACHEFLUSH_D_PURGE|CACHEFLUSH_I)))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Verify that the specified address region actually belongs
|
|
|
+ * to this process.
|
|
|
+ */
|
|
|
+ if (addr + len < addr)
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ down_read(¤t->mm->mmap_sem);
|
|
|
+ vma = find_vma (current->mm, addr);
|
|
|
+ if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end) {
|
|
|
+ up_read(¤t->mm->mmap_sem);
|
|
|
+ return -EFAULT;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (op & CACHEFLUSH_D_PURGE) {
|
|
|
+ case CACHEFLUSH_D_INVAL:
|
|
|
+ __flush_invalidate_region((void *)addr, len);
|
|
|
+ break;
|
|
|
+ case CACHEFLUSH_D_WB:
|
|
|
+ __flush_wback_region((void *)addr, len);
|
|
|
+ break;
|
|
|
+ case CACHEFLUSH_D_PURGE:
|
|
|
+ __flush_purge_region((void *)addr, len);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (op & CACHEFLUSH_I)
|
|
|
+ flush_cache_all();
|
|
|
+
|
|
|
+ up_read(¤t->mm->mmap_sem);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
asmlinkage int sys_uname(struct old_utsname __user *name)
|
|
|
{
|
|
|
int err;
|