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