From e04c28f1be939797cf8aebebc9cfdf2f07cd4d37 Mon Sep 17 00:00:00 2001 From: Sergiusz Bazanski Date: Sat, 2 Jul 2011 13:03:29 +0200 Subject: [PATCH] Working on the PMM --- Kernel/include/Tier0/paging.h | 97 +++++++++++---- Kernel/include/Tier0/physical_alloc.h | 23 +++- Kernel/include/Tier0/system.h | 16 ++- Kernel/src/Tier0/kmain.c | 47 ++++---- Kernel/src/{Tier0_32 => Tier0}/paging.c | 87 +++++++++----- Kernel/src/{Tier0_32 => Tier0}/panic.c | 13 +- Kernel/src/Tier0/physical_alloc.c | 153 ++++++++++++++++++++++++ Kernel/src/Tier0/system.c | 141 ++++++++++++++++++++++ Kernel/src/Tier0_32/physical_alloc.c | 66 ---------- Kernel/src/Tier0_32/system.c | 119 ------------------ Loader/src/load.c | 11 +- Loader/src/start.asm | 2 + 12 files changed, 494 insertions(+), 281 deletions(-) rename Kernel/src/{Tier0_32 => Tier0}/paging.c (69%) rename Kernel/src/{Tier0_32 => Tier0}/panic.c (94%) create mode 100644 Kernel/src/Tier0/physical_alloc.c create mode 100644 Kernel/src/Tier0/system.c delete mode 100644 Kernel/src/Tier0_32/physical_alloc.c delete mode 100644 Kernel/src/Tier0_32/system.c diff --git a/Kernel/include/Tier0/paging.h b/Kernel/include/Tier0/paging.h index 3a449b5..9c9ef43 100644 --- a/Kernel/include/Tier0/paging.h +++ b/Kernel/include/Tier0/paging.h @@ -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 diff --git a/Kernel/include/Tier0/physical_alloc.h b/Kernel/include/Tier0/physical_alloc.h index 3b4374c..ae103fc 100644 --- a/Kernel/include/Tier0/physical_alloc.h +++ b/Kernel/include/Tier0/physical_alloc.h @@ -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 diff --git a/Kernel/include/Tier0/system.h b/Kernel/include/Tier0/system.h index 368aebc..3be1460 100644 --- a/Kernel/include/Tier0/system.h +++ b/Kernel/include/Tier0/system.h @@ -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 diff --git a/Kernel/src/Tier0/kmain.c b/Kernel/src/Tier0/kmain.c index dc74504..5e9e1d9 100644 --- a/Kernel/src/Tier0/kmain.c +++ b/Kernel/src/Tier0/kmain.c @@ -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); diff --git a/Kernel/src/Tier0_32/paging.c b/Kernel/src/Tier0/paging.c similarity index 69% rename from Kernel/src/Tier0_32/paging.c rename to Kernel/src/Tier0/paging.c index 045a907..005a95d 100644 --- a/Kernel/src/Tier0_32/paging.c +++ b/Kernel/src/Tier0/paging.c @@ -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); -} +}*/ diff --git a/Kernel/src/Tier0_32/panic.c b/Kernel/src/Tier0/panic.c similarity index 94% rename from Kernel/src/Tier0_32/panic.c rename to Kernel/src/Tier0/panic.c index f0c33e4..18061f9 100644 --- a/Kernel/src/Tier0_32/panic.c +++ b/Kernel/src/Tier0/panic.c @@ -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");*/ diff --git a/Kernel/src/Tier0/physical_alloc.c b/Kernel/src/Tier0/physical_alloc.c new file mode 100644 index 0000000..56c7462 --- /dev/null +++ b/Kernel/src/Tier0/physical_alloc.c @@ -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; +} diff --git a/Kernel/src/Tier0/system.c b/Kernel/src/Tier0/system.c new file mode 100644 index 0000000..c5e2766 --- /dev/null +++ b/Kernel/src/Tier0/system.c @@ -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; +} + diff --git a/Kernel/src/Tier0_32/physical_alloc.c b/Kernel/src/Tier0_32/physical_alloc.c deleted file mode 100644 index c2321a1..0000000 --- a/Kernel/src/Tier0_32/physical_alloc.c +++ /dev/null @@ -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); -} diff --git a/Kernel/src/Tier0_32/system.c b/Kernel/src/Tier0_32/system.c deleted file mode 100644 index 8b0205d..0000000 --- a/Kernel/src/Tier0_32/system.c +++ /dev/null @@ -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; -} - diff --git a/Loader/src/load.c b/Loader/src/load.c index 5088944..e382a54 100644 --- a/Loader/src/load.c +++ b/Loader/src/load.c @@ -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; } diff --git a/Loader/src/start.asm b/Loader/src/start.asm index 0e0e0f9..bbc714e 100644 --- a/Loader/src/start.asm +++ b/Loader/src/start.asm @@ -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