| /* MN10300 Userspace accessor functions | |
| * | |
| * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd. | |
| * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | |
| * Written by David Howells (dhowells@redhat.com) | |
| * | |
| * This program is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU General Public Licence | |
| * as published by the Free Software Foundation; either version | |
| * 2 of the Licence, or (at your option) any later version. | |
| */ | |
| #include <linux/uaccess.h> | |
| unsigned long | |
| __generic_copy_to_user(void *to, const void *from, unsigned long n) | |
| { | |
| if (access_ok(VERIFY_WRITE, to, n)) | |
| __copy_user(to, from, n); | |
| return n; | |
| } | |
| unsigned long | |
| __generic_copy_from_user(void *to, const void *from, unsigned long n) | |
| { | |
| if (access_ok(VERIFY_READ, from, n)) | |
| __copy_user_zeroing(to, from, n); | |
| else | |
| memset(to, 0, n); | |
| return n; | |
| } | |
| /* | |
| * Copy a null terminated string from userspace. | |
| */ | |
| #define __do_strncpy_from_user(dst, src, count, res) \ | |
| do { \ | |
| int w; \ | |
| asm volatile( \ | |
| " mov %1,%0\n" \ | |
| " cmp 0,%1\n" \ | |
| " beq 2f\n" \ | |
| "0:\n" \ | |
| " movbu (%5),%2\n" \ | |
| "1:\n" \ | |
| " movbu %2,(%6)\n" \ | |
| " inc %5\n" \ | |
| " inc %6\n" \ | |
| " cmp 0,%2\n" \ | |
| " beq 2f\n" \ | |
| " add -1,%1\n" \ | |
| " bne 0b\n" \ | |
| "2:\n" \ | |
| " sub %1,%0\n" \ | |
| "3:\n" \ | |
| " .section .fixup,\"ax\"\n" \ | |
| "4:\n" \ | |
| " mov %3,%0\n" \ | |
| " jmp 3b\n" \ | |
| " .previous\n" \ | |
| " .section __ex_table,\"a\"\n" \ | |
| " .balign 4\n" \ | |
| " .long 0b,4b\n" \ | |
| " .long 1b,4b\n" \ | |
| " .previous" \ | |
| :"=&r"(res), "=r"(count), "=&r"(w) \ | |
| :"i"(-EFAULT), "1"(count), "a"(src), "a"(dst) \ | |
| : "memory", "cc"); \ | |
| } while (0) | |
| long | |
| __strncpy_from_user(char *dst, const char *src, long count) | |
| { | |
| long res; | |
| __do_strncpy_from_user(dst, src, count, res); | |
| return res; | |
| } | |
| long | |
| strncpy_from_user(char *dst, const char *src, long count) | |
| { | |
| long res = -EFAULT; | |
| if (access_ok(VERIFY_READ, src, 1)) | |
| __do_strncpy_from_user(dst, src, count, res); | |
| return res; | |
| } | |
| /* | |
| * Clear a userspace memory | |
| */ | |
| #define __do_clear_user(addr, size) \ | |
| do { \ | |
| int w; \ | |
| asm volatile( \ | |
| " cmp 0,%0\n" \ | |
| " beq 1f\n" \ | |
| " clr %1\n" \ | |
| "0: movbu %1,(%3,%2)\n" \ | |
| " inc %3\n" \ | |
| " cmp %0,%3\n" \ | |
| " bne 0b\n" \ | |
| "1:\n" \ | |
| " sub %3,%0\n" \ | |
| "2:\n" \ | |
| ".section .fixup,\"ax\"\n" \ | |
| "3: jmp 2b\n" \ | |
| ".previous\n" \ | |
| ".section __ex_table,\"a\"\n" \ | |
| " .balign 4\n" \ | |
| " .long 0b,3b\n" \ | |
| ".previous\n" \ | |
| : "+r"(size), "=&r"(w) \ | |
| : "a"(addr), "d"(0) \ | |
| : "memory", "cc"); \ | |
| } while (0) | |
| unsigned long | |
| __clear_user(void *to, unsigned long n) | |
| { | |
| __do_clear_user(to, n); | |
| return n; | |
| } | |
| unsigned long | |
| clear_user(void *to, unsigned long n) | |
| { | |
| if (access_ok(VERIFY_WRITE, to, n)) | |
| __do_clear_user(to, n); | |
| return n; | |
| } | |
| /* | |
| * Return the size of a string (including the ending 0) | |
| * | |
| * Return 0 on exception, a value greater than N if too long | |
| */ | |
| long strnlen_user(const char *s, long n) | |
| { | |
| unsigned long res, w; | |
| if (!__addr_ok(s)) | |
| return 0; | |
| if (n < 0 || n + (u_long) s > current_thread_info()->addr_limit.seg) | |
| n = current_thread_info()->addr_limit.seg - (u_long)s; | |
| asm volatile( | |
| "0: cmp %4,%0\n" | |
| " beq 2f\n" | |
| "1: movbu (%0,%3),%1\n" | |
| " inc %0\n" | |
| " cmp 0,%1\n" | |
| " beq 3f\n" | |
| " bra 0b\n" | |
| "2: clr %0\n" | |
| "3:\n" | |
| ".section .fixup,\"ax\"\n" | |
| "4: jmp 2b\n" | |
| ".previous\n" | |
| ".section __ex_table,\"a\"\n" | |
| " .balign 4\n" | |
| " .long 1b,4b\n" | |
| ".previous\n" | |
| :"=d"(res), "=&r"(w) | |
| :"0"(0), "a"(s), "r"(n) | |
| : "memory", "cc"); | |
| return res; | |
| } |