Skip to contentSkip to conversation

csky: uaccess.h: Coding convention with asm generic

PATCH Superseded [email protected] 4 participants 9 messages Apr 21, 2021 – Apr 28, 2021

Subsystems (2)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

PATCH 1/1 csky: uaccess.h: Coding convention with asm generic

From: Guo Ren <[email protected]>

Using asm-generic/uaccess.h to prevent duplicated code:
- Add user_addr_max which mentioned in generic uaccess.h
- Remove custom definitions of KERNEL/USER_DS, get/set_fs, uaccess_kerenl
- Using generic extable.h instead of custom definitions in uaccess.h

Cc Arnd Bergmann <[email protected]>
---
 arch/csky/include/asm/Kbuild    |   1 +
 arch/csky/include/asm/segment.h |   7 -
 arch/csky/include/asm/uaccess.h | 362 ++++++++-------------------------------
 arch/csky/lib/usercopy.c        | 364 +++++++++++++++++++++++-----------------
 arch/csky/mm/fault.c            |   2 +-
 5 files changed, 287 insertions(+), 449 deletions(-)
arch/csky/include/asm/Kbuild +1 -0
index cc24bb8..904a18a 100644
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 generic-y += asm-offsets.h
+generic-y += extable.h
 generic-y += gpio.h
 generic-y += kvm_para.h
 generic-y += qrwlock.h
arch/csky/include/asm/segment.h +0 -7
index 589e832..5bc1cc62 100644
@@ -7,11 +7,4 @@ typedef struct {
 	unsigned long seg;
 } mm_segment_t;
 
-#define KERNEL_DS		((mm_segment_t) { 0xFFFFFFFF })
-
-#define USER_DS			((mm_segment_t) { PAGE_OFFSET })
-#define get_fs()		(current_thread_info()->addr_limit)
-#define set_fs(x)		(current_thread_info()->addr_limit = (x))
-#define uaccess_kernel()	(get_fs().seg == KERNEL_DS.seg)
-
 #endif /* __ASM_CSKY_SEGMENT_H */
arch/csky/include/asm/uaccess.h +74 -288

413 lines not on this page · raw message

arch/csky/lib/usercopy.c +211 -153

414 lines not on this page · raw message

arch/csky/mm/fault.c +1 -1
index 1482de5..466ad94 100644
@@ -12,7 +12,7 @@ int fixup_exception(struct pt_regs *regs)
 
 	fixup = search_exception_tables(instruction_pointer(regs));
 	if (fixup) {
-		regs->pc = fixup->nextinsn;
+		regs->pc = fixup->fixup;
 
 		return 1;
 	}
Signature · 1 line
2.7.4
#1 lore raw
Quoted 6 lines · On Wed, Apr 21, 2021 at 08:54:15AM +0000, [email protected] wrote:

From: Guo Ren <[email protected]>

Using asm-generic/uaccess.h to prevent duplicated code:
- Add user_addr_max which mentioned in generic uaccess.h
- Remove custom definitions of KERNEL/USER_DS, get/set_fs, uaccess_kerenl

Instead of using the generic definitions removing support for set_fs entirely would be much preferred. The series in linux-next for mips, or the riscv version that landed in 5.10 might be good examples.

#2 lore raw
In reply to [email protected]
Quoted 11 lines · On Wed, Apr 21, 2021 at 08:54:15AM +0000, [email protected] wrote:

From: Guo Ren <[email protected]>

Using asm-generic/uaccess.h to prevent duplicated code:
- Add user_addr_max which mentioned in generic uaccess.h
- Remove custom definitions of KERNEL/USER_DS, get/set_fs, uaccess_kerenl
- Using generic extable.h instead of custom definitions in uaccess.h

Cc Arnd Bergmann <[email protected]>

Building csky:tinyconfig ... failed
--------------
Error log:
csky-linux-ld: fs/readdir.o: in function `__put_user_fn':
readdir.c:(.text+0x7c): undefined reference to `__put_user_bad'
csky-linux-ld: fs/readdir.o: in function `$d':
readdir.c:(.text+0x1bc): undefined reference to `__put_user_bad' make[1]: *** [Makefile:1277: vmlinux] Error 1
make: *** [Makefile:222: __sub-make] Error 2

Bisect log attached.

Guenter

---
# bad: [3f1fee3e7237347f09a2c7fa538119e6d9ea4b84] Add linux-next specific files for 20210426 # good: [9f4ad9e425a1d3b6a34617b8ea226d56a119a717] Linux 5.12
git bisect start 'HEAD' 'v5.12'
# bad: [bb8f486776983897309645c98705670c3d2a16e5] Merge remote-tracking branch 'crypto/master' git bisect bad bb8f486776983897309645c98705670c3d2a16e5
# bad: [6ab4f4364c450991a476eef5bc57bef3586354ed] Merge remote-tracking branch 'jc_docs/docs-next' git bisect bad 6ab4f4364c450991a476eef5bc57bef3586354ed
# bad: [fd73cab0b2a046136842b23f027dae3686588ba5] Merge remote-tracking branch 'parisc-hd/for-next' git bisect bad fd73cab0b2a046136842b23f027dae3686588ba5
# good: [f0e6103e023e0ede67848ddcd6b07044574f4fd3] soc: document merges
git bisect good f0e6103e023e0ede67848ddcd6b07044574f4fd3
# good: [70361dc0add47d3818acf9c33718ce7395f8aaa5] Merge remote-tracking branch 'arm-soc/for-next' git bisect good 70361dc0add47d3818acf9c33718ce7395f8aaa5
# good: [f62ad9f6e1100e3a1b6ca7a004fd5a972ff768df] Merge remote-tracking branch 'ti-k3/ti-k3-next' git bisect good f62ad9f6e1100e3a1b6ca7a004fd5a972ff768df
# bad: [b3b33dda4fd25e201c77f0ce9277dd34f31e86ce] Merge remote-tracking branch 'h8300/h8300-next' git bisect bad b3b33dda4fd25e201c77f0ce9277dd34f31e86ce
# good: [6a861bd8cf3c96f5825d031732e365b7721a84a5] Merge branch 'clk-qcom' into clk-next git bisect good 6a861bd8cf3c96f5825d031732e365b7721a84a5
# good: [1dd129f1deec0606fb70992521a7e5bcd2f85c69] Merge branch 'clk-qcom' into clk-next git bisect good 1dd129f1deec0606fb70992521a7e5bcd2f85c69
# good: [8808515be0ed4e33de9bfdc65f4c1b547ee11065] h8300: Replace <linux/clk-provider.h> by <linux/of_clk.h> git bisect good 8808515be0ed4e33de9bfdc65f4c1b547ee11065
# good: [e27d3ecdeb8923f35cb856fd20be14256aaa7575] Merge remote-tracking branch 'clk/clk-next' git bisect good e27d3ecdeb8923f35cb856fd20be14256aaa7575
# bad: [d3900e8d918f8fbd1366b9c2998e2830e66a0081] csky: uaccess.h: Coding convention with asm generic git bisect bad d3900e8d918f8fbd1366b9c2998e2830e66a0081
# good: [0b1f557a1fa02174a982f557581e348d91987ec6] csky: Fixup typos
git bisect good 0b1f557a1fa02174a982f557581e348d91987ec6
# good: [8bfe70e696584deeed1de1bcbfcde405aa1a1344] csky: fix syscache.c fallthrough warning git bisect good 8bfe70e696584deeed1de1bcbfcde405aa1a1344

# first bad commit: [d3900e8d918f8fbd1366b9c2998e2830e66a0081] csky: uaccess.h: Coding convention with asm generic
author maintainer
#3 lore raw

Thx, Guenter

Quoted 14 lines · Guenter Roeck
Quoted 11 lines · On Wed, Apr 21, 2021 at 08:54:15AM +0000, [email protected] wrote:

From: Guo Ren <[email protected]>

Using asm-generic/uaccess.h to prevent duplicated code:
- Add user_addr_max which mentioned in generic uaccess.h
- Remove custom definitions of KERNEL/USER_DS, get/set_fs, uaccess_kerenl
- Using generic extable.h instead of custom definitions in uaccess.h

Cc Arnd Bergmann <[email protected]>
Quoted 9 lines

Building csky:tinyconfig ... failed
--------------
Error log:
csky-linux-ld: fs/readdir.o: in function `__put_user_fn':
readdir.c:(.text+0x7c): undefined reference to `__put_user_bad'
csky-linux-ld: fs/readdir.o: in function `$d':
readdir.c:(.text+0x1bc): undefined reference to `__put_user_bad' make[1]: *** [Makefile:1277: vmlinux] Error 1
make: *** [Makefile:222: __sub-make] Error 2

It's a bug, I can't put __put_user_bad in __put_user_fn, and __put_user has done that:

/*
* These are the main single-value transfer routines. They automatically
* use the right size if we just have the right pointer type.
* This version just falls back to copy_{from,to}_user, which should
* provide a fast-path for small values.
*/
#define __put_user(x, ptr) \

({                                                              \
        __typeof__(*(ptr)) __x = (x);                           \
        int __pu_err = -EFAULT;                                 \
        __chk_user_ptr(ptr);                                    \
        switch (sizeof (*(ptr))) {                              \
        case 1:                                                 \
        case 2:                                                 \
        case 4:                                                 \
        case 8:                                                 \
                __pu_err = __put_user_fn(sizeof (*(ptr)),       \
                                         ptr, &__x);            \
                break;                                          \
        default:                                                \
                __put_user_bad();                               \
                break;                                          \
         }                                                      \
        __pu_err;                                               \

})

Also, the same problem in __get_user, and I didn't implement "case 8:".

I'll fix up it in another patch and implement __get_user_case_8 (similar with arch/arc.)

Quoted 38 lines

Bisect log attached.

Guenter

---
# bad: [3f1fee3e7237347f09a2c7fa538119e6d9ea4b84] Add linux-next specific files for 20210426 # good: [9f4ad9e425a1d3b6a34617b8ea226d56a119a717] Linux 5.12
git bisect start 'HEAD' 'v5.12'
# bad: [bb8f486776983897309645c98705670c3d2a16e5] Merge remote-tracking branch 'crypto/master' git bisect bad bb8f486776983897309645c98705670c3d2a16e5
# bad: [6ab4f4364c450991a476eef5bc57bef3586354ed] Merge remote-tracking branch 'jc_docs/docs-next' git bisect bad 6ab4f4364c450991a476eef5bc57bef3586354ed
# bad: [fd73cab0b2a046136842b23f027dae3686588ba5] Merge remote-tracking branch 'parisc-hd/for-next' git bisect bad fd73cab0b2a046136842b23f027dae3686588ba5
# good: [f0e6103e023e0ede67848ddcd6b07044574f4fd3] soc: document merges
git bisect good f0e6103e023e0ede67848ddcd6b07044574f4fd3
# good: [70361dc0add47d3818acf9c33718ce7395f8aaa5] Merge remote-tracking branch 'arm-soc/for-next' git bisect good 70361dc0add47d3818acf9c33718ce7395f8aaa5
# good: [f62ad9f6e1100e3a1b6ca7a004fd5a972ff768df] Merge remote-tracking branch 'ti-k3/ti-k3-next' git bisect good f62ad9f6e1100e3a1b6ca7a004fd5a972ff768df
# bad: [b3b33dda4fd25e201c77f0ce9277dd34f31e86ce] Merge remote-tracking branch 'h8300/h8300-next' git bisect bad b3b33dda4fd25e201c77f0ce9277dd34f31e86ce
# good: [6a861bd8cf3c96f5825d031732e365b7721a84a5] Merge branch 'clk-qcom' into clk-next git bisect good 6a861bd8cf3c96f5825d031732e365b7721a84a5
# good: [1dd129f1deec0606fb70992521a7e5bcd2f85c69] Merge branch 'clk-qcom' into clk-next git bisect good 1dd129f1deec0606fb70992521a7e5bcd2f85c69
# good: [8808515be0ed4e33de9bfdc65f4c1b547ee11065] h8300: Replace <linux/clk-provider.h> by <linux/of_clk.h> git bisect good 8808515be0ed4e33de9bfdc65f4c1b547ee11065
# good: [e27d3ecdeb8923f35cb856fd20be14256aaa7575] Merge remote-tracking branch 'clk/clk-next' git bisect good e27d3ecdeb8923f35cb856fd20be14256aaa7575
# bad: [d3900e8d918f8fbd1366b9c2998e2830e66a0081] csky: uaccess.h: Coding convention with asm generic git bisect bad d3900e8d918f8fbd1366b9c2998e2830e66a0081
# good: [0b1f557a1fa02174a982f557581e348d91987ec6] csky: Fixup typos
git bisect good 0b1f557a1fa02174a982f557581e348d91987ec6
# good: [8bfe70e696584deeed1de1bcbfcde405aa1a1344] csky: fix syscache.c fallthrough warning git bisect good 8bfe70e696584deeed1de1bcbfcde405aa1a1344

# first bad commit: [d3900e8d918f8fbd1366b9c2998e2830e66a0081] csky: uaccess.h: Coding convention with asm generic
Signature · 4 lines
Best Regards
 Guo Ren

ML: https://lore.kernel.org/linux-csky/
maintainer
#4 lore raw
Quoted 51 lines · Guo Ren
Quoted 14 lines · Guenter Roeck
Quoted 11 lines · On Wed, Apr 21, 2021 at 08:54:15AM +0000, [email protected] wrote:

From: Guo Ren <[email protected]>

Using asm-generic/uaccess.h to prevent duplicated code:
- Add user_addr_max which mentioned in generic uaccess.h
- Remove custom definitions of KERNEL/USER_DS, get/set_fs, uaccess_kerenl
- Using generic extable.h instead of custom definitions in uaccess.h

Cc Arnd Bergmann <[email protected]>
Quoted 9 lines

Building csky:tinyconfig ... failed
--------------
Error log:
csky-linux-ld: fs/readdir.o: in function `__put_user_fn':
readdir.c:(.text+0x7c): undefined reference to `__put_user_bad'
csky-linux-ld: fs/readdir.o: in function `$d':
readdir.c:(.text+0x1bc): undefined reference to `__put_user_bad' make[1]: *** [Makefile:1277: vmlinux] Error 1
make: *** [Makefile:222: __sub-make] Error 2

It's a bug, I can't put __put_user_bad in __put_user_fn, and __put_user has done that:

/*
* These are the main single-value transfer routines. They automatically
* use the right size if we just have the right pointer type.
* This version just falls back to copy_{from,to}_user, which should
* provide a fast-path for small values.
*/
#define __put_user(x, ptr) \

({                                                              \
        __typeof__(*(ptr)) __x = (x);                           \
        int __pu_err = -EFAULT;                                 \
        __chk_user_ptr(ptr);                                    \
        switch (sizeof (*(ptr))) {                              \
        case 1:                                                 \
        case 2:                                                 \
        case 4:                                                 \
        case 8:                                                 \
                __pu_err = __put_user_fn(sizeof (*(ptr)),       \
                                         ptr, &__x);            \
                break;                                          \
        default:                                                \
                __put_user_bad();                               \
                break;                                          \
         }                                                      \
        __pu_err;                                               \
Quoted 1 line

})

Actually, please don't use the asm-generic __put_user version based on copy_to_user, we probably have killed it off long ago.

We might want to come up with a new version of asm-generic/uaccess.h that actually makes it easier to have a sane per-architecture implementation of the low-level accessors without set_fs().

I've added Christoph to Cc here, he probably has some ideas on where we should be heading.

One noteworthy aspect is that almost nothing users the low-level __get_user()/__put_user() helpers any more outside of architecture specific code, so we may not need to have separate versions for much longer.

Arnd

#5 lore raw
Quoted 2 lines · Arnd Bergmann

Actually, please don't use the asm-generic __put_user version based on copy_to_user, we probably have killed it off long ago.

Yes, they are horrible.

Quoted 6 lines

We might want to come up with a new version of asm-generic/uaccess.h that actually makes it easier to have a sane per-architecture implementation of the low-level accessors without set_fs().

I've added Christoph to Cc here, he probably has some ideas on where we should be heading.

I think asm-generic/uaccess.h pretty much only makes sense for nommu. For that case we can just kill the __{get,put}_user_fn indirection. I actually have work for that in an old branch.

Trying to use any of asm-generic/uaccess.h for MMU based kernel is just asking for trouble.

Quoted 4 lines

One noteworthy aspect is that almost nothing users the low-level __get_user()/__put_user() helpers any more outside of architecture specific code, so we may not need to have separate versions for much longer.

Al has been trying to kill them off entirely for a while, and I hope he'll eventually succeed. That being said the difference should be that the __ versions just skip the access_ok, so having both is fairly trivial to implement.

author maintainer
#6 lore raw
Quoted 14 lines · Christoph Hellwig
Quoted 2 lines · Arnd Bergmann

Actually, please don't use the asm-generic __put_user version based on copy_to_user, we probably have killed it off long ago.

Yes, they are horrible.

Quoted 6 lines

We might want to come up with a new version of asm-generic/uaccess.h that actually makes it easier to have a sane per-architecture implementation of the low-level accessors without set_fs().

I've added Christoph to Cc here, he probably has some ideas on where we should be heading.

Quoted 6 lines

I think asm-generic/uaccess.h pretty much only makes sense for nommu. For that case we can just kill the __{get,put}_user_fn indirection. I actually have work for that in an old branch.

Trying to use any of asm-generic/uaccess.h for MMU based kernel is just asking for trouble.

I still think the arch should base on asm-generic/uaccess.h, not abandon it.

Thx for reviewing.

Quoted 10 lines
Quoted 5 lines

One noteworthy aspect is that almost nothing users the low-level __get_user()/__put_user() helpers any more outside of architecture specific code, so we may not need to have separate versions for much longer.

Al has been trying to kill them off entirely for a while, and I hope he'll eventually succeed. That being said the difference should be that the __ versions just skip the access_ok, so having both is fairly trivial to implement.

Signature · 4 lines
Best Regards
 Guo Ren

ML: https://lore.kernel.org/linux-csky/
maintainer
#7 lore raw
In reply to Christoph Hellwig
Quoted 8 lines · Christoph Hellwig
Quoted 6 lines · Arnd Bergmann

We might want to come up with a new version of asm-generic/uaccess.h that actually makes it easier to have a sane per-architecture implementation of the low-level accessors without set_fs().

I've added Christoph to Cc here, he probably has some ideas on where we should be heading.

Quoted 6 lines

I think asm-generic/uaccess.h pretty much only makes sense for nommu. For that case we can just kill the __{get,put}_user_fn indirection. I actually have work for that in an old branch.

Trying to use any of asm-generic/uaccess.h for MMU based kernel is just asking for trouble.

The one thing I'd like to see is a generic implementation of the outer bit that implements handling the variable-length arguments, there are so many ways that people have gotten that wrong in the past, and it would be nice if architectures only had to implement a set of fixed-size accessors that contain the architecture specific inline asm.

There is now a new version for x86 that based on asm-goto with output, which should in theory provide a better implementation for any architecture when using gcc-11/clang-11 or higher.

Quoted 9 lines
Quoted 4 lines

One noteworthy aspect is that almost nothing users the low-level __get_user()/__put_user() helpers any more outside of architecture specific code, so we may not need to have separate versions for much longer.

Al has been trying to kill them off entirely for a while, and I hope he'll eventually succeed. That being said the difference should be that the __ versions just skip the access_ok, so having both is fairly trivial to implement.

That is the difference in the interface, but in some of architectures there is another difference in that the __ version is completely inlined while the normal version calls an external function. I could never quite figure out the reason for this difference.

Arnd

author maintainer
#8 lore raw
In reply to Arnd Bergmann
Quoted 62 lines · Arnd Bergmann
Quoted 51 lines · Guo Ren
Quoted 14 lines · Guenter Roeck
Quoted 11 lines · On Wed, Apr 21, 2021 at 08:54:15AM +0000, [email protected] wrote:

From: Guo Ren <[email protected]>

Using asm-generic/uaccess.h to prevent duplicated code:
- Add user_addr_max which mentioned in generic uaccess.h
- Remove custom definitions of KERNEL/USER_DS, get/set_fs, uaccess_kerenl
- Using generic extable.h instead of custom definitions in uaccess.h

Cc Arnd Bergmann <[email protected]>
Quoted 9 lines

Building csky:tinyconfig ... failed
--------------
Error log:
csky-linux-ld: fs/readdir.o: in function `__put_user_fn':
readdir.c:(.text+0x7c): undefined reference to `__put_user_bad'
csky-linux-ld: fs/readdir.o: in function `$d':
readdir.c:(.text+0x1bc): undefined reference to `__put_user_bad' make[1]: *** [Makefile:1277: vmlinux] Error 1
make: *** [Makefile:222: __sub-make] Error 2

It's a bug, I can't put __put_user_bad in __put_user_fn, and __put_user has done that:

/*
* These are the main single-value transfer routines. They automatically
* use the right size if we just have the right pointer type.
* This version just falls back to copy_{from,to}_user, which should
* provide a fast-path for small values.
*/
#define __put_user(x, ptr) \

({                                                              \
        __typeof__(*(ptr)) __x = (x);                           \
        int __pu_err = -EFAULT;                                 \
        __chk_user_ptr(ptr);                                    \
        switch (sizeof (*(ptr))) {                              \
        case 1:                                                 \
        case 2:                                                 \
        case 4:                                                 \
        case 8:                                                 \
                __pu_err = __put_user_fn(sizeof (*(ptr)),       \
                                         ptr, &__x);            \
                break;                                          \
        default:                                                \
                __put_user_bad();                               \
                break;                                          \
         }                                                      \
        __pu_err;                                               \
Quoted 1 line

})

Actually, please don't use the asm-generic __put_user version based on copy_to_user, we probably have killed it off long ago.

We might want to come up with a new version of asm-generic/uaccess.h that actually makes it easier to have a sane per-architecture implementation of the low-level accessors without set_fs().

Quoted 7 lines

I've added Christoph to Cc here, he probably has some ideas on where we should be heading.

One noteworthy aspect is that almost nothing users the low-level __get_user()/__put_user() helpers any more outside of architecture specific code, so we may not need to have separate versions for much longer.

Thx Arnd, here is my implementation:

#define __put_user_asm_64(x, ptr, err)                  \
do {                                                    \
        int tmp;                                        \
        int errcode;                                    \
                                                        \
        __asm__ __volatile__(                           \
        "     ldw     %3, (%1, 0)     \n"               \
        "1:   stw     %3, (%2, 0)     \n"               \
        "     ldw     %3, (%1, 4)     \n"               \
        "2:   stw     %3, (%2, 4)     \n"               \
        "     br      4f              \n"               \
        "3:   mov     %0, %4          \n"               \
        "     br      4f              \n"               \
        ".section __ex_table, \"a\"   \n"               \
        ".align   2                   \n"               \
        ".long    1b, 3b              \n"               \
        ".long    2b, 3b              \n"               \
        ".previous                    \n"               \
        "4:                           \n"               \
        : "=r"(err), "=r"(x), "=r"(ptr),                \
          "=r"(tmp), "=r"(errcode)                      \
        : "0"(err), "1"(x), "2"(ptr), "3"(0),           \
          "4"(-EFAULT)                                  \
        : "memory");                                    \
} while (0)

static inline int __put_user_fn(size_t size, void __user *ptr, void *x)

{
        int retval = 0;
        u32 tmp;
...
        case 8:
                __put_user_asm_64(x, (u64 *)ptr, retval);
                break;
        }

        return retval;
}

#define __put_user_fn __put_user_fn

#define __get_user_asm_64(x, ptr, err)                  \
do {                                                    \
        int tmp;                                        \
        int errcode;                                    \
                                                        \
        __asm__ __volatile__(                           \
        "1:   ldw     %3, (%2, 0)     \n"               \
        "     stw     %3, (%1, 0)     \n"               \
        "2:   ldw     %3, (%2, 4)     \n"               \
        "     stw     %3, (%1, 4)     \n"               \
        "     br      4f              \n"               \
        "3:   mov     %0, %4          \n"               \
        "     br      4f              \n"               \
        ".section __ex_table, \"a\"   \n"               \
        ".align   2                   \n"               \
        ".long    1b, 3b              \n"               \
        ".long    2b, 3b              \n"               \
        ".previous                    \n"               \
        "4:                           \n"               \
        : "=r"(err), "=r"(x), "=r"(ptr),                \
          "=r"(tmp), "=r"(errcode)                      \
        : "0"(err), "1"(x), "2"(ptr), "3"(0),           \
          "4"(-EFAULT)                                  \
        : "memory");                                    \
} while (0)

static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)

{
        int retval;
        u32 tmp;

...

        case 8:
                __get_user_asm_64(x, ptr, retval);
                break;
        }

        return retval;
}

#define __get_user_fn __get_user_fn

Signature · 4 lines
Best Regards
 Guo Ren

ML: https://lore.kernel.org/linux-csky/