summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel <m.i@gmx.at>2018-09-10 04:13:28 +0200
committerMiguel <m.i@gmx.at>2018-09-10 04:13:28 +0200
commit65f5cca027af81e77b3e06da658b6d13f1861a03 (patch)
tree4e1aa57b8d4dedb00beb649992054faf6f24ff40
parent67e7f93fc2ea9c6d04698f9af29be78d0123afb0 (diff)
fixing paging / per cpu pages
-rw-r--r--driver/timer.c2
-rw-r--r--kernel/interrupts.c10
-rw-r--r--kernel/kernel.c18
-rw-r--r--kernel/mem.c2
-rw-r--r--kernel/scheduler.c3
-rw-r--r--kernel/smp.c24
-rw-r--r--kernel/vmem.c126
-rw-r--r--kernel/vmem.h3
8 files changed, 148 insertions, 40 deletions
diff --git a/driver/timer.c b/driver/timer.c
index 1ceebc5..34e7637 100644
--- a/driver/timer.c
+++ b/driver/timer.c
@@ -1,3 +1,4 @@
+#include "kernel.h"
#include "timer.h"
#include "asm_x86.h"
@@ -153,6 +154,7 @@ uint64_t timer_init()
uint64_t epoch_time=get_rtc_time();
task_system_clock_start=epoch_time*25; // since pit ticks 25times a second
asm_pit_rate_40ms();
+ fixme("pit rate does not work anymore 1/25 seconds??" );
return epoch_time;
}
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();