Commit | Line | Data |
---|---|---|
4bd1c0bf | 1 | /*- |
eb5ba828 | 2 | * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. |
4bd1c0bf WN |
3 | * All rights reserved. |
4 | * | |
5 | * This code is derived from software contributed to Berkeley by | |
eb5ba828 | 6 | * William Jolitz. |
4bd1c0bf | 7 | * |
af359dea C |
8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | |
15 | * documentation and/or other materials provided with the distribution. | |
16 | * 3. All advertising materials mentioning features or use of this software | |
17 | * must display the following acknowledgement: | |
18 | * This product includes software developed by the University of | |
19 | * California, Berkeley and its contributors. | |
20 | * 4. Neither the name of the University nor the names of its contributors | |
21 | * may be used to endorse or promote products derived from this software | |
22 | * without specific prior written permission. | |
3a20b539 | 23 | * |
af359dea C |
24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
34 | * SUCH DAMAGE. | |
35 | * | |
36 | * @(#)machdep.c 7.4 (Berkeley) 6/3/91 | |
3a0e7e3d | 37 | */ |
4bd1c0bf | 38 | |
af359dea | 39 | |
3a20b539 BJ |
40 | #include "param.h" |
41 | #include "systm.h" | |
af359dea | 42 | #include "signalvar.h" |
3a20b539 BJ |
43 | #include "kernel.h" |
44 | #include "map.h" | |
3a20b539 | 45 | #include "proc.h" |
af359dea | 46 | #include "user.h" |
3a20b539 BJ |
47 | #include "buf.h" |
48 | #include "reboot.h" | |
49 | #include "conf.h" | |
3a20b539 | 50 | #include "file.h" |
3a20b539 BJ |
51 | #include "clist.h" |
52 | #include "callout.h" | |
af359dea | 53 | #include "malloc.h" |
3a20b539 BJ |
54 | #include "mbuf.h" |
55 | #include "msgbuf.h" | |
2313b06b | 56 | #include "net/netisr.h" |
3a20b539 | 57 | |
af359dea C |
58 | #include "vm/vm.h" |
59 | #include "vm/vm_kern.h" | |
60 | #include "vm/vm_page.h" | |
61 | ||
62 | vm_map_t buffer_map; | |
63 | extern vm_offset_t avail_end; | |
64 | ||
65 | #include "machine/cpu.h" | |
2313b06b | 66 | #include "machine/reg.h" |
2313b06b WN |
67 | #include "machine/psl.h" |
68 | #include "machine/specialreg.h" | |
69 | #include "i386/isa/rtc.h" | |
3a20b539 BJ |
70 | |
71 | /* | |
72 | * Declare these as initialized data so we can patch them. | |
73 | */ | |
74 | int nswbuf = 0; | |
75 | #ifdef NBUF | |
76 | int nbuf = NBUF; | |
77 | #else | |
78 | int nbuf = 0; | |
79 | #endif | |
80 | #ifdef BUFPAGES | |
81 | int bufpages = BUFPAGES; | |
82 | #else | |
83 | int bufpages = 0; | |
84 | #endif | |
2313b06b | 85 | int msgbufmapped; /* set when safe to use msgbuf */ |
3a20b539 BJ |
86 | |
87 | /* | |
88 | * Machine-dependent startup code | |
89 | */ | |
eb5ba828 | 90 | int boothowto = 0, Maxmem = 0; |
af359dea C |
91 | long dumplo; |
92 | int physmem, maxmem; | |
eb5ba828 BJ |
93 | extern int bootdev; |
94 | #ifdef SMALL | |
95 | extern int forcemaxmem; | |
96 | #endif | |
97 | int biosmem; | |
98 | ||
99 | extern cyloffset; | |
100 | ||
af359dea | 101 | cpu_startup(firstaddr) |
3a20b539 BJ |
102 | int firstaddr; |
103 | { | |
104 | register int unixsize; | |
105 | register unsigned i; | |
106 | register struct pte *pte; | |
107 | int mapaddr, j; | |
108 | register caddr_t v; | |
109 | int maxbufs, base, residual; | |
af359dea C |
110 | extern long Usrptsize; |
111 | vm_offset_t minaddr, maxaddr; | |
112 | vm_size_t size; | |
eb5ba828 | 113 | |
3a20b539 BJ |
114 | /* |
115 | * Initialize error message buffer (at end of core). | |
116 | */ | |
eb5ba828 | 117 | |
af359dea C |
118 | /* avail_end was pre-decremented in pmap_bootstrap to compensate */ |
119 | for (i = 0; i < btoc(sizeof (struct msgbuf)); i++) | |
120 | pmap_enter(pmap_kernel(), msgbufp, avail_end + i * NBPG, | |
121 | VM_PROT_ALL, TRUE); | |
122 | msgbufmapped = 1; | |
4bd1c0bf | 123 | |
3a20b539 BJ |
124 | #ifdef KDB |
125 | kdb_init(); /* startup kernel debugger */ | |
126 | #endif | |
127 | /* | |
128 | * Good {morning,afternoon,evening,night}. | |
129 | */ | |
130 | printf(version); | |
131 | printf("real mem = %d\n", ctob(physmem)); | |
132 | ||
133 | /* | |
134 | * Allocate space for system data structures. | |
135 | * The first available real memory address is in "firstaddr". | |
136 | * The first available kernel virtual address is in "v". | |
137 | * As pages of kernel virtual memory are allocated, "v" is incremented. | |
138 | * As pages of memory are allocated and cleared, | |
139 | * "firstaddr" is incremented. | |
140 | * An index into the kernel page table corresponding to the | |
141 | * virtual memory address maintained in "v" is kept in "mapaddr". | |
142 | */ | |
af359dea C |
143 | |
144 | /* | |
145 | * Make two passes. The first pass calculates how much memory is | |
146 | * needed and allocates it. The second pass assigns virtual | |
147 | * addresses to the various data structures. | |
148 | */ | |
149 | firstaddr = 0; | |
150 | again: | |
151 | v = (caddr_t)firstaddr; | |
152 | ||
3a20b539 BJ |
153 | #define valloc(name, type, num) \ |
154 | (name) = (type *)v; v = (caddr_t)((name)+(num)) | |
155 | #define valloclim(name, type, num, lim) \ | |
156 | (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) | |
3a20b539 BJ |
157 | valloc(cfree, struct cblock, nclist); |
158 | valloc(callout, struct callout, ncallout); | |
af359dea | 159 | valloc(swapmap, struct map, nswapmap = maxproc * 2); |
2313b06b WN |
160 | #ifdef SYSVSHM |
161 | valloc(shmsegs, struct shmid_ds, shminfo.shmmni); | |
3a20b539 | 162 | #endif |
3a20b539 BJ |
163 | /* |
164 | * Determine how many buffers to allocate. | |
165 | * Use 10% of memory for the first 2 Meg, 5% of the remaining | |
166 | * memory. Insure a minimum of 16 buffers. | |
167 | * We allocate 1/2 as many swap buffer headers as file i/o buffers. | |
168 | */ | |
169 | if (bufpages == 0) | |
170 | if (physmem < (2 * 1024 * 1024)) | |
171 | bufpages = physmem / 10 / CLSIZE; | |
172 | else | |
173 | bufpages = ((2 * 1024 * 1024 + physmem) / 20) / CLSIZE; | |
174 | if (nbuf == 0) { | |
175 | nbuf = bufpages / 2; | |
176 | if (nbuf < 16) | |
177 | nbuf = 16; | |
178 | } | |
179 | if (nswbuf == 0) { | |
180 | nswbuf = (nbuf / 2) &~ 1; /* force even */ | |
181 | if (nswbuf > 256) | |
182 | nswbuf = 256; /* sanity */ | |
183 | } | |
184 | valloc(swbuf, struct buf, nswbuf); | |
3a20b539 BJ |
185 | valloc(buf, struct buf, nbuf); |
186 | ||
187 | /* | |
af359dea | 188 | * End of first pass, size has been calculated so allocate memory |
3a20b539 | 189 | */ |
af359dea C |
190 | if (firstaddr == 0) { |
191 | size = (vm_size_t)(v - firstaddr); | |
192 | firstaddr = (int)kmem_alloc(kernel_map, round_page(size)); | |
193 | if (firstaddr == 0) | |
194 | panic("startup: no room for tables"); | |
195 | goto again; | |
196 | } | |
3a20b539 | 197 | /* |
af359dea | 198 | * End of second pass, addresses have been assigned |
3a20b539 | 199 | */ |
af359dea C |
200 | if ((vm_size_t)(v - firstaddr) != size) |
201 | panic("startup: table size inconsistency"); | |
3a20b539 BJ |
202 | /* |
203 | * Now allocate buffers proper. They are different than the above | |
204 | * in that they usually occupy more virtual memory than physical. | |
205 | */ | |
af359dea C |
206 | size = MAXBSIZE * nbuf; |
207 | buffer_map = kmem_suballoc(kernel_map, (vm_offset_t)&buffers, | |
208 | &maxaddr, size, FALSE); | |
209 | minaddr = (vm_offset_t)buffers; | |
210 | if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0, | |
211 | &minaddr, size, FALSE) != KERN_SUCCESS) | |
212 | panic("startup: cannot allocate buffers"); | |
3a20b539 BJ |
213 | base = bufpages / nbuf; |
214 | residual = bufpages % nbuf; | |
af359dea C |
215 | for (i = 0; i < nbuf; i++) { |
216 | vm_size_t curbufsize; | |
217 | vm_offset_t curbuf; | |
3a20b539 | 218 | |
af359dea C |
219 | /* |
220 | * First <residual> buffers get (base+1) physical pages | |
221 | * allocated for them. The rest get (base) physical pages. | |
222 | * | |
223 | * The rest of each buffer occupies virtual space, | |
224 | * but has no physical memory allocated for it. | |
225 | */ | |
226 | curbuf = (vm_offset_t)buffers + i * MAXBSIZE; | |
227 | curbufsize = CLBYTES * (i < residual ? base+1 : base); | |
228 | vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE); | |
229 | vm_map_simplify(buffer_map, curbuf); | |
230 | } | |
3a20b539 | 231 | /* |
af359dea C |
232 | * Allocate a submap for exec arguments. This map effectively |
233 | * limits the number of processes exec'ing at any time. | |
3a20b539 | 234 | */ |
af359dea C |
235 | exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, |
236 | 16*NCARGS, TRUE); | |
3a20b539 | 237 | /* |
af359dea | 238 | * Allocate a submap for physio |
3a20b539 | 239 | */ |
af359dea C |
240 | phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, |
241 | VM_PHYS_SIZE, TRUE); | |
eb5ba828 BJ |
242 | |
243 | /* | |
af359dea C |
244 | * Finally, allocate mbuf pool. Since mclrefcnt is an off-size |
245 | * we use the more space efficient malloc in place of kmem_alloc. | |
eb5ba828 | 246 | */ |
af359dea C |
247 | mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES, |
248 | M_MBUF, M_NOWAIT); | |
249 | bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES); | |
250 | mb_map = kmem_suballoc(kernel_map, (vm_offset_t)&mbutl, &maxaddr, | |
251 | VM_MBUF_SIZE, FALSE); | |
252 | /* | |
253 | * Initialize callouts | |
254 | */ | |
255 | callfree = callout; | |
256 | for (i = 1; i < ncallout; i++) | |
257 | callout[i-1].c_next = &callout[i]; | |
eb5ba828 | 258 | |
af359dea | 259 | printf("avail mem = %d\n", ptoa(vm_page_free_count)); |
3a20b539 BJ |
260 | printf("using %d buffers containing %d bytes of memory\n", |
261 | nbuf, bufpages * CLBYTES); | |
3a20b539 BJ |
262 | |
263 | /* | |
264 | * Set up CPU-specific registers, cache, etc. | |
265 | */ | |
266 | initcpu(); | |
267 | ||
268 | /* | |
269 | * Set up buffers, so they can be used to read disk labels. | |
270 | */ | |
af359dea | 271 | bufinit(); |
3a20b539 BJ |
272 | |
273 | /* | |
274 | * Configure the system. | |
275 | */ | |
276 | configure(); | |
277 | } | |
278 | ||
279 | #ifdef PGINPROF | |
280 | /* | |
281 | * Return the difference (in microseconds) | |
282 | * between the current time and a previous | |
283 | * time as represented by the arguments. | |
284 | * If there is a pending clock interrupt | |
285 | * which has not been serviced due to high | |
286 | * ipl, return error code. | |
287 | */ | |
288 | /*ARGSUSED*/ | |
289 | vmtime(otime, olbolt, oicr) | |
290 | register int otime, olbolt, oicr; | |
291 | { | |
292 | ||
293 | return (((time.tv_sec-otime)*60 + lbolt-olbolt)*16667); | |
294 | } | |
295 | #endif | |
296 | ||
4bd1c0bf WN |
297 | struct sigframe { |
298 | int sf_signum; | |
299 | int sf_code; | |
300 | struct sigcontext *sf_scp; | |
2313b06b | 301 | sig_t sf_handler; |
4bd1c0bf WN |
302 | int sf_eax; |
303 | int sf_edx; | |
304 | int sf_ecx; | |
2313b06b | 305 | struct sigcontext sf_sc; |
4bd1c0bf WN |
306 | } ; |
307 | ||
af359dea C |
308 | extern int kstack[]; |
309 | ||
3a20b539 BJ |
310 | /* |
311 | * Send an interrupt to process. | |
312 | * | |
313 | * Stack is set up to allow sigcode stored | |
314 | * in u. to call routine, followed by kcall | |
315 | * to sigreturn routine below. After sigreturn | |
316 | * resets the signal mask, the stack, and the | |
317 | * frame pointer, it returns to the user | |
318 | * specified pc, psl. | |
319 | */ | |
af359dea C |
320 | void |
321 | sendsig(catcher, sig, mask, code) | |
2313b06b WN |
322 | sig_t catcher; |
323 | int sig, mask; | |
324 | unsigned code; | |
3a20b539 | 325 | { |
af359dea | 326 | register struct proc *p = curproc; |
3a20b539 | 327 | register int *regs; |
4bd1c0bf | 328 | register struct sigframe *fp; |
af359dea C |
329 | struct sigacts *ps = p->p_sigacts; |
330 | int oonstack, frmtrap; | |
3a20b539 | 331 | |
af359dea C |
332 | regs = p->p_regs; |
333 | oonstack = ps->ps_onstack; | |
334 | frmtrap = curpcb->pcb_flags & FM_TRAP; | |
3a20b539 BJ |
335 | /* |
336 | * Allocate and validate space for the signal handler | |
337 | * context. Note that if the stack is in P0 space, the | |
338 | * call to grow() is a nop, and the useracc() check | |
339 | * will fail if the process has not already allocated | |
340 | * the space with a `brk'. | |
341 | */ | |
af359dea C |
342 | if (!ps->ps_onstack && (ps->ps_sigonstack & sigmask(sig))) { |
343 | fp = (struct sigframe *)(ps->ps_sigsp | |
344 | - sizeof(struct sigframe)); | |
345 | ps->ps_onstack = 1; | |
4bd1c0bf | 346 | } else { |
af359dea | 347 | if (frmtrap) |
2313b06b WN |
348 | fp = (struct sigframe *)(regs[tESP] |
349 | - sizeof(struct sigframe)); | |
4bd1c0bf | 350 | else |
2313b06b WN |
351 | fp = (struct sigframe *)(regs[sESP] |
352 | - sizeof(struct sigframe)); | |
4bd1c0bf | 353 | } |
2313b06b | 354 | |
af359dea | 355 | if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) |
2313b06b WN |
356 | (void)grow((unsigned)fp); |
357 | ||
358 | if (useracc((caddr_t)fp, sizeof (struct sigframe), B_WRITE) == 0) { | |
3a20b539 BJ |
359 | /* |
360 | * Process has trashed its stack; give it an illegal | |
361 | * instruction to halt it in its tracks. | |
362 | */ | |
2313b06b | 363 | SIGACTION(p, SIGILL) = SIG_DFL; |
3a20b539 | 364 | sig = sigmask(SIGILL); |
2313b06b WN |
365 | p->p_sigignore &= ~sig; |
366 | p->p_sigcatch &= ~sig; | |
367 | p->p_sigmask &= ~sig; | |
368 | psignal(p, SIGILL); | |
3a20b539 BJ |
369 | return; |
370 | } | |
4bd1c0bf | 371 | |
3a20b539 BJ |
372 | /* |
373 | * Build the argument list for the signal handler. | |
374 | */ | |
375 | fp->sf_signum = sig; | |
2313b06b | 376 | fp->sf_code = code; |
2313b06b WN |
377 | fp->sf_scp = &fp->sf_sc; |
378 | fp->sf_handler = catcher; | |
4bd1c0bf WN |
379 | |
380 | /* save scratch registers */ | |
af359dea | 381 | if(frmtrap) { |
4bd1c0bf WN |
382 | fp->sf_eax = regs[tEAX]; |
383 | fp->sf_edx = regs[tEDX]; | |
384 | fp->sf_ecx = regs[tECX]; | |
385 | } else { | |
386 | fp->sf_eax = regs[sEAX]; | |
387 | fp->sf_edx = regs[sEDX]; | |
388 | fp->sf_ecx = regs[sECX]; | |
389 | } | |
3a20b539 BJ |
390 | /* |
391 | * Build the signal context to be used by sigreturn. | |
392 | */ | |
af359dea | 393 | fp->sf_sc.sc_onstack = oonstack; |
2313b06b | 394 | fp->sf_sc.sc_mask = mask; |
af359dea | 395 | if(frmtrap) { |
2313b06b WN |
396 | fp->sf_sc.sc_sp = regs[tESP]; |
397 | fp->sf_sc.sc_fp = regs[tEBP]; | |
398 | fp->sf_sc.sc_pc = regs[tEIP]; | |
399 | fp->sf_sc.sc_ps = regs[tEFLAGS]; | |
4bd1c0bf | 400 | regs[tESP] = (int)fp; |
af359dea | 401 | regs[tEIP] = (int)((struct pcb *)kstack)->pcb_sigc; |
4bd1c0bf | 402 | } else { |
2313b06b WN |
403 | fp->sf_sc.sc_sp = regs[sESP]; |
404 | fp->sf_sc.sc_fp = regs[sEBP]; | |
405 | fp->sf_sc.sc_pc = regs[sEIP]; | |
406 | fp->sf_sc.sc_ps = regs[sEFLAGS]; | |
4bd1c0bf | 407 | regs[sESP] = (int)fp; |
af359dea | 408 | regs[sEIP] = (int)((struct pcb *)kstack)->pcb_sigc; |
4bd1c0bf | 409 | } |
3a20b539 BJ |
410 | } |
411 | ||
412 | /* | |
413 | * System call to cleanup state after a signal | |
414 | * has been taken. Reset signal mask and | |
415 | * stack state from context left by sendsig (above). | |
416 | * Return to previous pc and psl as specified by | |
417 | * context left by sendsig. Check carefully to | |
418 | * make sure that the user has not modified the | |
419 | * psl to gain improper priviledges or to cause | |
420 | * a machine fault. | |
421 | */ | |
2313b06b WN |
422 | sigreturn(p, uap, retval) |
423 | struct proc *p; | |
424 | struct args { | |
425 | struct sigcontext *sigcntxp; | |
426 | } *uap; | |
427 | int *retval; | |
3a20b539 | 428 | { |
3a20b539 | 429 | register struct sigcontext *scp; |
2313b06b | 430 | register struct sigframe *fp; |
af359dea C |
431 | register int *regs = p->p_regs; |
432 | ||
3a20b539 | 433 | |
4bd1c0bf | 434 | fp = (struct sigframe *) regs[sESP] ; |
2313b06b WN |
435 | |
436 | if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0) | |
437 | return(EINVAL); | |
4bd1c0bf WN |
438 | |
439 | /* restore scratch registers */ | |
440 | regs[sEAX] = fp->sf_eax ; | |
441 | regs[sEDX] = fp->sf_edx ; | |
442 | regs[sECX] = fp->sf_ecx ; | |
4bd1c0bf WN |
443 | |
444 | scp = fp->sf_scp; | |
2313b06b WN |
445 | if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0) |
446 | return(EINVAL); | |
4bd1c0bf WN |
447 | #ifdef notyet |
448 | if ((scp->sc_ps & PSL_MBZ) != 0 || (scp->sc_ps & PSL_MBO) != PSL_MBO) { | |
2313b06b | 449 | return(EINVAL); |
3a20b539 | 450 | } |
4bd1c0bf | 451 | #endif |
af359dea | 452 | p->p_sigacts->ps_onstack = scp->sc_onstack & 01; |
2313b06b | 453 | p->p_sigmask = scp->sc_mask &~ |
3a20b539 | 454 | (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)); |
4bd1c0bf WN |
455 | regs[sEBP] = scp->sc_fp; |
456 | regs[sESP] = scp->sc_sp; | |
457 | regs[sEIP] = scp->sc_pc; | |
458 | regs[sEFLAGS] = scp->sc_ps; | |
2313b06b | 459 | return(EJUSTRETURN); |
3a20b539 | 460 | } |
3a20b539 BJ |
461 | |
462 | int waittime = -1; | |
463 | ||
464 | boot(arghowto) | |
465 | int arghowto; | |
466 | { | |
467 | register long dummy; /* r12 is reserved */ | |
468 | register int howto; /* r11 == how to boot */ | |
469 | register int devtype; /* r10 == major of root dev */ | |
470 | extern char *panicstr; | |
471 | ||
472 | howto = arghowto; | |
473 | if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) { | |
474 | register struct buf *bp; | |
475 | int iter, nbusy; | |
476 | ||
477 | waittime = 0; | |
478 | (void) splnet(); | |
479 | printf("syncing disks... "); | |
480 | /* | |
481 | * Release inodes held by texts before update. | |
482 | */ | |
483 | if (panicstr == 0) | |
af359dea | 484 | vnode_pager_umount(NULL); |
2313b06b | 485 | sync((struct sigcontext *)0); |
3a20b539 BJ |
486 | |
487 | for (iter = 0; iter < 20; iter++) { | |
488 | nbusy = 0; | |
489 | for (bp = &buf[nbuf]; --bp >= buf; ) | |
490 | if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY) | |
491 | nbusy++; | |
492 | if (nbusy == 0) | |
493 | break; | |
494 | printf("%d ", nbusy); | |
495 | DELAY(40000 * iter); | |
496 | } | |
497 | if (nbusy) | |
498 | printf("giving up\n"); | |
499 | else | |
500 | printf("done\n"); | |
501 | DELAY(10000); /* wait for printf to finish */ | |
502 | } | |
4bd1c0bf | 503 | splhigh(); |
3a20b539 | 504 | devtype = major(rootdev); |
3a20b539 | 505 | if (howto&RB_HALT) { |
4bd1c0bf | 506 | printf("halting (in tight loop); hit reset\n\n"); |
af359dea | 507 | splx(0xfffd); /* all but keyboard XXX */ |
9c09b4f2 | 508 | for (;;) ; |
3a20b539 BJ |
509 | } else { |
510 | if (howto & RB_DUMP) { | |
af359dea | 511 | dumpsys(); |
3a20b539 BJ |
512 | /*NOTREACHED*/ |
513 | } | |
3a20b539 BJ |
514 | } |
515 | #ifdef lint | |
516 | dummy = 0; dummy = dummy; | |
517 | printf("howto %d, devtype %d\n", arghowto, devtype); | |
518 | #endif | |
9c09b4f2 BJ |
519 | reset_cpu(); |
520 | for(;;) ; | |
3a20b539 BJ |
521 | /*NOTREACHED*/ |
522 | } | |
523 | ||
3a20b539 BJ |
524 | int dumpmag = 0x8fca0101; /* magic number for savecore */ |
525 | int dumpsize = 0; /* also for savecore */ | |
526 | /* | |
527 | * Doadump comes here after turning off memory management and | |
528 | * getting on the dump stack, either when called above, or by | |
529 | * the auto-restart code. | |
530 | */ | |
531 | dumpsys() | |
532 | { | |
533 | ||
534 | if (dumpdev == NODEV) | |
535 | return; | |
3a20b539 BJ |
536 | if ((minor(dumpdev)&07) != 1) |
537 | return; | |
3a20b539 BJ |
538 | dumpsize = physmem; |
539 | printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo); | |
540 | printf("dump "); | |
541 | switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) { | |
542 | ||
543 | case ENXIO: | |
544 | printf("device bad\n"); | |
545 | break; | |
546 | ||
547 | case EFAULT: | |
548 | printf("device not ready\n"); | |
549 | break; | |
550 | ||
551 | case EINVAL: | |
552 | printf("area improper\n"); | |
553 | break; | |
554 | ||
555 | case EIO: | |
556 | printf("i/o error\n"); | |
557 | break; | |
558 | ||
559 | default: | |
560 | printf("succeeded\n"); | |
561 | break; | |
562 | } | |
563 | printf("\n\n"); | |
564 | DELAY(1000); | |
3a20b539 BJ |
565 | } |
566 | ||
567 | microtime(tvp) | |
568 | register struct timeval *tvp; | |
569 | { | |
570 | int s = splhigh(); | |
571 | ||
572 | *tvp = time; | |
573 | tvp->tv_usec += tick; | |
574 | while (tvp->tv_usec > 1000000) { | |
575 | tvp->tv_sec++; | |
576 | tvp->tv_usec -= 1000000; | |
577 | } | |
578 | splx(s); | |
579 | } | |
580 | ||
581 | physstrat(bp, strat, prio) | |
582 | struct buf *bp; | |
583 | int (*strat)(), prio; | |
584 | { | |
4bd1c0bf WN |
585 | register int s; |
586 | caddr_t baddr; | |
3a20b539 | 587 | |
4bd1c0bf WN |
588 | /* |
589 | * vmapbuf clobbers b_addr so we must remember it so that it | |
590 | * can be restored after vunmapbuf. This is truely rude, we | |
591 | * should really be storing this in a field in the buf struct | |
592 | * but none are available and I didn't want to add one at | |
593 | * this time. Note that b_addr for dirty page pushes is | |
594 | * restored in vunmapbuf. (ugh!) | |
595 | */ | |
596 | baddr = bp->b_un.b_addr; | |
597 | vmapbuf(bp); | |
3a20b539 BJ |
598 | (*strat)(bp); |
599 | /* pageout daemon doesn't wait for pushed pages */ | |
600 | if (bp->b_flags & B_DIRTY) | |
601 | return; | |
4bd1c0bf | 602 | s = splbio(); |
3a20b539 BJ |
603 | while ((bp->b_flags & B_DONE) == 0) |
604 | sleep((caddr_t)bp, prio); | |
605 | splx(s); | |
4bd1c0bf WN |
606 | vunmapbuf(bp); |
607 | bp->b_un.b_addr = baddr; | |
3a20b539 BJ |
608 | } |
609 | ||
610 | initcpu() | |
611 | { | |
3a20b539 BJ |
612 | } |
613 | ||
614 | /* | |
615 | * Clear registers on exec | |
616 | */ | |
af359dea C |
617 | setregs(p, entry) |
618 | struct proc *p; | |
3a20b539 BJ |
619 | u_long entry; |
620 | { | |
621 | ||
af359dea C |
622 | p->p_regs[sEBP] = 0; /* bottom of the fp chain */ |
623 | p->p_regs[sEIP] = entry; | |
2313b06b | 624 | |
af359dea | 625 | p->p_addr->u_pcb.pcb_flags = 0; /* no fp at all */ |
2313b06b WN |
626 | load_cr0(rcr0() | CR0_EM); /* start emulating */ |
627 | #ifdef NPX | |
628 | npxinit(0x262); | |
629 | #endif | |
4bd1c0bf WN |
630 | } |
631 | ||
632 | /* | |
633 | * Initialize 386 and configure to run kernel | |
634 | */ | |
635 | ||
636 | /* | |
637 | * Initialize segments & interrupt table | |
638 | */ | |
639 | ||
640 | ||
641 | #define GNULL_SEL 0 /* Null Descriptor */ | |
642 | #define GCODE_SEL 1 /* Kernel Code Descriptor */ | |
643 | #define GDATA_SEL 2 /* Kernel Data Descriptor */ | |
644 | #define GLDT_SEL 3 /* LDT - eventually one per process */ | |
645 | #define GTGATE_SEL 4 /* Process task switch gate */ | |
646 | #define GPANIC_SEL 5 /* Task state to consider panic from */ | |
647 | #define GPROC0_SEL 6 /* Task state process slot zero and up */ | |
af359dea | 648 | #define NGDT GPROC0_SEL+1 |
4bd1c0bf | 649 | |
af359dea | 650 | union descriptor gdt[GPROC0_SEL+1]; |
4bd1c0bf WN |
651 | |
652 | /* interrupt descriptor table */ | |
653 | struct gate_descriptor idt[32+16]; | |
654 | ||
655 | /* local descriptor table */ | |
656 | union descriptor ldt[5]; | |
657 | #define LSYS5CALLS_SEL 0 /* forced by intel BCS */ | |
658 | #define LSYS5SIGR_SEL 1 | |
659 | ||
660 | #define L43BSDCALLS_SEL 2 /* notyet */ | |
661 | #define LUCODE_SEL 3 | |
662 | #define LUDATA_SEL 4 | |
663 | /* seperate stack, es,fs,gs sels ? */ | |
664 | /* #define LPOSIXCALLS_SEL 5 /* notyet */ | |
665 | ||
af359dea C |
666 | struct i386tss tss, panic_tss; |
667 | ||
668 | extern struct user *proc0paddr; | |
4bd1c0bf WN |
669 | |
670 | /* software prototypes -- in more palitable form */ | |
671 | struct soft_segment_descriptor gdt_segs[] = { | |
672 | /* Null Descriptor */ | |
673 | { 0x0, /* segment base address */ | |
674 | 0x0, /* length - all address space */ | |
675 | 0, /* segment type */ | |
676 | 0, /* segment descriptor priority level */ | |
677 | 0, /* segment descriptor present */ | |
678 | 0,0, | |
679 | 0, /* default 32 vs 16 bit size */ | |
680 | 0 /* limit granularity (byte/page units)*/ }, | |
681 | /* Code Descriptor for kernel */ | |
682 | { 0x0, /* segment base address */ | |
683 | 0xfffff, /* length - all address space */ | |
684 | SDT_MEMERA, /* segment type */ | |
685 | 0, /* segment descriptor priority level */ | |
686 | 1, /* segment descriptor present */ | |
687 | 0,0, | |
688 | 1, /* default 32 vs 16 bit size */ | |
689 | 1 /* limit granularity (byte/page units)*/ }, | |
690 | /* Data Descriptor for kernel */ | |
691 | { 0x0, /* segment base address */ | |
692 | 0xfffff, /* length - all address space */ | |
693 | SDT_MEMRWA, /* segment type */ | |
694 | 0, /* segment descriptor priority level */ | |
695 | 1, /* segment descriptor present */ | |
696 | 0,0, | |
697 | 1, /* default 32 vs 16 bit size */ | |
698 | 1 /* limit granularity (byte/page units)*/ }, | |
699 | /* LDT Descriptor */ | |
700 | { (int) ldt, /* segment base address */ | |
701 | sizeof(ldt)-1, /* length - all address space */ | |
702 | SDT_SYSLDT, /* segment type */ | |
703 | 0, /* segment descriptor priority level */ | |
704 | 1, /* segment descriptor present */ | |
705 | 0,0, | |
706 | 0, /* unused - default 32 vs 16 bit size */ | |
707 | 0 /* limit granularity (byte/page units)*/ }, | |
708 | /* Null Descriptor - Placeholder */ | |
709 | { 0x0, /* segment base address */ | |
710 | 0x0, /* length - all address space */ | |
711 | 0, /* segment type */ | |
712 | 0, /* segment descriptor priority level */ | |
713 | 0, /* segment descriptor present */ | |
714 | 0,0, | |
715 | 0, /* default 32 vs 16 bit size */ | |
716 | 0 /* limit granularity (byte/page units)*/ }, | |
717 | /* Panic Tss Descriptor */ | |
af359dea C |
718 | { (int) &panic_tss, /* segment base address */ |
719 | sizeof(tss)-1, /* length - all address space */ | |
720 | SDT_SYS386TSS, /* segment type */ | |
721 | 0, /* segment descriptor priority level */ | |
722 | 1, /* segment descriptor present */ | |
723 | 0,0, | |
724 | 0, /* unused - default 32 vs 16 bit size */ | |
725 | 0 /* limit granularity (byte/page units)*/ }, | |
726 | /* Proc 0 Tss Descriptor */ | |
727 | { (int) kstack, /* segment base address */ | |
4bd1c0bf WN |
728 | sizeof(tss)-1, /* length - all address space */ |
729 | SDT_SYS386TSS, /* segment type */ | |
730 | 0, /* segment descriptor priority level */ | |
731 | 1, /* segment descriptor present */ | |
732 | 0,0, | |
733 | 0, /* unused - default 32 vs 16 bit size */ | |
734 | 0 /* limit granularity (byte/page units)*/ }}; | |
735 | ||
736 | struct soft_segment_descriptor ldt_segs[] = { | |
737 | /* Null Descriptor - overwritten by call gate */ | |
738 | { 0x0, /* segment base address */ | |
739 | 0x0, /* length - all address space */ | |
740 | 0, /* segment type */ | |
741 | 0, /* segment descriptor priority level */ | |
742 | 0, /* segment descriptor present */ | |
743 | 0,0, | |
744 | 0, /* default 32 vs 16 bit size */ | |
745 | 0 /* limit granularity (byte/page units)*/ }, | |
746 | /* Null Descriptor - overwritten by call gate */ | |
747 | { 0x0, /* segment base address */ | |
748 | 0x0, /* length - all address space */ | |
749 | 0, /* segment type */ | |
750 | 0, /* segment descriptor priority level */ | |
751 | 0, /* segment descriptor present */ | |
752 | 0,0, | |
753 | 0, /* default 32 vs 16 bit size */ | |
754 | 0 /* limit granularity (byte/page units)*/ }, | |
755 | /* Null Descriptor - overwritten by call gate */ | |
756 | { 0x0, /* segment base address */ | |
757 | 0x0, /* length - all address space */ | |
758 | 0, /* segment type */ | |
759 | 0, /* segment descriptor priority level */ | |
760 | 0, /* segment descriptor present */ | |
761 | 0,0, | |
762 | 0, /* default 32 vs 16 bit size */ | |
763 | 0 /* limit granularity (byte/page units)*/ }, | |
764 | /* Code Descriptor for user */ | |
765 | { 0x0, /* segment base address */ | |
766 | 0xfffff, /* length - all address space */ | |
767 | SDT_MEMERA, /* segment type */ | |
768 | SEL_UPL, /* segment descriptor priority level */ | |
769 | 1, /* segment descriptor present */ | |
770 | 0,0, | |
771 | 1, /* default 32 vs 16 bit size */ | |
772 | 1 /* limit granularity (byte/page units)*/ }, | |
773 | /* Data Descriptor for user */ | |
774 | { 0x0, /* segment base address */ | |
775 | 0xfffff, /* length - all address space */ | |
776 | SDT_MEMRWA, /* segment type */ | |
777 | SEL_UPL, /* segment descriptor priority level */ | |
778 | 1, /* segment descriptor present */ | |
779 | 0,0, | |
780 | 1, /* default 32 vs 16 bit size */ | |
781 | 1 /* limit granularity (byte/page units)*/ } }; | |
782 | ||
783 | /* table descriptors - used to load tables by microp */ | |
784 | struct region_descriptor r_gdt = { | |
785 | sizeof(gdt)-1,(char *)gdt | |
786 | }; | |
787 | ||
788 | struct region_descriptor r_idt = { | |
789 | sizeof(idt)-1,(char *)idt | |
790 | }; | |
791 | ||
3a0e7e3d | 792 | setidt(idx, func, typ, dpl) char *func; { |
4bd1c0bf WN |
793 | struct gate_descriptor *ip = idt + idx; |
794 | ||
795 | ip->gd_looffset = (int)func; | |
796 | ip->gd_selector = 8; | |
797 | ip->gd_stkcpy = 0; | |
798 | ip->gd_xx = 0; | |
799 | ip->gd_type = typ; | |
3a0e7e3d | 800 | ip->gd_dpl = dpl; |
4bd1c0bf WN |
801 | ip->gd_p = 1; |
802 | ip->gd_hioffset = ((int)func)>>16 ; | |
803 | } | |
804 | ||
af359dea | 805 | #define IDTVEC(name) __CONCAT(X, name) |
9c09b4f2 BJ |
806 | extern IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl), |
807 | IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm), | |
808 | IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot), | |
809 | IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(rsvd0), | |
810 | IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4), | |
811 | IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8), | |
812 | IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12), | |
813 | IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(rsvd14), IDTVEC(syscall); | |
4bd1c0bf WN |
814 | |
815 | int lcr0(), lcr3(), rcr0(), rcr2(); | |
816 | int _udatasel, _ucodesel, _gsel_tss; | |
817 | ||
eb5ba828 | 818 | init386(first) { extern ssdtosd(), lgdt(), lidt(), lldt(), etext; |
4bd1c0bf | 819 | int x, *pi; |
af359dea | 820 | unsigned biosbasemem, biosextmem; |
4bd1c0bf | 821 | struct gate_descriptor *gdp; |
af359dea C |
822 | extern int sigcode,szsigcode; |
823 | ||
824 | proc0.p_addr = proc0paddr; | |
825 | ||
826 | /* | |
827 | * Initialize the console before we print anything out. | |
828 | */ | |
829 | ||
830 | cninit (KERNBASE+0xa0000); | |
4bd1c0bf WN |
831 | |
832 | /* make gdt memory segments */ | |
833 | gdt_segs[GCODE_SEL].ssd_limit = btoc((int) &etext + NBPG); | |
af359dea | 834 | for (x=0; x < NGDT; x++) ssdtosd(gdt_segs+x, gdt+x); |
4bd1c0bf | 835 | /* make ldt memory segments */ |
af359dea C |
836 | ldt_segs[LUCODE_SEL].ssd_limit = btoc(UPT_MIN_ADDRESS); |
837 | ldt_segs[LUDATA_SEL].ssd_limit = btoc(UPT_MIN_ADDRESS); | |
838 | /* Note. eventually want private ldts per process */ | |
9c09b4f2 | 839 | for (x=0; x < 5; x++) ssdtosd(ldt_segs+x, ldt+x); |
4bd1c0bf | 840 | |
af359dea | 841 | /* exceptions */ |
3a0e7e3d DA |
842 | setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL); |
843 | setidt(1, &IDTVEC(dbg), SDT_SYS386TGT, SEL_KPL); | |
844 | setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL); | |
9c09b4f2 | 845 | setidt(3, &IDTVEC(bpt), SDT_SYS386TGT, SEL_UPL); |
3a0e7e3d DA |
846 | setidt(4, &IDTVEC(ofl), SDT_SYS386TGT, SEL_KPL); |
847 | setidt(5, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL); | |
848 | setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL); | |
849 | setidt(7, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL); | |
850 | setidt(8, &IDTVEC(dble), SDT_SYS386TGT, SEL_KPL); | |
851 | setidt(9, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL); | |
852 | setidt(10, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL); | |
853 | setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL); | |
854 | setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL); | |
855 | setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL); | |
856 | setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL); | |
857 | setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL); | |
858 | setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL); | |
859 | setidt(17, &IDTVEC(rsvd0), SDT_SYS386TGT, SEL_KPL); | |
860 | setidt(18, &IDTVEC(rsvd1), SDT_SYS386TGT, SEL_KPL); | |
861 | setidt(19, &IDTVEC(rsvd2), SDT_SYS386TGT, SEL_KPL); | |
862 | setidt(20, &IDTVEC(rsvd3), SDT_SYS386TGT, SEL_KPL); | |
863 | setidt(21, &IDTVEC(rsvd4), SDT_SYS386TGT, SEL_KPL); | |
864 | setidt(22, &IDTVEC(rsvd5), SDT_SYS386TGT, SEL_KPL); | |
865 | setidt(23, &IDTVEC(rsvd6), SDT_SYS386TGT, SEL_KPL); | |
866 | setidt(24, &IDTVEC(rsvd7), SDT_SYS386TGT, SEL_KPL); | |
867 | setidt(25, &IDTVEC(rsvd8), SDT_SYS386TGT, SEL_KPL); | |
868 | setidt(26, &IDTVEC(rsvd9), SDT_SYS386TGT, SEL_KPL); | |
869 | setidt(27, &IDTVEC(rsvd10), SDT_SYS386TGT, SEL_KPL); | |
870 | setidt(28, &IDTVEC(rsvd11), SDT_SYS386TGT, SEL_KPL); | |
871 | setidt(29, &IDTVEC(rsvd12), SDT_SYS386TGT, SEL_KPL); | |
872 | setidt(30, &IDTVEC(rsvd13), SDT_SYS386TGT, SEL_KPL); | |
873 | setidt(31, &IDTVEC(rsvd14), SDT_SYS386TGT, SEL_KPL); | |
4bd1c0bf | 874 | |
9c09b4f2 BJ |
875 | #include "isa.h" |
876 | #if NISA >0 | |
877 | isa_defaultirq(); | |
878 | #endif | |
4bd1c0bf WN |
879 | |
880 | lgdt(gdt, sizeof(gdt)-1); | |
881 | lidt(idt, sizeof(idt)-1); | |
882 | lldt(GSEL(GLDT_SEL, SEL_KPL)); | |
883 | ||
af359dea C |
884 | #ifdef notyet |
885 | /* determine amount of memory present so we can scale kernel PT */ | |
886 | for (i= RAM_BEGIN; i < IOM_BEGIN; i += NBPG) | |
887 | if (probemem(i) == 0) break; | |
888 | if (i == IOM_BEGIN) { | |
889 | if (maxphysmem == 0) maxphysmem = RAM_END; | |
890 | for (i= IOM_END; i < maxphysmem; i += NBPG) | |
891 | if (probemem(i) == 0) break; | |
892 | } | |
893 | maxmem = i / NBPG; | |
894 | #else | |
895 | Maxmem = 8192 *1024 /NBPG; | |
896 | maxmem = Maxmem; | |
897 | #endif | |
898 | ||
899 | /* reconcile against BIOS's recorded values in RTC | |
900 | * we trust neither of them, as both can lie! | |
901 | */ | |
902 | biosbasemem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8); | |
903 | biosextmem = rtcin(RTC_EXTLO)+ (rtcin(RTC_EXTHI)<<8); | |
904 | if (biosbasemem == 0xffff || biosextmem == 0xffff) { | |
905 | if (maxmem > 0xffc) | |
906 | maxmem = 640/4; | |
907 | } else if (biosextmem > 0 && biosbasemem == 640) { | |
908 | int totbios = (biosbasemem + 0x60000 + biosextmem)/4; | |
909 | if (totbios < maxmem) maxmem = totbios; | |
910 | } else maxmem = 640/4; | |
911 | maxmem = maxmem-1; | |
912 | physmem = maxmem - (0x100 -0xa0); | |
913 | ||
914 | /* call pmap initialization to make new kernel address space */ | |
915 | pmap_bootstrap (first, 0); | |
916 | /* now running on new page tables, configured,and u/iom is accessible */ | |
4bd1c0bf WN |
917 | |
918 | /* make a initial tss so microp can get interrupt stack on syscall! */ | |
af359dea C |
919 | proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) kstack + UPAGES*NBPG; |
920 | proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ; | |
921 | _gsel_tss = GSEL(GPROC0_SEL, SEL_KPL); | |
4bd1c0bf WN |
922 | ltr(_gsel_tss); |
923 | ||
924 | /* make a call gate to reenter kernel with */ | |
925 | gdp = &ldt[LSYS5CALLS_SEL].gd; | |
926 | ||
927 | x = (int) &IDTVEC(syscall); | |
928 | gdp->gd_looffset = x++; | |
929 | gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL); | |
930 | gdp->gd_stkcpy = 0; | |
931 | gdp->gd_type = SDT_SYS386CGT; | |
932 | gdp->gd_dpl = SEL_UPL; | |
933 | gdp->gd_p = 1; | |
934 | gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16; | |
935 | ||
936 | /* transfer to user mode */ | |
937 | ||
938 | _ucodesel = LSEL(LUCODE_SEL, SEL_UPL); | |
939 | _udatasel = LSEL(LUDATA_SEL, SEL_UPL); | |
af359dea C |
940 | |
941 | /* setup proc 0's pcb */ | |
942 | bcopy(&sigcode, proc0.p_addr->u_pcb.pcb_sigc, szsigcode); | |
943 | proc0.p_addr->u_pcb.pcb_flags = 0; | |
944 | proc0.p_addr->u_pcb.pcb_ptd = IdlePTD; | |
4bd1c0bf WN |
945 | } |
946 | ||
af359dea C |
947 | extern struct pte *CMAP1, *CMAP2; |
948 | extern caddr_t CADDR1, CADDR2; | |
4bd1c0bf WN |
949 | /* |
950 | * zero out physical memory | |
951 | * specified in relocation units (NBPG bytes) | |
952 | */ | |
953 | clearseg(n) { | |
4bd1c0bf | 954 | |
af359dea C |
955 | *(int *)CMAP2 = PG_V | PG_KW | ctob(n); |
956 | load_cr3(rcr3()); | |
957 | bzero(CADDR2,NBPG); | |
958 | *(int *) CADDR2 = 0; | |
4bd1c0bf WN |
959 | } |
960 | ||
961 | /* | |
962 | * copy a page of physical memory | |
963 | * specified in relocation units (NBPG bytes) | |
964 | */ | |
965 | copyseg(frm, n) { | |
4bd1c0bf | 966 | |
af359dea C |
967 | *(int *)CMAP2 = PG_V | PG_KW | ctob(n); |
968 | load_cr3(rcr3()); | |
969 | bcopy((void *)frm, (void *)CADDR2, NBPG); | |
4bd1c0bf WN |
970 | } |
971 | ||
af359dea C |
972 | /* |
973 | * copy a page of physical memory | |
974 | * specified in relocation units (NBPG bytes) | |
975 | */ | |
976 | physcopyseg(frm, to) { | |
977 | ||
978 | *(int *)CMAP1 = PG_V | PG_KW | ctob(frm); | |
979 | *(int *)CMAP2 = PG_V | PG_KW | ctob(to); | |
980 | load_cr3(rcr3()); | |
981 | bcopy(CADDR1, CADDR2, NBPG); | |
4bd1c0bf WN |
982 | } |
983 | ||
af359dea C |
984 | /*aston() { |
985 | schednetisr(NETISR_AST); | |
986 | }*/ | |
987 | ||
2313b06b WN |
988 | setsoftclock() { |
989 | schednetisr(NETISR_SCLK); | |
990 | } | |
991 | ||
4bd1c0bf WN |
992 | /* |
993 | * insert an element into a queue | |
994 | */ | |
995 | #undef insque | |
996 | _insque(element, head) | |
997 | register struct prochd *element, *head; | |
998 | { | |
999 | element->ph_link = head->ph_link; | |
1000 | head->ph_link = (struct proc *)element; | |
1001 | element->ph_rlink = (struct proc *)head; | |
1002 | ((struct prochd *)(element->ph_link))->ph_rlink=(struct proc *)element; | |
1003 | } | |
1004 | ||
1005 | /* | |
1006 | * remove an element from a queue | |
1007 | */ | |
1008 | #undef remque | |
1009 | _remque(element) | |
1010 | register struct prochd *element; | |
1011 | { | |
1012 | ((struct prochd *)(element->ph_link))->ph_rlink = element->ph_rlink; | |
1013 | ((struct prochd *)(element->ph_rlink))->ph_link = element->ph_link; | |
1014 | element->ph_rlink = (struct proc *)0; | |
1015 | } | |
1016 | ||
1017 | vmunaccess() {} | |
1018 | ||
1019 | /* | |
1020 | * Below written in C to allow access to debugging code | |
1021 | */ | |
af359dea C |
1022 | copyinstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength; |
1023 | void *toaddr, *fromaddr; { | |
1024 | u_int c,tally; | |
4bd1c0bf | 1025 | |
3a0e7e3d | 1026 | tally = 0; |
4bd1c0bf WN |
1027 | while (maxlength--) { |
1028 | c = fubyte(fromaddr++); | |
3a0e7e3d DA |
1029 | if (c == -1) { |
1030 | if(lencopied) *lencopied = tally; | |
1031 | return(EFAULT); | |
1032 | } | |
1033 | tally++; | |
af359dea | 1034 | *(char *)toaddr++ = (char) c; |
4bd1c0bf | 1035 | if (c == 0){ |
3a0e7e3d DA |
1036 | if(lencopied) *lencopied = tally; |
1037 | return(0); | |
1038 | } | |
4bd1c0bf | 1039 | } |
3a0e7e3d | 1040 | if(lencopied) *lencopied = tally; |
2313b06b | 1041 | return(ENAMETOOLONG); |
4bd1c0bf WN |
1042 | } |
1043 | ||
af359dea C |
1044 | copyoutstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength; |
1045 | void *fromaddr, *toaddr; { | |
4bd1c0bf | 1046 | int c; |
3a0e7e3d | 1047 | int tally; |
4bd1c0bf | 1048 | |
3a0e7e3d | 1049 | tally = 0; |
4bd1c0bf | 1050 | while (maxlength--) { |
af359dea | 1051 | c = subyte(toaddr++, *(char *)fromaddr); |
4bd1c0bf | 1052 | if (c == -1) return(EFAULT); |
3a0e7e3d | 1053 | tally++; |
af359dea | 1054 | if (*(char *)fromaddr++ == 0){ |
3a0e7e3d | 1055 | if(lencopied) *lencopied = tally; |
4bd1c0bf | 1056 | return(0); |
3a0e7e3d | 1057 | } |
4bd1c0bf | 1058 | } |
3a0e7e3d | 1059 | if(lencopied) *lencopied = tally; |
2313b06b | 1060 | return(ENAMETOOLONG); |
4bd1c0bf WN |
1061 | } |
1062 | ||
af359dea C |
1063 | copystr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength; |
1064 | void *fromaddr, *toaddr; { | |
1065 | u_int tally; | |
4bd1c0bf | 1066 | |
3a0e7e3d | 1067 | tally = 0; |
4bd1c0bf | 1068 | while (maxlength--) { |
af359dea | 1069 | *(u_char *)toaddr = *(u_char *)fromaddr++; |
3a0e7e3d | 1070 | tally++; |
af359dea | 1071 | if (*(u_char *)toaddr++ == 0) { |
3a0e7e3d | 1072 | if(lencopied) *lencopied = tally; |
4bd1c0bf | 1073 | return(0); |
3a0e7e3d | 1074 | } |
4bd1c0bf | 1075 | } |
3a0e7e3d | 1076 | if(lencopied) *lencopied = tally; |
2313b06b | 1077 | return(ENAMETOOLONG); |
3a20b539 | 1078 | } |