Working on the PMM
parent
f096be37a2
commit
e04c28f1be
|
@ -3,36 +3,93 @@
|
|||
|
||||
#include "types.h"
|
||||
|
||||
struct S_PAGING_PAGE {
|
||||
// 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;
|
||||
u32 Physical : 20;
|
||||
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);
|
||||
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_DIRECTORY *Directory);
|
||||
void paging_map_kernel_page(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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
u64 Address;
|
||||
__asm__ volatile("mov %%cr3, %0\n" : "=r"(Address));
|
||||
return (T_PAGING_ML4*)Address;
|
||||
}
|
||||
|
||||
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);
|
||||
u8 paging_get_physical_ex(u64 Virtual, u64 *Physical, T_PAGING_ML4 *ML4)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
u8 paging_get_physical(u32 Virtual, u32 *Physical)
|
||||
u8 paging_get_physical(u64 Virtual, u64 *Physical)
|
||||
{
|
||||
return paging_get_physical_ex(Virtual, Physical, &g_kernel_page_directory);
|
||||
T_PAGING_ML4 *ml4 = paging_get_ml4();
|
||||
return paging_get_physical_ex(Virtual, Physical, ml4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void paging_dump_directory(void)
|
||||
// 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);
|
||||
}
|
||||
}*/
|
||||
|
|
@ -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");*/
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue