paging.hpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. #pragma once
  2. #include <bit>
  3. #include <cstddef>
  4. #include <tuple>
  5. #include <stdint.h>
  6. #include <kernel/mem/phys.hpp>
  7. namespace kernel::mem::paging {
  8. constexpr int idx_p5(uintptr_t vaddr) noexcept {
  9. return (vaddr >> 48) & 0x1ff;
  10. }
  11. constexpr int idx_p4(uintptr_t vaddr) noexcept {
  12. return (vaddr >> 39) & 0x1ff;
  13. }
  14. constexpr int idx_p3(uintptr_t vaddr) noexcept {
  15. return (vaddr >> 30) & 0x1ff;
  16. }
  17. constexpr int idx_p2(uintptr_t vaddr) noexcept {
  18. return (vaddr >> 21) & 0x1ff;
  19. }
  20. constexpr int idx_p1(uintptr_t vaddr) noexcept {
  21. return (vaddr >> 12) & 0x1ff;
  22. }
  23. constexpr std::tuple<int, int, int, int, int> idx_all(
  24. uintptr_t vaddr) noexcept {
  25. return {idx_p5(vaddr), idx_p4(vaddr), idx_p3(vaddr), idx_p2(vaddr),
  26. idx_p1(vaddr)};
  27. }
  28. // page frame number
  29. // since we have large pages now, pfns are not shifted right
  30. using pfn_t = uintptr_t;
  31. // paging structure attributes
  32. using psattr_t = uintptr_t;
  33. constexpr psattr_t PA_P = 0x0000000000000001ULL;
  34. constexpr psattr_t PA_RW = 0x0000000000000002ULL;
  35. constexpr psattr_t PA_US = 0x0000000000000004ULL;
  36. constexpr psattr_t PA_PWT = 0x0000000000000008ULL;
  37. constexpr psattr_t PA_PCD = 0x0000000000000010ULL;
  38. constexpr psattr_t PA_A = 0x0000000000000020ULL;
  39. constexpr psattr_t PA_D = 0x0000000000000040ULL;
  40. constexpr psattr_t PA_PS = 0x0000000000000080ULL;
  41. constexpr psattr_t PA_G = 0x0000000000000100ULL;
  42. constexpr psattr_t PA_COW = 0x0000000000000200ULL; // copy on write
  43. constexpr psattr_t PA_MMAP = 0x0000000000000400ULL; // memory mapped
  44. constexpr psattr_t PA_ANON = 0x0000000000000800ULL; // anonymous map
  45. constexpr psattr_t PA_NXE = 0x8000000000000000ULL;
  46. constexpr psattr_t PA_MASK = 0xfff0000000000fffULL;
  47. constexpr psattr_t PA_DATA = PA_P | PA_RW | PA_NXE;
  48. constexpr psattr_t PA_KERNEL_DATA = PA_DATA | PA_G;
  49. constexpr psattr_t PA_USER_DATA = PA_DATA | PA_G | PA_US;
  50. constexpr psattr_t PA_PAGE_TABLE = PA_P | PA_RW;
  51. constexpr psattr_t PA_KERNEL_PAGE_TABLE = PA_PAGE_TABLE | PA_G;
  52. constexpr psattr_t PA_USER_PAGE_TABLE = PA_PAGE_TABLE | PA_US;
  53. constexpr psattr_t PA_DATA_HUGE = PA_DATA | PA_PS;
  54. constexpr psattr_t PA_KERNEL_DATA_HUGE = PA_DATA_HUGE | PA_G;
  55. constexpr psattr_t PA_USER_DATA_HUGE = PA_DATA_HUGE | PA_US;
  56. constexpr psattr_t PA_ANONYMOUS_PAGE = PA_P | PA_US | PA_COW | PA_ANON;
  57. constexpr psattr_t PA_MMAPPED_PAGE = PA_US | PA_COW | PA_ANON | PA_MMAP;
  58. namespace __inner {
  59. using pse_t = uint64_t;
  60. } // namespace __inner
  61. class PSE {
  62. physaddr<__inner::pse_t> m_ptrbase;
  63. public:
  64. explicit constexpr PSE(uintptr_t pptr) noexcept : m_ptrbase{pptr} {}
  65. constexpr void clear() noexcept { *m_ptrbase = 0; }
  66. constexpr void set(psattr_t attributes, pfn_t pfn) {
  67. *m_ptrbase = (attributes & PA_MASK) | (pfn & ~PA_MASK);
  68. }
  69. constexpr pfn_t pfn() const noexcept { return *m_ptrbase & ~PA_MASK; }
  70. constexpr psattr_t attributes() const noexcept {
  71. return *m_ptrbase & PA_MASK;
  72. }
  73. constexpr PSE operator[](std::size_t nth) const noexcept {
  74. return PSE{m_ptrbase.phys() + 8 * nth};
  75. }
  76. constexpr PSE parse() const noexcept { return PSE{*m_ptrbase & ~PA_MASK}; }
  77. };
  78. constexpr pfn_t EMPTY_PAGE_PFN = 0x7f000;
  79. constexpr uintptr_t KERNEL_PAGE_TABLE_ADDR = 0x100000;
  80. constexpr physaddr<void> KERNEL_PAGE_TABLE_PHYS_ADDR{KERNEL_PAGE_TABLE_ADDR};
  81. constexpr PSE KERNEL_PAGE_TABLE{0x100000};
  82. constexpr unsigned long PAGE_PRESENT = 0x00010000;
  83. constexpr unsigned long PAGE_BUDDY = 0x00020000;
  84. constexpr unsigned long PAGE_SLAB = 0x00040000;
  85. struct page {
  86. // TODO: use atomic
  87. unsigned long refcount;
  88. unsigned long flags;
  89. page* next;
  90. page* prev;
  91. };
  92. inline page* PAGE_ARRAY;
  93. void create_zone(uintptr_t start, uintptr_t end);
  94. void mark_present(uintptr_t start, uintptr_t end);
  95. [[nodiscard]] page* alloc_page();
  96. // order represents power of 2
  97. [[nodiscard]] page* alloc_pages(unsigned order);
  98. // order represents power of 2
  99. void free_pages(page* page, unsigned order);
  100. void free_page(page* page);
  101. // order represents power of 2
  102. void free_pages(pfn_t pfn, unsigned order);
  103. void free_page(pfn_t pfn);
  104. // clear the page all zero
  105. [[nodiscard]] pfn_t alloc_page_table();
  106. pfn_t page_to_pfn(page* page);
  107. page* pfn_to_page(pfn_t pfn);
  108. void increase_refcount(page* page);
  109. constexpr unsigned long PAGE_FAULT_P = 0x00000001;
  110. constexpr unsigned long PAGE_FAULT_W = 0x00000002;
  111. constexpr unsigned long PAGE_FAULT_U = 0x00000004;
  112. constexpr unsigned long PAGE_FAULT_R = 0x00000008;
  113. constexpr unsigned long PAGE_FAULT_I = 0x00000010;
  114. constexpr unsigned long PAGE_FAULT_PK = 0x00000020;
  115. constexpr unsigned long PAGE_FAULT_SS = 0x00000040;
  116. constexpr unsigned long PAGE_FAULT_SGX = 0x00008000;
  117. void handle_page_fault(unsigned long err);
  118. class vaddr_range {
  119. std::size_t n;
  120. int idx4;
  121. int idx3;
  122. int idx2;
  123. int idx1;
  124. PSE pml4;
  125. PSE pdpt;
  126. PSE pd;
  127. PSE pt;
  128. uintptr_t m_start;
  129. uintptr_t m_end;
  130. bool is_privilege;
  131. public:
  132. explicit vaddr_range(pfn_t pt, uintptr_t start, uintptr_t end,
  133. bool is_privilege = false);
  134. explicit vaddr_range(std::nullptr_t);
  135. vaddr_range begin() const noexcept;
  136. vaddr_range end() const noexcept;
  137. PSE operator*() const noexcept;
  138. vaddr_range& operator++();
  139. operator bool() const noexcept;
  140. // compares remaining pages to iterate
  141. bool operator==(const vaddr_range& other) const noexcept;
  142. };
  143. } // namespace kernel::mem::paging