《操作系统》的实验代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

284 lines
7.6 KiB

  1. #include <swap.h>
  2. #include <swapfs.h>
  3. #include <swap_fifo.h>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <memlayout.h>
  7. #include <pmm.h>
  8. #include <mmu.h>
  9. #include <default_pmm.h>
  10. #include <kdebug.h>
  11. // the valid vaddr for check is between 0~CHECK_VALID_VADDR-1
  12. #define CHECK_VALID_VIR_PAGE_NUM 5
  13. #define BEING_CHECK_VALID_VADDR 0X1000
  14. #define CHECK_VALID_VADDR (CHECK_VALID_VIR_PAGE_NUM+1)*0x1000
  15. // the max number of valid physical page for check
  16. #define CHECK_VALID_PHY_PAGE_NUM 4
  17. // the max access seq number
  18. #define MAX_SEQ_NO 10
  19. static struct swap_manager *sm;
  20. size_t max_swap_offset;
  21. volatile int swap_init_ok = 0;
  22. unsigned int swap_page[CHECK_VALID_VIR_PAGE_NUM];
  23. unsigned int swap_in_seq_no[MAX_SEQ_NO],swap_out_seq_no[MAX_SEQ_NO];
  24. static void check_swap(void);
  25. int
  26. swap_init(void)
  27. {
  28. swapfs_init();
  29. if (!(1024 <= max_swap_offset && max_swap_offset < MAX_SWAP_OFFSET_LIMIT))
  30. {
  31. panic("bad max_swap_offset %08x.\n", max_swap_offset);
  32. }
  33. sm = &swap_manager_fifo;
  34. int r = sm->init();
  35. if (r == 0)
  36. {
  37. swap_init_ok = 1;
  38. cprintf("SWAP: manager = %s\n", sm->name);
  39. check_swap();
  40. }
  41. return r;
  42. }
  43. int
  44. swap_init_mm(struct mm_struct *mm)
  45. {
  46. return sm->init_mm(mm);
  47. }
  48. int
  49. swap_tick_event(struct mm_struct *mm)
  50. {
  51. return sm->tick_event(mm);
  52. }
  53. int
  54. swap_map_swappable(struct mm_struct *mm, uintptr_t addr, struct Page *page, int swap_in)
  55. {
  56. return sm->map_swappable(mm, addr, page, swap_in);
  57. }
  58. int
  59. swap_set_unswappable(struct mm_struct *mm, uintptr_t addr)
  60. {
  61. return sm->set_unswappable(mm, addr);
  62. }
  63. volatile unsigned int swap_out_num=0;
  64. int
  65. swap_out(struct mm_struct *mm, int n, int in_tick)
  66. {
  67. int i;
  68. for (i = 0; i != n; ++ i)
  69. {
  70. uintptr_t v;
  71. //struct Page **ptr_page=NULL;
  72. struct Page *page;
  73. // cprintf("i %d, SWAP: call swap_out_victim\n",i);
  74. int r = sm->swap_out_victim(mm, &page, in_tick);
  75. if (r != 0) {
  76. cprintf("i %d, swap_out: call swap_out_victim failed\n",i);
  77. break;
  78. }
  79. //assert(!PageReserved(page));
  80. //cprintf("SWAP: choose victim page 0x%08x\n", page);
  81. v=page->pra_vaddr;
  82. pte_t *ptep = get_pte(mm->pgdir, v, 0);
  83. assert((*ptep & PTE_P) != 0);
  84. if (swapfs_write( (page->pra_vaddr/PGSIZE+1)<<8, page) != 0) {
  85. cprintf("SWAP: failed to save\n");
  86. sm->map_swappable(mm, v, page, 0);
  87. continue;
  88. }
  89. else {
  90. cprintf("swap_out: i %d, store page in vaddr 0x%x to disk swap entry %d\n", i, v, page->pra_vaddr/PGSIZE+1);
  91. *ptep = (page->pra_vaddr/PGSIZE+1)<<8;
  92. free_page(page);
  93. }
  94. tlb_invalidate(mm->pgdir, v);
  95. }
  96. return i;
  97. }
  98. int
  99. swap_in(struct mm_struct *mm, uintptr_t addr, struct Page **ptr_result)
  100. {
  101. struct Page *result = alloc_page();
  102. assert(result!=NULL);
  103. pte_t *ptep = get_pte(mm->pgdir, addr, 0);
  104. // cprintf("SWAP: load ptep %x swap entry %d to vaddr 0x%08x, page %x, No %d\n", ptep, (*ptep)>>8, addr, result, (result-pages));
  105. int r;
  106. if ((r = swapfs_read((*ptep), result)) != 0)
  107. {
  108. assert(r!=0);
  109. }
  110. cprintf("swap_in: load disk swap entry %d with swap_page in vadr 0x%x\n", (*ptep)>>8, addr);
  111. *ptr_result=result;
  112. return 0;
  113. }
  114. static inline void
  115. check_content_set(void)
  116. {
  117. *(unsigned char *)0x1000 = 0x0a;
  118. assert(pgfault_num==1);
  119. *(unsigned char *)0x1010 = 0x0a;
  120. assert(pgfault_num==1);
  121. *(unsigned char *)0x2000 = 0x0b;
  122. assert(pgfault_num==2);
  123. *(unsigned char *)0x2010 = 0x0b;
  124. assert(pgfault_num==2);
  125. *(unsigned char *)0x3000 = 0x0c;
  126. assert(pgfault_num==3);
  127. *(unsigned char *)0x3010 = 0x0c;
  128. assert(pgfault_num==3);
  129. *(unsigned char *)0x4000 = 0x0d;
  130. assert(pgfault_num==4);
  131. *(unsigned char *)0x4010 = 0x0d;
  132. assert(pgfault_num==4);
  133. }
  134. static inline int
  135. check_content_access(void)
  136. {
  137. int ret = sm->check_swap();
  138. return ret;
  139. }
  140. struct Page * check_rp[CHECK_VALID_PHY_PAGE_NUM];
  141. pte_t * check_ptep[CHECK_VALID_PHY_PAGE_NUM];
  142. unsigned int check_swap_addr[CHECK_VALID_VIR_PAGE_NUM];
  143. extern free_area_t free_area;
  144. #define free_list (free_area.free_list)
  145. #define nr_free (free_area.nr_free)
  146. static void
  147. check_swap(void)
  148. {
  149. //backup mem env
  150. int ret, count = 0, total = 0, i;
  151. list_entry_t *le = &free_list;
  152. while ((le = list_next(le)) != &free_list) {
  153. struct Page *p = le2page(le, page_link);
  154. assert(PageProperty(p));
  155. count ++, total += p->property;
  156. }
  157. assert(total == nr_free_pages());
  158. cprintf("BEGIN check_swap: count %d, total %d\n",count,total);
  159. //now we set the phy pages env
  160. struct mm_struct *mm = mm_create();
  161. assert(mm != NULL);
  162. extern struct mm_struct *check_mm_struct;
  163. assert(check_mm_struct == NULL);
  164. check_mm_struct = mm;
  165. pde_t *pgdir = mm->pgdir = boot_pgdir;
  166. assert(pgdir[0] == 0);
  167. struct vma_struct *vma = vma_create(BEING_CHECK_VALID_VADDR, CHECK_VALID_VADDR, VM_WRITE | VM_READ);
  168. assert(vma != NULL);
  169. insert_vma_struct(mm, vma);
  170. //setup the temp Page Table vaddr 0~4MB
  171. cprintf("setup Page Table for vaddr 0X1000, so alloc a page\n");
  172. pte_t *temp_ptep=NULL;
  173. temp_ptep = get_pte(mm->pgdir, BEING_CHECK_VALID_VADDR, 1);
  174. assert(temp_ptep!= NULL);
  175. cprintf("setup Page Table vaddr 0~4MB OVER!\n");
  176. for (i=0;i<CHECK_VALID_PHY_PAGE_NUM;i++) {
  177. check_rp[i] = alloc_page();
  178. assert(check_rp[i] != NULL );
  179. assert(!PageProperty(check_rp[i]));
  180. }
  181. list_entry_t free_list_store = free_list;
  182. list_init(&free_list);
  183. assert(list_empty(&free_list));
  184. //assert(alloc_page() == NULL);
  185. unsigned int nr_free_store = nr_free;
  186. nr_free = 0;
  187. for (i=0;i<CHECK_VALID_PHY_PAGE_NUM;i++) {
  188. free_pages(check_rp[i],1);
  189. }
  190. assert(nr_free==CHECK_VALID_PHY_PAGE_NUM);
  191. cprintf("set up init env for check_swap begin!\n");
  192. //setup initial vir_page<->phy_page environment for page relpacement algorithm
  193. pgfault_num=0;
  194. check_content_set();
  195. assert( nr_free == 0);
  196. for(i = 0; i<MAX_SEQ_NO ; i++)
  197. swap_out_seq_no[i]=swap_in_seq_no[i]=-1;
  198. for (i= 0;i<CHECK_VALID_PHY_PAGE_NUM;i++) {
  199. check_ptep[i]=0;
  200. check_ptep[i] = get_pte(pgdir, (i+1)*0x1000, 0);
  201. //cprintf("i %d, check_ptep addr %x, value %x\n", i, check_ptep[i], *check_ptep[i]);
  202. assert(check_ptep[i] != NULL);
  203. assert(pte2page(*check_ptep[i]) == check_rp[i]);
  204. assert((*check_ptep[i] & PTE_P));
  205. }
  206. cprintf("set up init env for check_swap over!\n");
  207. // now access the virt pages to test page relpacement algorithm
  208. ret=check_content_access();
  209. assert(ret==0);
  210. //restore kernel mem env
  211. for (i=0;i<CHECK_VALID_PHY_PAGE_NUM;i++) {
  212. free_pages(check_rp[i],1);
  213. }
  214. //free_page(pte2page(*temp_ptep));
  215. free_page(pa2page(pgdir[0]));
  216. pgdir[0] = 0;
  217. mm->pgdir = NULL;
  218. mm_destroy(mm);
  219. check_mm_struct = NULL;
  220. nr_free = nr_free_store;
  221. free_list = free_list_store;
  222. le = &free_list;
  223. while ((le = list_next(le)) != &free_list) {
  224. struct Page *p = le2page(le, page_link);
  225. count --, total -= p->property;
  226. }
  227. cprintf("count is %d, total is %d\n",count,total);
  228. //assert(count == 0);
  229. cprintf("check_swap() succeeded!\n");
  230. }