1 /** 2 * @file mm-stat.c 3 * @author longjin(longjin@RinGoTek.cn) 4 * @brief 查询内存信息 5 * @version 0.1 6 * @date 2022-08-06 7 * 8 * @copyright Copyright (c) 2022 9 * 10 */ 11 12 #include "mm.h" 13 #include "slab.h" 14 #include <common/errno.h> 15 #include <process/ptrace.h> 16 17 extern const struct slab kmalloc_cache_group[16]; 18 19 static int __empty_2m_pages(int zone); 20 static int __count_in_using_2m_pages(int zone); 21 static uint64_t __count_kmalloc_free(); 22 static uint64_t __count_kmalloc_using(); 23 static uint64_t __count_kmalloc_total(); 24 uint64_t sys_mm_stat(struct pt_regs *regs); 25 26 /** 27 * @brief 获取指定zone中的空闲2M页的数量 28 * 29 * @param zone 内存zone号 30 * @return int 空闲2M页数量 31 */ __count_empty_2m_pages(int zone)32static int __count_empty_2m_pages(int zone) 33 { 34 int zone_start = 0, zone_end = 0; 35 36 uint64_t attr = 0; 37 switch (zone) 38 { 39 case ZONE_DMA: 40 // DMA区域 41 zone_start = 0; 42 zone_end = ZONE_DMA_INDEX; 43 attr |= PAGE_PGT_MAPPED; 44 break; 45 case ZONE_NORMAL: 46 zone_start = ZONE_DMA_INDEX; 47 zone_end = ZONE_NORMAL_INDEX; 48 attr |= PAGE_PGT_MAPPED; 49 break; 50 case ZONE_UNMAPPED_IN_PGT: 51 zone_start = ZONE_NORMAL_INDEX; 52 zone_end = ZONE_UNMAPPED_INDEX; 53 attr = 0; 54 break; 55 default: 56 kerror("In __count_empty_2m_pages: param: zone invalid."); 57 // 返回错误码 58 return -EINVAL; 59 break; 60 } 61 62 uint64_t result = 0; 63 for (int i = zone_start; i <= zone_end; ++i) 64 { 65 result += (memory_management_struct.zones_struct + i)->count_pages_free; 66 } 67 return result; 68 } 69 70 /** 71 * @brief 获取指定zone中的正在使用的2M页的数量 72 * 73 * @param zone 内存zone号 74 * @return int 空闲2M页数量 75 */ __count_in_using_2m_pages(int zone)76static int __count_in_using_2m_pages(int zone) 77 { 78 int zone_start = 0, zone_end = 0; 79 80 uint64_t attr = 0; 81 switch (zone) 82 { 83 case ZONE_DMA: 84 // DMA区域 85 zone_start = 0; 86 zone_end = ZONE_DMA_INDEX; 87 attr |= PAGE_PGT_MAPPED; 88 break; 89 case ZONE_NORMAL: 90 zone_start = ZONE_DMA_INDEX; 91 zone_end = ZONE_NORMAL_INDEX; 92 attr |= PAGE_PGT_MAPPED; 93 break; 94 case ZONE_UNMAPPED_IN_PGT: 95 zone_start = ZONE_NORMAL_INDEX; 96 zone_end = ZONE_UNMAPPED_INDEX; 97 attr = 0; 98 break; 99 default: 100 kerror("In __count_in_using_2m_pages: param: zone invalid."); 101 // 返回错误码 102 return -EINVAL; 103 break; 104 } 105 106 uint64_t result = 0; 107 for (int i = zone_start; i <= zone_end; ++i) 108 { 109 result += (memory_management_struct.zones_struct + i)->count_pages_using; 110 } 111 return result; 112 } 113 114 /** 115 * @brief 计算kmalloc缓冲区中的空闲内存 116 * 117 * @return uint64_t 空闲内存(字节) 118 */ __count_kmalloc_free()119static uint64_t __count_kmalloc_free() 120 { 121 uint64_t result = 0; 122 for (int i = 0; i < sizeof(kmalloc_cache_group) / sizeof(struct slab); ++i) 123 { 124 result += kmalloc_cache_group[i].size * kmalloc_cache_group[i].count_total_free; 125 } 126 return result; 127 } 128 129 /** 130 * @brief 计算kmalloc缓冲区中已使用的内存 131 * 132 * @return uint64_t 已使用的内存(字节) 133 */ __count_kmalloc_using()134static uint64_t __count_kmalloc_using() 135 { 136 uint64_t result = 0; 137 for (int i = 0; i < sizeof(kmalloc_cache_group) / sizeof(struct slab); ++i) 138 { 139 result += kmalloc_cache_group[i].size * kmalloc_cache_group[i].count_total_using; 140 } 141 return result; 142 } 143 144 /** 145 * @brief 计算kmalloc缓冲区中总共占用的内存 146 * 147 * @return uint64_t 缓冲区占用的内存(字节) 148 */ __count_kmalloc_total()149static uint64_t __count_kmalloc_total() 150 { 151 uint64_t result = 0; 152 for (int i = 0; i < sizeof(kmalloc_cache_group) / sizeof(struct slab); ++i) 153 { 154 result += kmalloc_cache_group[i].size * (kmalloc_cache_group[i].count_total_free + kmalloc_cache_group[i].count_total_using); 155 } 156 return result; 157 } 158 159 /** 160 * @brief 获取系统当前的内存信息(未上锁,不一定精准) 161 * 162 * @return struct mm_stat_t 内存信息结构体 163 */ mm_stat()164struct mm_stat_t mm_stat() 165 { 166 struct mm_stat_t tmp = {0}; 167 // 统计物理页的信息 168 tmp.used = __count_in_using_2m_pages(ZONE_NORMAL) * PAGE_2M_SIZE; 169 tmp.free = __count_empty_2m_pages(ZONE_NORMAL) * PAGE_2M_SIZE; 170 tmp.total = tmp.used + tmp.free; 171 tmp.shared = 0; 172 // 统计kmalloc slab中的信息 173 tmp.cache_free = __count_kmalloc_free(); 174 tmp.cache_used = __count_kmalloc_using(); 175 tmp.available = tmp.free + tmp.cache_free; 176 return tmp; 177 } 178 179 /** 180 * @brief 获取内存信息的系统调用 181 * 182 * @param r8 返回的内存信息结构体的地址 183 * @return uint64_t 184 */ sys_mstat(struct pt_regs * regs)185uint64_t sys_mstat(struct pt_regs *regs) 186 { 187 if (regs->r8 == NULL) 188 return -EINVAL; 189 struct mm_stat_t stat = mm_stat(); 190 if (regs->cs == (USER_CS | 0x3)) 191 copy_to_user((void *)regs->r8, &stat, sizeof(struct mm_stat_t)); 192 else 193 memcpy((void *)regs->r8, &stat, sizeof(struct mm_stat_t)); 194 return 0; 195 }