The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kernel/main.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /* This file contains the main program of MINIX as well as its shutdown code.
    2  * The routine main() initializes the system and starts the ball rolling by
    3  * setting up the process table, interrupt vectors, and scheduling each task 
    4  * to run to initialize itself.
    5  * The routine shutdown() does the opposite and brings down MINIX. 
    6  *
    7  * The entries into this file are:
    8  *   main:              MINIX main program
    9  *   prepare_shutdown:  prepare to take MINIX down
   10  *
   11  * Changes:
   12  *   Nov 24, 2004   simplified main() with system image  (Jorrit N. Herder)
   13  *   Aug 20, 2004   new prepare_shutdown() and shutdown()  (Jorrit N. Herder)
   14  */
   15 #include "kernel.h"
   16 #include <signal.h>
   17 #include <string.h>
   18 #include <unistd.h>
   19 #include <a.out.h>
   20 #include <minix/callnr.h>
   21 #include <minix/com.h>
   22 #include "proc.h"
   23 
   24 /* Prototype declarations for PRIVATE functions. */
   25 FORWARD _PROTOTYPE( void announce, (void));     
   26 FORWARD _PROTOTYPE( void shutdown, (timer_t *tp));
   27 
   28 /*===========================================================================*
   29  *                              main                                         *
   30  *===========================================================================*/
   31 PUBLIC void main()
   32 {
   33 /* Start the ball rolling. */
   34   struct boot_image *ip;        /* boot image pointer */
   35   register struct proc *rp;     /* process pointer */
   36   register struct priv *sp;     /* privilege structure pointer */
   37   register int i, s;
   38   int hdrindex;                 /* index to array of a.out headers */
   39   phys_clicks text_base;
   40   vir_clicks text_clicks, data_clicks;
   41   reg_t ktsb;                   /* kernel task stack base */
   42   struct exec e_hdr;            /* for a copy of an a.out header */
   43 
   44   /* Initialize the interrupt controller. */
   45   intr_init(1);
   46 
   47   /* Clear the process table. Anounce each slot as empty and set up mappings 
   48    * for proc_addr() and proc_nr() macros. Do the same for the table with 
   49    * privilege structures for the system processes. 
   50    */
   51   for (rp = BEG_PROC_ADDR, i = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++i) {
   52         rp->p_rts_flags = SLOT_FREE;            /* initialize free slot */
   53         rp->p_nr = i;                           /* proc number from ptr */
   54         (pproc_addr + NR_TASKS)[i] = rp;        /* proc ptr from number */
   55   }
   56   for (sp = BEG_PRIV_ADDR, i = 0; sp < END_PRIV_ADDR; ++sp, ++i) {
   57         sp->s_proc_nr = NONE;                   /* initialize as free */
   58         sp->s_id = i;                           /* priv structure index */
   59         ppriv_addr[i] = sp;                     /* priv ptr from number */
   60   }
   61 
   62   /* Set up proc table entries for processes in boot image.  The stacks of the
   63    * kernel tasks are initialized to an array in data space.  The stacks
   64    * of the servers have been added to the data segment by the monitor, so
   65    * the stack pointer is set to the end of the data segment.  All the
   66    * processes are in low memory on the 8086.  On the 386 only the kernel
   67    * is in low memory, the rest is loaded in extended memory.
   68    */
   69 
   70   /* Task stacks. */
   71   ktsb = (reg_t) t_stack;
   72 
   73   for (i=0; i < NR_BOOT_PROCS; ++i) {
   74         ip = &image[i];                         /* process' attributes */
   75         rp = proc_addr(ip->proc_nr);            /* get process pointer */
   76         rp->p_max_priority = ip->priority;      /* max scheduling priority */
   77         rp->p_priority = ip->priority;          /* current priority */
   78         rp->p_quantum_size = ip->quantum;       /* quantum size in ticks */
   79         rp->p_ticks_left = ip->quantum;         /* current credit */
   80         strncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set process name */
   81         (void) get_priv(rp, (ip->flags & SYS_PROC));    /* assign structure */
   82         priv(rp)->s_flags = ip->flags;                  /* process flags */
   83         priv(rp)->s_trap_mask = ip->trap_mask;          /* allowed traps */
   84         priv(rp)->s_call_mask = ip->call_mask;          /* kernel call mask */
   85         priv(rp)->s_ipc_to.chunk[0] = ip->ipc_to;       /* restrict targets */
   86         if (iskerneln(proc_nr(rp))) {           /* part of the kernel? */ 
   87                 if (ip->stksize > 0) {          /* HARDWARE stack size is 0 */
   88                         rp->p_priv->s_stack_guard = (reg_t *) ktsb;
   89                         *rp->p_priv->s_stack_guard = STACK_GUARD;
   90                 }
   91                 ktsb += ip->stksize;    /* point to high end of stack */
   92                 rp->p_reg.sp = ktsb;    /* this task's initial stack ptr */
   93                 text_base = kinfo.code_base >> CLICK_SHIFT;
   94                                         /* processes that are in the kernel */
   95                 hdrindex = 0;           /* all use the first a.out header */
   96         } else {
   97                 hdrindex = 1 + i-NR_TASKS;      /* servers, drivers, INIT */
   98         }
   99 
  100         /* The bootstrap loader created an array of the a.out headers at
  101          * absolute address 'aout'. Get one element to e_hdr.
  102          */
  103         phys_copy(aout + hdrindex * A_MINHDR, vir2phys(&e_hdr),
  104                                                 (phys_bytes) A_MINHDR);
  105         /* Convert addresses to clicks and build process memory map */
  106         text_base = e_hdr.a_syms >> CLICK_SHIFT;
  107         text_clicks = (e_hdr.a_text + CLICK_SIZE-1) >> CLICK_SHIFT;
  108         if (!(e_hdr.a_flags & A_SEP)) text_clicks = 0;     /* common I&D */
  109         data_clicks = (e_hdr.a_total + CLICK_SIZE-1) >> CLICK_SHIFT;
  110         rp->p_memmap[T].mem_phys = text_base;
  111         rp->p_memmap[T].mem_len  = text_clicks;
  112         rp->p_memmap[D].mem_phys = text_base + text_clicks;
  113         rp->p_memmap[D].mem_len  = data_clicks;
  114         rp->p_memmap[S].mem_phys = text_base + text_clicks + data_clicks;
  115         rp->p_memmap[S].mem_vir  = data_clicks; /* empty - stack is in data */
  116 
  117         /* Set initial register values.  The processor status word for tasks 
  118          * is different from that of other processes because tasks can
  119          * access I/O; this is not allowed to less-privileged processes 
  120          */
  121         rp->p_reg.pc = (reg_t) ip->initial_pc;
  122         rp->p_reg.psw = (iskernelp(rp)) ? INIT_TASK_PSW : INIT_PSW;
  123 
  124         /* Initialize the server stack pointer. Take it down one word
  125          * to give crtso.s something to use as "argc".
  126          */
  127         if (isusern(proc_nr(rp))) {             /* user-space process? */ 
  128                 rp->p_reg.sp = (rp->p_memmap[S].mem_vir +
  129                                 rp->p_memmap[S].mem_len) << CLICK_SHIFT;
  130                 rp->p_reg.sp -= sizeof(reg_t);
  131         }
  132         
  133         /* Set ready. The HARDWARE task is never ready. */
  134         if (rp->p_nr != HARDWARE) {
  135                 rp->p_rts_flags = 0;            /* runnable if no flags */
  136                 lock_enqueue(rp);               /* add to scheduling queues */
  137         } else {
  138                 rp->p_rts_flags = NO_MAP;       /* prevent from running */
  139         }
  140 
  141         /* Code and data segments must be allocated in protected mode. */
  142         alloc_segments(rp);
  143   }
  144 
  145 #if ENABLE_BOOTDEV 
  146   /* Expect an image of the boot device to be loaded into memory as well. 
  147    * The boot device is the last module that is loaded into memory, and, 
  148    * for example, can contain the root FS (useful for embedded systems). 
  149    */
  150   hdrindex ++;
  151   phys_copy(aout + hdrindex * A_MINHDR,vir2phys(&e_hdr),(phys_bytes) A_MINHDR);
  152   if (e_hdr.a_flags & A_IMG) {
  153         kinfo.bootdev_base = e_hdr.a_syms; 
  154         kinfo.bootdev_size = e_hdr.a_data; 
  155   }
  156 #endif
  157 
  158   /* MINIX is now ready. All boot image processes are on the ready queue.
  159    * Return to the assembly code to start running the current process. 
  160    */
  161   bill_ptr = proc_addr(IDLE);           /* it has to point somewhere */
  162   announce();                           /* print MINIX startup banner */
  163   restart();
  164 }
  165 
  166 /*===========================================================================*
  167  *                              announce                                     *
  168  *===========================================================================*/
  169 PRIVATE void announce(void)
  170 {
  171   /* Display the MINIX startup banner. */
  172   kprintf("\nMINIX %s.%s. "
  173       "Copyright 2006, Vrije Universiteit, Amsterdam, The Netherlands\n",
  174       OS_RELEASE, OS_VERSION);
  175 #if (CHIP == INTEL)
  176   /* Real mode, or 16/32-bit protected mode? */
  177   kprintf("Executing in %s mode.\n\n",
  178       machine.protected ? "32-bit protected" : "real");
  179 #endif
  180 }
  181 
  182 /*===========================================================================*
  183  *                              prepare_shutdown                             *
  184  *===========================================================================*/
  185 PUBLIC void prepare_shutdown(how)
  186 int how;
  187 {
  188 /* This function prepares to shutdown MINIX. */
  189   static timer_t shutdown_timer;
  190   register struct proc *rp; 
  191   message m;
  192 
  193   /* Send a signal to all system processes that are still alive to inform 
  194    * them that the MINIX kernel is shutting down. A proper shutdown sequence
  195    * should be implemented by a user-space server. This mechanism is useful
  196    * as a backup in case of system panics, so that system processes can still
  197    * run their shutdown code, e.g, to synchronize the FS or to let the TTY
  198    * switch to the first console. 
  199    */
  200   kprintf("Sending SIGKSTOP to system processes ...\n"); 
  201   for (rp=BEG_PROC_ADDR; rp<END_PROC_ADDR; rp++) {
  202       if (!isemptyp(rp) && (priv(rp)->s_flags & SYS_PROC) && !iskernelp(rp))
  203           send_sig(proc_nr(rp), SIGKSTOP);
  204   }
  205 
  206   /* Continue after 1 second, to give processes a chance to get scheduled to 
  207    * do shutdown work.  Set a watchog timer to call shutdown(). The timer 
  208    * argument passes the shutdown status. 
  209    */
  210   kprintf("MINIX will now be shut down ...\n");
  211   tmr_arg(&shutdown_timer)->ta_int = how;
  212   shutdown(&shutdown_timer);
  213 }
  214 /*===========================================================================*
  215  *                              shutdown                                     *
  216  *===========================================================================*/
  217 PRIVATE void shutdown(tp)
  218 timer_t *tp;
  219 {
  220 /* This function is called from prepare_shutdown or stop_sequence to bring 
  221  * down MINIX. How to shutdown is in the argument: RBT_HALT (return to the
  222  * monitor), RBT_MONITOR (execute given code), RBT_RESET (hard reset). 
  223  */
  224   int how = tmr_arg(tp)->ta_int;
  225   u16_t magic; 
  226 
  227   /* Now mask all interrupts, including the clock, and stop the clock. */
  228   outb(INT_CTLMASK, ~0); 
  229   clock_stop();
  230 
  231   if (mon_return && how != RBT_RESET) {
  232         /* Reinitialize the interrupt controllers to the BIOS defaults. */
  233         intr_init(0);
  234         outb(INT_CTLMASK, 0);
  235         outb(INT2_CTLMASK, 0);
  236 
  237         /* Return to the boot monitor. Set the program if not already done. */
  238         if (how != RBT_MONITOR) phys_copy(vir2phys(""), kinfo.params_base, 1); 
  239         level0(monitor);
  240   }
  241 
  242   /* Reset the system by jumping to the reset address (real mode), or by
  243    * forcing a processor shutdown (protected mode). First stop the BIOS 
  244    * memory test by setting a soft reset flag. 
  245    */
  246   magic = STOP_MEM_CHECK;
  247   phys_copy(vir2phys(&magic), SOFT_RESET_FLAG_ADDR, SOFT_RESET_FLAG_SIZE);
  248   level0(reset);
  249 }
  250 

Cache object: 2f5eaffc5c2e1754bbe47c6daf67e807


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.