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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
|
/*
* Copyright (c) 2006-2025, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-01-30 lizhirui first version
* 2023-10-12 Shell Add permission control API
* 2025-04-26 GuEe-GUI Follow the specific and vendor
*/
#ifndef __MMU_H__
#define __MMU_H__
#include <page_def.h>
#include <asm-generic.h>
#ifndef __ASSEMBLY__
#include <mm_aspace.h>
/* Normal memory wra mapping type */
#define NORMAL_MEM 0
/* Normal nocache memory mapping type */
#define NORMAL_NOCACHE_MEM 1
/* Device mapping type */
#define DEVICE_MEM 2
struct mem_desc
{
unsigned long vaddr_start;
unsigned long vaddr_end;
unsigned long paddr_start;
unsigned long attr;
struct rt_varea varea;
};
#ifdef __HAS_MMU_VENDOR__
#include <mmu_vendor.h>
#endif
#endif /* !__ASSEMBLY__ */
#define RT_HW_MMU_PROT_READ 1
#define RT_HW_MMU_PROT_WRITE 2
#define RT_HW_MMU_PROT_EXECUTE 4
#define RT_HW_MMU_PROT_KERNEL 8
#define RT_HW_MMU_PROT_USER 16
#define RT_HW_MMU_PROT_CACHE 32
/* Page table entry (PTE) fields */
#define PTE_V BIT(0) /* Valid */
#define PTE_R BIT(1) /* Read */
#define PTE_W BIT(2) /* Write */
#define PTE_X BIT(3) /* Execute */
#define PTE_U BIT(4) /* User */
#define PTE_G BIT(5) /* Global */
#define PTE_A BIT(6) /* Accessed */
#define PTE_D BIT(7) /* Dirty */
#define PTE_SOFT GENMASK(9, 8) /* Reserved for Software */
#define PTE_BITS 10
#if __riscv_xlen == 32
#define PTE_PPN_MASK GENMASK(31, 10)
#else
#define PTE_PPN_MASK GENMASK(53, 10)
#endif
#define PTE_ATTR_NONE _UL(0)
#define PTE_ATTR_RW (PTE_R | PTE_W)
#define PTE_ATTR_RWX (PTE_ATTR_RW | PTE_X)
#define PTE_ATTR_KERNEL (PTE_V | PTE_ATTR_RWX | PTE_A | PTE_D)
#define PTE_ATTR_USER (PTE_ATTR_KERNEL | PTE_U)
#if !defined(__HAS_MMU_VENDOR__) && __riscv_xlen != 32
#define SVPBMT_SHIFT 61 /* ISA SVPBMT */
#define PTE_VENDOR_PMA (0x0ULL << SVPBMT_SHIFT)
#define PTE_VENDOR_NOCACHE (0x1ULL << SVPBMT_SHIFT)
#define PTE_VENDOR_IO (0x2ULL << SVPBMT_SHIFT)
#define PTE_VENDOR_MTMASK (0x3ULL << SVPBMT_SHIFT)
#endif /* !__HAS_MMU_VENDOR__ && __riscv_xlen != 32 */
#ifndef PTE_VENDOR_PMA
#define PTE_VENDOR_PMA PTE_ATTR_NONE
#endif
#ifndef PTE_VENDOR_NOCACHE
#define PTE_VENDOR_NOCACHE PTE_ATTR_NONE
#endif
#ifndef PTE_VENDOR_IO
#define PTE_VENDOR_IO PTE_ATTR_NONE
#endif
#ifndef PTE_VENDOR_MTMASK
#define PTE_VENDOR_MTMASK PTE_ATTR_NONE
#endif
#ifndef MMU_VENDOR_MAP_K_ROCB
#define MMU_VENDOR_MAP_K_ROCB ((PTE_ATTR_KERNEL & ~PTE_W) | PTE_VENDOR_PMA)
#endif
#ifndef MMU_VENDOR_MAP_K_RO
#define MMU_VENDOR_MAP_K_RO ((PTE_ATTR_KERNEL & ~PTE_W) | PTE_VENDOR_NOCACHE)
#endif
#ifndef MMU_VENDOR_MAP_K_RWCB
#define MMU_VENDOR_MAP_K_RWCB (PTE_ATTR_KERNEL | PTE_VENDOR_PMA)
#endif
#ifndef MMU_VENDOR_MAP_K_RW
#define MMU_VENDOR_MAP_K_RW (PTE_ATTR_KERNEL | PTE_VENDOR_NOCACHE)
#endif
#ifndef MMU_VENDOR_MAP_K_DEVICE
#define MMU_VENDOR_MAP_K_DEVICE ((PTE_ATTR_KERNEL & ~PTE_X) | PTE_VENDOR_IO)
#endif
#ifndef MMU_VENDOR_MAP_U_ROCB
#define MMU_VENDOR_MAP_U_ROCB ((PTE_ATTR_USER & ~PTE_W) | PTE_VENDOR_PMA)
#endif
#ifndef MMU_VENDOR_MAP_U_RO
#define MMU_VENDOR_MAP_U_RO ((PTE_ATTR_USER & ~PTE_W) | PTE_VENDOR_NOCACHE)
#endif
#ifndef MMU_VENDOR_MAP_U_RWCB
#define MMU_VENDOR_MAP_U_RWCB (PTE_ATTR_USER | PTE_VENDOR_PMA)
#endif
#ifndef MMU_VENDOR_MAP_U_RW
#define MMU_VENDOR_MAP_U_RW (PTE_ATTR_USER | PTE_VENDOR_NOCACHE)
#endif
#ifndef MMU_VENDOR_MAP_U_DEVICE
#define MMU_VENDOR_MAP_U_DEVICE ((PTE_ATTR_USER & ~PTE_X) | PTE_VENDOR_IO)
#endif
#ifndef MMU_VENDOR_MAP_EARLY
#define MMU_VENDOR_MAP_EARLY (PTE_RWX | PTE_G | PTE_V)
#endif
#define MMU_MAP_K_ROCB MMU_VENDOR_MAP_K_ROCB
#define MMU_MAP_K_RO MMU_VENDOR_MAP_K_RO
#define MMU_MAP_K_RWCB MMU_VENDOR_MAP_K_RWCB
#define MMU_MAP_K_RW MMU_VENDOR_MAP_K_RW
#define MMU_MAP_K_DEVICE MMU_VENDOR_MAP_K_DEVICE
#define MMU_MAP_U_ROCB MMU_VENDOR_MAP_U_ROCB
#define MMU_MAP_U_RO MMU_VENDOR_MAP_U_RO
#define MMU_MAP_U_RWCB MMU_VENDOR_MAP_U_RWCB
#define MMU_MAP_U_RW MMU_VENDOR_MAP_U_RW
#define MMU_MAP_U_DEVICE MMU_VENDOR_MAP_U_DEVICE
#define MMU_MAP_ERROR_VANOTALIGN -1
#define MMU_MAP_ERROR_PANOTALIGN -2
#define MMU_MAP_ERROR_NOPAGE -3
#define MMU_MAP_ERROR_CONFLICT -4
#ifdef RT_PAGE_MPR_SIZE_DYNAMIC
#define ARCH_VADDR_WIDTH rt_hw_arch_vaddr_width
#elif __riscv_xlen == 32
#define ARCH_VADDR_WIDTH 32
#elif defined(ARCH_MM_MMU_SV48)
#define ARCH_VADDR_WIDTH 48
#elif defined(ARCH_MM_MMU_SV57)
#define ARCH_VADDR_WIDTH 57
#else
#define ARCH_VADDR_WIDTH 39
#endif
#define ARCH_ADDRESS_WIDTH_BITS __riscv_xlen
#define ARCH_MAP_FAILED _AT(void *, _ULL(-1))
#define ARCH_EARLY_MAP_SIZE 0x80000000
#ifndef __ASSEMBLY__
struct rt_aspace;
extern rt_uint8_t rt_hw_arch_vaddr_width;
void *rt_hw_mmu_tbl_get(void);
void rt_hw_mmu_tbl_set(rt_ubase_t tbl);
int rt_hw_mmu_map_init(rt_aspace_t aspace, void *v_address, rt_ubase_t size,
rt_ubase_t *vtable, rt_ubase_t pv_off);
void rt_hw_mmu_setup(rt_aspace_t aspace, struct mem_desc *mdesc, int desc_nr);
void *rt_hw_mmu_map(rt_aspace_t aspace, void *v_addr, void *p_addr, size_t size,
size_t attr);
void rt_hw_mmu_unmap(rt_aspace_t aspace, void *v_addr, size_t size);
void rt_hw_aspace_switch(rt_aspace_t aspace);
void *rt_hw_mmu_v2p(rt_aspace_t aspace, void *vaddr);
int rt_hw_mmu_control(struct rt_aspace *aspace, void *vaddr, size_t size,
enum rt_mmu_cntl cmd);
void *rt_hw_mmu_pgtbl_create(void);
void rt_hw_mmu_pgtbl_delete(void *pgtbl);
#ifndef MMU_VENDOR_ATTR_RM_PERM_IMPL
/**
* @brief Remove permission from attribution
*
* @param attr architecture specified mmu attribution
* @param prot protect that will be removed
* @return size_t returned attribution
*/
rt_inline size_t rt_hw_mmu_attr_rm_perm(size_t attr, rt_base_t prot)
{
switch (prot)
{
/* remove write permission for user */
case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_USER:
attr &= ~PTE_W;
break;
/* remove write permission for kernel */
case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_KERNEL:
attr &= ~PTE_W;
break;
default:
RT_ASSERT(0);
}
return attr;
}
#endif /* MMU_VENDOR_ATTR_RM_PERM_IMPL */
#ifndef MMU_VENDOR_ATTR_ADD_PERM_IMPL
/**
* @brief Add permission from attribution
*
* @param attr architecture specified mmu attribution
* @param prot protect that will be added
* @return size_t returned attribution
*/
rt_inline size_t rt_hw_mmu_attr_add_perm(size_t attr, rt_base_t prot)
{
switch (prot)
{
/* add write permission for user */
case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_USER:
attr |= (PTE_R | PTE_W | PTE_U);
break;
default:
RT_ASSERT(0);
}
return attr;
}
#endif /* MMU_VENDOR_ATTR_ADD_PERM_IMPL */
#ifndef MMU_VENDOR_ATTR_TEST_PERM_IMPL
/**
* @brief Test permission from attribution
*
* @param attr architecture specified mmu attribution
* @param prot protect that will be test
* @return rt_bool_t RT_TRUE if the prot is allowed, otherwise RT_FALSE
*/
rt_inline rt_bool_t rt_hw_mmu_attr_test_perm(size_t attr, rt_base_t prot)
{
rt_bool_t rc = 0;
switch (prot & ~RT_HW_MMU_PROT_USER)
{
/* test write permission for user */
case RT_HW_MMU_PROT_WRITE:
rc = ((attr & PTE_W) && (attr & PTE_R));
break;
case RT_HW_MMU_PROT_READ:
rc = !!(attr & PTE_R);
break;
case RT_HW_MMU_PROT_EXECUTE:
rc = !!(attr & PTE_X);
break;
default:
RT_ASSERT(0);
}
if (rc && (prot & RT_HW_MMU_PROT_USER))
{
rc = !!(attr & PTE_U);
}
return rc;
}
#endif /* MMU_VENDOR_ATTR_TEST_PERM_IMPL */
#endif /* !__ASSEMBLY__ */
#endif /* __MMU_H__ */
|