]> Zhao Yanbai Git Server - minix.git/commitdiff
kernel/vm: change pde table info from single buffer to explicit per-process.
authorBen Gras <ben@minix3.org>
Wed, 12 May 2010 08:31:05 +0000 (08:31 +0000)
committerBen Gras <ben@minix3.org>
Wed, 12 May 2010 08:31:05 +0000 (08:31 +0000)
makes code in kernel more readable, and allows better sanity checking on
using the pde info.

include/arch/i386/archtypes.h
include/minix/com.h
include/minix/syslib.h
kernel/arch/i386/arch_do_vmctl.c
kernel/arch/i386/memory.c
kernel/arch/i386/sconst.h
kernel/proto.h
kernel/system/do_clear.c
kernel/system/do_fork.c
lib/libsys/sys_vmctl.c
servers/vm/arch/i386/pagetable.c

index 3300a2ebb85a73b0a5716302963a20fa3c005a52..7db2f481d9d5d2d5f66dea9089825d4abd177751 100644 (file)
@@ -25,6 +25,7 @@ struct segdesc_s {            /* segment descriptor for protected mode */
 typedef struct segframe {
        reg_t p_ldt_sel;    /* selector in gdt with ldt base and limit */
        reg_t   p_cr3;          /* page table root */
+       u32_t   *p_cr3_v;
        struct segdesc_s p_ldt[LDT_SIZE]; /* CS, DS and remote */
 } segframe_t;
 
index 86ac88016a3a32793bd03403ec04a6146a4ffe53..9d64eec8f99da2d02a35cb2449f540ba068dd554 100644 (file)
 #define        SVMCTL_MRG_ADDR2        m2_l2   /* MEMREQ_GET reply: source address */
 #define SVMCTL_MRG_REQUESTOR   m2_p1   /* MEMREQ_GET reply: requestor */
 #define SVMCTL_MAP_VIR_ADDR    m1_p1
+#define SVMCTL_PTROOT          m1_i3
+#define SVMCTL_PTROOT_V                m1_p1
 
 /* Reply message for VMCTL_KERN_PHYSMAP */
 #define SVMCTL_MAP_FLAGS       m2_i1   /* VMMF_* */
 #define VMMF_UNCACHED          (1L << 0)
 
 /* Values for SVMCTL_PARAM. */
-#define VMCTL_I386_SETCR3      10
 #define VMCTL_CLEAR_PAGEFAULT  12
 #define VMCTL_I386_GETCR3      13
 #define VMCTL_MEMREQ_GET       14
 #define VMCTL_INCSP            16
 #define VMCTL_NOPAGEZERO       18
 #define VMCTL_I386_KERNELLIMIT 19
-#define VMCTL_I386_PAGEDIRS    20
 #define VMCTL_I386_FREEPDE     23
 #define VMCTL_ENABLE_PAGING    24
 #define VMCTL_I386_INVLPG      25
 #define VMCTL_FLUSHTLB         26
 #define VMCTL_KERN_PHYSMAP     27
 #define VMCTL_KERN_MAP_REPLY   28
+#define VMCTL_SETADDRSPACE     29
 
 /* Codes and field names for SYS_SYSCTL. */
 #define SYSCTL_CODE            m1_i1   /* SYSCTL_CODE_* below */
index 5d59540667439251b7e041cb0eeff856224f31cd..f09339374dae829c4ec0bd2027162ec5fc81a401 100644 (file)
@@ -79,6 +79,9 @@ _PROTOTYPE( int sys_sysctl_stacktrace, (endpoint_t who));
 _PROTOTYPE( int sys_vmctl_get_mapping, (int index, phys_bytes *addr,
        phys_bytes *len, int *flags));
 _PROTOTYPE( int sys_vmctl_reply_mapping, (int index, vir_bytes addr));
+_PROTOTYPE( int sys_vmctl_set_addrspace, (endpoint_t who,
+        phys_bytes ptroot, void *ptroot_v));
+
 
 /* Shorthands for sys_sdevio() system call. */
 #define sys_insb(port, proc_ep, buffer, count) \
index ca1d291b4e1a9f12f0fd94210f5bb9f63b233c71..a1be5e39d85732b43296824b1d831d2931bd932a 100644 (file)
@@ -12,8 +12,6 @@
 
 #include "proto.h"
 
-extern u8_t *vm_pagedirs;
-
 /*===========================================================================*
  *                             arch_do_vmctl                                *
  *===========================================================================*/
@@ -26,13 +24,15 @@ struct proc *p;
                /* Get process CR3. */
                m_ptr->SVMCTL_VALUE = p->p_seg.p_cr3;
                return OK;
-       case VMCTL_I386_SETCR3:
+       case VMCTL_SETADDRSPACE:
                /* Set process CR3. */
-               if(m_ptr->SVMCTL_VALUE) {
-                       p->p_seg.p_cr3 = m_ptr->SVMCTL_VALUE;
+               if(m_ptr->SVMCTL_PTROOT) {
+                       p->p_seg.p_cr3 = m_ptr->SVMCTL_PTROOT;
+                       p->p_seg.p_cr3_v = (u32_t *) m_ptr->SVMCTL_PTROOT_V;
                        p->p_misc_flags |= MF_FULLVM;
                } else {
                        p->p_seg.p_cr3 = 0;
+                       p->p_seg.p_cr3_v = NULL;
                        p->p_misc_flags &= ~MF_FULLVM;
                }
                RTS_UNSET(p, RTS_VMINHIBIT);
@@ -48,11 +48,6 @@ struct proc *p;
                r = prot_set_kern_seg_limit(m_ptr->SVMCTL_VALUE);
                return r;
        }
-       case VMCTL_I386_PAGEDIRS:
-       {
-               vm_pagedirs = (u8_t *) m_ptr->SVMCTL_VALUE;
-               return OK;
-       }
        case VMCTL_I386_FREEPDE:
        {
                i386_freepde(m_ptr->SVMCTL_VALUE);
index bb2f327e20348640ba082ae7f7582254d67220f7..b4c6111ad6bb454aef93bd486a18e46c0bd56b27 100644 (file)
 
 PRIVATE int psok = 0;
 
-#define PROCPDEPTR(pr, pi) ((u32_t *) ((u8_t *) vm_pagedirs +\
-                               I386_PAGE_SIZE * pr->p_nr +     \
-                               I386_VM_PT_ENT_SIZE * pi))
-
-PUBLIC u8_t *vm_pagedirs = NULL;
-
 #define MAX_FREEPDES (3 * CONFIG_MAX_CPUS)
 PRIVATE int nfreepdes = 0, freepdes[MAX_FREEPDES];
 
@@ -90,6 +84,7 @@ PRIVATE phys_bytes createpde(
 
        assert(free_pde_idx >= 0 && free_pde_idx < nfreepdes);
        pde = freepdes[free_pde_idx];
+       assert(pde >= 0 && pde < 1024);
 
        if(pr && ((pr == ptproc) || !HASPT(pr))) {
                /* Process memory is requested, and
@@ -106,7 +101,8 @@ PRIVATE phys_bytes createpde(
                 * accessible directly. Grab the PDE entry of that process'
                 * page table that corresponds to the requested address.
                 */
-               pdeval = *PROCPDEPTR(pr, I386_VM_PDE(linaddr));
+               assert(pr->p_seg.p_cr3_v);
+               pdeval = pr->p_seg.p_cr3_v[I386_VM_PDE(linaddr)];
        } else {
                /* Requested address is physical. Make up the PDE entry. */
                pdeval = (linaddr & I386_VM_ADDR_MASK_4MB) | 
@@ -118,8 +114,9 @@ PRIVATE phys_bytes createpde(
         * can access, into the currently loaded page table so it becomes
         * visible.
         */
-       if(*PROCPDEPTR(ptproc, pde) != pdeval) {
-               *PROCPDEPTR(ptproc, pde) = pdeval;
+       assert(ptproc->p_seg.p_cr3_v);
+       if(ptproc->p_seg.p_cr3_v[pde] != pdeval) {
+               ptproc->p_seg.p_cr3_v[pde] = pdeval;
                *changed = 1;
        }
 
@@ -155,6 +152,11 @@ PRIVATE int lin_lin_copy(const struct proc *srcproc, vir_bytes srclinaddr,
 
        assert(procslot >= 0 && procslot < I386_VM_DIR_ENTRIES);
 
+       if(srcproc) assert(!RTS_ISSET(srcproc, RTS_SLOT_FREE));
+       if(dstproc) assert(!RTS_ISSET(dstproc, RTS_SLOT_FREE));
+       assert(!RTS_ISSET(ptproc, RTS_SLOT_FREE));
+       assert(ptproc->p_seg.p_cr3_v);
+
        while(bytes > 0) {
                phys_bytes srcptr, dstptr;
                vir_bytes chunk = bytes;
@@ -191,6 +193,11 @@ PRIVATE int lin_lin_copy(const struct proc *srcproc, vir_bytes srclinaddr,
                dstlinaddr += chunk;
        }
 
+       if(srcproc) assert(!RTS_ISSET(srcproc, RTS_SLOT_FREE));
+       if(dstproc) assert(!RTS_ISSET(dstproc, RTS_SLOT_FREE));
+       assert(!RTS_ISSET(ptproc, RTS_SLOT_FREE));
+       assert(ptproc->p_seg.p_cr3_v);
+
        return OK;
 }
 
@@ -677,6 +684,8 @@ int vm_phys_memset(phys_bytes ph, const u8_t c, phys_bytes bytes)
 
        assert(nfreepdes >= 3);
 
+       assert(ptproc->p_seg.p_cr3_v);
+
        /* With VM, we have to map in the physical memory. 
         * We can do this 4MB at a time.
         */
@@ -695,6 +704,7 @@ int vm_phys_memset(phys_bytes ph, const u8_t c, phys_bytes bytes)
                ph += chunk;
        }
 
+       assert(ptproc->p_seg.p_cr3_v);
 
        return OK;
 }
@@ -1004,3 +1014,8 @@ PUBLIC int arch_enable_paging(struct proc * caller, const message * m_ptr)
 
        return OK;
 }
+
+PUBLIC void release_address_space(struct proc *pr)
+{
+       pr->p_seg.p_cr3_v = NULL;
+}
index 2a5e3b667319afa359c97227880c0b06094cd9b5..ca59b62bf9a8477e830e095ca5edaad7ab3da50b 100644 (file)
@@ -30,7 +30,8 @@
        FP_SAVE_AREA_P = P_STACKTOP
        P_LDT_SEL = FP_SAVE_AREA_P + 532
        P_CR3 = P_LDT_SEL+W
-       P_LDT = P_CR3+W
+       P_CR3_V = P_CR3+4
+       P_LDT = P_CR3_V+W
        P_MISC_FLAGS = P_LDT + 50
        Msize = 9       /* size of a message in 32-bit words*/
 
index 560f10662ba5ce592a3d2c1104b16152da5974ea..7f58ac8218459b6904dd91705439d59a5c97e1ea 100644 (file)
@@ -182,4 +182,5 @@ _PROTOTYPE( int copy_msg_from_user, (struct proc * p, message * user_mbuf,
 _PROTOTYPE( int copy_msg_to_user, (struct proc * p, message * src,
                                                        message * user_mbuf));
 _PROTOTYPE(void switch_address_space, (struct proc * p));
+_PROTOTYPE(void release_address_space, (struct proc *pr));
 #endif /* PROTO_H */
index 58819aa5c5a5357f875e0a70df6bf422ac2d9121..db960cb7a6baf6b4a88608c000680470ce1d7abd 100644 (file)
@@ -31,6 +31,8 @@ PUBLIC int do_clear(struct proc * caller, message * m_ptr)
   }
   rc = proc_addr(exit_p);      /* clean up */
 
+  release_address_space(rc);
+
   /* Don't clear if already cleared. */
   if(isemptyp(rc)) return OK;
 
index 936df8f5abebce99b5393f0711b80667e05e4d85..11629afb930a833c5875493d74eb13359939ec21 100644 (file)
@@ -117,6 +117,9 @@ PUBLIC int do_fork(struct proc * caller, message * m_ptr)
   RTS_UNSET(rpc, (RTS_SIGNALED | RTS_SIG_PENDING | RTS_P_STOP));
   sigemptyset(&rpc->p_pending);
 
+  rpc->p_seg.p_cr3 = 0;
+  rpc->p_seg.p_cr3_v = NULL;
+
   return r;
 }
 
index 73ab87430158c260ac64156cffe664bf700168c9..9656710544e9b048ee376d202bfc997800760f91 100644 (file)
@@ -26,6 +26,21 @@ PUBLIC int sys_vmctl_get_cr3_i386(endpoint_t who, u32_t *cr3)
   return(r);
 }
 
+PUBLIC int sys_vmctl_set_addrspace(endpoint_t who,
+        phys_bytes ptroot, void *ptroot_v)
+{
+  message m;
+  int r;
+
+  m.SVMCTL_WHO = who;
+  m.SVMCTL_PARAM = VMCTL_SETADDRSPACE;
+  m.SVMCTL_PTROOT = ptroot;
+  m.SVMCTL_PTROOT_V = ptroot_v;
+  r = _kernel_call(SYS_VMCTL, &m);
+
+  return(r);
+}
+
 PUBLIC int sys_vmctl_get_memreq(endpoint_t *who, vir_bytes *mem,
         vir_bytes *len, int *wrflag, endpoint_t *who_s, vir_bytes *mem_s,
         endpoint_t *requestor)
index 4fa248311ac8d37ba22070d1249e0e102da49878..939322b41a9a62e451b02d46d896a09a919bd223 100644 (file)
@@ -717,7 +717,7 @@ PUBLIC void pt_init(phys_bytes usedlimit)
  */
         pt_t *newpt;
         int s, r;
-        vir_bytes v, kpagedir;
+        vir_bytes v;
         phys_bytes lo, hi; 
         vir_bytes extra_clicks;
         u32_t moveup = 0;
@@ -886,14 +886,6 @@ PUBLIC void pt_init(phys_bytes usedlimit)
        /* first pde in use by process. */
        proc_pde = free_pde;
 
-       kpagedir = arch_map2vir(&vmproc[VMP_SYSTEM],
-               pagedir_pde*I386_BIG_PAGE_SIZE);
-
-       /* Tell kernel how to get at the page directories. */
-       if((r=sys_vmctl(SELF, VMCTL_I386_PAGEDIRS, kpagedir)) != OK) {
-                panic("VMCTL_I386_PAGEDIRS failed: %d", r);
-       }
-       
         /* Give our process the new, copied, private page table. */
        pt_mapkernel(newpt);    /* didn't know about vm_dir pages earlier */
         pt_bind(newpt, vmprocess);
@@ -922,12 +914,15 @@ PUBLIC int pt_bind(pt_t *pt, struct vmproc *who)
 {
        int slot, ispt;
        u32_t phys;
+       void *pdes;
 
        /* Basic sanity checks. */
        assert(who);
        assert(who->vm_flags & VMF_INUSE);
        assert(pt);
 
+       assert(pagedir_pde >= 0);
+
        slot = who->vm_slot;
        assert(slot >= 0);
        assert(slot < ELEMENTS(vmproc));
@@ -939,12 +934,21 @@ PUBLIC int pt_bind(pt_t *pt, struct vmproc *who)
        /* Update "page directory pagetable." */
        page_directories[slot] = phys | I386_VM_PRESENT|I386_VM_WRITE;
 
+       /* This is where the PDE's will be visible to the kernel
+        * in its address space.
+        */
+       pdes = (void *) arch_map2vir(&vmproc[VMP_SYSTEM],
+               pagedir_pde*I386_BIG_PAGE_SIZE + 
+                       slot * I386_PAGE_SIZE);
+
 #if 0
-       printf("VM: slot %d has pde val 0x%lx\n", slot, page_directories[slot]);
+       printf("VM: slot %d endpoint %d has pde val 0x%lx at kernel address 0x%lx\n",
+               slot, who->vm_endpoint, page_directories[slot], pdes);
 #endif
        /* Tell kernel about new page table root. */
-       return sys_vmctl(who->vm_endpoint, VMCTL_I386_SETCR3,
-               pt ? pt->pt_dir_phys : 0);
+       return sys_vmctl_set_addrspace(who->vm_endpoint,
+               pt ? pt->pt_dir_phys : 0,
+               pt ? pdes : 0);
 }
 
 /*===========================================================================*