blob: 39626912de986ed500a9d5da3931905cc3fc4bf3 [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
David Howellsb920de12008-02-08 04:19:31 -080014/*
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) \
Mark Salterd6bb7a12010-01-08 14:43:16 -080049 : "memory", "cc"); \
David Howellsb920de12008-02-08 04:19:31 -080050} while (0)
51
52long
David Howellsb920de12008-02-08 04:19:31 -080053strncpy_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) \
Mark Salterd6bb7a12010-01-08 14:43:16 -080088 : "memory", "cc"); \
David Howellsb920de12008-02-08 04:19:31 -080089} 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)
Mark Salterd6bb7a12010-01-08 14:43:16 -0800140 : "memory", "cc");
David Howellsb920de12008-02-08 04:19:31 -0800141 return res;
142}