mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 00:07:43 +00:00
Revert "Kernel: Move Kernel mapping to 0xc0000000"
This reverts commit bd33c66273
.
This broke the network card drivers, since they depended on kmalloc
addresses being identity-mapped.
This commit is contained in:
parent
f61ed8eab5
commit
9a157b5e81
13 changed files with 64 additions and 132 deletions
|
@ -34,9 +34,9 @@ stack_top:
|
||||||
.section .page_tables
|
.section .page_tables
|
||||||
.align 4096
|
.align 4096
|
||||||
page_tables_start:
|
page_tables_start:
|
||||||
.skip 4096*5
|
.skip 4096*3
|
||||||
|
|
||||||
.section .text.boot
|
.section .text
|
||||||
|
|
||||||
.global start
|
.global start
|
||||||
.type start, @function
|
.type start, @function
|
||||||
|
@ -51,79 +51,13 @@ start:
|
||||||
cli
|
cli
|
||||||
cld
|
cld
|
||||||
|
|
||||||
# We first save the multiboot_info_ptr so it doesn't get trampled
|
|
||||||
addl $0xc0000000, %ebx
|
|
||||||
movl %ebx, multiboot_info_ptr - 0xc0000000
|
|
||||||
|
|
||||||
# First, let's set up the first page table to map the the first 4MiB of memory.
|
|
||||||
# This makes sure we don't crash after we set CR3 and enable paging
|
|
||||||
movl $0x200, %ecx
|
|
||||||
xor %ebx, %ebx
|
|
||||||
movl $((page_tables_start + (4096 * 1)) - 0xc0000000), %edx
|
|
||||||
call make_table
|
|
||||||
|
|
||||||
# Now we create the kernel mappings. The kernel maps 0MiB -> 8MiB into its address space at
|
|
||||||
# v0xc0000000.
|
|
||||||
movl $0x400, %ecx
|
|
||||||
movl $0x0, %ebx # ebx is the base pointer (kernel base is at physical address 0 in this case)
|
|
||||||
movl $((page_tables_start + (4096 * 2)) - 0xc0000000), %edx
|
|
||||||
call make_table
|
|
||||||
|
|
||||||
movl $0x400, %ecx
|
|
||||||
movl $0x400000, %ebx # ebx is the base pointer (kernel base is at physical address 0 in this case)
|
|
||||||
movl $((page_tables_start + (4096 * 3)) - 0xc0000000), %edx
|
|
||||||
call make_table
|
|
||||||
|
|
||||||
|
|
||||||
# Okay, so we have a page table that contains addresses of the first 4MiB of memory. Let's insert this into the
|
|
||||||
# boot page directory. The index we need to insert it into is at vaddr >> 22, which is the page directory index.
|
|
||||||
# This reveals that we need to insert the page directory into 0xc0000000 >> 22 = 768
|
|
||||||
# An interesting quirk is that we must also identity map the first 4MiB too, as the next instruction after enabling
|
|
||||||
# paging is at a physical address, which cause a page fault. As we have no handler, this would cause a triple fault.
|
|
||||||
movl $((page_tables_start + (4096 * 1)) - 0xc0000000 + 0x003), page_tables_start - 0xc0000000 + 0
|
|
||||||
movl $((page_tables_start + (4096 * 2)) - 0xc0000000 + 0x003), page_tables_start - 0xc0000000 + 768 * 4
|
|
||||||
movl $((page_tables_start + (4096 * 3)) - 0xc0000000 + 0x003), page_tables_start - 0xc0000000 + 769 * 4
|
|
||||||
|
|
||||||
# Now let's load the CR3 register with our page directory
|
|
||||||
movl $(page_tables_start - 0xc0000000), %ecx
|
|
||||||
movl %ecx, %cr3
|
|
||||||
|
|
||||||
# Let's enable paging!
|
|
||||||
movl %cr0, %ecx
|
|
||||||
orl $0x80000001, %ecx
|
|
||||||
movl %ecx, %cr0
|
|
||||||
|
|
||||||
lea high_address_space_start, %ecx
|
|
||||||
jmp *%ecx
|
|
||||||
|
|
||||||
|
|
||||||
# Make a page table. This is called with the following arguments:
|
|
||||||
# ebx = base pointer of mapping
|
|
||||||
# edx = page table physical address
|
|
||||||
# ecx = number of pages to map
|
|
||||||
#
|
|
||||||
# Registers used in function
|
|
||||||
# eax = loop counter
|
|
||||||
make_table:
|
|
||||||
xorl %eax, %eax
|
|
||||||
.loop:
|
|
||||||
pushl %ecx
|
|
||||||
movl %ebx, %ecx
|
|
||||||
orl $0x3, %ecx # addr | READ_WRITE | PAGE_PRESENT
|
|
||||||
movl %ecx, 0(%edx, %eax, 4)
|
|
||||||
addl $0x1000, %ebx
|
|
||||||
inc %eax
|
|
||||||
popl %ecx
|
|
||||||
loop .loop
|
|
||||||
ret
|
|
||||||
|
|
||||||
# At this point, the CPU now starts reading instructions from (virtual) address 0xc00100000
|
|
||||||
high_address_space_start:
|
|
||||||
mov $stack_top, %esp
|
mov $stack_top, %esp
|
||||||
|
|
||||||
and $-16, %esp
|
and $-16, %esp
|
||||||
|
|
||||||
pushl $(page_tables_start - 0xc0000000)
|
mov %ebx, multiboot_info_ptr
|
||||||
|
|
||||||
|
pushl $page_tables_start
|
||||||
call init
|
call init
|
||||||
add $4, %esp
|
add $4, %esp
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
#define PAGE_SIZE 4096
|
#define PAGE_SIZE 4096
|
||||||
#define PAGE_MASK 0xfffff000
|
#define PAGE_MASK 0xfffff000
|
||||||
|
|
||||||
static const u32 kernel_virtual_base = 0xc0000000;
|
|
||||||
|
|
||||||
class MemoryManager;
|
class MemoryManager;
|
||||||
class PageTableEntry;
|
class PageTableEntry;
|
||||||
|
|
||||||
|
@ -91,7 +89,6 @@ class PageDirectoryEntry {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PageTableEntry* page_table_base() { return reinterpret_cast<PageTableEntry*>(m_raw & 0xfffff000u); }
|
PageTableEntry* page_table_base() { return reinterpret_cast<PageTableEntry*>(m_raw & 0xfffff000u); }
|
||||||
PageTableEntry* page_table_virtual_base() { return reinterpret_cast<PageTableEntry*>((m_raw + kernel_virtual_base) & 0xfffff000u); }
|
|
||||||
void set_page_table_base(u32 value)
|
void set_page_table_base(u32 value)
|
||||||
{
|
{
|
||||||
m_raw &= 0xfff;
|
m_raw &= 0xfff;
|
||||||
|
|
|
@ -116,13 +116,11 @@ void PATAChannel::initialize(bool force_pio)
|
||||||
kprintf("PATAChannel: PATA Controller found! id=%w:%w\n", id.vendor_id, id.device_id);
|
kprintf("PATAChannel: PATA Controller found! id=%w:%w\n", id.vendor_id, id.device_id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
m_prdt_page = MM.allocate_supervisor_physical_page();
|
|
||||||
m_force_pio.resource() = false;
|
m_force_pio.resource() = false;
|
||||||
if (!m_pci_address.is_null()) {
|
if (!m_pci_address.is_null()) {
|
||||||
// Let's try to set up DMA transfers.
|
// Let's try to set up DMA transfers.
|
||||||
PCI::enable_bus_mastering(m_pci_address);
|
PCI::enable_bus_mastering(m_pci_address);
|
||||||
prdt().end_of_table = 0x8000;
|
m_prdt.end_of_table = 0x8000;
|
||||||
m_bus_master_base = PCI::get_BAR4(m_pci_address) & 0xfffc;
|
m_bus_master_base = PCI::get_BAR4(m_pci_address) & 0xfffc;
|
||||||
m_dma_buffer_page = MM.allocate_supervisor_physical_page();
|
m_dma_buffer_page = MM.allocate_supervisor_physical_page();
|
||||||
kprintf("PATAChannel: Bus master IDE: I/O @ %x\n", m_bus_master_base);
|
kprintf("PATAChannel: Bus master IDE: I/O @ %x\n", m_bus_master_base);
|
||||||
|
@ -261,16 +259,16 @@ bool PATAChannel::ata_read_sectors_with_dma(u32 lba, u16 count, u8* outbuf, bool
|
||||||
|
|
||||||
disable_irq();
|
disable_irq();
|
||||||
|
|
||||||
prdt().offset = m_dma_buffer_page->paddr();
|
m_prdt.offset = m_dma_buffer_page->paddr();
|
||||||
prdt().size = 512 * count;
|
m_prdt.size = 512 * count;
|
||||||
|
|
||||||
ASSERT(prdt().size <= PAGE_SIZE);
|
ASSERT(m_prdt.size <= PAGE_SIZE);
|
||||||
|
|
||||||
// Stop bus master
|
// Stop bus master
|
||||||
IO::out8(m_bus_master_base, 0);
|
IO::out8(m_bus_master_base, 0);
|
||||||
|
|
||||||
// Write the PRDT location
|
// Write the PRDT location
|
||||||
IO::out32(m_bus_master_base + 4, (u32)&prdt());
|
IO::out32(m_bus_master_base + 4, (u32)&m_prdt);
|
||||||
|
|
||||||
// Turn on "Interrupt" and "Error" flag. The error flag should be cleared by hardware.
|
// Turn on "Interrupt" and "Error" flag. The error flag should be cleared by hardware.
|
||||||
IO::out8(m_bus_master_base + 2, IO::in8(m_bus_master_base + 2) | 0x6);
|
IO::out8(m_bus_master_base + 2, IO::in8(m_bus_master_base + 2) | 0x6);
|
||||||
|
@ -340,18 +338,18 @@ bool PATAChannel::ata_write_sectors_with_dma(u32 lba, u16 count, const u8* inbuf
|
||||||
|
|
||||||
disable_irq();
|
disable_irq();
|
||||||
|
|
||||||
prdt().offset = m_dma_buffer_page->paddr();
|
m_prdt.offset = m_dma_buffer_page->paddr();
|
||||||
prdt().size = 512 * count;
|
m_prdt.size = 512 * count;
|
||||||
|
|
||||||
memcpy(m_dma_buffer_page->paddr().as_ptr(), inbuf, 512 * count);
|
memcpy(m_dma_buffer_page->paddr().as_ptr(), inbuf, 512 * count);
|
||||||
|
|
||||||
ASSERT(prdt().size <= PAGE_SIZE);
|
ASSERT(m_prdt.size <= PAGE_SIZE);
|
||||||
|
|
||||||
// Stop bus master
|
// Stop bus master
|
||||||
IO::out8(m_bus_master_base, 0);
|
IO::out8(m_bus_master_base, 0);
|
||||||
|
|
||||||
// Write the PRDT location
|
// Write the PRDT location
|
||||||
IO::out32(m_bus_master_base + 4, (u32)&prdt());
|
IO::out32(m_bus_master_base + 4, (u32)&m_prdt);
|
||||||
|
|
||||||
// Turn on "Interrupt" and "Error" flag. The error flag should be cleared by hardware.
|
// Turn on "Interrupt" and "Error" flag. The error flag should be cleared by hardware.
|
||||||
IO::out8(m_bus_master_base + 2, IO::in8(m_bus_master_base + 2) | 0x6);
|
IO::out8(m_bus_master_base + 2, IO::in8(m_bus_master_base + 2) | 0x6);
|
||||||
|
|
|
@ -55,8 +55,6 @@ private:
|
||||||
bool ata_read_sectors(u32, u16, u8*, bool);
|
bool ata_read_sectors(u32, u16, u8*, bool);
|
||||||
bool ata_write_sectors(u32, u16, const u8*, bool);
|
bool ata_write_sectors(u32, u16, const u8*, bool);
|
||||||
|
|
||||||
PhysicalRegionDescriptor& prdt() { return *reinterpret_cast<PhysicalRegionDescriptor*>(m_prdt_page->paddr().as_ptr()); }
|
|
||||||
|
|
||||||
// Data members
|
// Data members
|
||||||
u8 m_channel_number { 0 }; // Channel number. 0 = master, 1 = slave
|
u8 m_channel_number { 0 }; // Channel number. 0 = master, 1 = slave
|
||||||
u16 m_io_base { 0x1F0 };
|
u16 m_io_base { 0x1F0 };
|
||||||
|
@ -65,7 +63,7 @@ private:
|
||||||
volatile bool m_interrupted { false };
|
volatile bool m_interrupted { false };
|
||||||
|
|
||||||
PCI::Address m_pci_address;
|
PCI::Address m_pci_address;
|
||||||
RefPtr<PhysicalPage> m_prdt_page;
|
PhysicalRegionDescriptor m_prdt;
|
||||||
RefPtr<PhysicalPage> m_dma_buffer_page;
|
RefPtr<PhysicalPage> m_dma_buffer_page;
|
||||||
u16 m_bus_master_base { 0 };
|
u16 m_bus_master_base { 0 };
|
||||||
Lockable<bool> m_dma_enabled;
|
Lockable<bool> m_dma_enabled;
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
#include <AK/Assertions.h>
|
#include <AK/Assertions.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
#include <Kernel/Arch/i386/CPU.h>
|
#include <Kernel/Arch/i386/CPU.h>
|
||||||
#include <Kernel/Heap/kmalloc.h>
|
|
||||||
#include <Kernel/KSyms.h>
|
#include <Kernel/KSyms.h>
|
||||||
#include <Kernel/Process.h>
|
#include <Kernel/Process.h>
|
||||||
#include <Kernel/Scheduler.h>
|
#include <Kernel/Scheduler.h>
|
||||||
#include <Kernel/StdLib.h>
|
#include <Kernel/StdLib.h>
|
||||||
|
#include <Kernel/Heap/kmalloc.h>
|
||||||
|
|
||||||
#define SANITIZE_KMALLOC
|
#define SANITIZE_KMALLOC
|
||||||
|
|
||||||
|
@ -20,11 +20,11 @@ struct [[gnu::packed]] allocation_t
|
||||||
size_t nchunk;
|
size_t nchunk;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define KMALLOC_RANGE_BASE (0xc0000000 + (4 * MB))
|
#define BASE_PHYSICAL (4 * MB)
|
||||||
#define CHUNK_SIZE 8
|
#define CHUNK_SIZE 8
|
||||||
#define POOL_SIZE (3 * MB)
|
#define POOL_SIZE (3 * MB)
|
||||||
|
|
||||||
#define ETERNAL_RANGE_BASE (0xc0000000 + (2 * MB))
|
#define ETERNAL_BASE_PHYSICAL (2 * MB)
|
||||||
#define ETERNAL_RANGE_SIZE (2 * MB)
|
#define ETERNAL_RANGE_SIZE (2 * MB)
|
||||||
|
|
||||||
static u8 alloc_map[POOL_SIZE / CHUNK_SIZE / 8];
|
static u8 alloc_map[POOL_SIZE / CHUNK_SIZE / 8];
|
||||||
|
@ -42,21 +42,21 @@ static u8* s_end_of_eternal_range;
|
||||||
|
|
||||||
bool is_kmalloc_address(const void* ptr)
|
bool is_kmalloc_address(const void* ptr)
|
||||||
{
|
{
|
||||||
if (ptr >= (u8*)ETERNAL_RANGE_BASE && ptr < s_next_eternal_ptr)
|
if (ptr >= (u8*)ETERNAL_BASE_PHYSICAL && ptr < s_next_eternal_ptr)
|
||||||
return true;
|
return true;
|
||||||
return (size_t)ptr >= KMALLOC_RANGE_BASE && (size_t)ptr <= (KMALLOC_RANGE_BASE + POOL_SIZE);
|
return (size_t)ptr >= BASE_PHYSICAL && (size_t)ptr <= (BASE_PHYSICAL + POOL_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kmalloc_init()
|
void kmalloc_init()
|
||||||
{
|
{
|
||||||
memset(&alloc_map, 0, sizeof(alloc_map));
|
memset(&alloc_map, 0, sizeof(alloc_map));
|
||||||
memset((void*)KMALLOC_RANGE_BASE, 0, POOL_SIZE);
|
memset((void*)BASE_PHYSICAL, 0, POOL_SIZE);
|
||||||
|
|
||||||
kmalloc_sum_eternal = 0;
|
kmalloc_sum_eternal = 0;
|
||||||
sum_alloc = 0;
|
sum_alloc = 0;
|
||||||
sum_free = POOL_SIZE;
|
sum_free = POOL_SIZE;
|
||||||
|
|
||||||
s_next_eternal_ptr = (u8*)ETERNAL_RANGE_BASE;
|
s_next_eternal_ptr = (u8*)ETERNAL_BASE_PHYSICAL;
|
||||||
s_end_of_eternal_range = s_next_eternal_ptr + ETERNAL_RANGE_SIZE;
|
s_end_of_eternal_range = s_next_eternal_ptr + ETERNAL_RANGE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ void* kmalloc_impl(size_t size)
|
||||||
++chunks_here;
|
++chunks_here;
|
||||||
|
|
||||||
if (chunks_here == chunks_needed) {
|
if (chunks_here == chunks_needed) {
|
||||||
auto* a = (allocation_t*)(KMALLOC_RANGE_BASE + (first_chunk * CHUNK_SIZE));
|
auto* a = (allocation_t*)(BASE_PHYSICAL + (first_chunk * CHUNK_SIZE));
|
||||||
u8* ptr = (u8*)a;
|
u8* ptr = (u8*)a;
|
||||||
ptr += sizeof(allocation_t);
|
ptr += sizeof(allocation_t);
|
||||||
a->nchunk = chunks_needed;
|
a->nchunk = chunks_needed;
|
||||||
|
|
|
@ -107,7 +107,7 @@ CXXFLAGS += -nostdlib -nostdinc -nostdinc++
|
||||||
CXXFLAGS += -I../Toolchain/Local/i686-pc-serenity/include/c++/8.3.0/
|
CXXFLAGS += -I../Toolchain/Local/i686-pc-serenity/include/c++/8.3.0/
|
||||||
CXXFLAGS += -I../Toolchain/Local/i686-pc-serenity/include/c++/8.3.0/i686-pc-serenity/
|
CXXFLAGS += -I../Toolchain/Local/i686-pc-serenity/include/c++/8.3.0/i686-pc-serenity/
|
||||||
DEFINES += -DKERNEL
|
DEFINES += -DKERNEL
|
||||||
LDFLAGS += -Wl,-T linker.ld -nostdlib
|
LDFLAGS += -Ttext 0x100000 -Wl,-T linker.ld -nostdlib
|
||||||
|
|
||||||
all: $(KERNEL) kernel.map
|
all: $(KERNEL) kernel.map
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#include "VirtualConsole.h"
|
#include "VirtualConsole.h"
|
||||||
#include "IO.h"
|
#include "IO.h"
|
||||||
#include "StdLib.h"
|
#include "StdLib.h"
|
||||||
|
#include <Kernel/Heap/kmalloc.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <Kernel/Arch/i386/CPU.h>
|
#include <Kernel/Arch/i386/CPU.h>
|
||||||
#include <Kernel/Devices/KeyboardDevice.h>
|
#include <Kernel/Devices/KeyboardDevice.h>
|
||||||
#include <Kernel/Heap/kmalloc.h>
|
|
||||||
|
|
||||||
static u8* s_vga_buffer;
|
static u8* s_vga_buffer;
|
||||||
static VirtualConsole* s_consoles[6];
|
static VirtualConsole* s_consoles[6];
|
||||||
|
@ -32,7 +32,7 @@ void VirtualConsole::flush_vga_cursor()
|
||||||
|
|
||||||
void VirtualConsole::initialize()
|
void VirtualConsole::initialize()
|
||||||
{
|
{
|
||||||
s_vga_buffer = (u8*)(kernel_virtual_base + 0xb8000);
|
s_vga_buffer = (u8*)0xb8000;
|
||||||
memset(s_consoles, 0, sizeof(s_consoles));
|
memset(s_consoles, 0, sizeof(s_consoles));
|
||||||
s_active_console = -1;
|
s_active_console = -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,7 @@ MemoryManager::MemoryManager(u32 physical_address_for_kernel_page_tables)
|
||||||
{
|
{
|
||||||
m_kernel_page_directory = PageDirectory::create_at_fixed_address(PhysicalAddress(physical_address_for_kernel_page_tables));
|
m_kernel_page_directory = PageDirectory::create_at_fixed_address(PhysicalAddress(physical_address_for_kernel_page_tables));
|
||||||
m_page_table_zero = (PageTableEntry*)(physical_address_for_kernel_page_tables + PAGE_SIZE);
|
m_page_table_zero = (PageTableEntry*)(physical_address_for_kernel_page_tables + PAGE_SIZE);
|
||||||
m_page_table_768 = (PageTableEntry*)(physical_address_for_kernel_page_tables + PAGE_SIZE * 2);
|
m_page_table_one = (PageTableEntry*)(physical_address_for_kernel_page_tables + PAGE_SIZE * 2);
|
||||||
m_page_table_769 = (PageTableEntry*)(physical_address_for_kernel_page_tables + PAGE_SIZE * 3);
|
|
||||||
initialize_paging();
|
initialize_paging();
|
||||||
|
|
||||||
kprintf("MM initialized.\n");
|
kprintf("MM initialized.\n");
|
||||||
|
@ -39,6 +38,7 @@ void MemoryManager::populate_page_directory(PageDirectory& page_directory)
|
||||||
{
|
{
|
||||||
page_directory.m_directory_page = allocate_supervisor_physical_page();
|
page_directory.m_directory_page = allocate_supervisor_physical_page();
|
||||||
page_directory.entries()[0].copy_from({}, kernel_page_directory().entries()[0]);
|
page_directory.entries()[0].copy_from({}, kernel_page_directory().entries()[0]);
|
||||||
|
page_directory.entries()[1].copy_from({}, kernel_page_directory().entries()[1]);
|
||||||
// Defer to the kernel page tables for 0xC0000000-0xFFFFFFFF
|
// Defer to the kernel page tables for 0xC0000000-0xFFFFFFFF
|
||||||
for (int i = 768; i < 1024; ++i)
|
for (int i = 768; i < 1024; ++i)
|
||||||
page_directory.entries()[i].copy_from({}, kernel_page_directory().entries()[i]);
|
page_directory.entries()[i].copy_from({}, kernel_page_directory().entries()[i]);
|
||||||
|
@ -47,6 +47,7 @@ void MemoryManager::populate_page_directory(PageDirectory& page_directory)
|
||||||
void MemoryManager::initialize_paging()
|
void MemoryManager::initialize_paging()
|
||||||
{
|
{
|
||||||
memset(m_page_table_zero, 0, PAGE_SIZE);
|
memset(m_page_table_zero, 0, PAGE_SIZE);
|
||||||
|
memset(m_page_table_one, 0, PAGE_SIZE);
|
||||||
|
|
||||||
#ifdef MM_DEBUG
|
#ifdef MM_DEBUG
|
||||||
dbgprintf("MM: Kernel page directory @ %p\n", kernel_page_directory().cr3());
|
dbgprintf("MM: Kernel page directory @ %p\n", kernel_page_directory().cr3());
|
||||||
|
@ -59,12 +60,16 @@ void MemoryManager::initialize_paging()
|
||||||
map_protected(VirtualAddress(0), PAGE_SIZE);
|
map_protected(VirtualAddress(0), PAGE_SIZE);
|
||||||
|
|
||||||
#ifdef MM_DEBUG
|
#ifdef MM_DEBUG
|
||||||
dbgprintf("MM: Identity map bottom 1MiB\n", kernel_virtual_base);
|
dbgprintf("MM: Identity map bottom 8MB\n");
|
||||||
#endif
|
#endif
|
||||||
create_identity_mapping(kernel_page_directory(), VirtualAddress(PAGE_SIZE), (1 * MB) - PAGE_SIZE);
|
// The bottom 8 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), (8 * MB) - PAGE_SIZE);
|
||||||
|
|
||||||
|
// FIXME: We should move everything kernel-related above the 0xc0000000 virtual mark.
|
||||||
|
|
||||||
// Basic physical memory map:
|
// Basic physical memory map:
|
||||||
// 0 -> 1 MB Page table/directory / I/O memory region
|
// 0 -> 1 MB We're just leaving this alone for now.
|
||||||
// 1 -> 3 MB Kernel image.
|
// 1 -> 3 MB Kernel image.
|
||||||
// (last page before 2MB) Used by quickmap_page().
|
// (last page before 2MB) Used by quickmap_page().
|
||||||
// 2 MB -> 4 MB kmalloc_eternal() space.
|
// 2 MB -> 4 MB kmalloc_eternal() space.
|
||||||
|
@ -73,10 +78,8 @@ void MemoryManager::initialize_paging()
|
||||||
// 8 MB -> MAX Userspace physical pages (available for allocation!)
|
// 8 MB -> MAX Userspace physical pages (available for allocation!)
|
||||||
|
|
||||||
// Basic virtual memory map:
|
// Basic virtual memory map:
|
||||||
// 0x00000000-0x00100000 Identity mapped for Kernel Physical pages handed out by allocate_supervisor_physical_page (for I/O, page tables etc).
|
// 0 MB -> 8MB Identity mapped.
|
||||||
// 0x00800000-0xbfffffff Userspace program virtual address space.
|
// 0xc0000000-0xffffffff Kernel-only virtual address space.
|
||||||
// 0xc0001000-0xc0800000 Kernel-only virtual address space. This area is mapped to the first 8 MB of physical memory and includes areas for kmalloc, etc.
|
|
||||||
// 0xc0800000-0xffffffff Kernel virtual address space for kernel Page Directory.
|
|
||||||
|
|
||||||
#ifdef MM_DEBUG
|
#ifdef MM_DEBUG
|
||||||
dbgprintf("MM: Quickmap will use %p\n", m_quickmap_addr.get());
|
dbgprintf("MM: Quickmap will use %p\n", m_quickmap_addr.get());
|
||||||
|
@ -97,6 +100,10 @@ void MemoryManager::initialize_paging()
|
||||||
if (mmap->type != MULTIBOOT_MEMORY_AVAILABLE)
|
if (mmap->type != MULTIBOOT_MEMORY_AVAILABLE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// FIXME: Maybe make use of stuff below the 1MB mark?
|
||||||
|
if (mmap->addr < (1 * MB))
|
||||||
|
continue;
|
||||||
|
|
||||||
if ((mmap->addr + mmap->len) > 0xffffffff)
|
if ((mmap->addr + mmap->len) > 0xffffffff)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -124,8 +131,9 @@ void MemoryManager::initialize_paging()
|
||||||
for (size_t page_base = mmap->addr; page_base < (mmap->addr + mmap->len); page_base += PAGE_SIZE) {
|
for (size_t page_base = mmap->addr; page_base < (mmap->addr + mmap->len); page_base += PAGE_SIZE) {
|
||||||
auto addr = PhysicalAddress(page_base);
|
auto addr = PhysicalAddress(page_base);
|
||||||
|
|
||||||
// Anything below 1 * MB is a Kernel Physical region
|
if (page_base < 7 * MB) {
|
||||||
if (page_base > PAGE_SIZE && page_base < 1 * MB) {
|
// nothing
|
||||||
|
} else if (page_base >= 7 * MB && page_base < 8 * MB) {
|
||||||
if (region.is_null() || !region_is_super || region->upper().offset(PAGE_SIZE) != addr) {
|
if (region.is_null() || !region_is_super || region->upper().offset(PAGE_SIZE) != addr) {
|
||||||
m_super_physical_regions.append(PhysicalRegion::create(addr, addr));
|
m_super_physical_regions.append(PhysicalRegion::create(addr, addr));
|
||||||
region = m_super_physical_regions.last();
|
region = m_super_physical_regions.last();
|
||||||
|
@ -133,7 +141,7 @@ void MemoryManager::initialize_paging()
|
||||||
} else {
|
} else {
|
||||||
region->expand(region->lower(), addr);
|
region->expand(region->lower(), addr);
|
||||||
}
|
}
|
||||||
} else if (page_base > 8 * MB) {
|
} else {
|
||||||
if (region.is_null() || region_is_super || region->upper().offset(PAGE_SIZE) != addr) {
|
if (region.is_null() || region_is_super || region->upper().offset(PAGE_SIZE) != addr) {
|
||||||
m_user_physical_regions.append(PhysicalRegion::create(addr, addr));
|
m_user_physical_regions.append(PhysicalRegion::create(addr, addr));
|
||||||
region = m_user_physical_regions.last();
|
region = m_user_physical_regions.last();
|
||||||
|
@ -154,6 +162,7 @@ void MemoryManager::initialize_paging()
|
||||||
#ifdef MM_DEBUG
|
#ifdef MM_DEBUG
|
||||||
dbgprintf("MM: Installing page directory\n");
|
dbgprintf("MM: Installing page directory\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Turn on CR4.PGE so the CPU will respect the G bit in page tables.
|
// Turn on CR4.PGE so the CPU will respect the G bit in page tables.
|
||||||
asm volatile(
|
asm volatile(
|
||||||
"mov %cr4, %eax\n"
|
"mov %cr4, %eax\n"
|
||||||
|
@ -166,6 +175,10 @@ void MemoryManager::initialize_paging()
|
||||||
"orl $0x80000001, %%eax\n"
|
"orl $0x80000001, %%eax\n"
|
||||||
"movl %%eax, %%cr0\n" ::
|
"movl %%eax, %%cr0\n" ::
|
||||||
: "%eax", "memory");
|
: "%eax", "memory");
|
||||||
|
|
||||||
|
#ifdef MM_DEBUG
|
||||||
|
dbgprintf("MM: Paging initialized.\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
PageTableEntry& MemoryManager::ensure_pte(PageDirectory& page_directory, VirtualAddress vaddr)
|
PageTableEntry& MemoryManager::ensure_pte(PageDirectory& page_directory, VirtualAddress vaddr)
|
||||||
|
@ -186,16 +199,9 @@ PageTableEntry& MemoryManager::ensure_pte(PageDirectory& page_directory, Virtual
|
||||||
pde.set_present(true);
|
pde.set_present(true);
|
||||||
pde.set_writable(true);
|
pde.set_writable(true);
|
||||||
pde.set_global(true);
|
pde.set_global(true);
|
||||||
} else if (page_directory_index == 768) {
|
} else if (page_directory_index == 1) {
|
||||||
ASSERT(&page_directory == m_kernel_page_directory);
|
ASSERT(&page_directory == m_kernel_page_directory);
|
||||||
pde.set_page_table_base((u32)m_page_table_768);
|
pde.set_page_table_base((u32)m_page_table_one);
|
||||||
pde.set_user_allowed(false);
|
|
||||||
pde.set_present(true);
|
|
||||||
pde.set_writable(true);
|
|
||||||
pde.set_global(true);
|
|
||||||
} else if (page_directory_index == 769) {
|
|
||||||
ASSERT(&page_directory == m_kernel_page_directory);
|
|
||||||
pde.set_page_table_base((u32)m_page_table_769);
|
|
||||||
pde.set_user_allowed(false);
|
pde.set_user_allowed(false);
|
||||||
pde.set_present(true);
|
pde.set_present(true);
|
||||||
pde.set_writable(true);
|
pde.set_writable(true);
|
||||||
|
@ -221,7 +227,7 @@ PageTableEntry& MemoryManager::ensure_pte(PageDirectory& page_directory, Virtual
|
||||||
page_directory.m_physical_pages.set(page_directory_index, move(page_table));
|
page_directory.m_physical_pages.set(page_directory_index, move(page_table));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pde.page_table_virtual_base()[page_table_index];
|
return pde.page_table_base()[page_table_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryManager::map_protected(VirtualAddress vaddr, size_t length)
|
void MemoryManager::map_protected(VirtualAddress vaddr, size_t length)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/String.h>
|
||||||
#include <AK/Badge.h>
|
#include <AK/Badge.h>
|
||||||
#include <AK/Bitmap.h>
|
#include <AK/Bitmap.h>
|
||||||
#include <AK/ByteBuffer.h>
|
#include <AK/ByteBuffer.h>
|
||||||
|
@ -7,7 +8,6 @@
|
||||||
#include <AK/NonnullRefPtrVector.h>
|
#include <AK/NonnullRefPtrVector.h>
|
||||||
#include <AK/RefCounted.h>
|
#include <AK/RefCounted.h>
|
||||||
#include <AK/RefPtr.h>
|
#include <AK/RefPtr.h>
|
||||||
#include <AK/String.h>
|
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
#include <AK/Weakable.h>
|
#include <AK/Weakable.h>
|
||||||
|
@ -114,8 +114,7 @@ private:
|
||||||
|
|
||||||
RefPtr<PageDirectory> m_kernel_page_directory;
|
RefPtr<PageDirectory> m_kernel_page_directory;
|
||||||
PageTableEntry* m_page_table_zero { nullptr };
|
PageTableEntry* m_page_table_zero { nullptr };
|
||||||
PageTableEntry* m_page_table_768 { nullptr };
|
PageTableEntry* m_page_table_one { nullptr };
|
||||||
PageTableEntry* m_page_table_769 { nullptr };
|
|
||||||
|
|
||||||
VirtualAddress m_quickmap_addr;
|
VirtualAddress m_quickmap_addr;
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ RefPtr<PageDirectory> PageDirectory::find_by_pdb(u32 pdb)
|
||||||
}
|
}
|
||||||
|
|
||||||
PageDirectory::PageDirectory(PhysicalAddress paddr)
|
PageDirectory::PageDirectory(PhysicalAddress paddr)
|
||||||
: m_range_allocator(VirtualAddress(kernelspace_range_base + 0x800000), 0x3f000000)
|
: m_range_allocator(VirtualAddress(0xc0000000), 0x3f000000)
|
||||||
{
|
{
|
||||||
m_directory_page = PhysicalPage::create(paddr, true, false);
|
m_directory_page = PhysicalPage::create(paddr, true, false);
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
|
|
|
@ -22,7 +22,7 @@ public:
|
||||||
~PageDirectory();
|
~PageDirectory();
|
||||||
|
|
||||||
u32 cr3() const { return m_directory_page->paddr().get(); }
|
u32 cr3() const { return m_directory_page->paddr().get(); }
|
||||||
PageDirectoryEntry* entries() { return reinterpret_cast<PageDirectoryEntry*>(cr3() + kernel_virtual_base); }
|
PageDirectoryEntry* entries() { return reinterpret_cast<PageDirectoryEntry*>(cr3()); }
|
||||||
|
|
||||||
void flush(VirtualAddress);
|
void flush(VirtualAddress);
|
||||||
|
|
||||||
|
|
|
@ -252,7 +252,7 @@ void Region::map(PageDirectory& page_directory)
|
||||||
pte.set_user_allowed(is_user_accessible());
|
pte.set_user_allowed(is_user_accessible());
|
||||||
page_directory.flush(page_vaddr);
|
page_directory.flush(page_vaddr);
|
||||||
#ifdef MM_DEBUG
|
#ifdef MM_DEBUG
|
||||||
kprintf("MM: >> map_region_at_address (PD=%p) '%s' V%p => P%p (@%p)\n", &page_directory, name().characters(), page_vaddr.get(), physical_page ? physical_page->paddr().get() : 0, physical_page.ptr());
|
dbgprintf("MM: >> map_region_at_address (PD=%p) '%s' V%p => P%p (@%p)\n", &page_directory, name().characters(), page_vaddr.get(), physical_page ? physical_page->paddr().get() : 0, physical_page.ptr());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@ ENTRY(start)
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
. = 0xc0100000;
|
. = 0x100000;
|
||||||
|
|
||||||
.text ALIGN(4K) : AT(ADDR(.text) - 0xc0000000)
|
.text BLOCK(4K) : ALIGN(4K)
|
||||||
{
|
{
|
||||||
Arch/i386/Boot/boot.ao
|
Arch/i386/Boot/boot.ao
|
||||||
*(.multiboot)
|
*(.multiboot)
|
||||||
|
@ -13,7 +13,7 @@ SECTIONS
|
||||||
*(.text.startup)
|
*(.text.startup)
|
||||||
}
|
}
|
||||||
|
|
||||||
.rodata ALIGN(4K) : AT(ADDR(.rodata) - 0xc0000000)
|
.rodata BLOCK(4K) : ALIGN(4K)
|
||||||
{
|
{
|
||||||
start_ctors = .;
|
start_ctors = .;
|
||||||
*(.ctors)
|
*(.ctors)
|
||||||
|
@ -22,12 +22,12 @@ SECTIONS
|
||||||
*(.rodata)
|
*(.rodata)
|
||||||
}
|
}
|
||||||
|
|
||||||
.data ALIGN(4K) : AT(ADDR(.data) - 0xc0000000)
|
.data BLOCK(4K) : ALIGN(4K)
|
||||||
{
|
{
|
||||||
*(.data)
|
*(.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
.bss ALIGN(4K) : AT(ADDR(.bss) - 0xc0000000)
|
.bss BLOCK(4K) : ALIGN(4K)
|
||||||
{
|
{
|
||||||
*(COMMON)
|
*(COMMON)
|
||||||
*(.bss)
|
*(.bss)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue