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