ソースを参照

Kernel: Use ksyms in-place instead of duplicating them into eternal heap

We can leave the .ksyms section mapped-but-read-only and then have the
symbols index simply point into it.

Note that we manually insert null-terminators into the symbols section
while parsing it.

This gets rid of ~950 KiB of kmalloc_eternal() at startup. :^)
Andreas Kling 3 年 前
コミット
1f2d0d0ad4
4 ファイル変更11 行追加13 行削除
  1. 5 6
      Kernel/KSyms.cpp
  2. 3 4
      Kernel/Memory/MemoryManager.cpp
  3. 1 1
      Kernel/Memory/MemoryManager.h
  4. 2 2
      Kernel/init.cpp

+ 5 - 6
Kernel/KSyms.cpp

@@ -54,12 +54,12 @@ const KernelSymbol* symbolicate_kernel_address(FlatPtr address)
     return nullptr;
 }
 
-UNMAP_AFTER_INIT static void load_kernel_symbols_from_data(ReadonlyBytes buffer)
+UNMAP_AFTER_INIT static void load_kernel_symbols_from_data(Bytes buffer)
 {
     g_lowest_kernel_symbol_address = 0xffffffff;
     g_highest_kernel_symbol_address = 0;
 
-    auto* bufptr = (const char*)buffer.data();
+    auto* bufptr = (char*)buffer.data();
     auto* start_of_name = bufptr;
     FlatPtr address = 0;
 
@@ -84,10 +84,9 @@ UNMAP_AFTER_INIT static void load_kernel_symbols_from_data(ReadonlyBytes buffer)
         }
         auto& ksym = s_symbols[current_symbol_index];
         ksym.address = kernel_load_base + address;
-        char* name = static_cast<char*>(kmalloc_eternal((bufptr - start_of_name) + 1));
-        memcpy(name, start_of_name, bufptr - start_of_name);
-        name[bufptr - start_of_name] = '\0';
-        ksym.name = name;
+        ksym.name = start_of_name;
+
+        *bufptr = '\0';
 
         if (ksym.address < g_lowest_kernel_symbol_address)
             g_lowest_kernel_symbol_address = ksym.address;

+ 3 - 4
Kernel/Memory/MemoryManager.cpp

@@ -136,7 +136,7 @@ void MemoryManager::unmap_text_after_init()
     dmesgln("Unmapped {} KiB of kernel text after init! :^)", (end - start) / KiB);
 }
 
-void MemoryManager::unmap_ksyms_after_init()
+void MemoryManager::protect_ksyms_after_init()
 {
     SpinlockLocker mm_lock(s_mm_lock);
     SpinlockLocker page_lock(kernel_page_directory().get_lock());
@@ -144,14 +144,13 @@ void MemoryManager::unmap_ksyms_after_init()
     auto start = page_round_down((FlatPtr)start_of_kernel_ksyms);
     auto end = page_round_up((FlatPtr)end_of_kernel_ksyms);
 
-    // Unmap the entire .ksyms section
     for (auto i = start; i < end; i += PAGE_SIZE) {
         auto& pte = *ensure_pte(kernel_page_directory(), VirtualAddress(i));
-        pte.clear();
+        pte.set_writable(false);
         flush_tlb(&kernel_page_directory(), VirtualAddress(i));
     }
 
-    dmesgln("Unmapped {} KiB of kernel symbols after init! :^)", (end - start) / KiB);
+    dmesgln("Write-protected kernel symbols after init.");
 }
 
 UNMAP_AFTER_INIT void MemoryManager::register_reserved_ranges()

+ 1 - 1
Kernel/Memory/MemoryManager.h

@@ -160,7 +160,7 @@ public:
 
     void protect_readonly_after_init_memory();
     void unmap_text_after_init();
-    void unmap_ksyms_after_init();
+    void protect_ksyms_after_init();
 
     static void enter_process_address_space(Process&);
     static void enter_address_space(AddressSpace&);

+ 2 - 2
Kernel/init.cpp

@@ -336,8 +336,8 @@ void init_stage2(void*)
     // NOTE: Everything marked UNMAP_AFTER_INIT becomes inaccessible after this point.
     MM.unmap_text_after_init();
 
-    // NOTE: Everything in the .ksyms section becomes inaccessible after this point.
-    MM.unmap_ksyms_after_init();
+    // NOTE: Everything in the .ksyms section becomes read-only after this point.
+    MM.protect_ksyms_after_init();
 
     // FIXME: It would be nicer to set the mode from userspace.
     // FIXME: It would be smarter to not hardcode that the first tty is the only graphical one