main.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /*
  2. * memory/main.c
  3. *
  4. * Copyright (C) 2018 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as
  8. * published by the Free Software Foundation, either version 3 of the
  9. * License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <new_memory.h>
  20. #include <boot/multiboot.h>
  21. #define MULTIBOOT_LOAD_ADDRESS 0x00100000
  22. #define VIRTUAL_LOAD_ADDRESS 0x80000000
  23. extern void memory_init_mapping_hack(void);
  24. extern void memory_init_physical(memory_map_entry_t *mmap, size_t num_entries);
  25. extern void (*_end)();
  26. uintptr_t memory_metadata_base = MEMORY_METADATA_TOP;
  27. static int compare_map_entry(const void *p1, const void *p2)
  28. {
  29. memory_map_entry_t *a = (memory_map_entry_t*)p1;
  30. memory_map_entry_t *b = (memory_map_entry_t*)p2;
  31. if (a->address < b->address) return -1;
  32. else if (a->address > b->address) return 1;
  33. else return 0;
  34. }
  35. static size_t plot_memory_map(uintptr_t mboot_tags, size_t mboot_size, memory_map_entry_t *map, size_t max_entries)
  36. {
  37. multiboot_tag_t *mboot = (multiboot_tag_t*)(PAGE_ALIGN_UP((uintptr_t)&_end) + PAGE_OFFSET(mboot_tags)); // HACK
  38. size_t num_entries = 0;
  39. if (num_entries >= max_entries) return 0;
  40. map[num_entries++] = (memory_map_entry_t) {
  41. .address = MULTIBOOT_LOAD_ADDRESS,
  42. .length = PAGE_ALIGN_UP((uintptr_t)&_end - VIRTUAL_LOAD_ADDRESS),
  43. .status = PAGE_STATUS_ALLOCATED,
  44. };
  45. if (num_entries >= max_entries) return 0;
  46. map[num_entries++] = (memory_map_entry_t) {
  47. .address = PAGE_ALIGN(mboot_tags),
  48. .length = PAGE_ALIGN_UP(mboot_tags + mboot_size) - PAGE_ALIGN(mboot_tags),
  49. .status = PAGE_STATUS_ALLOCATED,
  50. };
  51. if (num_entries >= max_entries) return 0;
  52. map[num_entries++] = (memory_map_entry_t) { .address = 0, .length = 0x1000, .status = PAGE_STATUS_RESERVED };
  53. for (multiboot_tag_t *tag = mboot; tag->type != MULTIBOOT_INFO_END; tag = (multiboot_tag_t*)(((uintptr_t)tag + tag->size + 7) & ~7))
  54. {
  55. switch (tag->type)
  56. {
  57. case MULTIBOOT_INFO_MEMORY_MAP:
  58. {
  59. multiboot_tag_mmap_t *mmap = (multiboot_tag_mmap_t*)tag;
  60. for (multiboot_mmap_entry_t *entry = (multiboot_mmap_entry_t*)(mmap + 1);
  61. (uintptr_t)entry < ((uintptr_t)mmap + mmap->size);
  62. entry = (multiboot_mmap_entry_t*)((uintptr_t)entry + mmap->entry_size))
  63. {
  64. if (entry->type == 5) continue;
  65. if (num_entries >= max_entries) return 0;
  66. map[num_entries++] = (memory_map_entry_t) {
  67. .address = PAGE_ALIGN(entry->base),
  68. .length = PAGE_ALIGN_UP(entry->base + entry->length) - PAGE_ALIGN(entry->base),
  69. .status = (entry->type == 1) ? PAGE_STATUS_FREE : PAGE_STATUS_RESERVED,
  70. };
  71. }
  72. break;
  73. }
  74. case MULTIBOOT_INFO_MODULES:
  75. {
  76. multiboot_tag_module_t *module = (multiboot_tag_module_t*)tag;
  77. if (num_entries >= max_entries) return 0;
  78. map[num_entries++] = (memory_map_entry_t) {
  79. .address = PAGE_ALIGN(module->mod_start),
  80. .length = PAGE_ALIGN_UP(module->mod_end) - PAGE_ALIGN(module->mod_start),
  81. .status = PAGE_STATUS_ALLOCATED,
  82. };
  83. break;
  84. }
  85. }
  86. }
  87. qsort(map, num_entries, sizeof(memory_map_entry_t), compare_map_entry);
  88. for (size_t i = 1; i < num_entries; i++)
  89. {
  90. uintptr_t current_end = map[i].address + map[i].length;
  91. uintptr_t previous_end = map[i - 1].address + map[i - 1].length;
  92. if (map[i].status > map[i - 1].status)
  93. {
  94. if (previous_end > current_end)
  95. {
  96. if (num_entries >= max_entries) return 0;
  97. memmove(&map[i + 2], &map[i + 1], (num_entries - i - 1) * sizeof(memory_map_entry_t));
  98. map[i + 1].address = current_end;
  99. map[i + 1].length = previous_end - current_end;
  100. map[i + 1].status = map[i - 1].status;
  101. num_entries++;
  102. }
  103. if (previous_end > map[i].address)
  104. {
  105. if (map[i - 1].length > previous_end - map[i].address)
  106. {
  107. map[i - 1].length -= previous_end - map[i].address;
  108. }
  109. else
  110. {
  111. memmove(&map[i - 1], &map[i], (num_entries - i) * sizeof(memory_map_entry_t));
  112. i -= 2;
  113. num_entries--;
  114. }
  115. }
  116. }
  117. else if (map[i].status < map[i - 1].status)
  118. {
  119. if (previous_end >= current_end)
  120. {
  121. memmove(&map[i], &map[i + 1], (num_entries - i - 1) * sizeof(memory_map_entry_t));
  122. i--;
  123. num_entries--;
  124. }
  125. else if (previous_end > map[i].address)
  126. {
  127. map[i].length -= previous_end - map[i].address;
  128. map[i].address = previous_end;
  129. }
  130. }
  131. else if (map[i].address <= previous_end)
  132. {
  133. map[i - 1].length = (current_end > previous_end ? current_end : previous_end) - map[i - 1].address;
  134. memmove(&map[i], &map[i + 1], (num_entries - i - 1) * sizeof(memory_map_entry_t));
  135. num_entries--;
  136. }
  137. }
  138. return num_entries;
  139. }
  140. void *memory_request_metadata_space(size_t count, size_t size)
  141. {
  142. memory_metadata_base -= count * size;
  143. if (memory_metadata_base % size) memory_metadata_base = size * (memory_metadata_base / size);
  144. return (void*)memory_metadata_base;
  145. }
  146. void new_memory_init(uintptr_t mboot_tags, size_t mboot_size)
  147. {
  148. cpu_max_physical_bits = 32; // No PAE for now
  149. memory_init_mapping_hack();
  150. size_t num_entries, max_entries = 1024;
  151. for (;;)
  152. {
  153. memory_map_entry_t map[max_entries];
  154. if ((num_entries = plot_memory_map(mboot_tags, mboot_size, map, max_entries)))
  155. {
  156. memory_init_physical(map, num_entries);
  157. break;
  158. }
  159. max_entries += max_entries;
  160. }
  161. area_t kernel_area = {
  162. .pages = memory_find_page_by_address(MULTIBOOT_LOAD_ADDRESS),
  163. .count = PAGE_NUMBER(PAGE_ALIGN_UP((uintptr_t)&_end - VIRTUAL_LOAD_ADDRESS)),
  164. };
  165. ASSERT(kernel_area.pages != NULL);
  166. memory_init_virtual(&kernel_area);
  167. }