]> Zhao Yanbai Git Server - minix.git/commitdiff
Rewrite of boot process
authorCristiano Giuffrida <cristiano@minix3.org>
Fri, 11 Dec 2009 00:08:19 +0000 (00:08 +0000)
committerCristiano Giuffrida <cristiano@minix3.org>
Fri, 11 Dec 2009 00:08:19 +0000 (00:08 +0000)
KERNEL CHANGES:
- The kernel only knows about privileges of kernel tasks and the root system
process (now RS).
- Kernel tasks and the root system process are the only processes that are made
schedulable by the kernel at startup. All the other processes in the boot image
don't get their privileges set at startup and are inhibited from running by the
RTS_NO_PRIV flag.
- Removed the assumption on the ordering of processes in the boot image table.
System processes can now appear in any order in the boot image table.
- Privilege ids can now be assigned both statically or dynamically. The kernel
assigns static privilege ids to kernel tasks and the root system process. Each
id is directly derived from the process number.
- User processes now all share the static privilege id of the root user
process (now INIT).
- sys_privctl split: we have more calls now to let RS set privileges for system
processes. SYS_PRIV_ALLOW / SYS_PRIV_DISALLOW are only used to flip the
RTS_NO_PRIV flag and allow / disallow a process from running. SYS_PRIV_SET_SYS /
SYS_PRIV_SET_USER are used to set privileges for a system / user process.
- boot image table flags split: PROC_FULLVM is the only flag that has been
moved out of the privilege flags and is still maintained in the boot image
table. All the other privilege flags are out of the kernel now.

RS CHANGES:
- RS is the only user-space process who gets to run right after in-kernel
startup.
- RS uses the boot image table from the kernel and three additional boot image
info table (priv table, sys table, dev table) to complete the initialization
of the system.
- RS checks that the entries in the priv table match the entries in the boot
image table to make sure that every process in the boot image gets schedulable.
- RS only uses static privilege ids to set privileges for system services in
the boot image.
- RS includes basic memory management support to allocate the boot image buffer
dynamically during initialization. The buffer shall contain the executable
image of all the system services we would like to restart after a crash.
- First step towards decoupling between resource provisioning and resource
requirements in RS: RS must know what resources it needs to restart a process
and what resources it has currently available. This is useful to tradeoff
reliability and resource consumption. When required resources are missing, the
process cannot be restarted. In that case, in the future, a system flag will
tell RS what to do. For example, if CORE_PROC is set, RS should trigger a
system-wide panic because the system can no longer function correctly without
a core system process.

PM CHANGES:
- The process tree built at initialization time is changed to have INIT as root
with pid 0, RS child of INIT and all the system services children of RS. This
is required to make RS in control of all the system services.
- PM no longer registers labels for system services in the boot image. This is
now part of RS's initialization process.

33 files changed:
commands/ps/ps.c
include/minix/com.h
include/minix/const.h
include/minix/syslib.h
kernel/const.h
kernel/main.c
kernel/priv.h
kernel/proc.c
kernel/proc.h
kernel/system.c
kernel/system/do_getinfo.c
kernel/system/do_privctl.c
kernel/table.c
kernel/type.h
lib/syslib/sys_times.c
servers/init/init.c
servers/is/dmp_kernel.c
servers/is/dmp_rs.c
servers/pm/const.h
servers/pm/forkexit.c
servers/pm/main.c
servers/pm/time.c
servers/rs/Makefile
servers/rs/const.h [new file with mode: 0644]
servers/rs/glo.h [new file with mode: 0644]
servers/rs/inc.h
servers/rs/main.c
servers/rs/manager.c
servers/rs/memory.c [new file with mode: 0644]
servers/rs/proto.h
servers/rs/table.c [new file with mode: 0644]
servers/rs/type.h [new file with mode: 0644]
servers/rs/utility.c [new file with mode: 0644]

index 03d637a77bfd8dfaab1319df3d6a7955a4b88a67..08efe8a5077d01526a89b3865f6419047713d91b 100644 (file)
@@ -84,6 +84,7 @@
 #include "../../kernel/proc.h"
 
 #include "../../servers/pm/mproc.h"
+#include "../../servers/pm/const.h"
 #include "../../servers/vfs/fproc.h"
 #include "../../servers/vfs/const.h"
 #include "../../servers/mfs/const.h"
@@ -518,12 +519,18 @@ int endpoints;
        if(endpoints) bufp->ps_pid = ps_proc[p_ki].p_endpoint;
        else bufp->ps_pid = ps_mproc[p_nr].mp_pid;
        bufp->ps_ppid = ps_mproc[ps_mproc[p_nr].mp_parent].mp_pid;
+       /* Assume no parent when the parent and the child share the same pid.
+        * This is what PM currently assumes.
+        */
+       if(bufp->ps_ppid == bufp->ps_pid) {
+           bufp->ps_ppid = NO_PID;
+       }
        bufp->ps_pgrp = ps_mproc[p_nr].mp_procgrp;
        bufp->ps_mflags = ps_mproc[p_nr].mp_flags;
   } else {
        if(endpoints) bufp->ps_pid = ps_proc[p_ki].p_endpoint;
-       else bufp->ps_pid = 0;
-       bufp->ps_ppid = 0;
+       else bufp->ps_pid = NO_PID;
+       bufp->ps_ppid = NO_PID;
        bufp->ps_ruid = bufp->ps_euid = 0;
        bufp->ps_pgrp = 0;
        bufp->ps_mflags = 0;
index 0b95b687aac6412ff044fd6466b591a4d7f65db4..82f573fe488b714c294aab435cd31dc95e291ba2 100644 (file)
 #define VM_PROC_NR        8     /* memory server */
 #define INIT_PROC_NR     9     /* init -- goes multiuser */
 
+/* Root system process and root user process. */
+#define ROOT_SYS_PROC_NR  RS_PROC_NR
+#define ROOT_USR_PROC_NR  INIT_PROC_NR
+
 /* Number of processes contained in the system image. */
 #define NR_BOOT_PROCS  (NR_TASKS + INIT_PROC_NR + 1)
 
 #define SYS_ALL_CALLS (NR_SYS_CALLS)
 
 /* Subfunctions for SYS_PRIVCTL */
-#define SYS_PRIV_INIT          1       /* Initialize a privilege structure */
-#define SYS_PRIV_ADD_IO                2       /* Add I/O range (struct io_range) */
-#define SYS_PRIV_ADD_MEM       3       /* Add memory range (struct mem_range)
-                                        */
-#define SYS_PRIV_ADD_IRQ       4       /* Add IRQ */
-#define SYS_PRIV_USER          5       /* Make a process an oridinary user 
-                                        * process.
+#define SYS_PRIV_ALLOW         1       /* Allow process to run */
+#define SYS_PRIV_DISALLOW      2       /* Disallow process to run */
+#define SYS_PRIV_SET_SYS       3       /* Set a system privilege structure */
+#define SYS_PRIV_SET_USER      4       /* Set a user privilege structure */
+#define SYS_PRIV_ADD_IO        5       /* Add I/O range (struct io_range) */
+#define SYS_PRIV_ADD_MEM       6       /* Add memory range (struct mem_range)
                                         */
-#define SYS_PRIV_QUERY_MEM     6       /* Verify memory privilege. */
+#define SYS_PRIV_ADD_IRQ       7       /* Add IRQ */
+#define SYS_PRIV_QUERY_MEM     8       /* Verify memory privilege. */
 
 /* Subfunctions for SYS_SETGRANT */
 #define SYS_PARAM_SET_GRANT    1       /* Set address and size of grant table */
 #   define GET_BIOSBUFFER 14   /* get a buffer for BIOS calls */
 #   define GET_LOADINFO   15   /* get load average information */
 #   define GET_IRQACTIDS  16   /* get the IRQ masks */
-#   define GET_PRIVID    17    /* get ID of privilege structure */
+#   define GET_PRIV      17    /* get privilege structure */
 #   define GET_HZ        18    /* get HZ value */
 #   define GET_WHOAMI    19    /* get own name and endpoint */
 #   define GET_RANDOMNESS_BIN 20 /* get one randomness bin */
 #   define GET_IDLETSC   21    /* get cumulative idle time stamp counter */
+#   define GET_AOUTHEADER     22 /* get a.out headers from the boot image */
 #define I_ENDPT      m7_i4     /* calling process */
 #define I_VAL_PTR      m7_p1   /* virtual address at caller */ 
 #define I_VAL_LEN      m7_i1   /* max length of value */
index e4ec34f18fb6a86c6cf7cf5f02f6d52da58cabb0..010ad7df79c420d4d23b4854f2f30e1f0abe0d3d 100644 (file)
 #define SERVARNAME             "cttyline"
 
 /* Bits for the system property flags in boot image processes. */
+#define PROC_FULLVM    0x100    /* VM sets and manages full pagetable */
+
+/* Bits for s_flags in the privilege structure. */
 #define PREEMPTIBLE     0x02    /* kernel tasks are not preemptible */
 #define BILLABLE        0x04    /* some processes are not billable */
+#define DYN_PRIV_ID     0x08    /* privilege id assigned dynamically */
  
 #define SYS_PROC        0x10    /* system processes have own priv structure */
 #define CHECK_IO_PORT   0x20    /* check if I/O request is allowed */
 #define CHECK_IRQ       0x40    /* check if IRQ can be used */
 #define CHECK_MEM       0x80    /* check if (VM) mem map request is allowed */
-#define PROC_FULLVM    0x100    /* VM sets and manages full pagetable */
-
index 02c03bed52c2515682f19867d9356c6549f78c90..60f8587da24218ae2588bea0d7c72fc1592d4bb8 100644 (file)
@@ -101,7 +101,7 @@ _PROTOTYPE(void *alloc_contig, (size_t len, int flags, phys_bytes *phys));
  * retrieve/set a process-virtual timer.
  */
 _PROTOTYPE( int sys_times, (endpoint_t proc_ep, clock_t *user_time,
-       clock_t *sys_time, clock_t *uptime));
+       clock_t *sys_time, clock_t *uptime, time_t *boottime));
 _PROTOTYPE(int sys_setalarm, (clock_t exp_time, int abs_time));
 _PROTOTYPE( int sys_vtimer, (endpoint_t proc_nr, int which, clock_t *newval,
        clock_t *oldval));
@@ -178,8 +178,9 @@ _PROTOTYPE(int sys_segctl, (int *index, u16_t *seg, vir_bytes *off,
 #define sys_getmonparams(v,vl) sys_getinfo(GET_MONPARAMS, v,vl, 0,0)
 #define sys_getschedinfo(v1,v2)        sys_getinfo(GET_SCHEDINFO, v1,0, v2,0)
 #define sys_getlocktimings(dst)        sys_getinfo(GET_LOCKTIMING, dst, 0,0,0)
-#define sys_getprivid(nr)      sys_getinfo(GET_PRIVID, 0, 0,0, nr)
+#define sys_getpriv(dst, nr)   sys_getinfo(GET_PRIV, dst, 0,0, nr)
 #define sys_getidletsc(dst)    sys_getinfo(GET_IDLETSC, dst, 0,0,0)
+#define sys_getaoutheader(dst,nr) sys_getinfo(GET_AOUTHEADER, dst, 0,0,nr)
 _PROTOTYPE(int sys_getinfo, (int request, void *val_ptr, int val_len,
                                 void *val_ptr2, int val_len2)          );
 _PROTOTYPE(int sys_whoami, (endpoint_t *ep, char *name, int namelen));
index 9f41136f10d8a2d6b30b24e3da0dfad9bf119670..771291241f9d9d5ce4c390abbb6261c24de8ae8a 100644 (file)
@@ -8,9 +8,6 @@
 #include "config.h"
 #include "debug.h"
 
-/* Map a process number to a privilege structure id. */
-#define s_nr_to_id(n)  (NR_TASKS + (n) + 1)
-
 /* Translate a pointer to a field in a structure to a pointer to the structure
  * itself. So it translates '&struct_ptr->field' back to 'struct_ptr'.
  */
index 30c040585e4d76cf9bee0c4373bd020cb358414b..94df0738061a69d3afad1041ba95cf682f2a7dbb 100644 (file)
@@ -73,7 +73,8 @@ PUBLIC void main()
   ktsb = (reg_t) t_stack;
 
   for (i=0; i < NR_BOOT_PROCS; ++i) {
-       int ci;
+       int schedulable_proc, proc_nr;
+       int ipc_to_m, kcalls;
        bitchunk_t fv;
 
        ip = &image[i];                         /* process' attributes */
@@ -84,35 +85,57 @@ PUBLIC void main()
        rp->p_quantum_size = ip->quantum;       /* quantum size in ticks */
        rp->p_ticks_left = ip->quantum;         /* current credit */
        strncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set process name */
-       (void) get_priv(rp, (ip->flags & SYS_PROC));    /* assign structure */
-       priv(rp)->s_flags = ip->flags;                  /* process flags */
-       priv(rp)->s_trap_mask = ip->trap_mask;          /* allowed traps */
 
-       /* Warn about violations of the boot image table order consistency. */
-       if (priv_id(rp) != s_nr_to_id(ip->proc_nr) && (ip->flags & SYS_PROC))
-               kprintf("Warning: boot image table has wrong process order\n");
-
-       /* Initialize call mask bitmap from unordered set.
-        * A single SYS_ALL_CALLS is a special case - it
-        * means all calls are allowed.
+       /* See if this process is immediately schedulable.
+        * In that case, set its privileges now and allow it to run.
+        * Only kernel tasks and the root system process get to run immediately.
+        * All the other system processes are inhibited from running by the
+        * RTS_NO_PRIV flag. They can only be scheduled once the root system
+        * process has set their privileges.
         */
-       if(ip->nr_k_calls == 1 && ip->k_calls[0] == SYS_ALL_CALLS)
-               fv = ~0;                /* fill call mask */
-       else
-               fv = 0;                 /* clear call mask */
-
-       for(ci = 0; ci < CALL_MASK_SIZE; ci++)  /* fill or clear call mask */
-               priv(rp)->s_k_call_mask[ci] = fv;
-       if(!fv)                 /* not all full? enter calls bit by bit */
-               for(ci = 0; ci < ip->nr_k_calls; ci++)
-                       SET_BIT(priv(rp)->s_k_call_mask,
-                               ip->k_calls[ci]-KERNEL_CALL);
-
-       for (j = 0; j < NR_SYS_PROCS && j < BITCHUNK_BITS; j++)
-               if (ip->ipc_to & (1 << j))
-                       set_sendto_bit(rp, j);  /* restrict targets */
-
-       if (iskerneln(proc_nr(rp))) {           /* part of the kernel? */ 
+       proc_nr = proc_nr(rp);
+       schedulable_proc = (iskerneln(proc_nr) || isrootsysn(proc_nr));
+       if(schedulable_proc) {
+           /* Assign privilege structure. Force a static privilege id. */
+            (void) get_priv(rp, static_priv_id(proc_nr));
+
+            /* Priviliges for kernel tasks. */
+            if(iskerneln(proc_nr)) {
+                /* Privilege flags. */
+                priv(rp)->s_flags = (proc_nr == IDLE ? IDL_F : TSK_F);
+                /* Allowed traps. */
+                priv(rp)->s_trap_mask = (proc_nr == CLOCK 
+                    || proc_nr == SYSTEM  ? CSK_T : TSK_T);
+                ipc_to_m = TSK_M;                  /* allowed targets */
+                kcalls = TSK_KC;                   /* allowed kernel calls */
+            }
+            /* Priviliges for the root system process. */
+            else if(isrootsysn(proc_nr)) {
+                priv(rp)->s_flags= RSYS_F;         /* privilege flags */
+                priv(rp)->s_trap_mask= RSYS_T;     /* allowed traps */
+                ipc_to_m = RSYS_M;                 /* allowed targets */
+                kcalls = RSYS_KC;                  /* allowed kernel calls */
+            }
+
+            /* Fill in target mask. */
+            for (j=0; j < NR_SYS_PROCS; j++) {
+                if (ipc_to_m & (1 << j))
+                    set_sendto_bit(rp, j);
+                else
+                    unset_sendto_bit(rp, j);
+           }
+
+            /* Fill in kernel call mask. */
+            for(j = 0; j < CALL_MASK_SIZE; j++) {
+                priv(rp)->s_k_call_mask[j] = (kcalls == NO_C ? 0 : (~0));
+            }
+       }
+       else {
+           /* Don't let the process run for now. */
+            RTS_SET(rp, RTS_NO_PRIV);
+       }
+
+       if (iskerneln(proc_nr)) {               /* part of the kernel? */ 
                if (ip->stksize > 0) {          /* HARDWARE stack size is 0 */
                        rp->p_priv->s_stack_guard = (reg_t *) ktsb;
                        *rp->p_priv->s_stack_guard = STACK_GUARD;
@@ -121,7 +144,7 @@ PUBLIC void main()
                rp->p_reg.sp = ktsb;    /* this task's initial stack ptr */
                hdrindex = 0;           /* all use the first a.out header */
        } else {
-               hdrindex = 1 + i-NR_TASKS;      /* servers, drivers, INIT */
+               hdrindex = 1 + i-NR_TASKS;      /* system/user processes */
        }
 
        /* Architecture-specific way to find out aout header of this
@@ -153,12 +176,12 @@ PUBLIC void main()
         * access I/O; this is not allowed to less-privileged processes 
         */
        rp->p_reg.pc = (reg_t) ip->initial_pc;
-       rp->p_reg.psw = (iskernelp(rp)) ? INIT_TASK_PSW : INIT_PSW;
+       rp->p_reg.psw = (iskerneln(proc_nr)) ? INIT_TASK_PSW : INIT_PSW;
 
        /* Initialize the server stack pointer. Take it down one word
         * to give crtso.s something to use as "argc".
         */
-       if (isusern(proc_nr(rp))) {             /* user-space process? */ 
+       if (isusern(proc_nr)) {         /* user-space process? */ 
                rp->p_reg.sp = (rp->p_memmap[S].mem_vir +
                                rp->p_memmap[S].mem_len) << CLICK_SHIFT;
                rp->p_reg.sp -= sizeof(reg_t);
@@ -171,9 +194,9 @@ PUBLIC void main()
         * PT up and manage it. VM will signal the kernel when it has
         * done this; until then, don't let it run.
         */
-       if(priv(rp)->s_flags & PROC_FULLVM)
+       if(ip->flags & PROC_FULLVM)
                RTS_SET(rp, RTS_VMINHIBIT);
-       
+
        /* Set ready. The HARDWARE task is never ready. */
        if (rp->p_nr == HARDWARE) RTS_SET(rp, RTS_PROC_STOP);
        /* IDLE task is never put on a run queue as it is never ready to run */
index 6775be7fb82adb0acf5e5299ce3da3398eebb974..39a397aaa6d5a024185888c2c6a49eaf5ba1558f 100644 (file)
@@ -9,7 +9,8 @@
  * between common and privileged process fields and is very space efficient. 
  *
  * Changes:
- *   Jul 01, 2005      Created.  (Jorrit N. Herder)    
+ *   Nov 22, 2009  rewrite of privilege management (Cristiano Giuffrida)
+ *   Jul 01, 2005  Created.  (Jorrit N. Herder)        
  */
 #include <minix/com.h>
 #include "const.h"
@@ -65,9 +66,18 @@ struct priv {
 /* Guard word for task stacks. */
 #define STACK_GUARD    ((reg_t) (sizeof(reg_t) == 2 ? 0xBEEF : 0xDEADBEEF))
 
+/* Static privilege id definitions. */
+#define NR_STATIC_PRIV_IDS         NR_BOOT_PROCS
+#define is_static_priv_id(id)     (id >= 0 && id < NR_STATIC_PRIV_IDS)
+#define static_priv_id(n)          (NR_TASKS + (n))
+
 /* Magic system structure table addresses. */
-#define BEG_PRIV_ADDR (&priv[0])
-#define END_PRIV_ADDR (&priv[NR_SYS_PROCS])
+#define BEG_PRIV_ADDR              (&priv[0])
+#define END_PRIV_ADDR              (&priv[NR_SYS_PROCS])
+#define BEG_STATIC_PRIV_ADDR       BEG_PRIV_ADDR
+#define END_STATIC_PRIV_ADDR       (BEG_STATIC_PRIV_ADDR + NR_STATIC_PRIV_IDS)
+#define BEG_DYN_PRIV_ADDR          END_STATIC_PRIV_ADDR
+#define END_DYN_PRIV_ADDR          END_PRIV_ADDR
 
 #define priv_addr(i)      (ppriv_addr)[(i)]
 #define priv_id(rp)      ((rp)->p_priv->s_id)
@@ -78,6 +88,10 @@ struct priv {
 
 #define may_send_to(rp, nr) (get_sys_bit(priv(rp)->s_ipc_to, nr_to_id(nr)))
 
+/* Privilege management shorthands. */
+#define spi_to(n)          (1 << (static_priv_id(n)))
+#define unset_usr_to(m)    ((m) & ~(1 << USER_PRIV_ID))
+
 /* The system structures table and pointers to individual table slots. The 
  * pointers allow faster access because now a process entry can be found by 
  * indexing the psys_addr array, while accessing an element i requires a 
@@ -86,10 +100,14 @@ struct priv {
 EXTERN struct priv priv[NR_SYS_PROCS];         /* system properties table */
 EXTERN struct priv *ppriv_addr[NR_SYS_PROCS];  /* direct slot pointers */
 
-/* Unprivileged user processes all share the same privilege structure.
+/* Unprivileged user processes all share the privilege structure of the
+ * root user process.
  * This id must be fixed because it is used to check send mask entries.
  */
-#define USER_PRIV_ID   0
+#define USER_PRIV_ID   static_priv_id(ROOT_USR_PROC_NR)
+/* Specifies a null privilege id.
+ */
+#define NULL_PRIV_ID   -1
 
 /* Make sure the system can boot. The following sanity check verifies that
  * the system privileges table is large enough for the number of processes
@@ -99,4 +117,37 @@ EXTERN struct priv *ppriv_addr[NR_SYS_PROCS];       /* direct slot pointers */
 #error NR_SYS_PROCS must be larger than NR_BOOT_PROCS
 #endif
 
+/*
+ * Privileges masks used by the kernel.
+ */
+#define IDL_F     (SYS_PROC | BILLABLE) /* idle task is not preemptible as we
+                                         * don't want it to interfere with the
+                                         * timer tick interrupt handler code.
+                                         * Unlike other processes idle task is
+                                         * handled in a special way and is
+                                         * preempted always if timer tick occurs
+                                         * and there is another runnable process
+                                         */
+#define TSK_F     (SYS_PROC)                            /* other kernel tasks */
+#define RSYS_F    (SYS_PROC | PREEMPTIBLE)              /* root system proc */
+#define DEF_SYS_F (RSYS_F | DYN_PRIV_ID)                /* default sys proc */
+
+/* allowed traps */
+#define CSK_T     (1 << RECEIVE)                        /* clock and system */
+#define TSK_T     0                                     /* other kernel tasks */
+#define RSYS_T    (~0)                                  /* root system proc */
+#define DEF_SYS_T RSYS_T                                /* default sys proc */
+
+/* allowed targets */
+#define TSK_M     0                                     /* all kernel tasks */
+#define RSYS_M    (~0)                                  /* root system proc */
+#define DEF_SYS_M unset_usr_to(RSYS_M)                  /* default sys proc */
+
+/* allowed kernel calls */
+#define NO_C 0              /* no calls allowed */
+#define ALL_C 1             /* all calls allowed */
+#define TSK_KC     NO_C                                 /* all kernel tasks */
+#define RSYS_KC    ALL_C                                /* root system proc */
+#define DEF_SYS_KC RSYS_KC                              /* default sys proc */
+
 #endif /* PRIV_H */
index c39470937a74053d078abf4cf9c536ac4e51ae03..f693525d60e13f28667504e5812afe22386415f9 100644 (file)
@@ -824,7 +824,7 @@ endpoint_t dst_e;                   /* which process to notify */
   } 
 
   /* Destination is not ready to receive the notification. Add it to the 
-   * bit map with pending notifications. Note the indirectness: the system id 
+   * bit map with pending notifications. Note the indirectness: the privilege id
    * instead of the process number is used in the pending bit map.
    */ 
   src_id = priv(caller_ptr)->s_id;
index 4606b571772d35d908b27ac52d2e95d3afd43b33..092edbe06ae4198f438531f3262a9514170541cb 100644 (file)
@@ -250,6 +250,8 @@ struct proc {
 #define iskerneln(n)     ((n) < 0)
 #define isuserp(p)        isusern((p) >= BEG_USER_ADDR)
 #define isusern(n)        ((n) >= 0)
+#define isrootsysp(p)    isrootsysn((p)->p_nr)
+#define isrootsysn(n)    ((n) == ROOT_SYS_PROC_NR)
 
 #ifndef __ASSEMBLY__
 
index b949ac2db32878e3690077c4491e8187fe1dce14..e4d72d17d5a085f39ca565f52abc19ee5ae24ce6 100644 (file)
@@ -22,6 +22,7 @@
  *   clear_endpoint:   remove a process' ability to send and receive messages
  *
  * Changes:
+*    Nov 22, 2009   get_priv supports static priv ids (Cristiano Giuffrida)
  *   Aug 04, 2005   check if system call is allowed  (Jorrit N. Herder)
  *   Jul 20, 2005   send signal to services with message  (Jorrit N. Herder) 
  *   Jan 15, 2005   new, generalized virtual copy function  (Jorrit N. Herder)
@@ -238,32 +239,36 @@ PRIVATE void initialize(void)
 /*===========================================================================*
  *                             get_priv                                     *
  *===========================================================================*/
-PUBLIC int get_priv(rc, proc_type)
+PUBLIC int get_priv(rc, priv_id)
 register struct proc *rc;              /* new (child) process pointer */
-int proc_type;                         /* system or user process flag */
+int priv_id;                           /* privilege id */
 {
-/* Get a privilege structure. All user processes share the same privilege 
- * structure. System processes get their own privilege structure. 
+/* Allocate a new privilege structure for a system process. Privilege ids
+ * can be assigned either statically or dynamically.
  */
-  register struct priv *sp;                    /* privilege structure */
-
-  if (proc_type == SYS_PROC) {                 /* find a new slot */
-      for (sp = BEG_PRIV_ADDR; sp < END_PRIV_ADDR; ++sp) 
-          if (sp->s_proc_nr == NONE && sp->s_id != USER_PRIV_ID) break;        
-      if (sp >= END_PRIV_ADDR) return(ENOSPC);
-      rc->p_priv = sp;                         /* assign new slot */
-      rc->p_priv->s_proc_nr = proc_nr(rc);     /* set association */
-      rc->p_priv->s_flags = SYS_PROC;          /* mark as privileged */
-
-      /* Clear some fields */
-      sp->s_asyntab= -1;       
-      sp->s_asynsize= 0;
-  } else {
-      rc->p_priv = &priv[USER_PRIV_ID];                /* use shared slot */
-      rc->p_priv->s_proc_nr = INIT_PROC_NR;    /* set association */
+  register struct priv *sp;                 /* privilege structure */
 
-      /* s_flags of this shared structure are to be once at system startup. */
+  if(priv_id == NULL_PRIV_ID) {             /* allocate slot dynamically */
+      for (sp = BEG_DYN_PRIV_ADDR; sp < END_DYN_PRIV_ADDR; ++sp) 
+          if (sp->s_proc_nr == NONE) break;    
+      if (sp >= END_DYN_PRIV_ADDR) return(ENOSPC);
+  }
+  else {                                    /* allocate slot from id */
+      if(!is_static_priv_id(priv_id)) {
+          return EINVAL;                    /* invalid static priv id */
+      }
+      if(priv[priv_id].s_proc_nr != NONE) {
+          return EBUSY;                     /* slot already in use */
+      }
+      sp = &priv[priv_id];
   }
+  rc->p_priv = sp;                         /* assign new slot */
+  rc->p_priv->s_proc_nr = proc_nr(rc);     /* set association */
+  
+  /* Clear some fields */
+  sp->s_asyntab= -1;
+  sp->s_asynsize= 0;
+
   return(OK);
 }
 
@@ -275,22 +280,24 @@ PUBLIC void set_sendto_bit(struct proc *rp, int id)
 /* Allow a process to send messages to the process(es) associated with the
  * system privilege structure with the given ID. 
  */
-  struct proc *rrp;                    /* receiver process */
 
-  /* Disallow the process from sending to a system privilege structure with no
+  /* Disallow the process from sending to a process privilege structure with no
    * associated process, and disallow the process from sending to itself.
    */
-  if (id_to_nr(id) == NONE || priv_id(rp) == id)
+  if (id_to_nr(id) == NONE || priv_id(rp) == id) {
+       unset_sys_bit(priv(rp)->s_ipc_to, id);
        return;
+  }
 
   set_sys_bit(priv(rp)->s_ipc_to, id);
 
-  /* The process that this process can now send to, must be able to reply.
-   * Therefore, its send mask should be updated as well.
+  /* The process that this process can now send to, must be able to reply (or
+   * vice versa). Therefore, its send mask should be updated as well. Ignore
+   * receivers that don't support traps other than RECEIVE, they can't reply
+   * or send messages anyway.
    */
-  rrp = proc_addr(id_to_nr(id));
-  if (!iskernelp(rrp))
-       set_sys_bit(priv(rrp)->s_ipc_to, priv_id(rp));
+  if (priv_addr(id)->s_trap_mask & ~((1 << RECEIVE)))
+      set_sys_bit(priv_addr(id)->s_ipc_to, priv_id(rp));
 }
 
 /*===========================================================================*
index 22cbcbe5c75d14934a3bb7e449fbc18597c2e4a0..f7568c71ed041893ff269dd9122e713917c74c2a 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <string.h>
+#include <minix/endpoint.h>
 
 #include "../system.h"
 #include "../vm.h"
@@ -31,6 +32,7 @@ register message *m_ptr;      /* pointer to request message */
   int proc_nr, nr_e, nr, r;
   struct proc *caller;
   int wipe_rnd_bin = -1;
+  struct exec e_hdr;
 
   caller = proc_addr(who_p);
 
@@ -84,6 +86,14 @@ register message *m_ptr;     /* pointer to request message */
         src_vir = (vir_bytes) proc_addr(nr);
         break;
     }
+    case GET_PRIV: {
+        nr_e = (m_ptr->I_VAL_LEN2_E == SELF) ?
+            who_e : m_ptr->I_VAL_LEN2_E;
+        if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
+        length = sizeof(struct priv);
+        src_vir = (vir_bytes) priv_addr(nr_to_id(nr));
+        break;
+    }
     case GET_WHOAMI: {
        int len;
        /* GET_WHOAMI uses m3 and only uses the message contents for info. */
@@ -146,11 +156,6 @@ register message *m_ptr;   /* pointer to request message */
         src_vir = (vir_bytes) irq_actids;
         break;
     }
-    case GET_PRIVID: {
-       if (!isokendpt(m_ptr->I_VAL_LEN2_E, &proc_nr)) 
-               return EINVAL;
-       return proc_addr(proc_nr)->p_priv->s_id;
-    }
     case GET_IDLETSC: {
 #ifdef CONFIG_IDLE_TSC
         length = sizeof(idle_tsc);
@@ -161,6 +166,22 @@ register message *m_ptr;   /* pointer to request message */
         return(EINVAL);
 #endif
     }
+    case GET_AOUTHEADER: {
+        int hdrindex, index = m_ptr->I_VAL_LEN2_E;
+        if(index < 0 || index >= NR_BOOT_PROCS) {
+            return EINVAL;
+        }
+        if (iskerneln(_ENDPOINT_P(image[index].endpoint))) { 
+            hdrindex = 0;
+        } else {
+            hdrindex = 1 + index-NR_TASKS;
+        }
+        arch_get_aout_headers(hdrindex, &e_hdr);
+        length = sizeof(e_hdr);
+        src_vir = (vir_bytes) &e_hdr;
+        break;
+    }
+
     default:
        kprintf("do_getinfo: invalid request %d\n", m_ptr->I_REQUEST);
         return(EINVAL);
index befcb043d642ec8c159cc1c93039e14f6a7f988b..d32ade0dcbbf83602ca150368241d86bb3b2ec64 100644 (file)
@@ -14,8 +14,6 @@
 
 #if USE_PRIVCTL
 
-#define FILLED_MASK    (~0)
-
 /*===========================================================================*
  *                             do_privctl                                   *
  *===========================================================================*/
@@ -29,6 +27,7 @@ message *m_ptr;                       /* pointer to request message */
   register struct proc *rp;
   int proc_nr;
   int priv_id;
+  int ipc_to_m, kcalls;
   int i, r;
   struct io_range io_range;
   struct mem_range mem_range;
@@ -48,16 +47,49 @@ message *m_ptr;                     /* pointer to request message */
 
   switch(m_ptr->CTL_REQUEST)
   {
-  case SYS_PRIV_INIT:
+  case SYS_PRIV_ALLOW:
+       /* Allow process to run. Make sure its privilege structure has already
+        * been set.
+        */
+       if (!RTS_ISSET(rp, RTS_NO_PRIV) || priv(rp)->s_proc_nr == NONE) {
+               return(EPERM);
+       }
+       RTS_LOCK_UNSET(rp, RTS_NO_PRIV);
+       return(OK);
+
+  case SYS_PRIV_DISALLOW:
+       /* Disallow process from running. */
+       if (RTS_ISSET(rp, RTS_NO_PRIV)) return(EPERM);
+       RTS_LOCK_SET(rp, RTS_NO_PRIV);
+       return(OK);
+
+  case SYS_PRIV_SET_SYS:
+       /* Set a privilege structure of a blocked system process. */
        if (! RTS_ISSET(rp, RTS_NO_PRIV)) return(EPERM);
 
+       /* Check whether a static or dynamic privilege id must be allocated. */
+       priv_id = NULL_PRIV_ID;
+       if (m_ptr->CTL_ARG_PTR)
+       {
+               /* Copy privilege structure from caller */
+               if((r=data_copy(who_e, (vir_bytes) m_ptr->CTL_ARG_PTR,
+                       SYSTEM, (vir_bytes) &priv, sizeof(priv))) != OK)
+                       return r;
+
+               /* See if the caller wants to assign a static privilege id. */
+               if(!(priv.s_flags & DYN_PRIV_ID)) {
+                       priv_id = priv.s_id;
+               }
+       }
+
        /* Make sure this process has its own privileges structure. This may
         * fail, since there are only a limited number of system processes.
-        * Then copy the privileges from the caller and restore some defaults.
+        * Then copy privileges from the caller and restore some defaults.
         */
-       if ((i=get_priv(rp, SYS_PROC)) != OK)
+       if ((i=get_priv(rp, priv_id)) != OK)
        {
-               kprintf("do_privctl: out of priv structures\n");
+               kprintf("do_privctl: unable to allocate priv_id %d: %d\n",
+                       priv_id, i);
                return(i);
        }
        priv_id = priv(rp)->s_id;               /* backup privilege id */
@@ -70,88 +102,109 @@ message *m_ptr;                   /* pointer to request message */
        priv(rp)->s_int_pending = 0;                    /* - interrupts */
        sigemptyset(&priv(rp)->s_sig_pending);          /* - signals */
 
-       /* Now update the process' privileges as requested. */
-       rp->p_priv->s_trap_mask = FILLED_MASK;
-
-       /* Set a default send mask. */
-       for (i=0; i < NR_SYS_PROCS; i++) {
-               if (i != USER_PRIV_ID)
-                       set_sendto_bit(rp, i);
-               else
-                       unset_sendto_bit(rp, i);
+       /* Set defaults for privilege bitmaps. */
+       priv(rp)->s_flags= DEF_SYS_F;           /* privilege flags */
+       priv(rp)->s_trap_mask= DEF_SYS_T;       /* allowed traps */
+       ipc_to_m = DEF_SYS_M;                   /* allowed targets */
+       kcalls = DEF_SYS_KC;                    /* allowed kernel calls */
+       for(i = 0; i < CALL_MASK_SIZE; i++) {
+               priv(rp)->s_k_call_mask[i] = (kcalls == NO_C ? 0 : (~0));
        }
 
-       /* No I/O resources, no memory resources, no IRQs, no grant table */
+       /* Set defaults for resources: no I/O resources, no memory resources,
+        * no IRQs, no grant table
+        */
        priv(rp)->s_nr_io_range= 0;
        priv(rp)->s_nr_mem_range= 0;
        priv(rp)->s_nr_irq= 0;
        priv(rp)->s_grant_table= 0;
        priv(rp)->s_grant_entries= 0;
 
+       /* Override defaults if the caller has supplied a privilege structure. */
        if (m_ptr->CTL_ARG_PTR)
        {
-               /* Copy privilege structure from caller */
-               if((r=data_copy(who_e, (vir_bytes) m_ptr->CTL_ARG_PTR,
-                       SYSTEM, (vir_bytes) &priv, sizeof(priv))) != OK)
-                       return r;
-
-               /* Copy the call mask */
-               for (i= 0; i<CALL_MASK_SIZE; i++)
-                       priv(rp)->s_k_call_mask[i]= priv.s_k_call_mask[i];
+               /* Copy s_flags. */
+               priv(rp)->s_flags = priv.s_flags;
 
                /* Copy IRQs */
-               if (priv.s_nr_irq < 0 || priv.s_nr_irq > NR_IRQ)
-                       return EINVAL;
-               priv(rp)->s_nr_irq= priv.s_nr_irq;
-               for (i= 0; i<priv.s_nr_irq; i++)
-               {
-                       priv(rp)->s_irq_tab[i]= priv.s_irq_tab[i];
+               if(priv.s_flags & CHECK_IRQ) {
+                       if (priv.s_nr_irq < 0 || priv.s_nr_irq > NR_IRQ)
+                               return EINVAL;
+                       priv(rp)->s_nr_irq= priv.s_nr_irq;
+                       for (i= 0; i<priv.s_nr_irq; i++)
+                       {
+                               priv(rp)->s_irq_tab[i]= priv.s_irq_tab[i];
 #if 0
-                       kprintf("do_privctl: adding IRQ %d for %d\n",
-                               priv(rp)->s_irq_tab[i], rp->p_endpoint);
+                               kprintf("do_privctl: adding IRQ %d for %d\n",
+                                       priv(rp)->s_irq_tab[i], rp->p_endpoint);
 #endif
+                       }
                }
 
-               priv(rp)->s_flags |= CHECK_IRQ; /* Check requests for IRQs */
-
                /* Copy I/O ranges */
-               if (priv.s_nr_io_range < 0 || priv.s_nr_io_range > NR_IO_RANGE)
-                       return EINVAL;
-               priv(rp)->s_nr_io_range= priv.s_nr_io_range;
-               for (i= 0; i<priv.s_nr_io_range; i++)
-               {
-                       priv(rp)->s_io_tab[i]= priv.s_io_tab[i];
+               if(priv.s_flags & CHECK_IO_PORT) {
+                       if (priv.s_nr_io_range < 0 || priv.s_nr_io_range > NR_IO_RANGE)
+                               return EINVAL;
+                       priv(rp)->s_nr_io_range= priv.s_nr_io_range;
+                       for (i= 0; i<priv.s_nr_io_range; i++)
+                       {
+                               priv(rp)->s_io_tab[i]= priv.s_io_tab[i];
+#if 0
+                               kprintf("do_privctl: adding I/O range [%x..%x] for %d\n",
+                                       priv(rp)->s_io_tab[i].ior_base,
+                                       priv(rp)->s_io_tab[i].ior_limit,
+                                       rp->p_endpoint);
+#endif
+                       }
+               }
+
+               /* Copy memory ranges */
+               if(priv.s_flags & CHECK_MEM) {
+                       if (priv.s_nr_mem_range < 0 || priv.s_nr_mem_range > NR_MEM_RANGE)
+                               return EINVAL;
+                       priv(rp)->s_nr_mem_range= priv.s_nr_mem_range;
+                       for (i= 0; i<priv.s_nr_mem_range; i++)
+                       {
+                               priv(rp)->s_mem_tab[i]= priv.s_mem_tab[i];
 #if 0
-                       kprintf("do_privctl: adding I/O range [%x..%x] for %d\n",
-                               priv(rp)->s_io_tab[i].ior_base,
-                               priv(rp)->s_io_tab[i].ior_limit,
-                               rp->p_endpoint);
+                               kprintf("do_privctl: adding mem range [%x..%x] for %d\n",
+                                       priv(rp)->s_mem_tab[i].mr_base,
+                                       priv(rp)->s_mem_tab[i].mr_limit,
+                                       rp->p_endpoint);
 #endif
+                       }
                }
 
-               /* Check requests for IRQs */
-               priv(rp)->s_flags |= CHECK_IO_PORT;
+               /* Copy trap mask. */
+               priv(rp)->s_trap_mask = priv.s_trap_mask;
+
+               /* Copy target mask. */
+               memcpy(&ipc_to_m, &priv.s_ipc_to, sizeof(ipc_to_m));
 
+               /* Copy kernel call mask. */
                memcpy(priv(rp)->s_k_call_mask, priv.s_k_call_mask,
                        sizeof(priv(rp)->s_k_call_mask));
+       }
 
-               /* Set a custom send mask. */
-               for (i=0; i < NR_SYS_PROCS; i++) {
-                       if (get_sys_bit(priv.s_ipc_to, i))
-                               set_sendto_bit(rp, i);
-                       else
-                               unset_sendto_bit(rp, i);
-               }
+       /* Fill in target mask. */
+       for (i=0; i < NR_SYS_PROCS; i++) {
+               if (ipc_to_m & (1 << i))
+                       set_sendto_bit(rp, i);
+               else
+                       unset_sendto_bit(rp, i);
        }
 
-       /* Done. Privileges have been set. Allow process to run again. */
-       RTS_LOCK_UNSET(rp, RTS_NO_PRIV);
        return(OK);
-  case SYS_PRIV_USER:
-       /* Make this process an ordinary user process. */
+
+  case SYS_PRIV_SET_USER:
+       /* Set a privilege structure of a blocked user process. */
        if (!RTS_ISSET(rp, RTS_NO_PRIV)) return(EPERM);
-       if ((i=get_priv(rp, 0)) != OK) return(i);
-       RTS_LOCK_UNSET(rp, RTS_NO_PRIV);
+
+       /* Link the process to the privilege structure of the root user
+        * process all the user processes share.
+        */
+       priv(rp) = priv_addr(USER_PRIV_ID);
+
        return(OK);
 
   case SYS_PRIV_ADD_IO:
index 7d068f5217395fb292457ffef63dbbf27c4bfa47..d4d830e419c2fef39d774e3477e2a5885a220ceb 100644 (file)
@@ -22,6 +22,7 @@
  * include 'boot_image' (this file) and 'idt' and 'gdt' (protect.c). 
  *
  * Changes:
+ *    Nov 22, 2009   rewrite of privilege management (Cristiano Giuffrida)
  *    Aug 02, 2005   set privileges and minimal boot image (Jorrit N. Herder)
  *    Oct 17, 2004   updated above and tasktab comments  (Jorrit N. Herder)
  *    May 01, 2004   changed struct for system image  (Jorrit N. Herder)
 /* Stack space for all the task stacks.  Declared as (char *) to align it. */
 #define        TOT_STACK_SPACE (IDL_S + HRD_S + (2 * TSK_S))
 PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
-       
-/* Define flags for the various process types. */
-#define IDL_F  (SYS_PROC | BILLABLE)   /* idle task is not preemptible as we
-                                        * don't want it to interfere with the
-                                        * timer tick interrupt handler code.
-                                        * Unlike other processes idle task is
-                                        * handled in a special way and is
-                                        * preempted always if timer tick occurs
-                                        * and there is another runnable process
-                                        */
-#define TSK_F  (SYS_PROC)                              /* kernel tasks */
-#define SRV_F  (SYS_PROC | PREEMPTIBLE)                /* system services */
-#define VM_F   (SYS_PROC)                              /* vm  */
-#define USR_F  (BILLABLE | PREEMPTIBLE | PROC_FULLVM)  /* user processes */
-#define SVM_F  (SRV_F | PROC_FULLVM)                   /* servers with VM */
 
-/* Define system call traps for the various process types. These call masks
- * determine what system call traps a process is allowed to make.
- */
-#define TSK_T  (1 << RECEIVE)                  /* clock and system */
-#define SRV_T  (~0)                            /* system services */
-#define USR_T   ((1 << SENDREC))               /* user processes */
-
-/* Send masks determine to whom processes can send messages or notifications. 
- * The values here are used for the processes in the boot image. We rely on 
- * the boot image table itself to match the order of the process numbers, so
- * that the send mask that is defined here can be interpreted properly.
- * Privilege structure 0 is shared by user processes. 
- */
-#define s(n)   (1 << (s_nr_to_id(n)))
-#define SRV_M  (~0)
-#define SYS_M  (~0)
-#define USR_M (s(PM_PROC_NR) | s(FS_PROC_NR) | s(RS_PROC_NR) | s(VM_PROC_NR))
-#define DRV_M (USR_M | s(SYSTEM) | s(DS_PROC_NR) | s(LOG_PROC_NR) | s(TTY_PROC_NR))
-
-/* Define kernel calls that processes are allowed to make. This is not looking
- * very nice, but we need to define the access rights on a per call basis. 
- * Note that the reincarnation server has all bits on, because it should
- * be allowed to distribute rights to services that it starts. 
- * 
- * Calls are unordered lists, converted by the kernel to bitmasks
- * once at runtime.
- */
-#define FS_C SYS_KILL, SYS_VIRCOPY, SYS_SAFECOPYFROM, SYS_SAFECOPYTO, \
-    SYS_VIRVCOPY, SYS_UMAP, SYS_GETINFO, SYS_EXIT, SYS_TIMES, SYS_SETALARM, \
-    SYS_PRIVCTL, SYS_TRACE , SYS_SETGRANT, SYS_PROFBUF, SYS_SYSCTL
-#define DRV_C  FS_C, SYS_SEGCTL, SYS_IRQCTL, SYS_INT86, SYS_DEVIO, \
-       SYS_SDEVIO, SYS_VDEVIO, SYS_SETGRANT, SYS_PROFBUF, SYS_SYSCTL
-
-PRIVATE int
-  fs_c[] = { FS_C },
-  pm_c[] = { SYS_ALL_CALLS },
-  rs_c[] = { SYS_ALL_CALLS },
-  ds_c[] = { SYS_ALL_CALLS },
-  vm_c[] = { SYS_ALL_CALLS },
-  drv_c[] = { DRV_C },
-  usr_c[] = { SYS_SYSCTL },
-  tty_c[] = { DRV_C, SYS_PHYSCOPY, SYS_ABORT, SYS_IOPENABLE,
-               SYS_READBIOS },
-  mem_c[] = { DRV_C, SYS_PHYSCOPY, SYS_PHYSVCOPY, SYS_IOPENABLE };
+/* Define boot process flags. */
+#define BVM_F    (PROC_FULLVM)                    /* boot processes with 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
- * in the boot image and all kernel tasks must come first. Furthermore, the
- * order of the entries MUST agree with their process numbers. See above.
+ * in the boot image and all kernel tasks must come first.
  *
  * Each entry provides the process number, flags, quantum size, scheduling
- * queue, allowed traps, ipc mask, and a name for the process table. The 
- * initial program counter and stack size is also provided for kernel tasks.
+ * queue, and a name for the process table. The initial program counter and
+ * stack size is also provided for kernel tasks.
  *
  * Note: the quantum size must be positive in all cases! 
  */
-#define c(calls) calls, (sizeof(calls) / sizeof((calls)[0]))
-#define no_c { 0 }, 0
 
 PUBLIC struct boot_image image[] = {
-/* process nr, pc,flags, qs,  queue, stack, traps, ipcto, call,  name */ 
-{IDLE,       NULL,IDL_F,  0,      0, IDL_S,     0,     0, no_c,"idle"  },
-{CLOCK,clock_task,TSK_F,  8, TASK_Q, TSK_S, TSK_T,     0, no_c,"clock" },
-{SYSTEM, sys_task,TSK_F,  8, TASK_Q, TSK_S, TSK_T,     0, no_c,"system"},
-{HARDWARE,      0,TSK_F,  8, TASK_Q, HRD_S,     0,     0, no_c,"kernel"},
-{PM_PROC_NR,    0,SRV_F, 32,      4, 0,     SRV_T, SRV_M, c(pm_c),"pm"    },
-{FS_PROC_NR,    0,SRV_F, 32,      5, 0,     SRV_T, SRV_M, c(fs_c),"vfs"   },
-{RS_PROC_NR,    0,SVM_F,  4,      4, 0,     SRV_T, SYS_M, c(rs_c),"rs"    },
-{MEM_PROC_NR,   0,SVM_F,  4,      3, 0,     SRV_T, SYS_M,c(mem_c),"memory"},
-{LOG_PROC_NR,   0,SRV_F,  4,      2, 0,     SRV_T, SYS_M,c(drv_c),"log"   },
-{TTY_PROC_NR,   0,SVM_F,  4,      1, 0,     SRV_T, SYS_M,c(tty_c),"tty"   },
-{DS_PROC_NR,    0,SVM_F,  4,      4, 0,     SRV_T, SYS_M, c(ds_c),"ds"    },
-{MFS_PROC_NR,   0,SVM_F, 32,      5, 0,     SRV_T, SRV_M, c(fs_c),"mfs"   },
-{VM_PROC_NR,    0,VM_F, 32,      2, 0,     SRV_T, SRV_M, c(vm_c),"vm"    },
-{INIT_PROC_NR,  0,USR_F,  8, USER_Q, 0,     USR_T, USR_M, c(usr_c),"init"  },
+/* process nr, pc, flags, qs,  queue, stack,   name */ 
+{IDLE,       NULL,     0,  0,      0, IDL_S, "idle"  },
+{CLOCK,clock_task,     0,  8, TASK_Q, TSK_S, "clock" },
+{SYSTEM, sys_task,     0,  8, TASK_Q, TSK_S, "system"},
+{HARDWARE,      0,     0,  8, TASK_Q, HRD_S, "kernel"},
+{PM_PROC_NR,    0,     0, 32,      4, 0,     "pm"    },
+{FS_PROC_NR,    0,     0, 32,      5, 0,     "vfs"   },
+{RS_PROC_NR,    0,     0,  4,      4, 0,     "rs"    },
+{MEM_PROC_NR,   0, BVM_F,  4,      3, 0,     "memory"},
+{LOG_PROC_NR,   0, BVM_F,  4,      2, 0,     "log"   },
+{TTY_PROC_NR,   0, BVM_F,  4,      1, 0,     "tty"   },
+{DS_PROC_NR,    0, BVM_F,  4,      4, 0,     "ds"    },
+{MFS_PROC_NR,   0, BVM_F, 32,      5, 0,     "mfs"   },
+{VM_PROC_NR,    0,     0, 32,      2, 0,     "vm"    },
+{INIT_PROC_NR,  0, BVM_F,  8, USER_Q, 0,     "init"  },
 };
 
 /* Verify the size of the system image table at compile time. Also verify that 
index f09939737704b37ef98ce8d7af43237b51ecec4b..d9e80519b3edde8bf06ab00dc16fcd889d626a9a 100644 (file)
@@ -20,10 +20,6 @@ struct boot_image {
   unsigned char quantum;               /* quantum (tick count) */
   int priority;                                /* scheduling priority */
   int stksize;                         /* stack size for tasks */
-  short trap_mask;                     /* allowed system call traps */
-  bitchunk_t ipc_to;                   /* send mask protection */
-  int *k_calls;                                /* kern. call protection */
-  int nr_k_calls;
   char proc_name[P_NAME_LEN];          /* name in process table */
   endpoint_t endpoint;                 /* endpoint number when started */
 };
index 5615c017035865a55abe635fb5f72c2f64dc0112..68982489f90cdb1193939d2d08960ad3d90e8e58 100644 (file)
@@ -1,12 +1,13 @@
 #include "syslib.h"
 
-PUBLIC int sys_times(proc_ep, user_time, sys_time, uptime)
+PUBLIC int sys_times(proc_ep, user_time, sys_time, uptime, boottime)
 endpoint_t proc_ep;            /* proc_ep whose times are needed */
 clock_t *user_time;            /* time spend in the process itself */
 clock_t *sys_time;             /* time spend in system on behalf of the
                                 * process
                                 */
 clock_t *uptime;               /* time the system is running */
+time_t *boottime;              /* boot time */
 {
 /* Fetch the accounting info for a proc_ep. */
   message m;
@@ -17,5 +18,6 @@ clock_t *uptime;              /* time the system is running */
   if (user_time) *user_time = m.T_USER_TIME;
   if (sys_time) *sys_time = m.T_SYSTEM_TIME;
   if (uptime) *uptime = m.T_BOOT_TICKS;
+  if (boottime) *boottime = m.T_BOOTTIME;
   return(r);
 }
index 5fd15fd3e40398fa472f3f7b4b9d65c141d62cec..05c8236c3e64527fd93de404b016a1ee37eb4443 100644 (file)
@@ -69,6 +69,7 @@ int main(void)
   int fd;                      /* generally useful */
   int linenr;                  /* loop variable */
   int check;                   /* check if a new process must be spawned */
+  int sn;                      /* signal number */
   struct slotent *slotp;       /* slots[] pointer */
   struct ttyent *ttyp;         /* ttytab entry */
   struct sigaction sa;
@@ -85,6 +86,12 @@ int main(void)
   sigemptyset(&sa.sa_mask);
   sa.sa_flags = 0;
 
+  /* Default: Ignore every signal (except those that follow). */
+  sa.sa_handler = SIG_IGN;
+  for (sn = 1; sn < _NSIG; sn++) {
+      sigaction(sn, &sa, NULL);
+  }
+
   /* Hangup: Reexamine /etc/ttytab for newly enabled terminal lines. */
   sa.sa_handler = onhup;
   sigaction(SIGHUP, &sa, NULL);
index 9f335d0f5ce06abf68f2f0b0b01a30adf9218dce..8c0ea2b53d3e0462aa72f79c41cbbb458f03f9f1 100644 (file)
@@ -45,6 +45,7 @@ FORWARD _PROTOTYPE( char *proc_name, (int proc_nr)            );
 FORWARD _PROTOTYPE( char *s_traps_str, (int flags)             );
 FORWARD _PROTOTYPE( char *s_flags_str, (int flags)             );
 FORWARD _PROTOTYPE( char *p_rts_flags_str, (int flags)         );
+FORWARD _PROTOTYPE( char *boot_flags_str, (int flags)          );
 
 /* Some global data that is shared among several dumping procedures. 
  * Note that the process table copy has the same name as in the kernel
@@ -195,6 +196,18 @@ PUBLIC void irqtab_dmp()
   printf("\n");
 }
 
+/*===========================================================================*
+ *                           boot_flags_str                                 *
+ *===========================================================================*/
+PRIVATE char *boot_flags_str(int flags)
+{
+       static char str[10];
+       str[0] = (flags & PROC_FULLVM)        ? 'V' : '-';
+       str[1] = '\0';
+
+       return str;
+}
+
 /*===========================================================================*
  *                             image_dmp                                    *
  *===========================================================================*/
@@ -202,25 +215,18 @@ PUBLIC void image_dmp()
 {
   int m, i,j,r;
   struct boot_image *ip;
-  static char ipc_to[BITCHUNK_BITS*2];
        
   if ((r = sys_getimage(image)) != OK) {
       report("IS","warning: couldn't get copy of image table", r);
       return;
   }
   printf("Image table dump showing all processes included in system image.\n");
-  printf("---name-- -nr- -flags- -traps- -sq- ----pc- -stack- -ipc_to[0]--------\n");
+  printf("---name- -nr- ----pc- flags -qs- -queue- -stack-\n");
   for (m=0; m<NR_BOOT_PROCS; m++) { 
       ip = &image[m];
-        for (i=j=0; i < BITCHUNK_BITS; i++, j++) {
-                   ipc_to[j] = (ip->ipc_to & (1<<i)) ? '1' : '0';
-                   if (i % 8 == 7) ipc_to[++j] = ' ';
-               }
-        ipc_to[j] = '\0';
-      printf("%8s %4d   %s   %s  %3d %7lu %7lu   %s\n",
-          ip->proc_name, ip->proc_nr, 
-              s_flags_str(ip->flags), s_traps_str(ip->trap_mask), 
-       ip->priority, (long)ip->initial_pc, ip->stksize, ipc_to); 
+      printf("%8s %4d %7lu %5s %4d %7d %7lu\n",
+          ip->proc_name, ip->proc_nr, (long)ip->initial_pc,
+          boot_flags_str(ip->flags), ip->quantum, ip->priority, ip->stksize); 
   }
   printf("\n");
 }
@@ -267,19 +273,27 @@ PUBLIC void kenv_dmp()
     printf("\n");
 }
 
+/*===========================================================================*
+ *                           s_flags_str                                    *
+ *===========================================================================*/
 PRIVATE char *s_flags_str(int flags)
 {
        static char str[10];
-       str[0] = (flags & PREEMPTIBLE) ? 'P' : '-';
-       str[1] = '-';
-       str[2] = (flags & BILLABLE)    ? 'B' : '-';
-       str[3] = (flags & SYS_PROC)    ? 'S' : '-';
-       str[4] = '-';
-       str[5] = '\0';
+       str[0] = (flags & PREEMPTIBLE)        ? 'P' : '-';
+       str[1] = (flags & BILLABLE)           ? 'B' : '-';
+       str[2] = (flags & DYN_PRIV_ID)        ? 'D' : '-';
+       str[3] = (flags & SYS_PROC)           ? 'S' : '-';
+       str[4] = (flags & CHECK_IO_PORT)      ? 'I' : '-';
+       str[5] = (flags & CHECK_IRQ)          ? 'Q' : '-';
+       str[6] = (flags & CHECK_MEM)          ? 'M' : '-';
+       str[7] = '\0';
 
        return str;
 }
 
+/*===========================================================================*
+ *                           s_traps_str                                    *
+ *===========================================================================*/
 PRIVATE char *s_traps_str(int flags)
 {
        static char str[10];
@@ -313,7 +327,7 @@ PUBLIC void privileges_dmp()
       return;
   }
 
-  printf("\n--nr-id-name---- -flags- -traps- grants -ipc_to-- -system calls--\n");
+  printf("-nr- -id- -name-- -flags-    traps  grants -ipc_to--  -kernel calls-\n");
 
   PROCLOOP(rp, oldrp)
         r = -1;
@@ -322,7 +336,7 @@ PUBLIC void privileges_dmp()
         if (r == -1 && !isemptyp(rp)) {
            sp = &priv[USER_PRIV_ID];
         }
-       printf("(%02u) %-7.7s %s   %s %7d",
+       printf("(%02u) %-7.7s %s    %s %7d",
               sp->s_id, rp->p_name,
               s_flags_str(sp->s_flags), s_traps_str(sp->s_trap_mask),
                sp->s_grant_entries);
@@ -339,6 +353,9 @@ PUBLIC void privileges_dmp()
   }
 }
 
+/*===========================================================================*
+ *                            p_rts_flags_str                               *
+ *===========================================================================*/
 PRIVATE char *p_rts_flags_str(int flags)
 {
        static char str[10];
index c3f738954c663f490d2cdc35f322dc228f871766..da7b7cfba8e27e40cb914a76f9eb312eabe79386 100644 (file)
@@ -11,7 +11,8 @@
 #include <timers.h>
 #include <minix/rs.h>
 #include "../../kernel/priv.h"
-#include "../rs/manager.h"
+#include "../rs/const.h"
+#include "../rs/type.h"
 
 PUBLIC struct rproc rproc[NR_SYS_PROCS];
 
@@ -29,19 +30,15 @@ PUBLIC void rproc_dmp()
   getsysinfo(RS_PROC_NR, SI_PROC_TAB, rproc);
 
   printf("Reincarnation Server (RS) system process table dump\n");
-  printf("-endpoint-flag--dev- -T---checked----alive-starts-backoff-label command-\n");
+  printf("----label---- endpoint- -pid- flags -dev- -T- alive_tm starts command\n");
   for (i=prev_i; i<NR_SYS_PROCS; i++) {
        rp = &rproc[i];
        if (! rp->r_flags & RS_IN_USE) continue;
        if (++n > 22) break;
-       printf("%9d %s %3d/%2d %3u %8u %8u %4dx %3d %s %s",
-               rp->r_proc_nr_e,
-               s_flags_str(rp->r_flags),
-               rp->r_dev_nr, rp->r_dev_style,
-               rp->r_period, 
-               rp->r_check_tm, rp->r_alive_tm,
-               rp->r_restarts, rp->r_backoff,
-               rp->r_label,
+       printf("%13s %9d %5d %5s %3d/%1d %3u %8u %5dx %s",
+               rp->r_label, rp->r_proc_nr_e, rp->r_pid,
+               s_flags_str(rp->r_flags), rp->r_dev_nr, rp->r_dev_style,
+               rp->r_period, rp->r_alive_tm, rp->r_restarts,
                rp->r_cmd
        );
        printf("\n");
@@ -54,11 +51,13 @@ PUBLIC void rproc_dmp()
 
 PRIVATE char *s_flags_str(int flags)
 {
-       static char str[5];
-       str[0] = (flags & RS_IN_USE)     ? 'U' : '-';
-       str[1] = (flags & RS_EXITING)    ? 'E' : '-';
-       str[2] = '-';
-       str[3] = '\0';
+       static char str[10];
+       str[0] = (flags & RS_IN_USE)        ? 'U' : '-';
+       str[1] = (flags & RS_EXITING)       ? 'E' : '-';
+       str[2] = (flags & RS_REFRESHING)    ? 'R' : '-';
+       str[3] = (flags & RS_NOPINGREPLY)   ? 'N' : '-';
+       str[4] = '-';
+       str[5] = '\0';
 
        return(str);
 }
index 2fa9bdad1b33d98ffa64e6f02cb6c8bc4a3f3ccd..9ed5790484fb51b75faf0e590bef792dd5a415c0 100644 (file)
@@ -5,7 +5,7 @@
                                 * a 'short' instead of pid_t.)
                                 */
 
-#define PM_PID            0    /* PM's process id number */
+#define NO_PID            0    /* pid value indicating no process */
 #define INIT_PID          1    /* INIT's process id number */
 
 #define NO_TRACER         0    /* process is not being traced */
index bc57d80efe52aaee32a2ff075134f09c1ff344b2..72b3d91a1ac18ad6ba1e3b20993dbf7815a65a51 100644 (file)
@@ -260,7 +260,7 @@ int dump_core;                      /* flag indicating whether to dump core */
   if (rmp->mp_flags & ALARM_ON) set_alarm(rmp, (clock_t) 0);
 
   /* Do accounting: fetch usage times and accumulate at parent. */
-  if((r=sys_times(proc_nr_e, &user_time, &sys_time, NULL)) != OK)
+  if((r=sys_times(proc_nr_e, &user_time, &sys_time, NULL, NULL)) != OK)
        panic(__FILE__,"exit_proc: sys_times failed", r);
 
   p_mp = &mproc[rmp->mp_parent];                       /* process' parent */
index 6c317082ddc2df68bc189fb63c8f51b9892a0318..4d18b0ca7437da1c73541d6882a8ea6b8adefce5 100644 (file)
@@ -226,8 +226,6 @@ extern int unmap_ok;
  *===========================================================================*/
 PRIVATE void pm_init()
 {
-       int failed = 0;
-       int f = 0;
 /* Initialize the process manager. 
  * Memory use info is collected from the boot monitor, the kernel, and
  * all processes compiled into the system image. Initially this information
@@ -288,19 +286,28 @@ PRIVATE void pm_init()
                /* Set process details found in the image table. */
                rmp = &mproc[ip->proc_nr];      
                strncpy(rmp->mp_name, ip->proc_name, PROC_NAME_LEN); 
-#if 0
-               rmp->mp_parent = RS_PROC_NR;
-#endif
                rmp->mp_nice = get_nice_value(ip->priority);
                sigemptyset(&rmp->mp_sig2mess);
                sigemptyset(&rmp->mp_ignore);   
                sigemptyset(&rmp->mp_sigmask);
                sigemptyset(&rmp->mp_catch);
                if (ip->proc_nr == INIT_PROC_NR) {      /* user process */
+                       /* INIT is root, we make it father of itself. This is
+                        * not really OK, INIT should have no father, i.e.
+                        * a father with pid NO_PID. But PM currently assumes 
+                        * that mp_parent always points to a valid slot number.
+                        */
+                       rmp->mp_parent = INIT_PROC_NR;
                        rmp->mp_procgrp = rmp->mp_pid = INIT_PID;
                        rmp->mp_flags |= IN_USE; 
                }
                else {                                  /* system process */
+                       if(ip->proc_nr == RS_PROC_NR) {
+                               rmp->mp_parent = INIT_PROC_NR;
+                       }
+                       else {
+                               rmp->mp_parent = RS_PROC_NR;
+                       }
                        rmp->mp_pid = get_free_pid();
                        rmp->mp_flags |= IN_USE | PRIV_PROC; 
                        for (sig_ptr = mess_sigs; 
@@ -318,23 +325,10 @@ PRIVATE void pm_init()
                mess.PR_ENDPT = rmp->mp_endpoint;
                if (OK != (s=send(FS_PROC_NR, &mess)))
                        panic(__FILE__,"can't sync up with FS", s);
-
-               /* Register proces with ds */
-               s= ds_publish_u32(rmp->mp_name, rmp->mp_endpoint);
-               if (s != OK)
-                       failed++;
        }
   }
 
-  if(failed > 0)
-       printf("PM: failed to register %d/%d boot processes\n",
-               failed, NR_BOOT_PROCS);
-
-  /* Override some details. INIT, PM, FS and RS are somewhat special. */
-  mproc[PM_PROC_NR].mp_pid = PM_PID;           /* PM has magic pid */
-#if 0
-  mproc[RS_PROC_NR].mp_parent = INIT_PROC_NR;  /* INIT is root */
-#endif
+  /* Override some details for PM. */
   sigfillset(&mproc[PM_PROC_NR].mp_ignore);    /* guard against signals */
 
   /* Tell FS that no more system processes follow and synchronize. */
@@ -347,8 +341,6 @@ PRIVATE void pm_init()
         strcpy(uts_val.machine + 1, itoa(getprocessor()));
 #endif  
 
- if(f > 0) printf("PM: failed to register %d processes with DS.\n", f);
-
  system_hz = sys_hz();
 
  /* Map out our own text and data. This is normally done in crtso.o
index 9c5497aaefa1436a848535ed34b6f5e1552b54c7..ffbceb5ac74eef94bfd6ea1f24b6331ec3086ee1 100644 (file)
@@ -69,7 +69,7 @@ PUBLIC int do_times()
   clock_t user_time, sys_time, uptime;
   int s;
 
-  if (OK != (s=sys_times(who_e, &user_time, &sys_time, &uptime)))
+  if (OK != (s=sys_times(who_e, &user_time, &sys_time, &uptime, NULL)))
       panic(__FILE__,"do_times couldn't get times", s);
   rmp->mp_reply.reply_t1 = user_time;          /* user time */
   rmp->mp_reply.reply_t2 = sys_time;           /* system time */
index 8963584c23ec88ca7fc92c06f62c0edf3bdc1c22..72cd9261b9fe96f896ed6d46225f2ed0089bf584 100644 (file)
@@ -19,7 +19,7 @@ LDFLAGS = -i
 LIBS = -lsys 
 
 UTIL_OBJ = service.o
-OBJ = exec.o main.o manager.o 
+OBJ = exec.o main.o manager.o table.o utility.o memory.o
 
 # build local binary
 all build:     $(SERVER) $(UTIL)
@@ -27,7 +27,7 @@ $(UTIL):      $(UTIL_OBJ)
        $(CC) -o $@ $(LDFLAGS) $(UTIL_OBJ) $(UTIL_LIBS)
 $(SERVER):     $(OBJ)
        $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
-       install -S 32k $@
+       install -S 350k $@
 
 # install with other servers
 install:       /bin/$(UTIL) /usr/sbin/$(SERVER)
diff --git a/servers/rs/const.h b/servers/rs/const.h
new file mode 100644 (file)
index 0000000..25f135a
--- /dev/null
@@ -0,0 +1,83 @@
+/* Global constants used in RS.
+ */
+#ifndef RS_CONST_H
+#define RS_CONST_H
+
+/* Space reserved for program and arguments. */
+#define MAX_COMMAND_LEN     512         /* maximum argument string length */
+#define MAX_LABEL_LEN        16         /* Unique name of (this instance of)
+                                         * the driver
+                                         */
+#define MAX_SCRIPT_LEN      256         /* maximum restart script name length */
+#define MAX_NR_ARGS           4         /* maximum number of arguments */
+#define MAX_RESCUE_DIR_LEN   64         /* maximum rescue dir length */
+
+#define MAX_IPC_LIST        256         /* Max size of list for IPC target
+                                         * process names
+                                         */
+#define MAX_VM_LIST         256
+
+/* Flag values. */
+#define RS_IN_USE       0x001    /* set when process slot is in use */
+#define RS_EXITING      0x004    /* set when exit is expected */
+#define RS_REFRESHING   0x008    /* set when refresh must be done */
+#define RS_NOPINGREPLY  0x010    /* driver failed to reply to a ping request */
+#define RS_KILLED       0x020    /* driver is killed */
+#define RS_CRASHED      0x040    /* driver crashed */
+#define RS_LATEREPLY    0x080    /* no reply sent to RS_DOWN caller yet */
+#define RS_SIGNALED     0x100    /* driver crashed */
+
+/* Sys flag values. */
+#define SF_CORE_PROC    0x001    /* set for core system processes
+                                  * XXX FIXME: This should trigger a system
+                                  * panic when a CORE_PROC service cannot
+                                  * be restarted. We need better error-handling
+                                  * in RS to change this.
+                                  */
+#define SF_NEED_COPY    0x004    /* set when process needs copy to restart */
+#define SF_USE_COPY     0x008    /* set when process has a copy in memory */
+
+/* Constants determining RS period and binary exponential backoff. */
+#define RS_DELTA_T       60                     /* check every T ticks */
+#define BACKOFF_BITS    (sizeof(long)*8)        /* bits in backoff field */
+#define MAX_BACKOFF      30                     /* max backoff in RS_DELTA_T */
+
+/* Magic process table addresses. */
+#define BEG_RPROC_ADDR  (&rproc[0])
+#define END_RPROC_ADDR  (&rproc[NR_SYS_PROCS])
+#define NIL_RPROC ((struct mproc *) 0)
+
+
+/* Definitions for boot info tables. */
+#define NULL_BOOT_NR    NR_BOOT_PROCS        /* marks a null boot entry */
+#define DEFAULT_BOOT_NR NR_BOOT_PROCS        /* marks the default boot entry */
+#define SYS_ALL_C       (NR_SYS_CALLS+0)     /* specifies all calls */
+#define SYS_NULL_C      (NR_SYS_CALLS+1)     /* marks a null call entry */
+
+/* Define privilege flags for the various process types. */
+#define SRV_F  (SYS_PROC | PREEMPTIBLE)            /* system services */
+#define DSRV_F (SRV_F | DYN_PRIV_ID | CHECK_IO_PORT | CHECK_IRQ)
+                                                   /* dynamic system services */
+#define VM_F   (SYS_PROC)                          /* vm  */
+#define RUSR_F (BILLABLE | PREEMPTIBLE)            /* root user proc */
+
+/* Define system call traps for the various process types. These call masks
+ * determine what system call traps a process is allowed to make.
+ */
+#define SRV_T   (~0)                               /* system services */
+#define DSRV_T  SRV_T                              /* dynamic system services */
+#define RUSR_T  (1 << SENDREC)                     /* root user proc */
+
+/* Send masks determine to whom processes can send messages or notifications. */
+#define SRV_M   (~0)                               /* system services */
+#define RUSR_M \
+    ( spi_to(PM_PROC_NR) | spi_to(FS_PROC_NR) | spi_to(RS_PROC_NR) \
+    | spi_to(VM_PROC_NR) )                         /* root user proc */
+
+/* Define sys flags for the various process types. */
+#define SRV_SF   (SF_CORE_PROC | SF_NEED_COPY) /* system services */
+#define SRVC_SF  (SRV_SF | SF_USE_COPY)        /* system services with a copy */
+#define DSRV_SF  (0)                           /* dynamic system services */
+
+#endif /* RS_CONST_H */
+
diff --git a/servers/rs/glo.h b/servers/rs/glo.h
new file mode 100644 (file)
index 0000000..e1681b3
--- /dev/null
@@ -0,0 +1,44 @@
+/* Global variables used in RS.
+ */
+#ifndef RS_GLO_H
+#define RS_GLO_H
+
+#ifdef _TABLE
+#undef EXTERN
+#define EXTERN
+#endif
+
+/* The boot image priv table. This table has entries for all system
+ * services in the boot image.
+ */
+extern struct boot_image_priv boot_image_priv_table[];
+
+/* The boot image sys table. This table has entries for system services in
+ * the boot image that override default sys properties.
+ */
+extern struct boot_image_sys boot_image_sys_table[];
+
+/* The boot image dev table. This table has entries for system services in
+ * the boot image that support dev properties.
+ */
+extern struct boot_image_dev boot_image_dev_table[];
+
+/* The system process table. This table only has entries for system
+ * services (servers and drivers), and thus is not directly indexed by
+ * slot number.
+ */
+EXTERN struct rproc rproc[NR_SYS_PROCS];
+EXTERN struct rproc *rproc_ptr[NR_PROCS];       /* mapping for fast access */
+
+/* Pipe for detection of exec failures. The pipe is close-on-exec, and
+ * no data will be written to the pipe if the exec succeeds. After an 
+ * exec failure, the slot number is written to the pipe. After each exit,
+ * a non-blocking read retrieves the slot number from the pipe.
+ */
+EXTERN int exec_pipe[2];
+
+/* Enable/disable verbose output. */
+EXTERN long rs_verbose;
+
+#endif /* RS_GLO_H */
+
index b4c6ee566b71526e546ff0e41a36abeab541a447..892aa76fb8f9d308bf1c6ff85d223c7ac8976d04 100644 (file)
@@ -7,8 +7,6 @@
 #define _SYSTEM            1    /* get OK and negative error codes */
 #define _MINIX             1   /* tell headers to include MINIX stuff */
 
-#define VERBOSE                   0    /* display diagnostics */
-
 #include <ansi.h>
 #include <sys/types.h>
 #include <limits.h>
 #include <minix/keymap.h>
 #include <minix/bitmap.h>
 #include <minix/rs.h>
+#include <minix/dmap.h>
+#include <minix/endpoint.h>
 
 #include <archtypes.h>
 #include <timers.h>                            /* For priv.h */
 #include "../../kernel/priv.h"
+#include "../../kernel/ipc.h"
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -38,5 +39,7 @@
 #include <signal.h>
 
 #include "proto.h"
-#include "manager.h"
+#include "const.h"
+#include "type.h"
+#include "glo.h"
 
index 72174bc3c522a0cfcea3452b0bca3f2abfd0a141..b67cf5c06341151406732d5f9e927a42f86ea648 100644 (file)
@@ -4,25 +4,45 @@
  * services to see whether they are still alive.   The system services are 
  * expected to periodically send a heartbeat message. 
  * 
- * Created:
- *   Jul 22, 2005      by Jorrit N. Herder
+ * Changes:
+ *   Nov 22, 2009: rewrite of boot process (Cristiano Giuffrida)
+ *   Jul 22, 2005: Created  (Jorrit N. Herder)
  */
 #include "inc.h"
 #include <fcntl.h>
-#include <minix/endpoint.h>
+#include <a.out.h>
+#include <minix/crtso.h>
 #include "../../kernel/const.h"
 #include "../../kernel/type.h"
+#include "../../kernel/proc.h"
+#include "../pm/mproc.h"
+#include "../pm/const.h"
 
 /* Declare some local functions. */
+FORWARD _PROTOTYPE(void exec_image_copy, ( int boot_proc_idx,
+    struct boot_image *ip, struct rproc *rp)                            );
+FORWARD _PROTOTYPE(void boot_image_info_lookup, ( endpoint_t endpoint,
+    struct boot_image *image,
+    struct boot_image **ip, struct boot_image_priv **pp,
+    struct boot_image_sys **sp, struct boot_image_dev **dp)             );
+FORWARD _PROTOTYPE(void fill_call_mask, ( int *calls, int tot_nr_calls,
+    bitchunk_t *call_mask, int call_base)                               );
 FORWARD _PROTOTYPE(void init_server, (void)                            );
 FORWARD _PROTOTYPE(void sig_handler, (void)                            );
 FORWARD _PROTOTYPE(void get_work, (message *m)                         );
 FORWARD _PROTOTYPE(void reply, (int whom, message *m_out)              );
 
-/* Data buffers to retrieve info during initialization. */
-PRIVATE struct boot_image image[NR_BOOT_PROCS];
+/* The buffer where the boot image is copied during initialization. */
+PRIVATE int boot_image_buffer_size;
+PRIVATE char *boot_image_buffer;
 
-long rs_verbose = 0;
+/* Macro to identify a system service in the boot image. This rules out
+ * kernel tasks and the root system process (RS).
+ */
+#define isbootsrvprocn(n) (!iskerneln((n)) && !isrootsysn((n)))
+
+/* Flag set when memory unmapping can be done. */
+EXTERN int unmap_ok;
 
 /*===========================================================================*
  *                             main                                         *
@@ -120,6 +140,168 @@ PUBLIC int main(void)
   }
 }
 
+/*===========================================================================*
+ *                         exec_image_copy                                  *
+ *===========================================================================*/
+PRIVATE void exec_image_copy(boot_proc_idx, ip, rp)
+int boot_proc_idx;
+struct boot_image *ip;
+struct rproc *rp;
+{
+/* Copy the executable image of the given boot process. */
+  int s;
+  struct exec header;
+  static char *boot_image_ptr = NULL;
+
+  if(boot_image_ptr == NULL) {
+      boot_image_ptr = boot_image_buffer;
+  }
+  s = NO_NUM;
+
+  /* Get a.out header. */
+  if(boot_image_buffer+boot_image_buffer_size - boot_image_ptr < sizeof(header)
+      || (s = sys_getaoutheader(&header, boot_proc_idx)) != OK) {
+      panic("RS", "unable to get copy of a.out header", s);
+  }
+  memcpy(boot_image_ptr, &header, header.a_hdrlen);
+  boot_image_ptr += header.a_hdrlen;
+
+  /* Get text segment. */
+  if(boot_image_buffer+boot_image_buffer_size - boot_image_ptr < header.a_text
+      || (s = rs_startup_segcopy(ip->endpoint, T, D, (vir_bytes) boot_image_ptr,
+      header.a_text)) != OK) {
+      panic("RS", "unable to get copy of text segment", s);
+  }
+  boot_image_ptr += header.a_text;
+
+  /* Get data segment. */
+  if(boot_image_buffer+boot_image_buffer_size - boot_image_ptr < header.a_data
+      || (s = rs_startup_segcopy(ip->endpoint, D, D, (vir_bytes) boot_image_ptr,
+      header.a_data)) != OK) {
+      panic("RS", "unable to get copy of data segment", s);
+  }
+  boot_image_ptr += header.a_data;
+
+  /* Set the executable image for the given boot process. */
+  rp->r_exec_len = header.a_hdrlen + header.a_text + header.a_data;
+  rp->r_exec = boot_image_ptr - rp->r_exec_len;
+}
+
+/*===========================================================================*
+ *                         boot_image_info_lookup                            *
+ *===========================================================================*/
+PRIVATE void boot_image_info_lookup(endpoint, image, ip, pp, sp, dp)
+endpoint_t endpoint;
+struct boot_image *image;
+struct boot_image **ip;
+struct boot_image_priv **pp;
+struct boot_image_sys **sp;
+struct boot_image_dev **dp;
+{
+/* Lookup entries in boot image tables. */
+  int i;
+
+  /* When requested, locate the corresponding entry in the boot image table
+   * or panic if not found.
+   */
+  if(ip) {
+      for (i=0; i < NR_BOOT_PROCS; i++) {
+          if(image[i].endpoint == endpoint) {
+              *ip = &image[i];
+              break;
+          }
+      }
+      if(i == NR_BOOT_PROCS) {
+          panic("RS", "boot image table lookup failed", NO_NUM);
+      }
+  }
+
+  /* When requested, locate the corresponding entry in the boot image priv table
+   * or panic if not found.
+   */
+  if(pp) {
+      for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
+          if(boot_image_priv_table[i].endpoint == endpoint) {
+              *pp = &boot_image_priv_table[i];
+              break;
+          }
+      }
+      if(i == NULL_BOOT_NR) {
+          panic("RS", "boot image priv table lookup failed", NO_NUM);
+      }
+  }
+
+  /* When requested, locate the corresponding entry in the boot image sys table
+   * or resort to the default entry if not found.
+   */
+  if(sp) {
+      for (i=0; boot_image_sys_table[i].endpoint != DEFAULT_BOOT_NR; i++) {
+          if(boot_image_sys_table[i].endpoint == endpoint) {
+              *sp = &boot_image_sys_table[i];
+              break;
+          }
+      }
+      if(boot_image_sys_table[i].endpoint == DEFAULT_BOOT_NR) {
+          *sp = &boot_image_sys_table[i];         /* accept the default entry */
+      }
+  }
+
+  /* When requested, locate the corresponding entry in the boot image dev table
+   * or resort to the default entry if not found.
+   */
+  if(dp) {
+      for (i=0; boot_image_dev_table[i].endpoint != DEFAULT_BOOT_NR; i++) {
+          if(boot_image_dev_table[i].endpoint == endpoint) {
+              *dp = &boot_image_dev_table[i];
+              break;
+          }
+      }
+      if(boot_image_dev_table[i].endpoint == DEFAULT_BOOT_NR) {
+          *dp = &boot_image_dev_table[i];         /* accept the default entry */
+      }
+  }
+}
+
+/*===========================================================================*
+ *                           fill_call_mask                                 *
+ *===========================================================================*/
+PRIVATE void fill_call_mask(calls, tot_nr_calls, call_mask, call_base)
+int *calls;                     /* the unordered set of calls */
+int tot_nr_calls;               /* the total number of calls */
+bitchunk_t *call_mask;          /* the call mask to fill in */
+int call_base;                  /* the base offset for the calls */
+{
+/* Fill a call mask from an unordered set of calls. */
+  int i;
+  bitchunk_t fv;
+  int call_mask_size, nr_calls;
+
+  call_mask_size = BITMAP_CHUNKS(tot_nr_calls);
+
+  /* Count the number of calls to fill in. */
+  nr_calls = 0;
+  for(i=0; calls[i] != SYS_NULL_C; i++) {
+      nr_calls++;
+  }
+
+  /* See if all calls are allowed and call mask must be completely filled. */
+  fv = 0;
+  if(nr_calls == 1 && calls[0] == SYS_ALL_C) {
+      fv = (~0);
+  }
+
+  /* Fill or clear call mask. */
+  for(i=0; i < call_mask_size; i++) {
+      call_mask[i] = fv;
+  }
+
+  /* Not all calls allowed? Enter calls bit by bit. */
+  if(!fv) {
+      for(i=0; i < nr_calls; i++) {
+          SET_BIT(call_mask, calls[i] - call_base);
+      }
+  }
+}
 
 /*===========================================================================*
  *                             init_server                                  *
@@ -129,7 +311,252 @@ PRIVATE void init_server(void)
 /* Initialize the reincarnation server. */
   struct sigaction sa;
   struct boot_image *ip;
-  int s,t;
+  int s,i,j;
+  int nr_image_srvs, nr_image_priv_srvs;
+  struct rproc *rp;
+  struct boot_image image[NR_BOOT_PROCS];
+  struct mproc mproc[NR_PROCS];
+  struct exec header;
+  struct boot_image_priv *boot_image_priv;
+  struct boot_image_sys *boot_image_sys;
+  struct boot_image_dev *boot_image_dev;
+
+  /* See if we run in verbose mode. */
+  env_parse("rs_verbose", "d", 0, &rs_verbose, 0, 1);
+
+  /* Get a copy of the boot image table. */
+  if ((s = sys_getimage(image)) != OK) {
+      panic("RS", "unable to get copy of boot image table", s);
+  }
+
+  /* Determine the number of system services in the boot image table and
+   * compute the size required for the boot image buffer.
+   */
+  nr_image_srvs = 0;
+  boot_image_buffer_size = 0;
+  for(i=0;i<NR_BOOT_PROCS;i++) {
+      ip = &image[i];
+
+      /* System services only. */
+      if(!isbootsrvprocn(_ENDPOINT_P(ip->endpoint))) {
+          continue;
+      }
+      nr_image_srvs++;
+
+      /* Lookup the corresponding entry in the boot image sys table. */
+      boot_image_info_lookup(ip->endpoint, image,
+          NULL, NULL, &boot_image_sys, NULL);
+
+      /* If we must keep a copy of this system service, read the header
+       * and increase the size of the boot image buffer.
+       */
+      if(boot_image_sys->flags & SF_USE_COPY) {
+          if((s = sys_getaoutheader(&header, i)) != OK) {
+              panic("RS", "unable to get copy of a.out header", s);
+          }
+          boot_image_buffer_size += header.a_hdrlen
+              + header.a_text + header.a_data;
+      }
+  }
+
+  /* Determine the number of entries in the boot image priv table and make sure
+   * it matches the number of system services in the boot image table.
+   */
+  nr_image_priv_srvs = 0;
+  for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
+      boot_image_priv = &boot_image_priv_table[i];
+
+      /* System services only. */
+      if(!isbootsrvprocn(_ENDPOINT_P(boot_image_priv->endpoint))) {
+          continue;
+      }
+      nr_image_priv_srvs++;
+  }
+  if(nr_image_srvs != nr_image_priv_srvs) {
+      panic("RS", "boot image table and boot image priv table mismatch",
+          NO_NUM);
+  }
+
+  /* Allocate boot image buffer. */
+  if(boot_image_buffer_size > 0) {
+      boot_image_buffer = rs_startup_sbrk(boot_image_buffer_size);
+      if(boot_image_buffer == (char *) -1) {
+          panic("RS", "unable to allocate boot image buffer", NO_NUM);
+      }
+  }
+
+  /* Initialize the system process table in 3 steps, each of them following
+   * the appearance of system services in the boot image priv table.
+   * - Step 1: get a copy of the executable image of every system service that
+   * requires it while it is not yet running.
+   * In addition, set priviliges, sys properties, and dev properties (if any)
+   * for every system service.
+   */
+  for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
+      boot_image_priv = &boot_image_priv_table[i];
+
+      /* System services only. */
+      if(!isbootsrvprocn(_ENDPOINT_P(boot_image_priv->endpoint))) {
+          continue;
+      }
+
+      /* Lookup the corresponding entries in other tables. */
+      boot_image_info_lookup(boot_image_priv->endpoint, image,
+          &ip, NULL, &boot_image_sys, &boot_image_dev);
+      rp = &rproc[boot_image_priv - boot_image_priv_table];
+
+      /*
+       * Get a copy of the executable image if required.
+       */
+      rp->r_exec_len = 0;
+      rp->r_exec = NULL;
+      if(boot_image_sys->flags & SF_USE_COPY) {
+          exec_image_copy(ip - image, ip, rp);
+      }
+
+      /*
+       * Set privileges.
+       * XXX FIXME: We should also let RS set vm calls allowed for each sys
+       * service by using vm_set_priv(). We need a more uniform privilege
+       * management scheme in VM for this change.
+       */
+      /* Force a static privilege 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. */
+      rp->r_priv.s_flags = boot_image_priv->flags;         /* privilege flags */
+      rp->r_priv.s_trap_mask = boot_image_priv->trap_mask; /* allowed traps */
+      memcpy(&rp->r_priv.s_ipc_to, &boot_image_priv->ipc_to,
+                       sizeof(rp->r_priv.s_ipc_to));      /* allowed targets */
+
+      /* Initialize 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);
+
+      /* Set the privilege structure. */
+      if ((s = sys_privctl(ip->endpoint, SYS_PRIV_SET_SYS, &(rp->r_priv)))
+          != OK) {
+          panic("RS", "unable to set privilege structure", s);
+      }
+
+      /* Synch the privilege structure with the kernel. */
+      if ((s = sys_getpriv(&(rp->r_priv), ip->endpoint)) != OK) {
+          panic("RS", "unable to synch privilege structure", s);
+      }
+
+      /*
+       * Set sys properties.
+       */
+      rp->r_sys_flags = boot_image_sys->flags;        /* sys flags */
+
+      /*
+       * Set dev properties.
+       */
+      rp->r_dev_nr = boot_image_dev->dev_nr;          /* major device number */
+      rp->r_dev_style = boot_image_dev->dev_style;    /* device style */
+      rp->r_period = boot_image_dev->period;          /* heartbeat period */
+  }
+
+  /* - Step 2: allow every system service in the boot image to run.
+   */
+  for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
+      boot_image_priv = &boot_image_priv_table[i];
+
+      /* System services only. */
+      if(!isbootsrvprocn(_ENDPOINT_P(boot_image_priv->endpoint))) {
+          continue;
+      }
+
+      /* Lookup the corresponding entry in the boot image table. */
+      boot_image_info_lookup(boot_image_priv->endpoint, image,
+          &ip, NULL, NULL, NULL);
+
+      /* Allow the process to run. */
+      if ((s = sys_privctl(ip->endpoint, SYS_PRIV_ALLOW, NULL)) != OK) {
+          panic("RS", "unable to initialize privileges", s);
+      }
+  }
+
+  /* - Step 3: all the system services in the boot image are now running. Use
+   * the boot image table from the kernel and PM process table to complete
+   * the initialization of the system process table.
+   */
+  if ((s = getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc)) != OK) {
+      panic("RS", "unable to get copy of PM process table", s);
+  }
+  for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
+      boot_image_priv = &boot_image_priv_table[i];
+
+      /* System services only. */
+      if(!isbootsrvprocn(_ENDPOINT_P(boot_image_priv->endpoint))) {
+          continue;
+      }
+
+      /* Lookup the corresponding entry in the boot image table. */
+      boot_image_info_lookup(boot_image_priv->endpoint, image,
+          &ip, NULL, NULL, NULL);
+      rp = &rproc[boot_image_priv - boot_image_priv_table];
+
+      /* Get label. */
+      strcpy(rp->r_label, ip->proc_name);
+
+      /* Get command settings. */
+      rp->r_cmd[0]= '\0';
+      rp->r_argv[0] = rp->r_cmd;
+      rp->r_argv[1] = NULL;
+      rp->r_argc = 1;
+      rp->r_script[0]= '\0';
+
+      /* Get settings from the boot image table. */
+      rp->r_nice = ip->priority;
+      rp->r_proc_nr_e = ip->endpoint;
+
+      /* Get pid from PM process table. */
+      rp->r_pid = NO_PID;
+      for (j = 0; j < NR_PROCS; j++) {
+          if (mproc[j].mp_endpoint == rp->r_proc_nr_e) {
+              rp->r_pid = mproc[j].mp_pid;
+              break;
+          }
+      }
+      if(j == NR_PROCS) {
+          panic("RS", "unable to get pid", NO_NUM);
+      }
+
+      /* Set some defaults. */
+      rp->r_uid = 0;                           /* root */
+      rp->r_check_tm = 0;                      /* not checked yet */
+      getuptime(&rp->r_alive_tm);              /* currently alive */
+      rp->r_stop_tm = 0;                       /* not exiting yet */
+      rp->r_restarts = 0;                      /* no restarts so far */
+      rp->r_set_resources = 0;                 /* no resources */
+
+      /* Mark as in use. */
+      rp->r_flags = RS_IN_USE;
+      rproc_ptr[_ENDPOINT_P(rp->r_proc_nr_e)]= rp;
+
+      /* Publish the new system service. */
+      s = publish_service(rp);
+      if (s != OK) {
+          panic("RS", "unable to publish boot system service", s);
+      }
+  }
+
+  /*
+   * Now complete RS initialization process in collaboration with other
+   * system services.
+   */
+  /* Let the rest of the system know about our dynamically allocated buffer. */
+  if(boot_image_buffer_size > 0) {
+      boot_image_buffer = rs_startup_sbrk_synch(boot_image_buffer_size);
+      if(boot_image_buffer == (char *) -1) {
+          panic("RS", "unable to synch boot image buffer", NO_NUM);
+      }
+  }
+
+  /* Set alarm to periodically check service status. */
+  if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
+      panic("RS", "couldn't set alarm", s);
 
   /* Install signal handlers. Ask PM to transform signal into message. */
   sa.sa_handler = SIG_MESS;
@@ -138,19 +565,6 @@ PRIVATE void init_server(void)
   if (sigaction(SIGCHLD,&sa,NULL)<0) panic("RS","sigaction failed", errno);
   if (sigaction(SIGTERM,&sa,NULL)<0) panic("RS","sigaction failed", errno);
 
-  /* Initialize the system process table. Use the boot image from the kernel
-   * and the device map from the FS to gather all needed information.
-   */
-  if ((s = sys_getimage(image)) != OK) 
-      panic("RS","warning: couldn't get copy of image table", s);
-  
-  /* Set alarm to periodically check driver status. */
-  if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
-      panic("RS", "couldn't set alarm", s);
-
-  /* See if we run in verbose mode. */
-  env_parse("rs_verbose", "d", 0, &rs_verbose, 0, 1); 
-
   /* Initialize the exec pipe. */
   if (pipe(exec_pipe) == -1)
        panic("RS", "pipe failed", errno);
@@ -169,6 +583,17 @@ PRIVATE void init_server(void)
   {
        panic("RS", "fcntl set O_NONBLOCK on pipe input failed", errno);
   }
+
+ /* 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();
 }
 
 /*===========================================================================*
@@ -198,7 +623,6 @@ message *m_in;                              /* pointer to message */
         panic("RS","receive failed", s);
 }
 
-
 /*===========================================================================*
  *                             reply                                        *
  *===========================================================================*/
@@ -213,6 +637,3 @@ message *m_out;                         /* reply message */
         printf("RS: unable to send reply to %d: %d\n", who, s);
 }
 
-
-
-
index 1528b2e0a900e2a22195eae04f74f488858712ae..33897e5cbadde0e3521a0b1289144b208971ad88 100644 (file)
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <sys/vm.h>
-#include <minix/dmap.h>
-#include <minix/ds.h>
-#include <minix/endpoint.h>
 #include <minix/vm.h>
 #include <lib.h>
 
-#include <timers.h>                            /* For priv.h */
-#include "../../kernel/priv.h"
-
-/* Allocate variables. */
-struct rproc rproc[NR_SYS_PROCS];              /* system process table */
-struct rproc *rproc_ptr[NR_PROCS];             /* mapping for fast access */
+#include <minix/sysutil.h>
 
 /* Prototypes for internal functions that do the hard work. */
 FORWARD _PROTOTYPE( int caller_is_root, (endpoint_t endpoint) );
@@ -46,12 +38,12 @@ FORWARD _PROTOTYPE( void add_forward_ipc, (struct rproc *rp,
 FORWARD _PROTOTYPE( void add_backward_ipc, (struct rproc *rp,
        struct priv *privp) );
 FORWARD _PROTOTYPE( void init_privs, (struct rproc *rp, struct priv *privp) );
+FORWARD _PROTOTYPE( int set_privs, (endpoint_t endpoint, struct priv *privp,
+    int req) );
 FORWARD _PROTOTYPE( void init_pci, (struct rproc *rp, int endpoint) );
 
 PRIVATE int shutting_down = FALSE;
 
-extern int rs_verbose;
-
 /*===========================================================================*
  *                             caller_is_root                               *
  *===========================================================================*/
@@ -219,6 +211,7 @@ int flags;                                  /* extra flags, if any */
   rp->r_uid= 0;
   rp->r_nice= 0;
 
+  rp->r_sys_flags = DSRV_SF;
   rp->r_exec= NULL;
 
   if (do_copy)
@@ -226,6 +219,8 @@ int flags;                                  /* extra flags, if any */
        s= read_exec(rp);
        if (s != OK)
                return s;
+
+       rp->r_sys_flags |= SF_USE_COPY;
   }
 
   /* Initialize some fields. */
@@ -404,6 +399,7 @@ message *m_ptr;                                     /* request message pointer */
   else
        rp->r_ipc_list[0]= '\0';
 
+  rp->r_sys_flags = DSRV_SF;
   rp->r_exec= NULL;
   if (rs_start.rss_flags & RF_COPY) {
        int exst_cpy;
@@ -417,7 +413,7 @@ message *m_ptr;                                     /* request message pointer */
                 for(i = 0; i < NR_SYS_PROCS; i++) {
                        rp2 = &rproc[i];
                         if(strcmp(rp->r_cmd, rp2->r_cmd) == 0 &&
-                           rp2->r_exec != NULL) {
+                           (rp2->r_sys_flags & SF_USE_COPY)) {
                                 /* We have found the same binary that's
                                  * already been copied */
                                  exst_cpy = 1;
@@ -433,8 +429,17 @@ message *m_ptr;                                    /* request message pointer */
 
        if (s != OK)
                return s;
+
+       rp->r_sys_flags |= SF_USE_COPY;
   }
 
+  /* All dynamically created services get the same privilege flags, and
+   * allowed traps. Other privilege settings can be specified at runtime.
+   * The privilege id is dynamically allocated by the kernel.
+   */
+  rp->r_priv.s_flags = DSRV_F;           /* privilege flags */
+  rp->r_priv.s_trap_mask = DSRV_T;       /* allowed traps */
+
   /* Copy granted resources */
   if (rs_start.rss_nr_irq > NR_IRQ)
   {
@@ -460,12 +465,10 @@ message *m_ptr;                                   /* request message pointer */
        rp->r_priv.s_io_tab[i].ior_base= rs_start.rss_io[i].base;
        rp->r_priv.s_io_tab[i].ior_limit=
                rs_start.rss_io[i].base+rs_start.rss_io[i].len-1;
-#if 0
        if(rs_verbose)
           printf("RS: do_start: I/O [%x..%x]\n",
                rp->r_priv.s_io_tab[i].ior_base,
                rp->r_priv.s_io_tab[i].ior_limit);
-#endif
   }
 
   if (rs_start.rss_nr_pci_id > RSS_NR_PCI_ID)
@@ -516,7 +519,7 @@ message *m_ptr;                                     /* request message pointer */
   rp->r_dev_nr = rs_start.rss_major;
   rp->r_dev_style = STYLE_DEV; 
   rp->r_restarts = -1;                                 /* will be incremented */
-  rp->r_set_resources= 1;                      /* new style, enforece
+  rp->r_set_resources= 1;                      /* new style, enforce
                                                 * I/O resources
                                                 */
   if (sizeof(rp->r_vm) == sizeof(rs_start.rss_vm) &&
@@ -632,9 +635,10 @@ PUBLIC int do_restart(message *m_ptr)
          return(r);
       }
   }
-#if VERBOSE
-  printf("RS: do_restart: '%s' not found\n", label);
-#endif
+  if(rs_verbose) {
+      printf("RS: do_restart: '%s' not found\n", label);
+  }
+  
   return(ESRCH);
 }
 
@@ -666,16 +670,17 @@ PUBLIC int do_refresh(message *m_ptr)
 
   for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
       if (rp->r_flags & RS_IN_USE && strcmp(rp->r_label, label) == 0) {
-#if VERBOSE
-         printf("RS: refreshing %s (%d)\n", rp->r_label, rp->r_pid);
-#endif
+          if(rs_verbose) {
+              printf("RS: refreshing %s (%d)\n", rp->r_label, rp->r_pid);
+          }
          stop_service(rp,RS_REFRESHING);
          return(OK);
       }
   }
-#if VERBOSE
-  printf("RS: do_refresh: '%s' not found\n", label);
-#endif
+  if(rs_verbose) {
+      printf("RS: do_refresh: '%s' not found\n", label);
+  }
+  
   return(ESRCH);
 }
 
@@ -818,7 +823,7 @@ rp->r_restarts= 0;
                                rp->r_cmd, rp->r_backoff);
                      rp->r_backoff = 1 << MIN(rp->r_restarts,(BACKOFF_BITS-2));
                      rp->r_backoff = MIN(rp->r_backoff,MAX_BACKOFF); 
-                     if (rp->r_exec != NULL && rp->r_backoff > 1)
+                     if ((rp->r_sys_flags & SF_USE_COPY) && rp->r_backoff > 1)
                        rp->r_backoff= 1;
                  }
                  else {
@@ -897,8 +902,10 @@ message *m_ptr;
               * check and, if so request the system service's status.
               */
              else if (now - rp->r_check_tm > rp->r_period) {
+#if 0
                if(rs_verbose)
-                  printf("RS: status request sent to %d\n", rp->r_proc_nr_e); 
+                  printf("RS: status request sent to %d\n", rp->r_proc_nr_e);
+#endif
                  notify(rp->r_proc_nr_e);              /* request status */
                  rp->r_check_tm = now;                 /* mark time */
               }
@@ -933,8 +940,15 @@ endpoint_t *endpoint;
   message m;
   char * null_env = NULL;
 
-  use_copy= (rp->r_exec != NULL);
-  
+  use_copy= (rp->r_sys_flags & SF_USE_COPY);
+
+  /* See if we are not using a copy but we do need one to start the service. */
+  if(!use_copy && (rp->r_sys_flags & SF_NEED_COPY)) {
+       printf("RS: unable to start service %s without an in-memory copy\n",
+           rp->r_label);
+       return(EPERM);
+  }
+
   /* Now fork and branch for parent and child process (and check for error). */
   if (use_copy) {
   if(rs_verbose) printf("RS: fork_nb..\n");
@@ -1046,21 +1060,13 @@ endpoint_t *endpoint;
    * That will also cause the child process to start running.
    * This call should succeed: we tested number in use above.
    */
-  if ((s = sys_privctl(child_proc_nr_e, SYS_PRIV_INIT, privp)) < 0) {
-      report("RS","sys_privctl call failed", s);       /* to let child run */
+  if ((s = set_privs(child_proc_nr_e, privp, SYS_PRIV_SET_SYS)) != OK) {
+      report("RS","set_privs failed", s);
       kill(child_pid, SIGKILL);                                /* kill driver */
       rp->r_flags |= RS_EXITING;                       /* expect exit */
       return(s);                                       /* return error */
   }
 
-  /* The child is now running. Publish its endpoint in DS. */
-  s= ds_publish_u32(rp->r_label, child_proc_nr_e);
-  if (s != OK)
-       printf("RS: start_service: ds_publish_u32 failed: %d\n", s);
-  else if(rs_verbose)
-       printf("RS: start_service: ds_publish_u32 done: %s -> %d\n", 
-               rp->r_label, child_proc_nr_e);
-
   /* The purpose of non-blocking forks is to avoid involving VFS in the forking
    * process, because VFS may be blocked on a sendrec() to a MFS that is
    * waiting for a endpoint update for a dead driver. We have just published
@@ -1074,6 +1080,11 @@ endpoint_t *endpoint;
   if (use_copy)
        setuid(0);
 
+  /* Publish the new system service. */
+  s = publish_service(rp);
+  if (s != OK) {
+       printf("RS: warning: publish_service failed: %d\n", s);
+  }
   if (rp->r_dev_nr > 0) {                              /* set driver map */
       if ((s=mapdriver5(rp->r_label, strlen(rp->r_label),
              rp->r_dev_nr, rp->r_dev_style, !!use_copy /* force */)) < 0) {
@@ -1270,14 +1281,13 @@ struct rproc *rp;
                        rp->r_script, strerror(errno));
                exit(1);
        default:
-               /* Set the privilege structure for the child process to let it
+               /* Set the privilege structure for the child process and let it
                 * run.
                 */
                proc_nr_e = getnprocnr(pid);
-               r= sys_privctl(proc_nr_e, SYS_PRIV_USER, NULL);
-               if (r < 0)
-                       printf("RS: run_script: sys_privctl call failed: %d\n", r);
-
+               if ((r= set_privs(proc_nr_e, NULL, SYS_PRIV_SET_USER)) != OK) {
+                       printf("RS: run_script: set_privs call failed: %d\n",r);
+               }
                /* Do not wait for the child */
                break;
        }
@@ -1339,7 +1349,9 @@ struct priv *privp;
        char label[MAX_LABEL_LEN+1], *p;
        struct rproc *tmp_rp;
        endpoint_t proc_nr_e;
+       int r;
        int slot_nr, priv_id;
+       struct priv priv;
 
        p = rp->r_ipc_list;
 
@@ -1385,14 +1397,14 @@ struct priv *privp;
                        proc_nr_e= tmp_rp->r_proc_nr_e;
                }
 
-               priv_id= sys_getprivid(proc_nr_e);
-               if (priv_id < 0)
+               if ((r = sys_getpriv(&priv, proc_nr_e)) < 0)
                {
                        printf(
                "add_forward_ipc: unable to get priv_id for '%s': %d\n",
-                               label, priv_id);
+                               label, r);
                        continue;
                }
+               priv_id= priv.s_id;
                set_sys_bit(privp->s_ipc_to, priv_id);
        }
 }
@@ -1440,14 +1452,7 @@ struct priv *privp;
                                continue;
                }
 
-               priv_id= sys_getprivid(rrp->r_proc_nr_e);
-               if (priv_id < 0)
-               {
-                       printf(
-               "add_backward_ipc: unable to get priv_id for '%s': %d\n",
-                               label, priv_id);
-                       continue;
-               }
+               priv_id= rrp->r_priv.s_id;
 
                set_sys_bit(privp->s_ipc_to, priv_id);
        }
@@ -1513,6 +1518,35 @@ struct priv *privp;
        }
 }
 
+/*===========================================================================*
+ *                             set_privs                                    *
+ *===========================================================================*/
+PRIVATE int set_privs(endpoint, privp, req)
+endpoint_t endpoint;
+struct priv *privp;
+int req;
+{
+  int r;
+
+  /* Set the privilege structure. */
+  if ((r = sys_privctl(endpoint, req, privp)) != OK) {
+      return r;
+  }
+
+  /* Synch the privilege structure with the kernel for system services. */
+  if(req == SYS_PRIV_SET_SYS) {
+      if ((r = sys_getpriv(privp, endpoint)) != OK) {
+          return r;
+      }
+  }
+
+  /* Allow the process to run. */
+  if ((r = sys_privctl(endpoint, SYS_PRIV_ALLOW, NULL)) != OK) {
+      return r;
+  }
+
+  return(OK);
+}
 
 /*===========================================================================*
  *                             init_pci                                     *
diff --git a/servers/rs/memory.c b/servers/rs/memory.c
new file mode 100644 (file)
index 0000000..b805610
--- /dev/null
@@ -0,0 +1,213 @@
+/* This file contains memory management routines for RS.
+ *
+ * Changes:
+ *   Nov 22, 2009: Created    (Cristiano Giuffrida)
+ */
+
+#include "inc.h"
+#include "../../kernel/const.h"
+#include "../../kernel/type.h"
+#include "../../kernel/proc.h"
+
+EXTERN char *_brksize;
+
+PRIVATE char * _rs_startbrksize = NULL;
+PRIVATE char * _rs_endbrksize = NULL;
+
+#define munmap _munmap
+#define munmap_text _munmap_text
+#include <sys/mman.h>
+#undef munmap
+#undef munmap_text
+
+PUBLIC int unmap_ok = 0;
+
+/*===========================================================================*
+ *                           check_mem_available                            *
+ *===========================================================================*/
+PRIVATE int check_mem_available(char *new_brksize)
+{
+/* Check if enough memory is available to grow break size. */
+  register struct mem_map *mem_sp, *mem_dp;
+  vir_clicks sp_click, gap_base, sp_lower;
+  int s;
+  long base_of_stack, sp_delta;        /* longs avoid certain problems */
+  vir_bytes sp;
+  struct proc proc;
+  vir_clicks data_clicks;
+
+  /* Get stack pointer and pointers to data/stack segment maps. */
+  if ((s=sys_getproc(&proc, SELF)) != OK) {
+      return(s);
+  }
+  sp = proc.p_reg.sp;                    /* stack pointer */
+  mem_dp = &proc.p_memmap[D];            /* pointer to data segment map */
+  mem_sp = &proc.p_memmap[S];            /* pointer to stack segment map */
+
+  /* Compute how many clicks the data segment is to become. */
+  data_clicks = (vir_clicks) ( ((long) new_brksize + CLICK_SIZE - 1) >>
+      CLICK_SHIFT) - mem_dp->mem_vir;
+
+  /* See if stack size has gone negative (i.e., sp too close to 0xFFFF...) */
+  base_of_stack = (long) mem_sp->mem_vir + (long) mem_sp->mem_len;
+  sp_click = sp >> CLICK_SHIFT;        /* click containing sp */
+  if (sp_click >= base_of_stack)
+  {
+       return(ENOMEM); /* sp too high */
+  }
+
+  /* Compute size of gap between stack and data segments. */
+  sp_delta = (long) mem_sp->mem_vir - (long) sp_click;
+  sp_lower = (sp_delta > 0 ? sp_click : mem_sp->mem_vir);
+
+  /* Add a safety margin for future stack growth. Impossible to do right. */
+#define SAFETY_BYTES  (384 * sizeof(char *))
+#define SAFETY_CLICKS ((SAFETY_BYTES + CLICK_SIZE - 1) / CLICK_SIZE)
+  gap_base = mem_dp->mem_vir + data_clicks + SAFETY_CLICKS;
+  if (sp_lower < gap_base)
+  {
+       return(ENOMEM); /* data and stack collided */
+  }
+
+  return(OK);
+}
+  
+/*===========================================================================*
+ *                             rs_startup_sbrk                              *
+ *===========================================================================*/
+PUBLIC void* rs_startup_sbrk(size)
+size_t size;                    /* the size to grow */
+{
+/* RS's own sbrk() used at startup. */
+  void* addr;
+  char* new_brksize;
+
+  /* Check input for non-positive size or size overflows. */
+  new_brksize = _brksize + size;
+  if (size <= 0 || new_brksize < _brksize) {
+      return( (char *) -1);
+  }
+
+  /* Check if enough memory is available. */
+  if(check_mem_available(new_brksize) != OK) {
+      return( (char *) -1);
+  }
+  
+  /* Save initial break size. */
+  if(_rs_startbrksize == NULL) {
+      _rs_startbrksize = _brksize;
+  }
+  
+  /* Set address and adjust break size. */
+  addr = _brksize;
+  _brksize = new_brksize;
+  _rs_endbrksize = _brksize;
+
+  return addr;
+}
+
+/*===========================================================================*
+ *                             rs_startup_sbrk_synch                        *
+ *===========================================================================*/
+PUBLIC void* rs_startup_sbrk_synch(size)
+size_t size;                    /* the size to grow */
+{
+/* Synchronize RS's own sbrk() with the rest of the system right after
+ * startup. We use the original sbrk() here.
+ */
+  void* addr;
+
+  /* Restore original break size. */
+  _brksize = _rs_startbrksize;
+
+  /* Call original sbrk() and see if we observe the same effect. */
+  addr = (void*)sbrk(size);
+  if(_rs_startbrksize != addr) {
+      printf("Unable to synch rs_startup_sbrk() and sbrk(): addr 0x%x!=0x%x\n",
+          (int) _rs_startbrksize, (int) addr);
+      return( (char *) -1);
+  }
+  if(_rs_endbrksize != _brksize) {
+      printf("Unable to synch rs_startup_sbrk() and sbrk(): size 0x%x!=0x%x\n",
+         (int) _rs_endbrksize, (int) _brksize);
+      return( (char *) -1);
+  }
+
+  return addr;
+}
+
+/*===========================================================================*
+ *                             rs_startup_segcopy                           *
+ *===========================================================================*/
+PUBLIC int rs_startup_segcopy(src_proc, src_seg, dst_seg, dst_vir, bytes)
+endpoint_t src_proc;            /* source process */
+int src_seg;                    /* source memory segment */
+int dst_seg;                    /* destination memory segment */
+vir_bytes dst_vir;              /* destination virtual address */
+phys_bytes bytes;               /* how many bytes */
+{
+/* Copy a process's T, D, S segment to RS's address space. Used at startup. */
+  struct proc src_p, dst_p;
+  phys_bytes src_phys, dst_phys;
+  int s;
+
+  /* Check input. */
+  if((src_seg != T && src_seg != D && src_seg != S) || bytes <= 0) {
+      return EINVAL;
+  }
+
+  /* We don't override normal behavior when not copying to our data segment. */
+  if(dst_seg != D) {
+      s = sys_vircopy(src_proc, src_seg, 0, SELF, dst_seg, dst_vir, bytes);
+      return(s);
+  }
+
+  /* Get kernel process slot for both source and destination. */
+  if ((s=sys_getproc(&src_p, src_proc)) != OK) {
+      return(s);
+  }
+  if ((s=sys_getproc(&dst_p, SELF)) != OK) {
+      return(s);
+  }
+
+  /* Map source address to physical address. */
+  src_phys = (phys_bytes) src_p.p_memmap[src_seg].mem_phys << CLICK_SHIFT;
+
+  /* Check if destination address is out of bounds or overflows. */
+  if(dst_vir+bytes > (vir_bytes)_rs_endbrksize
+      || dst_vir < (vir_bytes)_rs_startbrksize || dst_vir+bytes < dst_vir) {
+      return EFAULT;
+  }
+
+  /* Map destination address to physical address. */
+  dst_phys = (phys_bytes) dst_p.p_memmap[D].mem_phys << CLICK_SHIFT;
+  dst_phys += dst_vir - (dst_p.p_memmap[D].mem_vir << CLICK_SHIFT);
+
+  /* Make a physical copy for the requested data. */
+  s = sys_abscopy(src_phys, dst_phys, bytes);
+
+  return(s);
+}
+
+/*===========================================================================*
+ *                                 munmap                                   *
+ *===========================================================================*/
+PUBLIC int munmap(void *addrstart, vir_bytes len)
+{
+  if(!unmap_ok) 
+      return ENOSYS;
+
+  return _munmap(addrstart, len);
+}
+
+/*===========================================================================*
+ *                              munmap_text                                 *
+ *===========================================================================*/
+PUBLIC int munmap_text(void *addrstart, vir_bytes len)
+{
+  if(!unmap_ok)
+      return ENOSYS;
+
+  return _munmap_text(addrstart, len);
+}
+
index 7ec33f0cacd140c8b778a3834dab38d76b281ce7..e8d9a099f0fc395886d1573372632bc36f693fbc 100644 (file)
@@ -1,5 +1,8 @@
 /* Function prototypes. */
 
+/* Structs used in prototypes must be declared as such first. */
+struct rproc;
+
 /* exec.c */
 _PROTOTYPE( int dev_execve, (int proc_e, 
        char *exec, size_t exec_len,  char *argv[], char **env));
@@ -19,4 +22,12 @@ _PROTOTYPE( void do_period, (message *m));
 _PROTOTYPE( void do_exit, (message *m));
 _PROTOTYPE( int do_getsysinfo, (message *m));
 
+/* utility.c */
+_PROTOTYPE( int publish_service, (struct rproc *rp));
+
+/* memory.c */
+_PROTOTYPE( void* rs_startup_sbrk, (size_t size));
+_PROTOTYPE( void* rs_startup_sbrk_synch, (size_t size));
+_PROTOTYPE( int rs_startup_segcopy, (endpoint_t src_proc, int src_s,
+    int dst_s, vir_bytes dst_vir, phys_bytes bytes));
 
diff --git a/servers/rs/table.c b/servers/rs/table.c
new file mode 100644 (file)
index 0000000..4264c87
--- /dev/null
@@ -0,0 +1,67 @@
+/* This file contains the definition of the boot image info tables.
+ *
+ * Changes:
+ *   Nov 22, 2009: Created  (Cristiano Giuffrida)
+ */
+
+#define _TABLE
+
+#include "inc.h"
+
+/* Define kernel calls that processes are allowed to make. This is not looking
+ * very nice, but we need to define the access rights on a per call basis.
+ * 
+ * Calls are unordered lists, converted by RS to bitmasks
+ * once at runtime.
+ */
+#define FS_KC SYS_KILL, SYS_VIRCOPY, SYS_SAFECOPYFROM, SYS_SAFECOPYTO, \
+    SYS_VIRVCOPY, SYS_UMAP, SYS_GETINFO, SYS_EXIT, SYS_TIMES, SYS_SETALARM, \
+    SYS_PRIVCTL, SYS_TRACE , SYS_SETGRANT, SYS_PROFBUF, SYS_SYSCTL
+#define DRV_KC FS_KC, SYS_SEGCTL, SYS_IRQCTL, SYS_INT86, SYS_DEVIO, \
+    SYS_SDEVIO, SYS_VDEVIO, SYS_SETGRANT, SYS_PROFBUF, SYS_SYSCTL
+
+PRIVATE int
+  fs_kc[] = { FS_KC, SYS_NULL_C },
+  pm_kc[] = { SYS_ALL_C, SYS_NULL_C },
+  ds_kc[] = { SYS_ALL_C, SYS_NULL_C },
+  vm_kc[] = { SYS_ALL_C, SYS_NULL_C },
+  drv_kc[] = { DRV_KC, SYS_NULL_C },
+  tty_kc[] = { DRV_KC, SYS_PHYSCOPY, SYS_ABORT, SYS_IOPENABLE,
+      SYS_READBIOS, SYS_NULL_C },
+  mem_kc[] = { DRV_KC, SYS_PHYSCOPY, SYS_PHYSVCOPY, SYS_IOPENABLE, SYS_NULL_C },
+  rusr_kc[] = { SYS_NULL_C },
+
+  no_kc[] = { SYS_NULL_C }; /* no kernel call */
+
+/* Definition of the boot image priv table. */
+PUBLIC struct boot_image_priv boot_image_priv_table[] = {
+  /*endpoint,    priv flags,  traps,  ipcto,  kcalls    */
+  { VM_PROC_NR,       VM_F,   SRV_T,  SRV_M,  vm_kc     },
+  { PM_PROC_NR,       SRV_F,  SRV_T,  SRV_M,  pm_kc     },
+  { FS_PROC_NR,       SRV_F,  SRV_T,  SRV_M,  fs_kc     },
+  { DS_PROC_NR,       SRV_F,  SRV_T,  SRV_M,  ds_kc     },
+  { TTY_PROC_NR,      SRV_F,  SRV_T,  SRV_M,  tty_kc    },
+  { MEM_PROC_NR,      SRV_F,  SRV_T,  SRV_M,  mem_kc    },
+  { LOG_PROC_NR,      SRV_F,  SRV_T,  SRV_M,  drv_kc    },
+  { MFS_PROC_NR,      SRV_F,  SRV_T,  SRV_M,  fs_kc     },
+  { INIT_PROC_NR,     RUSR_F, RUSR_T, RUSR_M, rusr_kc   },
+  { NULL_BOOT_NR,     0,      0,      0,      no_kc     } /* null entry */
+};
+
+/* Definition of the boot image sys table. */
+PUBLIC struct boot_image_sys boot_image_sys_table[] = {
+  /*endpoint,         sys flags                         */
+  { LOG_PROC_NR,      SRVC_SF                           },
+  { MFS_PROC_NR,      SRVC_SF                           },
+  { DEFAULT_BOOT_NR,  SRV_SF                            } /* default entry */
+};
+
+/* Definition of the boot image dev table. */
+PUBLIC struct boot_image_dev boot_image_dev_table[] = {
+  /*endpoint,         dev_nr,       dev_style,  period  */
+  { TTY_PROC_NR,      TTY_MAJOR,    STYLE_TTY,       0  },
+  { MEM_PROC_NR,      MEMORY_MAJOR, STYLE_DEV,       0  },
+  { LOG_PROC_NR,      LOG_MAJOR,    STYLE_DEV,       0  },
+  { DEFAULT_BOOT_NR,  0,            STYLE_NDEV,      0  } /* default entry */
+};
+
diff --git a/servers/rs/type.h b/servers/rs/type.h
new file mode 100644 (file)
index 0000000..aa2e2ce
--- /dev/null
@@ -0,0 +1,78 @@
+/* Type definitions used in RS.
+ */
+#ifndef RS_TYPE_H
+#define RS_TYPE_H
+
+/* Definition of an entry of the boot image priv table. */
+struct boot_image_priv {
+  endpoint_t endpoint;         /* process endpoint number */
+
+  int flags;                   /* privilege flags */
+  short trap_mask;             /* allowed system call traps */
+  int ipc_to;                  /* send mask protection */
+  int *k_calls;                /* kernel call protection */
+};
+
+/* Definition of an entry of the boot image sys table. */
+struct boot_image_sys {
+  endpoint_t endpoint;         /* process endpoint number */
+
+  int flags;                   /* system flags */
+};
+
+/* Definition of an entry of the boot image dev table. */
+struct boot_image_dev {
+  endpoint_t endpoint;         /* process endpoint number */
+
+  dev_t dev_nr;                /* major device number */
+  int dev_style;               /* device style */
+  long period;                 /* heartbeat period (or zero) */
+};
+
+/* Definition of an entry of the system process table. */
+struct rproc {
+  endpoint_t r_proc_nr_e;      /* process endpoint number */
+  pid_t r_pid;                 /* process id, -1 if the process is not there */
+  dev_t r_dev_nr;              /* major device number */
+  int r_dev_style;             /* device style */
+
+  int r_restarts;              /* number of restarts (initially zero) */
+  long r_backoff;              /* number of periods to wait before revive */
+  unsigned r_flags;            /* status and policy flags */
+  unsigned r_sys_flags;        /* sys flags */
+
+  long r_period;               /* heartbeat period (or zero) */
+  clock_t r_check_tm;          /* timestamp of last check */
+  clock_t r_alive_tm;          /* timestamp of last heartbeat */
+  clock_t r_stop_tm;           /* timestamp of SIGTERM signal */
+  endpoint_t r_caller;         /* RS_LATEREPLY caller */
+
+  char *r_exec;                        /* Executable image */ 
+  size_t r_exec_len;           /* Length of image */
+
+  char r_label[MAX_LABEL_LEN]; /* unique name of this driver */
+  char r_cmd[MAX_COMMAND_LEN]; /* raw command plus arguments */
+  char r_script[MAX_SCRIPT_LEN]; /* name of the restart script executable */
+  char *r_argv[MAX_NR_ARGS+2];  /* parsed arguments vector */
+  int r_argc;                          /* number of arguments */
+
+  /* Resources */
+  int r_set_resources;
+  struct priv r_priv;          /* Privilege structure to be passed to the
+                                * kernel.
+                                */
+  uid_t r_uid;
+  int r_nice;
+  int r_nr_pci_id;             /* Number of PCI devices IDs */
+  struct { u16_t vid; u16_t did; } r_pci_id[RSS_NR_PCI_ID];
+  int r_nr_pci_class;          /* Number of PCI class IDs */
+  struct { u32_t class; u32_t mask; } r_pci_class[RSS_NR_PCI_CLASS];
+
+  u32_t r_call_mask[RSS_NR_SYSTEM];
+  char r_ipc_list[MAX_IPC_LIST];
+  bitchunk_t r_vm[RSS_VM_CALL_SIZE];
+  int r_nr_control;
+  char r_control[RSS_NR_CONTROL][MAX_LABEL_LEN];
+};
+
+#endif /* RS_TYPE_H */
diff --git a/servers/rs/utility.c b/servers/rs/utility.c
new file mode 100644 (file)
index 0000000..5caf96c
--- /dev/null
@@ -0,0 +1,32 @@
+/* This file contains some utility routines for RS.
+ *
+ * Changes:
+ *   Nov 22, 2009: Created    (Cristiano Giuffrida)
+ */
+
+#include "inc.h"
+
+#include <minix/ds.h>
+
+/*===========================================================================*
+ *                             publish_service                              *
+ *===========================================================================*/
+PUBLIC int publish_service(rp)
+struct rproc *rp;                              /* pointer to process slot */
+{
+/* A new system service has been started. Publish the necessary information. */
+  int s;
+
+  /* Register its label with DS. */
+  s= ds_publish_u32(rp->r_label, rp->r_proc_nr_e);
+  if (s != OK) {
+      return s;
+  }
+  if (rs_verbose) {
+      printf("RS: publish_service: DS label registration done: %s -> %d\n", 
+          rp->r_label, rp->r_proc_nr_e);
+  }
+
+  return(OK);
+}
+