source: trunk/minix/kernel/main.c@ 20

Last change on this file since 20 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

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