• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_LITEIPC              (1<<19)
161 #define     VM_MAP_REGION_FLAG_INVALID              (1<<20) /* indicates that flags are not specified */
162 
OsCvtProtFlagsToRegionFlags(unsigned long prot,unsigned long flags)163 STATIC INLINE UINT32 OsCvtProtFlagsToRegionFlags(unsigned long prot, unsigned long flags)
164 {
165     UINT32 regionFlags = 0;
166 
167     regionFlags |= VM_MAP_REGION_FLAG_PERM_USER;
168     regionFlags |= (prot & PROT_READ) ? VM_MAP_REGION_FLAG_PERM_READ : 0;
169     regionFlags |= (prot & PROT_WRITE) ? (VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE) : 0;
170     regionFlags |= (prot & PROT_EXEC) ? (VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_EXECUTE) : 0;
171     regionFlags |= (flags & MAP_SHARED) ? VM_MAP_REGION_FLAG_SHARED : 0;
172     regionFlags |= (flags & MAP_PRIVATE) ? VM_MAP_REGION_FLAG_PRIVATE : 0;
173     regionFlags |= (flags & MAP_FIXED) ? VM_MAP_REGION_FLAG_FIXED : 0;
174     regionFlags |= (flags & MAP_FIXED_NOREPLACE) ? VM_MAP_REGION_FLAG_FIXED_NOREPLACE : 0;
175 
176     return regionFlags;
177 }
178 
LOS_IsKernelAddress(VADDR_T vaddr)179 STATIC INLINE BOOL LOS_IsKernelAddress(VADDR_T vaddr)
180 {
181     return ((vaddr >= (VADDR_T)KERNEL_ASPACE_BASE) &&
182             (vaddr <= ((VADDR_T)KERNEL_ASPACE_BASE + ((VADDR_T)KERNEL_ASPACE_SIZE - 1))));
183 }
184 
LOS_IsKernelAddressRange(VADDR_T vaddr,size_t len)185 STATIC INLINE BOOL LOS_IsKernelAddressRange(VADDR_T vaddr, size_t len)
186 {
187     return (vaddr + len > vaddr) && LOS_IsKernelAddress(vaddr) && (LOS_IsKernelAddress(vaddr + len - 1));
188 }
189 
LOS_RegionEndAddr(LosVmMapRegion * region)190 STATIC INLINE VADDR_T LOS_RegionEndAddr(LosVmMapRegion *region)
191 {
192     return (region->range.base + region->range.size - 1);
193 }
194 
LOS_RegionSize(VADDR_T start,VADDR_T end)195 STATIC INLINE size_t LOS_RegionSize(VADDR_T start, VADDR_T end)
196 {
197     return (end - start + 1);
198 }
199 
LOS_IsRegionTypeFile(LosVmMapRegion * region)200 STATIC INLINE BOOL LOS_IsRegionTypeFile(LosVmMapRegion* region)
201 {
202     return region->regionType == VM_MAP_REGION_TYPE_FILE;
203 }
204 
LOS_IsRegionPermUserReadOnly(LosVmMapRegion * region)205 STATIC INLINE BOOL LOS_IsRegionPermUserReadOnly(LosVmMapRegion* region)
206 {
207     return ((region->regionFlags & VM_MAP_REGION_FLAG_PROT_MASK) ==
208             (VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ));
209 }
210 
LOS_IsRegionFlagPrivateOnly(LosVmMapRegion * region)211 STATIC INLINE BOOL LOS_IsRegionFlagPrivateOnly(LosVmMapRegion* region)
212 {
213     return ((region->regionFlags & VM_MAP_REGION_FLAG_FLAG_MASK) == VM_MAP_REGION_FLAG_PRIVATE);
214 }
215 
LOS_SetRegionTypeFile(LosVmMapRegion * region)216 STATIC INLINE VOID LOS_SetRegionTypeFile(LosVmMapRegion* region)
217 {
218     region->regionType = VM_MAP_REGION_TYPE_FILE;
219 }
220 
LOS_IsRegionTypeDev(LosVmMapRegion * region)221 STATIC INLINE BOOL LOS_IsRegionTypeDev(LosVmMapRegion* region)
222 {
223     return region->regionType == VM_MAP_REGION_TYPE_DEV;
224 }
225 
LOS_SetRegionTypeDev(LosVmMapRegion * region)226 STATIC INLINE VOID LOS_SetRegionTypeDev(LosVmMapRegion* region)
227 {
228     region->regionType = VM_MAP_REGION_TYPE_DEV;
229 }
230 
LOS_IsRegionTypeAnon(LosVmMapRegion * region)231 STATIC INLINE BOOL LOS_IsRegionTypeAnon(LosVmMapRegion* region)
232 {
233     return region->regionType == VM_MAP_REGION_TYPE_ANON;
234 }
235 
LOS_SetRegionTypeAnon(LosVmMapRegion * region)236 STATIC INLINE VOID LOS_SetRegionTypeAnon(LosVmMapRegion* region)
237 {
238     region->regionType = VM_MAP_REGION_TYPE_ANON;
239 }
240 
LOS_IsUserAddress(VADDR_T vaddr)241 STATIC INLINE BOOL LOS_IsUserAddress(VADDR_T vaddr)
242 {
243     return ((vaddr >= USER_ASPACE_BASE) &&
244             (vaddr <= (USER_ASPACE_BASE + (USER_ASPACE_SIZE - 1))));
245 }
246 
LOS_IsUserAddressRange(VADDR_T vaddr,size_t len)247 STATIC INLINE BOOL LOS_IsUserAddressRange(VADDR_T vaddr, size_t len)
248 {
249     return (vaddr + len > vaddr) && LOS_IsUserAddress(vaddr) && (LOS_IsUserAddress(vaddr + len - 1));
250 }
251 
LOS_IsVmallocAddress(VADDR_T vaddr)252 STATIC INLINE BOOL LOS_IsVmallocAddress(VADDR_T vaddr)
253 {
254     return ((vaddr >= VMALLOC_START) &&
255             (vaddr <= (VMALLOC_START + (VMALLOC_SIZE - 1))));
256 }
257 
OsIsVmRegionEmpty(LosVmSpace * vmSpace)258 STATIC INLINE BOOL OsIsVmRegionEmpty(LosVmSpace *vmSpace)
259 {
260     if (vmSpace->regionRbTree.ulNodes == 0) {
261         return TRUE;
262     }
263     return FALSE;
264 }
265 
266 LosVmSpace *LOS_GetKVmSpace(VOID);
267 LOS_DL_LIST *LOS_GetVmSpaceList(VOID);
268 LosVmSpace *LOS_GetVmallocSpace(VOID);
269 VOID OsInitMappingStartUp(VOID);
270 VOID OsKSpaceInit(VOID);
271 BOOL LOS_IsRangeInSpace(const LosVmSpace *space, VADDR_T vaddr, size_t size);
272 STATUS_T LOS_VmSpaceReserve(LosVmSpace *space, size_t size, VADDR_T vaddr);
273 INT32 OsUserHeapFree(LosVmSpace *vmSpace, VADDR_T addr, size_t len);
274 VADDR_T OsAllocRange(LosVmSpace *vmSpace, size_t len);
275 VADDR_T OsAllocSpecificRange(LosVmSpace *vmSpace, VADDR_T vaddr, size_t len, UINT32 regionFlags);
276 LosVmMapRegion *OsCreateRegion(VADDR_T vaddr, size_t len, UINT32 regionFlags, unsigned long offset);
277 BOOL OsInsertRegion(LosRbTree *regionRbTree, LosVmMapRegion *region);
278 LosVmSpace *LOS_SpaceGet(VADDR_T vaddr);
279 LosVmSpace *LOS_CurrSpaceGet(VOID);
280 BOOL LOS_IsRegionFileValid(LosVmMapRegion *region);
281 LosVmMapRegion *LOS_RegionRangeFind(LosVmSpace *vmSpace, VADDR_T addr, size_t len);
282 LosVmMapRegion *LOS_RegionFind(LosVmSpace *vmSpace, VADDR_T addr);
283 PADDR_T LOS_PaddrQuery(VOID *vaddr);
284 LosVmMapRegion *LOS_RegionAlloc(LosVmSpace *vmSpace, VADDR_T vaddr, size_t len, UINT32 regionFlags, VM_OFFSET_T pgoff);
285 STATUS_T OsRegionsRemove(LosVmSpace *space, VADDR_T vaddr, size_t size);
286 STATUS_T OsVmRegionAdjust(LosVmSpace *space, VADDR_T vaddr, size_t size);
287 LosVmMapRegion *OsVmRegionDup(LosVmSpace *space, LosVmMapRegion *oldRegion, VADDR_T vaddr, size_t size);
288 STATUS_T OsIsRegionCanExpand(LosVmSpace *space, LosVmMapRegion *region, size_t size);
289 STATUS_T LOS_RegionFree(LosVmSpace *space, LosVmMapRegion *region);
290 STATUS_T LOS_VmSpaceFree(LosVmSpace *space);
291 STATUS_T LOS_VaddrToPaddrMmap(LosVmSpace *space, VADDR_T vaddr, PADDR_T paddr, size_t len, UINT32 flags);
292 BOOL OsUserVmSpaceInit(LosVmSpace *vmSpace, VADDR_T *virtTtb);
293 LosVmSpace *OsCreateUserVmSpace(VOID);
294 STATUS_T LOS_VmSpaceClone(UINT32 cloneFlags, LosVmSpace *oldVmSpace, LosVmSpace *newVmSpace);
295 LosMux *OsGVmSpaceMuxGet(VOID);
296 STATUS_T OsUnMMap(LosVmSpace *space, VADDR_T addr, size_t size);
297 STATUS_T OsVmSpaceRegionFree(LosVmSpace *space);
298 
299 /**
300  * thread safety
301  * it is used to malloc continuous virtual memory, no sure for continuous physical memory.
302  */
303 VOID *LOS_VMalloc(size_t size);
304 VOID LOS_VFree(const VOID *addr);
305 
306 /**
307  * thread safety
308  * these is used to malloc or free kernel memory.
309  * when the size is large and close to multiples of pages,
310  * will alloc pmm pages, otherwise alloc bestfit memory.
311  */
312 VOID *LOS_KernelMalloc(UINT32 size);
313 VOID *LOS_KernelMallocAlign(UINT32 size, UINT32 boundary);
314 VOID *LOS_KernelRealloc(VOID *ptr, UINT32 size);
315 VOID LOS_KernelFree(VOID *ptr);
316 
317 #ifdef __cplusplus
318 #if __cplusplus
319 }
320 #endif /* __cplusplus */
321 #endif /* __cplusplus */
322 
323 #endif /* __LOS_VM_MAP_H__ */
324 
325