1 /*
2 * Copyright (c) 1982,1987,1988 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
6 * @(#)machdep.c 7.16 (Berkeley) 07/12/92
7 */
8
9 #include "sys/param.h"
10 #include "sys/systm.h"
11 #include "sys/user.h"
12 #include "sys/kernel.h"
13 #include "sys/map.h"
14 #include "sys/vm.h"
15 #include "sys/proc.h"
16 #include "sys/buf.h"
17 #include "sys/reboot.h"
18 #include "sys/conf.h"
19 #include "sys/file.h"
20 #include "sys/text.h"
21 #include "sys/clist.h"
22 #include "sys/callout.h"
23 #include "sys/cmap.h"
24 #include "sys/malloc.h"
25 #include "sys/mbuf.h"
26 #include "sys/msgbuf.h"
27 #ifdef SYSVSHM
28 #include "sys/shm.h"
29 #endif
30
31 #include "../include/cpu.h"
32 #include "../include/reg.h"
33 #include "../include/pte.h"
34 #include "../include/psl.h"
35 #include "mem.h"
36 #include "../include/mtpr.h"
37 #include "cp.h"
38
39 #include "../vba/vbavar.h"
40
41 /*
42 * Declare these as initialized data so we can patch them.
43 */
44 int nswbuf = 0;
45 #ifdef NBUF
46 int nbuf = NBUF;
47 #else
48 int nbuf = 0;
49 #endif
50 #ifdef BUFPAGES
51 int bufpages = BUFPAGES;
52 #else
53 int bufpages = 0;
54 #endif
55 #include "yc.h"
56 #if NCY > 0
57 #include "../vba/cyreg.h"
58 #endif
59 int msgbufmapped; /* set when safe to use msgbuf */
60 int physmem = MAXMEM; /* max supported memory, changes to actual */
61 /*
62 * safepri is a safe priority for sleep to set for a spin-wait
63 * during autoconfiguration or after a panic. On the tahoe, this must
64 * be > 0 so that we can take interrupts after a panic while on the interrupt
65 * stack. Otherwise, we will get a illegal instruction trap when we return
66 * from any interrupt that comes in.
67 */
68 int safepri = 1;
69
70 /*
71 * Machine-dependent startup code
72 */
startup(firstaddr)73 startup(firstaddr)
74 int firstaddr;
75 {
76 register int unixsize;
77 register unsigned i;
78 register struct pte *pte;
79 int mapaddr, j;
80 register caddr_t v;
81 int maxbufs, base, residual;
82
83 /*
84 * Initialize error message buffer (at end of core).
85 */
86 maxmem = physmem - btoc(sizeof (struct msgbuf));
87 pte = msgbufmap;
88 for (i = 1; i < btoc(sizeof (struct msgbuf)) + 1; i++)
89 *(int *)pte++ = PG_V | PG_KW | (physmem - i);
90 mtpr(TBIA, 1);
91 msgbufmapped = 1;
92 #ifdef KADB
93 kdb_init(); /* startup kernel debugger */
94 (void) cnopen(makedev(0, 1), 0); /* open console XXX */
95 #endif
96 /*
97 * Good {morning,afternoon,evening,night}.
98 */
99 printf(version);
100 printf("real mem = %d\n", ctob(physmem));
101
102 /*
103 * Allocate space for system data structures.
104 * The first available real memory address is in "firstaddr".
105 * The first available kernel virtual address is in "v".
106 * As pages of kernel virtual memory are allocated, "v" is incremented.
107 * As pages of memory are allocated and cleared,
108 * "firstaddr" is incremented.
109 * An index into the kernel page table corresponding to the
110 * virtual memory address maintained in "v" is kept in "mapaddr".
111 */
112 v = (caddr_t)(0xc0000000 | (firstaddr * NBPG));
113 #define valloc(name, type, num) \
114 (name) = (type *)v; v = (caddr_t)((name)+(num))
115 #define valloclim(name, type, num, lim) \
116 (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
117 #if NCY > 0
118 /*
119 * Allocate raw buffers for tapemaster controllers
120 * first, as they need buffers in the first megabyte.
121 */
122 valloc(cybuf, char, NCY * CYMAXIO);
123 #endif
124 valloclim(file, struct file, nfile, fileNFILE);
125 valloclim(proc, struct proc, nproc, procNPROC);
126 valloclim(text, struct text, ntext, textNTEXT);
127 valloc(cfree, struct cblock, nclist);
128 valloc(callout, struct callout, ncallout);
129 valloc(swapmap, struct map, nswapmap = nproc * 2);
130 valloc(argmap, struct map, ARGMAPSIZE);
131 valloc(kernelmap, struct map, nproc);
132 valloc(mbmap, struct map, nmbclusters/4);
133 valloc(kmemmap, struct map, ekmempt - kmempt);
134 valloc(kmemusage, struct kmemusage, ekmempt - kmempt);
135 #ifdef SYSVSHM
136 valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
137 #endif
138
139 /*
140 * Determine how many buffers to allocate.
141 * Use 10% of memory for the first 2 Meg, 5% of the remaining
142 * memory. Insure a minimum of 16 buffers.
143 * We allocate 1/2 as many swap buffer headers as file i/o buffers.
144 */
145 if (bufpages == 0)
146 if (physmem < (2 * 1024 * 1024))
147 bufpages = physmem / 10 / CLSIZE;
148 else
149 bufpages = ((2 * 1024 * 1024 + physmem) / 20) / CLSIZE;
150 if (nbuf == 0) {
151 nbuf = bufpages / 2;
152 if (nbuf < 16)
153 nbuf = 16;
154 }
155 if (nswbuf == 0) {
156 nswbuf = (nbuf / 2) &~ 1; /* force even */
157 if (nswbuf > 256)
158 nswbuf = 256; /* sanity */
159 }
160 valloc(swbuf, struct buf, nswbuf);
161
162 /*
163 * Now the amount of virtual memory remaining for buffers
164 * can be calculated, estimating needs for the cmap.
165 */
166 ncmap = (maxmem*NBPG - ((int)v &~ 0xc0000000)) /
167 (CLBYTES + sizeof(struct cmap)) + 2;
168 maxbufs = ((SYSPTSIZE * NBPG) -
169 ((int)(v + ncmap * sizeof(struct cmap)) - 0xc0000000)) /
170 (MAXBSIZE + sizeof(struct buf));
171 if (maxbufs < 16)
172 panic("sys pt too small");
173 if (nbuf > maxbufs) {
174 printf("SYSPTSIZE limits number of buffers to %d\n", maxbufs);
175 nbuf = maxbufs;
176 }
177 if (bufpages > nbuf * (MAXBSIZE / CLBYTES))
178 bufpages = nbuf * (MAXBSIZE / CLBYTES);
179 valloc(buf, struct buf, nbuf);
180
181 /*
182 * Allocate space for core map.
183 * Allow space for all of phsical memory minus the amount
184 * dedicated to the system. The amount of physical memory
185 * dedicated to the system is the total virtual memory of
186 * the system thus far, plus core map, buffer pages,
187 * and buffer headers not yet allocated.
188 * Add 2: 1 because the 0th entry is unused, 1 for rounding.
189 */
190 ncmap = (maxmem*NBPG - ((int)(v + bufpages*CLBYTES) &~ 0xc0000000)) /
191 (CLBYTES + sizeof(struct cmap)) + 2;
192 valloclim(cmap, struct cmap, ncmap, ecmap);
193
194 /*
195 * Clear space allocated thus far, and make r/w entries
196 * for the space in the kernel map.
197 */
198 unixsize = btoc((int)v &~ 0xc0000000);
199 while (firstaddr < unixsize) {
200 *(int *)(&Sysmap[firstaddr]) = PG_V | PG_KW | firstaddr;
201 clearseg((unsigned)firstaddr);
202 firstaddr++;
203 }
204
205 /*
206 * Now allocate buffers proper. They are different than the above
207 * in that they usually occupy more virtual memory than physical.
208 */
209 v = (caddr_t) ((int)(v + PGOFSET) &~ PGOFSET);
210 valloc(buffers, char, MAXBSIZE * nbuf);
211 base = bufpages / nbuf;
212 residual = bufpages % nbuf;
213 mapaddr = firstaddr;
214 for (i = 0; i < residual; i++) {
215 for (j = 0; j < (base + 1) * CLSIZE; j++) {
216 *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr;
217 clearseg((unsigned)firstaddr);
218 firstaddr++;
219 }
220 mapaddr += MAXBSIZE / NBPG;
221 }
222 for (i = residual; i < nbuf; i++) {
223 for (j = 0; j < base * CLSIZE; j++) {
224 *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr;
225 clearseg((unsigned)firstaddr);
226 firstaddr++;
227 }
228 mapaddr += MAXBSIZE / NBPG;
229 }
230
231 unixsize = btoc((int)v &~ 0xc0000000);
232 if (firstaddr >= physmem - 8*UPAGES)
233 panic("no memory");
234 mtpr(TBIA, 1); /* After we just cleared it all! */
235
236 /*
237 * Initialize callouts
238 */
239 callfree = callout;
240 for (i = 1; i < ncallout; i++)
241 callout[i-1].c_next = &callout[i];
242
243 /*
244 * Initialize memory allocator and swap
245 * and user page table maps.
246 *
247 * THE USER PAGE TABLE MAP IS CALLED ``kernelmap''
248 * WHICH IS A VERY UNDESCRIPTIVE AND INCONSISTENT NAME.
249 */
250 meminit(firstaddr, maxmem);
251 maxmem = freemem;
252 printf("avail mem = %d\n", ctob(maxmem));
253 printf("using %d buffers containing %d bytes of memory\n",
254 nbuf, bufpages * CLBYTES);
255 rminit(kernelmap, (long)USRPTSIZE, (long)1,
256 "usrpt", nproc);
257 rminit(mbmap, (long)(nmbclusters * CLSIZE), (long)CLSIZE,
258 "mbclusters", nmbclusters/4);
259 kmeminit(); /* now safe to do malloc/free */
260 intenable = 1; /* Enable interrupts from now on */
261
262 /*
263 * Set up CPU-specific registers, cache, etc.
264 */
265 initcpu();
266
267 /*
268 * Set up buffers, so they can be used to read disk labels.
269 */
270 bhinit();
271 binit();
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*/
vmtime(otime,olbolt,oicr)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
297 /*
298 * Send an interrupt to process.
299 *
300 * Stack is set up to allow sigcode stored
301 * in u. to call routine, followed by kcall
302 * to sigreturn routine below. After sigreturn
303 * resets the signal mask, the stack, and the
304 * frame pointer, it returns to the user
305 * specified pc, psl.
306 */
sendsig(catcher,sig,mask,code)307 sendsig(catcher, sig, mask, code)
308 sig_t catcher;
309 int sig, mask;
310 unsigned code;
311 {
312 register struct sigcontext *scp;
313 register struct proc *p = u.u_procp;
314 register int *regs;
315 register struct sigframe {
316 int sf_signum;
317 int sf_code;
318 struct sigcontext *sf_scp;
319 sig_t sf_handler;
320 int sf_regs[6]; /* r0-r5 */
321 struct sigcontext *sf_scpcopy;
322 } *fp;
323 int oonstack;
324
325 regs = u.u_ar0;
326 oonstack = u.u_onstack;
327 /*
328 * Allocate and validate space for the signal handler
329 * context. Note that if the stack is in P0 space, the
330 * call to grow() is a nop, and the useracc() check
331 * will fail if the process has not already allocated
332 * the space with a `brk'.
333 */
334 if (!u.u_onstack && (u.u_sigonstack & sigmask(sig))) {
335 scp = (struct sigcontext *)u.u_sigsp - 1;
336 u.u_onstack = 1;
337 } else
338 scp = (struct sigcontext *)regs[SP] - 1;
339 fp = (struct sigframe *)scp - 1;
340 if ((int)fp <= USRSTACK - ctob(u.u_ssize))
341 (void) grow((unsigned)fp);
342 if (useracc((caddr_t)fp, sizeof (*fp) + sizeof (*scp), B_WRITE) == 0) {
343 /*
344 * Process has trashed its stack; give it an illegal
345 * instruction to halt it in its tracks.
346 */
347 SIGACTION(p, SIGILL) = SIG_DFL;
348 sig = sigmask(SIGILL);
349 p->p_sigignore &= ~sig;
350 p->p_sigcatch &= ~sig;
351 p->p_sigmask &= ~sig;
352 psignal(p, SIGILL);
353 return;
354 }
355 /*
356 * Build the argument list for the signal handler.
357 */
358 fp->sf_signum = sig;
359 fp->sf_code = code;
360 fp->sf_scp = scp;
361 fp->sf_handler = catcher;
362 /*
363 * Build the callf argument frame to be used to call sigreturn.
364 */
365 fp->sf_scpcopy = scp;
366 /*
367 * Build the signal context to be used by sigreturn.
368 */
369 scp->sc_onstack = oonstack;
370 scp->sc_mask = mask;
371 scp->sc_sp = regs[SP];
372 scp->sc_fp = regs[FP];
373 scp->sc_pc = regs[PC];
374 scp->sc_ps = regs[PS];
375 regs[SP] = (int)fp;
376 regs[PC] = (int)u.u_pcb.pcb_sigc;
377 }
378
379 /*
380 * System call to cleanup state after a signal
381 * has been taken. Reset signal mask and
382 * stack state from context left by sendsig (above).
383 * Return to previous pc and psl as specified by
384 * context left by sendsig. Check carefully to
385 * make sure that the user has not modified the
386 * psl to gain improper priviledges or to cause
387 * a machine fault.
388 */
389 struct sigreturn_args {
390 struct sigcontext *sigcntxp;
391 };
392 /* ARGSUSED */
393 sigreturn(p, uap, retval)
394 struct proc *p;
395 struct sigreturn_args *uap;
396 int *retval;
397 {
398 register struct sigcontext *scp;
399 register int *regs = u.u_ar0;
400
401 scp = uap->sigcntxp;
402 if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0)
403 return (EINVAL);
404 if ((scp->sc_ps & (PSL_MBZ|PSL_IPL|PSL_IS)) != 0 ||
405 (scp->sc_ps & (PSL_PRVMOD|PSL_CURMOD)) != (PSL_PRVMOD|PSL_CURMOD))
406 return (EINVAL);
407 u.u_onstack = scp->sc_onstack & 01;
408 p->p_sigmask = scp->sc_mask &~ sigcantmask;
409 regs[FP] = scp->sc_fp;
410 regs[SP] = scp->sc_sp;
411 regs[PC] = scp->sc_pc;
412 regs[PS] = scp->sc_ps;
413 return (EJUSTRETURN);
414 }
415
416 int waittime = -1;
417
boot(arghowto)418 boot(arghowto)
419 int arghowto;
420 {
421 register long dummy; /* r12 is reserved */
422 register int howto; /* r11 == how to boot */
423 register int devtype; /* r10 == major of root dev */
424 extern char *panicstr;
425
426 howto = arghowto;
427 if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) {
428 register struct buf *bp;
429 int iter, nbusy;
430
431 waittime = 0;
432 (void) splnet();
433 printf("syncing disks... ");
434 /*
435 * Release vnodes held by texts before update.
436 */
437 if (panicstr == 0)
438 xumount(NULL);
439 sync();
440
441 for (iter = 0; iter < 20; iter++) {
442 nbusy = 0;
443 for (bp = &buf[nbuf]; --bp >= buf; )
444 if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
445 nbusy++;
446 if (nbusy == 0)
447 break;
448 printf("%d ", nbusy);
449 DELAY(40000 * iter);
450 }
451 if (nbusy)
452 printf("giving up\n");
453 else
454 printf("done\n");
455 DELAY(10000); /* wait for printf to finish */
456 }
457 mtpr(IPL, 0x1f); /* extreme priority */
458 devtype = major(rootdev);
459 *(int *)CPBFLG = howto;
460 if (howto&RB_HALT) {
461 printf("halting (in tight loop); hit ~h\n\n");
462 mtpr(IPL, 0x1f);
463 for (;;)
464 ;
465 } else {
466 if (howto & RB_DUMP) {
467 doadump(); /* CPBOOT's itsself */
468 /*NOTREACHED*/
469 }
470 tocons(CPBOOT);
471 }
472 #ifdef lint
473 dummy = 0; dummy = dummy;
474 printf("howto %d, devtype %d\n", arghowto, devtype);
475 #endif
476 for (;;)
477 asm("halt");
478 /*NOTREACHED*/
479 }
480
481 struct cpdcb_o cpcontrol;
482
483 /*
484 * Send the given comand ('c') to the console processor.
485 * Assumed to be one of the last things the OS does before
486 * halting or rebooting.
487 */
tocons(c)488 tocons(c)
489 {
490 register timeout;
491
492 cpcontrol.cp_hdr.cp_unit = CPUNIT;
493 cpcontrol.cp_hdr.cp_comm = (char)c;
494 if (c != CPBOOT)
495 cpcontrol.cp_hdr.cp_count = 1; /* Just for sanity */
496 else {
497 cpcontrol.cp_hdr.cp_count = 4;
498 *(int *)cpcontrol.cp_buf = 0; /* r11 value for reboot */
499 }
500 timeout = 100000; /* Delay loop */
501 while (timeout-- && (cnlast->cp_unit&CPDONE) == 0)
502 uncache(&cnlast->cp_unit);
503 /* give up, force it to listen */
504 mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)&cpcontrol));
505 }
506
507 #if CLSIZE != 1
508 /*
509 * Invalidate single all pte's in a cluster
510 */
tbiscl(v)511 tbiscl(v)
512 unsigned v;
513 {
514 register caddr_t addr; /* must be first reg var */
515 register int i;
516
517 addr = ptob(v);
518 for (i = 0; i < CLSIZE; i++) {
519 mtpr(TBIS, addr);
520 addr += NBPG;
521 }
522 }
523 #endif
524
525 int dumpmag = 0x8fca0101; /* magic number for savecore */
526 int dumpsize = 0; /* also for savecore */
527
dumpconf()528 dumpconf()
529 {
530 int nblks;
531
532 dumpsize = physmem;
533 if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) {
534 nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
535 if (dumpsize > btoc(dbtob(nblks - dumplo)))
536 dumpsize = btoc(dbtob(nblks - dumplo));
537 else if (dumplo == 0)
538 dumplo = nblks - btodb(ctob(physmem));
539 }
540 /*
541 * Don't dump on the first CLSIZE pages,
542 * in case the dump device includes a disk label.
543 */
544 if (dumplo < CLSIZE)
545 dumplo = CLSIZE;
546 }
547
548 /*
549 * Doadump comes here after turning off memory management and
550 * getting on the dump stack, either when called above, or by
551 * the auto-restart code.
552 */
dumpsys()553 dumpsys()
554 {
555
556 if (dumpdev == NODEV)
557 return;
558 /*
559 * For dumps during autoconfiguration,
560 * if dump device has already configured...
561 */
562 if (dumpsize == 0)
563 dumpconf();
564 if (dumplo < 0)
565 return;
566 printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
567 printf("dump ");
568 switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
569
570 case ENXIO:
571 printf("device bad\n");
572 break;
573
574 case EFAULT:
575 printf("device not ready\n");
576 break;
577
578 case EINVAL:
579 printf("area improper\n");
580 break;
581
582 case EIO:
583 printf("i/o error\n");
584 break;
585
586 default:
587 printf("succeeded\n");
588 break;
589 }
590 printf("\n\n");
591 DELAY(1000);
592 tocons(CPBOOT);
593 }
594
595 /*
596 * Bus error 'recovery' code.
597 * Print out the buss frame and then give up.
598 * (More information from special registers can be printed here.)
599 */
600
601 /*
602 * Frame for bus error
603 */
604 struct buserframe {
605 int which_bus; /* primary or secondary */
606 int memerreg; /* memory error register */
607 int trp_pc; /* trapped pc */
608 int trp_psl; /* trapped psl */
609 };
610
611 char *mem_errcd[8] = {
612 "Unknown error code 0",
613 "Address parity error", /* APE */
614 "Data parity error", /* DPE */
615 "Data check error", /* DCE */
616 "Versabus timeout", /* VTO */
617 "Versabus error", /* VBE */
618 "Non-existent memory", /* NEM */
619 "Unknown error code 7",
620 };
621
buserror(v)622 buserror(v)
623 caddr_t v;
624 {
625 register struct buserframe *busef = (struct buserframe *)v;
626 register long reg;
627
628 printf("bus error, address %x, psl %x\n",
629 busef->trp_pc, busef->trp_psl);
630 reg = busef->memerreg;
631 printf("mear %x %s\n",
632 ((reg&MEAR)>>16)&0xffff, mem_errcd[reg & ERRCD]);
633 if (reg&AXE)
634 printf("adapter external error\n");
635 printf("error master: %s\n", reg&ERM ? "versabus" : "tahoe");
636 if (reg&IVV)
637 printf("illegal interrupt vector from ipl %d\n", (reg>>2)&7);
638 reg = busef->which_bus;
639 printf("mcbr %x versabus type %x\n",
640 ((reg&MCBR)>>16)&0xffff, reg & 0xffc3);
641 if ((busef->memerreg&IVV) == 0)
642 panic("buserror");
643 }
644
microtime(tvp)645 microtime(tvp)
646 register struct timeval *tvp;
647 {
648 int s = splhigh();
649
650 *tvp = time;
651 tvp->tv_usec += tick;
652 while (tvp->tv_usec > 1000000) {
653 tvp->tv_sec++;
654 tvp->tv_usec -= 1000000;
655 }
656 splx(s);
657 }
658
initcpu()659 initcpu()
660 {
661 register struct proc *p;
662
663 p = &proc[0];
664 #define initkey(which, p, index) \
665 which/**/_cache[index] = 1, which/**/_cnt[index] = 1; \
666 p->p_/**/which = index;
667 initkey(ckey, p, MAXCKEY);
668 initkey(dkey, p, MAXDKEY);
669 }
670
671 /*
672 * Clear registers on exec
673 */
674 /* ARGSUSED */
setregs(entry,retval)675 setregs(entry, retval)
676 u_long entry;
677 int *retval;
678 {
679
680 #ifdef notdef
681 /* should pass args to init on the stack */
682 for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];)
683 *rp++ = 0;
684 #endif
685 u.u_ar0[FP] = 0; /* bottom of the fp chain */
686 u.u_ar0[PC] = entry + 2;
687 }
688