• 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 /**
33  * @defgroup los_vm_dump virtual memory dump operation
34  * @ingroup kernel
35  */
36 
37 #include "los_vm_dump.h"
38 #include "los_mmu_descriptor_v6.h"
39 #ifdef LOSCFG_FS_VFS
40 #include "fs/file.h"
41 #include "vnode.h"
42 #endif
43 #include "los_printf.h"
44 #include "los_vm_page.h"
45 #include "los_vm_phys.h"
46 #include "los_process_pri.h"
47 #include "los_atomic.h"
48 #include "los_vm_lock.h"
49 #include "los_memory_pri.h"
50 
51 
52 #ifdef LOSCFG_KERNEL_VM
53 
54 #define     FLAG_SIZE               4
55 #define     FLAG_START              2
56 
OsGetRegionNameOrFilePath(LosVmMapRegion * region)57 const CHAR *OsGetRegionNameOrFilePath(LosVmMapRegion *region)
58 {
59     struct Vnode *vnode = NULL;
60     if (region == NULL) {
61         return "";
62 #ifdef LOSCFG_FS_VFS
63     } else if (LOS_IsRegionFileValid(region)) {
64         vnode = region->unTypeData.rf.vnode;
65         return vnode->filePath;
66 #endif
67     } else if (region->regionFlags & VM_MAP_REGION_FLAG_HEAP) {
68         return "HEAP";
69     } else if (region->regionFlags & VM_MAP_REGION_FLAG_STACK) {
70         return "STACK";
71     } else if (region->regionFlags & VM_MAP_REGION_FLAG_TEXT) {
72         return "Text";
73     } else if (region->regionFlags & VM_MAP_REGION_FLAG_VDSO) {
74         return "VDSO";
75     } else if (region->regionFlags & VM_MAP_REGION_FLAG_MMAP) {
76         return "MMAP";
77     } else if (region->regionFlags & VM_MAP_REGION_FLAG_SHM) {
78         return "SHM";
79     } else {
80         return "";
81     }
82     return "";
83 }
84 
OsRegionOverlapCheckUnlock(LosVmSpace * space,LosVmMapRegion * region)85 INT32 OsRegionOverlapCheckUnlock(LosVmSpace *space, LosVmMapRegion *region)
86 {
87     LosVmMapRegion *regionTemp = NULL;
88     LosRbNode *pstRbNode = NULL;
89     LosRbNode *pstRbNodeNext = NULL;
90 
91     /* search the region list */
92     RB_SCAN_SAFE(&space->regionRbTree, pstRbNode, pstRbNodeNext)
93         regionTemp = (LosVmMapRegion *)pstRbNode;
94         if (region->range.base == regionTemp->range.base && region->range.size == regionTemp->range.size) {
95             continue;
96         }
97         if (((region->range.base + region->range.size) > regionTemp->range.base) &&
98             (region->range.base < (regionTemp->range.base + regionTemp->range.size))) {
99             VM_ERR("overlap between regions:\n"
100                    "flags:%#x base:%p size:%08x space:%p\n"
101                    "flags:%#x base:%p size:%08x space:%p",
102                    region->regionFlags, region->range.base, region->range.size, region->space,
103                    regionTemp->regionFlags, regionTemp->range.base, regionTemp->range.size, regionTemp->space);
104             return -1;
105         }
106     RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNode, pstRbNodeNext)
107 
108     return 0;
109 }
110 
OsShellCmdProcessVmUsage(LosVmSpace * space)111 UINT32 OsShellCmdProcessVmUsage(LosVmSpace *space)
112 {
113     LosVmMapRegion *region = NULL;
114     LosRbNode *pstRbNode = NULL;
115     LosRbNode *pstRbNodeNext = NULL;
116     UINT32 used = 0;
117 
118     if (space == NULL) {
119         return 0;
120     }
121 
122     if (space == LOS_GetKVmSpace()) {
123         OsShellCmdProcessPmUsage(space, NULL, &used);
124         return used;
125     }
126     UINT32 ret = LOS_MuxAcquire(&space->regionMux);
127     if (ret != 0) {
128         return 0;
129     }
130 
131     RB_SCAN_SAFE(&space->regionRbTree, pstRbNode, pstRbNodeNext)
132         region = (LosVmMapRegion *)pstRbNode;
133         used += region->range.size;
134     RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNode, pstRbNodeNext)
135     (VOID)LOS_MuxRelease(&space->regionMux);
136     return used;
137 }
138 
OsKProcessPmUsage(LosVmSpace * kSpace,UINT32 * actualPm)139 UINT32 OsKProcessPmUsage(LosVmSpace *kSpace, UINT32 *actualPm)
140 {
141     UINT32 memUsed;
142     UINT32 totalMem;
143     UINT32 freeMem;
144     UINT32 usedCount = 0;
145     UINT32 totalCount = 0;
146     LosVmSpace *space = NULL;
147     LOS_DL_LIST *spaceList = NULL;
148     UINT32 UProcessUsed = 0;
149 
150     if (actualPm == NULL) {
151         return 0;
152     }
153 
154     memUsed = LOS_MemTotalUsedGet(m_aucSysMem1);
155     totalMem = LOS_MemPoolSizeGet(m_aucSysMem1);
156     freeMem = totalMem - memUsed;
157 
158     OsVmPhysUsedInfoGet(&usedCount, &totalCount);
159     /* Kernel resident memory, include default heap memory */
160     memUsed = SYS_MEM_SIZE_DEFAULT - (totalCount << PAGE_SHIFT);
161 
162     spaceList = LOS_GetVmSpaceList();
163     LosMux *vmSpaceListMux = OsGVmSpaceMuxGet();
164     (VOID)LOS_MuxAcquire(vmSpaceListMux);
165     LOS_DL_LIST_FOR_EACH_ENTRY(space, spaceList, LosVmSpace, node) {
166         if (space == LOS_GetKVmSpace()) {
167             continue;
168         }
169         UProcessUsed += OsUProcessPmUsage(space, NULL, NULL);
170     }
171     (VOID)LOS_MuxRelease(vmSpaceListMux);
172 
173     /* Kernel dynamic memory, include extended heap memory */
174     memUsed += ((usedCount << PAGE_SHIFT) - UProcessUsed);
175     /* Remaining heap memory */
176     memUsed -= freeMem;
177 
178     *actualPm = memUsed;
179     return memUsed;
180 }
181 
OsShellCmdProcessPmUsage(LosVmSpace * space,UINT32 * sharePm,UINT32 * actualPm)182 UINT32 OsShellCmdProcessPmUsage(LosVmSpace *space, UINT32 *sharePm, UINT32 *actualPm)
183 {
184     if (space == NULL) {
185         return 0;
186     }
187 
188     if ((sharePm == NULL) && (actualPm == NULL)) {
189         return 0;
190     }
191 
192     if (space == LOS_GetKVmSpace()) {
193         return OsKProcessPmUsage(space, actualPm);
194     }
195     return OsUProcessPmUsage(space, sharePm, actualPm);
196 }
197 
OsUProcessPmUsage(LosVmSpace * space,UINT32 * sharePm,UINT32 * actualPm)198 UINT32 OsUProcessPmUsage(LosVmSpace *space, UINT32 *sharePm, UINT32 *actualPm)
199 {
200     LosVmMapRegion *region = NULL;
201     LosRbNode *pstRbNode = NULL;
202     LosRbNode *pstRbNodeNext = NULL;
203     LosVmPage *page = NULL;
204     VADDR_T vaddr;
205     size_t size;
206     PADDR_T paddr;
207     STATUS_T ret;
208     INT32 shareRef;
209     UINT32 pmSize = 0;
210 
211     if (sharePm != NULL) {
212         *sharePm = 0;
213     }
214 
215     ret = LOS_MuxAcquire(&space->regionMux);
216     if (ret != 0) {
217         return 0;
218     }
219     RB_SCAN_SAFE(&space->regionRbTree, pstRbNode, pstRbNodeNext)
220         region = (LosVmMapRegion *)pstRbNode;
221         vaddr = region->range.base;
222         size = region->range.size;
223         for (; size > 0; vaddr += PAGE_SIZE, size -= PAGE_SIZE) {
224             ret = LOS_ArchMmuQuery(&space->archMmu, vaddr, &paddr, NULL);
225             if (ret < 0) {
226                 continue;
227             }
228             page = LOS_VmPageGet(paddr);
229             if (page == NULL) {
230                 continue;
231             }
232 
233             shareRef = LOS_AtomicRead(&page->refCounts);
234             if (shareRef > 1) {
235                 if (sharePm != NULL) {
236                     *sharePm += PAGE_SIZE;
237                 }
238                 pmSize += PAGE_SIZE / shareRef;
239             } else {
240                 pmSize += PAGE_SIZE;
241             }
242         }
243     RB_SCAN_SAFE_END(&oldVmSpace->regionRbTree, pstRbNode, pstRbNodeNext)
244 
245     (VOID)LOS_MuxRelease(&space->regionMux);
246 
247     if (actualPm != NULL) {
248         *actualPm = pmSize;
249     }
250 
251     return pmSize;
252 }
253 
OsGetPIDByAspace(const LosVmSpace * space)254 LosProcessCB *OsGetPIDByAspace(const LosVmSpace *space)
255 {
256     UINT32 pid;
257     UINT32 intSave;
258     LosProcessCB *processCB = NULL;
259 
260     SCHEDULER_LOCK(intSave);
261     for (pid = 0; pid < g_processMaxNum; ++pid) {
262         processCB = g_processCBArray + pid;
263         if (OsProcessIsUnused(processCB)) {
264             continue;
265         }
266 
267         if (processCB->vmSpace == space) {
268             SCHEDULER_UNLOCK(intSave);
269             return processCB;
270         }
271     }
272     SCHEDULER_UNLOCK(intSave);
273     return NULL;
274 }
275 
OsCountRegionPages(LosVmSpace * space,LosVmMapRegion * region,UINT32 * pssPages)276 UINT32 OsCountRegionPages(LosVmSpace *space, LosVmMapRegion *region, UINT32 *pssPages)
277 {
278     UINT32 regionPages = 0;
279     PADDR_T paddr;
280     VADDR_T vaddr;
281     UINT32 ref;
282     STATUS_T status;
283     float pss = 0;
284     LosVmPage *page = NULL;
285 
286     for (vaddr = region->range.base; vaddr < region->range.base + region->range.size; vaddr = vaddr + PAGE_SIZE) {
287         status = LOS_ArchMmuQuery(&space->archMmu, vaddr, &paddr, NULL);
288         if (status == LOS_OK) {
289             regionPages++;
290             if (pssPages == NULL) {
291                 continue;
292             }
293             page = LOS_VmPageGet(paddr);
294             if (page != NULL) {
295                 ref = LOS_AtomicRead(&page->refCounts);
296                 pss += ((ref > 0) ? (1.0 / ref) : 1);
297             } else {
298                 pss += 1;
299             }
300         }
301     }
302 
303     if (pssPages != NULL) {
304         *pssPages = (UINT32)(pss + 0.5);    /* 0.5, for page alignment */
305     }
306 
307     return regionPages;
308 }
309 
OsCountAspacePages(LosVmSpace * space)310 UINT32 OsCountAspacePages(LosVmSpace *space)
311 {
312     UINT32 spacePages = 0;
313     LosVmMapRegion *region = NULL;
314     LosRbNode *pstRbNode = NULL;
315     LosRbNode *pstRbNodeNext = NULL;
316 
317     RB_SCAN_SAFE(&space->regionRbTree, pstRbNode, pstRbNodeNext)
318         region = (LosVmMapRegion *)pstRbNode;
319         spacePages += OsCountRegionPages(space, region, NULL);
320     RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNode, pstRbNodeNext)
321     return spacePages;
322 }
323 
OsArchFlagsToStr(const UINT32 archFlags)324 CHAR *OsArchFlagsToStr(const UINT32 archFlags)
325 {
326     UINT32 index;
327     UINT32 cacheFlags = archFlags & VM_MAP_REGION_FLAG_CACHE_MASK;
328     UINT32 flagSize = FLAG_SIZE * BITMAP_BITS_PER_WORD * sizeof(CHAR);
329     CHAR *archMmuFlagsStr = (CHAR *)LOS_MemAlloc(m_aucSysMem0, flagSize);
330     if (archMmuFlagsStr == NULL) {
331         return NULL;
332     }
333     (VOID)memset_s(archMmuFlagsStr, flagSize, 0, flagSize);
334     switch (cacheFlags) {
335         case 0UL:
336             (VOID)strcat_s(archMmuFlagsStr, flagSize, " CH\0");
337             break;
338         case 1UL:
339             (VOID)strcat_s(archMmuFlagsStr, flagSize, " UC\0");
340             break;
341         case 2UL:
342             (VOID)strcat_s(archMmuFlagsStr, flagSize, " UD\0");
343             break;
344         case 3UL:
345             (VOID)strcat_s(archMmuFlagsStr, flagSize, " WC\0");
346             break;
347         default:
348             break;
349     }
350 
351     static const CHAR FLAGS[BITMAP_BITS_PER_WORD][FLAG_SIZE] = {
352         [0 ... (__builtin_ffsl(VM_MAP_REGION_FLAG_PERM_USER) - 2)] = "???\0",
353         [__builtin_ffsl(VM_MAP_REGION_FLAG_PERM_USER) - 1] = " US\0",
354         [__builtin_ffsl(VM_MAP_REGION_FLAG_PERM_READ) - 1] = " RD\0",
355         [__builtin_ffsl(VM_MAP_REGION_FLAG_PERM_WRITE) - 1] = " WR\0",
356         [__builtin_ffsl(VM_MAP_REGION_FLAG_PERM_EXECUTE) - 1] = " EX\0",
357         [__builtin_ffsl(VM_MAP_REGION_FLAG_NS) - 1] = " NS\0",
358         [__builtin_ffsl(VM_MAP_REGION_FLAG_INVALID) - 1] = " IN\0",
359         [__builtin_ffsl(VM_MAP_REGION_FLAG_INVALID) ... (BITMAP_BITS_PER_WORD - 1)] = "???\0",
360     };
361 
362     for (index = FLAG_START; index < BITMAP_BITS_PER_WORD; index++) {
363         if (FLAGS[index][0] == '?') {
364             continue;
365         }
366 
367         if (archFlags & (1UL << index)) {
368             UINT32 status = strcat_s(archMmuFlagsStr, flagSize, FLAGS[index]);
369             if (status != 0) {
370                 PRINTK("error\n");
371             }
372         }
373     }
374 
375     return archMmuFlagsStr;
376 }
377 
OsDumpRegion2(LosVmSpace * space,LosVmMapRegion * region)378 VOID OsDumpRegion2(LosVmSpace *space, LosVmMapRegion *region)
379 {
380     UINT32 pssPages = 0;
381     UINT32 regionPages;
382 
383     regionPages = OsCountRegionPages(space, region, &pssPages);
384     CHAR *flagsStr = OsArchFlagsToStr(region->regionFlags);
385     if (flagsStr == NULL) {
386         return;
387     }
388     PRINTK("\t %#010x  %-32.32s %#010x %#010x %-15.15s %4d    %4d\n",
389         region, OsGetRegionNameOrFilePath(region), region->range.base,
390         region->range.size, flagsStr, regionPages, pssPages);
391     (VOID)LOS_MemFree(m_aucSysMem0, flagsStr);
392 }
393 
OsDumpAspace(LosVmSpace * space)394 VOID OsDumpAspace(LosVmSpace *space)
395 {
396     LosVmMapRegion *region = NULL;
397     LosRbNode *pstRbNode = NULL;
398     LosRbNode *pstRbNodeNext = NULL;
399     UINT32 spacePages;
400     LosProcessCB *pcb = OsGetPIDByAspace(space);
401 
402     if (pcb == NULL) {
403         return;
404     }
405 
406     spacePages = OsCountAspacePages(space);
407     PRINTK("\r\n PID    aspace     name       base       size     pages \n");
408     PRINTK(" ----   ------     ----       ----       -----     ----\n");
409     PRINTK(" %-4d %#010x %-10.10s %#010x %#010x     %d\n", pcb->processID, space, pcb->processName,
410         space->base, space->size, spacePages);
411     PRINTK("\r\n\t region      name                base       size       mmu_flags      pages   pg/ref\n");
412     PRINTK("\t ------      ----                ----       ----       ---------      -----   -----\n");
413     RB_SCAN_SAFE(&space->regionRbTree, pstRbNode, pstRbNodeNext)
414         region = (LosVmMapRegion *)pstRbNode;
415         if (region != NULL) {
416             OsDumpRegion2(space, region);
417             (VOID)OsRegionOverlapCheck(space, region);
418         } else {
419             PRINTK("region is NULL\n");
420         }
421     RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNode, pstRbNodeNext)
422     return;
423 }
424 
OsDumpAllAspace(VOID)425 VOID OsDumpAllAspace(VOID)
426 {
427     LosVmSpace *space = NULL;
428     LOS_DL_LIST *aspaceList = LOS_GetVmSpaceList();
429     LOS_DL_LIST_FOR_EACH_ENTRY(space, aspaceList, LosVmSpace, node) {
430         (VOID)LOS_MuxAcquire(&space->regionMux);
431         OsDumpAspace(space);
432         (VOID)LOS_MuxRelease(&space->regionMux);
433     }
434     return;
435 }
436 
OsRegionOverlapCheck(LosVmSpace * space,LosVmMapRegion * region)437 STATUS_T OsRegionOverlapCheck(LosVmSpace *space, LosVmMapRegion *region)
438 {
439     int ret;
440 
441     if (space == NULL || region == NULL) {
442         return -1;
443     }
444 
445     (VOID)LOS_MuxAcquire(&space->regionMux);
446     ret = OsRegionOverlapCheckUnlock(space, region);
447     (VOID)LOS_MuxRelease(&space->regionMux);
448     return ret;
449 }
450 
OsDumpPte(VADDR_T vaddr)451 VOID OsDumpPte(VADDR_T vaddr)
452 {
453     UINT32 l1Index = vaddr >> MMU_DESCRIPTOR_L1_SMALL_SHIFT;
454     LosVmSpace *space = LOS_SpaceGet(vaddr);
455     UINT32 ttEntry;
456     LosVmPage *page = NULL;
457     PTE_T *l2Table = NULL;
458     UINT32 l2Index;
459 
460     if (space == NULL) {
461         return;
462     }
463 
464     ttEntry = space->archMmu.virtTtb[l1Index];
465     if (ttEntry) {
466         l2Table = LOS_PaddrToKVaddr(MMU_DESCRIPTOR_L1_PAGE_TABLE_ADDR(ttEntry));
467         l2Index = (vaddr % MMU_DESCRIPTOR_L1_SMALL_SIZE) >> PAGE_SHIFT;
468         if (l2Table == NULL) {
469             goto ERR;
470         }
471         page = LOS_VmPageGet(l2Table[l2Index] & ~(PAGE_SIZE - 1));
472         if (page == NULL) {
473             goto ERR;
474         }
475         PRINTK("vaddr %p, l1Index %d, ttEntry %p, l2Table %p, l2Index %d, pfn %p count %d\n",
476                vaddr, l1Index, ttEntry, l2Table, l2Index, l2Table[l2Index], LOS_AtomicRead(&page->refCounts));
477     } else {
478         PRINTK("vaddr %p, l1Index %d, ttEntry %p\n", vaddr, l1Index, ttEntry);
479     }
480     return;
481 ERR:
482     PRINTK("%s, error vaddr: %#x, l2Table: %#x, l2Index: %#x\n", __FUNCTION__, vaddr, l2Table, l2Index);
483 }
484 
OsVmPhySegPagesGet(LosVmPhysSeg * seg)485 UINT32 OsVmPhySegPagesGet(LosVmPhysSeg *seg)
486 {
487     UINT32 intSave;
488     UINT32 flindex;
489     UINT32 segFreePages = 0;
490 
491     LOS_SpinLockSave(&seg->freeListLock, &intSave);
492     for (flindex = 0; flindex < VM_LIST_ORDER_MAX; flindex++) {
493         segFreePages += ((1 << flindex) * seg->freeList[flindex].listCnt);
494     }
495     LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
496 
497     return segFreePages;
498 }
499 
OsVmPhysDump(VOID)500 VOID OsVmPhysDump(VOID)
501 {
502     LosVmPhysSeg *seg = NULL;
503     UINT32 segFreePages;
504     UINT32 totalFreePages = 0;
505     UINT32 totalPages = 0;
506     UINT32 segIndex;
507     UINT32 intSave;
508     UINT32 flindex;
509     UINT32 listCount[VM_LIST_ORDER_MAX] = {0};
510 
511     for (segIndex = 0; segIndex < g_vmPhysSegNum; segIndex++) {
512         seg = &g_vmPhysSeg[segIndex];
513         if (seg->size > 0) {
514             segFreePages = OsVmPhySegPagesGet(seg);
515 #ifdef LOSCFG_SHELL_CMD_DEBUG
516             PRINTK("\r\n phys_seg      base         size        free_pages    \n");
517             PRINTK(" --------      -------      ----------  ---------  \n");
518 #endif
519             PRINTK(" 0x%08x    0x%08x   0x%08x   %8u  \n", seg, seg->start, seg->size, segFreePages);
520             totalFreePages += segFreePages;
521             totalPages += (seg->size >> PAGE_SHIFT);
522 
523             LOS_SpinLockSave(&seg->freeListLock, &intSave);
524             for (flindex = 0; flindex < VM_LIST_ORDER_MAX; flindex++) {
525                 listCount[flindex] = seg->freeList[flindex].listCnt;
526             }
527             LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
528             for (flindex = 0; flindex < VM_LIST_ORDER_MAX; flindex++) {
529                 PRINTK("order = %d, free_count = %d\n", flindex, listCount[flindex]);
530             }
531 
532             PRINTK("active   anon   %d\n", seg->lruSize[VM_LRU_ACTIVE_ANON]);
533             PRINTK("inactive anon   %d\n", seg->lruSize[VM_LRU_INACTIVE_ANON]);
534             PRINTK("active   file   %d\n", seg->lruSize[VM_LRU_ACTIVE_FILE]);
535             PRINTK("inactive file   %d\n", seg->lruSize[VM_LRU_INACTIVE_FILE]);
536         }
537     }
538     PRINTK("\n\rpmm pages: total = %u, used = %u, free = %u\n",
539            totalPages, (totalPages - totalFreePages), totalFreePages);
540 }
541 
OsVmPhysUsedInfoGet(UINT32 * usedCount,UINT32 * totalCount)542 VOID OsVmPhysUsedInfoGet(UINT32 *usedCount, UINT32 *totalCount)
543 {
544     UINT32 index;
545     UINT32 segFreePages;
546     LosVmPhysSeg *physSeg = NULL;
547 
548     if (usedCount == NULL || totalCount == NULL) {
549         return;
550     }
551     *usedCount = 0;
552     *totalCount = 0;
553 
554     for (index = 0; index < g_vmPhysSegNum; index++) {
555         physSeg = &g_vmPhysSeg[index];
556         if (physSeg->size > 0) {
557             *totalCount += physSeg->size >> PAGE_SHIFT;
558             segFreePages = OsVmPhySegPagesGet(physSeg);
559             *usedCount += (*totalCount - segFreePages);
560         }
561     }
562 }
563 #endif
564 
565