blob: ce8899e5e171370ebc88c08a91727ef9232febf9 [file] [log] [blame]
David Howellsb920de12008-02-08 04:19:31 -08001/* 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 */
Al Viroae7cc572016-08-20 16:33:10 -040012#include <linux/uaccess.h>
David Howellsb920de12008-02-08 04:19:31 -080013
14unsigned long
15__generic_copy_to_user(void *to, const void *from, unsigned long n)
16{
17 if (access_ok(VERIFY_WRITE, to, n))
18 __copy_user(to, from, n);
19 return n;
20}
21
22unsigned long
23__generic_copy_from_user(void *to, const void *from, unsigned long n)
24{
25 if (access_ok(VERIFY_READ, from, n))
26 __copy_user_zeroing(to, from, n);
Al Viroae7cc572016-08-20 16:33:10 -040027 else
28 memset(to, 0, n);
David Howellsb920de12008-02-08 04:19:31 -080029 return n;
30}
31
32/*
33 * Copy a null terminated string from userspace.
34 */
35#define __do_strncpy_from_user(dst, src, count, res) \
36do { \
37 int w; \
38 asm volatile( \
39 " mov %1,%0\n" \
40 " cmp 0,%1\n" \
41 " beq 2f\n" \
42 "0:\n" \
43 " movbu (%5),%2\n" \
44 "1:\n" \
45 " movbu %2,(%6)\n" \
46 " inc %5\n" \
47 " inc %6\n" \
48 " cmp 0,%2\n" \
49 " beq 2f\n" \
50 " add -1,%1\n" \
51 " bne 0b\n" \
52 "2:\n" \
53 " sub %1,%0\n" \
54 "3:\n" \
55 " .section .fixup,\"ax\"\n" \
56 "4:\n" \
57 " mov %3,%0\n" \
58 " jmp 3b\n" \
59 " .previous\n" \
60 " .section __ex_table,\"a\"\n" \
61 " .balign 4\n" \
62 " .long 0b,4b\n" \
63 " .long 1b,4b\n" \
64 " .previous" \
65 :"=&r"(res), "=r"(count), "=&r"(w) \
66 :"i"(-EFAULT), "1"(count), "a"(src), "a"(dst) \
Mark Salterd6bb7a12010-01-08 14:43:16 -080067 : "memory", "cc"); \
David Howellsb920de12008-02-08 04:19:31 -080068} while (0)
69
70long
71__strncpy_from_user(char *dst, const char *src, long count)
72{
73 long res;
74 __do_strncpy_from_user(dst, src, count, res);
75 return res;
76}
77
78long
79strncpy_from_user(char *dst, const char *src, long count)
80{
81 long res = -EFAULT;
82 if (access_ok(VERIFY_READ, src, 1))
83 __do_strncpy_from_user(dst, src, count, res);
84 return res;
85}
86
87
88/*
89 * Clear a userspace memory
90 */
91#define __do_clear_user(addr, size) \
92do { \
93 int w; \
94 asm volatile( \
95 " cmp 0,%0\n" \
96 " beq 1f\n" \
97 " clr %1\n" \
98 "0: movbu %1,(%3,%2)\n" \
99 " inc %3\n" \
100 " cmp %0,%3\n" \
101 " bne 0b\n" \
102 "1:\n" \
103 " sub %3,%0\n" \
104 "2:\n" \
105 ".section .fixup,\"ax\"\n" \
106 "3: jmp 2b\n" \
107 ".previous\n" \
108 ".section __ex_table,\"a\"\n" \
109 " .balign 4\n" \
110 " .long 0b,3b\n" \
111 ".previous\n" \
112 : "+r"(size), "=&r"(w) \
113 : "a"(addr), "d"(0) \
Mark Salterd6bb7a12010-01-08 14:43:16 -0800114 : "memory", "cc"); \
David Howellsb920de12008-02-08 04:19:31 -0800115} while (0)
116
117unsigned long
118__clear_user(void *to, unsigned long n)
119{
120 __do_clear_user(to, n);
121 return n;
122}
123
124unsigned long
125clear_user(void *to, unsigned long n)
126{
127 if (access_ok(VERIFY_WRITE, to, n))
128 __do_clear_user(to, n);
129 return n;
130}
131
132/*
133 * Return the size of a string (including the ending 0)
134 *
135 * Return 0 on exception, a value greater than N if too long
136 */
137long strnlen_user(const char *s, long n)
138{
139 unsigned long res, w;
140
141 if (!__addr_ok(s))
142 return 0;
143
144 if (n < 0 || n + (u_long) s > current_thread_info()->addr_limit.seg)
145 n = current_thread_info()->addr_limit.seg - (u_long)s;
146
147 asm volatile(
148 "0: cmp %4,%0\n"
149 " beq 2f\n"
150 "1: movbu (%0,%3),%1\n"
151 " inc %0\n"
152 " cmp 0,%1\n"
153 " beq 3f\n"
154 " bra 0b\n"
155 "2: clr %0\n"
156 "3:\n"
157 ".section .fixup,\"ax\"\n"
158 "4: jmp 2b\n"
159 ".previous\n"
160 ".section __ex_table,\"a\"\n"
161 " .balign 4\n"
162 " .long 1b,4b\n"
163 ".previous\n"
164 :"=d"(res), "=&r"(w)
165 :"0"(0), "a"(s), "r"(n)
Mark Salterd6bb7a12010-01-08 14:43:16 -0800166 : "memory", "cc");
David Howellsb920de12008-02-08 04:19:31 -0800167 return res;
168}