]> Zhao Yanbai Git Server - minix.git/commitdiff
copy of beng's working copy
authorBen Gras <ben@minix3.org>
Wed, 20 May 2009 16:54:58 +0000 (16:54 +0000)
committerBen Gras <ben@minix3.org>
Wed, 20 May 2009 16:54:58 +0000 (16:54 +0000)
13 files changed:
include/minix/com.h
include/minix/config.h
include/sys/vm_i386.h
kernel/arch/i386/arch_do_vmctl.c
kernel/arch/i386/include/archconst.h
kernel/arch/i386/klib386.s
kernel/arch/i386/memory.c
kernel/arch/i386/protect.c
kernel/arch/i386/proto.h
servers/vm/glo.h
servers/vm/i386/pagetable.c
servers/vm/main.c
servers/vm/utility.c

index 267c187343f823a7aaa43bc3bf7d27fae6e3757f..aecb857339099c3713a32b13dc3e19bf8ef78a65 100755 (executable)
 #define VMCTL_MEMREQ_REPLY     15
 #define VMCTL_INCSP            16
 #define VMCTL_NOPAGEZERO       18
+#define VMCTL_I386_KERNELLIMIT 19
+#define VMCTL_I386_PAGEDIRS    20
+#define VMCTL_I386_PDE         21
+#define VMCTL_I386_PDEVAL      22
+#define VMCTL_I386_FREEPDE     23
 
 /*===========================================================================*
  *                Messages for the Reincarnation Server                     *
index c8ccdfea9dbc720f13ebe9c4e6d0bebe36052766..c4b3b969042b49adbd61e0372713e54f33ff51d1 100755 (executable)
@@ -96,6 +96,6 @@
 #define CPROFILE          0    /* call profiling */
 
 /* Compile kernel so that first page of code and data can be unmapped. */
-#define VM_KERN_NOPAGEZERO      1       
+#define VM_KERN_NOPAGEZERO      0
 
 #endif /* _CONFIG_H */
index 7fd137ffdee519871c0e98cf5b44dcbc5b68865f..1ab6d4c126e3e04cf09ce46867b684c44ccb1f39 100644 (file)
@@ -14,6 +14,7 @@ sys/vm_i386.h
 #define I386_VM_ACC    0x020   /* Accessed */
 #define I386_VM_ADDR_MASK 0xFFFFF000 /* physical address */
 #define I386_VM_ADDR_MASK_4MB 0xFFC00000 /* physical address */
+#define I386_VM_OFFSET_MASK_4MB 0x003FFFFF /* physical address */
 
 /* Page directory specific flags. */
 #define I386_VM_BIGPAGE        0x080   /* 4MB page */
index 523165d82a19f4c43bde6b1b9808c89a19f68ebb..7ab5aa3ee71e2acc52af9e889832beaa4a534e80 100644 (file)
 #include "../../system.h"
 #include <minix/type.h>
 
+#include "proto.h"
+
 extern u32_t kernel_cr3;
+extern u32_t *vm_pagedirs;
 
 /*===========================================================================*
  *                             arch_do_vmctl                                *
@@ -19,6 +22,10 @@ PUBLIC int arch_do_vmctl(m_ptr, p)
 register message *m_ptr;       /* pointer to request message */
 struct proc *p;
 {
+
+  static int vmpde = -1;
+  static u32_t pdeval = -1;
+
   switch(m_ptr->SVMCTL_PARAM) {
        case VMCTL_I386_GETCR3:
                /* Get process CR3. */
@@ -53,6 +60,41 @@ struct proc *p;
                m_ptr->SVMCTL_PF_I386_ERR = rp->p_pagefault.pf_flags;
                return OK;
        }
+       case VMCTL_I386_KERNELLIMIT:
+       {
+               /* VM wants kernel to increase its segment. */
+               kprintf("kernel: increase limit to 0x%x\n", 
+                       m_ptr->SVMCTL_VALUE);
+               return prot_set_kern_seg_limit(m_ptr->SVMCTL_VALUE);
+       }
+       case VMCTL_I386_PAGEDIRS:
+       {
+               int pde;
+               vm_pagedirs = (u32_t *) m_ptr->SVMCTL_VALUE;
+               kprintf("kernel: pagedirs now 0x%lx\n", vm_pagedirs);
+               return OK;
+       }
+       case VMCTL_I386_PDE:
+       {
+               vmpde = m_ptr->SVMCTL_VALUE;
+               kprintf("kernel: HACK: vmpde %d\n", vmpde);
+               return OK;
+       }
+       case VMCTL_I386_PDEVAL:
+       {
+               pdeval = m_ptr->SVMCTL_VALUE;
+               kprintf("kernel: HACK: vmpde %d, set val 0x%x\n",
+                       vmpde, pdeval);
+               i386_updatepde(vmpde, pdeval);
+               kprintf("kernel: HACK: vmpde %d, set val 0x%x done\n",
+                       vmpde, pdeval);
+               return OK;
+       }
+       case VMCTL_I386_FREEPDE:
+       {
+               i386_freepde(m_ptr->SVMCTL_VALUE);
+               return OK;
+       }
   }
 
   kprintf("arch_do_vmctl: strange param %d\n", m_ptr->SVMCTL_PARAM);
index d1d78d5f293068c5daf622e073ecf92549935c8c..368f5efa450a58a130e0549030c6abbee0d201a3 100644 (file)
 #define IOPL_MASK 0x003000
 
 #define vir2phys(vir)   (kinfo.data_base + (vir_bytes) (vir))
+#define phys2vir(ph)   ((vir_bytes) (ph) - kinfo.data_base)
 
 #endif /* _I386_ACONST_H */
index 0aff6c0bd8a353c2b447b8b435684a6b2e2f46a6..dfec1dbb9d11685701aeae2b1bb929cb8586333d 100755 (executable)
@@ -40,6 +40,8 @@
 .define        _write_cr0      ! write a value in cr0
 .define        _read_cr4
 .define        _write_cr4
+.define _i386_invlpg_addr
+.define _i386_invlpg_level0
 
 .define        _kernel_cr3     
 
@@ -644,3 +646,15 @@ _write_cr3:
        pop     ebp
        ret
 
+!*===========================================================================*
+!*                             i386_invlpg                             *
+!*===========================================================================*
+! PUBLIC void i386_invlpg(void);
+_i386_invlpg_level0:
+       push    ebp
+       invlpg  (_i386_invlpg_addr)
+       pop     ebp
+       ret
+
+
+
index a04b0e94c120f611c26e8eb5668ffb0ff151c41b..ed5b051695cc6301c945bb42441fa1cc826fb111 100644 (file)
@@ -23,6 +23,13 @@ PUBLIC u32_t kernel_cr3;
 extern u32_t cswitch;
 u32_t last_cr3 = 0;
 
+u32_t *vm_pagedirs = NULL;
+
+u32_t i386_invlpg_addr = 0;
+
+#define WANT_FREEPDES 4
+PRIVATE int nfreepdes = 0, freepdes[WANT_FREEPDES];
+
 #define HASPT(procptr) ((procptr)->p_seg.p_cr3 != 0)
 
 FORWARD _PROTOTYPE( void phys_put32, (phys_bytes addr, u32_t value)    );
@@ -693,6 +700,92 @@ void vm_print(u32_t *root)
        return;
 }
 
+void invlpg_range(u32_t lin, u32_t bytes)
+{
+       u32_t o;
+       o = lin % I386_PAGE_SIZE;
+       lin -= o;
+       bytes += o;
+       while(bytes >= I386_PAGE_SIZE) {
+               i386_invlpg_addr = lin;
+               level0(i386_invlpg_level0);
+               lin += I386_PAGE_SIZE;
+               bytes -= I386_PAGE_SIZE;
+       }
+}
+
+/*===========================================================================*
+ *                             lin_lin_copy                                 *
+ *===========================================================================*/
+int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, u8_t *vsrc,
+       struct proc *dstproc, vir_bytes dstlinaddr, u8_t *vdst,
+       vir_bytes bytes)
+{
+
+       if(nfreepdes < 2)
+               minix_panic("vm: not enough free PDE's", NO_NUM);
+
+       util_stacktrace();
+
+#define CREATEPDE(PROC, PTR, LINADDR, OFFSET, FREEPDE, VIRT) { \
+       if(iskernelp(PROC)) {                                   \
+               PTR = VIRT;                                     \
+               OFFSET = 0;                                     \
+       } else {                                                \
+               u32_t *pdevalptr;                               \
+               u32_t myphysaddr;                               \
+               int pde_index;                                  \
+               pde_index = I386_VM_PDE(LINADDR);               \
+               pdevalptr = (u32_t *) ((u8_t *) vm_pagedirs +   \
+                       I386_PAGE_SIZE * PROC->p_nr +           \
+                       I386_VM_PT_ENT_SIZE * pde_index);       \
+               kprintf("pagedirs: 0x%x p_nr: %d linaddr: 0x%x pde: %d\n", \
+                       vm_pagedirs, PROC->p_nr, LINADDR, pde_index);   \
+               kprintf("pde ptr: 0x%x\n", pdevalptr);          \
+               kprintf("value: 0x%x\n", *pdevalptr);           \
+               myphysaddr = kernel_cr3 + FREEPDE*I386_VM_PT_ENT_SIZE; \
+               phys_put32(myphysaddr, *pdevalptr);             \
+               PTR = (u8_t *) phys2vir(I386_BIG_PAGE_SIZE*FREEPDE);    \
+               kprintf("ptr: 0x%x\n", PTR);            \
+               OFFSET = LINADDR & I386_VM_OFFSET_MASK_4MB;     \
+               kprintf("offset: 0x%lx & 0x%lx -> 0x%lx\n", LINADDR, \
+                       I386_VM_OFFSET_MASK_4MB, OFFSET);       \
+               invlpg_range(LINADDR, bytes + I386_PAGE_SIZE);  \
+       }                                                       \
+}
+
+       while(bytes > 0) {
+               u8_t *srcptr, *dstptr;
+               vir_bytes srcoffset, dstoffset, chunk, remain;
+
+               /* Set up 4MB ranges. */
+               CREATEPDE(srcproc, srcptr, srclinaddr, srcoffset, freepdes[0], vsrc);
+               CREATEPDE(dstproc, dstptr, dstlinaddr, dstoffset, freepdes[1], vdst);
+
+               remain = I386_BIG_PAGE_SIZE - MAX(srcoffset, dstoffset);
+               chunk = MIN(bytes, remain);
+
+               /* Copy pages. */
+               while(chunk > 0) {
+                       kprintf("copy %d -> %d  %d/%d using 0x%lx+0x%lx -> 0x%lx+0x%lx\n",
+                               srcproc->p_endpoint, dstproc->p_endpoint,
+                               chunk, bytes, srcptr, srcoffset,
+                               dstptr, dstoffset);
+                       memcpy(dstptr + dstoffset, srcptr + srcoffset, chunk);
+                       kprintf("done\n");
+               }
+
+               /* Update counter and addresses for next iteration, if any. */
+               bytes -= chunk;
+               srclinaddr += chunk;
+               dstlinaddr += chunk;
+               vsrc += chunk;
+               vdst += chunk;
+       }
+
+       return OK;
+}
+
 /*===========================================================================*
  *                             virtual_copy_f                               *
  *===========================================================================*/
@@ -778,6 +871,17 @@ int vmcheck;                       /* if nonzero, can return VMSUSPEND */
       }
   }
 
+#if 0
+  /* Special case: vir to vir copy */
+  if(vm_pagedirs && procs[_SRC_] && procs[_DST_] &&
+       HASPT(procs[_SRC_]) && HASPT(procs[_DST_]) &&
+       src_addr->segment == D && src_addr->segment == D) {
+       lin_lin_copy(procs[_SRC_], phys_addr[_SRC_], (u8_t *) src_addr->offset,
+               procs[_DST_], phys_addr[_DST_], (u8_t *) dst_addr->offset,
+               bytes);
+  }
+#endif
+
   if(vmcheck && procs[_SRC_])
        CHECKRANGE_OR_SUSPEND(procs[_SRC_], phys_addr[_SRC_], bytes, 0);
   if(vmcheck && procs[_DST_])
@@ -852,4 +956,21 @@ PUBLIC int arch_umap(struct proc *pr, vir_bytes offset, vir_bytes count,
        return EINVAL;
 }
 
+void i386_updatepde(int pde, u32_t val)
+{
+       u32_t physaddr;
+       physaddr = kernel_cr3 + pde*I386_VM_PT_ENT_SIZE;
+       kprintf("kernel: i386_updatepde: cr3 0x%lx; phys addr 0x%lx; pde %d, val 0x%lx\n",
+               kernel_cr3, physaddr, pde, val);
+       kprintf("previous entry was: 0x%lx\n", phys_get32(physaddr));
+       phys_put32(physaddr, val);
+       kprintf("entry is now: 0x%lx\n", phys_get32(physaddr));
+}
 
+void i386_freepde(int pde)
+{
+       if(nfreepdes >= WANT_FREEPDES)
+               return;
+       freepdes[nfreepdes++] = pde;
+       printf("kernel: free pde: %d\n", pde);
+}
index a360113eb5d3c98b63c3c5c907e8cf43a3a8aef5..8e2408ee7854f59af17a9e05dbafbeeca69c7ba9 100755 (executable)
@@ -189,6 +189,11 @@ PUBLIC void prot_init(void)
        { level0_call, LEVEL0_VECTOR, TASK_PRIVILEGE },
   };
 
+  /* Click-round kernel. */
+  if(kinfo.data_base % CLICK_SIZE)
+       minix_panic("kinfo.data_base not aligned", NO_NUM);
+  kinfo.data_size = ((kinfo.data_size+CLICK_SIZE-1)/CLICK_SIZE) * CLICK_SIZE;
+
   /* Build gdt and idt pointers in GDT where the BIOS expects them. */
   dtp= (struct desctableptr_s *) &gdt[GDT_INDEX];
   * (u16_t *) dtp->limit = (sizeof gdt) - 1;
@@ -325,3 +330,51 @@ PUBLIC void alloc_segments(register struct proc *rp)
       rp->p_reg.ds = (DS_LDT_INDEX*DESC_SIZE) | TI | privilege;
 }
 
+/*===========================================================================*
+ *                             prot_set_kern_seg_limit                      *
+ *===========================================================================*/
+PUBLIC int prot_set_kern_seg_limit(vir_bytes limit)
+{
+       struct proc *rp;
+       vir_bytes prev;
+       int orig_click;
+       int incr_clicks;
+
+       kprintf("prot_set_kern_seg_limit: limit 0x%lx\n", limit);
+
+       if(limit <= kinfo.data_base) {
+               kprintf("prot_set_kern_seg_limit: limit bogus\n");
+               return EINVAL;
+       }
+
+       kprintf("size: 0x%lx -> ", kinfo.data_size);
+
+       /* Do actual increase. */
+       orig_click = kinfo.data_size / CLICK_SIZE;
+       kinfo.data_size = limit - kinfo.data_base;
+       incr_clicks = kinfo.data_size / CLICK_SIZE - orig_click;
+
+       kprintf("0x%lx\n", kinfo.data_size);
+
+       kprintf("prot_set_kern_seg_limit: prot_init\n");
+
+       prot_init();
+
+       kprintf("prot_set_kern_seg_limit: prot_init done\n");
+
+       /* Increase kernel processes too. */
+       for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; ++rp) {
+               if (RTS_ISSET(rp, SLOT_FREE) || !iskernelp(rp))
+                       continue;
+               kprintf("prot_set_kern_seg_limit: increase %d 0x%x ->\n",
+                       rp->p_endpoint, rp->p_memmap[S].mem_len);
+               rp->p_memmap[S].mem_len += incr_clicks;
+               alloc_segments(rp);
+               kprintf("prot_set_kern_seg_limit: increase %d done -> 0x%x\n",
+                       rp->p_endpoint, rp->p_memmap[S].mem_len);
+       }
+       kprintf("prot_set_kern_seg_limit: done\n");
+
+       return OK;
+}
+
index b6ae9b27ad525ef11e148bbdf8cd448abb0ae808..a33153a6c2df59aa8ab3e7c7e5d0f66ae4926b4c 100644 (file)
@@ -49,6 +49,8 @@ _PROTOTYPE( void vir_insb, (u16_t port, struct proc *proc, u32_t vir, size_t cou
 _PROTOTYPE( void vir_outsb, (u16_t port, struct proc *proc, u32_t vir, size_t count));
 _PROTOTYPE( void vir_insw, (u16_t port, struct proc *proc, u32_t vir, size_t count));
 _PROTOTYPE( void vir_outsw, (u16_t port, struct proc *proc, u32_t vir, size_t count));
+_PROTOTYPE( void i386_updatepde, (int pde, u32_t val));
+_PROTOTYPE( void i386_freepde, (int pde));
 
 
 /* exception.c */
@@ -70,7 +72,7 @@ _PROTOTYPE( void phys_insb, (U16_t port, phys_bytes buf, size_t count)  );
 _PROTOTYPE( void phys_insw, (U16_t port, phys_bytes buf, size_t count)  );
 _PROTOTYPE( void phys_outsb, (U16_t port, phys_bytes buf, size_t count) );
 _PROTOTYPE( void phys_outsw, (U16_t port, phys_bytes buf, size_t count) );
-_PROTOTYPE( void i386_invlpg, (U32_t addr) );
+_PROTOTYPE( void i386_invlpg_level0, (void) );
 
 /* protect.c */
 _PROTOTYPE( void prot_init, (void)                                             );
@@ -79,6 +81,7 @@ _PROTOTYPE( void init_codeseg, (struct segdesc_s *segdp, phys_bytes base,
 _PROTOTYPE( void init_dataseg, (struct segdesc_s *segdp, phys_bytes base,
                 vir_bytes size, int privilege)                          );
 _PROTOTYPE( void enable_iop, (struct proc *pp)                          );
+_PROTOTYPE( int prot_set_kern_seg_limit, (vir_bytes limit)             );
 
 /* functions defined in architecture-independent kernel source. */
 #include "../../proto.h"
index 593fb1820ab4305d3ebcc8459fd30f3b5d3a96ad..404c2838e4abed658460fbd05c7fc8f8041cb89f 100644 (file)
@@ -25,4 +25,3 @@ EXTERN long vm_sanitychecklevel;
 
 /* vm operation mode state and values */
 EXTERN long vm_paged;
-EXTERN phys_bytes kernel_top_bytes;
index 8e3c827ce1f1821e3449cea2df0ee0a5d1871aad..27e07d8a6e549892461e315524bec66f1488a4f1 100644 (file)
 
 #include "memory.h"
 
-int global_bit_ok = 0;
-int bigpage_ok = 0;
-
 /* Location in our virtual address space where we can map in 
  * any physical page we want.
 */
-static unsigned char *varmap = NULL;   /* Our address space. */
-static u32_t varmap_loc;               /* Our page table. */
+PRIVATE unsigned char *varmap = NULL;  /* Our address space. */
+PRIVATE u32_t varmap_loc;              /* Our page table. */
+
+/* PDE used to map in kernel, kernel physical address. */
+PRIVATE int kernel_pde = -1, pagedir_pde = -1;
+PRIVATE u32_t kern_pde_val = 0, global_bit = 0, pagedir_pde_val;
+
+/* 4MB page size available in hardware? */
+PRIVATE int bigpage_ok = 0;
 
 /* Our process table entry. */
 struct vmproc *vmp = &vmproc[VM_PROC_NR];
@@ -52,7 +56,7 @@ struct vmproc *vmp = &vmproc[VM_PROC_NR];
  */
 #define SPAREPAGES 5
 int missing_spares = SPAREPAGES;
-static struct {
+PRIVATE struct {
        void *page;
        u32_t phys;
 } sparepages[SPAREPAGES];
@@ -262,10 +266,7 @@ PRIVATE void *vm_checkspares(void)
        }
        if(worst < n) worst = n;
        total += n;
-#if 0
-       if(n > 0)
-               printf("VM: made %d spares, total %d, worst %d\n", n, total, worst);
-#endif
+
        return NULL;
 }
 
@@ -520,13 +521,14 @@ PUBLIC void pt_init(void)
  */
         pt_t *newpt;
         int s, r;
-        vir_bytes v;
+        vir_bytes v, kpagedir;
         phys_bytes lo, hi; 
         vir_bytes extra_clicks;
         u32_t moveup = 0;
-
-       global_bit_ok = _cpufeature(_CPUF_I386_PGE);
-       bigpage_ok = _cpufeature(_CPUF_I386_PSE);
+       int global_bit_ok = 0;
+       int free_pde;
+       int p;
+       vir_bytes kernlimit;
 
         /* Shorthand. */
         newpt = &vmp->vm_pt;
@@ -541,6 +543,33 @@ PUBLIC void pt_init(void)
         }
 
        missing_spares = 0;
+
+       /* global bit and 4MB pages available? */
+       global_bit_ok = _cpufeature(_CPUF_I386_PGE);
+       bigpage_ok = _cpufeature(_CPUF_I386_PSE);
+
+       /* Set bit for PTE's and PDE's if available. */
+       if(global_bit_ok)
+               global_bit = I386_VM_GLOBAL;
+
+       /* Figure out kernel pde slot. */
+       {
+               int pde1, pde2;
+               pde1 = I386_VM_PDE(KERNEL_TEXT);
+               pde2 = I386_VM_PDE(KERNEL_DATA+KERNEL_DATA_LEN);
+               if(pde1 != pde2)
+                       vm_panic("pt_init: kernel too big", NO_NUM); 
+
+               /* Map in kernel with this single pde value if 4MB pages
+                * supported.
+                */
+               kern_pde_val = (KERNEL_TEXT & I386_VM_ADDR_MASK_4MB) |
+                               I386_VM_BIGPAGE|
+                               I386_VM_PRESENT|I386_VM_WRITE|global_bit;
+               kernel_pde = pde1;
+               vm_assert(kernel_pde >= 0);
+               free_pde = kernel_pde+1;
+       }
         
         /* Make new page table for ourselves, partly copied
          * from the current one.
@@ -584,18 +613,14 @@ 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);
-
        /* Allocate us a page table in which to remember page directory
         * pointers.
         */
        if(!(page_directories = vm_allocpages(&page_directories_phys,
                1, VMP_PAGETABLE)))
                 vm_panic("no virt addr for vm mappings", NO_NUM);
-#endif
+
+       memset(page_directories, 0, I386_PAGE_SIZE);
        
         /* Give our process the new, copied, private page table. */
         pt_bind(newpt, vmp);
@@ -646,6 +671,55 @@ PUBLIC void pt_init(void)
         }
         varmap = (unsigned char *) arch_map2vir(vmp, varmap_loc);
 
+       /* Find a PDE below processes available for mapping in the
+        * page directories (readonly).
+        */
+       pagedir_pde = free_pde++;
+       pagedir_pde_val = (page_directories_phys & I386_VM_ADDR_MASK) |
+                               I386_VM_PRESENT | I386_VM_USER;
+
+       printf("VM: HACK: pagedir pde val is 0x%x (phys 0x%x)\n",
+               pagedir_pde_val, page_directories_phys);
+
+       /* Temporary hack while kernel still maintains own pagetable */
+       if((r=sys_vmctl(SELF, VMCTL_I386_PDE, pagedir_pde)) != OK) {
+                vm_panic("VMCTL_I386_PDE failed", r);
+       }
+
+       printf("VM: HACK: pagedir pde val is 0x%x\n", pagedir_pde_val);
+
+       /* Temporary hack while kernel still maintains own pagetable */
+       if((r=sys_vmctl(SELF, VMCTL_I386_PDEVAL, pagedir_pde_val)) != OK) {
+                vm_panic("VMCTL_I386_PDEVAL failed", r);
+       }
+
+       /* Tell kernel about free pde's. */
+       while(free_pde*I386_BIG_PAGE_SIZE < VM_PROCSTART) {
+               printf("VM: telling kernel about free pde %d\n", free_pde);
+               if((r=sys_vmctl(SELF, VMCTL_I386_FREEPDE, free_pde++)) != OK) {
+                       vm_panic("VMCTL_I386_FREEPDE failed", r);
+               }
+       }
+
+       kernlimit = free_pde*I386_BIG_PAGE_SIZE;
+
+       printf("VM: set limit to 0x%x\n", kernlimit);
+
+       /* Increase kernel segment to address this memory. */
+       if((r=sys_vmctl(SELF, VMCTL_I386_KERNELLIMIT, kernlimit)) != OK) {
+                vm_panic("VMCTL_I386_KERNELLIMIT failed", r);
+       }
+
+       kpagedir = arch_map2vir(&vmproc[VMP_SYSTEM],
+               pagedir_pde*I386_BIG_PAGE_SIZE);
+       printf("VM: pagedir linear 0x%x, in kernel 0x%x\n",
+               pagedir_pde*I386_BIG_PAGE_SIZE, kpagedir);
+
+       /* Tell kernel how to get at the page directories. */
+       if((r=sys_vmctl(SELF, VMCTL_I386_PAGEDIRS, kpagedir)) != OK) {
+                vm_panic("VMCTL_I386_KERNELLIMIT failed", r);
+       }
+
         /* All OK. */
         return;
 }
@@ -657,6 +731,7 @@ PUBLIC void pt_init(void)
 PUBLIC int pt_bind(pt_t *pt, struct vmproc *who)
 {
        int slot;
+       u32_t phys;
 
        /* Basic sanity checks. */
        vm_assert(who);
@@ -664,15 +739,16 @@ PUBLIC int pt_bind(pt_t *pt, struct vmproc *who)
        if(pt) PT_SANE(pt);
        vm_assert(pt);
 
-#if 0
        slot = who->vm_slot;
        vm_assert(slot >= 0);
        vm_assert(slot < ELEMENTS(vmproc));
-       vm_assert(!(pt->pt_dir_phys & ~I386_VM_ADDR_MASK));
+       vm_assert(slot < I386_VM_PT_ENTRIES);
 
-       page_directories[slot] = (pt->pt_dir_phys & I386_VM_ADDR_MASK) | 
-               (I386_VM_PRESENT|I386_VM_WRITE);
-#endif
+       phys = pt->pt_dir_phys & I386_VM_ADDR_MASK;
+       vm_assert(pt->pt_dir_phys == phys);
+
+       /* Update "page directory pagetable." */
+       page_directories[slot] = phys | I386_VM_PRESENT|I386_VM_WRITE;
 
        /* Tell kernel about new page table root. */
        return sys_vmctl(who->vm_endpoint, VMCTL_I386_SETCR3,
@@ -715,46 +791,28 @@ PUBLIC void pt_free(pt_t *pt)
 PUBLIC int pt_mapkernel(pt_t *pt)
 {
        int r;
-       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 && bigpage_ok) {
-               int pde1, pde2;
-               pde1 = I386_VM_PDE(KERNEL_TEXT);
-               pde2 = I386_VM_PDE(KERNEL_DATA+KERNEL_DATA_LEN);
-               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);
-               }
-       }
-
-       if(do_bigpage) {
-               pt->pt_dir[pde] = kern_phys |
-                       I386_VM_BIGPAGE|I386_VM_PRESENT|I386_VM_WRITE|global;
+       if(bigpage_ok) {
+               pt->pt_dir[kernel_pde] = kern_pde_val;
        } 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)
+                       I386_VM_PRESENT|global_bit, 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)
+                       I386_VM_PRESENT|I386_VM_WRITE, 0)) != OK)
                        return r;
        }
 
+       /* Kernel also wants to know about all page directories. */
+       pt->pt_dir[pagedir_pde] = pagedir_pde_val;
+
        return OK;
 }
 
index 8b3b18d3ae6bc1ce13e25aa0cd43c9c9c5c7a2e7..31f870aa2a24865abbde05886cb9d45b0feb5ebb 100644 (file)
@@ -177,6 +177,7 @@ PUBLIC int main(void)
 PRIVATE void vm_init(void)
 {
        int s, i;
+       int click, clicksforgotten = 0;
        struct memory mem_chunks[NR_MEMS];
        struct boot_image image[NR_BOOT_PROCS];
        struct boot_image *ip;
@@ -251,11 +252,7 @@ PRIVATE void vm_init(void)
        /* Initialize tables to all physical memory. */
        mem_init(mem_chunks);
 
-       /* Bits of code need to know where a process can
-        * start in a pagetable.
-        */
-        kernel_top_bytes = find_kernel_top();
-
+#if 0
        /* Can first kernel pages of code and data be (left) mapped out?
         * If so, change the SYSTEM process' memory map to reflect this
         * (future mappings of SYSTEM into other processes will not include
@@ -272,6 +269,7 @@ PRIVATE void vm_init(void)
                vmp->vm_arch.vm_seg[D].mem_phys += DIFF;
                vmp->vm_arch.vm_seg[D].mem_len -= DIFF;
        }
+#endif
 
        /* Give these processes their own page table. */
        for (ip = &image[0]; ip < &image[NR_BOOT_PROCS]; ip++) {
@@ -318,6 +316,13 @@ PRIVATE void vm_init(void)
                                VM_STACKTOP);
        }
 
+       /* Temporary hack; throw away all lower memory. */
+       while((click=ALLOC_MEM(1, 0)) <= ABS2CLICK(VM_PROCSTART)) {
+               clicksforgotten++;
+       }
+
+       printf("VM: HACK: clicks forgotten: %d last one: 0x%x\n", clicksforgotten, click);
+
        /* Set up table of calls. */
 #define CALLMAP(code, func, thecaller) { int i;                              \
        if((i=CALLNUMBER(code)) < 0) { vm_panic(#code " invalid", (code)); } \
@@ -370,11 +375,3 @@ PRIVATE void vm_init(void)
                vm_panic("kernel loaded too high", NO_NUM);
 }
 
-#if 0
-void kputc(int c)
-{
-       if(c == '\n')
-               ser_putc('\r');
-       ser_putc(c);
-}
-#endif
index 47ed47a40fab18014635cd0710c36edabc8d370b..0987c7c09dc30efdd98d3b26a06efbaab7768e4e 100644 (file)
@@ -108,6 +108,9 @@ struct mem_map *map_ptr;                        /* memory to remove */
   }
   if (memp >= &mem_chunks[NR_MEMS])
   {
+       printf("VM: looking for memory at 0x%x, length 0x%x\n",
+               CLICK2ABS(map_ptr[T].mem_phys),
+               CLICK2ABS(map_ptr[T].mem_len));
         vm_panic("reserve_proc_mem: can't find map in mem_chunks ",
                 map_ptr[T].mem_phys);
   }