162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <linux/uaccess.h>
562306a36Sopenharmony_ci#include <linux/types.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ciunsigned long raw_copy_from_user(void *to, const void *from,
862306a36Sopenharmony_ci			unsigned long n)
962306a36Sopenharmony_ci{
1062306a36Sopenharmony_ci	int tmp, nsave;
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci	__asm__ __volatile__(
1362306a36Sopenharmony_ci	"0:     cmpnei  %1, 0           \n"
1462306a36Sopenharmony_ci	"       bf      7f              \n"
1562306a36Sopenharmony_ci	"       mov     %3, %1          \n"
1662306a36Sopenharmony_ci	"       or      %3, %2          \n"
1762306a36Sopenharmony_ci	"       andi    %3, 3           \n"
1862306a36Sopenharmony_ci	"       cmpnei  %3, 0           \n"
1962306a36Sopenharmony_ci	"       bf      1f              \n"
2062306a36Sopenharmony_ci	"       br      5f              \n"
2162306a36Sopenharmony_ci	"1:     cmplti  %0, 16          \n"
2262306a36Sopenharmony_ci	"       bt      3f              \n"
2362306a36Sopenharmony_ci	"2:     ldw     %3, (%2, 0)     \n"
2462306a36Sopenharmony_ci	"10:    ldw     %4, (%2, 4)     \n"
2562306a36Sopenharmony_ci	"       stw     %3, (%1, 0)     \n"
2662306a36Sopenharmony_ci	"       stw     %4, (%1, 4)     \n"
2762306a36Sopenharmony_ci	"11:    ldw     %3, (%2, 8)     \n"
2862306a36Sopenharmony_ci	"12:    ldw     %4, (%2, 12)    \n"
2962306a36Sopenharmony_ci	"       stw     %3, (%1, 8)     \n"
3062306a36Sopenharmony_ci	"       stw     %4, (%1, 12)    \n"
3162306a36Sopenharmony_ci	"       addi    %2, 16          \n"
3262306a36Sopenharmony_ci	"       addi    %1, 16          \n"
3362306a36Sopenharmony_ci	"       subi    %0, 16          \n"
3462306a36Sopenharmony_ci	"       br      1b              \n"
3562306a36Sopenharmony_ci	"3:     cmplti  %0, 4           \n"
3662306a36Sopenharmony_ci	"       bt      5f              \n"
3762306a36Sopenharmony_ci	"4:     ldw     %3, (%2, 0)     \n"
3862306a36Sopenharmony_ci	"       stw     %3, (%1, 0)     \n"
3962306a36Sopenharmony_ci	"       addi    %2, 4           \n"
4062306a36Sopenharmony_ci	"       addi    %1, 4           \n"
4162306a36Sopenharmony_ci	"       subi    %0, 4           \n"
4262306a36Sopenharmony_ci	"       br      3b              \n"
4362306a36Sopenharmony_ci	"5:     cmpnei  %0, 0           \n"
4462306a36Sopenharmony_ci	"       bf      7f              \n"
4562306a36Sopenharmony_ci	"6:     ldb     %3, (%2, 0)     \n"
4662306a36Sopenharmony_ci	"       stb     %3, (%1, 0)     \n"
4762306a36Sopenharmony_ci	"       addi    %2,  1          \n"
4862306a36Sopenharmony_ci	"       addi    %1,  1          \n"
4962306a36Sopenharmony_ci	"       subi    %0,  1          \n"
5062306a36Sopenharmony_ci	"       br      5b              \n"
5162306a36Sopenharmony_ci	"8:     stw     %3, (%1, 0)     \n"
5262306a36Sopenharmony_ci	"       subi    %0, 4           \n"
5362306a36Sopenharmony_ci	"       bf      7f              \n"
5462306a36Sopenharmony_ci	"9:     subi    %0, 8           \n"
5562306a36Sopenharmony_ci	"       bf      7f              \n"
5662306a36Sopenharmony_ci	"13:    stw     %3, (%1, 8)     \n"
5762306a36Sopenharmony_ci	"       subi    %0, 12          \n"
5862306a36Sopenharmony_ci	"       bf      7f              \n"
5962306a36Sopenharmony_ci	".section __ex_table, \"a\"     \n"
6062306a36Sopenharmony_ci	".align   2                     \n"
6162306a36Sopenharmony_ci	".long    2b, 7f                \n"
6262306a36Sopenharmony_ci	".long    4b, 7f                \n"
6362306a36Sopenharmony_ci	".long    6b, 7f                \n"
6462306a36Sopenharmony_ci	".long   10b, 8b                \n"
6562306a36Sopenharmony_ci	".long   11b, 9b                \n"
6662306a36Sopenharmony_ci	".long   12b,13b                \n"
6762306a36Sopenharmony_ci	".previous                      \n"
6862306a36Sopenharmony_ci	"7:                             \n"
6962306a36Sopenharmony_ci	: "=r"(n), "=r"(to), "=r"(from), "=r"(nsave),
7062306a36Sopenharmony_ci	  "=r"(tmp)
7162306a36Sopenharmony_ci	: "0"(n), "1"(to), "2"(from)
7262306a36Sopenharmony_ci	: "memory");
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	return n;
7562306a36Sopenharmony_ci}
7662306a36Sopenharmony_ciEXPORT_SYMBOL(raw_copy_from_user);
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ciunsigned long raw_copy_to_user(void *to, const void *from,
7962306a36Sopenharmony_ci			unsigned long n)
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci	int w0, w1, w2, w3;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	__asm__ __volatile__(
8462306a36Sopenharmony_ci	"0:     cmpnei  %1, 0           \n"
8562306a36Sopenharmony_ci	"       bf      8f              \n"
8662306a36Sopenharmony_ci	"       mov     %3, %1          \n"
8762306a36Sopenharmony_ci	"       or      %3, %2          \n"
8862306a36Sopenharmony_ci	"       andi    %3, 3           \n"
8962306a36Sopenharmony_ci	"       cmpnei  %3, 0           \n"
9062306a36Sopenharmony_ci	"       bf      1f              \n"
9162306a36Sopenharmony_ci	"       br      5f              \n"
9262306a36Sopenharmony_ci	"1:     cmplti  %0, 16          \n" /* 4W */
9362306a36Sopenharmony_ci	"       bt      3f              \n"
9462306a36Sopenharmony_ci	"       ldw     %3, (%2, 0)     \n"
9562306a36Sopenharmony_ci	"       ldw     %4, (%2, 4)     \n"
9662306a36Sopenharmony_ci	"       ldw     %5, (%2, 8)     \n"
9762306a36Sopenharmony_ci	"       ldw     %6, (%2, 12)    \n"
9862306a36Sopenharmony_ci	"2:     stw     %3, (%1, 0)     \n"
9962306a36Sopenharmony_ci	"9:     stw     %4, (%1, 4)     \n"
10062306a36Sopenharmony_ci	"10:    stw     %5, (%1, 8)     \n"
10162306a36Sopenharmony_ci	"11:    stw     %6, (%1, 12)    \n"
10262306a36Sopenharmony_ci	"       addi    %2, 16          \n"
10362306a36Sopenharmony_ci	"       addi    %1, 16          \n"
10462306a36Sopenharmony_ci	"       subi    %0, 16          \n"
10562306a36Sopenharmony_ci	"       br      1b              \n"
10662306a36Sopenharmony_ci	"3:     cmplti  %0, 4           \n" /* 1W */
10762306a36Sopenharmony_ci	"       bt      5f              \n"
10862306a36Sopenharmony_ci	"       ldw     %3, (%2, 0)     \n"
10962306a36Sopenharmony_ci	"4:     stw     %3, (%1, 0)     \n"
11062306a36Sopenharmony_ci	"       addi    %2, 4           \n"
11162306a36Sopenharmony_ci	"       addi    %1, 4           \n"
11262306a36Sopenharmony_ci	"       subi    %0, 4           \n"
11362306a36Sopenharmony_ci	"       br      3b              \n"
11462306a36Sopenharmony_ci	"5:     cmpnei  %0, 0           \n"  /* 1B */
11562306a36Sopenharmony_ci	"       bf      13f             \n"
11662306a36Sopenharmony_ci	"       ldb     %3, (%2, 0)     \n"
11762306a36Sopenharmony_ci	"6:     stb     %3, (%1, 0)     \n"
11862306a36Sopenharmony_ci	"       addi    %2,  1          \n"
11962306a36Sopenharmony_ci	"       addi    %1,  1          \n"
12062306a36Sopenharmony_ci	"       subi    %0,  1          \n"
12162306a36Sopenharmony_ci	"       br      5b              \n"
12262306a36Sopenharmony_ci	"7:     subi	%0,  4          \n"
12362306a36Sopenharmony_ci	"8:     subi	%0,  4          \n"
12462306a36Sopenharmony_ci	"12:    subi	%0,  4          \n"
12562306a36Sopenharmony_ci	"       br      13f             \n"
12662306a36Sopenharmony_ci	".section __ex_table, \"a\"     \n"
12762306a36Sopenharmony_ci	".align   2                     \n"
12862306a36Sopenharmony_ci	".long    2b, 13f               \n"
12962306a36Sopenharmony_ci	".long    4b, 13f               \n"
13062306a36Sopenharmony_ci	".long    6b, 13f               \n"
13162306a36Sopenharmony_ci	".long    9b, 12b               \n"
13262306a36Sopenharmony_ci	".long   10b, 8b                \n"
13362306a36Sopenharmony_ci	".long   11b, 7b                \n"
13462306a36Sopenharmony_ci	".previous                      \n"
13562306a36Sopenharmony_ci	"13:                            \n"
13662306a36Sopenharmony_ci	: "=r"(n), "=r"(to), "=r"(from), "=r"(w0),
13762306a36Sopenharmony_ci	  "=r"(w1), "=r"(w2), "=r"(w3)
13862306a36Sopenharmony_ci	: "0"(n), "1"(to), "2"(from)
13962306a36Sopenharmony_ci	: "memory");
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	return n;
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ciEXPORT_SYMBOL(raw_copy_to_user);
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci/*
14662306a36Sopenharmony_ci * __clear_user: - Zero a block of memory in user space, with less checking.
14762306a36Sopenharmony_ci * @to:   Destination address, in user space.
14862306a36Sopenharmony_ci * @n:    Number of bytes to zero.
14962306a36Sopenharmony_ci *
15062306a36Sopenharmony_ci * Zero a block of memory in user space.  Caller must check
15162306a36Sopenharmony_ci * the specified block with access_ok() before calling this function.
15262306a36Sopenharmony_ci *
15362306a36Sopenharmony_ci * Returns number of bytes that could not be cleared.
15462306a36Sopenharmony_ci * On success, this will be zero.
15562306a36Sopenharmony_ci */
15662306a36Sopenharmony_ciunsigned long
15762306a36Sopenharmony_ci__clear_user(void __user *to, unsigned long n)
15862306a36Sopenharmony_ci{
15962306a36Sopenharmony_ci	int data, value, tmp;
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	__asm__ __volatile__(
16262306a36Sopenharmony_ci	"0:     cmpnei  %1, 0           \n"
16362306a36Sopenharmony_ci	"       bf      7f              \n"
16462306a36Sopenharmony_ci	"       mov     %3, %1          \n"
16562306a36Sopenharmony_ci	"       andi    %3, 3           \n"
16662306a36Sopenharmony_ci	"       cmpnei  %3, 0           \n"
16762306a36Sopenharmony_ci	"       bf      1f              \n"
16862306a36Sopenharmony_ci	"       br      5f              \n"
16962306a36Sopenharmony_ci	"1:     cmplti  %0, 32          \n" /* 4W */
17062306a36Sopenharmony_ci	"       bt      3f              \n"
17162306a36Sopenharmony_ci	"8:     stw     %2, (%1, 0)     \n"
17262306a36Sopenharmony_ci	"10:    stw     %2, (%1, 4)     \n"
17362306a36Sopenharmony_ci	"11:    stw     %2, (%1, 8)     \n"
17462306a36Sopenharmony_ci	"12:    stw     %2, (%1, 12)    \n"
17562306a36Sopenharmony_ci	"13:    stw     %2, (%1, 16)    \n"
17662306a36Sopenharmony_ci	"14:    stw     %2, (%1, 20)    \n"
17762306a36Sopenharmony_ci	"15:    stw     %2, (%1, 24)    \n"
17862306a36Sopenharmony_ci	"16:    stw     %2, (%1, 28)    \n"
17962306a36Sopenharmony_ci	"       addi    %1, 32          \n"
18062306a36Sopenharmony_ci	"       subi    %0, 32          \n"
18162306a36Sopenharmony_ci	"       br      1b              \n"
18262306a36Sopenharmony_ci	"3:     cmplti  %0, 4           \n" /* 1W */
18362306a36Sopenharmony_ci	"       bt      5f              \n"
18462306a36Sopenharmony_ci	"4:     stw     %2, (%1, 0)     \n"
18562306a36Sopenharmony_ci	"       addi    %1, 4           \n"
18662306a36Sopenharmony_ci	"       subi    %0, 4           \n"
18762306a36Sopenharmony_ci	"       br      3b              \n"
18862306a36Sopenharmony_ci	"5:     cmpnei  %0, 0           \n" /* 1B */
18962306a36Sopenharmony_ci	"9:     bf      7f              \n"
19062306a36Sopenharmony_ci	"6:     stb     %2, (%1, 0)     \n"
19162306a36Sopenharmony_ci	"       addi    %1,  1          \n"
19262306a36Sopenharmony_ci	"       subi    %0,  1          \n"
19362306a36Sopenharmony_ci	"       br      5b              \n"
19462306a36Sopenharmony_ci	".section __ex_table,\"a\"      \n"
19562306a36Sopenharmony_ci	".align   2                     \n"
19662306a36Sopenharmony_ci	".long    8b, 9b                \n"
19762306a36Sopenharmony_ci	".long    10b, 9b               \n"
19862306a36Sopenharmony_ci	".long    11b, 9b               \n"
19962306a36Sopenharmony_ci	".long    12b, 9b               \n"
20062306a36Sopenharmony_ci	".long    13b, 9b               \n"
20162306a36Sopenharmony_ci	".long    14b, 9b               \n"
20262306a36Sopenharmony_ci	".long    15b, 9b               \n"
20362306a36Sopenharmony_ci	".long    16b, 9b               \n"
20462306a36Sopenharmony_ci	".long    4b, 9b                \n"
20562306a36Sopenharmony_ci	".long    6b, 9b                \n"
20662306a36Sopenharmony_ci	".previous                      \n"
20762306a36Sopenharmony_ci	"7:                             \n"
20862306a36Sopenharmony_ci	: "=r"(n), "=r" (data), "=r"(value), "=r"(tmp)
20962306a36Sopenharmony_ci	: "0"(n), "1"(to), "2"(0)
21062306a36Sopenharmony_ci	: "memory");
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	return n;
21362306a36Sopenharmony_ci}
21462306a36Sopenharmony_ciEXPORT_SYMBOL(__clear_user);
215