Working on the PMM

alentours-dev
Sergiusz Bazanski 2011-07-02 13:03:29 +02:00
parent f096be37a2
commit e04c28f1be
12 changed files with 494 additions and 281 deletions

View File

@ -3,36 +3,93 @@
#include "types.h"
struct S_PAGING_PAGE {
u8 Present : 1;
u8 RW : 1;
u8 User : 1;
u8 Accessed : 1;
u8 Misc : 8;
u32 Physical : 20;
// Some helpful macros
#define PAGING_GET_ML4_INDEX(x) (((u64)x >> 39) & 0x1FF)
#define PAGING_GET_DPT_INDEX(x) (((u64)x >> 30) & 0x1FF)
#define PAGING_GET_DIR_INDEX(x) (((u64)x >> 21) & 0x1FF)
#define PAGING_GET_TAB_INDEX(x) (((u64)x >> 12) & 0x1FF)
#define PAGING_GET_PAGE_OFFSET(x) (x & 0xFFF)
// Intel-defined entries - strict!
struct S_PAGING_TAB_ENTRY {
u8 Present : 1;
u8 RW : 1;
u8 User : 1;
u8 Accessed : 1;
u8 Misc : 8;
u64 Physical : 40; // The physical address is limited by MAXPHYADDR
u16 Zero : 12;
} __attribute__((packed));
typedef struct S_PAGING_TAB_ENTRY T_PAGING_TAB_ENTRY;
typedef struct S_PAGING_PAGE T_PAGING_PAGE;
struct S_PAGING_DIR_ENTRY {
u8 Present : 1;
u8 RW : 1;
u8 User : 1;
u8 Accessed : 1;
u8 Misc : 8;
u64 Physical : 40; // The physical address is limited by MAXPHYADDR
u64 Zero : 12;
} __attribute__((packed));
typedef struct S_PAGING_DIR_ENTRY T_PAGING_DIR_ENTRY;
struct S_PAGING_DPT_ENTRY {
u8 Present : 1;
u8 RW : 1;
u8 User : 1;
u8 Accessed : 1;
u8 Misc : 8;
u64 Physical : 40; // The physical address is limited by MAXPHYADDR
u64 Zero : 12;
} __attribute__((packed));
typedef struct S_PAGING_DPT_ENTRY T_PAGING_DPT_ENTRY;
struct S_PAGING_ML4_ENTRY {
u8 Present : 1;
u8 RW : 1;
u8 User : 1;
u8 Accessed : 1;
u8 Misc : 8;
u64 Physical : 40; // The physical address is limited by MAXPHYADDR
u64 Zero : 12;
} __attribute__((packed));
typedef struct S_PAGING_ML4_ENTRY T_PAGING_ML4_ENTRY;
// OS-defined structures - semi-loose.
typedef struct {
T_PAGING_TAB_ENTRY Entries[512];
u64 PhysicalAddress;
} T_PAGING_TAB;
typedef struct {
T_PAGING_PAGE Pages[1024];
} T_PAGING_TABLE;
T_PAGING_DIR_ENTRY Entries[512]; // For use by CPU
T_PAGING_TAB *Children[512]; // For use by OS
u64 PhysicalAddress; // FOr use by OS when setting CPU
} T_PAGING_DIR;
typedef struct {
u32 Entries[1024];
T_PAGING_TABLE *Tables[1024];
u32 PhysicalAddress;
} T_PAGING_DIRECTORY;
T_PAGING_DPT_ENTRY Entries[512];
T_PAGING_DIR *Children[512];
u64 PhysicalAddress;
} T_PAGING_DPT;
void paging_init_simple(void);
u8 paging_get_physical(u64 Virtual, u64 *Physical);
u8 paging_get_physical_ex(u64 Virtual, u64 *Physical,
T_PAGING_DIRECTORY *Directory);
void paging_map_kernel_page(u64 Virtual, u64 Physical);
typedef struct {
T_PAGING_ML4_ENTRY Entries[512];
T_PAGING_DPT *Children[512];
u64 PhysicalAddress;
} T_PAGING_ML4;
void paging_init_simple(u64 PhysicalVirtualOffset);
T_PAGING_ML4 * paging_get_ml4(void);
u8 paging_get_physical(u64 Virtual, u64 *Physical);
u8 paging_get_physical_ex(u64 Virtual, u64 *Physical,T_PAGING_ML4 *ML4);
/*void paging_map_kernel_page(u64 Virtual, u64 Physical);
void paging_map_kernel_table(u64 Virtual, u64 Physical);
void paging_map_page(u64 Virtual, u64 Physical, T_PAGING_DIRECTORY *Directory,
u8 User, u8 RW);
void paging_use_directory(T_PAGING_DIRECTORY *Directory);
T_PAGING_DIRECTORY *paging_get_directory(void);
T_PAGING_DIRECTORY *paging_get_directory(void);*/
#endif

View File

@ -3,13 +3,24 @@
#include "types.h"
void physmem_init(void);
#define PHYSALLOC_PAGE_SIZE 4096
#define PHYSALLOC_NUM_BITMAPS ((4096 * 8 / 64) - 1)
void physmem_mark_as_used(u32 Page);
u32 physmem_allocate_page(void);
void physmem_free_page(u32 Page);
struct S_PHYSALLOC_NODE {
u64 Bitmaps[PHYSALLOC_NUM_BITMAPS];
struct S_PHYSALLOC_NODE *Next;
};
u32 physmem_page_to_physical(u32 Page);
u32 physmem_physical_to_page(u32 Physical);
typedef struct S_PHYSALLOC_NODE T_PHYSALLOC_NODE;
void physmem_init(u64 MemorySize);
void physmem_set_node_space(u64 Space);
void physmem_mark_as_used(u64 Page);
u64 physmem_allocate_page(void);
void physmem_free_page(u64 Page);
u64 physmem_page_to_physical(u64 Page);
u64 physmem_physical_to_page(u64 Physical);
#endif

View File

@ -3,24 +3,22 @@
struct S_SYSTEM_MLTBT_MMAP {
u32 Size;
u32 BaseLow;
u32 BaseHigh;
u32 LengthLow;
u32 LengthHigh;
u64 Base;
u64 Length;
u32 Type;
} __attribute__ ((packed));
typedef struct S_SYSTEM_MLTBT_MMAP T_SYSTEM_MLTBT_MMAP;
struct S_SYSTEM_INVALID_RAM {
u32 Base;
u32 Size;
u64 Base;
u64 Size;
} __attribute__ ((packed));
typedef struct S_SYSTEM_INVALID_RAM T_SYSTEM_INVALID_RAM;
void system_parse_multiboot_header(void *Header);
u32 system_get_memory_upper(void);
u32 system_get_memory_lower(void);
u64 system_get_memory_upper(void);
u64 system_get_memory_lower(void);
s8 *system_get_bootloader_name(void);
u8 system_memory_available(u32 Start, u32 Length);
u8 system_memory_available(u64 Start, u64 Length);
#endif

View File

@ -1,22 +1,24 @@
#include "types.h"
#include "Tier0/kstdio.h"
/*#include "Tier0/gdt.h"
//#include "Tier0/gdt.h"
#include "Tier0/paging.h"
#include "Tier0/acpi.h"
#include "Tier0/interrupts.h"
#include "Tier0/ps2.h"
//#include "Tier0/acpi.h"
//#include "Tier0/interrupts.h"
//#include "Tier0/ps2.h"
#include "Tier0/system.h"
#include "Tier0/pic.h"
#include "Tier0/kbd_layout.h"
#include "Tier0/physical_alloc.h"
#include "Tier0/heap.h"
#include "Tier0/cpp.h"
#include "Tier0/exceptions.h"
#include "Tier0/panic.h"
#include "Tier0/prng.h"*/
//#include "Tier0/pic.h"
//#include "Tier0/kbd_layout.h"
//#include "Tier0/physical_alloc.h"
//#include "Tier0/heap.h"
//#include "Tier0/cpp.h"
//#include "Tier0/exceptions.h"
//#include "Tier0/panic.h"
//#include "Tier0/prng.h"
extern u64 _end;
// Real kernel entry point, called from loader
void kmain(u32 current_line, u32 cursor_x, u32 cursor_y)
void kmain(u32 current_line, u32 cursor_x, u32 cursor_y, u32 MultibootHeader)
{
kstdio_init();
kstdio_set_globals(current_line, cursor_x, cursor_y);
@ -26,19 +28,18 @@ void kmain(u32 current_line, u32 cursor_x, u32 cursor_y)
" | _| | | _| | | | . | -_| _|\n"
" |___|___|___|___|_|_|_|___|___|_| \n\n");
kprintf("[i] Welcome to Cucumber (x86-64)!\n");
//kprintf("%x %x %x\n", current_line, cursor_x, cursor_y);
kprintf("[i] Multiboot header @%x\n", MultibootHeader);
system_parse_multiboot_header((void*)((u64)MultibootHeader));
kprintf("[i] Booting via %s.\n", system_get_bootloader_name());
kprintf("[i] Memory available: %uk.\n", system_get_memory_upper());
kprintf("[i] Kernel end: %x.\n", &_end);
//paging_init_simple();
for (;;) {}
/*if (Magic != 0x2BADB002)
{
kprintf("[e] Fatal! Boot via incompatible bootloader.\n");
return;
}
paging_init_simple();
gdt_create_flat();
/*gdt_create_flat();
physmem_init();
system_parse_multiboot_header(MultibootHeader);

View File

@ -1,43 +1,72 @@
#include "Tier0/paging.h"
#include "Tier0/system.h"
#include "Tier0/kstdio.h"
#include "Tier0/kstdlib.h"
#include "Tier0/interrupts.h"
#include "Tier0/heap.h"
#include "types.h"
T_PAGING_DIRECTORY g_kernel_page_directory __attribute__ ((aligned (4096)));
T_PAGING_TABLE g_kernel_page_tables[1024] __attribute__ ((aligned (4096)));
// The basic structures for the first kernel thread...
// Since they are < 2Mib, their virtual addresses = their physical addresses -
// some offset given by the loader
//T_PAGING_ML4 g_paging_basic_ml4;
// These are the structures for mapping the lowest 2MiB
//T_PAGING_ML4 g_paging_basic_dpt_lowmap;
//T_PAGING_ML4 g_paging_basic_dir_lowmap;
//T_PAGING_ML4 g_paging_basic_tab_lowmap;
// These are the structures for mapping the kernel memory (2Mib)
//T_PAGING_ML4 g_paging_basic_dpt_kernel;
//T_PAGING_ML4 g_paging_basic_dir_kernel;
//T_PAGING_ML4 g_paging_basic_tab_kernel;
u8 paging_get_physical_ex(u32 Virtual, u32 *Physical,
T_PAGING_DIRECTORY *Directory)
T_PAGING_ML4 *paging_get_ml4(void)
{
u16 DirectoryIndex = (Virtual >> 22) & 0x3FF;
u32 DirectoryEntry = Directory->Entries[DirectoryIndex];
u8 TablePresent = DirectoryEntry & 0b1;
if (!TablePresent)
return 0;
T_PAGING_TABLE *Table = Directory->Tables[DirectoryIndex];
u16 TableIndex = (Virtual >> 12) & 0x3FF;
T_PAGING_PAGE Page = (Table->Pages[TableIndex]);
if (!Page.Present)
return 0;
*Physical = (Page.Physical << 12);
*Physical |= (Virtual & 0xFFF);
return 1;
u64 Address;
__asm__ volatile("mov %%cr3, %0\n" : "=r"(Address));
return (T_PAGING_ML4*)Address;
}
u8 paging_get_physical(u32 Virtual, u32 *Physical)
u8 paging_get_physical_ex(u64 Virtual, u64 *Physical, T_PAGING_ML4 *ML4)
{
return paging_get_physical_ex(Virtual, Physical, &g_kernel_page_directory);
u16 ML4Index = PAGING_GET_ML4_INDEX(Virtual);
u16 DPTIndex = PAGING_GET_DPT_INDEX(Virtual);
u16 DirIndex = PAGING_GET_DIR_INDEX(Virtual);
u16 TabIndex = PAGING_GET_TAB_INDEX(Virtual);
if (!ML4->Entries[ML4Index].Present)
return 1;
T_PAGING_DPT *DPT = ML4->Children[ML4Index];
if (!DPT->Entries[DPTIndex].Present)
return 1;
T_PAGING_DIR *Dir = DPT->Children[DPTIndex];
if (!Dir->Entries[DirIndex].Present)
return 1;
T_PAGING_TAB *Tab = Dir->Children[DirIndex];
if (!Tab->Entries[TabIndex].Present)
return 1;
(*Physical) = (Tab->Entries[TabIndex].Physical << 12) + PAGING_GET_PAGE_OFFSET(Virtual);
return 0;
}
void paging_dump_directory(void)
u8 paging_get_physical(u64 Virtual, u64 *Physical)
{
T_PAGING_ML4 *ml4 = paging_get_ml4();
return paging_get_physical_ex(Virtual, Physical, ml4);
return 0;
}
// This initializes a very basic paging structure for the first kernel thread
void paging_init_simple(u64 PhysicalVirtualOffset)
{
}
/*void paging_dump_directory(void)
{
for (u32 i = 0; i < 10; i++)
{
@ -167,5 +196,5 @@ void paging_init_simple(void)
paging_map_kernel_table(0xC0400000, 0x00400000);
paging_use_directory(&g_kernel_page_directory);
}
}*/

View File

@ -1,6 +1,6 @@
#include "Tier0/panic.h"
#include "Tier0/kstdio.h"
#include "Tier0/prng.h"
//#include "Tier0/prng.h"
#include "preprocessor_hacks.h"
#define KPANIC_HEADER(n) KPANIC_HEADER##n
@ -21,7 +21,8 @@
char *kpanic_get_random_message(void)
{
u16 N = krand() % 10;
//u16 N = krand() % 10;
u16 N = 0;
switch (N)
{
PPHAX_DO10(KPANIC_CASE);
@ -71,7 +72,7 @@ void kpanic_ex(const s8 *Error, const s8 *File, u32 Line, T_ISR_REGISTERS R)
// Dumping registers
u32 ds, cr0, cr3;
/*u32 ds, cr0, cr3;
__asm__ volatile("mov %%cr0, %0": "=r"(cr0));
__asm__ volatile("mov %%cr3, %0": "=r"(cr3));
@ -84,13 +85,13 @@ void kpanic_ex(const s8 *Error, const s8 *File, u32 Line, T_ISR_REGISTERS R)
kprintf(" eax: 0x%X ebx: 0x%x ecx: 0x%x edx: 0x%x\n",
R.eax, R.ebx, R.ecx, R.edx);
kprintf(" esi: 0x%X edi: 0x%x ebp: 0x%x esp: 0x%x\n",
R.esi, R.edi, R.ebp, R.esp);
R.esi, R.edi, R.ebp, R.esp);*/
//s32 FrameSize = R.ebp - R.esp;
/*if (FrameSize > 0 && FrameSize < 0x100)
{*/
kprintf("\n stack frame looks promising...\n");
/*kprintf("\n stack frame looks promising...\n");
kprintf(" attempting stack dump:\n");
u32 Number = 80;
@ -98,7 +99,7 @@ void kpanic_ex(const s8 *Error, const s8 *File, u32 Line, T_ISR_REGISTERS R)
{
kprintf(" %x %x %x %x %x %x %x %x\n",
*v, *(v+1), *(v+2), *(v+3), *(v+4), *(v+5), *(v+6), *(v+7));
}
}*/
/*}
else
kprintf("\n stack looks unusable, not dummping.\n");*/

View File

@ -0,0 +1,153 @@
// Kinda like a heap, but not really.
// (the following sizes are for x86)
// Based on a very large number of 4k pages. They are kept in a linear list
// of 512 64-bit (4kbyte) bitmaps. If there aren't any free pages in the
// bitmap, oh we want to mark a page as reserved further down in the list,
// then we create a new one and link the together. Freeing pages does not
// (yet?) free bitmaps. We always reserve one page for extending the list.
#include "Tier0/physical_alloc.h"
#include "Tier0/kstdio.h"
#include "Tier0/panic.h"
T_PHYSALLOC_NODE g_physalloc_root_node;
T_PHYSALLOC_NODE *g_physalloc_top_node;
u64 g_physalloc_list_size = 1;
u64 g_physalloc_space_for_next = 0;
u64 g_physalloc_mem_max = 0;
void physmem_zero_node(T_PHYSALLOC_NODE *Node)
{
for (u64 i = 0; i < PHYSALLOC_NUM_BITMAPS; i++)
Node->Bitmaps[i] = 0;
Node->Next = 0;
}
void physmem_init(u64 MemorySize)
{
// Create the first node
physmem_zero_node(&g_physalloc_root_node);
g_physalloc_top_node = &g_physalloc_root_node;
g_physalloc_mem_max = MemorySize;
}
void physmem_create_node(void)
{
if (!g_physalloc_space_for_next)
PANIC("No space for next physmem node! :o");
T_PHYSALLOC_NODE *NewNode = (T_PHYSALLOC_NODE *)g_physalloc_space_for_next;
physmem_zero_node(NewNode);
g_physalloc_top_node->Next = NewNode;
g_physalloc_top_node = NewNode;
g_physalloc_space_for_next = physmem_allocate_page();
g_physalloc_list_size++;
}
T_PHYSALLOC_NODE *physmem_traverse_list(u64 Index)
{
if (Index > g_physalloc_list_size)
PANIC("Tried to traverse list too far!");
u32 Current = 0;
T_PHYSALLOC_NODE *Node = &g_physalloc_root_node;
while (Current < Index)
Node = Node->Next;
Current++;
return Node;
}
void physmem_set_node_space(u64 Space)
{
g_physalloc_space_for_next = Space;
}
void physmem_mark_as_used(u64 Page)
{
T_PHYSALLOC_NODE *Node;
if (g_physalloc_list_size * PHYSALLOC_NUM_BITMAPS * 64 >= Page)
Node = physmem_traverse_list(Page / (PHYSALLOC_NUM_BITMAPS * 64));
else
{
while (g_physalloc_list_size * PHYSALLOC_NUM_BITMAPS * 64 < Page)
{
physmem_create_node();
}
Node = g_physalloc_top_node;
}
u16 OffsetInBitmaps = Page / (PHYSALLOC_NUM_BITMAPS * 64);
u8 OffsetInBitmap = Page % 64;
//kprintf("p: marking %i (%i %i)\n", Page, OffsetInBitmaps, OffsetInBitmap);
u64 Bitmap = Node->Bitmaps[OffsetInBitmaps];
Bitmap |= (1 << OffsetInBitmap);
Node->Bitmaps[OffsetInBitmaps] = Bitmap;
}
u64 physmem_allocate_page(void)
{
T_PHYSALLOC_NODE *Node = &g_physalloc_root_node;
for (u64 nNode = 0; nNode < g_physalloc_list_size; nNode++)
{
for (u16 nBitmap = 0; nBitmap < PHYSALLOC_NUM_BITMAPS; nBitmap++)
{
u64 Bitmap = Node->Bitmaps[nBitmap];
if (Bitmap != 0xFFFFFFFFFFFFFFFF)
{
for (u8 nBit = 0; nBit < 64; nBit++)
{
if ((Bitmap & (1 << nBit)) == 0)
{
Bitmap |= (1 << nBit);
Node->Bitmaps[nBitmap] = Bitmap;
kprintf("physmem: allocated %i\n", nNode * PHYSALLOC_NUM_BITMAPS + nBitmap * 64 + nBit);
return nNode * PHYSALLOC_NUM_BITMAPS + nBitmap * 64 + nBit;
}
}
}
}
Node = Node->Next;
}
// Still no space? Create a new node, if there is still space left in the memory
if (g_physalloc_mem_max && ((g_physalloc_list_size + 1) * PHYSALLOC_NUM_BITMAPS * 64 * PHYSALLOC_PAGE_SIZE > g_physalloc_mem_max))
{
kprintf("physmem: extending\n");
physmem_create_node();
Node = g_physalloc_top_node;
Node->Bitmaps[0] = 0x1;
return ((g_physalloc_list_size - 1) * PHYSALLOC_NUM_BITMAPS * 64) + 1;
}
PANIC("Out of memory!");
return 0;
}
void physmem_free_page(u64 Page)
{
T_PHYSALLOC_NODE *Node = physmem_traverse_list(Page / (PHYSALLOC_NUM_BITMAPS * 64));
u16 OffsetInBitmaps = Page % (PHYSALLOC_NUM_BITMAPS * 64);
u8 OffsetInBitmap = Page % 64;
u64 Bitmap = Node->Bitmaps[OffsetInBitmaps];
Bitmap ^= (1 << OffsetInBitmap);
Node->Bitmaps[OffsetInBitmaps] = Bitmap;
}
u64 physmem_page_to_physical(u64 Page)
{
return Page * PHYSALLOC_PAGE_SIZE;
}
u64 physmem_physical_to_page(u64 Physical)
{
return Physical / PHYSALLOC_PAGE_SIZE;
}

141
Kernel/src/Tier0/system.c Normal file
View File

@ -0,0 +1,141 @@
// Basic information gathere about system
#include "types.h"
#include "Tier0/system.h"
#include "Tier0/kstdio.h"
#include "Tier0/physical_alloc.h"
u64 g_system_memory_lower = 0;
u64 g_system_memory_upper = 0;
s8* g_system_bootloader = "Unknown Multiboot Bootloader";
// Just a guess...
T_SYSTEM_INVALID_RAM g_system_invalid_areas[256];
u8 g_system_num_invalid_areas;
extern u64 _end;
void system_parse_multiboot_header(void *Header)
{
u8 Flags = *((u8*)Header);
if (Flags & 1)
{
g_system_memory_lower = (u64)((u8*)Header)[4];
g_system_memory_upper = (u64)((u8*)Header)[8];
}
if ((Flags >> 9) & 1)
g_system_bootloader = (s8*)(u64)((u32*)Header)[16];
u64 HighestUnavailable = 0;
if ((Flags >> 6) & 1)
{
// Memory map from bootloader...
u64 MapStart = ((u32*)Header)[12];
u64 MapLength = ((u32*)Header)[11];
g_system_num_invalid_areas = 0;
u64 AvailableMemory = 0;
T_SYSTEM_MLTBT_MMAP *Node = (T_SYSTEM_MLTBT_MMAP*)MapStart;
while ((u64)Node + 4 - MapStart < MapLength)
{
u32 Size = Node->Size;
if (Size == 0)
Size = sizeof(T_SYSTEM_MLTBT_MMAP);
if (Node->Type == 1)
AvailableMemory += Node->Length;
else
{
// Not available!
T_SYSTEM_INVALID_RAM *Area = \
&g_system_invalid_areas[g_system_num_invalid_areas];
Area->Base = Node->Base;
Area->Size = Node->Length;
if (Area->Base > HighestUnavailable)
HighestUnavailable = Area->Base;
g_system_num_invalid_areas++;
}
Node = (T_SYSTEM_MLTBT_MMAP*)((u64)Node + Size + 4);
}
g_system_memory_upper = AvailableMemory / 1024;
}
kprintf("[i] Highest unavailable address is %x.\n", HighestUnavailable);
physmem_init(HighestUnavailable);
for (u8 i = 0; i < g_system_num_invalid_areas; i++)
{
T_SYSTEM_INVALID_RAM *Area = &g_system_invalid_areas[i];
if (Area->Base < HighestUnavailable)
{
u64 Page = physmem_physical_to_page(Area->Base);
kprintf("[i] %x - %x unavailable\n", Area->Base, Area->Base + Area->Size);
for (int j = 0; j <= Area->Size / PHYSALLOC_PAGE_SIZE; j++)
physmem_mark_as_used(Page + j);
}
}
// Mark BIOS (1MB) as used
//u64 BIOSSize = 1024*1024;
//for (u16 i = 0; i < BIOSSize / PHYSALLOC_PAGE_SIZE; i++)
// physmem_mark_as_used(i);
// Mark kernel memory as used
//u64 KernelSize = ((u64)&_end) - 0xFF000000;
//for (u16 i = 0; i < KernelSize / PHYSALLOC_PAGE_SIZE; i++)
// physmem_mark_as_used(i);
// Set the new node space for physmem
u64 Page = physmem_allocate_page();
u64 Memory = physmem_page_to_physical(Page);
// TODO: Fix relying on identity paging for low memory addresses
physmem_set_node_space(Memory);
}
u64 system_get_memory_upper(void)
{
return g_system_memory_upper;
}
u64 system_get_memory_lower(void)
{
return g_system_memory_lower;
}
s8 *system_get_bootloader_name(void)
{
return g_system_bootloader;
}
u8 system_memory_available(u64 Start, u64 Length)
{
for (u8 i = 0; i < g_system_num_invalid_areas; i++)
{
T_SYSTEM_INVALID_RAM Area = g_system_invalid_areas[i];
// If the start address is somwhere in the invalid area
if (Area.Base <= Start && Area.Base + Area.Size > Start)
return 0;
// If the end address is somewhere in the invalid area
if (Area.Base <= Start + Length && Area.Base + Area.Size > Start + Length)
return 0;
// If the request spans accross an invalid area
if (Area.Base >= Start && Start + Length < Area.Base + Area.Size)
return 0;
}
return 1;
}

View File

@ -1,66 +0,0 @@
// Kinda like a heap, but not really.
// Based on 1024 4MB superpages. You can't allocate anything lower than that,
// but who cares. The only time this is going to be called is by lower parts of
// the kernel, anyway.
#include "Tier0/physical_alloc.h"
#include "Tier0/kstdio.h"
#include "Tier0/panic.h"
u32 g_physmem_directory[32 * 1024];
void physmem_init(void)
{
for (int i = 0; i < 32; i++)
g_physmem_directory[i] = 0;
}
void physmem_mark_as_used(u32 Page)
{
u32 Entry = Page / 32;
u8 Bit = Page % 32;
g_physmem_directory[Entry] |= (1 << Bit);
}
u32 physmem_allocate_page(void)
{
for (u32 i = 0; i < 32 * 1024; i++)
{
u32 Entry = g_physmem_directory[i];
if (Entry != 0xFFFFFFFF)
{
// Ooh, there's a page in this entry
for (int j = 0; j < 32; j++)
{
u8 Available = (~Entry & (1 << j)) > 0;
if (Available)
{
u32 Page = i * 32 + j;
physmem_mark_as_used(Page);
return Page;
}
}
}
}
PANIC("Could not allocate page!");
return 0;
}
void physmem_free_page(u32 Page)
{
u8 Entry = Page / 32;
u8 Bit = Page % 32;
g_physmem_directory[Entry] &= ~(1 << Bit);
}
u32 physmem_page_to_physical(u32 Page)
{
return Page * 1024 * 4;
}
u32 physmem_physical_to_page(u32 Physical)
{
return Physical / (1024 * 4);
}

View File

@ -1,119 +0,0 @@
// Basic information gathere about system
#include "types.h"
#include "Tier0/system.h"
#include "Tier0/kstdio.h"
#include "Tier0/physical_alloc.h"
u32 g_system_memory_lower = 0;
u32 g_system_memory_upper = 0;
s8* g_system_bootloader = "Unknown Multiboot Bootloader";
// Just a guess...
T_SYSTEM_INVALID_RAM g_system_invalid_areas[256];
u8 g_system_num_invalid_areas;
void system_parse_multiboot_header(void *Header)
{
u8 Flags = *((u8*)Header);
if (Flags & 1)
{
g_system_memory_lower = ((u8*)Header)[4];
g_system_memory_upper = ((u8*)Header)[8];
}
if ((Flags >> 9) & 1)
g_system_bootloader = (s8*)((u32*)Header)[16];
if ((Flags >> 6) & 1)
{
// Memory map from bootloader...
u32 MapStart = ((u32*)Header)[12];
u32 MapLength = ((u32*)Header)[11];
g_system_num_invalid_areas = 0;
u32 AvailableMemory = 0;
T_SYSTEM_MLTBT_MMAP *Node = (T_SYSTEM_MLTBT_MMAP*)MapStart;
while ((u32)Node + 4 - MapStart < MapLength)
{
u32 Size = Node->Size;
if (Size == 0)
Size = sizeof(T_SYSTEM_MLTBT_MMAP);
if (Node->Type == 1)
AvailableMemory += Node->LengthLow;
else
{
// Not available!
T_SYSTEM_INVALID_RAM Area = \
g_system_invalid_areas[g_system_num_invalid_areas];
Area.Base = Node->BaseLow;
Area.Size = Node->LengthLow;
g_system_num_invalid_areas++;
u32 Page = physmem_physical_to_page(Area.Base);
for (int i = 0; i <= Area.Size / (4 * 1024); i++)
physmem_mark_as_used(Page + i);
}
Node = (T_SYSTEM_MLTBT_MMAP*)((u32)Node + Size + 4);
}
g_system_memory_upper = AvailableMemory / 1024;
}
// Mark first 8 MB as used (that's where our kernel binary is loaded)
for (u16 i = 0; i < 1024 * 8; i++)
physmem_mark_as_used(i);
// Mark all memory > memory size as used.
u16 StartPage = g_system_memory_upper / (1024 * 4);
u16 NumPages = (0xFFFFFFFF / 1024 - g_system_memory_upper) / (1024 * 4);
for (int i = 0; i < NumPages; i++)
physmem_mark_as_used(StartPage + i);
if (g_system_memory_upper % (1024 * 4) != 0)
physmem_mark_as_used(0xFFFFFFFF / (1024 * 4));
}
u32 system_get_memory_upper(void)
{
return g_system_memory_upper;
}
u32 system_get_memory_lower(void)
{
return g_system_memory_lower;
}
s8 *system_get_bootloader_name(void)
{
return g_system_bootloader;
}
u8 system_memory_available(u32 Start, u32 Length)
{
for (u8 i = 0; i < g_system_num_invalid_areas; i++)
{
T_SYSTEM_INVALID_RAM Area = g_system_invalid_areas[i];
// If the start address is somwhere in the invalid area
if (Area.Base <= Start && Area.Base + Area.Size > Start)
return 0;
// If the end address is somewhere in the invalid area
if (Area.Base <= Start + Length && Area.Base + Area.Size > Start + Length)
return 0;
// If the request spans accross an invalid area
if (Area.Base >= Start && Start + Length < Area.Base + Area.Size)
return 0;
}
return 1;
}

View File

@ -190,6 +190,7 @@ static inline void cpuid(u32 code, u32 *a, u32 *d) {
// This will be replaced later on by the kernel code.
u64 pml4[512] __attribute__((aligned(0x1000)));
u64 page_dir_ptr_tab_low[512] __attribute__((aligned(0x1000)));
u64 page_dir_low[512] __attribute__((aligned(0x1000)));
u64 page_tab_low[512] __attribute__((aligned(0x1000)));
@ -276,21 +277,25 @@ u32 create_ia32e_paging(u64 KernelPhysicalStart, u64 KernelVirtualStart, u64 Ker
for (u16 i = GET_TAB_ENTRY(KernelVirtualStart); i < GET_TAB_ENTRY(KernelVirtualStart) + NumPages; i++)
{
page_tab_high[i] = Address | 3;
print_hex(KernelVirtualStart + i * 0x1000);
/*print_hex(KernelVirtualStart + i * 0x1000);
puts(" -> ");
print_hex(Address);
puts("\n");
puts("\n");*/
Address += 0x1000;
}
return 0;
}
u32 g_multiboot_header;
u32 load(void *Multiboot, unsigned int Magic)
{
clear();
puts("Cucumber x86-64 loader...\n");
g_multiboot_header = (u32)Multiboot;
if (Magic != 0x2BADB002)
{
@ -437,5 +442,5 @@ u32 load(void *Multiboot, unsigned int Magic)
puts("Now in 32-bit compability mode, jumping to the kernel...\n");
return (u32)Header->Entry;
return 1;
}

View File

@ -3,6 +3,7 @@ extern puts
extern stdio_current_line
extern stdio_cur_x
extern stdio_cur_y
extern g_multiboot_header;
global _loader
; Multiboot-related constants
@ -81,6 +82,7 @@ _loader_gdt:
movzx edi, byte [stdio_current_line]
movzx esi, byte [stdio_cur_x]
movzx edx, byte [stdio_cur_y]
mov ecx, dword [g_multiboot_header]
; 64-bit, here we come!
call 0x18:0xFF000000