MemoryManager.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. #pragma once
  2. #include "types.h"
  3. #include "i386.h"
  4. #include <AK/ByteBuffer.h>
  5. #include <AK/Retainable.h>
  6. #include <AK/RetainPtr.h>
  7. #include <AK/Vector.h>
  8. #include <AK/HashTable.h>
  9. #include <AK/String.h>
  10. class Process;
  11. extern Process* current;
  12. enum class PageFaultResponse {
  13. ShouldCrash,
  14. Continue,
  15. };
  16. struct PageDirectory {
  17. dword entries[1024];
  18. PhysicalAddress physical_addresses[1024];
  19. };
  20. struct Zone : public Retainable<Zone> {
  21. friend ByteBuffer procfs$mm();
  22. public:
  23. ~Zone();
  24. size_t size() const { return m_pages.size() * PAGE_SIZE; }
  25. const Vector<PhysicalAddress>& pages() const { return m_pages; }
  26. private:
  27. friend class MemoryManager;
  28. explicit Zone(Vector<PhysicalAddress>&&);
  29. Vector<PhysicalAddress> m_pages;
  30. };
  31. struct Region : public Retainable<Region> {
  32. Region(LinearAddress, size_t, RetainPtr<Zone>&&, String&&);
  33. ~Region();
  34. LinearAddress linearAddress;
  35. size_t size { 0 };
  36. RetainPtr<Zone> zone;
  37. String name;
  38. };
  39. struct Subregion {
  40. Subregion(Region&, dword offset, size_t, LinearAddress, String&& name);
  41. ~Subregion();
  42. RetainPtr<Region> region;
  43. dword offset;
  44. size_t size { 0 };
  45. LinearAddress linearAddress;
  46. String name;
  47. };
  48. #define MM MemoryManager::the()
  49. class MemoryManager {
  50. AK_MAKE_ETERNAL
  51. friend ByteBuffer procfs$mm();
  52. public:
  53. static MemoryManager& the() PURE;
  54. PhysicalAddress pageDirectoryBase() const { return PhysicalAddress(reinterpret_cast<dword>(m_kernel_page_directory)); }
  55. static void initialize();
  56. PageFaultResponse handlePageFault(const PageFault&);
  57. RetainPtr<Zone> createZone(size_t);
  58. bool mapSubregion(Process&, Subregion&);
  59. bool unmapSubregion(Process&, Subregion&);
  60. bool mapRegion(Process&, Region&);
  61. bool unmapRegion(Process&, Region&);
  62. void registerZone(Zone&);
  63. void unregisterZone(Zone&);
  64. void populate_page_directory(Process&);
  65. void release_page_directory(Process&);
  66. byte* create_kernel_alias_for_region(Region&);
  67. void remove_kernel_alias_for_region(Region&, byte*);
  68. void enter_kernel_paging_scope();
  69. void enter_process_paging_scope(Process&);
  70. bool validate_user_read(const Process&, LinearAddress) const;
  71. bool validate_user_write(const Process&, LinearAddress) const;
  72. private:
  73. MemoryManager();
  74. ~MemoryManager();
  75. LinearAddress allocate_linear_address_range(size_t);
  76. void map_region_at_address(PageDirectory*, Region&, LinearAddress, bool user_accessible);
  77. void unmap_range(PageDirectory*, LinearAddress, size_t);
  78. void initializePaging();
  79. void flushEntireTLB();
  80. void flushTLB(LinearAddress);
  81. void* allocate_page_table();
  82. void protectMap(LinearAddress, size_t length);
  83. void identityMap(LinearAddress, size_t length);
  84. Vector<PhysicalAddress> allocatePhysicalPages(size_t count);
  85. struct PageDirectoryEntry {
  86. explicit PageDirectoryEntry(dword* pde) : m_pde(pde) { }
  87. dword* pageTableBase() { return reinterpret_cast<dword*>(raw() & 0xfffff000u); }
  88. void setPageTableBase(dword value)
  89. {
  90. *m_pde &= 0xfff;
  91. *m_pde |= value & 0xfffff000;
  92. }
  93. dword raw() const { return *m_pde; }
  94. dword* ptr() { return m_pde; }
  95. enum Flags {
  96. Present = 1 << 0,
  97. ReadWrite = 1 << 1,
  98. UserSupervisor = 1 << 2,
  99. };
  100. bool isPresent() const { return raw() & Present; }
  101. void setPresent(bool b) { setBit(Present, b); }
  102. bool isUserAllowed() const { return raw() & UserSupervisor; }
  103. void setUserAllowed(bool b) { setBit(UserSupervisor, b); }
  104. bool isWritable() const { return raw() & ReadWrite; }
  105. void setWritable(bool b) { setBit(ReadWrite, b); }
  106. void setBit(byte bit, bool value)
  107. {
  108. if (value)
  109. *m_pde |= bit;
  110. else
  111. *m_pde &= ~bit;
  112. }
  113. dword* m_pde;
  114. };
  115. struct PageTableEntry {
  116. explicit PageTableEntry(dword* pte) : m_pte(pte) { }
  117. dword* physicalPageBase() { return reinterpret_cast<dword*>(raw() & 0xfffff000u); }
  118. void setPhysicalPageBase(dword value)
  119. {
  120. *m_pte &= 0xfffu;
  121. *m_pte |= value & 0xfffff000u;
  122. }
  123. dword raw() const { return *m_pte; }
  124. dword* ptr() { return m_pte; }
  125. enum Flags {
  126. Present = 1 << 0,
  127. ReadWrite = 1 << 1,
  128. UserSupervisor = 1 << 2,
  129. };
  130. bool isPresent() const { return raw() & Present; }
  131. void setPresent(bool b) { setBit(Present, b); }
  132. bool isUserAllowed() const { return raw() & UserSupervisor; }
  133. void setUserAllowed(bool b) { setBit(UserSupervisor, b); }
  134. bool isWritable() const { return raw() & ReadWrite; }
  135. void setWritable(bool b) { setBit(ReadWrite, b); }
  136. void setBit(byte bit, bool value)
  137. {
  138. if (value)
  139. *m_pte |= bit;
  140. else
  141. *m_pte &= ~bit;
  142. }
  143. dword* m_pte;
  144. };
  145. PageTableEntry ensurePTE(PageDirectory*, LinearAddress);
  146. PageDirectory* m_kernel_page_directory;
  147. dword* m_pageTableZero;
  148. dword* m_pageTableOne;
  149. LinearAddress m_next_laddr;
  150. HashTable<Zone*> m_zones;
  151. Vector<PhysicalAddress> m_freePages;
  152. };
  153. struct KernelPagingScope {
  154. KernelPagingScope() { MM.enter_kernel_paging_scope(); }
  155. ~KernelPagingScope() { MM.enter_process_paging_scope(*current); }
  156. };
  157. struct ProcessPagingScope {
  158. ProcessPagingScope(Process& process) { MM.enter_process_paging_scope(process); }
  159. ~ProcessPagingScope() { MM.enter_process_paging_scope(*current); }
  160. };