mem.hpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. #pragma once
  2. #include <types/size.h>
  3. #include <types/stdint.h>
  4. #define PAGE_SIZE (4096)
  5. #define KERNEL_IDENTICALLY_MAPPED_AREA_LIMIT ((void*)0x30000000)
  6. #ifdef __cplusplus
  7. extern "C" {
  8. #endif
  9. // in mem.c
  10. extern struct mm* kernel_mm_head;
  11. // don't forget to add the initial 1m to the total
  12. struct mem_size_info {
  13. uint16_t n_1k_blks; // memory between 1m and 16m in 1k blocks
  14. uint16_t n_64k_blks; // memory above 16m in 64k blocks
  15. };
  16. struct e820_mem_map_entry_20 {
  17. uint64_t base;
  18. uint64_t len;
  19. uint32_t type;
  20. };
  21. struct e820_mem_map_entry_24 {
  22. struct e820_mem_map_entry_20 in;
  23. uint32_t acpi_extension_attr;
  24. };
  25. /*
  26. * page directory entry
  27. *
  28. * p : present (1)
  29. * rw : allow write (1)
  30. * us : allow user access (1)
  31. * pwt : todo
  32. * pcd : todo
  33. * a : accessed for linear address translation (1)
  34. * d : dirty (1) (ignored)
  35. * ps : use 4MiB pages (ignored)
  36. * addr: page table address
  37. */
  38. struct page_directory_entry_in {
  39. uint32_t p : 1;
  40. uint32_t rw : 1;
  41. uint32_t us : 1;
  42. uint32_t pwt : 1;
  43. uint32_t pcd : 1;
  44. uint32_t a : 1;
  45. uint32_t d : 1;
  46. uint32_t ps : 1;
  47. uint32_t ignored : 4;
  48. page_t pt_page : 20;
  49. };
  50. typedef union page_directory_entry {
  51. uint32_t v;
  52. struct page_directory_entry_in in;
  53. } page_directory_entry;
  54. /*
  55. * page table entry
  56. *
  57. * p : present (1)
  58. * rw : allow write (1)
  59. * us : allow user access (1)
  60. * pwt : todo
  61. * pcd : todo
  62. * a : accessed for linear address translation (1)
  63. * d : dirty (1)
  64. * pat : todo (ignored)
  65. * g : used in cr4 mode (ignored)
  66. * addr: physical memory address
  67. */
  68. struct page_table_entry_in {
  69. uint32_t p : 1;
  70. uint32_t rw : 1;
  71. uint32_t us : 1;
  72. uint32_t pwt : 1;
  73. uint32_t pcd : 1;
  74. uint32_t a : 1;
  75. uint32_t d : 1;
  76. uint32_t pat : 1;
  77. uint32_t g : 1;
  78. uint32_t ignored : 3;
  79. page_t page : 20;
  80. };
  81. typedef union page_table_entry {
  82. uint32_t v;
  83. struct page_table_entry_in in;
  84. } page_table_entry;
  85. struct page_attr {
  86. uint32_t read : 1;
  87. uint32_t write : 1;
  88. uint32_t system : 1;
  89. uint32_t cow : 1;
  90. };
  91. struct page {
  92. page_t phys_page_id;
  93. size_t* ref_count;
  94. struct page_attr attr;
  95. struct page* next;
  96. };
  97. struct mm_attr {
  98. uint32_t read : 1;
  99. uint32_t write : 1;
  100. uint32_t system : 1;
  101. };
  102. struct mm {
  103. linr_ptr_t start;
  104. size_t len;
  105. struct mm_attr attr;
  106. struct page* pgs;
  107. struct mm* next;
  108. page_directory_entry* pd;
  109. };
  110. // in kernel_main.c
  111. extern uint8_t e820_mem_map[1024];
  112. extern uint32_t e820_mem_map_count;
  113. extern uint32_t e820_mem_map_entry_size;
  114. extern size_t kernel_size;
  115. extern struct mem_size_info mem_size_info;
  116. #define KERNEL_HEAP_START ((void*)0x30000000)
  117. #define KERNEL_HEAP_LIMIT ((void*)0x40000000)
  118. struct mem_blk_flags {
  119. uint8_t is_free;
  120. uint8_t has_next;
  121. uint8_t _unused2;
  122. uint8_t _unused3;
  123. };
  124. struct mem_blk {
  125. size_t size;
  126. struct mem_blk_flags flags;
  127. // the first byte of the memory space
  128. // the minimal allocated space is 4 bytes
  129. uint8_t data[4];
  130. };
  131. int init_heap(void);
  132. void* k_malloc(size_t size);
  133. void k_free(void* ptr);
  134. // translate physical address to virtual(mapped) address
  135. void* p_ptr_to_v_ptr(phys_ptr_t p_ptr);
  136. // translate linear address to physical address
  137. phys_ptr_t l_ptr_to_p_ptr(struct mm* mm_area, linr_ptr_t v_ptr);
  138. // translate virtual(mapped) address to physical address
  139. phys_ptr_t v_ptr_to_p_ptr(void* v_ptr);
  140. // check if the l_ptr is contained in the area
  141. // @return GB_OK if l_ptr is in the area
  142. // GB_FAILED if not
  143. int is_l_ptr_valid(struct mm* mm_area, linr_ptr_t l_ptr);
  144. // find the corresponding page the l_ptr pointing to
  145. // @return the pointer to the struct if found, NULL if not found
  146. struct page* find_page_by_l_ptr(struct mm* mm_area, linr_ptr_t l_ptr);
  147. static inline page_t phys_addr_to_page(phys_ptr_t ptr)
  148. {
  149. return ptr >> 12;
  150. }
  151. static inline pd_i_t page_to_pd_i(page_t p)
  152. {
  153. return p >> 10;
  154. }
  155. static inline pt_i_t page_to_pt_i(page_t p)
  156. {
  157. return p & (1024 - 1);
  158. }
  159. static inline phys_ptr_t page_to_phys_addr(page_t p)
  160. {
  161. return p << 12;
  162. }
  163. static inline pd_i_t linr_addr_to_pd_i(linr_ptr_t ptr)
  164. {
  165. return page_to_pd_i(phys_addr_to_page(ptr));
  166. }
  167. static inline pd_i_t linr_addr_to_pt_i(linr_ptr_t ptr)
  168. {
  169. return page_to_pt_i(phys_addr_to_page(ptr));
  170. }
  171. static inline page_directory_entry* lptr_to_pde(struct mm* mm, linr_ptr_t l_ptr)
  172. {
  173. return mm->pd + linr_addr_to_pd_i((phys_ptr_t)l_ptr);
  174. }
  175. static inline page_table_entry* lptr_to_pte(struct mm* mm, linr_ptr_t l_ptr)
  176. {
  177. page_directory_entry* pde = lptr_to_pde(mm, l_ptr);
  178. page_table_entry* pte = (page_table_entry*)p_ptr_to_v_ptr(page_to_phys_addr(pde->in.pt_page));
  179. return pte + linr_addr_to_pt_i((phys_ptr_t)l_ptr);
  180. }
  181. static inline page_directory_entry* lp_to_pde(struct mm* mm, linr_ptr_t l_ptr)
  182. {
  183. phys_ptr_t p_ptr = l_ptr_to_p_ptr(mm, l_ptr);
  184. page_directory_entry* pde = mm->pd + linr_addr_to_pd_i(p_ptr);
  185. return pde;
  186. }
  187. // get the corresponding pte for the linear address
  188. // for example: l_ptr = 0x30001000 will return the pte including the page it is mapped to
  189. static inline page_table_entry* lp_to_pte(struct mm* mm, linr_ptr_t l_ptr)
  190. {
  191. phys_ptr_t p_ptr = l_ptr_to_p_ptr(mm, l_ptr);
  192. page_directory_entry* pde = lp_to_pde(mm, l_ptr);
  193. phys_ptr_t p_pt = page_to_phys_addr(pde->in.pt_page);
  194. page_table_entry* pte = (page_table_entry*)p_ptr_to_v_ptr(p_pt);
  195. pte += linr_addr_to_pt_i(p_ptr);
  196. return pte;
  197. }
  198. // map the page to the end of the mm_area in pd
  199. int k_map(
  200. struct mm* mm_area,
  201. struct page* page,
  202. int read,
  203. int write,
  204. int priv,
  205. int cow);
  206. // allocate a raw page
  207. page_t alloc_raw_page(void);
  208. // allocate a struct page together with the raw page
  209. struct page* allocate_page(void);
  210. #define KERNEL_PAGE_DIRECTORY_ADDR ((page_directory_entry*)0x00000000)
  211. void init_mem(void);
  212. #define KERNEL_CODE_SEGMENT (0x08)
  213. #define KERNEL_DATA_SEGMENT (0x10)
  214. #define USER_CODE_SEGMENT (0x18)
  215. #define USER_DATA_SEGMENT (0x20)
  216. #define SD_TYPE_CODE_SYSTEM (0x9a)
  217. #define SD_TYPE_DATA_SYSTEM (0x92)
  218. #define SD_TYPE_CODE_USER (0xfa)
  219. #define SD_TYPE_DATA_USER (0xf2)
  220. #define SD_TYPE_TSS (0x89)
  221. typedef struct segment_descriptor_struct {
  222. uint64_t limit_low : 16;
  223. uint64_t base_low : 16;
  224. uint64_t base_mid : 8;
  225. uint64_t access : 8;
  226. uint64_t limit_high : 4;
  227. uint64_t flags : 4;
  228. uint64_t base_high : 8;
  229. } segment_descriptor;
  230. void create_segment_descriptor(
  231. segment_descriptor* sd,
  232. uint32_t base,
  233. uint32_t limit,
  234. uint32_t flags,
  235. uint32_t access);
  236. #ifdef __cplusplus
  237. }
  238. #endif