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