1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2023 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /**
33 * @defgroup los_vm_map vm mapping management
34 * @ingroup kernel
35 */
36
37 #ifndef __LOS_VM_MAP_H__
38 #define __LOS_VM_MAP_H__
39
40 #include "los_typedef.h"
41 #include "los_arch_mmu.h"
42 #include "los_mux.h"
43 #include "los_rbtree.h"
44 #include "los_vm_syscall.h"
45 #include "los_vm_zone.h"
46 #include "los_vm_common.h"
47
48 struct Vnode;
49
50 #ifdef __cplusplus
51 #if __cplusplus
52 extern "C" {
53 #endif /* __cplusplus */
54 #endif /* __cplusplus */
55
56 /* If the kernel malloc size is less than 16k, use heap, otherwise use physical pages */
57 #define KMALLOC_LARGE_SIZE (PAGE_SIZE << 2)
58
59 typedef struct VmMapRange {
60 VADDR_T base; /**< vm region base addr */
61 UINT32 size; /**< vm region size */
62 } LosVmMapRange;
63
64 struct VmMapRegion;
65 typedef struct VmMapRegion LosVmMapRegion;
66 struct VmFileOps;
67 typedef struct VmFileOps LosVmFileOps;
68 struct VmSpace;
69 typedef struct VmSpace LosVmSpace;
70
71 typedef struct VmFault {
72 UINT32 flags; /* FAULT_FLAG_xxx flags */
73 unsigned long pgoff; /* Logical page offset based on region */
74 VADDR_T vaddr; /* Faulting virtual address */
75 VADDR_T *pageKVaddr; /* KVaddr of pagefault's vm page's paddr */
76 } LosVmPgFault;
77
78 struct VmFileOps {
79 void (*open)(struct VmMapRegion *region);
80 void (*close)(struct VmMapRegion *region);
81 int (*fault)(struct VmMapRegion *region, LosVmPgFault *pageFault);
82 void (*remove)(struct VmMapRegion *region, LosArchMmu *archMmu, VM_OFFSET_T offset);
83 };
84
85 struct VmMapRegion {
86 LosRbNode rbNode; /**< region red-black tree node */
87 LosVmSpace *space;
88 LOS_DL_LIST node; /**< region dl list */
89 LosVmMapRange range; /**< region address range */
90 VM_OFFSET_T pgOff; /**< region page offset to file */
91 UINT32 regionFlags; /**< region flags: cow, user_wired */
92 UINT32 shmid; /**< shmid about shared region */
93 UINT8 forkFlags; /**< vm space fork flags: COPY, ZERO, */
94 UINT8 regionType; /**< vm region type: ANON, FILE, DEV */
95 union {
96 struct VmRegionFile {
97 int f_oflags;
98 struct Vnode *vnode;
99 const LosVmFileOps *vmFOps;
100 } rf;
101 struct VmRegionAnon {
102 LOS_DL_LIST node; /**< region LosVmPage list */
103 } ra;
104 struct VmRegionDev {
105 LOS_DL_LIST node; /**< region LosVmPage list */
106 const LosVmFileOps *vmFOps;
107 } rd;
108 } unTypeData;
109 };
110
111 typedef struct VmSpace {
112 LOS_DL_LIST node; /**< vm space dl list */
113 LosRbTree regionRbTree; /**< region red-black tree root */
114 LosMux regionMux; /**< region red-black tree mutex lock */
115 VADDR_T base; /**< vm space base addr */
116 UINT32 size; /**< vm space size */
117 VADDR_T heapBase; /**< vm space heap base address */
118 VADDR_T heapNow; /**< vm space heap base now */
119 LosVmMapRegion *heap; /**< heap region */
120 VADDR_T mapBase; /**< vm space mapping area base */
121 UINT32 mapSize; /**< vm space mapping area size */
122 LosArchMmu archMmu; /**< vm mapping physical memory */
123 #ifdef LOSCFG_DRIVERS_TZDRIVER
124 VADDR_T codeStart; /**< user process code area start */
125 VADDR_T codeEnd; /**< user process code area end */
126 #endif
127 } LosVmSpace;
128
129 #define VM_MAP_REGION_TYPE_NONE (0x0)
130 #define VM_MAP_REGION_TYPE_ANON (0x1)
131 #define VM_MAP_REGION_TYPE_FILE (0x2)
132 #define VM_MAP_REGION_TYPE_DEV (0x4)
133 #define VM_MAP_REGION_TYPE_MASK (0x7)
134
135 /* the high 8 bits(24~31) should reserved, shm will use it */
136 #define VM_MAP_REGION_FLAG_CACHED (0<<0)
137 #define VM_MAP_REGION_FLAG_UNCACHED (1<<0)
138 #define VM_MAP_REGION_FLAG_UNCACHED_DEVICE (2<<0) /* only exists on some arches, otherwise UNCACHED */
139 #define VM_MAP_REGION_FLAG_STRONGLY_ORDERED (3<<0) /* only exists on some arches, otherwise UNCACHED */
140 #define VM_MAP_REGION_FLAG_CACHE_MASK (3<<0)
141 #define VM_MAP_REGION_FLAG_PERM_USER (1<<2)
142 #define VM_MAP_REGION_FLAG_PERM_READ (1<<3)
143 #define VM_MAP_REGION_FLAG_PERM_WRITE (1<<4)
144 #define VM_MAP_REGION_FLAG_PERM_EXECUTE (1<<5)
145 #define VM_MAP_REGION_FLAG_PROT_MASK (0xF<<2)
146 #define VM_MAP_REGION_FLAG_NS (1<<6) /* NON-SECURE */
147 #define VM_MAP_REGION_FLAG_SHARED (1<<7)
148 #define VM_MAP_REGION_FLAG_PRIVATE (1<<8)
149 #define VM_MAP_REGION_FLAG_FLAG_MASK (3<<7)
150 #define VM_MAP_REGION_FLAG_STACK (1<<9)
151 #define VM_MAP_REGION_FLAG_HEAP (1<<10)
152 #define VM_MAP_REGION_FLAG_DATA (1<<11)
153 #define VM_MAP_REGION_FLAG_TEXT (1<<12)
154 #define VM_MAP_REGION_FLAG_BSS (1<<13)
155 #define VM_MAP_REGION_FLAG_VDSO (1<<14)
156 #define VM_MAP_REGION_FLAG_MMAP (1<<15)
157 #define VM_MAP_REGION_FLAG_SHM (1<<16)
158 #define VM_MAP_REGION_FLAG_FIXED (1<<17)
159 #define VM_MAP_REGION_FLAG_FIXED_NOREPLACE (1<<18)
160 #define VM_MAP_REGION_FLAG_INVALID (1<<19) /* indicates that flags are not specified */
161
OsCvtProtFlagsToRegionFlags(unsigned long prot,unsigned long flags)162 STATIC INLINE UINT32 OsCvtProtFlagsToRegionFlags(unsigned long prot, unsigned long flags)
163 {
164 UINT32 regionFlags = 0;
165
166 regionFlags |= VM_MAP_REGION_FLAG_PERM_USER;
167 regionFlags |= (prot & PROT_READ) ? VM_MAP_REGION_FLAG_PERM_READ : 0;
168 regionFlags |= (prot & PROT_WRITE) ? (VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE) : 0;
169 regionFlags |= (prot & PROT_EXEC) ? (VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_EXECUTE) : 0;
170 regionFlags |= (flags & MAP_SHARED) ? VM_MAP_REGION_FLAG_SHARED : 0;
171 regionFlags |= (flags & MAP_PRIVATE) ? VM_MAP_REGION_FLAG_PRIVATE : 0;
172 regionFlags |= (flags & MAP_FIXED) ? VM_MAP_REGION_FLAG_FIXED : 0;
173 regionFlags |= (flags & MAP_FIXED_NOREPLACE) ? VM_MAP_REGION_FLAG_FIXED_NOREPLACE : 0;
174
175 return regionFlags;
176 }
177
LOS_IsKernelAddress(VADDR_T vaddr)178 STATIC INLINE BOOL LOS_IsKernelAddress(VADDR_T vaddr)
179 {
180 return ((vaddr >= (VADDR_T)KERNEL_ASPACE_BASE) &&
181 (vaddr <= ((VADDR_T)KERNEL_ASPACE_BASE + ((VADDR_T)KERNEL_ASPACE_SIZE - 1))));
182 }
183
LOS_IsKernelAddressRange(VADDR_T vaddr,size_t len)184 STATIC INLINE BOOL LOS_IsKernelAddressRange(VADDR_T vaddr, size_t len)
185 {
186 return (vaddr + len > vaddr) && LOS_IsKernelAddress(vaddr) && (LOS_IsKernelAddress(vaddr + len - 1));
187 }
188
LOS_RegionEndAddr(LosVmMapRegion * region)189 STATIC INLINE VADDR_T LOS_RegionEndAddr(LosVmMapRegion *region)
190 {
191 return (region->range.base + region->range.size - 1);
192 }
193
LOS_RegionSize(VADDR_T start,VADDR_T end)194 STATIC INLINE size_t LOS_RegionSize(VADDR_T start, VADDR_T end)
195 {
196 return (end - start + 1);
197 }
198
LOS_IsRegionTypeFile(LosVmMapRegion * region)199 STATIC INLINE BOOL LOS_IsRegionTypeFile(LosVmMapRegion* region)
200 {
201 return region->regionType == VM_MAP_REGION_TYPE_FILE;
202 }
203
LOS_IsRegionPermUserReadOnly(LosVmMapRegion * region)204 STATIC INLINE BOOL LOS_IsRegionPermUserReadOnly(LosVmMapRegion* region)
205 {
206 return ((region->regionFlags & VM_MAP_REGION_FLAG_PROT_MASK) ==
207 (VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ));
208 }
209
LOS_IsRegionFlagPrivateOnly(LosVmMapRegion * region)210 STATIC INLINE BOOL LOS_IsRegionFlagPrivateOnly(LosVmMapRegion* region)
211 {
212 return ((region->regionFlags & VM_MAP_REGION_FLAG_FLAG_MASK) == VM_MAP_REGION_FLAG_PRIVATE);
213 }
214
LOS_SetRegionTypeFile(LosVmMapRegion * region)215 STATIC INLINE VOID LOS_SetRegionTypeFile(LosVmMapRegion* region)
216 {
217 region->regionType = VM_MAP_REGION_TYPE_FILE;
218 }
219
LOS_IsRegionTypeDev(LosVmMapRegion * region)220 STATIC INLINE BOOL LOS_IsRegionTypeDev(LosVmMapRegion* region)
221 {
222 return region->regionType == VM_MAP_REGION_TYPE_DEV;
223 }
224
LOS_SetRegionTypeDev(LosVmMapRegion * region)225 STATIC INLINE VOID LOS_SetRegionTypeDev(LosVmMapRegion* region)
226 {
227 region->regionType = VM_MAP_REGION_TYPE_DEV;
228 }
229
LOS_IsRegionTypeAnon(LosVmMapRegion * region)230 STATIC INLINE BOOL LOS_IsRegionTypeAnon(LosVmMapRegion* region)
231 {
232 return region->regionType == VM_MAP_REGION_TYPE_ANON;
233 }
234
LOS_SetRegionTypeAnon(LosVmMapRegion * region)235 STATIC INLINE VOID LOS_SetRegionTypeAnon(LosVmMapRegion* region)
236 {
237 region->regionType = VM_MAP_REGION_TYPE_ANON;
238 }
239
LOS_IsUserAddress(VADDR_T vaddr)240 STATIC INLINE BOOL LOS_IsUserAddress(VADDR_T vaddr)
241 {
242 return ((vaddr >= USER_ASPACE_BASE) &&
243 (vaddr <= (USER_ASPACE_BASE + (USER_ASPACE_SIZE - 1))));
244 }
245
LOS_IsUserAddressRange(VADDR_T vaddr,size_t len)246 STATIC INLINE BOOL LOS_IsUserAddressRange(VADDR_T vaddr, size_t len)
247 {
248 return (vaddr + len > vaddr) && LOS_IsUserAddress(vaddr) && (LOS_IsUserAddress(vaddr + len - 1));
249 }
250
LOS_IsVmallocAddress(VADDR_T vaddr)251 STATIC INLINE BOOL LOS_IsVmallocAddress(VADDR_T vaddr)
252 {
253 return ((vaddr >= VMALLOC_START) &&
254 (vaddr <= (VMALLOC_START + (VMALLOC_SIZE - 1))));
255 }
256
OsIsVmRegionEmpty(LosVmSpace * vmSpace)257 STATIC INLINE BOOL OsIsVmRegionEmpty(LosVmSpace *vmSpace)
258 {
259 if (vmSpace->regionRbTree.ulNodes == 0) {
260 return TRUE;
261 }
262 return FALSE;
263 }
264
265 LosVmSpace *LOS_GetKVmSpace(VOID);
266 LOS_DL_LIST *LOS_GetVmSpaceList(VOID);
267 LosVmSpace *LOS_GetVmallocSpace(VOID);
268 VOID OsInitMappingStartUp(VOID);
269 VOID OsKSpaceInit(VOID);
270 BOOL LOS_IsRangeInSpace(const LosVmSpace *space, VADDR_T vaddr, size_t size);
271 STATUS_T LOS_VmSpaceReserve(LosVmSpace *space, size_t size, VADDR_T vaddr);
272 INT32 OsUserHeapFree(LosVmSpace *vmSpace, VADDR_T addr, size_t len);
273 VADDR_T OsAllocRange(LosVmSpace *vmSpace, size_t len);
274 VADDR_T OsAllocSpecificRange(LosVmSpace *vmSpace, VADDR_T vaddr, size_t len, UINT32 regionFlags);
275 LosVmMapRegion *OsCreateRegion(VADDR_T vaddr, size_t len, UINT32 regionFlags, unsigned long offset);
276 BOOL OsInsertRegion(LosRbTree *regionRbTree, LosVmMapRegion *region);
277 LosVmSpace *LOS_SpaceGet(VADDR_T vaddr);
278 LosVmSpace *LOS_CurrSpaceGet(VOID);
279 BOOL LOS_IsRegionFileValid(LosVmMapRegion *region);
280 LosVmMapRegion *LOS_RegionRangeFind(LosVmSpace *vmSpace, VADDR_T addr, size_t len);
281 LosVmMapRegion *LOS_RegionFind(LosVmSpace *vmSpace, VADDR_T addr);
282 PADDR_T LOS_PaddrQuery(VOID *vaddr);
283 LosVmMapRegion *LOS_RegionAlloc(LosVmSpace *vmSpace, VADDR_T vaddr, size_t len, UINT32 regionFlags, VM_OFFSET_T pgoff);
284 STATUS_T OsRegionsRemove(LosVmSpace *space, VADDR_T vaddr, size_t size);
285 STATUS_T OsVmRegionAdjust(LosVmSpace *space, VADDR_T vaddr, size_t size);
286 LosVmMapRegion *OsVmRegionDup(LosVmSpace *space, LosVmMapRegion *oldRegion, VADDR_T vaddr, size_t size);
287 STATUS_T OsIsRegionCanExpand(LosVmSpace *space, LosVmMapRegion *region, size_t size);
288 STATUS_T LOS_RegionFree(LosVmSpace *space, LosVmMapRegion *region);
289 STATUS_T LOS_VmSpaceFree(LosVmSpace *space);
290 STATUS_T LOS_VaddrToPaddrMmap(LosVmSpace *space, VADDR_T vaddr, PADDR_T paddr, size_t len, UINT32 flags);
291 BOOL OsUserVmSpaceInit(LosVmSpace *vmSpace, VADDR_T *virtTtb);
292 LosVmSpace *OsCreateUserVmSpace(VOID);
293 STATUS_T LOS_VmSpaceClone(UINT32 cloneFlags, LosVmSpace *oldVmSpace, LosVmSpace *newVmSpace);
294 LosMux *OsGVmSpaceMuxGet(VOID);
295 STATUS_T OsUnMMap(LosVmSpace *space, VADDR_T addr, size_t size);
296 STATUS_T OsVmSpaceRegionFree(LosVmSpace *space);
297
298 /**
299 * thread safety
300 * it is used to malloc continuous virtual memory, no sure for continuous physical memory.
301 */
302 VOID *LOS_VMalloc(size_t size);
303 VOID LOS_VFree(const VOID *addr);
304
305 /**
306 * thread safety
307 * these is used to malloc or free kernel memory.
308 * when the size is large and close to multiples of pages,
309 * will alloc pmm pages, otherwise alloc bestfit memory.
310 */
311 VOID *LOS_KernelMalloc(UINT32 size);
312 VOID *LOS_KernelMallocAlign(UINT32 size, UINT32 boundary);
313 VOID *LOS_KernelRealloc(VOID *ptr, UINT32 size);
314 VOID LOS_KernelFree(VOID *ptr);
315
316 #ifdef __cplusplus
317 #if __cplusplus
318 }
319 #endif /* __cplusplus */
320 #endif /* __cplusplus */
321
322 #endif /* __LOS_VM_MAP_H__ */
323
324