《操作系统》的实验代码。
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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