vma.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. #include "mm.h"
  2. #include "slab.h"
  3. #include "internal.h"
  4. /**
  5. * @brief 获取一块新的vma结构体,并将其与指定的mm进行绑定
  6. *
  7. * @param mm 与VMA绑定的内存空间分布结构体
  8. * @return struct vm_area_struct* 新的VMA
  9. */
  10. struct vm_area_struct *vm_area_alloc(struct mm_struct *mm)
  11. {
  12. struct vm_area_struct *vma = (struct vm_area_struct *)kmalloc(sizeof(struct vm_area_struct), 0);
  13. if (vma)
  14. vma_init(vma, mm);
  15. return vma;
  16. }
  17. /**
  18. * @brief 从链表中删除指定的vma结构体
  19. *
  20. * @param vma
  21. */
  22. void vm_area_del(struct vm_area_struct *vma)
  23. {
  24. if (vma->vm_mm == NULL)
  25. return;
  26. __vma_unlink_list(vma->vm_mm, vma);
  27. }
  28. /**
  29. * @brief 释放vma结构体
  30. *
  31. * @param vma 待释放的vma结构体
  32. */
  33. void vm_area_free(struct vm_area_struct *vma)
  34. {
  35. if (vma->vm_prev == NULL && vma->vm_next == NULL) // 如果当前是剩余的最后一个vma
  36. vma->vm_mm->vmas = NULL;
  37. kfree(vma);
  38. }
  39. /**
  40. * @brief 将vma结构体插入mm_struct的链表之中
  41. *
  42. * @param mm 内存空间分布结构体
  43. * @param vma 待插入的VMA结构体
  44. * @param prev 链表的前一个结点
  45. */
  46. void __vma_link_list(struct mm_struct *mm, struct vm_area_struct *vma, struct vm_area_struct *prev)
  47. {
  48. struct vm_area_struct *next = NULL;
  49. vma->vm_prev = prev;
  50. if (prev) // 若指定了前一个结点,则直接连接
  51. {
  52. next = prev->vm_next;
  53. prev->vm_next = vma;
  54. }
  55. else // 否则将vma直接插入到给定的mm的vma链表之中
  56. {
  57. next = mm->vmas;
  58. mm->vmas = vma;
  59. }
  60. vma->vm_next = next;
  61. if (next != NULL)
  62. next->vm_prev = vma;
  63. }
  64. /**
  65. * @brief 将vma给定结构体从vma链表的结点之中删除
  66. *
  67. * @param mm 内存空间分布结构体
  68. * @param vma 待插入的VMA结构体
  69. */
  70. void __vma_unlink_list(struct mm_struct *mm, struct vm_area_struct *vma)
  71. {
  72. struct vm_area_struct *prev, *next;
  73. next = vma->vm_next;
  74. prev = vma->vm_prev;
  75. if (prev)
  76. prev->vm_next = next;
  77. else // 当前vma是链表中的第一个vma
  78. mm->vmas = next;
  79. if (next)
  80. next->vm_prev = prev;
  81. }
  82. /**
  83. * @brief 查找第一个符合“addr < vm_end”条件的vma
  84. *
  85. * @param mm 内存空间分布结构体
  86. * @param addr 虚拟地址
  87. * @return struct vm_area_struct* 符合条件的vma
  88. */
  89. struct vm_area_struct *vma_find(struct mm_struct *mm, uint64_t addr)
  90. {
  91. struct vm_area_struct *vma = mm->vmas;
  92. struct vm_area_struct *result = NULL;
  93. while (vma != NULL)
  94. {
  95. if (vma->vm_end > addr)
  96. {
  97. result = vma;
  98. break;
  99. }
  100. vma = vma->vm_next;
  101. }
  102. return result;
  103. }
  104. /**
  105. * @brief 插入vma
  106. *
  107. * @param mm
  108. * @param vma
  109. * @return int
  110. */
  111. int vma_insert(struct mm_struct *mm, struct vm_area_struct *vma)
  112. {
  113. struct vm_area_struct *prev;
  114. prev = vma_find(mm, vma->vm_start);
  115. if (prev && prev->vm_start <= vma->vm_start && prev->vm_end >= vma->vm_end)
  116. {
  117. // 已经存在了相同的vma
  118. return -EEXIST;
  119. }
  120. else if (prev && (prev->vm_start == vma->vm_start || prev->vm_end == vma->vm_end)) // 暂时不支持扩展vma
  121. {
  122. kwarn("Not support: expand vma");
  123. return -ENOTSUP;
  124. }
  125. prev = vma_find(mm, vma->vm_end);
  126. if (prev)
  127. prev = prev->vm_prev;
  128. if (prev == NULL) // 要将当前vma插入到链表的尾部
  129. {
  130. struct vm_area_struct *ptr = mm->vmas;
  131. while (ptr)
  132. {
  133. if (ptr->vm_next)
  134. ptr = ptr->vm_next;
  135. else
  136. {
  137. prev = ptr;
  138. break;
  139. }
  140. }
  141. }
  142. __vma_link_list(mm, vma, prev);
  143. return 0;
  144. }
  145. /**
  146. * @brief 创建anon_vma,并将其与页面结构体进行绑定
  147. * 若提供的页面结构体指针为NULL,则只创建,不绑定
  148. *
  149. * @param page 页面结构体的指针
  150. * @param lock_page 是否将页面结构体加锁
  151. * @return struct anon_vma_t* 创建好的anon_vma
  152. */
  153. struct anon_vma_t *__anon_vma_create_alloc(struct Page *page, bool lock_page)
  154. {
  155. struct anon_vma_t *anon_vma = (struct anon_vma_t *)kmalloc(sizeof(struct anon_vma_t), 0);
  156. if (unlikely(anon_vma == NULL))
  157. return NULL;
  158. memset(anon_vma, 0, sizeof(struct anon_vma_t));
  159. list_init(&anon_vma->vma_list);
  160. semaphore_init(&anon_vma->sem, 1);
  161. // 需要和page进行绑定
  162. if (page != NULL)
  163. {
  164. if (lock_page == true) // 需要加锁
  165. {
  166. uint64_t rflags;
  167. spin_lock(&page->op_lock);
  168. page->anon_vma = anon_vma;
  169. spin_unlock(&page->op_lock);
  170. }
  171. else
  172. page->anon_vma = anon_vma;
  173. anon_vma->page = page;
  174. }
  175. return anon_vma;
  176. }
  177. /**
  178. * @brief 将指定的vma加入到anon_vma的管理范围之中
  179. *
  180. * @param anon_vma 页面的anon_vma
  181. * @param vma 待加入的vma
  182. * @return int 返回码
  183. */
  184. int __anon_vma_add(struct anon_vma_t *anon_vma, struct vm_area_struct *vma)
  185. {
  186. semaphore_down(&anon_vma->sem);
  187. list_add(&anon_vma->vma_list, &vma->anon_vma_list);
  188. vma->anon_vma = anon_vma;
  189. atomic_inc(&anon_vma->ref_count);
  190. semaphore_up(&anon_vma->sem);
  191. return 0;
  192. }
  193. /**
  194. * @brief 释放anon vma结构体
  195. *
  196. * @param anon_vma 待释放的anon_vma结构体
  197. * @return int 返回码
  198. */
  199. int __anon_vma_free(struct anon_vma_t *anon_vma)
  200. {
  201. if (anon_vma->page != NULL)
  202. {
  203. spin_lock(&anon_vma->page->op_lock);
  204. anon_vma->page->anon_vma = NULL;
  205. spin_unlock(&anon_vma->page->op_lock);
  206. }
  207. kfree(anon_vma);
  208. return 0;
  209. }
  210. /**
  211. * @brief 从anon_vma的管理范围中删除指定的vma
  212. * (在进入这个函数之前,应该要对anon_vma加锁)
  213. * @param vma 将要取消对应的anon_vma管理的vma结构体
  214. * @return int 返回码
  215. */
  216. int __anon_vma_del(struct vm_area_struct *vma)
  217. {
  218. // 当前vma没有绑定anon_vma
  219. if (vma->anon_vma == NULL)
  220. return -EINVAL;
  221. list_del(&vma->anon_vma_list);
  222. atomic_dec(&vma->anon_vma->ref_count);
  223. // 若当前anon_vma的引用计数归零,则意味着可以释放内存页
  224. if (unlikely(atomic_read(&vma->anon_vma->ref_count) == 0)) // 应当释放该anon_vma
  225. {
  226. // 若页面结构体是mmio创建的,则释放页面结构体
  227. if (vma->anon_vma->page->attr & PAGE_DEVICE)
  228. kfree(vma->anon_vma->page);
  229. else
  230. free_pages(vma->anon_vma->page, 1);
  231. __anon_vma_free(vma->anon_vma);
  232. }
  233. // 清理当前vma的关联数据
  234. vma->anon_vma = NULL;
  235. list_init(&vma->anon_vma_list);
  236. }