Преглед изворни кода

Kernel: Add a quickmap region for each processor

Threads need to be able to concurrently quickmap things.
Tom пре 5 година
родитељ
комит
2a38cc9a12
5 измењених фајлова са 56 додато и 22 уклоњено
  1. 3 2
      Kernel/Arch/i386/CPU.cpp
  2. 12 0
      Kernel/Arch/i386/CPU.h
  3. 29 16
      Kernel/VM/MemoryManager.cpp
  4. 10 3
      Kernel/VM/MemoryManager.h
  5. 2 1
      Kernel/init.cpp

+ 3 - 2
Kernel/Arch/i386/CPU.cpp

@@ -215,7 +215,7 @@ void page_fault_handler(TrapFrame* trap)
 
 #ifdef PAGE_FAULT_DEBUG
     u32 fault_page_directory = read_cr3();
-    dbg() << "Ring " << (regs.cs & 3)
+    dbg() << "CPU #" << (Processor::is_initialized() ? Processor::current().id() : 0) << " ring " << (regs.cs & 3)
           << " " << (regs.exception_code & 1 ? "PV" : "NP")
           << " page fault in PD=" << String::format("%x", fault_page_directory) << ", "
           << (regs.exception_code & 8 ? "reserved-bit " : "")
@@ -831,6 +831,7 @@ void Processor::initialize(u32 cpu)
 
     m_idle_thread = nullptr;
     m_current_thread = nullptr;
+    m_mm_data = nullptr;
 
     gdt_init();
     if (cpu == 0)
@@ -859,7 +860,7 @@ void Processor::initialize(u32 cpu)
         (*s_processors)[cpu] = this;
     }
 
-    klog() << "CPU #" << cpu << " using Processor at " << VirtualAddress(FlatPtr(this));
+    klog() << "CPU[" << cpu << "]: initialized Processor at " << VirtualAddress(FlatPtr(this));
 }
 
 void Processor::write_raw_gdt_entry(u16 selector, u32 low, u32 high)

+ 12 - 0
Kernel/Arch/i386/CPU.h

@@ -611,6 +611,7 @@ struct TrapFrame;
 #define GDT_SELECTOR_TSS 0x38
 
 class ProcessorInfo;
+struct MemoryManagerData;
 
 class Processor {
     Processor* m_self; // must be first field (%fs offset 0x0)
@@ -626,6 +627,7 @@ class Processor {
     static FPUState s_clean_fpu_state;
 
     ProcessorInfo* m_info;
+    MemoryManagerData* m_mm_data;
     Thread* m_current_thread;
     Thread* m_idle_thread;
 
@@ -668,6 +670,16 @@ public:
         return get_fs() == GDT_SELECTOR_PROC && read_fs_u32(0) != 0;
     }
 
+    ALWAYS_INLINE void set_mm_data(MemoryManagerData& mm_data)
+    {
+        m_mm_data = &mm_data;
+    }
+
+    ALWAYS_INLINE MemoryManagerData& get_mm_data() const
+    {
+        return *m_mm_data;
+    }
+
     ALWAYS_INLINE Thread* idle_thread() const
     {
         return m_idle_thread;

+ 29 - 16
Kernel/VM/MemoryManager.cpp

@@ -207,9 +207,16 @@ PageTableEntry& MemoryManager::ensure_pte(PageDirectory& page_directory, Virtual
     return quickmap_pt(PhysicalAddress((FlatPtr)pde.page_table_base()))[page_table_index];
 }
 
-void MemoryManager::initialize()
+void MemoryManager::initialize(u32 cpu)
 {
-    s_the = new MemoryManager;
+    auto mm_data = new MemoryManagerData;
+#ifdef MM_DEBUG
+    dbg() << "MM: Processor #" << cpu << " specific data at " << VirtualAddress(mm_data);
+#endif
+    Processor::current().set_mm_data(*mm_data);
+
+    if (cpu == 0)
+        s_the = new MemoryManager;
 }
 
 Region* MemoryManager::kernel_region_from_vaddr(VirtualAddress vaddr)
@@ -566,50 +573,56 @@ PageDirectoryEntry* MemoryManager::quickmap_pd(PageDirectory& directory, size_t
 PageTableEntry* MemoryManager::quickmap_pt(PhysicalAddress pt_paddr)
 {
     ScopedSpinLock lock(s_lock);
-    auto& pte = boot_pd3_pt1023[8];
+    auto& pte = boot_pd3_pt1023[0];
     if (pte.physical_page_base() != pt_paddr.as_ptr()) {
 #ifdef MM_DEBUG
-        dbg() << "quickmap_pt: Mapping P" << (void*)pt_paddr.as_ptr() << " at 0xffe08000 in pte @ " << &pte;
+        dbg() << "quickmap_pt: Mapping P" << (void*)pt_paddr.as_ptr() << " at 0xffe00000 in pte @ " << &pte;
 #endif
         pte.set_physical_page_base(pt_paddr.get());
         pte.set_present(true);
         pte.set_writable(true);
         pte.set_user_allowed(false);
-        flush_tlb(VirtualAddress(0xffe08000));
+        flush_tlb(VirtualAddress(0xffe00000));
     }
-    return (PageTableEntry*)0xffe08000;
+    return (PageTableEntry*)0xffe00000;
 }
 
 u8* MemoryManager::quickmap_page(PhysicalPage& physical_page)
 {
     ASSERT_INTERRUPTS_DISABLED();
+    auto& mm_data = get_data();
+    mm_data.m_quickmap_in_use.lock();
     ScopedSpinLock lock(s_lock);
-    ASSERT(!m_quickmap_in_use);
-    m_quickmap_in_use = true;
 
-    auto& pte = boot_pd3_pt1023[0];
+    u32 pte_idx = 8 + Processor::current().id();
+    VirtualAddress vaddr(0xffe00000 + pte_idx * PAGE_SIZE);
+
+    auto& pte = boot_pd3_pt1023[pte_idx];
     if (pte.physical_page_base() != physical_page.paddr().as_ptr()) {
 #ifdef MM_DEBUG
-        dbg() << "quickmap_page: Mapping P" << (void*)physical_page.paddr().as_ptr() << " at 0xffe00000 in pte @ " << &pte;
+        dbg() << "quickmap_page: Mapping P" << (void*)physical_page.paddr().as_ptr() << " at 0xffe08000 in pte @ " << &pte;
 #endif
         pte.set_physical_page_base(physical_page.paddr().get());
         pte.set_present(true);
         pte.set_writable(true);
         pte.set_user_allowed(false);
-        flush_tlb(VirtualAddress(0xffe00000));
+        flush_tlb(vaddr);
     }
-    return (u8*)0xffe00000;
+    return vaddr.as_ptr();
 }
 
 void MemoryManager::unquickmap_page()
 {
     ASSERT_INTERRUPTS_DISABLED();
     ScopedSpinLock lock(s_lock);
-    ASSERT(m_quickmap_in_use);
-    auto& pte = boot_pd3_pt1023[0];
+    auto& mm_data = get_data();
+    ASSERT(mm_data.m_quickmap_in_use.is_locked());
+    u32 pte_idx = 8 + Processor::current().id();
+    VirtualAddress vaddr(0xffe00000 + pte_idx * PAGE_SIZE);
+    auto& pte = boot_pd3_pt1023[pte_idx];
     pte.clear();
-    flush_tlb(VirtualAddress(0xffe00000));
-    m_quickmap_in_use = false;
+    flush_tlb(vaddr);
+    mm_data.m_quickmap_in_use.unlock();
 }
 
 template<MemoryManager::AccessSpace space, MemoryManager::AccessType access_type>

+ 10 - 3
Kernel/VM/MemoryManager.h

@@ -67,6 +67,10 @@ class SynthFSInode;
 
 #define MM Kernel::MemoryManager::the()
 
+struct MemoryManagerData {
+    SpinLock<u8> m_quickmap_in_use;
+};
+
 class MemoryManager {
     AK_MAKE_ETERNAL
     friend class PageDirectory;
@@ -80,7 +84,12 @@ class MemoryManager {
 public:
     static MemoryManager& the();
 
-    static void initialize();
+    static void initialize(u32 cpu);
+    
+    static inline MemoryManagerData& get_data()
+    {
+        return Processor::current().get_mm_data();
+    }
 
     PageFaultResponse handle_page_fault(const PageFault&);
 
@@ -204,8 +213,6 @@ private:
 
     static RecursiveSpinLock s_lock;
 
-    bool m_quickmap_in_use { false };
-
     RefPtr<PhysicalPage> m_low_pseudo_identity_mapping_pages[4];
 };
 

+ 2 - 1
Kernel/init.cpp

@@ -114,7 +114,7 @@ extern "C" [[noreturn]] void init()
     }
 
     CommandLine::initialize(reinterpret_cast<const char*>(low_physical_to_virtual(multiboot_info_ptr->cmdline)));
-    MemoryManager::initialize();
+    MemoryManager::initialize(0);
 
     // Invoke all static global constructors in the kernel.
     // Note that we want to do this as early as possible.
@@ -168,6 +168,7 @@ extern "C" [[noreturn]] void init_ap(u32 cpu, Processor* processor_info)
     klog() << "CPU #" << cpu << " processor_info at " << VirtualAddress(FlatPtr(processor_info));
     cpu_setup(cpu);
     processor_info->initialize(cpu);
+    MemoryManager::initialize(cpu);
 
     APIC::the().enable(cpu);