]> Zhao Yanbai Git Server - minix.git/commitdiff
Give RS a page table.
authorCristiano Giuffrida <cristiano@minix3.org>
Mon, 28 Jun 2010 21:53:37 +0000 (21:53 +0000)
committerCristiano Giuffrida <cristiano@minix3.org>
Mon, 28 Jun 2010 21:53:37 +0000 (21:53 +0000)
16 files changed:
include/minix/com.h
include/minix/vm.h
kernel/kernel.h
kernel/system/do_safecopy.c
kernel/table.c
lib/libc/other/Makefile.inc
lib/libc/syscall/Makefile.inc
servers/rs/main.c
servers/rs/manager.c
servers/rs/table.c
servers/vm/exit.c
servers/vm/main.c
servers/vm/proto.h
servers/vm/region.c
servers/vm/rs.c
servers/vm/utility.c

index 4b3c1df34ee15ffd999af9b975c6d245d46781c4..b8efd12c1d29fce5877cd05da960ebdbc5b68a2e 100644 (file)
 #      define VM_RS_SRC_ENDPT          m1_i1
 #      define VM_RS_DST_ENDPT          m1_i2
 
+#define VM_RS_MEMCTL           (VM_RQ_BASE+42)
+#      define VM_RS_CTL_ENDPT          m1_i1
+#      define VM_RS_CTL_REQ            m1_i2
+#              define VM_RS_MEM_PIN    0       /* pin memory */
+
 /* Total. */
-#define NR_VM_CALLS                            42
+#define NR_VM_CALLS                            43
 #define VM_CALL_MASK_SIZE                      BITMAP_CHUNKS(NR_VM_CALLS)
 
 /* not handled as a normal VM call, thus at the end of the reserved rage */
index c37839ba58af596267da5dd78f3d641895e18cee..2a65ffa5c0dbf99ac3a2e4df1c3a0791675b6267 100644 (file)
@@ -23,9 +23,9 @@ _PROTOTYPE( void *vm_map_phys, (endpoint_t who, void *physaddr, size_t len));
 _PROTOTYPE( int vm_unmap_phys, (endpoint_t who, void *vaddr, size_t len));
 
 _PROTOTYPE( int vm_notify_sig, (endpoint_t ep, endpoint_t ipc_ep));
-_PROTOTYPE( int vm_ctl, (int what, int param));
 _PROTOTYPE( int vm_set_priv, (int procnr, void *buf));
 _PROTOTYPE( int vm_update, (endpoint_t src_e, endpoint_t dst_e));
+_PROTOTYPE( int vm_memctl, (endpoint_t ep, int req));
 _PROTOTYPE( int vm_query_exit, (int *endpt));
 _PROTOTYPE( int vm_forgetblock, (u64_t id));
 _PROTOTYPE( void vm_forgetblocks, (void));
index 6652a27c7a648db57ba35e81812e3925a551b7cc..968dbce7a8cdf109fad5580b751b87b0bcc50a79 100644 (file)
@@ -49,6 +49,7 @@
 #include "glo.h"               /* global variables */
 #include "ipc.h"               /* IPC constants */
 #include "profile.h"           /* system profiling */
+#include "perf.h"              /* performance-related definitions */
 #include "debug.h"             /* debugging, MUST be last kernel header */
 
 #endif /* __ASSEMBLY__ */
index 752bc1cc408ad052e01525b6c2d68060640f29de..0a55ef4b5649f780f7b4733d66d6fa6aaa7d5d92 100644 (file)
@@ -23,8 +23,6 @@
 
 #define MEM_TOP 0xFFFFFFFFUL
 
-#define USE_COW_SAFECOPY 0
-
 FORWARD _PROTOTYPE(int safecopy, (struct proc *, endpoint_t, endpoint_t,
                cp_grant_id_t, int, int, size_t, vir_bytes, vir_bytes, int));
 
@@ -240,7 +238,7 @@ int access;                 /* CPF_READ for a copy from granter to grantee, CPF_WRITE
        endpoint_t new_granter, *src, *dst;
        struct proc *granter_p;
        int r;
-#if USE_COW_SAFECOPY
+#if PERF_USE_COW_SAFECOPY
        vir_bytes size;
 #endif
 
@@ -290,7 +288,7 @@ int access;                 /* CPF_READ for a copy from granter to grantee, CPF_WRITE
        }
 
        /* Do the regular copy. */
-#if USE_COW_SAFECOPY
+#if PERF_USE_COW_SAFECOPY
        if(v_offset % CLICK_SIZE != addr % CLICK_SIZE || bytes < CLICK_SIZE) {
                /* Give up on COW immediately when offsets are not aligned
                 * or we are copying less than a page.
index f1d19e9ca453fb860d7f454f3c192e34caef1da0..708214dce98c27368e4df71fcb39b94d87359fa8 100644 (file)
 PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
 
 /* Define boot process flags. */
-#define BVM_F    (PROC_FULLVM)                    /* boot processes with VM */
+#define BVM_F   (PROC_FULLVM)                    /* boot processes with VM */
+#define OVM_F   (PERF_SYS_CORE_FULLVM ? PROC_FULLVM : 0) /* critical boot
+                                                           * processes with
+                                                           * optional VM.
+                                                           */
 
 /* The system image table lists all programs that are part of the boot image. 
  * The order of the entries here MUST agree with the order of the programs
@@ -74,9 +78,9 @@ PUBLIC struct boot_image image[] = {
 {DS_PROC_NR,   BVM_F, 50,      4, 0,     "ds"    },
 {RS_PROC_NR,       0, 50,      4, 0,     "rs"    },
 
-{PM_PROC_NR,       0,500,      4, 0,     "pm"    },
-{SCHED_PROC_NR,    0,500,      4, 0,     "sched" },
-{VFS_PROC_NR,      0,500,      5, 0,     "vfs"   },
+{PM_PROC_NR,   OVM_F,500,      4, 0,     "pm"    },
+{SCHED_PROC_NR,OVM_F,500,      4, 0,     "sched" },
+{VFS_PROC_NR,  OVM_F,500,      5, 0,     "vfs"   },
 {MEM_PROC_NR,  BVM_F, 50,      3, 0,     "memory"},
 {LOG_PROC_NR,  BVM_F, 50,      2, 0,     "log"   },
 {TTY_PROC_NR,  BVM_F, 50,      1, 0,     "tty"   },
index 835fc4244a01e25039b8964f5cd8981ca8d6783a..7f96f8ee47c66fab06634f540c3f3465b862fba3 100644 (file)
@@ -32,6 +32,7 @@ SRCS+=  \
        _svrctl.c \
        _sysuname.c \
        _vm_dmacalls.c \
+       _vm_memctl.c \
        _vm_set_priv.c \
        _vm_update.c \
        _vm_query_exit.c \
index 64a5ba6521e9bce9b0fc240ee2161c54c3bcbf36..f0d177fb0f6be274c8a04aa113681f38c499fb36 100644 (file)
@@ -73,6 +73,7 @@ SRCS+=  \
        munmap.S \
        vm_getphys.S \
        vm_getrefcount.S \
+       vm_memctl.S \
        vm_remap.S \
        vm_unmap.S \
        vm_set_priv.S \
index e862e6ffb6d94415e22d3fa005506deba570a618..27723f003f79060fffd60d71e5b125ea2e310324 100644 (file)
@@ -159,6 +159,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
   int s,i,j;
   int nr_image_srvs, nr_image_priv_srvs, nr_uncaught_init_srvs;
   struct rproc *rp;
+  struct rproc *replica_rp;
   struct rprocpub *rpub;
   struct boot_image image[NR_BOOT_PROCS];
   struct mproc mproc[NR_PROCS];
@@ -166,6 +167,9 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
   struct boot_image_priv *boot_image_priv;
   struct boot_image_sys *boot_image_sys;
   struct boot_image_dev *boot_image_dev;
+  message m;
+  int pid, replica_pid;
+  endpoint_t replica_endpoint;
 
   /* See if we run in verbose mode. */
   env_parse("rs_verbose", "d", 0, &rs_verbose, 0, 1);
@@ -293,23 +297,23 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
       /* Get heartbeat period. */
       rpub->period = boot_image_priv->period;
 
-      if(boot_image_priv->endpoint != RS_PROC_NR) {
-          /* Force a static priv id for system services in the boot image. */
-          rp->r_priv.s_id = static_priv_id(
-              _ENDPOINT_P(boot_image_priv->endpoint));
-
-          /* Initialize privilege bitmaps and signal manager. */
-          rp->r_priv.s_flags = boot_image_priv->flags;         /* priv flags */
-          rp->r_priv.s_trap_mask = boot_image_priv->trap_mask; /* traps */
-          memcpy(&rp->r_priv.s_ipc_to, &boot_image_priv->ipc_to,
-                            sizeof(rp->r_priv.s_ipc_to));      /* targets */
-          rp->r_priv.s_sig_mgr = boot_image_priv->sig_mgr;     /* sig mgr */
-
-          /* Initialize kernel call mask bitmap from unordered set. */
-          fill_call_mask(boot_image_priv->k_calls, NR_SYS_CALLS,
-              rp->r_priv.s_k_call_mask, KERNEL_CALL, TRUE);
+      /* Force a static priv id for system services in the boot image. */
+      rp->r_priv.s_id = static_priv_id(
+          _ENDPOINT_P(boot_image_priv->endpoint));
+      
+      /* Initialize privilege bitmaps and signal manager. */
+      rp->r_priv.s_flags = boot_image_priv->flags;         /* priv flags */
+      rp->r_priv.s_trap_mask = boot_image_priv->trap_mask; /* traps */
+      memcpy(&rp->r_priv.s_ipc_to, &boot_image_priv->ipc_to,
+                        sizeof(rp->r_priv.s_ipc_to));      /* targets */
+      rp->r_priv.s_sig_mgr = boot_image_priv->sig_mgr;     /* sig mgr */
+      
+      /* Initialize kernel call mask bitmap from unordered set. */
+      fill_call_mask(boot_image_priv->k_calls, NR_SYS_CALLS,
+          rp->r_priv.s_k_call_mask, KERNEL_CALL, TRUE);
 
           /* Set the privilege structure. */
+      if(boot_image_priv->endpoint != RS_PROC_NR) {
           if ((s = sys_privctl(ip->endpoint, SYS_PRIV_SET_SYS, &(rp->r_priv)))
               != OK) {
               panic("unable to set privilege structure: %d", s);
@@ -474,16 +478,75 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
   if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
       panic("couldn't set alarm: %d", s);
 
- /* Map out our own text and data. This is normally done in crtso.o
-  * but RS is an exception - we don't get to talk to VM so early on.
-  * That's why we override munmap() and munmap_text() in utility.c.
-  *
-  * _minix_unmapzero() is the same code in crtso.o that normally does
-  * it on startup. It's best that it's there as crtso.o knows exactly
-  * what the ranges are of the filler data.
-  */
-  unmap_ok = 1;
-  _minix_unmapzero();
+  /* Now create a new RS instance with a private page table and let the current
+   * instance live update into the replica. Clone RS' own slot first.
+   */
+  rp = rproc_ptr[_ENDPOINT_P(RS_PROC_NR)];
+  if((s = clone_slot(rp, &replica_rp)) != OK) {
+      panic("unable to clone current RS instance: %d", s);
+  }
+
+  /* Fork a new RS instance. */
+  pid = srv_fork();
+  if(pid == -1) {
+      panic("unable to fork a new RS instance");
+  }
+  replica_pid = pid ? pid : getpid();
+  replica_endpoint = getnprocnr(replica_pid);
+  replica_rp->r_pid = replica_pid;
+  replica_rp->r_pub->endpoint = replica_endpoint;
+
+  if(pid == 0) {
+      /* New RS instance running. */
+
+      /* Synchronize with the old instance. */
+      s = sef_receive(RS_PROC_NR, &m);
+      if(s != OK) {
+          panic("sef_receive failed: %d", s);
+      }
+
+      /* Live update the old instance into the new one. */
+      s = update_service(&rp, &replica_rp);
+      if(s != OK) {
+          panic("unable to live update RS: %d", s);
+      }
+      cpf_reload();
+
+      /* Clean up the old RS instance, the new instance will take over. */
+      cleanup_service(rp);
+
+      /* Map out our own text and data. */
+      unmap_ok = 1;
+      _minix_unmapzero();
+  }
+  else {
+      /* Old RS instance running. */
+
+      /* Ask VM to pin memory for the new RS instance. */
+      s = vm_memctl(replica_endpoint, VM_RS_MEM_PIN);
+      if(s != OK) {
+          panic("unable to pin memory for the new RS instance: %d", s);
+      }
+
+      /* Set up privileges for the new instance and let it run. */
+      set_sys_bit(replica_rp->r_priv.s_ipc_to, static_priv_id(RS_PROC_NR));
+      s = sys_privctl(replica_endpoint, SYS_PRIV_SET_SYS, &(replica_rp->r_priv));
+      if(s != OK) {
+          panic("unable to set privileges for the new RS instance: %d", s);
+      }
+      s = sys_privctl(replica_endpoint, SYS_PRIV_ALLOW, NULL);
+      if(s != OK) {
+          panic("unable to let the new RS instance run: %d", s);
+      }
+
+      /* Synchronize with the new instance and go to sleep. */
+      m.m_type = RS_INIT;
+      s = sendrec(replica_endpoint, &m);
+      if(s != OK) {
+          panic("sendrec failed: %d", s);
+      }
+      /* Not reachable */
+  }
 
   return(OK);
 }
index 423a1232de0373c600c9969192acb1a2779ca680..6aa0684c751fc49df3d8a83858bc52ededc48040 100644 (file)
@@ -1435,6 +1435,11 @@ struct rproc **clone_rpp;
   rpub = rp->r_pub;
   clone_rpub = clone_rp->r_pub;
 
+  /* Synch the privilege structure of the source with the kernel. */
+  if ((r = sys_getpriv(&(rp->r_priv), rpub->endpoint)) != OK) {
+      panic("unable to synch privilege structure: %d", r);
+  }
+
   /* Shallow copy. */
   *clone_rp = *rp;
   *clone_rpub = *rpub;
index 25f7dfa072f121d6924201ab60d7ea260ecd27b9..9a5650f34e0c649f0f137d9f4ea1f73ebaded318 100644 (file)
@@ -44,7 +44,8 @@ PRIVATE int
       VM_NOTIFY_SIG, SYS_NULL_C },
   sched_vmc[] ={ VM_BASIC_CALLS, SYS_NULL_C },
   vfs_vmc[] =  { VM_BASIC_CALLS, SYS_NULL_C },
-  rs_vmc[] =   { VM_BASIC_CALLS, VM_RS_SET_PRIV, VM_RS_UPDATE, SYS_NULL_C },
+  rs_vmc[] =   { VM_BASIC_CALLS, VM_RS_SET_PRIV, VM_RS_UPDATE, VM_RS_MEMCTL,
+      SYS_NULL_C },
   ds_vmc[] =   { VM_BASIC_CALLS, SYS_NULL_C },
   vm_vmc[] =   { SYS_NULL_C },
   tty_vmc[] =  { VM_BASIC_CALLS, SYS_NULL_C },
index 9afee36e47c14818cb7ffa6015b780d5be3a7880..43d0763f9a3df9bae268d20761a7ef6ce98ef6f7 100644 (file)
@@ -70,12 +70,17 @@ SANITYCHECK(SCL_FUNCTIONS);
 
        if(vmp->vm_flags & VMF_HAS_DMA) {
                release_dma(vmp);
-       } else {
-               assert(vmp->vm_flags & VMF_HASPT);
+       } else if(vmp->vm_flags & VMF_HASPT) {
                /* Free pagetable and pages allocated by pt code. */
 SANITYCHECK(SCL_DETAIL);
                free_proc(vmp);
 SANITYCHECK(SCL_DETAIL);
+       } else {
+                 /* Free the data and stack segments. */        
+                free_mem(vmp->vm_arch.vm_seg[D].mem_phys,       
+                        vmp->vm_arch.vm_seg[S].mem_vir +        
+                        vmp->vm_arch.vm_seg[S].mem_len -        
+                        vmp->vm_arch.vm_seg[D].mem_vir);        
        }
 SANITYCHECK(SCL_DETAIL);
 
index fd9490a8daa3bb9dcbde0c3c8421f2828c060cf0..03540a62a5b530bcbc8be77361dd9de1474116f9 100644 (file)
@@ -344,6 +344,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
        /* Calls from RS */
        CALLMAP(VM_RS_SET_PRIV, do_rs_set_priv);
        CALLMAP(VM_RS_UPDATE, do_rs_update);
+       CALLMAP(VM_RS_MEMCTL, do_rs_memctl);
 
        /* Generic calls. */
        CALLMAP(VM_REMAP, do_remap);
index fb20c424dd08f4ae8f035438beef1968e9b58470..0c52d35103a5e9452777bce3edcc77a0592c1b2e 100644 (file)
@@ -141,6 +141,7 @@ _PROTOTYPE(int map_proc_copy,(struct vmproc *dst, struct vmproc *src));
 _PROTOTYPE(struct vir_region *map_lookup,(struct vmproc *vmp, vir_bytes addr));
 _PROTOTYPE(int map_pf,(struct vmproc *vmp,
        struct vir_region *region, vir_bytes offset, int write));
+_PROTOTYPE(int map_pin_memory,(struct vmproc *vmp));
 _PROTOTYPE(int map_handle_memory,(struct vmproc *vmp,
        struct vir_region *region, vir_bytes offset, vir_bytes len, int write));
 _PROTOTYPE(void map_printmap, (struct vmproc *vmp));
@@ -185,6 +186,7 @@ _PROTOTYPE( vir_bytes arch_addrok, (struct vmproc *vmp, vir_bytes addr));
 /* rs.c */
 _PROTOTYPE(int do_rs_set_priv, (message *m));
 _PROTOTYPE(int do_rs_update, (message *m));
+_PROTOTYPE(int do_rs_memctl, (message *m));
 
 /* queryexit.c */
 _PROTOTYPE(int do_query_exit, (message *m));
index c9299d9224db9ae4dfbb8cf56183d270055d8b27..f6594c84d606283f800da5fc9f40482fd2970357 100644 (file)
@@ -1116,6 +1116,34 @@ int write;
        return r;
 }
 
+/*===========================================================================*
+ *                             map_pin_memory                               *
+ *===========================================================================*/
+PUBLIC int map_pin_memory(struct vmproc *vmp)
+{
+       struct vir_region *vr;
+       int offset, r;
+
+       /* Scan all memory regions. */
+       for(vr = vmp->vm_regions; vr; vr = vr->next) {
+               vir_bytes offset;
+               /* Skip regions that can't pagefault. */
+               if((vr->flags & VR_NOPF) || (vr->flags & VR_SHARED)) {
+                   continue;
+               }
+               /* Map other regions. */
+               for(offset=0;offset<vr->length;offset += VM_PAGE_SIZE) {
+                       if((r=map_pf(vmp, vr, offset, 1 /* write */))
+                               != OK) {
+                               printf("VM: map_pf failed\n");
+                               return r;
+                       }
+               }
+       }
+
+       return OK;
+}
+
 /*===========================================================================*
  *                             map_handle_memory                            *
  *===========================================================================*/
index dcda8c98b174f3f90e847361981ebbb8451e930a..45e85e6440b08b643f41af990196b872da898ca5 100644 (file)
@@ -38,7 +38,7 @@ PUBLIC int do_rs_set_priv(message *m)
        nr = m->VM_RS_NR;
 
        if ((r = vm_isokendpt(nr, &n)) != OK) {
-               printf("do_rs_set_priv: message from strange source %d\n", nr);
+               printf("do_rs_set_priv: bad endpoint %d\n", nr);
                return EINVAL;
        }
 
@@ -60,7 +60,7 @@ PUBLIC int do_rs_set_priv(message *m)
  *===========================================================================*/
 PUBLIC int do_rs_update(message *m_ptr)
 {
-       endpoint_t src_e, dst_e;
+       endpoint_t src_e, dst_e, reply_e;
        int r;
 
        src_e = m_ptr->VM_RS_SRC_ENDPT;
@@ -74,7 +74,52 @@ PUBLIC int do_rs_update(message *m_ptr)
 
        /* Do the update in VM now. */
        r = swap_proc(src_e, dst_e);
+       if(r != OK) {
+               return r;
+       }
+
+       /* Reply, update-aware. */
+       reply_e = m_ptr->m_source;
+       if(reply_e == src_e) reply_e = dst_e;
+       if(reply_e == dst_e) reply_e = src_e;
+       m_ptr->m_type = OK;
+       r = send(reply_e, m_ptr);
+       if(r != OK) {
+               panic("send() error");
+       }
 
-       return r;
+       return SUSPEND;
+}
+
+/*===========================================================================*
+ *                             do_rs_memctl                                 *
+ *===========================================================================*/
+PUBLIC int do_rs_memctl(message *m_ptr)
+{
+       endpoint_t ep;
+       int req, r, proc_nr;
+       struct vmproc *vmp;
+
+       ep = m_ptr->VM_RS_CTL_ENDPT;
+       req = m_ptr->VM_RS_CTL_REQ;
+
+       /* Lookup endpoint. */
+       if ((r = vm_isokendpt(ep, &proc_nr)) != OK) {
+               printf("do_rs_memctl: bad endpoint %d\n", ep);
+               return EINVAL;
+       }
+       vmp = &vmproc[proc_nr];
+
+       /* Process request. */
+       switch(req)
+       {
+       case VM_RS_MEM_PIN:
+               r = map_pin_memory(vmp);
+               return r;
+
+       default:
+               printf("do_rs_memctl: bad request %d\n", req);
+               return EINVAL;
+       }
 }
 
index 40147f6385dc4b2a8bcc37e227e90c2533e712bf..54c13708396e92dd5f213a32a8dbd90550290495 100644 (file)
@@ -286,10 +286,10 @@ PUBLIC int swap_proc(endpoint_t src_e, endpoint_t dst_e)
        }
 
        /* Adjust page tables. */
-       assert(src_vmp->vm_flags & VMF_HASPT);
-       assert(dst_vmp->vm_flags & VMF_HASPT);
-       pt_bind(&src_vmp->vm_pt, src_vmp);
-       pt_bind(&dst_vmp->vm_pt, dst_vmp);
+       if(src_vmp->vm_flags & VMF_HASPT)
+               pt_bind(&src_vmp->vm_pt, src_vmp);
+       if(dst_vmp->vm_flags & VMF_HASPT)
+               pt_bind(&dst_vmp->vm_pt, dst_vmp);
        if((r=sys_vmctl(SELF, VMCTL_FLUSHTLB, 0)) != OK) {
                panic("swap_proc: VMCTL_FLUSHTLB failed: %d", r);
        }