diff options
Diffstat (limited to 'kernel/vmem.c')
| -rw-r--r-- | kernel/vmem.c | 478 |
1 files changed, 36 insertions, 442 deletions
diff --git a/kernel/vmem.c b/kernel/vmem.c index c004f9e..3752725 100644 --- a/kernel/vmem.c +++ b/kernel/vmem.c @@ -143,17 +143,10 @@ static bool pd_entry_is_present (pd_entry e) return e&I86_PDE_PRESENT; } -/* -bool pd_entry_is_user (pd_entry e) -{ - return 1; -} - -bool pd_entry_is_4mb (pd_entry e) +bool pt_entry_is_user (pt_entry e) { - return 1; + return e&I86_PTE_USER; } -*/ static bool pd_entry_is_writable (pd_entry e) { @@ -208,7 +201,7 @@ static pdirectory* vmem_clean_dir() } // addresses need to be page aligned. (or will be forced down) -static void vmem_add_generic(pdirectory* dir,uint32_t phys,uint32_t virt,uint32_t pages, bool alloc) +static void vmem_add_generic(pdirectory* dir,uint32_t phys,uint32_t virt,uint32_t pages, bool alloc, bool user) { fixme("make sure the pages are marked as used in the physical mem manager, really?"); @@ -232,7 +225,7 @@ static void vmem_add_generic(pdirectory* dir,uint32_t phys,uint32_t virt,uint32_ pd_entry_add_attrib (entry, I86_PDE_PRESENT); pd_entry_add_attrib (entry, I86_PDE_WRITABLE); - pd_entry_add_attrib (entry, I86_PDE_USER); + if(user)pd_entry_add_attrib (entry, I86_PDE_USER); pd_entry_set_frame (entry, table); } else{ @@ -250,7 +243,7 @@ static void vmem_add_generic(pdirectory* dir,uint32_t phys,uint32_t virt,uint32_ 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); + if(user)pt_entry_add_attrib (&page, I86_PTE_USER); pt_entry_set_frame (&page, phys); //and add it to the page table @@ -264,18 +257,18 @@ static void vmem_add_generic(pdirectory* dir,uint32_t phys,uint32_t virt,uint32_ pages--; } } -static void vmem_add_alloc(pdirectory* dir,uint32_t addr,uint32_t pages) +static void vmem_add_alloc(pdirectory* dir,uint32_t addr,uint32_t pages,bool user) { - vmem_add_generic(dir,addr,addr,pages, true); + vmem_add_generic(dir,addr,addr,pages, true,user); } -static void vmem_add_remap(pdirectory* dir,uint32_t phys,uint32_t virt,uint32_t pages) +static void vmem_add_remap(pdirectory* dir,uint32_t phys,uint32_t virt,uint32_t pages,bool user) { - vmem_add_generic(dir,phys,virt,pages, false); + vmem_add_generic(dir,phys,virt,pages, false,user); } -static void vmem_add_identity(pdirectory* dir,uint32_t addr,uint32_t pages) +static void vmem_add_identity(pdirectory* dir,uint32_t addr,uint32_t pages, bool user) { - vmem_add_generic(dir,addr,addr,pages, false); + vmem_add_generic(dir,addr,addr,pages, false,user); } pdirectory* vmem_kernel_dir() @@ -289,18 +282,34 @@ pdirectory* vmem_kernel_dir() pdirectory* dir = vmem_clean_dir(); - vmem_add_identity(dir,0,1024*8);//identity map first 32 megs... + vmem_add_identity(dir,0,1024*8,false);//identity map first 32 megs... - vmem_add_remap(dir,fb_addr,VMEM_FRAMEBUFFER,1024*8);//32megs should be enough for 4k (think about pitch) - vmem_add_remap(dir,local_apic_addr,VMEM_LAPIC,1); //apic addr should be at pagestart, right? TODO: check. - vmem_add_remap(dir,io_apic_addr,VMEM_IOAPIC,1); - vmem_add_remap(dir,mod_start,VMEM_EXT2_RAMIMAGE,1024*8);//32megs for ramimage: TODO: check if enough? + vmem_add_remap(dir,fb_addr,VMEM_FRAMEBUFFER,1024*8,false);//32megs should be enough for 4k (think about pitch) + vmem_add_remap(dir,local_apic_addr,VMEM_LAPIC,1,false); //apic addr should be at pagestart, right? TODO: check. + vmem_add_remap(dir,io_apic_addr,VMEM_IOAPIC,1,false); + vmem_add_remap(dir,mod_start,VMEM_EXT2_RAMIMAGE,1024*8,false);//32megs for ramimage: TODO: check if enough? - vmem_add_alloc(dir,VMEM_CPU_PRIVATE,4); - vmem_add_alloc(dir,VMEM_CPU_STACK_TOP-4096*4,4); + vmem_add_alloc(dir,VMEM_CPU_PRIVATE,4,false); + vmem_add_alloc(dir,VMEM_CPU_STACK_TOP-4096*4,4,false); - vmem_add_alloc(dir,VMEM_USER_PROG,1024*2); - vmem_add_alloc(dir,VMEM_USER_STACK_TOP-4096*4,4); + vmem_add_alloc(dir,VMEM_USER_PROG,1024*2,true); + vmem_add_alloc(dir,VMEM_USER_STACK_TOP-4096*4,4,true); + + return dir; +} + +pdirectory* vmem_new_space_dir(pdirectory *copy_dir,bool stack_only) +{ + pdirectory* dir = vmem_clean_dir(); + //copy non-user pages. + for(int i=0;i<1024;i++) + { + uint32_t src_pt=copy_dir->m_entries [i]; + if(!pt_entry_is_user(src_pt))dir->m_entries [i]=src_pt; + } + + vmem_add_alloc(dir,VMEM_USER_PROG,1024*2,true); + vmem_add_alloc(dir,VMEM_USER_STACK_TOP-4096*4,4,true); return dir; } @@ -317,418 +326,3 @@ void vmem_init(multiboot_information *cfg_multiboot, acpi_information *cfg_acpi) } -/////////////////////////////////////////////////////////////////////// - -/// SHIT BELOW THIs LINE -void vmem_free_dir(pdirectory *dir) -{ - x86_paging_disable(); //TODO : do not disable this! - - uint32_t virt_addr=0; - - // first pages are identity mapped (kernel space) just remove links - for(int j=0;j<3;j++) - { - pd_entry* entry = &dir->m_entries [PAGE_DIRECTORY_INDEX (virt_addr) ]; - virt_addr+=1024*4096; - } - - // programm space - virt_addr=0x8000000; - for(int j=0;j<2;j++) - { - - pd_entry* entry = &dir->m_entries [PAGE_DIRECTORY_INDEX (virt_addr) ]; - ptable *table=pd_entry_get_frame(entry); - - for (int i=0, virt=virt_addr; i<1024; i++, virt+=4096) - { - pt_entry pte=&table->m_entries [PAGE_TABLE_INDEX (virt) ]; - mem_free_block(pt_entry_get_frame(pte)); // get free space from the memory manager - } - - mem_free_block(pd_entry_get_frame (entry)); - virt_addr+=1024*4096; - - } - - // stack - virt_addr=0x8c00000; - for(int j=0;j<1;j++) - { - - pd_entry* entry = &dir->m_entries [PAGE_DIRECTORY_INDEX (virt_addr) ]; - ptable *table=pd_entry_get_frame(entry); - - for (int i=0, virt=virt_addr; i<1024; i++, virt+=4096) - { - pt_entry pte=&table->m_entries [PAGE_TABLE_INDEX (virt) ]; - mem_free_block(pt_entry_get_frame(pte)); // get free space from the memory manager - } - - mem_free_block(pd_entry_get_frame (entry)); - virt_addr+=1024*4096; - - } - mem_free_block(dir); - - x86_paging_enable(); -} -// -// vmem init / also copies all the shit over for FORK -// if copy_dir==NULL creates brandnew dir -// otherwise copies kernel pages and copies -// programm pages procreates new programmspace -// -// TODO: FIX -// KERNEL SPACE `kernel_pages` first 8 PAGES = 32megs -// FRAMEBUFER WE GET ON INIT -// PROGRAMM SPACE HARDCODED TO 0x8000000+2 pages and 0x8c00000+1 pages -// - -pdirectory* vmem_new_space_dir(pdirectory *copy_dir,bool stack_only) -{ - x86_paging_disable(); //TODO: do not disable - - pdirectory* dir = vmem_clean_dir(); - - // identity mapping for first blocks - uint32_t phys_addr=0; - uint32_t virt_addr=0; - kernel_pages=8; //32megs - - // first pages are identity mapped - for(int j=0;j<kernel_pages;j++) - { - - // this is the table for our page directory. It maps 1024*4096 bytes - ptable* table; - - // create new tables on init - if(copy_dir==NULL) - { - // alloc space for our new table - table = (ptable*) kballoc(1); - if (!table)kpanic("unable to alloc table"); - - //! 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; - } - - 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); - - } - - // otherwise simply take existing stuff from pdir 0 - else - { - dir->m_entries[PAGE_DIRECTORY_INDEX(virt_addr)]= - copy_dir->m_entries[PAGE_DIRECTORY_INDEX(virt_addr)]; - - } - - phys_addr+=1024*4096; - virt_addr+=1024*4096; - } - - // FRAMEBUFFER IDENTITY MAP (4pages enought? ) - phys_addr=fb_addr; - virt_addr=fb_addr; - - if(fb_addr>0x100000) - for(int j=0;j<4;j++) - { - - // this is the table for our page directory. It maps 1024*4096 bytes - ptable* table; - - // create new tables on init - if(copy_dir==NULL) - { - // alloc space for our new table - table = (ptable*) kballoc(1); - if (!table)kpanic("unable to alloc table"); - - //! 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; - } - - 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); - - } - - // otherwise simply take existing stuff from pdir 0 - else - { - dir->m_entries[PAGE_DIRECTORY_INDEX(virt_addr)]= - copy_dir->m_entries[PAGE_DIRECTORY_INDEX(virt_addr)]; - - } - - phys_addr+=1024*4096; - virt_addr+=1024*4096; - } - - // 2 pages for apic ( in case on boundary??) - phys_addr=local_apic_addr; - virt_addr=local_apic_addr; - - for(int j=0;j<2;j++) - { - - // this is the table for our page directory. It maps 1024*4096 bytes - ptable* table; - - // create new tables on init - if(copy_dir==NULL) - { - // alloc space for our new table - table = (ptable*) kballoc(1); - if (!table)kpanic("unable to alloc table"); - - //! 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; - } - - 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); - - } - - // otherwise simply take existing stuff from pdir 0 - else - { - dir->m_entries[PAGE_DIRECTORY_INDEX(virt_addr)]= - copy_dir->m_entries[PAGE_DIRECTORY_INDEX(virt_addr)]; - - } - - phys_addr+=1024*4096; - virt_addr+=1024*4096; - } - // 2 pages for ioapic ( in case on boundary??) - phys_addr=io_apic_addr; - virt_addr=io_apic_addr; - - for(int j=0;j<2;j++) - { - - // this is the table for our page directory. It maps 1024*4096 bytes - ptable* table; - - // create new tables on init - if(copy_dir==NULL) - { - // alloc space for our new table - table = (ptable*) kballoc(1); - if (!table)kpanic("unable to alloc table"); - - //! 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; - } - - 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); - - } - - // otherwise simply take existing stuff from pdir 0 - else - { - dir->m_entries[PAGE_DIRECTORY_INDEX(virt_addr)]= - copy_dir->m_entries[PAGE_DIRECTORY_INDEX(virt_addr)]; - - } - - phys_addr+=1024*4096; - virt_addr+=1024*4096; - } - // programm space - virt_addr=0x8000000; - for(int j=0;j<2;j++) - { - if(stack_only) - { - dir->m_entries[PAGE_DIRECTORY_INDEX(virt_addr)]= - copy_dir->m_entries[PAGE_DIRECTORY_INDEX(virt_addr)]; - virt_addr+=1024*4096; - continue; - } - - ptable* table = (ptable*) kballoc (1); - pd_entry *oldentry=NULL; - ptable* oldtable=NULL; - - if(copy_dir!=NULL) - { - oldentry=&(copy_dir->m_entries[PAGE_DIRECTORY_INDEX(virt_addr)]); - oldtable=pd_entry_get_frame(oldentry); - } - - klog("oldtable at: 0x%08X",oldtable); - - if (!table)kpanic("unable to alloc table"); - klog("alloc table: %08X",table); - - for (int i=0, virt=virt_addr; i<1024; i++, virt+=4096) - { - //klog("i = %d",i); - 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! - if(copy_dir!=NULL) - { - uint32_t addr_old=pt_entry_get_frame(&oldtable->m_entries[PAGE_TABLE_INDEX(virt)]); - //klog("physical memcpy(0x%08X,0x%08X,4096)",phys_addr, addr_old); - memcpy(phys_addr,addr_old,4096); - - } - - 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; - } - - // programm space : stack? - virt_addr=0x8c00000; - for(int j=0;j<1;j++) - { - - ptable* table = (ptable*) kballoc (1); - pd_entry *oldentry=NULL; - ptable* oldtable=NULL; - - if(copy_dir!=NULL) - { - oldentry=&(copy_dir->m_entries[PAGE_DIRECTORY_INDEX(virt_addr)]); - oldtable=pd_entry_get_frame(oldentry); - } - klog("oldtable at: 0x%08X",oldtable); - - if (!table)kpanic("unable to alloc table"); - klog("alloc table: %08X",table); - - for (int i=0, virt=virt_addr; i<1024; i++, virt+=4096) - { - 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! - if(copy_dir!=NULL) - { - uint32_t addr_old=pt_entry_get_frame(&oldtable->m_entries[PAGE_TABLE_INDEX(virt)]); - //klog("physical memcpy(0x%08X,0x%08X,4096)",phys_addr, addr_old); - memcpy(phys_addr,addr_old,4096); - - } - - 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; - - } - - if(copy_dir==NULL) // this happens only on init - { - klog("initializing virtual memory (paging)"); - x86_set_page_directory(dir); - } - - x86_paging_enable(); - return dir; -} |
