paging.hpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. #pragma once
  2. #include <bit>
  3. #include <cstddef>
  4. #include <tuple>
  5. #include <stdint.h>
  6. #include <kernel/interrupt.hpp>
  7. #include <kernel/mem/paging_asm.h>
  8. #include <kernel/mem/phys.hpp>
  9. namespace kernel::mem::paging {
  10. constexpr int idx_p5(uintptr_t vaddr) noexcept {
  11. return (vaddr >> 48) & 0x1ff;
  12. }
  13. constexpr int idx_p4(uintptr_t vaddr) noexcept {
  14. return (vaddr >> 39) & 0x1ff;
  15. }
  16. constexpr int idx_p3(uintptr_t vaddr) noexcept {
  17. return (vaddr >> 30) & 0x1ff;
  18. }
  19. constexpr int idx_p2(uintptr_t vaddr) noexcept {
  20. return (vaddr >> 21) & 0x1ff;
  21. }
  22. constexpr int idx_p1(uintptr_t vaddr) noexcept {
  23. return (vaddr >> 12) & 0x1ff;
  24. }
  25. constexpr std::tuple<int, int, int, int, int> idx_all(uintptr_t vaddr) noexcept {
  26. return {idx_p5(vaddr), idx_p4(vaddr), idx_p3(vaddr), idx_p2(vaddr), 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_DATA = PA_P | PA_RW | PA_NXE;
  34. constexpr psattr_t PA_KERNEL_DATA = PA_DATA | PA_G;
  35. constexpr psattr_t PA_USER_DATA = PA_DATA | PA_G | PA_US;
  36. constexpr psattr_t PA_PAGE_TABLE = PA_P | PA_RW;
  37. constexpr psattr_t PA_KERNEL_PAGE_TABLE = PA_PAGE_TABLE | PA_G;
  38. constexpr psattr_t PA_DATA_HUGE = PA_DATA | PA_PS;
  39. constexpr psattr_t PA_KERNEL_DATA_HUGE = PA_DATA_HUGE | PA_G;
  40. constexpr psattr_t PA_USER_DATA_HUGE = PA_DATA_HUGE | PA_US;
  41. namespace __inner {
  42. using pse_t = uint64_t;
  43. } // namespace __inner
  44. class PSE {
  45. physaddr<__inner::pse_t> m_ptrbase;
  46. public:
  47. explicit constexpr PSE(uintptr_t pptr) noexcept : m_ptrbase{pptr} {}
  48. constexpr void clear() noexcept { *m_ptrbase = 0; }
  49. constexpr void set(psattr_t attributes, pfn_t pfn) {
  50. *m_ptrbase = (attributes & PA_MASK) | (pfn & ~PA_MASK);
  51. }
  52. constexpr pfn_t pfn() const noexcept { return *m_ptrbase & ~PA_MASK; }
  53. constexpr psattr_t attributes() const noexcept { return *m_ptrbase & PA_MASK; }
  54. constexpr PSE operator[](std::size_t nth) const noexcept {
  55. return PSE{m_ptrbase.phys() + 8 * nth};
  56. }
  57. constexpr PSE parse() const noexcept { return PSE{*m_ptrbase & ~PA_MASK}; }
  58. };
  59. constexpr physaddr<void> KERNEL_PAGE_TABLE_PHYS_ADDR{KERNEL_PML4};
  60. constexpr PSE KERNEL_PAGE_TABLE{KERNEL_PML4};
  61. constexpr unsigned long PAGE_PRESENT = 0x00010000;
  62. constexpr unsigned long PAGE_BUDDY = 0x00020000;
  63. constexpr unsigned long PAGE_SLAB = 0x00040000;
  64. struct page {
  65. // TODO: use atomic
  66. unsigned long refcount;
  67. unsigned long flags;
  68. page* next;
  69. page* prev;
  70. };
  71. inline page* PAGE_ARRAY;
  72. void create_zone(uintptr_t start, uintptr_t end);
  73. void mark_present(uintptr_t start, uintptr_t end);
  74. [[nodiscard]] page* alloc_page();
  75. // order represents power of 2
  76. [[nodiscard]] page* alloc_pages(unsigned order);
  77. // order represents power of 2
  78. void free_pages(page* page, unsigned order);
  79. void free_page(page* page);
  80. // order represents power of 2
  81. void free_pages(pfn_t pfn, unsigned order);
  82. void free_page(pfn_t pfn);
  83. // clear the page all zero
  84. [[nodiscard]] pfn_t alloc_page_table();
  85. pfn_t page_to_pfn(page* page);
  86. page* pfn_to_page(pfn_t pfn);
  87. void increase_refcount(page* page);
  88. constexpr unsigned long PAGE_FAULT_P = 0x00000001;
  89. constexpr unsigned long PAGE_FAULT_W = 0x00000002;
  90. constexpr unsigned long PAGE_FAULT_U = 0x00000004;
  91. constexpr unsigned long PAGE_FAULT_R = 0x00000008;
  92. constexpr unsigned long PAGE_FAULT_I = 0x00000010;
  93. constexpr unsigned long PAGE_FAULT_PK = 0x00000020;
  94. constexpr unsigned long PAGE_FAULT_SS = 0x00000040;
  95. constexpr unsigned long PAGE_FAULT_SGX = 0x00008000;
  96. void handle_page_fault(interrupt_stack* int_stack);
  97. } // namespace kernel::mem::paging