Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/mn10300/lib/usercopy.c
10817 views
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 ([email protected])
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 <asm/uaccess.h>
13
14
unsigned 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
22
unsigned 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);
27
return n;
28
}
29
30
/*
31
* Copy a null terminated string from userspace.
32
*/
33
#define __do_strncpy_from_user(dst, src, count, res) \
34
do { \
35
int w; \
36
asm volatile( \
37
" mov %1,%0\n" \
38
" cmp 0,%1\n" \
39
" beq 2f\n" \
40
"0:\n" \
41
" movbu (%5),%2\n" \
42
"1:\n" \
43
" movbu %2,(%6)\n" \
44
" inc %5\n" \
45
" inc %6\n" \
46
" cmp 0,%2\n" \
47
" beq 2f\n" \
48
" add -1,%1\n" \
49
" bne 0b\n" \
50
"2:\n" \
51
" sub %1,%0\n" \
52
"3:\n" \
53
" .section .fixup,\"ax\"\n" \
54
"4:\n" \
55
" mov %3,%0\n" \
56
" jmp 3b\n" \
57
" .previous\n" \
58
" .section __ex_table,\"a\"\n" \
59
" .balign 4\n" \
60
" .long 0b,4b\n" \
61
" .long 1b,4b\n" \
62
" .previous" \
63
:"=&r"(res), "=r"(count), "=&r"(w) \
64
:"i"(-EFAULT), "1"(count), "a"(src), "a"(dst) \
65
: "memory", "cc"); \
66
} while (0)
67
68
long
69
__strncpy_from_user(char *dst, const char *src, long count)
70
{
71
long res;
72
__do_strncpy_from_user(dst, src, count, res);
73
return res;
74
}
75
76
long
77
strncpy_from_user(char *dst, const char *src, long count)
78
{
79
long res = -EFAULT;
80
if (access_ok(VERIFY_READ, src, 1))
81
__do_strncpy_from_user(dst, src, count, res);
82
return res;
83
}
84
85
86
/*
87
* Clear a userspace memory
88
*/
89
#define __do_clear_user(addr, size) \
90
do { \
91
int w; \
92
asm volatile( \
93
" cmp 0,%0\n" \
94
" beq 1f\n" \
95
" clr %1\n" \
96
"0: movbu %1,(%3,%2)\n" \
97
" inc %3\n" \
98
" cmp %0,%3\n" \
99
" bne 0b\n" \
100
"1:\n" \
101
" sub %3,%0\n" \
102
"2:\n" \
103
".section .fixup,\"ax\"\n" \
104
"3: jmp 2b\n" \
105
".previous\n" \
106
".section __ex_table,\"a\"\n" \
107
" .balign 4\n" \
108
" .long 0b,3b\n" \
109
".previous\n" \
110
: "+r"(size), "=&r"(w) \
111
: "a"(addr), "d"(0) \
112
: "memory", "cc"); \
113
} while (0)
114
115
unsigned long
116
__clear_user(void *to, unsigned long n)
117
{
118
__do_clear_user(to, n);
119
return n;
120
}
121
122
unsigned long
123
clear_user(void *to, unsigned long n)
124
{
125
if (access_ok(VERIFY_WRITE, to, n))
126
__do_clear_user(to, n);
127
return n;
128
}
129
130
/*
131
* Return the size of a string (including the ending 0)
132
*
133
* Return 0 on exception, a value greater than N if too long
134
*/
135
long strnlen_user(const char *s, long n)
136
{
137
unsigned long res, w;
138
139
if (!__addr_ok(s))
140
return 0;
141
142
if (n < 0 || n + (u_long) s > current_thread_info()->addr_limit.seg)
143
n = current_thread_info()->addr_limit.seg - (u_long)s;
144
145
asm volatile(
146
"0: cmp %4,%0\n"
147
" beq 2f\n"
148
"1: movbu (%0,%3),%1\n"
149
" inc %0\n"
150
" cmp 0,%1\n"
151
" beq 3f\n"
152
" bra 0b\n"
153
"2: clr %0\n"
154
"3:\n"
155
".section .fixup,\"ax\"\n"
156
"4: jmp 2b\n"
157
".previous\n"
158
".section __ex_table,\"a\"\n"
159
" .balign 4\n"
160
" .long 1b,4b\n"
161
".previous\n"
162
:"=d"(res), "=&r"(w)
163
:"0"(0), "a"(s), "r"(n)
164
: "memory", "cc");
165
return res;
166
}
167
168