at v4.13 142 lines 3.1 kB view raw
1/* MN10300 Userspace accessor functions 2 * 3 * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd. 4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 5 * Written by David Howells (dhowells@redhat.com) 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public Licence 9 * as published by the Free Software Foundation; either version 10 * 2 of the Licence, or (at your option) any later version. 11 */ 12#include <linux/uaccess.h> 13 14/* 15 * Copy a null terminated string from userspace. 16 */ 17#define __do_strncpy_from_user(dst, src, count, res) \ 18do { \ 19 int w; \ 20 asm volatile( \ 21 " mov %1,%0\n" \ 22 " cmp 0,%1\n" \ 23 " beq 2f\n" \ 24 "0:\n" \ 25 " movbu (%5),%2\n" \ 26 "1:\n" \ 27 " movbu %2,(%6)\n" \ 28 " inc %5\n" \ 29 " inc %6\n" \ 30 " cmp 0,%2\n" \ 31 " beq 2f\n" \ 32 " add -1,%1\n" \ 33 " bne 0b\n" \ 34 "2:\n" \ 35 " sub %1,%0\n" \ 36 "3:\n" \ 37 " .section .fixup,\"ax\"\n" \ 38 "4:\n" \ 39 " mov %3,%0\n" \ 40 " jmp 3b\n" \ 41 " .previous\n" \ 42 " .section __ex_table,\"a\"\n" \ 43 " .balign 4\n" \ 44 " .long 0b,4b\n" \ 45 " .long 1b,4b\n" \ 46 " .previous" \ 47 :"=&r"(res), "=r"(count), "=&r"(w) \ 48 :"i"(-EFAULT), "1"(count), "a"(src), "a"(dst) \ 49 : "memory", "cc"); \ 50} while (0) 51 52long 53strncpy_from_user(char *dst, const char *src, long count) 54{ 55 long res = -EFAULT; 56 if (access_ok(VERIFY_READ, src, 1)) 57 __do_strncpy_from_user(dst, src, count, res); 58 return res; 59} 60 61 62/* 63 * Clear a userspace memory 64 */ 65#define __do_clear_user(addr, size) \ 66do { \ 67 int w; \ 68 asm volatile( \ 69 " cmp 0,%0\n" \ 70 " beq 1f\n" \ 71 " clr %1\n" \ 72 "0: movbu %1,(%3,%2)\n" \ 73 " inc %3\n" \ 74 " cmp %0,%3\n" \ 75 " bne 0b\n" \ 76 "1:\n" \ 77 " sub %3,%0\n" \ 78 "2:\n" \ 79 ".section .fixup,\"ax\"\n" \ 80 "3: jmp 2b\n" \ 81 ".previous\n" \ 82 ".section __ex_table,\"a\"\n" \ 83 " .balign 4\n" \ 84 " .long 0b,3b\n" \ 85 ".previous\n" \ 86 : "+r"(size), "=&r"(w) \ 87 : "a"(addr), "d"(0) \ 88 : "memory", "cc"); \ 89} while (0) 90 91unsigned long 92__clear_user(void *to, unsigned long n) 93{ 94 __do_clear_user(to, n); 95 return n; 96} 97 98unsigned long 99clear_user(void *to, unsigned long n) 100{ 101 if (access_ok(VERIFY_WRITE, to, n)) 102 __do_clear_user(to, n); 103 return n; 104} 105 106/* 107 * Return the size of a string (including the ending 0) 108 * 109 * Return 0 on exception, a value greater than N if too long 110 */ 111long strnlen_user(const char *s, long n) 112{ 113 unsigned long res, w; 114 115 if (!__addr_ok(s)) 116 return 0; 117 118 if (n < 0 || n + (u_long) s > current_thread_info()->addr_limit.seg) 119 n = current_thread_info()->addr_limit.seg - (u_long)s; 120 121 asm volatile( 122 "0: cmp %4,%0\n" 123 " beq 2f\n" 124 "1: movbu (%0,%3),%1\n" 125 " inc %0\n" 126 " cmp 0,%1\n" 127 " beq 3f\n" 128 " bra 0b\n" 129 "2: clr %0\n" 130 "3:\n" 131 ".section .fixup,\"ax\"\n" 132 "4: jmp 2b\n" 133 ".previous\n" 134 ".section __ex_table,\"a\"\n" 135 " .balign 4\n" 136 " .long 1b,4b\n" 137 ".previous\n" 138 :"=d"(res), "=&r"(w) 139 :"0"(0), "a"(s), "r"(n) 140 : "memory", "cc"); 141 return res; 142}