diff options
| author | Miguel <m.i@gmx.at> | 2018-09-10 04:13:28 +0200 |
|---|---|---|
| committer | Miguel <m.i@gmx.at> | 2018-09-10 04:13:28 +0200 |
| commit | 65f5cca027af81e77b3e06da658b6d13f1861a03 (patch) | |
| tree | 4e1aa57b8d4dedb00beb649992054faf6f24ff40 /kernel | |
| parent | 67e7f93fc2ea9c6d04698f9af29be78d0123afb0 (diff) | |
fixing paging / per cpu pages
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/interrupts.c | 10 | ||||
| -rw-r--r-- | kernel/kernel.c | 18 | ||||
| -rw-r--r-- | kernel/mem.c | 2 | ||||
| -rw-r--r-- | kernel/scheduler.c | 3 | ||||
| -rw-r--r-- | kernel/smp.c | 24 | ||||
| -rw-r--r-- | kernel/vmem.c | 126 | ||||
| -rw-r--r-- | kernel/vmem.h | 3 |
7 files changed, 146 insertions, 40 deletions
diff --git a/kernel/interrupts.c b/kernel/interrupts.c index 3ab0dd3..180658a 100644 --- a/kernel/interrupts.c +++ b/kernel/interrupts.c @@ -51,7 +51,10 @@ uint32_t interrupt_handler(uint32_t esp, uint32_t irq) { // DO NOT WRITE INSIDE INTERRUPTS!! COZ IT ACQUIRES LOCK AND WE WILL DEADLOCK // klog("int: %d on 0x%x",irq,apicID()); - if(irq==INTERRUPT_PIT_TIMER)asm_pit_tick(); + if(irq==INTERRUPT_PIT_TIMER){ + asm_pit_tick(); +// return esp; // tried to skip EOI + } // mouse and kb if(irq==INTERRUPT_KEYBOARD || irq==INTERRUPT_MOUSE){ @@ -60,7 +63,7 @@ uint32_t interrupt_handler(uint32_t esp, uint32_t irq) // TODO: mouse // test ipi - //apicIPI(15,0x81); // force cpu16 to autoschedule? just test + apicIPI(2,0x81); // force cpu16 to autoschedule? just test //klog("0x60 in %d",in); } @@ -80,8 +83,7 @@ uint32_t interrupt_handler(uint32_t esp, uint32_t irq) } // schedules on APIC timer 0x8C and IPI 0x81 - if(irq==INTERRUPT_PIT_TIMER || irq==INTERRUPT_IPI)esp=my_scheduler(esp,-1); // autoschedule - + if(irq==INTERRUPT_APIC_TIMER || irq==INTERRUPT_IPI)esp=my_scheduler(esp,-1); // autoschedule if(irq!=INTERRUPT_SYSCALL)apicEOI(); // ack all except software syscalls diff --git a/kernel/kernel.c b/kernel/kernel.c index d30abf0..dd8d3f0 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -52,7 +52,7 @@ void kernel_main(uint32_t eax,uint32_t ebx) // -- GET CONFIGS -- // klog("Read Multiboot Structures ..."); multiboot_information *cfg_multiboot; - cfg_multiboot=multiboot_read(eax, ebx,true); + cfg_multiboot=multiboot_read(eax, ebx,false); klog("Read Advanced Power Configuration Interface (ACPI) Structures ..."); acpi_information cfg_acpi; @@ -79,10 +79,14 @@ void kernel_main(uint32_t eax,uint32_t ebx) fixme("write convenneint management funcs as: mapCPU, mapKErnel, map USerspace.."); fixme("move stack and guard with empty pages!"); - struct pdirectory_struct *dir=vmem_init(0, // this is hardcoded to first 32megs anyway - (uint32_t)cfg_multiboot->framebuffer_addr, - cfg_acpi.local_apic_address, - cfg_acpi.io_apic_address); + vmem_init(0, // this is hardcoded to first 32megs anyway + (uint32_t)cfg_multiboot->framebuffer_addr, + cfg_acpi.local_apic_address, + cfg_acpi.io_apic_address); + + struct pdirectory_struct *dir=vmem_kernel_dir(); + x86_set_page_directory(dir); + x86_paging_enable(); // -- RAM IMAGE -- // klog("Ram Filesystem init ... "); @@ -100,10 +104,6 @@ void kernel_main(uint32_t eax,uint32_t ebx) uint32_t sstdout = syscall_open("term",0,0); // stdout 1 uint32_t sstderr = syscall_open("stderr",0,0); // stderr 2 - // -- ... -- // - klog("Scheduler init ..."); - scheduler_init(dir); - klog("Keyboard init ..."); keyboard_init(0); diff --git a/kernel/mem.c b/kernel/mem.c index a0650c6..8ce5c89 100644 --- a/kernel/mem.c +++ b/kernel/mem.c @@ -154,7 +154,7 @@ uint32_t mem_init(multiboot_information *info) 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("check if kernel/ramimage size/pos does not exceed first 32mb (better vmem dynamically) limits!"); fixme("communicate pages to vmmem to identity map in kernel!"); if(info->flags&&1<<6) diff --git a/kernel/scheduler.c b/kernel/scheduler.c index 8178c12..19e670f 100644 --- a/kernel/scheduler.c +++ b/kernel/scheduler.c @@ -158,6 +158,9 @@ void task_syscall_worker() // volatile uint32_t my_scheduler(uint32_t oldesp,uint32_t force_pid) { + uint32_t *apic_id=0x8000000; + klog("scheduler 0x%x",*apic_id); // TODO: do not log we are inisde an interrupt!! + // static bool first=true; if(current_task==NO_TASK)return oldesp; diff --git a/kernel/smp.c b/kernel/smp.c index aa1a878..3787ac1 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -4,6 +4,7 @@ #include <stdint.h> #include "gdt.h" #include "mem.h" +#include "vmem.h" #include "interrupts.h" #include "kmalloc.h" #include "spinlock.h" @@ -84,7 +85,7 @@ uint32_t readAPIC(uint32_t offset) uint32_t apicID() { - return readAPIC(APIC_APICID); + return readAPIC(APIC_APICID)>>24; } void apicEOI() @@ -149,7 +150,14 @@ void kernel_ap() interrupts_install(); gdt_init(); + + struct pdirectory_struct *dir=vmem_kernel_dir(); + x86_set_page_directory(dir); + x86_paging_enable(); + uint32_t *cpu_mem=0x8000000; //1024 pages from here on are mapped per cpu for testing! TODO: dynamic! + *cpu_mem=apicID(); + writeAPIC(APIC_TMRDIV, 0x3); writeAPIC(APIC_LVT_TMR,INTERRUPT_APIC_TIMER | TMR_PERIODIC); writeAPIC(APIC_TMRINITCNT, countdown); @@ -158,11 +166,7 @@ void kernel_ap() asm_smp_unlock(); - while(1) - { - asm("hlt"); - klog("tack: 0x%08X: 0x%08X",readAPIC(APIC_APICID), readAPIC(APIC_TMRCURRCNT)); - } + while(1)asm("hlt"); // switch_to_user_mode(); /* @@ -183,12 +187,16 @@ 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?"); fixme("check via cpuid if apic exist?"); local_apic_addr=pros->local_apic_address; io_apic_addr=pros->io_apic_address; - klog("bsp local apic id: 0x%08X",apicID()); + uint32_t *cpu_mem=0x8000000; //1024 pages from here on are mapped per cpu for testing! TODO: dynamic! + *cpu_mem=apicID(); + + klog("bsp local apic id: 0x%08X",*cpu_mem); apicEnable(); // bsp apic seems to be enabled anyway. @@ -196,10 +204,10 @@ void smp_start_aps(acpi_information *pros) // setup apic timer countdown=speed/16/10; // tick 10 times a second + countdown*=10; writeAPIC(APIC_TMRDIV, 0x3); // divisor 16 writeAPIC(APIC_LVT_TMR, INTERRUPT_APIC_TIMER | TMR_PERIODIC); // on interrupt 200 writeAPIC(APIC_TMRINITCNT, countdown); - countdown*=10; // setup IO APIC // PIT irq 00 -> 02 flags 0 -> 0x90 diff --git a/kernel/vmem.c b/kernel/vmem.c index ff464ea..04f0354 100644 --- a/kernel/vmem.c +++ b/kernel/vmem.c @@ -40,6 +40,7 @@ typedef struct ptable_struct { typedef struct pdirectory_struct { pd_entry m_entries[PAGES_PER_DIR]; }pdirectory; + static uint32_t kernel_pages; uint32_t fb_addr; // TODO!??!!? how can we share so ugly with vesa static uint32_t apic_addr; @@ -197,7 +198,7 @@ static pt_entry* vmmngr_ptable_lookup_entry (ptable* p, virtual_addr addr) /// SHIT BELOW THIs LINE void vmem_free_dir(pdirectory *dir) { - x86_paging_disable(); + x86_paging_disable(); //TODO : do not disable this! uint32_t virt_addr=0; @@ -250,7 +251,110 @@ void vmem_free_dir(pdirectory *dir) x86_paging_enable(); } +static pdirectory* vmem_clean_dir() +{ + fixme("replace ALLL kballoc with getting the pages from mem/vmem"); + pdirectory* dir = (pdirectory*) kballoc(1); + for(int i=0;i<1024;i++)dir->m_entries [i]=0; // zero all + klog("fresh page directory: 0x%X",dir); + return dir; +} + +static void vmem_add_alloc(pdirectory* dir,uint32_t start,uint32_t pages) +{ + uint32_t virt_addr=start; + for(int j=0;j<2;j++) + { + + ptable* table = (ptable*) kballoc (1); + pd_entry *oldentry=NULL; + ptable* oldtable=NULL; + + for (int i=0, virt=virt_addr; i<1024; i++, virt+=4096) + { + //klog("i = %d",i); + uint32_t phys_addr=mem_alloc_block(); // get free space from the memory manager + + uint32_t frame=phys_addr; + + //! create a new page + pt_entry page=0; + pt_entry_add_attrib (&page, I86_PTE_PRESENT); + pt_entry_add_attrib (&page, I86_PTE_WRITABLE); + pt_entry_add_attrib (&page, I86_PTE_USER); + pt_entry_set_frame (&page, frame); + + //! ...and add it to the page table + table->m_entries [PAGE_TABLE_INDEX (virt) ] = page; + } + + pd_entry* entry = &dir->m_entries [PAGE_DIRECTORY_INDEX (virt_addr) ]; + *entry=0; + pd_entry_add_attrib (entry, I86_PDE_PRESENT); + pd_entry_add_attrib (entry, I86_PDE_WRITABLE); + pt_entry_add_attrib (entry, I86_PTE_USER); + pd_entry_set_frame (entry, (physical_addr)table); + + virt_addr+=1024*4096; + } + +} + +static void vmem_add_identity(pdirectory* dir,uint32_t start,uint32_t pages) +{ + fixme("make sure the pages are marked as used in the physical mem manager"); + + uint32_t phys_addr=start; + uint32_t virt_addr=start; + + while(pages>0) + { + // each table in our page directory maps 1024*4096 bytes + ptable* table; + table = (ptable*) kballoc(1); + for(int i=0;i<1024;i++)table->m_entries [i]=0; // zero all + + //! idenitity mapping + for (int i=0, frame=phys_addr, virt=virt_addr; i<1024; i++, frame+=4096, virt+=4096) + { + //! create a new page + pt_entry page=0; + pt_entry_add_attrib (&page, I86_PTE_PRESENT); + pt_entry_add_attrib (&page, I86_PTE_WRITABLE); + pt_entry_add_attrib (&page, I86_PTE_USER); + pt_entry_set_frame (&page, frame); + + //! ...and add it to the page table + table->m_entries [PAGE_TABLE_INDEX (virt) ] = page; + pages--; + if(pages<=0)break; + } + + pd_entry* entry = &dir->m_entries [PAGE_DIRECTORY_INDEX (virt_addr) ]; + *entry=0; + pd_entry_add_attrib (entry, I86_PDE_PRESENT); + pd_entry_add_attrib (entry, I86_PDE_WRITABLE); + pd_entry_add_attrib (entry, I86_PDE_USER); + pd_entry_set_frame (entry, (physical_addr)table); + + phys_addr+=1024*4096; + virt_addr+=1024*4096; + } +} +pdirectory* vmem_kernel_dir() +{ + fixme("remove user flags where appropriate"); + fixme("do not waste soo many pages/page tables!"); + fixme("align properly!! / merge page tables if required!"); + pdirectory* dir = vmem_clean_dir(); + vmem_add_identity(dir,0,1024*8);//first 32 megs + if(fb_addr>0x100000)vmem_add_identity(dir,fb_addr,1024*4);//16megs (?) TODO: dynamic + vmem_add_identity(dir,apic_addr,1024*2); + vmem_add_identity(dir,io_apic_addr,1024*2); + vmem_add_alloc(dir,0x8000000,1024*4); + return dir; +} // // vmem init / also copies all the shit over for FORK @@ -266,22 +370,14 @@ void vmem_free_dir(pdirectory *dir) pdirectory* vmem_new_space_dir(pdirectory *copy_dir,bool stack_only) { - x86_paging_disable(); - - // - pdirectory* dir = (pdirectory*) kballoc(1); - - klog("new pdirectory: 0x%X",dir); - if (!dir)kpanic("unable to alloc pdirectory"); + x86_paging_disable(); //TODO: do not disable - // first of all let's zero all the entries - for(int i=0;i<1024;i++)dir->m_entries [i]=0; + pdirectory* dir = vmem_clean_dir(); // identity mapping for first blocks uint32_t phys_addr=0; uint32_t virt_addr=0; - - kernel_pages=8; + kernel_pages=8; //32megs // first pages are identity mapped for(int j=0;j<kernel_pages;j++) @@ -619,14 +715,10 @@ pdirectory* vmem_new_space_dir(pdirectory *copy_dir,bool stack_only) return dir; } -pdirectory* vmem_init(uint32_t kernel_blocks, uint32_t frameb_addr, uint32_t apic_ad, uint32_t ioapic_ad) +void vmem_init(uint32_t kernel_blocks, uint32_t frameb_addr, uint32_t apic_ad, uint32_t ioapic_ad) { fixme("do not share fb_addr with syscalls like that!"); fb_addr=frameb_addr; apic_addr=apic_ad; io_apic_addr=ioapic_ad; - kernel_pages=kernel_blocks/1024+1; - return vmem_new_space_dir(NULL,false); } - - diff --git a/kernel/vmem.h b/kernel/vmem.h index 4d00c3e..d6a6fe9 100644 --- a/kernel/vmem.h +++ b/kernel/vmem.h @@ -51,7 +51,8 @@ struct pdirectory_struct; -struct pdirectory_struct* vmem_init(uint32_t kernel_blocks,uint32_t fb_addr,uint32_t apic_addr, uint32_t ioapic_addr); +void vmem_init(uint32_t kernel_blocks,uint32_t fb_addr,uint32_t apic_addr, uint32_t ioapic_addr); void vmem_free_dir(struct pdirectory_struct *dir); struct pdirectory_struct* vmem_new_space_dir(struct pdirectory_struct *copy_dir,bool stack_only); +struct pdirectory_struct* vmem_kernel_dir(); |
