hc
2024-11-01 2f529f9b558ca1c1bd74be7437a84e4711743404
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/* SPDX-License-Identifier: GPL-2.0-only */
 
#ifndef __ASM_UACCESS_ASM_H__
#define __ASM_UACCESS_ASM_H__
 
#include <asm/asm-offsets.h>
#include <asm/domain.h>
#include <asm/memory.h>
#include <asm/thread_info.h>
 
   .macro    csdb
#ifdef CONFIG_THUMB2_KERNEL
   .inst.w    0xf3af8014
#else
   .inst    0xe320f014
#endif
   .endm
 
   .macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req
#ifndef CONFIG_CPU_USE_DOMAINS
   adds    \tmp, \addr, #\size - 1
   sbcscc    \tmp, \tmp, \limit
   bcs    \bad
#ifdef CONFIG_CPU_SPECTRE
   movcs    \addr, #0
   csdb
#endif
#endif
   .endm
 
   .macro uaccess_mask_range_ptr, addr:req, size:req, limit:req, tmp:req
#ifdef CONFIG_CPU_SPECTRE
   sub    \tmp, \limit, #1
   subs    \tmp, \tmp, \addr    @ tmp = limit - 1 - addr
   addhs    \tmp, \tmp, #1        @ if (tmp >= 0) {
   subshs    \tmp, \tmp, \size    @ tmp = limit - (addr + size) }
   movlo    \addr, #0        @ if (tmp < 0) addr = NULL
   csdb
#endif
   .endm
 
   .macro    uaccess_disable, tmp, isb=1
#ifdef CONFIG_CPU_SW_DOMAIN_PAN
   /*
    * Whenever we re-enter userspace, the domains should always be
    * set appropriately.
    */
   mov    \tmp, #DACR_UACCESS_DISABLE
   mcr    p15, 0, \tmp, c3, c0, 0        @ Set domain register
   .if    \isb
   instr_sync
   .endif
#endif
   .endm
 
   .macro    uaccess_enable, tmp, isb=1
#ifdef CONFIG_CPU_SW_DOMAIN_PAN
   /*
    * Whenever we re-enter userspace, the domains should always be
    * set appropriately.
    */
   mov    \tmp, #DACR_UACCESS_ENABLE
   mcr    p15, 0, \tmp, c3, c0, 0
   .if    \isb
   instr_sync
   .endif
#endif
   .endm
 
#if defined(CONFIG_CPU_SW_DOMAIN_PAN) || defined(CONFIG_CPU_USE_DOMAINS)
#define DACR(x...)    x
#else
#define DACR(x...)
#endif
 
   /*
    * Save the address limit on entry to a privileged exception.
    *
    * If we are using the DACR for kernel access by the user accessors
    * (CONFIG_CPU_USE_DOMAINS=y), always reset the DACR kernel domain
    * back to client mode, whether or not \disable is set.
    *
    * If we are using SW PAN, set the DACR user domain to no access
    * if \disable is set.
    */
   .macro    uaccess_entry, tsk, tmp0, tmp1, tmp2, disable
   ldr    \tmp1, [\tsk, #TI_ADDR_LIMIT]
   mov    \tmp2, #TASK_SIZE
   str    \tmp2, [\tsk, #TI_ADDR_LIMIT]
 DACR(    mrc    p15, 0, \tmp0, c3, c0, 0)
 DACR(    str    \tmp0, [sp, #SVC_DACR])
   str    \tmp1, [sp, #SVC_ADDR_LIMIT]
   .if \disable && IS_ENABLED(CONFIG_CPU_SW_DOMAIN_PAN)
   /* kernel=client, user=no access */
   mov    \tmp2, #DACR_UACCESS_DISABLE
   mcr    p15, 0, \tmp2, c3, c0, 0
   instr_sync
   .elseif IS_ENABLED(CONFIG_CPU_USE_DOMAINS)
   /* kernel=client */
   bic    \tmp2, \tmp0, #domain_mask(DOMAIN_KERNEL)
   orr    \tmp2, \tmp2, #domain_val(DOMAIN_KERNEL, DOMAIN_CLIENT)
   mcr    p15, 0, \tmp2, c3, c0, 0
   instr_sync
   .endif
   .endm
 
   /* Restore the user access state previously saved by uaccess_entry */
   .macro    uaccess_exit, tsk, tmp0, tmp1
   ldr    \tmp1, [sp, #SVC_ADDR_LIMIT]
 DACR(    ldr    \tmp0, [sp, #SVC_DACR])
   str    \tmp1, [\tsk, #TI_ADDR_LIMIT]
 DACR(    mcr    p15, 0, \tmp0, c3, c0, 0)
   .endm
 
#undef DACR
 
#endif /* __ASM_UACCESS_ASM_H__ */