1 /* This file contains the main program of MINIX. The routine main()
2 * initializes the system and starts the ball rolling by setting up the proc
3 * table, interrupt vectors, and scheduling each task to run to initialize
4 * itself.
5 *
6 * The entries into this file are:
7 * main: MINIX main program
8 * panic: abort MINIX due to a fatal error
9 */
10
11 #include "kernel.h"
12 #include <unistd.h>
13 #include <minix/callnr.h>
14 #include <minix/com.h>
15 #include "proc.h"
16 #if (MACHINE == SUN)
17 #include <minix/boot.h>
18 #include <sun/syscall.h>
19 #include "logging.h"
20 #include <net/gen/ether.h>
21 #include "bootinfo.h"
22 #endif
23
24 #if (MACHINE == SUN)
25 /*
26 * Must be first thing main's data segment (initialisation ensures that it
27 * goes into the data segment). Also, main.o must be the first file in the
28 * link that has a data segment.
29 *
30 * Because R8192 had to be removed from the data segment entry, the bootstrap
31 * program can no longer rely on the start of the data segment being aligned
32 * on an 8192 boundary---it may now start anywhere in the first page reserved
33 * for the data segment. The minix bootstrap still aligns the smxboot_info
34 * to an 8Kb boundary, however. We declare the smxboot_space structure
35 * so that we can be sure that there is enough space for the smx_bootinfo
36 * structure, even if the data segment is 8Kb aligned. We also use the
37 * address of smxboot_space to initialise smxboot, as they must both lie
38 * on the same 8Kb page.
39 */
40 struct smx_bootinfo smxboot_space = {{{1}}};
41 struct smx_bootinfo *smxboot;
42 #endif
43
44 static char rcsid[] = "$Id: main.c,v 1.6 1996/08/14 04:39:57 paul Exp $"; /* Must follow smxboot! */
45
46
47 /*===========================================================================*
48 * main *
49 *===========================================================================*/
50 PUBLIC void main()
51 {
52 /* Start the ball rolling. */
53
54 register struct proc *rp;
55 register int t;
56 int sizeindex;
57 phys_clicks text_base = 0;
58 vir_clicks text_clicks;
59 vir_clicks data_clicks;
60 #if (MACHINE != SUN)
61 phys_bytes phys_b;
62 #endif
63 reg_t ktsb; /* kernel task stack base */
64 struct memory *memp = 0;
65 struct tasktab *ttp;
66 #if (MACHINE == SUN)
67 unsigned long addr;
68 int prog_num;
69 smxboot = (struct smx_bootinfo *) downclick((int) &smxboot_space);
70
71 log_init();
72
73 /* fetch values that were placed by the minix bootstrap */
74 code_base = smxboot->prog[KERNEL_PROG].text_vaddr;
75 tot_mem_size = smxboot->mem_bytes >> CLICK_SHIFT;
76 set_debug_level(smxboot->debug);
77 #if ENABLE_NETWORKING
78 se_init((char *)&smxboot->ether_addr);
79 #endif
80
81
82 debug_str("Starting kernel - debugging on; smxboot addr = ");
83 debug_int((int) &smxboot);
84 debug_str("\n");
85
86 /*
87 * Unmap the text and data segments of the minix bootstrap program. They
88 * are no longer needed, and we will map in init and all other user programs
89 * in that address range.
90 */
91 for (addr = 0x10000; addr < (unsigned long)code_base; addr += CLICK_SIZE) {
92 SunOS(SYS_munmap, addr, CLICK_SIZE);
93 }
94
95 lock(); /* Lock out non-error SunOS signals until initialisation done */
96 #endif
97
98
99 #if (CHIP == INTEL)
100 /* Initialize the interrupt controller. */
101 intr_init(1);
102 #endif
103
104 /* Interpret memory sizes. */
105 mem_init();
106
107 /* Clear the process table.
108 * Set up mappings for proc_addr() and proc_number() macros.
109 */
110 for (rp = BEG_PROC_ADDR, t = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++t) {
111 rp->p_flags = P_SLOT_FREE;
112 #if (MACHINE == SUN)
113 rp->p_stn = INVALID_STN; /* not currently part of an interaction */
114 #endif
115 rp->p_nr = t; /* proc number from ptr */
116 (pproc_addr + NR_TASKS)[t] = rp; /* proc ptr from number */
117 }
118
119 /* Set up proc table entries for tasks and servers. The stacks of the
120 * kernel tasks are initialized to an array in data space. The stacks
121 * of the servers have been added to the data segment by the monitor, so
122 * the stack pointer is set to the end of the data segment. All the
123 * processes are in low memory on the 8086. On the 386 only the kernel
124 * is in low memory, the rest if loaded in extended memory.
125 */
126
127 /* Task stacks. */
128 ktsb = (reg_t) t_stack;
129
130 for (t = -NR_TASKS; t <= LOW_USER; ++t) {
131 rp = proc_addr(t); /* t's process slot */
132 ttp = &tasktab[t + NR_TASKS]; /* t's task attributes */
133 strcpy(rp->p_name, ttp->name);
134
135 #if (MACHINE == SUN)
136 /*
137 * Initialise the context for each process with the current
138 * context of the SunOS process. Critical values (sp, pc, npc)
139 * will be set before the context is used to start the smx process.
140 */
141 SunOS(SYS_context, 0, &rp->p_reg);
142 #endif
143
144 if (t < 0) {
145 if (ttp->stksize > 0) {
146 rp->p_stguard = (reg_t *) ktsb;
147 *rp->p_stguard = STACK_GUARD;
148 }
149 ktsb += ttp->stksize;
150 rp->p_reg.sp = ktsb;
151 text_base = code_base >> CLICK_SHIFT;
152 /* tasks are all in the kernel */
153 sizeindex = 0; /* and use the full kernel sizes */
154 memp = &mem[0]; /* remove from this memory chunk */
155 } else {
156 sizeindex = 2 * t + 2; /* MM, FS, INIT have their own sizes*/
157 }
158 rp->p_reg.pc = (reg_t) ttp->initial_pc;
159 rp->p_reg.psw = istaskp(rp) ? INIT_TASK_PSW : INIT_PSW;
160
161 #if (MACHINE == SUN)
162 /*
163 * Use the boot info to determine the sizes of the text and
164 * data segments. All tasks are within the kernel.
165 */
166 if (istaskp(rp) || isidlehardware(proc_number(rp))) {
167 prog_num = KERNEL_PROG;
168 } else {
169 prog_num = proc_number(rp) + (MM_PROG - MM_PROC_NR);
170 }
171
172 text_clicks = smxboot->prog[prog_num].text_clicks;
173 data_clicks = smxboot->prog[prog_num].data_clicks;
174 #endif
175
176 rp->p_map[T].mem_phys = text_base;
177 rp->p_map[T].mem_len = text_clicks;
178 rp->p_map[D].mem_phys = text_base + text_clicks;
179 rp->p_map[D].mem_len = data_clicks;
180 rp->p_map[S].mem_phys = text_base + text_clicks + data_clicks;
181 rp->p_map[S].mem_vir = data_clicks; /* empty - stack is in data */
182
183 #if (MACHINE == SUN)
184 /*
185 * Servers and user programs are mapped into the standard
186 * SunOS addresses. The Virtual addresses are specified in
187 * the boot info. The kernel is executed "in-situ", so the
188 * virtual addresses are the same as physical addresses.
189 */
190 if (istaskp(rp) || isidlehardware(proc_number(rp))) {
191 rp->p_map[T].mem_vir = rp->p_map[T].mem_phys;
192 rp->p_map[D].mem_vir = rp->p_map[D].mem_phys;
193 rp->p_map[S].mem_vir = rp->p_map[S].mem_phys;
194 } else {
195 rp->p_map[T].mem_vir = smxboot->prog[prog_num].text_vaddr >>
196 CLICK_SHIFT;
197 rp->p_map[D].mem_vir = smxboot->prog[prog_num].data_vaddr >>
198 CLICK_SHIFT;
199 rp->p_map[S].mem_vir = rp->p_map[D].mem_vir + data_clicks;
200 rp->p_reg.pc = smxboot->prog[prog_num].entry;
201 rp->p_reg.sp = rp->p_map[S].mem_vir << CLICK_SHIFT;
202 }
203 if (prog_num == INIT_PROG) {
204 /*
205 * Take the last click of the data/stack segment for the stack.
206 * The src/tools/Makefile must ensure that the gap is big
207 * enough to allow this.
208 */
209 rp->p_map[S].mem_len = 1;
210 rp->p_map[S].mem_phys -= 1;
211 rp->p_map[S].mem_vir = (code_base >> CLICK_SHIFT) -
212 rp->p_map[S].mem_len;
213 rp->p_reg.sp = (rp->p_map[S].mem_vir + rp->p_map[S].mem_len) <<
214 CLICK_SHIFT;
215 rp->p_map[D].mem_len -= 1;
216 } else {
217 rp->p_map[S].mem_len = 0;
218 }
219 rp->p_reg.npc = rp->p_reg.pc + 4;
220 rp->p_reg.sp -= INIT_SP; /*leave room for a stack frame*/
221
222 #endif /* MACHINE == SUN */
223 debug_str("Process "); debug_int(t);
224 debug_str(": pc = "); debug_int(rp->p_reg.pc);
225 debug_str(", sp = "); debug_int(rp->p_reg.sp);
226 debug_str("\n");
227 text_base += text_clicks + data_clicks; /* ready for next, if server */
228
229 memp->size -= (text_base - memp->base);
230 memp->base = text_base; /* memory no longer free */
231
232 #if (CHIP == INTEL)
233 if (t >= 0) {
234 /* Initialize the server stack pointer. Take it down one word
235 * to give crtso.s something to use as "argc".
236 */
237 rp->p_reg.sp = (rp->p_map[S].mem_vir +
238 rp->p_map[S].mem_len) << CLICK_SHIFT;
239 rp->p_reg.sp -= sizeof(reg_t);
240 }
241
242 #if _WORD_SIZE == 4
243 /* Servers are loaded in extended memory if in 386 mode. */
244 if (t < 0) {
245 memp = &mem[1];
246 text_base = 0x100000 >> CLICK_SHIFT;
247 }
248 #endif
249 #endif /* CHIP == INTEL */
250 if (!isidlehardware(t)) lock_ready(rp); /* IDLE, HARDWARE neveready */
251 rp->p_flags = 0;
252
253 #if (CHIP == INTEL)
254 alloc_segments(rp);
255 #endif
256 }
257
258 proc[NR_TASKS+INIT_PROC_NR].p_pid = 1;/* INIT of course has pid 1 */
259 bill_ptr = proc_addr(IDLE); /* it has to point somewhere */
260 lock_pick_proc();
261
262 #if (MACHINE == SUN)
263 init_sun_handlers(); /* Initialise sun signal handling */
264 /*
265 * Setup the smx boot information.
266 */
267 boot_parameters.bp_rootdev = DEV_FD0;
268 boot_parameters.bp_ramimagedev = 0;
269 boot_parameters.bp_ramsize = 0;
270 boot_parameters.bp_processor = CHIP;
271
272 /*
273 * Initialise the protection according to the protection level
274 * specified from the minix bootstrap.
275 */
276 protect_init(code_base, smxboot->prog[KERNEL_PROG].text_clicks,
277 smxboot->prog[KERNEL_PROG].data_clicks, tot_mem_size,
278 smxboot->prot_lev);
279
280 /* enable all SunOS signals */
281 unlock();
282 #endif /* MACHINE == SUN */
283
284 debug_str("In kernel main---about to call restart\n");
285
286 /* Now go to the assembly code to start running the current process. */
287 restart();
288 }
289
290
291 /*===========================================================================*
292 * panic *
293 *===========================================================================*/
294 PUBLIC void panic(s,n)
295 _CONST char *s;
296 int n;
297 {
298 /* The system has run aground of a fatal error. Terminate execution.
299 * If the panic originated in MM or FS, the string will be empty and the
300 * file system already syncked. If the panic originates in the kernel, we are
301 * kind of stuck.
302 */
303
304 if (*s != 0) {
305 printf("\nKernel panic: %s",s);
306 if (n != NO_NUM) printf(" %d", n);
307 printf("\n");
308 }
309 #if (MACHINE == SUN)
310 /* a useful register and context dump */
311 do_dump();
312 #endif
313 wreboot(RBT_PANIC);
314 }
315
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.