diff options
| -rw-r--r-- | README.md | 34 | ||||
| -rw-r--r-- | kernel/kernel.c | 11 | ||||
| -rw-r--r-- | kernel/mem.c | 88 | ||||
| -rw-r--r-- | kernel/mem.h | 31 | ||||
| -rw-r--r-- | kernel/multiboot.c | 6 | ||||
| -rw-r--r-- | kernel/multiboot.h | 2 | ||||
| -rw-r--r-- | kernel/scheduler.c | 4 | ||||
| -rw-r--r-- | kernel/smp.c | 4 | ||||
| -rw-r--r-- | kernel/vmem.c | 18 |
9 files changed, 104 insertions, 94 deletions
@@ -98,32 +98,16 @@ Discontinued Features Todos ----- -* ipxe (network drivers?) -* io_wait? -* cpuid (i686) check apic? -* lapic / spurious . ioapic -* newlib reentrant struct!! -* Interrupts between BSP and APS ? -* Do not forget to flush TLB -* APIC / at least LAPIC? HPET timer? -* Check 16bit stack alignment before ALL calls from assembler! -* Ethernet driver E1000 / NS2000 & Networking stack +* Unit Tests +* Newlib Reeentrancy Struct +* Ethernet driver E1000 / NS2000 & Networking stack (ipxe network drivers?) * Porting (ncurses, gcc, binutils, vim, apache...) -* Check VESA mode and adapt console (text/gui) -* cpu sleep if nothing to do -* use other cpus -* pdirectory contains bad bad hardcoded shit -* remap stack -* upper half kernel -* do not disable paging on context swtiches.. -* fork/clone -* sbrk() -* ESP collisions / TSS-ESP0 -* kbfree() and real pgdirectory alloc -* implement posix(?) getdents instead of our own readdir. -* Turning on some gcc optimizations breaks the kernel? -* Writing to files (at least in ext2 ram image) -* mutex +* Posix getdents +* GCC optimizations (break kernel?) +* Writing to ext2 RAM-image +* Mutes +* Flush TLB +* GUI / Window Manager (update\_rect, etc..) REFERENCES ========== diff --git a/kernel/kernel.c b/kernel/kernel.c index dfcab3f..2fdb09b 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -46,12 +46,13 @@ void kernel_main(uint32_t eax,uint32_t ebx) // -- DISABLE LEGACY PIC -- // klog("Remapping & Disabling Programmable Interrupt Controller (PIC) ..."); + fixme("io_wait & spurious interrupts"); asm_pic_setup(); // -- GET CONFIGS -- // klog("Read Multiboot Structures ..."); multiboot_information *cfg_multiboot; - cfg_multiboot=multiboot_read(eax, ebx); + cfg_multiboot=multiboot_read(eax, ebx,true); klog("Read Advanced Power Configuration Interface (ACPI) Structures ..."); acpi_information cfg_acpi; @@ -67,15 +68,21 @@ void kernel_main(uint32_t eax,uint32_t ebx) klog("Interrupt Vector Table (IVT) init ..."); interrupts_init(0x08); interrupts_install(); - fixme("register interrupt callback funcs"); + fixme("register interrupt callback funcs (instead hardcoded dispatcher)"); // -- MEMORY MANAGEMENT -- // klog("Memory init ... "); uint32_t kernel_blocks=mem_init(cfg_multiboot); klog("Vritual Memory / Paging init ... "); + fixme("do not disable anymore on context switching!"); + fixme("write convenneint management funcs as: mapCPU, mapKErnel, map USerspace.."); + pdirectory *dir=vmem_init(kernel_blocks,(uint32_t)cfg_multiboot->framebuffer_addr,cfg_acpi.local_apic_address,cfg_acpi.io_apic_address); + + fixme("move stack?"); + // -- RAM IMAGE -- // klog("Ram Filesystem init ... "); fs_mount(cfg_multiboot); diff --git a/kernel/mem.c b/kernel/mem.c index 7052e6c..79cfe9b 100644 --- a/kernel/mem.c +++ b/kernel/mem.c @@ -1,5 +1,6 @@ -#include <stdint.h> #include "kernel.h" +#include "mem.h" +#include <stdint.h> #include "multiboot.h" #define PMMNGR_BLOCKS_PER_BYTE 8 @@ -7,7 +8,7 @@ #define PMMNGR_MAX_BLOCKS 1048576 // 4096*1048576 = 2^32 bytes (maxium addressable memory ~4GB) #define PMMNGR_MAP_SIZE PMMNGR_MAX_BLOCKS/PMMNGR_BLOCKS_PER_BYTE/4 -// defined in linker.ld and multiboot.s +// defined in linker.ld and asm_start.s extern uint32_t kernel_start[]; extern uint32_t kernel_end[]; extern uint32_t stack_top[]; @@ -15,13 +16,12 @@ extern uint32_t stack_bottom[]; //memory map bit array. Each bit represents a 4KB memory block, //so uint32_t represents 8*4 blocks -static uint32_t _mmngr_memory_map[PMMNGR_MAP_SIZE]; //32Kb +static uint32_t _mmngr_memory_map[PMMNGR_MAP_SIZE]; //128KiB +//track number of free blocks static uint32_t mem_free_blocks; //number of free blocks -static uint32_t mem_max_block; //index of highest usable block -static uint32_t mem_min_block; //index of lowset block available for alloc -char *memmap_type_to_string[]= +static char *memmap_type_to_string[]= { "Usable", "Reserved", @@ -30,30 +30,25 @@ char *memmap_type_to_string[]= "Bad Memory" }; -uint32_t mem_get_free_blocks_count() -{ - return mem_free_blocks; -} - // bit funcs! -void mmap_set(int bit) +static void mmap_set(int bit) { _mmngr_memory_map[bit / 32] |= (1 << (bit % 32)); } -void mmap_unset(int bit) +static void mmap_unset(int bit) { _mmngr_memory_map[bit / 32] &= ~ (1 << (bit % 32)); } -int mmap_test(int bit) +static int mmap_test(int bit) { return _mmngr_memory_map[bit / 32] & (1 << (bit % 32)); } // // By default, Set all of memory is in use -void pmmngr_init () +static void pmmngr_init () { mem_free_blocks=0; @@ -64,9 +59,9 @@ void pmmngr_init () } //find the first free bit -int mmap_first_free () +static int mmap_first_free () { - for (int i=0; i<mem_max_block ; i++) + for (int i=0; i<PMMNGR_MAP_SIZE; i++) if (_mmngr_memory_map[i] != 0xffffffff) for (int j=0; j<32; j++) { @@ -76,33 +71,38 @@ int mmap_first_free () return -1; } -void pmmngr_init_region (uint32_t base, uint32_t size) +// work with regions +static void pmmngr_init_region (uint32_t base, uint32_t size) { uint32_t align = base / PMMNGR_BLOCK_SIZE; - uint32_t blocks = size / PMMNGR_BLOCK_SIZE; + uint32_t end_align = (base+size-1) / PMMNGR_BLOCK_SIZE; + uint32_t blocks = end_align-align+1; for (; blocks>0; blocks--) { +// if(mmap_test(align))kpanic("already initialized"); mmap_unset (align++); mem_free_blocks++; } } -void pmmngr_deinit_region (uint32_t base, uint32_t size) +static void pmmngr_deinit_region (uint32_t base, uint32_t size) { uint32_t align = base / PMMNGR_BLOCK_SIZE; - uint32_t blocks = size / PMMNGR_BLOCK_SIZE; + uint32_t end_align = (base+size-1) / PMMNGR_BLOCK_SIZE; + uint32_t blocks = end_align-align+1; if(size%PMMNGR_BLOCK_SIZE)blocks++; for (; blocks>0; blocks--) { +// if(mmap_test(align))kpanic("already de-initialized"); mmap_set (align++); mem_free_blocks--; } } -void* pmmngr_alloc_block () +void* mem_alloc_block () { int frame = mmap_first_free (); @@ -122,7 +122,7 @@ void* pmmngr_alloc_block () } -void pmmngr_free_block (void* p) +void mem_free_block (void* p) { uint32_t addr = (uint32_t)(uint32_t*)p; int frame = addr / PMMNGR_BLOCK_SIZE; @@ -142,29 +142,33 @@ void pmmngr_free_block (void* p) //klog("free block (%d) 0x%08X)",frame,addr); } +uint32_t mem_get_free_blocks_count() +{ + return mem_free_blocks; +} -// returns index of first block outside of kerel-land +/** initialize physical memory manager */ uint32_t mem_init(multiboot_information *info) { + klog("markers in kernel binary:"); + klog("kernel loaded at: 0x%08X- 0x%08X",kernel_start,kernel_end); + klog("initial stack at: 0x%08X- 0x%08X",stack_top,stack_bottom); + fixme("check if kernel size does not exceed memory limits!"); - fixme("move stack"); + fixme("communicate pages to vmmem to identity map in kernel!"); if(info->flags&&1<<6) { - klog("memory map of length %d provided by bootloader",info->mmap_length); + klog("Memory map of length %d provided by bootloader",info->mmap_length); } else kpanic("Unable to continue without memory map, sorry!"); - pmmngr_init (); //clear memmap + pmmngr_init (); //mark all memory as used uint64_t memmap=info->mmap_addr; uint64_t length=info->mmap_length; - klog("kernel loaded at: 0x%08X- 0x%08X",kernel_start,kernel_end); - klog("initial stack at: 0x%08X- 0x%08X",stack_top,stack_bottom); - - // count available mem and track high_end of usable memory - uint32_t total_mem=0, highest_end; + uint32_t total_mem=0; // iterate : print memory map, calc blocks, deinit for(uint32_t mmap_addr=memmap;mmap_addr<memmap+length;) @@ -182,7 +186,6 @@ uint32_t mem_init(multiboot_information *info) if(mmap->type==1||mmap->type==3) { total_mem+=mem; - highest_end=mmap->base_addr+mmap->length-1; pmmngr_init_region(mmap->base_addr,mmap->length); } @@ -190,8 +193,8 @@ uint32_t mem_init(multiboot_information *info) mmap_addr+=mmap->size+4; } - uint32_t blocks=highest_end/4096+1; - mem_max_block=blocks/32+1; + // deinit first page (coz address=0 reserved for failure) + pmmngr_deinit_region(0,4096); // deinit modules memory if(info->flags&&1<<3) @@ -201,8 +204,6 @@ uint32_t mem_init(multiboot_information *info) { klog("mod 0x%08X-0x%08X : %s", mod->mod_start,mod->mod_end, mod->string); - - mem_min_block=mod->mod_end/PMMNGR_BLOCK_SIZE+1; pmmngr_deinit_region(mod->mod_start,((uint32_t)mod->mod_end-(uint32_t)mod->mod_start)+1); @@ -213,17 +214,8 @@ uint32_t mem_init(multiboot_information *info) // deinitialize kernel pmmngr_deinit_region(kernel_start,((uint32_t)kernel_end-(uint32_t)kernel_start)+1); - // we deinit everything below mem_min_block anyway - //pmmngr_deinit_region(0,mem_min_block*PMMNGR_BLOCK_SIZE); - - pmmngr_deinit_region(0,4096); // deinit first page (coz address=0 reserved for failure) - + klog("Free 4K blocks: %d",mem_free_blocks); klog("Usable ~%d / %d MB ",mem_free_blocks*4096/1024/1024,total_mem/1024/1024); - klog( - "Free 4K blocks: %d (first free: %d)",mem_free_blocks,mem_min_block); - - return mem_min_block; + return 0; } - - diff --git a/kernel/mem.h b/kernel/mem.h index 76d12b0..6871e11 100644 --- a/kernel/mem.h +++ b/kernel/mem.h @@ -1,6 +1,31 @@ +/** + * @file + * + * Physical Memory Manager + * ======================= + * + * Allocating and Deallocating memory pagewise. Run mem_init() first. + * + * + * Memory Map + * ---------- + * This will allow to mark a bit on/off for each page to indicte if it is + * currently used or not. + * + * Remember that we have 4096 bytes per page so we need 1048576 bits to + * cover the whole 32bit addressable memory 2^32 byte (4GB). + * + * This results in a 128KiB map we which allocate statically. + */ + #include "multiboot.h" -typedef uint32_t physical_address; -physical_address* pmmngr_alloc_block (); -void pmmngr_free_block (physical_address* p); + +/** + * Init the physical memory manager. Please provide the multiboot_information + * strucutre filled by your bootloader (as grub). + * This is required for memory map et al. + */ uint32_t mem_init(multiboot_information *info); +void* mem_alloc_block (); +void mem_free_block(void* p); uint32_t mem_get_free_blocks_count(); diff --git a/kernel/multiboot.c b/kernel/multiboot.c index ee84180..ada9a4e 100644 --- a/kernel/multiboot.c +++ b/kernel/multiboot.c @@ -1,13 +1,15 @@ #include "kernel.h" #include "multiboot.h" -multiboot_information* multiboot_read(uint32_t eax, uint32_t ebx) +multiboot_information* multiboot_read(uint32_t eax, uint32_t ebx, bool silent) { if(eax!=0x2badb002)kpanic("EAX was not set properly by your bootlaoder!"); - klog("multiboot struct at addr: 0x%08X",ebx); multiboot_information *info; info=ebx; + if(silent) return info; // silence is golden + + klog("multiboot struct at addr: 0x%08X",ebx); klog("multiboot flags: 0x%08X",info->flags); diff --git a/kernel/multiboot.h b/kernel/multiboot.h index 09f7286..1c9c713 100644 --- a/kernel/multiboot.h +++ b/kernel/multiboot.h @@ -68,6 +68,6 @@ typedef struct multiboot_mod_struct }multiboot_mod; -multiboot_information* multiboot_read(uint32_t eax, uint32_t ebx); +multiboot_information* multiboot_read(uint32_t eax, uint32_t ebx,bool silent); #endif diff --git a/kernel/scheduler.c b/kernel/scheduler.c index 20c6f35..0f511f4 100644 --- a/kernel/scheduler.c +++ b/kernel/scheduler.c @@ -232,14 +232,14 @@ volatile uint32_t task_fork(uint32_t pid) { //TODO: what will happen if we get rescheduled!?!?! int ret=add_task(pid,vmem_new_space_dir(task_list[pid].vmem,false)); - klog("[%d] forked -> [%d] (free blocks remaining: %d )", pid, ret,mem_get_free_blocks_count()); + klog("[%d] forked -> [%d] (free blocks remaining: %d )", pid, ret,0); return ret; } volatile uint32_t task_clone(uint32_t pid) { //TODO: what will happen if we get rescheduled!?!?! int ret=add_task(pid,vmem_new_space_dir(task_list[pid].vmem,true)); - klog("[%d] cloned -> [%d] (free blocks remaining: %d )", pid, ret,mem_get_free_blocks_count()); + klog("[%d] cloned -> [%d] (free blocks remaining: %d )", pid, ret,0); return ret; } diff --git a/kernel/smp.c b/kernel/smp.c index 9434a47..aa1a878 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -183,8 +183,8 @@ void kernel_ap() // this will start all our application processors! void smp_start_aps(acpi_information *pros) { - fixme("how to support IPI addressing more than 16cpus?"); - // TODO: check if local APIC is present via CPUID (P6 (i686) and above) + fixme("how to support IPI addressing more than 16cpus?"); + fixme("check via cpuid if apic exist?"); local_apic_addr=pros->local_apic_address; io_apic_addr=pros->io_apic_address; diff --git a/kernel/vmem.c b/kernel/vmem.c index 3b5be30..ffe9a8e 100644 --- a/kernel/vmem.c +++ b/kernel/vmem.c @@ -138,7 +138,7 @@ void pd_entry_enable_global (pd_entry e) uint8_t vmmngr_alloc_page (pt_entry* e) { // allocate a free physical frame - void* p = pmmngr_alloc_block (); + void* p = mem_alloc_block (); if (!p) return 0; // map it to the page @@ -151,7 +151,7 @@ uint8_t vmmngr_alloc_page (pt_entry* e) void vmmngr_free_page (pt_entry* e) { void* p = (void*)pt_entry_pfn (*e); - if (p) pmmngr_free_block (p); + if (p) mem_free_block (p); pt_entry_del_attrib (e, I86_PTE_PRESENT); } @@ -186,10 +186,10 @@ void vmem_free_dir(pdirectory *dir) for (int i=0, virt=virt_addr; i<1024; i++, virt+=4096) { pt_entry pte=&table->m_entries [PAGE_TABLE_INDEX (virt) ]; - pmmngr_free_block(pt_entry_get_frame(pte)); // get free space from the memory manager + mem_free_block(pt_entry_get_frame(pte)); // get free space from the memory manager } - pmmngr_free_block(pd_entry_get_frame (entry)); + mem_free_block(pd_entry_get_frame (entry)); virt_addr+=1024*4096; } @@ -205,14 +205,14 @@ void vmem_free_dir(pdirectory *dir) for (int i=0, virt=virt_addr; i<1024; i++, virt+=4096) { pt_entry pte=&table->m_entries [PAGE_TABLE_INDEX (virt) ]; - pmmngr_free_block(pt_entry_get_frame(pte)); // get free space from the memory manager + mem_free_block(pt_entry_get_frame(pte)); // get free space from the memory manager } - pmmngr_free_block(pd_entry_get_frame (entry)); + mem_free_block(pd_entry_get_frame (entry)); virt_addr+=1024*4096; } - pmmngr_free_block(dir); + mem_free_block(dir); x86_paging_enable(); } @@ -484,7 +484,7 @@ pdirectory* vmem_new_space_dir(pdirectory *copy_dir,bool stack_only) for (int i=0, virt=virt_addr; i<1024; i++, virt+=4096) { //klog("i = %d",i); - phys_addr=pmmngr_alloc_block(); // get free space from the memory manager + phys_addr=mem_alloc_block(); // get free space from the memory manager if (!phys_addr)kpanic("unable to alloc spce for frame"); // if this is not init , copy contents from current space! @@ -540,7 +540,7 @@ pdirectory* vmem_new_space_dir(pdirectory *copy_dir,bool stack_only) for (int i=0, virt=virt_addr; i<1024; i++, virt+=4096) { - phys_addr=pmmngr_alloc_block(); // get free space from the memory manager + phys_addr=mem_alloc_block(); // get free space from the memory manager if (!phys_addr)kpanic("unable to alloc spce for frame"); // if this is not init , copy contents from current space! |
