Initialize paging before KernelInit.
This commit is contained in:
parent
a422c394b8
commit
218875eb79
|
@ -44,6 +44,8 @@
|
|||
|
||||
#include "com.h"
|
||||
|
||||
extern "C" unsigned char nullpage[4096];
|
||||
|
||||
namespace Sortix {
|
||||
namespace COM {
|
||||
|
||||
|
@ -101,12 +103,6 @@ static const unsigned int UART_16750 = 5;
|
|||
|
||||
static const size_t NUM_COM_PORTS = 4;
|
||||
|
||||
// The IO base ports of each COM port.
|
||||
static uint16_t com_ports[1 + NUM_COM_PORTS];
|
||||
|
||||
// The results of running HardwareProbe on each COM port.
|
||||
static unsigned int hw_version[1 + NUM_COM_PORTS];
|
||||
|
||||
// Uses various characteristics of the UART chips to determine the hardware.
|
||||
static unsigned int HardwareProbe(uint16_t port)
|
||||
{
|
||||
|
@ -145,20 +141,6 @@ static inline bool CanWriteByte(uint16_t port)
|
|||
return inport8(port + LSR) & LSR_THRE;
|
||||
}
|
||||
|
||||
void EarlyInit()
|
||||
{
|
||||
// We can fetch COM port information from the BIOS Data Area.
|
||||
const uint16_t* bioscom_ports = (const uint16_t*) 0x0400UL;
|
||||
|
||||
for ( size_t i = 1; i <= NUM_COM_PORTS; i++ )
|
||||
{
|
||||
if ( !(com_ports[i] = bioscom_ports[i-1]) )
|
||||
continue;
|
||||
hw_version[i] = HardwareProbe(com_ports[i]);
|
||||
outport8(com_ports[i] + IER, 0x0);
|
||||
}
|
||||
}
|
||||
|
||||
class DevCOMPort : public AbstractInode
|
||||
{
|
||||
public:
|
||||
|
@ -282,6 +264,21 @@ static Ref<DevCOMPort> com_devices[1 + NUM_COM_PORTS];
|
|||
|
||||
void Init(const char* devpath, Ref<Descriptor> slashdev)
|
||||
{
|
||||
uint16_t com_ports[1 + NUM_COM_PORTS];
|
||||
unsigned int hw_version[1 + NUM_COM_PORTS];
|
||||
|
||||
const uint16_t* bioscom_ports = (const uint16_t*) (nullpage + 0x400);
|
||||
|
||||
for ( size_t i = 1; i <= NUM_COM_PORTS; i++ )
|
||||
{
|
||||
if ( !(com_ports[i] = bioscom_ports[i-1]) )
|
||||
continue;
|
||||
hw_version[i] = HardwareProbe(com_ports[i]);
|
||||
outport8(com_ports[i] + IER, 0x0);
|
||||
}
|
||||
|
||||
(void) hw_version;
|
||||
|
||||
ioctx_t ctx; SetupKernelIOCtx(&ctx);
|
||||
|
||||
for ( size_t i = 1; i <= NUM_COM_PORTS; i++ )
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
namespace Sortix {
|
||||
namespace COM {
|
||||
|
||||
void EarlyInit();
|
||||
void Init(const char* devpath, Ref<Descriptor> slashdev);
|
||||
|
||||
} // namespace COM
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014, 2015.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
|
@ -91,7 +91,7 @@ void Flush();
|
|||
addr_t Fork();
|
||||
addr_t GetAddressSpace();
|
||||
addr_t SwitchAddressSpace(addr_t addrspace);
|
||||
void DestroyAddressSpace(addr_t fallback = 0);
|
||||
void DestroyAddressSpace(addr_t fallback);
|
||||
bool Map(addr_t physical, addr_t mapto, int prot);
|
||||
addr_t Unmap(addr_t mapto);
|
||||
addr_t Physical(addr_t mapto);
|
||||
|
|
|
@ -189,9 +189,6 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo)
|
|||
|
||||
// TODO: Call global constructors using the _init function.
|
||||
|
||||
// Detect and initialize any serial COM ports in the system.
|
||||
COM::EarlyInit();
|
||||
|
||||
// Setup a text buffer handle for use by the text terminal.
|
||||
uint16_t* const VGAFB = (uint16_t*) 0xB8000;
|
||||
const size_t VGA_WIDTH = 80;
|
||||
|
@ -256,9 +253,8 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo)
|
|||
"Use a 32-bit OS 3) Use another version of qemu.");
|
||||
#endif
|
||||
|
||||
if ( !bootinfo )
|
||||
Panic("The bootinfo structure was NULL. Is your bootloader multiboot "
|
||||
"compliant?");
|
||||
// Detect available physical memory.
|
||||
Memory::Init(bootinfo);
|
||||
|
||||
initrd = 0;
|
||||
initrdsize = 0;
|
||||
|
@ -271,13 +267,8 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo)
|
|||
break;
|
||||
}
|
||||
|
||||
if ( !initrd ) { PanicF("No init ramdisk provided"); }
|
||||
|
||||
// Initialize paging and virtual memory.
|
||||
Memory::Init(bootinfo);
|
||||
|
||||
// Initialize the interrupt handler table and enable interrupts.
|
||||
Interrupt::Init();
|
||||
if ( !initrd )
|
||||
Panic("No init ramdisk provided");
|
||||
|
||||
// Load the kernel symbols if provided by the bootloader.
|
||||
do if ( bootinfo->flags & MULTIBOOT_INFO_ELF_SHDR )
|
||||
|
@ -387,6 +378,9 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo)
|
|||
SetKernelSymbolTable(symbols, elf_symbol_count-1);
|
||||
} while ( false );
|
||||
|
||||
// Initialize the interrupt handler table and enable interrupts.
|
||||
Interrupt::Init();
|
||||
|
||||
// Initialize the interrupt worker (before scheduling is enabled).
|
||||
Interrupt::InitWorker();
|
||||
|
||||
|
|
|
@ -32,6 +32,40 @@
|
|||
.long 0x00000003 # Flags.
|
||||
.long -(0x1BADB002 + 0x00000003) # Checksum
|
||||
|
||||
.section .bss, "aw", @nobits
|
||||
.align 4096
|
||||
bootpml4:
|
||||
.skip 4096
|
||||
bootpml3:
|
||||
.skip 4096
|
||||
bootpml2:
|
||||
.skip 4096
|
||||
bootpml1_a:
|
||||
.skip 4096
|
||||
bootpml1_b:
|
||||
.skip 4096
|
||||
fracpml3:
|
||||
.skip 4096
|
||||
fracpml2:
|
||||
.skip 4096
|
||||
fracpml1:
|
||||
.skip 4096
|
||||
forkpml2:
|
||||
.skip 4096
|
||||
forkpml1:
|
||||
.skip 4096
|
||||
physpml3:
|
||||
.skip 4096
|
||||
physpml2:
|
||||
.skip 4096
|
||||
physpml1:
|
||||
.skip 4096
|
||||
physpml0:
|
||||
.skip 4096
|
||||
nullpage: .global nullpage
|
||||
.skip 4096
|
||||
|
||||
.section .text
|
||||
.global _start
|
||||
.global __start
|
||||
.type _start, @function
|
||||
|
@ -61,42 +95,53 @@ __start:
|
|||
pushl $0
|
||||
pushl %ebx # Multiboot information structure pointer.
|
||||
|
||||
# Clear the first $0xE000 bytes following 0x21000.
|
||||
movl $0x21000, %edi
|
||||
movl $bootpml4, %edi
|
||||
movl %edi, %cr3
|
||||
xorl %eax, %eax
|
||||
movl $0xE000, %ecx
|
||||
rep stosl
|
||||
movl %cr3, %edi
|
||||
|
||||
# Set the initial page tables.
|
||||
# Note that we OR with 0x7 here to allow user-space access, except in the
|
||||
# first 2 MiB. We also do this with 0x200 to allow forking the page.
|
||||
# Page-Map Level 4.
|
||||
movl $(bootpml3 + 0x207), bootpml4 + 0 * 8
|
||||
|
||||
# Page-Map Level 4
|
||||
movl $0x22207, (%edi)
|
||||
addl $0x1000, %edi
|
||||
# Page Directory Pointer Table.
|
||||
movl $(bootpml2 + 0x207), bootpml3 + 0 * 8
|
||||
|
||||
# Page-Directory Pointer Table
|
||||
movl $0x23207, (%edi)
|
||||
addl $0x1000, %edi
|
||||
|
||||
# Page-Directory (no user-space access here)
|
||||
movl $0x24003, (%edi) # (First 2 MiB)
|
||||
movl $0x25003, 8(%edi) # (Second 2 MiB)
|
||||
addl $0x1000, %edi
|
||||
|
||||
# Page-Table
|
||||
# Memory map the first 4 MiB.
|
||||
movl $0x3, %ebx
|
||||
movl $1024, %ecx
|
||||
# Page Directory (no user-space access here).
|
||||
movl $(bootpml1_a + 0x003), bootpml2 + 0 * 8
|
||||
movl $(bootpml1_b + 0x003), bootpml2 + 1 * 8
|
||||
|
||||
# Page Table (identity map the first 4 MiB, except NULL).
|
||||
movl $(bootpml1_a + 8), %edi
|
||||
movl $0x1003, %esi
|
||||
movl $1023, %ecx
|
||||
1:
|
||||
movl %ebx, (%edi)
|
||||
addl $0x1000, %ebx
|
||||
movl %esi, (%edi)
|
||||
addl $0x1000, %esi
|
||||
addl $8, %edi
|
||||
loop 1b
|
||||
|
||||
# Map the null page.
|
||||
movl $nullpage, %edi
|
||||
shrl $12, %edi
|
||||
movl $0x0003, bootpml1_a(, %edi, 8)
|
||||
|
||||
# Fractal mapping.
|
||||
movl $(bootpml4 + 0x003), bootpml4 + 511 * 8
|
||||
movl $(fracpml3 + 0x203), bootpml4 + 510 * 8
|
||||
movl $(bootpml4 + 0x003), fracpml3 + 511 * 8
|
||||
movl $(fracpml2 + 0x203), fracpml3 + 510 * 8
|
||||
movl $(bootpml4 + 0x003), fracpml2 + 511 * 8
|
||||
movl $(fracpml1 + 0x203), fracpml2 + 510 * 8
|
||||
movl $(bootpml4 + 0x003), fracpml1 + 511 * 8
|
||||
|
||||
# Predefined room for forking address spaces.
|
||||
movl $(forkpml2 + 0x203), fracpml3 + 0 * 8
|
||||
movl $(forkpml1 + 0x203), forkpml2 + 0 * 8
|
||||
|
||||
# Physical page allocator.
|
||||
movl $(physpml3 + 0x003), bootpml4 + 509 * 8
|
||||
movl $(physpml2 + 0x003), physpml3 + 0 * 8
|
||||
movl $(physpml1 + 0x003), physpml2 + 0 * 8
|
||||
movl $(physpml0 + 0x003), physpml1 + 0 * 8
|
||||
|
||||
# Enable PAE.
|
||||
movl %cr4, %eax
|
||||
orl $0x20, %eax
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014, 2015.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
|
@ -31,83 +31,9 @@
|
|||
#include "multiboot.h"
|
||||
#include "x86-family/memorymanagement.h"
|
||||
|
||||
namespace Sortix {
|
||||
namespace Page {
|
||||
|
||||
extern size_t stackused;
|
||||
extern size_t stacklength;
|
||||
void ExtendStack();
|
||||
|
||||
} // namespace Page
|
||||
} // namespace Sortix
|
||||
|
||||
namespace Sortix {
|
||||
namespace Memory {
|
||||
|
||||
void InitCPU()
|
||||
{
|
||||
// The x64 boot code already set up virtual memory and identity
|
||||
// mapped the first 2 MiB. This code finishes the job such that
|
||||
// virtual memory is fully usable and manageable.
|
||||
|
||||
// boot.s already initialized everything from 0x21000UL to 0x2F000UL to
|
||||
// zeroes. Since these structures are already used, doing it here would
|
||||
// destroying the existing data.
|
||||
|
||||
PML* const BOOTPML4 = (PML* const) 0x21000UL;
|
||||
PML* const BOOTPML3 = (PML* const) 0x26000UL;
|
||||
PML* const BOOTPML2 = (PML* const) 0x27000UL;
|
||||
PML* const BOOTPML1 = (PML* const) 0x28000UL;
|
||||
|
||||
// First order of business is to map the virtual memory structures
|
||||
// to the pre-defined locations in the virtual address space.
|
||||
addr_t flags = PML_PRESENT | PML_WRITABLE;
|
||||
|
||||
// Fractal map the PML1s.
|
||||
BOOTPML4->entry[511] = (addr_t) BOOTPML4 | flags;
|
||||
|
||||
// Fractal map the PML2s.
|
||||
BOOTPML4->entry[510] = (addr_t) BOOTPML3 | flags | PML_FORK;
|
||||
BOOTPML3->entry[511] = (addr_t) BOOTPML4 | flags;
|
||||
|
||||
// Fractal map the PML3s.
|
||||
BOOTPML3->entry[510] = (addr_t) BOOTPML2 | flags | PML_FORK;
|
||||
BOOTPML2->entry[511] = (addr_t) BOOTPML4 | flags;
|
||||
|
||||
// Fractal map the PML4s.
|
||||
BOOTPML2->entry[510] = (addr_t) BOOTPML1 | flags | PML_FORK;
|
||||
BOOTPML1->entry[511] = (addr_t) BOOTPML4 | flags;
|
||||
|
||||
// Add some predefined room for forking address spaces.
|
||||
PML* const FORKPML2 = (PML* const) 0x29000UL;
|
||||
PML* const FORKPML1 = (PML* const) 0x2A000UL;
|
||||
|
||||
BOOTPML3->entry[0] = (addr_t) FORKPML2 | flags | PML_FORK;
|
||||
FORKPML2->entry[0] = (addr_t) FORKPML1 | flags | PML_FORK;
|
||||
|
||||
// The virtual memory structures are now available on the predefined
|
||||
// locations. This means the virtual memory code is bootstrapped. Of
|
||||
// course, we still have no physical page allocator, so that's the
|
||||
// next step.
|
||||
|
||||
PML* const PHYSPML3 = (PML* const) 0x2B000UL;
|
||||
PML* const PHYSPML2 = (PML* const) 0x2C000UL;
|
||||
PML* const PHYSPML1 = (PML* const) 0x2D000UL;
|
||||
PML* const PHYSPML0 = (PML* const) 0x2E000UL;
|
||||
|
||||
BOOTPML4->entry[509] = (addr_t) PHYSPML3 | flags;
|
||||
PHYSPML3->entry[0] = (addr_t) PHYSPML2 | flags;
|
||||
PHYSPML2->entry[0] = (addr_t) PHYSPML1 | flags;
|
||||
PHYSPML1->entry[0] = (addr_t) PHYSPML0 | flags;
|
||||
|
||||
Page::stackused = 0;
|
||||
Page::stacklength = 4096UL / sizeof(addr_t);
|
||||
|
||||
// The physical memory allocator should now be ready for use. Next
|
||||
// up, the calling function will fill up the physical allocator with
|
||||
// plenty of nice physical pages. (see Page::InitPushRegion)
|
||||
}
|
||||
|
||||
// Please note that even if this function exists, you should still clean
|
||||
// up the address space of a process _before_ calling
|
||||
// DestroyAddressSpace. This is just a hack because it currently is
|
||||
|
@ -156,13 +82,6 @@ void DestroyAddressSpace(addr_t fallback)
|
|||
// TODO: Page::Put calls may internally Page::Get and then reusing pages we are not done with just yet
|
||||
RecursiveFreeUserspacePages(TOPPMLLEVEL, 0);
|
||||
|
||||
// Switch to the address space from when the world was originally
|
||||
// created. It should contain the kernel, the whole kernel, and
|
||||
// nothing but the kernel.
|
||||
PML* const BOOTPML4 = (PML* const) 0x21000UL;
|
||||
if ( !fallback )
|
||||
fallback = (addr_t) BOOTPML4;
|
||||
|
||||
SwitchAddressSpace(fallback);
|
||||
|
||||
// Ok, now we got marked everything left behind as unused, we can
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014, 2015.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
|
@ -49,13 +49,13 @@ namespace Sortix {
|
|||
namespace Page {
|
||||
|
||||
void InitPushRegion(addr_t position, size_t length);
|
||||
size_t pagesnotonstack;
|
||||
size_t stackused;
|
||||
size_t stackreserved;
|
||||
size_t stacklength;
|
||||
size_t totalmem;
|
||||
size_t pagesnotonstack = 0;
|
||||
size_t stackused = 0;
|
||||
size_t stackreserved = 0;
|
||||
size_t stacklength = 4096 / sizeof(addr_t);
|
||||
size_t totalmem = 0;
|
||||
size_t page_usage_counts[PAGE_USAGE_NUM_KINDS];
|
||||
kthread_mutex_t pagelock;
|
||||
kthread_mutex_t pagelock = KTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
} // namespace Page
|
||||
} // namespace Sortix
|
||||
|
@ -63,7 +63,6 @@ kthread_mutex_t pagelock;
|
|||
namespace Sortix {
|
||||
namespace Memory {
|
||||
|
||||
void InitCPU();
|
||||
void AllocateKernelPMLs();
|
||||
int SysMemStat(size_t* memused, size_t* memtotal);
|
||||
addr_t PAT2PMLFlags[PAT_NUM];
|
||||
|
@ -80,12 +79,7 @@ void InitCPU(multiboot_info_t* bootinfo)
|
|||
MAXKERNELEND);
|
||||
}
|
||||
|
||||
Page::stackreserved = 0;
|
||||
Page::pagesnotonstack = 0;
|
||||
Page::totalmem = 0;
|
||||
Page::pagelock = KTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
if ( !( bootinfo->flags & MULTIBOOT_INFO_MEM_MAP ) )
|
||||
if ( !(bootinfo->flags & MULTIBOOT_INFO_MEM_MAP) )
|
||||
Panic("memorymanagement.cpp: The memory map flag was't set in "
|
||||
"the multiboot structure. Are your bootloader multiboot "
|
||||
"specification compliant?");
|
||||
|
@ -98,9 +92,8 @@ void InitCPU(multiboot_info_t* bootinfo)
|
|||
for ( addr_t i = 0; i < PAT_NUM; i++ )
|
||||
PAT2PMLFlags[i] = EncodePATAsPMLFlag(i);
|
||||
}
|
||||
// Otherwise, reroute all requests to the backwards compatible
|
||||
// scheme. TODO: Not all early 32-bit x86 CPUs supports these
|
||||
// values, so we need yet another fallback.
|
||||
// Otherwise, reroute all requests to the backwards compatible scheme.
|
||||
// TODO: Not all early 32-bit x86 CPUs supports these values.
|
||||
else
|
||||
{
|
||||
PAT2PMLFlags[PAT_UC] = PML_WRTHROUGH | PML_NOCACHE;
|
||||
|
@ -113,9 +106,6 @@ void InitCPU(multiboot_info_t* bootinfo)
|
|||
PAT2PMLFlags[PAT_UCM] = PML_NOCACHE;
|
||||
}
|
||||
|
||||
// Initialize CPU-specific things.
|
||||
InitCPU();
|
||||
|
||||
typedef const multiboot_memory_map_t* mmap_t;
|
||||
|
||||
// Loop over every detected memory region.
|
||||
|
@ -203,8 +193,6 @@ void InitCPU(multiboot_info_t* bootinfo)
|
|||
Log::PrintF("%zu bytes of RAM aren't used due to technical "
|
||||
"restrictions.\n", (size_t) (Page::pagesnotonstack * 0x1000UL));
|
||||
|
||||
Memory::Unmap(0x0); // Remove NULL.
|
||||
|
||||
// Finish allocating the top level PMLs for the kernels use.
|
||||
AllocateKernelPMLs();
|
||||
}
|
||||
|
|
|
@ -32,6 +32,22 @@
|
|||
.long 0x00000003 # Flags.
|
||||
.long -(0x1BADB002 + 0x00000003) # Checksum.
|
||||
|
||||
.section .bss, "aw", @nobits
|
||||
.align 4096
|
||||
bootpml2:
|
||||
.skip 4096
|
||||
bootpml1:
|
||||
.skip 4096
|
||||
fracpml1:
|
||||
.skip 4096
|
||||
physpml1:
|
||||
.skip 4096
|
||||
physpml0:
|
||||
.skip 4096
|
||||
nullpage: .global nullpage
|
||||
.skip 4096
|
||||
|
||||
.section .text
|
||||
.global _start
|
||||
.global __start
|
||||
.type _start, @function
|
||||
|
@ -52,6 +68,41 @@ __start:
|
|||
shrl $8, %ecx
|
||||
movb %cl, gdt + 0x28 + 7
|
||||
|
||||
movl $bootpml2, %edi
|
||||
movl %edi, %cr3
|
||||
|
||||
# Page Directory.
|
||||
movl $(bootpml1 + 0x003), bootpml2 + 0 * 4
|
||||
|
||||
# Page Table (identity map the first 4 MiB, except NULL).
|
||||
movl $(bootpml1 + 4), %edi
|
||||
movl $0x1003, %esi
|
||||
movl $1023, %ecx
|
||||
1:
|
||||
movl %esi, (%edi)
|
||||
addl $0x1000, %esi
|
||||
addl $4, %edi
|
||||
loop 1b
|
||||
|
||||
# Map the null page.
|
||||
movl $nullpage, %edi
|
||||
shrl $12, %edi
|
||||
movl $0x0003, bootpml1(, %edi, 4)
|
||||
|
||||
# Fractal mapping.
|
||||
movl $(bootpml2 + 0x003), bootpml2 + 1023 * 4
|
||||
movl $(fracpml1 + 0x203), bootpml2 + 1022 * 4
|
||||
movl $(bootpml2 + 0x003), fracpml1 + 1023 * 4
|
||||
|
||||
# Physical page allocator.
|
||||
movl $(physpml1 + 0x003), bootpml2 + 1021 * 4
|
||||
movl $(physpml0 + 0x003), physpml1 + 0 * 4
|
||||
|
||||
# Enable paging.
|
||||
movl %cr0, %edi
|
||||
orl $0x80000000, %edi
|
||||
movl %edi, %cr0
|
||||
|
||||
# Load the Global Descriptor Table pointer register.
|
||||
subl $6, %esp
|
||||
movw gdt_size_minus_one, %cx
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014, 2015.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
|
@ -45,64 +45,6 @@ void ExtendStack();
|
|||
namespace Sortix {
|
||||
namespace Memory {
|
||||
|
||||
void InitCPU()
|
||||
{
|
||||
PML* const BOOTPML2 = (PML* const) 0x11000UL;
|
||||
PML* const BOOTPML1 = (PML* const) 0x12000UL;
|
||||
//PML* const FORKPML1 = (PML* const) 0x13000UL;
|
||||
PML* const IDENPML1 = (PML* const) 0x14000UL;
|
||||
|
||||
// Initialize the memory structures with zeroes.
|
||||
memset((PML* const) 0x11000UL, 0, 0x6000UL);
|
||||
|
||||
// Identity map the first 4 MiB.
|
||||
addr_t flags = PML_PRESENT | PML_WRITABLE;
|
||||
|
||||
BOOTPML2->entry[0] = ((addr_t) IDENPML1) | flags;
|
||||
|
||||
for ( size_t i = 0; i < ENTRIES; i++ )
|
||||
IDENPML1->entry[i] = (i * 4096UL) | flags;
|
||||
|
||||
// Next order of business is to map the virtual memory structures
|
||||
// to the pre-defined locations in the virtual address space.
|
||||
|
||||
// Fractal map the PML1s.
|
||||
BOOTPML2->entry[1023] = (addr_t) BOOTPML2 | flags;
|
||||
|
||||
// Fractal map the PML2s.
|
||||
BOOTPML2->entry[1022] = (addr_t) BOOTPML1 | flags | PML_FORK;
|
||||
BOOTPML1->entry[1023] = (addr_t) BOOTPML2 | flags;
|
||||
|
||||
// Add some predefined room for forking address spaces.
|
||||
BOOTPML1->entry[0] = 0; // (addr_t) FORKPML1 | flags | PML_FORK;
|
||||
|
||||
// The virtual memory structures are now available on the predefined
|
||||
// locations. This means the virtual memory code is bootstrapped. Of
|
||||
// course, we still have no physical page allocator, so that's the
|
||||
// next step.
|
||||
|
||||
PML* const PHYSPML1 = (PML* const) 0x15000UL;
|
||||
PML* const PHYSPML0 = (PML* const) 0x16000UL;
|
||||
|
||||
BOOTPML2->entry[1021] = (addr_t) PHYSPML1 | flags;
|
||||
PHYSPML1->entry[0] = (addr_t) PHYSPML0 | flags;
|
||||
|
||||
// Alright, enable virtual memory!
|
||||
SwitchAddressSpace((addr_t) BOOTPML2);
|
||||
|
||||
size_t cr0;
|
||||
asm volatile("mov %%cr0, %0": "=r"(cr0));
|
||||
cr0 |= 0x80000000UL; /* Enable paging! */
|
||||
asm volatile("mov %0, %%cr0":: "r"(cr0));
|
||||
|
||||
Page::stackused = 0;
|
||||
Page::stacklength = 4096UL / sizeof(addr_t);
|
||||
|
||||
// The physical memory allocator should now be ready for use. Next
|
||||
// up, the calling function will fill up the physical allocator with
|
||||
// plenty of nice physical pages. (see Page::InitPushRegion)
|
||||
}
|
||||
|
||||
// Please note that even if this function exists, you should still clean
|
||||
// up the address space of a process _before_ calling
|
||||
// DestroyAddressSpace. This is just a hack because it currently is
|
||||
|
@ -147,13 +89,6 @@ void DestroyAddressSpace(addr_t fallback)
|
|||
// TODO: Page::Put calls may internally Page::Get and then reusing pages we are not done with just yet
|
||||
RecursiveFreeUserspacePages(TOPPMLLEVEL, 0);
|
||||
|
||||
// Switch to the address space from when the world was originally
|
||||
// created. It should contain the kernel, the whole kernel, and
|
||||
// nothing but the kernel.
|
||||
PML* const BOOTPML2 = (PML* const) 0x11000UL;
|
||||
if ( !fallback )
|
||||
fallback = (addr_t) BOOTPML2;
|
||||
|
||||
SwitchAddressSpace(fallback);
|
||||
|
||||
// Ok, now we got marked everything left behind as unused, we can
|
||||
|
|
Loading…
Reference in New Issue