mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 02:38:11 +00:00
Add basic paging. Only identity maps the bottom 4MB as a start.
This commit is contained in:
parent
286e27ef40
commit
77299cf54d
5 changed files with 230 additions and 2 deletions
|
@ -17,7 +17,8 @@ KERNEL_OBJS = \
|
||||||
panel.o \
|
panel.o \
|
||||||
Disk.o \
|
Disk.o \
|
||||||
Userspace.o \
|
Userspace.o \
|
||||||
IDEDiskDevice.o
|
IDEDiskDevice.o \
|
||||||
|
MemoryManager.o
|
||||||
|
|
||||||
VFS_OBJS = \
|
VFS_OBJS = \
|
||||||
../VirtualFileSystem/DiskDevice.o \
|
../VirtualFileSystem/DiskDevice.o \
|
||||||
|
|
90
Kernel/MemoryManager.cpp
Normal file
90
Kernel/MemoryManager.cpp
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
#include "MemoryManager.h"
|
||||||
|
#include <AK/Assertions.h>
|
||||||
|
#include <AK/kstdio.h>
|
||||||
|
#include <AK/kmalloc.h>
|
||||||
|
#include "i386.h"
|
||||||
|
#include "StdLib.h"
|
||||||
|
|
||||||
|
static MemoryManager* s_the;
|
||||||
|
|
||||||
|
MemoryManager& MemoryManager::the()
|
||||||
|
{
|
||||||
|
return *s_the;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryManager::MemoryManager()
|
||||||
|
{
|
||||||
|
m_pageDirectory = (dword*)0x5000;
|
||||||
|
m_pageTableZero = (dword*)0x6000;
|
||||||
|
|
||||||
|
initializePaging();
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryManager::~MemoryManager()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryManager::initializePaging()
|
||||||
|
{
|
||||||
|
static_assert(sizeof(MemoryManager::PageDirectoryEntry) == 4);
|
||||||
|
static_assert(sizeof(MemoryManager::PageTableEntry) == 4);
|
||||||
|
memset(m_pageTableZero, 0, 4096);
|
||||||
|
memset(m_pageDirectory, 0, 4096);
|
||||||
|
|
||||||
|
kprintf("MM: Page directory @ %p\n", m_pageDirectory);
|
||||||
|
kprintf("MM: Page table zero @ %p [0]=%x\n", m_pageTableZero, m_pageTableZero[0]);
|
||||||
|
// Build a basic PDB that identity maps the first 1MB.
|
||||||
|
identityMap(LinearAddress(0), 4 * MB);
|
||||||
|
|
||||||
|
asm volatile("movl %%eax, %%cr3"::"a"(m_pageDirectory));
|
||||||
|
asm volatile(
|
||||||
|
"movl %cr0, %eax\n"
|
||||||
|
"orl $0x80000001, %eax\n"
|
||||||
|
"movl %eax, %cr0\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto MemoryManager::ensurePTE(LinearAddress linearAddress) -> PageTableEntry
|
||||||
|
{
|
||||||
|
dword pageDirectoryIndex = (linearAddress.get() >> 22) & 0x3ff;
|
||||||
|
dword pageTableIndex = (linearAddress.get() >> 12) & 0x3ff;
|
||||||
|
|
||||||
|
PageDirectoryEntry pde = PageDirectoryEntry(&m_pageDirectory[pageDirectoryIndex]);
|
||||||
|
if (!pde.isPresent()) {
|
||||||
|
kprintf("PDE %u !present, allocating\n", pageDirectoryIndex);
|
||||||
|
if (pageDirectoryIndex == 0) {
|
||||||
|
pde.setPageTableBase((dword)m_pageTableZero);
|
||||||
|
pde.setUserAllowed(true);
|
||||||
|
pde.setPresent(true);
|
||||||
|
pde.setWritable(true);
|
||||||
|
} else {
|
||||||
|
// FIXME: We need an allocator!
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PageTableEntry(&pde.pageTableBase()[pageTableIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryManager::identityMap(LinearAddress linearAddress, size_t length)
|
||||||
|
{
|
||||||
|
// FIXME: ASSERT(linearAddress is 4KB aligned);
|
||||||
|
for (dword offset = 0; offset < length; offset += 4096) {
|
||||||
|
auto pteAddress = linearAddress.offset(offset);
|
||||||
|
auto pte = ensurePTE(pteAddress);
|
||||||
|
pte.setPhysicalPageBase(pteAddress.get());
|
||||||
|
pte.setUserAllowed(true);
|
||||||
|
pte.setPresent(true);
|
||||||
|
pte.setWritable(true);
|
||||||
|
if (pteAddress.get() == 0x6023) {
|
||||||
|
kprintf("kek\n");
|
||||||
|
HANG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryManager::initialize()
|
||||||
|
{
|
||||||
|
s_the = new MemoryManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
131
Kernel/MemoryManager.h
Normal file
131
Kernel/MemoryManager.h
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/Types.h>
|
||||||
|
|
||||||
|
class PhysicalAddress {
|
||||||
|
public:
|
||||||
|
PhysicalAddress() { }
|
||||||
|
explicit PhysicalAddress(dword address) : m_address(address) { }
|
||||||
|
|
||||||
|
dword get() const { return m_address; }
|
||||||
|
void set(dword address) { m_address = address; }
|
||||||
|
void mask(dword m) { m_address &= m; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
dword m_address { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
class LinearAddress {
|
||||||
|
public:
|
||||||
|
LinearAddress() { }
|
||||||
|
explicit LinearAddress(dword address) : m_address(address) { }
|
||||||
|
|
||||||
|
LinearAddress offset(dword o) const { return LinearAddress(m_address + o); }
|
||||||
|
dword get() const { return m_address; }
|
||||||
|
void set(dword address) { m_address = address; }
|
||||||
|
void mask(dword m) { m_address &= m; }
|
||||||
|
|
||||||
|
bool operator==(const LinearAddress& other) const { return m_address == other.m_address; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
dword m_address { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
class MemoryManager {
|
||||||
|
public:
|
||||||
|
static MemoryManager& the();
|
||||||
|
|
||||||
|
PhysicalAddress pageDirectoryBase() const { return PhysicalAddress(reinterpret_cast<dword>(m_pageDirectory)); }
|
||||||
|
|
||||||
|
static void initialize();
|
||||||
|
private:
|
||||||
|
MemoryManager();
|
||||||
|
~MemoryManager();
|
||||||
|
|
||||||
|
void initializePaging();
|
||||||
|
|
||||||
|
void identityMap(LinearAddress, size_t length);
|
||||||
|
|
||||||
|
struct PageDirectoryEntry {
|
||||||
|
explicit PageDirectoryEntry(dword* pde) : m_pde(pde) { }
|
||||||
|
|
||||||
|
dword* pageTableBase() { return reinterpret_cast<dword*>(raw() & 0xfffff000u); }
|
||||||
|
void setPageTableBase(dword value)
|
||||||
|
{
|
||||||
|
*m_pde &= 0xfff;
|
||||||
|
*m_pde |= value & 0xfffff000;
|
||||||
|
}
|
||||||
|
|
||||||
|
dword raw() const { return *m_pde; }
|
||||||
|
dword* ptr() { return m_pde; }
|
||||||
|
|
||||||
|
enum Flags {
|
||||||
|
Present = 1 << 0,
|
||||||
|
ReadWrite = 1 << 1,
|
||||||
|
UserSupervisor = 1 << 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool isPresent() const { return raw() & Present; }
|
||||||
|
void setPresent(bool b) { setBit(Present, b); }
|
||||||
|
|
||||||
|
bool isUserAllowed() const { return raw() & UserSupervisor; }
|
||||||
|
void setUserAllowed(bool b) { setBit(UserSupervisor, b); }
|
||||||
|
|
||||||
|
bool isWritable() const { return raw() & ReadWrite; }
|
||||||
|
void setWritable(bool b) { setBit(ReadWrite, b); }
|
||||||
|
|
||||||
|
void setBit(byte bit, bool value)
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
*m_pde |= bit;
|
||||||
|
else
|
||||||
|
*m_pde &= ~bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
dword* m_pde;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PageTableEntry {
|
||||||
|
explicit PageTableEntry(dword* pte) : m_pte(pte) { }
|
||||||
|
|
||||||
|
dword* physicalPageBase() { return reinterpret_cast<dword*>(raw() & 0xfffff000u); }
|
||||||
|
void setPhysicalPageBase(dword value)
|
||||||
|
{
|
||||||
|
*m_pte &= 0xfffu;
|
||||||
|
*m_pte |= value & 0xfffff000u;
|
||||||
|
}
|
||||||
|
|
||||||
|
dword raw() const { return *m_pte; }
|
||||||
|
dword* ptr() { return m_pte; }
|
||||||
|
|
||||||
|
enum Flags {
|
||||||
|
Present = 1 << 0,
|
||||||
|
ReadWrite = 1 << 1,
|
||||||
|
UserSupervisor = 1 << 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool isPresent() const { return raw() & Present; }
|
||||||
|
void setPresent(bool b) { setBit(Present, b); }
|
||||||
|
|
||||||
|
bool isUserAllowed() const { return raw() & UserSupervisor; }
|
||||||
|
void setUserAllowed(bool b) { setBit(UserSupervisor, b); }
|
||||||
|
|
||||||
|
bool isWritable() const { return raw() & ReadWrite; }
|
||||||
|
void setWritable(bool b) { setBit(ReadWrite, b); }
|
||||||
|
|
||||||
|
void setBit(byte bit, bool value)
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
*m_pte |= bit;
|
||||||
|
else
|
||||||
|
*m_pte &= ~bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
dword* m_pte;
|
||||||
|
};
|
||||||
|
|
||||||
|
PageTableEntry ensurePTE(LinearAddress);
|
||||||
|
|
||||||
|
dword* m_pageDirectory;
|
||||||
|
dword* m_pageTableZero;
|
||||||
|
};
|
|
@ -6,6 +6,7 @@
|
||||||
#include "i386.h"
|
#include "i386.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
|
#include "MemoryManager.h"
|
||||||
|
|
||||||
Task* current;
|
Task* current;
|
||||||
Task* s_kernelTask;
|
Task* s_kernelTask;
|
||||||
|
@ -129,6 +130,8 @@ Task::Task(void (*e)(), const char* n, IPC::Handle h, RingLevel ring)
|
||||||
m_tss.ss = stackSegment;
|
m_tss.ss = stackSegment;
|
||||||
m_tss.cs = codeSegment;
|
m_tss.cs = codeSegment;
|
||||||
|
|
||||||
|
m_tss.cr3 = MemoryManager::the().pageDirectoryBase().get();
|
||||||
|
|
||||||
m_tss.eip = (DWORD)m_entry;
|
m_tss.eip = (DWORD)m_entry;
|
||||||
|
|
||||||
// NOTE: Each task gets 4KB of stack.
|
// NOTE: Each task gets 4KB of stack.
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <VirtualFileSystem/VirtualFileSystem.h>
|
#include <VirtualFileSystem/VirtualFileSystem.h>
|
||||||
#include <VirtualFileSystem/FileHandle.h>
|
#include <VirtualFileSystem/FileHandle.h>
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
|
#include "MemoryManager.h"
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* Keyboard LED disco task ;^) */
|
/* Keyboard LED disco task ;^) */
|
||||||
|
@ -67,7 +68,7 @@ static void user_main()
|
||||||
DO_SYSCALL_A3(0x3000, 2, 3, 4);
|
DO_SYSCALL_A3(0x3000, 2, 3, 4);
|
||||||
// Crash ourselves!
|
// Crash ourselves!
|
||||||
char* x = reinterpret_cast<char*>(0xbeefbabe);
|
char* x = reinterpret_cast<char*>(0xbeefbabe);
|
||||||
*x = 1;
|
//*x = 1;
|
||||||
//HANG;
|
//HANG;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// nothing?
|
// nothing?
|
||||||
|
@ -103,6 +104,8 @@ void init()
|
||||||
gdt_init();
|
gdt_init();
|
||||||
idt_init();
|
idt_init();
|
||||||
|
|
||||||
|
MemoryManager::initialize();
|
||||||
|
|
||||||
// Anything that registers interrupts goes *after* PIC and IDT for obvious reasons.
|
// Anything that registers interrupts goes *after* PIC and IDT for obvious reasons.
|
||||||
Syscall::initialize();
|
Syscall::initialize();
|
||||||
PIT::initialize();
|
PIT::initialize();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue