• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 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 #include "los_vm_map.h"
33 #include "los_vm_page.h"
34 #include "los_vm_phys.h"
35 #include "los_vm_dump.h"
36 #include "los_vm_lock.h"
37 #include "los_vm_zone.h"
38 #include "los_vm_common.h"
39 #include "los_vm_filemap.h"
40 #include "los_vm_shm_pri.h"
41 #include "los_arch_mmu.h"
42 #include "los_process_pri.h"
43 #ifdef LOSCFG_FS_VFS
44 #include "fs/file.h"
45 #include "vnode.h"
46 #endif
47 #include "los_task.h"
48 #include "los_memory_pri.h"
49 #include "los_vm_boot.h"
50 
51 
52 #ifdef LOSCFG_KERNEL_VM
53 
54 #define VM_MAP_WASTE_MEM_LEVEL          (PAGE_SIZE >> 2)
55 LosMux g_vmSpaceListMux;
56 LOS_DL_LIST_HEAD(g_vmSpaceList);
57 LosVmSpace g_kVmSpace;
58 LosVmSpace g_vMallocSpace;
59 
LOS_CurrSpaceGet(VOID)60 LosVmSpace *LOS_CurrSpaceGet(VOID)
61 {
62     return OsCurrProcessGet()->vmSpace;
63 }
64 
LOS_SpaceGet(VADDR_T vaddr)65 LosVmSpace *LOS_SpaceGet(VADDR_T vaddr)
66 {
67     if (LOS_IsKernelAddress(vaddr)) {
68         return LOS_GetKVmSpace();
69     } else if (LOS_IsUserAddress(vaddr)) {
70         return LOS_CurrSpaceGet();
71     } else if (LOS_IsVmallocAddress(vaddr)) {
72         return LOS_GetVmallocSpace();
73     } else {
74         return NULL;
75     }
76 }
77 
LOS_GetKVmSpace(VOID)78 LosVmSpace *LOS_GetKVmSpace(VOID)
79 {
80     return &g_kVmSpace;
81 }
82 
LOS_GetVmSpaceList(VOID)83 LOS_DL_LIST *LOS_GetVmSpaceList(VOID)
84 {
85     return &g_vmSpaceList;
86 }
87 
LOS_GetVmallocSpace(VOID)88 LosVmSpace *LOS_GetVmallocSpace(VOID)
89 {
90     return &g_vMallocSpace;
91 }
92 
OsRegionRbFreeFn(LosRbNode * pstNode)93 ULONG_T OsRegionRbFreeFn(LosRbNode *pstNode)
94 {
95     LOS_MemFree(m_aucSysMem0, pstNode);
96     return LOS_OK;
97 }
98 
OsRegionRbGetKeyFn(LosRbNode * pstNode)99 VOID *OsRegionRbGetKeyFn(LosRbNode *pstNode)
100 {
101     LosVmMapRegion *region = (LosVmMapRegion *)LOS_DL_LIST_ENTRY(pstNode, LosVmMapRegion, rbNode);
102     return (VOID *)&region->range;
103 }
104 
OsRegionRbCmpKeyFn(const VOID * pNodeKeyA,const VOID * pNodeKeyB)105 ULONG_T OsRegionRbCmpKeyFn(const VOID *pNodeKeyA, const VOID *pNodeKeyB)
106 {
107     LosVmMapRange rangeA = *(LosVmMapRange *)pNodeKeyA;
108     LosVmMapRange rangeB = *(LosVmMapRange *)pNodeKeyB;
109     UINT32 startA = rangeA.base;
110     UINT32 endA = rangeA.base + rangeA.size - 1;
111     UINT32 startB = rangeB.base;
112     UINT32 endB = rangeB.base + rangeB.size - 1;
113 
114     if (startA > endB) {
115         return RB_BIGGER;
116     } else if (startA >= startB) {
117         if (endA <= endB) {
118             return RB_EQUAL;
119         } else {
120             return RB_BIGGER;
121         }
122     } else if (startA <= startB) {
123         if (endA >= endB) {
124             return RB_EQUAL;
125         } else {
126             return RB_SMALLER;
127         }
128     } else if (endA < startB) {
129         return RB_SMALLER;
130     }
131     return RB_EQUAL;
132 }
133 
OsVmSpaceInitCommon(LosVmSpace * vmSpace,VADDR_T * virtTtb)134 STATIC BOOL OsVmSpaceInitCommon(LosVmSpace *vmSpace, VADDR_T *virtTtb)
135 {
136     LOS_RbInitTree(&vmSpace->regionRbTree, OsRegionRbCmpKeyFn, OsRegionRbFreeFn, OsRegionRbGetKeyFn);
137 
138     status_t retval = LOS_MuxInit(&vmSpace->regionMux, NULL);
139     if (retval != LOS_OK) {
140         VM_ERR("Create mutex for vm space failed, status: %d", retval);
141         return FALSE;
142     }
143 
144     (VOID)LOS_MuxAcquire(&g_vmSpaceListMux);
145     LOS_ListAdd(&g_vmSpaceList, &vmSpace->node);
146     (VOID)LOS_MuxRelease(&g_vmSpaceListMux);
147 
148     return OsArchMmuInit(&vmSpace->archMmu, virtTtb);
149 }
150 
OsVmMapInit(VOID)151 VOID OsVmMapInit(VOID)
152 {
153     status_t retval = LOS_MuxInit(&g_vmSpaceListMux, NULL);
154     if (retval != LOS_OK) {
155         VM_ERR("Create mutex for g_vmSpaceList failed, status: %d", retval);
156     }
157 }
158 
OsKernVmSpaceInit(LosVmSpace * vmSpace,VADDR_T * virtTtb)159 BOOL OsKernVmSpaceInit(LosVmSpace *vmSpace, VADDR_T *virtTtb)
160 {
161     vmSpace->base = KERNEL_ASPACE_BASE;
162     vmSpace->size = KERNEL_ASPACE_SIZE;
163     vmSpace->mapBase = KERNEL_VMM_BASE;
164     vmSpace->mapSize = KERNEL_VMM_SIZE;
165 #ifdef LOSCFG_DRIVERS_TZDRIVER
166     vmSpace->codeStart = 0;
167     vmSpace->codeEnd = 0;
168 #endif
169     return OsVmSpaceInitCommon(vmSpace, virtTtb);
170 }
171 
OsVMallocSpaceInit(LosVmSpace * vmSpace,VADDR_T * virtTtb)172 BOOL OsVMallocSpaceInit(LosVmSpace *vmSpace, VADDR_T *virtTtb)
173 {
174     vmSpace->base = VMALLOC_START;
175     vmSpace->size = VMALLOC_SIZE;
176     vmSpace->mapBase = VMALLOC_START;
177     vmSpace->mapSize = VMALLOC_SIZE;
178 #ifdef LOSCFG_DRIVERS_TZDRIVER
179     vmSpace->codeStart = 0;
180     vmSpace->codeEnd = 0;
181 #endif
182     return OsVmSpaceInitCommon(vmSpace, virtTtb);
183 }
184 
OsKSpaceInit(VOID)185 VOID OsKSpaceInit(VOID)
186 {
187     OsVmMapInit();
188     OsKernVmSpaceInit(&g_kVmSpace, OsGFirstTableGet());
189     OsVMallocSpaceInit(&g_vMallocSpace, OsGFirstTableGet());
190 }
191 
OsUserVmSpaceInit(LosVmSpace * vmSpace,VADDR_T * virtTtb)192 BOOL OsUserVmSpaceInit(LosVmSpace *vmSpace, VADDR_T *virtTtb)
193 {
194     vmSpace->base = USER_ASPACE_BASE;
195     vmSpace->size = USER_ASPACE_SIZE;
196     vmSpace->mapBase = USER_MAP_BASE;
197     vmSpace->mapSize = USER_MAP_SIZE;
198     vmSpace->heapBase = USER_HEAP_BASE;
199     vmSpace->heapNow = USER_HEAP_BASE;
200     vmSpace->heap = NULL;
201 #ifdef LOSCFG_DRIVERS_TZDRIVER
202     vmSpace->codeStart = 0;
203     vmSpace->codeEnd = 0;
204 #endif
205     return OsVmSpaceInitCommon(vmSpace, virtTtb);
206 }
207 
OsCreateUserVmSpace(VOID)208 LosVmSpace *OsCreateUserVmSpace(VOID)
209 {
210     BOOL retVal = FALSE;
211 
212     LosVmSpace *space = LOS_MemAlloc(m_aucSysMem0, sizeof(LosVmSpace));
213     if (space == NULL) {
214         return NULL;
215     }
216 
217     VADDR_T *ttb = LOS_PhysPagesAllocContiguous(1);
218     if (ttb == NULL) {
219         (VOID)LOS_MemFree(m_aucSysMem0, space);
220         return NULL;
221     }
222 
223     (VOID)memset_s(ttb, PAGE_SIZE, 0, PAGE_SIZE);
224     retVal = OsUserVmSpaceInit(space, ttb);
225     LosVmPage *vmPage = OsVmVaddrToPage(ttb);
226     if ((retVal == FALSE) || (vmPage == NULL)) {
227         (VOID)LOS_MemFree(m_aucSysMem0, space);
228         LOS_PhysPagesFreeContiguous(ttb, 1);
229         return NULL;
230     }
231     LOS_ListAdd(&space->archMmu.ptList, &(vmPage->node));
232 
233     return space;
234 }
235 
OsVmSpaceParamCheck(const LosVmSpace * vmSpace)236 STATIC BOOL OsVmSpaceParamCheck(const LosVmSpace *vmSpace)
237 {
238     if (vmSpace == NULL) {
239         return FALSE;
240     }
241     return TRUE;
242 }
243 
LOS_VmSpaceClone(LosVmSpace * oldVmSpace,LosVmSpace * newVmSpace)244 STATUS_T LOS_VmSpaceClone(LosVmSpace *oldVmSpace, LosVmSpace *newVmSpace)
245 {
246     LosVmMapRegion *oldRegion = NULL;
247     LosVmMapRegion *newRegion = NULL;
248     LosRbNode *pstRbNode = NULL;
249     LosRbNode *pstRbNodeNext = NULL;
250     STATUS_T ret = LOS_OK;
251     UINT32 numPages;
252     PADDR_T paddr;
253     VADDR_T vaddr;
254     UINT32 intSave;
255     LosVmPage *page = NULL;
256     UINT32 flags;
257     UINT32 i;
258 
259     if ((OsVmSpaceParamCheck(oldVmSpace) == FALSE) || (OsVmSpaceParamCheck(newVmSpace) == FALSE)) {
260         return LOS_ERRNO_VM_INVALID_ARGS;
261     }
262 
263     if ((OsIsVmRegionEmpty(oldVmSpace) == TRUE) || (oldVmSpace == &g_kVmSpace)) {
264         return LOS_ERRNO_VM_INVALID_ARGS;
265     }
266 
267     /* search the region list */
268     newVmSpace->mapBase = oldVmSpace->mapBase;
269     newVmSpace->heapBase = oldVmSpace->heapBase;
270     newVmSpace->heapNow = oldVmSpace->heapNow;
271     (VOID)LOS_MuxAcquire(&oldVmSpace->regionMux);
272     RB_SCAN_SAFE(&oldVmSpace->regionRbTree, pstRbNode, pstRbNodeNext)
273         oldRegion = (LosVmMapRegion *)pstRbNode;
274         newRegion = OsVmRegionDup(newVmSpace, oldRegion, oldRegion->range.base, oldRegion->range.size);
275         if (newRegion == NULL) {
276             VM_ERR("dup new region failed");
277             ret = LOS_ERRNO_VM_NO_MEMORY;
278             break;
279         }
280 
281 #ifdef LOSCFG_KERNEL_SHM
282         if (oldRegion->regionFlags & VM_MAP_REGION_FLAG_SHM) {
283             OsShmFork(newVmSpace, oldRegion, newRegion);
284             continue;
285         }
286 #endif
287 
288         if (oldRegion == oldVmSpace->heap) {
289             newVmSpace->heap = newRegion;
290         }
291 
292         numPages = newRegion->range.size >> PAGE_SHIFT;
293         for (i = 0; i < numPages; i++) {
294             vaddr = newRegion->range.base + (i << PAGE_SHIFT);
295             if (LOS_ArchMmuQuery(&oldVmSpace->archMmu, vaddr, &paddr, &flags) != LOS_OK) {
296                 continue;
297             }
298 
299             page = LOS_VmPageGet(paddr);
300             if (page != NULL) {
301                 LOS_AtomicInc(&page->refCounts);
302             }
303             if (flags & VM_MAP_REGION_FLAG_PERM_WRITE) {
304                 LOS_ArchMmuUnmap(&oldVmSpace->archMmu, vaddr, 1);
305                 LOS_ArchMmuMap(&oldVmSpace->archMmu, vaddr, paddr, 1, flags & ~VM_MAP_REGION_FLAG_PERM_WRITE);
306             }
307             LOS_ArchMmuMap(&newVmSpace->archMmu, vaddr, paddr, 1, flags & ~VM_MAP_REGION_FLAG_PERM_WRITE);
308 
309 #ifdef LOSCFG_FS_VFS
310             if (LOS_IsRegionFileValid(oldRegion)) {
311                 LosFilePage *fpage = NULL;
312                 LOS_SpinLockSave(&oldRegion->unTypeData.rf.vnode->mapping.list_lock, &intSave);
313                 fpage = OsFindGetEntry(&oldRegion->unTypeData.rf.vnode->mapping, newRegion->pgOff + i);
314                 if ((fpage != NULL) && (fpage->vmPage == page)) { /* cow page no need map */
315                     OsAddMapInfo(fpage, &newVmSpace->archMmu, vaddr);
316                 }
317                 LOS_SpinUnlockRestore(&oldRegion->unTypeData.rf.vnode->mapping.list_lock, intSave);
318             }
319 #endif
320         }
321     RB_SCAN_SAFE_END(&oldVmSpace->regionRbTree, pstRbNode, pstRbNodeNext)
322     (VOID)LOS_MuxRelease(&oldVmSpace->regionMux);
323     return ret;
324 }
325 
OsFindRegion(LosRbTree * regionRbTree,VADDR_T vaddr,size_t len)326 LosVmMapRegion *OsFindRegion(LosRbTree *regionRbTree, VADDR_T vaddr, size_t len)
327 {
328     LosVmMapRegion *regionRst = NULL;
329     LosRbNode *pstRbNode = NULL;
330     LosVmMapRange rangeKey;
331     rangeKey.base = vaddr;
332     rangeKey.size = len;
333 
334     if (LOS_RbGetNode(regionRbTree, (VOID *)&rangeKey, &pstRbNode)) {
335         regionRst = (LosVmMapRegion *)LOS_DL_LIST_ENTRY(pstRbNode, LosVmMapRegion, rbNode);
336     }
337     return regionRst;
338 }
339 
LOS_RegionFind(LosVmSpace * vmSpace,VADDR_T addr)340 LosVmMapRegion *LOS_RegionFind(LosVmSpace *vmSpace, VADDR_T addr)
341 {
342     LosVmMapRegion *region = NULL;
343 
344     (VOID)LOS_MuxAcquire(&vmSpace->regionMux);
345     region = OsFindRegion(&vmSpace->regionRbTree, addr, 1);
346     (VOID)LOS_MuxRelease(&vmSpace->regionMux);
347 
348     return region;
349 }
350 
LOS_RegionRangeFind(LosVmSpace * vmSpace,VADDR_T addr,size_t len)351 LosVmMapRegion *LOS_RegionRangeFind(LosVmSpace *vmSpace, VADDR_T addr, size_t len)
352 {
353     LosVmMapRegion *region = NULL;
354 
355     (VOID)LOS_MuxAcquire(&vmSpace->regionMux);
356     region = OsFindRegion(&vmSpace->regionRbTree, addr, len);
357     (VOID)LOS_MuxRelease(&vmSpace->regionMux);
358 
359     return region;
360 }
361 
OsAllocRange(LosVmSpace * vmSpace,size_t len)362 VADDR_T OsAllocRange(LosVmSpace *vmSpace, size_t len)
363 {
364     LosVmMapRegion *curRegion = NULL;
365     LosRbNode *pstRbNode = NULL;
366     LosRbNode *pstRbNodeTmp = NULL;
367     LosRbTree *regionRbTree = &vmSpace->regionRbTree;
368     VADDR_T curEnd = vmSpace->mapBase;
369     VADDR_T nextStart;
370 
371     curRegion = LOS_RegionFind(vmSpace, vmSpace->mapBase);
372     if (curRegion != NULL) {
373         pstRbNode = &curRegion->rbNode;
374         curEnd = curRegion->range.base + curRegion->range.size;
375         RB_MID_SCAN(regionRbTree, pstRbNode)
376             curRegion = (LosVmMapRegion *)pstRbNode;
377             nextStart = curRegion->range.base;
378             if (nextStart < curEnd) {
379                 continue;
380             }
381             if ((nextStart - curEnd) >= len) {
382                 return curEnd;
383             } else {
384                 curEnd = curRegion->range.base + curRegion->range.size;
385             }
386         RB_MID_SCAN_END(regionRbTree, pstRbNode)
387     } else {
388         /* rbtree scan is sorted, from small to big */
389         RB_SCAN_SAFE(regionRbTree, pstRbNode, pstRbNodeTmp)
390             curRegion = (LosVmMapRegion *)pstRbNode;
391             nextStart = curRegion->range.base;
392             if (nextStart < curEnd) {
393                 continue;
394             }
395             if ((nextStart - curEnd) >= len) {
396                 return curEnd;
397             } else {
398                 curEnd = curRegion->range.base + curRegion->range.size;
399             }
400         RB_SCAN_SAFE_END(regionRbTree, pstRbNode, pstRbNodeTmp)
401     }
402 
403     nextStart = vmSpace->mapBase + vmSpace->mapSize;
404     if ((nextStart >= curEnd) && ((nextStart - curEnd) >= len)) {
405         return curEnd;
406     }
407 
408     return 0;
409 }
410 
OsAllocSpecificRange(LosVmSpace * vmSpace,VADDR_T vaddr,size_t len,UINT32 regionFlags)411 VADDR_T OsAllocSpecificRange(LosVmSpace *vmSpace, VADDR_T vaddr, size_t len, UINT32 regionFlags)
412 {
413     STATUS_T status;
414 
415     if (LOS_IsRangeInSpace(vmSpace, vaddr, len) == FALSE) {
416         return 0;
417     }
418 
419     if ((LOS_RegionFind(vmSpace, vaddr) != NULL) ||
420         (LOS_RegionFind(vmSpace, vaddr + len - 1) != NULL) ||
421         (LOS_RegionRangeFind(vmSpace, vaddr, len - 1) != NULL)) {
422         if ((regionFlags & VM_MAP_REGION_FLAG_FIXED_NOREPLACE) != 0) {
423             return 0;
424         } else if ((regionFlags & VM_MAP_REGION_FLAG_FIXED) != 0) {
425             status = LOS_UnMMap(vaddr, len);
426             if (status != LOS_OK) {
427                 VM_ERR("unmap specific range va: %#x, len: %#x failed, status: %d", vaddr, len, status);
428                 return 0;
429             }
430         } else {
431             return OsAllocRange(vmSpace, len);
432         }
433     }
434 
435     return vaddr;
436 }
437 
LOS_IsRegionFileValid(LosVmMapRegion * region)438 BOOL LOS_IsRegionFileValid(LosVmMapRegion *region)
439 {
440     if ((region != NULL) && (LOS_IsRegionTypeFile(region)) &&
441         (region->unTypeData.rf.vnode != NULL)) {
442         return TRUE;
443     }
444     return FALSE;
445 }
446 
OsInsertRegion(LosRbTree * regionRbTree,LosVmMapRegion * region)447 BOOL OsInsertRegion(LosRbTree *regionRbTree, LosVmMapRegion *region)
448 {
449     if (LOS_RbAddNode(regionRbTree, (LosRbNode *)region) == FALSE) {
450         VM_ERR("insert region failed, base: %#x, size: %#x", region->range.base, region->range.size);
451         OsDumpAspace(region->space);
452         return FALSE;
453     }
454     return TRUE;
455 }
456 
OsCreateRegion(VADDR_T vaddr,size_t len,UINT32 regionFlags,unsigned long offset)457 LosVmMapRegion *OsCreateRegion(VADDR_T vaddr, size_t len, UINT32 regionFlags, unsigned long offset)
458 {
459     LosVmMapRegion *region = LOS_MemAlloc(m_aucSysMem0, sizeof(LosVmMapRegion));
460     if (region == NULL) {
461         VM_ERR("memory allocate for LosVmMapRegion failed");
462         return region;
463     }
464 
465     (void)memset_s(region, sizeof(LosVmMapRegion), 0, sizeof(LosVmMapRegion));
466     region->range.base = vaddr;
467     region->range.size = len;
468     region->pgOff = offset;
469     region->regionFlags = regionFlags;
470     region->regionType = VM_MAP_REGION_TYPE_NONE;
471     region->forkFlags = 0;
472     region->shmid = -1;
473     return region;
474 }
475 
LOS_PaddrQuery(VOID * vaddr)476 PADDR_T LOS_PaddrQuery(VOID *vaddr)
477 {
478     PADDR_T paddr = 0;
479     STATUS_T status;
480     LosVmSpace *space = NULL;
481     LosArchMmu *archMmu = NULL;
482 
483     if (LOS_IsKernelAddress((VADDR_T)(UINTPTR)vaddr)) {
484         archMmu = &g_kVmSpace.archMmu;
485     } else if (LOS_IsUserAddress((VADDR_T)(UINTPTR)vaddr)) {
486         space = OsCurrProcessGet()->vmSpace;
487         archMmu = &space->archMmu;
488     } else if (LOS_IsVmallocAddress((VADDR_T)(UINTPTR)vaddr)) {
489         archMmu = &g_vMallocSpace.archMmu;
490     } else {
491         VM_ERR("vaddr is beyond range");
492         return 0;
493     }
494 
495     status = LOS_ArchMmuQuery(archMmu, (VADDR_T)(UINTPTR)vaddr, &paddr, 0);
496     if (status == LOS_OK) {
497         return paddr;
498     } else {
499         return 0;
500     }
501 }
502 
LOS_RegionAlloc(LosVmSpace * vmSpace,VADDR_T vaddr,size_t len,UINT32 regionFlags,VM_OFFSET_T pgoff)503 LosVmMapRegion *LOS_RegionAlloc(LosVmSpace *vmSpace, VADDR_T vaddr, size_t len, UINT32 regionFlags, VM_OFFSET_T pgoff)
504 {
505     VADDR_T rstVaddr;
506     LosVmMapRegion *newRegion = NULL;
507     BOOL isInsertSucceed = FALSE;
508     /**
509      * If addr is NULL, then the kernel chooses the address at which to create the mapping;
510      * this is the most portable method of creating a new mapping.  If addr is not NULL,
511      * then the kernel takes it as where to place the mapping;
512      */
513     (VOID)LOS_MuxAcquire(&vmSpace->regionMux);
514     if (vaddr == 0) {
515         rstVaddr = OsAllocRange(vmSpace, len);
516     } else {
517         /* if it is already mmapped here, we unmmap it */
518         rstVaddr = OsAllocSpecificRange(vmSpace, vaddr, len, regionFlags);
519         if (rstVaddr == 0) {
520             VM_ERR("alloc specific range va: %#x, len: %#x failed", vaddr, len);
521             goto OUT;
522         }
523     }
524     if (rstVaddr == 0) {
525         goto OUT;
526     }
527 
528     newRegion = OsCreateRegion(rstVaddr, len, regionFlags, pgoff);
529     if (newRegion == NULL) {
530         goto OUT;
531     }
532     newRegion->space = vmSpace;
533     isInsertSucceed = OsInsertRegion(&vmSpace->regionRbTree, newRegion);
534     if (isInsertSucceed == FALSE) {
535         (VOID)LOS_MemFree(m_aucSysMem0, newRegion);
536         newRegion = NULL;
537     }
538 
539 OUT:
540     (VOID)LOS_MuxRelease(&vmSpace->regionMux);
541     return newRegion;
542 }
543 
OsAnonPagesRemove(LosArchMmu * archMmu,VADDR_T vaddr,UINT32 count)544 STATIC VOID OsAnonPagesRemove(LosArchMmu *archMmu, VADDR_T vaddr, UINT32 count)
545 {
546     status_t status;
547     paddr_t paddr;
548     LosVmPage *page = NULL;
549 
550     if ((archMmu == NULL) || (vaddr == 0) || (count == 0)) {
551         VM_ERR("OsAnonPagesRemove invalid args, archMmu %p, vaddr %p, count %d", archMmu, vaddr, count);
552         return;
553     }
554 
555     while (count > 0) {
556         count--;
557         status = LOS_ArchMmuQuery(archMmu, vaddr, &paddr, NULL);
558         if (status != LOS_OK) {
559             vaddr += PAGE_SIZE;
560             continue;
561         }
562 
563         LOS_ArchMmuUnmap(archMmu, vaddr, 1);
564 
565         page = LOS_VmPageGet(paddr);
566         if (page != NULL) {
567             if (!OsIsPageShared(page)) {
568                 LOS_PhysPageFree(page);
569             }
570         }
571         vaddr += PAGE_SIZE;
572     }
573 }
574 
OsDevPagesRemove(LosArchMmu * archMmu,VADDR_T vaddr,UINT32 count)575 STATIC VOID OsDevPagesRemove(LosArchMmu *archMmu, VADDR_T vaddr, UINT32 count)
576 {
577     status_t status;
578 
579     if ((archMmu == NULL) || (vaddr == 0) || (count == 0)) {
580         VM_ERR("OsDevPagesRemove invalid args, archMmu %p, vaddr %p, count %d", archMmu, vaddr, count);
581         return;
582     }
583 
584     status = LOS_ArchMmuQuery(archMmu, vaddr, NULL, NULL);
585     if (status != LOS_OK) {
586         return;
587     }
588 
589     /* in order to unmap section */
590     LOS_ArchMmuUnmap(archMmu, vaddr, count);
591 }
592 
593 #ifdef LOSCFG_FS_VFS
OsFilePagesRemove(LosVmSpace * space,LosVmMapRegion * region)594 STATIC VOID OsFilePagesRemove(LosVmSpace *space, LosVmMapRegion *region)
595 {
596     VM_OFFSET_T offset;
597     size_t size;
598 
599     if ((space == NULL) || (region == NULL) || (region->unTypeData.rf.vmFOps == NULL)) {
600         return;
601     }
602 
603     offset = region->pgOff;
604     size = region->range.size;
605     while (size >= PAGE_SIZE) {
606         region->unTypeData.rf.vmFOps->remove(region, &space->archMmu, offset);
607         offset++;
608         size -= PAGE_SIZE;
609     }
610 }
611 #endif
612 
LOS_RegionFree(LosVmSpace * space,LosVmMapRegion * region)613 STATUS_T LOS_RegionFree(LosVmSpace *space, LosVmMapRegion *region)
614 {
615     if ((space == NULL) || (region == NULL)) {
616         VM_ERR("args error, aspace %p, region %p", space, region);
617         return LOS_ERRNO_VM_INVALID_ARGS;
618     }
619 
620     (VOID)LOS_MuxAcquire(&space->regionMux);
621 
622 #ifdef LOSCFG_FS_VFS
623     if (LOS_IsRegionFileValid(region)) {
624         OsFilePagesRemove(space, region);
625         VnodeHold();
626         region->unTypeData.rf.vnode->useCount--;
627         VnodeDrop();
628     } else
629 #endif
630 
631 #ifdef LOSCFG_KERNEL_SHM
632     if (OsIsShmRegion(region)) {
633         OsShmRegionFree(space, region);
634     } else if (LOS_IsRegionTypeDev(region)) {
635 #else
636     if (LOS_IsRegionTypeDev(region)) {
637 #endif
638         OsDevPagesRemove(&space->archMmu, region->range.base, region->range.size >> PAGE_SHIFT);
639     } else {
640         OsAnonPagesRemove(&space->archMmu, region->range.base, region->range.size >> PAGE_SHIFT);
641     }
642 
643     /* remove it from space */
644     LOS_RbDelNode(&space->regionRbTree, &region->rbNode);
645     /* free it */
646     LOS_MemFree(m_aucSysMem0, region);
647     (VOID)LOS_MuxRelease(&space->regionMux);
648     return LOS_OK;
649 }
650 
651 LosVmMapRegion *OsVmRegionDup(LosVmSpace *space, LosVmMapRegion *oldRegion, VADDR_T vaddr, size_t size)
652 {
653     LosVmMapRegion *newRegion = NULL;
654     UINT32 regionFlags;
655 
656     (VOID)LOS_MuxAcquire(&space->regionMux);
657     regionFlags = oldRegion->regionFlags;
658     if (vaddr == 0) {
659         regionFlags &= ~(VM_MAP_REGION_FLAG_FIXED | VM_MAP_REGION_FLAG_FIXED_NOREPLACE);
660     } else {
661         regionFlags |= VM_MAP_REGION_FLAG_FIXED;
662     }
663     newRegion = LOS_RegionAlloc(space, vaddr, size, regionFlags, oldRegion->pgOff);
664     if (newRegion == NULL) {
665         VM_ERR("LOS_RegionAlloc failed");
666         goto REGIONDUPOUT;
667     }
668     newRegion->regionType = oldRegion->regionType;
669 
670 #ifdef LOSCFG_KERNEL_SHM
671     if (OsIsShmRegion(oldRegion)) {
672         newRegion->shmid = oldRegion->shmid;
673     }
674 #endif
675 
676 #ifdef LOSCFG_FS_VFS
677     if (LOS_IsRegionTypeFile(oldRegion)) {
678         newRegion->unTypeData.rf.vmFOps = oldRegion->unTypeData.rf.vmFOps;
679         newRegion->unTypeData.rf.vnode = oldRegion->unTypeData.rf.vnode;
680         newRegion->unTypeData.rf.f_oflags = oldRegion->unTypeData.rf.f_oflags;
681         VnodeHold();
682         newRegion->unTypeData.rf.vnode->useCount++;
683         VnodeDrop();
684     }
685 #endif
686 
687 REGIONDUPOUT:
688     (VOID)LOS_MuxRelease(&space->regionMux);
689     return newRegion;
690 }
691 
692 STATIC LosVmMapRegion *OsVmRegionSplit(LosVmMapRegion *oldRegion, VADDR_T newRegionStart)
693 {
694     LosVmMapRegion *newRegion = NULL;
695     LosVmSpace *space = oldRegion->space;
696     size_t size = LOS_RegionSize(newRegionStart, LOS_RegionEndAddr(oldRegion));
697 
698     oldRegion->range.size = LOS_RegionSize(oldRegion->range.base, newRegionStart - 1);
699     if (oldRegion->range.size == 0) {
700         LOS_RbDelNode(&space->regionRbTree, &oldRegion->rbNode);
701     }
702 
703     newRegion = OsVmRegionDup(oldRegion->space, oldRegion, newRegionStart, size);
704     if (newRegion == NULL) {
705         VM_ERR("OsVmRegionDup fail");
706         return NULL;
707     }
708 #ifdef LOSCFG_FS_VFS
709     newRegion->pgOff = oldRegion->pgOff + ((newRegionStart - oldRegion->range.base) >> PAGE_SHIFT);
710 #endif
711     return newRegion;
712 }
713 
714 STATUS_T OsVmRegionAdjust(LosVmSpace *space, VADDR_T newRegionStart, size_t size)
715 {
716     LosVmMapRegion *region = NULL;
717     VADDR_T nextRegionBase = newRegionStart + size;
718     LosVmMapRegion *newRegion = NULL;
719 
720     region = LOS_RegionFind(space, newRegionStart);
721     if ((region != NULL) && (newRegionStart > region->range.base)) {
722         newRegion = OsVmRegionSplit(region, newRegionStart);
723         if (newRegion == NULL) {
724             VM_ERR("region split fail");
725             return LOS_ERRNO_VM_NO_MEMORY;
726         }
727     }
728 
729     region = LOS_RegionFind(space, nextRegionBase - 1);
730     if ((region != NULL) && (nextRegionBase < LOS_RegionEndAddr(region))) {
731         newRegion = OsVmRegionSplit(region, nextRegionBase);
732         if (newRegion == NULL) {
733             VM_ERR("region split fail");
734             return LOS_ERRNO_VM_NO_MEMORY;
735         }
736     }
737 
738     return LOS_OK;
739 }
740 
741 STATUS_T OsRegionsRemove(LosVmSpace *space, VADDR_T regionBase, size_t size)
742 {
743     STATUS_T status;
744     VADDR_T regionEnd = regionBase + size - 1;
745     LosVmMapRegion *regionTemp = NULL;
746     LosRbNode *pstRbNodeTemp = NULL;
747     LosRbNode *pstRbNodeNext = NULL;
748 
749     (VOID)LOS_MuxAcquire(&space->regionMux);
750 
751     status = OsVmRegionAdjust(space, regionBase, size);
752     if (status != LOS_OK) {
753         goto ERR_REGION_SPLIT;
754     }
755 
756     RB_SCAN_SAFE(&space->regionRbTree, pstRbNodeTemp, pstRbNodeNext)
757         regionTemp = (LosVmMapRegion *)pstRbNodeTemp;
758         if (regionTemp->range.base > regionEnd) {
759             break;
760         }
761         if (regionBase <= regionTemp->range.base && regionEnd >= LOS_RegionEndAddr(regionTemp)) {
762             status = LOS_RegionFree(space, regionTemp);
763             if (status != LOS_OK) {
764                 VM_ERR("fail to free region, status=%d", status);
765                 goto ERR_REGION_SPLIT;
766             }
767         }
768 
769     RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNodeTemp, pstRbNodeNext)
770 
771 ERR_REGION_SPLIT:
772     (VOID)LOS_MuxRelease(&space->regionMux);
773     return status;
774 }
775 
776 INT32 OsUserHeapFree(LosVmSpace *vmSpace, VADDR_T addr, size_t len)
777 {
778     LosVmMapRegion *vmRegion = NULL;
779     LosVmPage *vmPage = NULL;
780     PADDR_T paddr = 0;
781     VADDR_T vaddr;
782     STATUS_T ret;
783 
784     if (vmSpace == LOS_GetKVmSpace() || vmSpace->heap == NULL) {
785         return -1;
786     }
787 
788     vmRegion = LOS_RegionFind(vmSpace, addr);
789     if (vmRegion == NULL) {
790         return -1;
791     }
792 
793     if (vmRegion == vmSpace->heap) {
794         vaddr = addr;
795         while (len > 0) {
796             if (LOS_ArchMmuQuery(&vmSpace->archMmu, vaddr, &paddr, 0) == LOS_OK) {
797                 ret = LOS_ArchMmuUnmap(&vmSpace->archMmu, vaddr, 1);
798                 if (ret <= 0) {
799                     VM_ERR("unmap failed, ret = %d", ret);
800                 }
801                 vmPage = LOS_VmPageGet(paddr);
802                 LOS_PhysPageFree(vmPage);
803             }
804             vaddr += PAGE_SIZE;
805             len -= PAGE_SIZE;
806         }
807         return 0;
808     }
809 
810     return -1;
811 }
812 
813 STATUS_T OsIsRegionCanExpand(LosVmSpace *space, LosVmMapRegion *region, size_t size)
814 {
815     LosVmMapRegion *nextRegion = NULL;
816 
817     if ((space == NULL) || (region == NULL)) {
818         return LOS_NOK;
819     }
820 
821     nextRegion = (LosVmMapRegion *)LOS_RbSuccessorNode(&space->regionRbTree, &region->rbNode);
822     /* if the gap is larger than size, then we can expand */
823     if ((nextRegion != NULL) && ((nextRegion->range.base - region->range.base) >= size)) {
824         return LOS_OK;
825     }
826 
827     return LOS_NOK;
828 }
829 
830 STATUS_T OsUnMMap(LosVmSpace *space, VADDR_T addr, size_t size)
831 {
832     size = LOS_Align(size, PAGE_SIZE);
833     addr = LOS_Align(addr, PAGE_SIZE);
834     (VOID)LOS_MuxAcquire(&space->regionMux);
835     STATUS_T status = OsRegionsRemove(space, addr, size);
836     if (status != LOS_OK) {
837         status = -EINVAL;
838         VM_ERR("region_split failed");
839         goto ERR_REGION_SPLIT;
840     }
841 
842 ERR_REGION_SPLIT:
843     (VOID)LOS_MuxRelease(&space->regionMux);
844     return status;
845 }
846 
847 STATIC VOID OsVmSpaceAllRegionFree(LosVmSpace *space)
848 {
849     LosRbNode *pstRbNode = NULL;
850     LosRbNode *pstRbNodeNext = NULL;
851 
852     /* free all of the regions */
853     RB_SCAN_SAFE(&space->regionRbTree, pstRbNode, pstRbNodeNext)
854         LosVmMapRegion *region = (LosVmMapRegion *)pstRbNode;
855         if (region->range.size == 0) {
856             VM_ERR("space free, region: %#x flags: %#x, base:%#x, size: %#x",
857                    region, region->regionFlags, region->range.base, region->range.size);
858         }
859         STATUS_T ret = LOS_RegionFree(space, region);
860         if (ret != LOS_OK) {
861             VM_ERR("free region error, space %p, region %p", space, region);
862         }
863     RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNode, pstRbNodeNext)
864 
865     return;
866 }
867 
868 STATUS_T OsVmSpaceRegionFree(LosVmSpace *space)
869 {
870     if (space == NULL) {
871         return LOS_ERRNO_VM_INVALID_ARGS;
872     }
873 
874     if (space == &g_kVmSpace) {
875         VM_ERR("try to free kernel aspace, not allowed");
876         return LOS_OK;
877     }
878 
879     (VOID)LOS_MuxAcquire(&space->regionMux);
880     OsVmSpaceAllRegionFree(space);
881     (VOID)LOS_MuxRelease(&space->regionMux);
882 
883     return LOS_OK;
884 }
885 
886 STATUS_T LOS_VmSpaceFree(LosVmSpace *space)
887 {
888     if (space == NULL) {
889         return LOS_ERRNO_VM_INVALID_ARGS;
890     }
891 
892     if (space == &g_kVmSpace) {
893         VM_ERR("try to free kernel aspace, not allowed");
894         return LOS_OK;
895     }
896 
897     /* pop it out of the global aspace list */
898     (VOID)LOS_MuxAcquire(&space->regionMux);
899 
900     LOS_ListDelete(&space->node);
901 
902     OsVmSpaceAllRegionFree(space);
903 
904     /* make sure the current thread does not map the aspace */
905     LosProcessCB *currentProcess = OsCurrProcessGet();
906     if (currentProcess->vmSpace == space) {
907         LOS_TaskLock();
908         currentProcess->vmSpace = NULL;
909         LOS_ArchMmuContextSwitch(&space->archMmu);
910         LOS_TaskUnlock();
911     }
912 
913     /* destroy the arch portion of the space */
914     LOS_ArchMmuDestroy(&space->archMmu);
915 
916     (VOID)LOS_MuxRelease(&space->regionMux);
917     (VOID)LOS_MuxDestroy(&space->regionMux);
918 
919     /* free the aspace */
920     LOS_MemFree(m_aucSysMem0, space);
921     return LOS_OK;
922 }
923 
924 BOOL LOS_IsRangeInSpace(const LosVmSpace *space, VADDR_T vaddr, size_t size)
925 {
926     /* is the starting address within the address space */
927     if (vaddr < space->base || vaddr > space->base + space->size - 1) {
928         return FALSE;
929     }
930     if (size == 0) {
931         return TRUE;
932     }
933     /* see if the size is enough to wrap the integer */
934     if (vaddr + size - 1 < vaddr) {
935         return FALSE;
936     }
937     /* see if the end address is within the address space's */
938     if (vaddr + size - 1 > space->base + space->size - 1) {
939         return FALSE;
940     }
941     return TRUE;
942 }
943 
944 STATUS_T LOS_VmSpaceReserve(LosVmSpace *space, size_t size, VADDR_T vaddr)
945 {
946     UINT32 regionFlags = 0;
947 
948     if ((space == NULL) || (size == 0) || (!IS_PAGE_ALIGNED(vaddr) || !IS_PAGE_ALIGNED(size))) {
949         return LOS_ERRNO_VM_INVALID_ARGS;
950     }
951 
952     if (!LOS_IsRangeInSpace(space, vaddr, size)) {
953         return LOS_ERRNO_VM_OUT_OF_RANGE;
954     }
955 
956     /* lookup how it's already mapped */
957     (VOID)LOS_ArchMmuQuery(&space->archMmu, vaddr, NULL, &regionFlags);
958 
959     /* build a new region structure */
960     LosVmMapRegion *region = LOS_RegionAlloc(space, vaddr, size, regionFlags | VM_MAP_REGION_FLAG_FIXED, 0);
961 
962     return region ? LOS_OK : LOS_ERRNO_VM_NO_MEMORY;
963 }
964 
965 STATUS_T LOS_VaddrToPaddrMmap(LosVmSpace *space, VADDR_T vaddr, PADDR_T paddr, size_t len, UINT32 flags)
966 {
967     STATUS_T ret;
968     LosVmMapRegion *region = NULL;
969     LosVmPage *vmPage = NULL;
970 
971     if ((vaddr != ROUNDUP(vaddr, PAGE_SIZE)) ||
972         (paddr != ROUNDUP(paddr, PAGE_SIZE)) ||
973         (len != ROUNDUP(len, PAGE_SIZE))) {
974         VM_ERR("vaddr :0x%x  paddr:0x%x len: 0x%x not page size align", vaddr, paddr, len);
975         return LOS_ERRNO_VM_NOT_VALID;
976     }
977 
978     if (space == NULL) {
979         space = OsCurrProcessGet()->vmSpace;
980     }
981 
982     region = LOS_RegionFind(space, vaddr);
983     if (region != NULL) {
984         VM_ERR("vaddr : 0x%x already used!", vaddr);
985         return LOS_ERRNO_VM_BUSY;
986     }
987 
988     region = LOS_RegionAlloc(space, vaddr, len, flags, 0);
989     if (region == NULL) {
990         VM_ERR("failed");
991         return LOS_ERRNO_VM_NO_MEMORY;
992     }
993 
994     while (len > 0) {
995         vmPage = LOS_VmPageGet(paddr);
996         if (vmPage == NULL) {
997             LOS_RegionFree(space, region);
998             VM_ERR("Page is NULL");
999             return LOS_ERRNO_VM_NOT_VALID;
1000         }
1001         LOS_AtomicInc(&vmPage->refCounts);
1002 
1003         ret = LOS_ArchMmuMap(&space->archMmu, vaddr, paddr, 1, region->regionFlags);
1004         if (ret <= 0) {
1005             VM_ERR("LOS_ArchMmuMap failed: %d", ret);
1006             LOS_RegionFree(space, region);
1007             return ret;
1008         }
1009 
1010         paddr += PAGE_SIZE;
1011         vaddr += PAGE_SIZE;
1012         len -= PAGE_SIZE;
1013     }
1014     return LOS_OK;
1015 }
1016 
1017 VOID *LOS_VMalloc(size_t size)
1018 {
1019     LosVmSpace *space = &g_vMallocSpace;
1020     LosVmMapRegion *region = NULL;
1021     size_t sizeCount;
1022     size_t count;
1023     LosVmPage *vmPage = NULL;
1024     VADDR_T va;
1025     PADDR_T pa;
1026     STATUS_T ret;
1027 
1028     size = LOS_Align(size, PAGE_SIZE);
1029     if ((size == 0) || (size > space->size)) {
1030         return NULL;
1031     }
1032     sizeCount = size >> PAGE_SHIFT;
1033 
1034     LOS_DL_LIST_HEAD(pageList);
1035     (VOID)LOS_MuxAcquire(&space->regionMux);
1036 
1037     count = LOS_PhysPagesAlloc(sizeCount, &pageList);
1038     if (count < sizeCount) {
1039         VM_ERR("failed to allocate enough pages (ask %zu, got %zu)", sizeCount, count);
1040         goto ERROR;
1041     }
1042 
1043     /* allocate a region and put it in the aspace list */
1044     region = LOS_RegionAlloc(space, 0, size, VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE, 0);
1045     if (region == NULL) {
1046         VM_ERR("alloc region failed, size = %x", size);
1047         goto ERROR;
1048     }
1049 
1050     va = region->range.base;
1051     while ((vmPage = LOS_ListRemoveHeadType(&pageList, LosVmPage, node))) {
1052         pa = vmPage->physAddr;
1053         LOS_AtomicInc(&vmPage->refCounts);
1054         ret = LOS_ArchMmuMap(&space->archMmu, va, pa, 1, region->regionFlags);
1055         if (ret != 1) {
1056             VM_ERR("LOS_ArchMmuMap failed!, err;%d", ret);
1057         }
1058         va += PAGE_SIZE;
1059     }
1060 
1061     (VOID)LOS_MuxRelease(&space->regionMux);
1062     return (VOID *)(UINTPTR)region->range.base;
1063 
1064 ERROR:
1065     (VOID)LOS_PhysPagesFree(&pageList);
1066     (VOID)LOS_MuxRelease(&space->regionMux);
1067     return NULL;
1068 }
1069 
1070 VOID LOS_VFree(const VOID *addr)
1071 {
1072     LosVmSpace *space = &g_vMallocSpace;
1073     LosVmMapRegion *region = NULL;
1074     STATUS_T ret;
1075 
1076     if (addr == NULL) {
1077         VM_ERR("addr is NULL!");
1078         return;
1079     }
1080 
1081     (VOID)LOS_MuxAcquire(&space->regionMux);
1082 
1083     region = LOS_RegionFind(space, (VADDR_T)(UINTPTR)addr);
1084     if (region == NULL) {
1085         VM_ERR("find region failed");
1086         goto DONE;
1087     }
1088 
1089     ret = LOS_RegionFree(space, region);
1090     if (ret) {
1091         VM_ERR("free region failed, ret = %d", ret);
1092     }
1093 
1094 DONE:
1095     (VOID)LOS_MuxRelease(&space->regionMux);
1096 }
1097 
1098 LosMux *OsGVmSpaceMuxGet(VOID)
1099 {
1100     return &g_vmSpaceListMux;
1101 }
1102 
1103 STATIC INLINE BOOL OsMemLargeAlloc(UINT32 size)
1104 {
1105     if (g_kHeapInited == FALSE) {
1106         return FALSE;
1107     }
1108 
1109     if (size < KMALLOC_LARGE_SIZE) {
1110         return FALSE;
1111     }
1112 
1113     return TRUE;
1114 }
1115 #else
1116 PADDR_T LOS_PaddrQuery(VOID *vaddr)
1117 {
1118     if (!LOS_IsKernelAddress((VADDR_T)vaddr)) {
1119         return 0;
1120     }
1121 
1122     return (PADDR_T)VMM_TO_DMA_ADDR((VADDR_T)vaddr);
1123 }
1124 #endif
1125 
1126 VOID *LOS_KernelMalloc(UINT32 size)
1127 {
1128     VOID *ptr = NULL;
1129 
1130 #ifdef LOSCFG_KERNEL_VM
1131     if (OsMemLargeAlloc(size)) {
1132         ptr = LOS_PhysPagesAllocContiguous(ROUNDUP(size, PAGE_SIZE) >> PAGE_SHIFT);
1133     } else
1134 #endif
1135     {
1136         ptr = LOS_MemAlloc(OS_SYS_MEM_ADDR, size);
1137     }
1138 
1139     return ptr;
1140 }
1141 
1142 VOID *LOS_KernelMallocAlign(UINT32 size, UINT32 boundary)
1143 {
1144     VOID *ptr = NULL;
1145 
1146 #ifdef LOSCFG_KERNEL_VM
1147     if (OsMemLargeAlloc(size) && IS_ALIGNED(PAGE_SIZE, boundary)) {
1148         ptr = LOS_PhysPagesAllocContiguous(ROUNDUP(size, PAGE_SIZE) >> PAGE_SHIFT);
1149     } else
1150 #endif
1151     {
1152         ptr = LOS_MemAllocAlign(OS_SYS_MEM_ADDR, size, boundary);
1153     }
1154 
1155     return ptr;
1156 }
1157 
1158 VOID *LOS_KernelRealloc(VOID *ptr, UINT32 size)
1159 {
1160     VOID *tmpPtr = NULL;
1161 
1162 #ifdef LOSCFG_KERNEL_VM
1163     LosVmPage *page = NULL;
1164     errno_t ret;
1165     if (ptr == NULL) {
1166         tmpPtr = LOS_KernelMalloc(size);
1167     } else {
1168         if (OsMemIsHeapNode(ptr) == FALSE) {
1169             page = OsVmVaddrToPage(ptr);
1170             if (page == NULL) {
1171                 VM_ERR("page of ptr(%#x) is null", ptr);
1172                 return NULL;
1173             }
1174             tmpPtr = LOS_KernelMalloc(size);
1175             if (tmpPtr == NULL) {
1176                 VM_ERR("alloc memory failed");
1177                 return NULL;
1178             }
1179             ret = memcpy_s(tmpPtr, size, ptr, page->nPages << PAGE_SHIFT);
1180             if (ret != EOK) {
1181                 LOS_KernelFree(tmpPtr);
1182                 VM_ERR("KernelRealloc memcpy error");
1183                 return NULL;
1184             }
1185             OsMemLargeNodeFree(ptr);
1186         } else {
1187             tmpPtr = LOS_MemRealloc(OS_SYS_MEM_ADDR, ptr, size);
1188         }
1189     }
1190 #else
1191     tmpPtr = LOS_MemRealloc(OS_SYS_MEM_ADDR, ptr, size);
1192 #endif
1193 
1194     return tmpPtr;
1195 }
1196 
1197 VOID LOS_KernelFree(VOID *ptr)
1198 {
1199 #ifdef LOSCFG_KERNEL_VM
1200     UINT32 ret;
1201     if (OsMemIsHeapNode(ptr) == FALSE) {
1202         ret = OsMemLargeNodeFree(ptr);
1203         if (ret != LOS_OK) {
1204             VM_ERR("KernelFree %p failed", ptr);
1205             return;
1206         }
1207     } else
1208 #endif
1209     {
1210         (VOID)LOS_MemFree(OS_SYS_MEM_ADDR, ptr);
1211     }
1212 }
1213