/src/arch/i386/lib/hat/initial_paging.c

https://github.com/mmikulicic/acaros · C · 184 lines · 134 code · 43 blank · 7 comment · 22 complexity · 20117a0294dd4e2254ae79421a527c1f MD5 · raw file

  1. #include <platform/hat/initial_paging.h>
  2. #include <platform/hat/page_allocator.h>
  3. #include <mm/addressspace.h>
  4. #include <stand/libc.h>
  5. #include <stand/stand.h>
  6. #include <debug.h>
  7. void* (*hat_initial_get_next_physical_page)() = get_next_physical_page;
  8. pte_t *page_directory;
  9. /** first physical 4Mb */
  10. pte_t *identity_page_table;
  11. void hat_resetPte(pte_t *pte) {
  12. pte->data = 0;
  13. }
  14. void hat_setPteBase(pte_t *pte, void *base) {
  15. pte->data &= ~(0xFFF);
  16. pte->data |= (u_int32_t)base & ~(0xFFF);
  17. }
  18. void hat_setPteFlags(pte_t *pte, unsigned short flags) {
  19. pte->data &= ~(0x1FF);
  20. pte->data |= flags;
  21. }
  22. void *hat_getPteBase(pte_t *pte) {
  23. return (void*)(pte->data & ~(0xFFF));
  24. }
  25. unsigned short hat_getPteFlags(pte_t *pte) {
  26. return pte->data & (0x1FF);
  27. }
  28. int hat_initInitialPaging() {
  29. page_directory = (pte_t*)(get_next_physical_page());
  30. identity_page_table = (pte_t*)(get_next_physical_page());
  31. memset(page_directory, PAGE_SIZE, 0);
  32. memset(identity_page_table, PAGE_SIZE, 0);
  33. hat_setPteBase(&page_directory[0], identity_page_table);
  34. hat_setPteFlags(&page_directory[0], PTE_RW | PTE_PRESENT | PTE_USER);
  35. hat_setPteBase(&page_directory[hat_pageDirIndex(HYPERSPACE)], page_directory);
  36. hat_setPteFlags(&page_directory[hat_pageDirIndex(HYPERSPACE)], PTE_RW | PTE_PRESENT | PTE_USER);
  37. int i;
  38. for(i=0; i<1024; i++) {
  39. hat_setPteBase(&identity_page_table[i], (void*)(i * PAGE_SIZE));
  40. hat_setPteFlags(&identity_page_table[i], PTE_RW | PTE_PRESENT);
  41. }
  42. WRITE_PAGE_DIRECTORY(page_directory);
  43. ENABLE_PAGING();
  44. stand_reserveVirtualRange((void*)PAGE_DIRECTORY, 1, 0, "hyperspace dir");
  45. stand_reserveVirtualRange((void*)PAGE_TABLE(0), 1, 0, "intentity pagetable");
  46. // stand_reserveVirtualRange((void*)HYPERSPACE, 1024, 0, "hyperspace");
  47. return 0;
  48. }
  49. int hat_unmapIdentityPages() {
  50. pte_t *page_table;
  51. page_table = PAGE_TABLE(0);
  52. int i;
  53. // for(i=0; i<1024; i++)
  54. for(i=0; i<1024; i++)
  55. hat_setPteFlags(&page_table[i], 0);
  56. //hat_setPteFlags(&(PAGE_DIRECTORY[0]), 0);
  57. flush_tlb();
  58. return 0;
  59. }
  60. int hat_initialMapAnonPages(pointer_t addr, size_t len,
  61. unsigned short flags, const char* tag) {
  62. int dir;
  63. int tab;
  64. pte_t *page_table;
  65. assert(len);
  66. // reserve if not already reserved
  67. pointer_t oldReservation = (pointer_t)stand_getNextFreeVirtual((void*)addr, len);
  68. if(oldReservation == addr)
  69. stand_reserveVirtualRange((void*)addr, len, flags, tag);
  70. int pflags = 0;
  71. if(flags & PROT_WRITE)
  72. pflags |= PTE_RW;
  73. if(flags & PROT_USER)
  74. pflags |= PTE_USER;
  75. while(len--) {
  76. dir = hat_pageDirIndex(addr);
  77. tab = hat_pageTableIndex(addr);
  78. if(!hat_getPteBase(&PAGE_DIRECTORY[dir])) {
  79. pte_t* new_page_table;
  80. new_page_table = hat_initial_get_next_physical_page();
  81. if(new_page_table == (void*)-1)
  82. return 0;
  83. stand_reserveVirtualRange((void*)PAGE_TABLE(addr), 1, 0, "hyperspace table");
  84. hat_setPteBase(&(PAGE_DIRECTORY[dir]), new_page_table);
  85. hat_setPteFlags(&(PAGE_DIRECTORY[dir]), PTE_RW | PTE_PRESENT | pflags);
  86. memset(PAGE_TABLE(addr), PAGE_SIZE, 0);
  87. }
  88. page_table = PAGE_TABLE(addr);
  89. void* page = hat_initial_get_next_physical_page();
  90. if(page == (void*)-1)
  91. return 0;
  92. hat_setPteBase(&page_table[tab], page);
  93. hat_setPteFlags(&page_table[tab], pflags | PTE_PRESENT);
  94. addr += PAGE_SIZE;
  95. }
  96. flush_tlb();
  97. return 1;
  98. }
  99. /** TODO share implementation with hat_mapAnonPages */
  100. int hat_initialMapPages(pointer_t addr, pointer_t phy, size_t len,
  101. unsigned short flags, const char* tag) {
  102. int dir;
  103. int tab;
  104. pte_t *page_table;
  105. // reserve if not already reserved
  106. pointer_t oldReservation = (pointer_t)stand_getNextFreeVirtual((void*)addr, 1);
  107. if(oldReservation == addr)
  108. stand_reserveVirtualRange((void*)addr, len, flags, tag);
  109. int pflags = 0;
  110. if(flags & PROT_WRITE)
  111. pflags |= PTE_RW;
  112. if(flags & PROT_USER)
  113. pflags |= PTE_USER;
  114. while(len--) {
  115. dir = hat_pageDirIndex(addr);
  116. tab = hat_pageTableIndex(addr);
  117. if(!hat_getPteBase(&PAGE_DIRECTORY[dir])) {
  118. pte_t* new_page_table;
  119. new_page_table = hat_initial_get_next_physical_page();
  120. if(new_page_table == 0)
  121. return 0;
  122. stand_reserveVirtualRange((void*)PAGE_TABLE(addr), 1, 0, "hyperspace table");
  123. hat_setPteBase(&(PAGE_DIRECTORY[dir]), new_page_table);
  124. hat_setPteFlags(&(PAGE_DIRECTORY[dir]), PTE_RW | PTE_PRESENT | PTE_USER);
  125. memset(PAGE_TABLE(addr), PAGE_SIZE, 0);
  126. }
  127. page_table = PAGE_TABLE(addr);
  128. hat_setPteBase(&page_table[tab], (void*)phy);
  129. hat_setPteFlags(&page_table[tab], PTE_RW | PTE_PRESENT | PTE_USER);
  130. addr += PAGE_SIZE;
  131. phy += PAGE_SIZE;
  132. }
  133. flush_tlb();
  134. return 1;
  135. }
  136. int hat_isValid(pointer_t addr) {
  137. if(hat_getPteFlags(&PAGE_DIRECTORY[hat_pageDirIndex(addr)]) & 0x1)
  138. if(hat_getPteFlags(&PAGE_TABLE(addr)[hat_pageTableIndex(addr)]) & 0x1)
  139. return 1;
  140. return 0;
  141. }