]> Zhao Yanbai Git Server - minix.git/commitdiff
map in kernel in 4MB, global-bit-set 'pages' if hardware
authorBen Gras <ben@minix3.org>
Mon, 18 May 2009 15:34:42 +0000 (15:34 +0000)
committerBen Gras <ben@minix3.org>
Mon, 18 May 2009 15:34:42 +0000 (15:34 +0000)
supports it. helps performance.

broken use of region data structure for kernel mapping to be fixed.

servers/vm/exec.c
servers/vm/i386/pagetable.c

index 4881423aa80dfe0eb2ab4d57662837a75f139483..47ec93889ac5f2314ef72c62040d0b4cc76331ef 100644 (file)
@@ -348,10 +348,12 @@ PUBLIC int proc_new(struct vmproc *vmp,
        vm_assert(!(data_start % VM_PAGE_SIZE));
        vm_assert((!text_start && !data_start) || (text_start && data_start));
 
+#if 0
        if(!map_proc_kernel(vmp)) {
                printf("VM: exec: map_proc_kernel failed\n");
                return ENOMEM;
        }
+#endif
 
        /* Place text at start of process. */
        vmp->vm_arch.vm_seg[T].mem_phys = ABS2CLICK(vstart);
index 235eafcf78dc0dbd75bca74e982b4c734f608084..8e3c827ce1f1821e3449cea2df0ee0a5d1871aad 100644 (file)
@@ -384,6 +384,7 @@ PUBLIC int pt_writemap(pt_t *pt, vir_bytes v, phys_bytes physaddr,
 /* Write mapping into page table. Allocate a new page table if necessary. */
 /* Page directory and table entries for this virtual address. */
        int p, pages, pde;
+       int finalpde;
        SANITYCHECK(SCL_FUNCTIONS);
 
        vm_assert(!(bytes % I386_PAGE_SIZE));
@@ -406,13 +407,18 @@ PUBLIC int pt_writemap(pt_t *pt, vir_bytes v, phys_bytes physaddr,
 
        PT_SANE(pt);
 
+       finalpde = I386_VM_PDE(v + I386_PAGE_SIZE * pages);
+
        /* First make sure all the necessary page tables are allocated,
         * before we start writing in any of them, because it's a pain
         * to undo our work properly. Walk the range in page-directory-entry
         * sized leaps.
         */
-       for(pde = I386_VM_PDE(v); pde <= I386_VM_PDE(v + I386_PAGE_SIZE * pages); pde++) {
+       for(pde = I386_VM_PDE(v); pde <= finalpde; pde++) {
                vm_assert(pde >= 0 && pde < I386_VM_DIR_ENTRIES);
+               if(pt->pt_dir[pde] & I386_VM_BIGPAGE) {
+                        vm_panic("pt_writemap: BIGPAGE found", NO_NUM);
+               }
                if(!(pt->pt_dir[pde] & I386_VM_PRESENT)) {
                        int r;
                        vm_assert(!pt->pt_dir[pde]);
@@ -494,6 +500,10 @@ PUBLIC int pt_new(pt_t *pt)
        /* Where to start looking for free virtual address space? */
        pt->pt_virtop = 0;
 
+        /* Map in kernel. */
+        if(pt_mapkernel(pt) != OK)
+                vm_panic("pt_new: pt_mapkernel failed", NO_NUM);
+
        return OK;
 }
 
@@ -574,11 +584,11 @@ PUBLIC void pt_init(void)
         vmp->vm_arch.vm_seg[D].mem_phys += ABS2CLICK(moveup);
         vmp->vm_arch.vm_seg[S].mem_phys += ABS2CLICK(moveup);
        
+#if 0
         /* Map in kernel. */
         if(pt_mapkernel(newpt) != OK)
                 vm_panic("pt_init: pt_mapkernel failed", NO_NUM);
 
-#if 0
        /* Allocate us a page table in which to remember page directory
         * pointers.
         */
@@ -705,32 +715,45 @@ PUBLIC void pt_free(pt_t *pt)
 PUBLIC int pt_mapkernel(pt_t *pt)
 {
        int r;
-       static int pde = -1;
-       int global;
+       static int pde = -1, do_bigpage = 0;
+       u32_t global = 0;
+       static u32_t kern_phys;
+       static int printed = 0;
 
        if(global_bit_ok) global = I386_VM_GLOBAL;
 
         /* Any i386 page table needs to map in the kernel address space. */
         vm_assert(vmproc[VMP_SYSTEM].vm_flags & VMF_INUSE);
 
-       if(pde == -1) {
+       if(pde == -1 && bigpage_ok) {
                int pde1, pde2;
                pde1 = I386_VM_PDE(KERNEL_TEXT);
                pde2 = I386_VM_PDE(KERNEL_DATA+KERNEL_DATA_LEN);
-               vm_assert(pde1 == pde2);
-               pde = pde1;
-               vm_assert(pde >= 0);
+               if(pde1 != pde2) {
+                       printf("VM: pt_mapkernel: kernel too big?");
+                       bigpage_ok = 0;
+               } else {
+                       kern_phys = KERNEL_TEXT & I386_VM_ADDR_MASK_4MB;
+                       pde = pde1;
+                       do_bigpage = 1;
+                       vm_assert(pde >= 0);
+               }
        }
 
-        /* Map in text. flags: don't write, supervisor only */
-        if((r=pt_writemap(pt, KERNEL_TEXT, KERNEL_TEXT, KERNEL_TEXT_LEN,
-               I386_VM_PRESENT|global, 0)) != OK)
-               return r;
+       if(do_bigpage) {
+               pt->pt_dir[pde] = kern_phys |
+                       I386_VM_BIGPAGE|I386_VM_PRESENT|I386_VM_WRITE|global;
+       } else {
+               /* Map in text. flags: don't write, supervisor only */
+               if((r=pt_writemap(pt, KERNEL_TEXT, KERNEL_TEXT, KERNEL_TEXT_LEN,
+                       I386_VM_PRESENT|global, 0)) != OK)
+                       return r;
  
-        /* Map in data. flags: read-write, supervisor only */
-        if((r=pt_writemap(pt, KERNEL_DATA, KERNEL_DATA, KERNEL_DATA_LEN,
-               I386_VM_PRESENT|I386_VM_WRITE|global, 0)) != OK)
-               return r;
+               /* Map in data. flags: read-write, supervisor only */
+               if((r=pt_writemap(pt, KERNEL_DATA, KERNEL_DATA, KERNEL_DATA_LEN,
+                       I386_VM_PRESENT|I386_VM_WRITE|global, 0)) != OK)
+                       return r;
+       }
 
        return OK;
 }