mirror of
https://github.com/RGBCube/serenity
synced 2025-05-16 18:45:07 +00:00
Kernel: Use the Multiboot memory map info to inform our paging setup.
This makes it possible to run Serenity with more than 64 MB of RAM. Because each physical page is represented by a PhysicalPage object, and such objects are allocated using kmalloc_eternal(), more RAM means more pressure on kmalloc_eternal(), so we're gonna need a better strategy for this. But for now, let's just celebrate that we can use the 128 MB of RAM we've been telling QEMU to run with. :^)
This commit is contained in:
parent
8258b699db
commit
9da62f52a1
4 changed files with 63 additions and 30 deletions
|
@ -5,6 +5,7 @@
|
|||
#include <AK/kstdio.h>
|
||||
#include <Kernel/Arch/i386/CPU.h>
|
||||
#include <Kernel/FileSystem/Inode.h>
|
||||
#include <Kernel/Multiboot.h>
|
||||
#include <Kernel/VM/MemoryManager.h>
|
||||
|
||||
//#define MM_DEBUG
|
||||
|
@ -21,18 +22,9 @@ MemoryManager& MM
|
|||
|
||||
MemoryManager::MemoryManager()
|
||||
{
|
||||
// FIXME: This is not the best way to do memory map detection.
|
||||
// Rewrite to use BIOS int 15,e820 once we have VM86 support.
|
||||
word base_memory = (CMOS::read(0x16) << 8) | CMOS::read(0x15);
|
||||
word ext_memory = (CMOS::read(0x18) << 8) | CMOS::read(0x17);
|
||||
|
||||
kprintf("%u kB base memory\n", base_memory);
|
||||
kprintf("%u kB extended memory\n", ext_memory);
|
||||
|
||||
m_ram_size = ext_memory * 1024;
|
||||
|
||||
m_kernel_page_directory = PageDirectory::create_at_fixed_address(PhysicalAddress(0x4000));
|
||||
m_page_table_zero = (dword*)0x6000;
|
||||
m_page_table_one = (dword*)0x7000;
|
||||
|
||||
initialize_paging();
|
||||
|
||||
|
@ -47,6 +39,7 @@ void MemoryManager::populate_page_directory(PageDirectory& page_directory)
|
|||
{
|
||||
page_directory.m_directory_page = allocate_supervisor_physical_page();
|
||||
page_directory.entries()[0] = kernel_page_directory().entries()[0];
|
||||
page_directory.entries()[1] = kernel_page_directory().entries()[1];
|
||||
// Defer to the kernel page tables for 0xC0000000-0xFFFFFFFF
|
||||
for (int i = 768; i < 1024; ++i)
|
||||
page_directory.entries()[i] = kernel_page_directory().entries()[i];
|
||||
|
@ -57,6 +50,7 @@ void MemoryManager::initialize_paging()
|
|||
static_assert(sizeof(MemoryManager::PageDirectoryEntry) == 4);
|
||||
static_assert(sizeof(MemoryManager::PageTableEntry) == 4);
|
||||
memset(m_page_table_zero, 0, PAGE_SIZE);
|
||||
memset(m_page_table_one, 0, PAGE_SIZE);
|
||||
|
||||
#ifdef MM_DEBUG
|
||||
dbgprintf("MM: Kernel page directory @ %p\n", kernel_page_directory().cr3());
|
||||
|
@ -69,27 +63,48 @@ void MemoryManager::initialize_paging()
|
|||
map_protected(VirtualAddress(0), PAGE_SIZE);
|
||||
|
||||
#ifdef MM_DEBUG
|
||||
dbgprintf("MM: Identity map bottom 4MB\n");
|
||||
dbgprintf("MM: Identity map bottom 5MB\n");
|
||||
#endif
|
||||
// The bottom 4 MB (except for the null page) are identity mapped & supervisor only.
|
||||
// The bottom 5 MB (except for the null page) are identity mapped & supervisor only.
|
||||
// Every process shares these mappings.
|
||||
create_identity_mapping(kernel_page_directory(), VirtualAddress(PAGE_SIZE), (4 * MB) - PAGE_SIZE);
|
||||
create_identity_mapping(kernel_page_directory(), VirtualAddress(PAGE_SIZE), (5 * MB) - PAGE_SIZE);
|
||||
|
||||
// Basic memory map:
|
||||
// 0 -> 512 kB Kernel code. Root page directory & PDE 0.
|
||||
// (last page before 1MB) Used by quickmap_page().
|
||||
// 1 MB -> 2 MB kmalloc_eternal() space.
|
||||
// 2 MB -> 3 MB kmalloc() space.
|
||||
// 3 MB -> 4 MB Supervisor physical pages (available for allocation!)
|
||||
// 4 MB -> 0xc0000000 Userspace physical pages (available for allocation!)
|
||||
// 1 MB -> 3 MB kmalloc_eternal() space.
|
||||
// 3 MB -> 4 MB kmalloc() space.
|
||||
// 4 MB -> 5 MB Supervisor physical pages (available for allocation!)
|
||||
// 5 MB -> 0xc0000000 Userspace physical pages (available for allocation!)
|
||||
// 0xc0000000-0xffffffff Kernel-only linear address space
|
||||
|
||||
for (size_t i = (2 * MB); i < (4 * MB); i += PAGE_SIZE)
|
||||
m_free_supervisor_physical_pages.append(PhysicalPage::create_eternal(PhysicalAddress(i), true));
|
||||
for (auto* mmap = (multiboot_memory_map_t*)multiboot_info_ptr->mmap_addr; (unsigned long)mmap < multiboot_info_ptr->mmap_addr + multiboot_info_ptr->mmap_length; mmap = (multiboot_memory_map_t*)((unsigned long)mmap + mmap->size + sizeof(mmap->size))) {
|
||||
kprintf("MM: Multiboot mmap: base_addr = 0x%x%08x, length = 0x%x%08x, type = 0x%x\n",
|
||||
(dword)(mmap->addr >> 32),
|
||||
(dword)(mmap->addr & 0xffffffff),
|
||||
(dword)(mmap->len >> 32),
|
||||
(dword)(mmap->len & 0xffffffff),
|
||||
(dword)mmap->type);
|
||||
|
||||
if (mmap->type != MULTIBOOT_MEMORY_AVAILABLE)
|
||||
continue;
|
||||
// FIXME: Maybe make use of stuff below the 1MB mark?
|
||||
if (mmap->addr < (1 * MB))
|
||||
continue;
|
||||
|
||||
for (size_t page_base = mmap->addr; page_base < (mmap->addr + mmap->len); page_base += PAGE_SIZE) {
|
||||
if (page_base < (4 * MB)) {
|
||||
// Skip over pages managed by kmalloc.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (page_base < (5 * MB))
|
||||
m_free_supervisor_physical_pages.append(PhysicalPage::create_eternal(PhysicalAddress(page_base), true));
|
||||
else
|
||||
m_free_physical_pages.append(PhysicalPage::create_eternal(PhysicalAddress(page_base), false));
|
||||
}
|
||||
}
|
||||
|
||||
dbgprintf("MM: 4MB-%uMB available for allocation\n", m_ram_size / 1048576);
|
||||
for (size_t i = (4 * MB); i < m_ram_size; i += PAGE_SIZE)
|
||||
m_free_physical_pages.append(PhysicalPage::create_eternal(PhysicalAddress(i), false));
|
||||
m_quickmap_addr = VirtualAddress((1 * MB) - PAGE_SIZE);
|
||||
#ifdef MM_DEBUG
|
||||
dbgprintf("MM: Quickmap will use P%x\n", m_quickmap_addr.get());
|
||||
|
@ -150,6 +165,12 @@ auto MemoryManager::ensure_pte(PageDirectory& page_directory, VirtualAddress vad
|
|||
pde.set_user_allowed(false);
|
||||
pde.set_present(true);
|
||||
pde.set_writable(true);
|
||||
} else if (page_directory_index == 1) {
|
||||
ASSERT(&page_directory == m_kernel_page_directory);
|
||||
pde.set_page_table_base((dword)m_page_table_one);
|
||||
pde.set_user_allowed(false);
|
||||
pde.set_present(true);
|
||||
pde.set_writable(true);
|
||||
} else {
|
||||
//ASSERT(&page_directory != m_kernel_page_directory.ptr());
|
||||
auto page_table = allocate_page_table(page_directory, page_directory_index);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue