1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-06-01 05:38:15 +00:00

Kernel: Add a quickmap region for each processor

Threads need to be able to concurrently quickmap things.
This commit is contained in:
Tom 2020-06-28 16:04:35 -06:00 committed by Andreas Kling
parent d249b5df8f
commit 2a38cc9a12
5 changed files with 56 additions and 22 deletions

View file

@ -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)

View file

@ -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;

View file

@ -207,8 +207,15 @@ 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)
{
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;
}
@ -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>

View file

@ -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];
};

View file

@ -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);