mm-stat.c 4.8 KB

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