Annotation of sys/arch/aviion/aviion/machdep.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: machdep.c,v 1.10 2007/06/06 17:15:11 deraadt Exp $ */
2: /*
3: * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr.
4: * Copyright (c) 1996 Nivas Madhur
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by Nivas Madhur.
18: * 4. The name of the author may not be used to endorse or promote products
19: * derived from this software without specific prior written permission
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31: *
32: */
33: /*
34: * Mach Operating System
35: * Copyright (c) 1993-1991 Carnegie Mellon University
36: * Copyright (c) 1991 OMRON Corporation
37: * All Rights Reserved.
38: *
39: * Permission to use, copy, modify and distribute this software and its
40: * documentation is hereby granted, provided that both the copyright
41: * notice and this permission notice appear in all copies of the
42: * software, derivative works or modified versions, and any portions
43: * thereof, and that both notices appear in supporting documentation.
44: *
45: */
46:
47: #include <sys/param.h>
48: #include <sys/systm.h>
49: #include <sys/kernel.h>
50: #include <sys/proc.h>
51: #include <sys/user.h>
52: #include <sys/buf.h>
53: #include <sys/reboot.h>
54: #include <sys/conf.h>
55: #include <sys/malloc.h>
56: #include <sys/mount.h>
57: #include <sys/msgbuf.h>
58: #include <sys/syscallargs.h>
59: #ifdef SYSVMSG
60: #include <sys/msg.h>
61: #endif
62: #include <sys/exec.h>
63: #include <sys/sysctl.h>
64: #include <sys/errno.h>
65: #include <sys/extent.h>
66: #include <sys/core.h>
67: #include <sys/kcore.h>
68:
69: #include <machine/asm.h>
70: #include <machine/asm_macro.h>
71: #include <machine/autoconf.h>
72: #include <machine/board.h>
73: #include <machine/cmmu.h>
74: #include <machine/cpu.h>
75: #include <machine/kcore.h>
76: #include <machine/prom.h>
77: #include <machine/reg.h>
78: #include <machine/trap.h>
79:
80: #include <dev/cons.h>
81:
82: #include <uvm/uvm_extern.h>
83:
84: #include "ksyms.h"
85: #if DDB
86: #include <machine/db_machdep.h>
87: #include <ddb/db_extern.h>
88: #include <ddb/db_interface.h>
89: #include <ddb/db_var.h>
90: #endif /* DDB */
91:
92: caddr_t allocsys(caddr_t);
93: void aviion_bootstrap(void);
94: int aviion_identify(void);
95: void consinit(void);
96: __dead void doboot(void);
97: void dumpconf(void);
98: void dumpsys(void);
99: u_int getipl(void);
100: void identifycpu(void);
101: void savectx(struct pcb *);
102: void secondary_main(void);
103: void secondary_pre_main(void);
104:
105: intrhand_t intr_handlers[NVMEINTR];
106:
107: int physmem; /* available physical memory, in pages */
108:
109: struct vm_map *exec_map = NULL;
110: struct vm_map *phys_map = NULL;
111:
112: #ifdef MULTIPROCESSOR
113: __cpu_simple_lock_t cpu_mutex = __SIMPLELOCK_UNLOCKED;
114: #endif
115:
116: /*
117: * Declare these as initialized data so we can patch them.
118: */
119: #ifndef BUFCACHEPERCENT
120: #define BUFCACHEPERCENT 5
121: #endif
122:
123: #ifdef BUFPAGES
124: int bufpages = BUFPAGES;
125: #else
126: int bufpages = 0;
127: #endif
128: int bufcachepercent = BUFCACHEPERCENT;
129:
130: /*
131: * Info for CTL_HW
132: */
133: char machine[] = MACHINE; /* cpu "architecture" */
134: char cpu_model[120];
135:
136: #if defined(DDB) || NKSYMS > 0
137: extern vaddr_t esym;
138: #endif
139:
140: const char *prom_bootargs; /* set in locore.S */
141: char bootargs[256]; /* local copy */
142: u_int bootdev, bootunit, bootpart; /* set in locore.S */
143:
144: int cputyp; /* set in locore.S */
145: int cpuspeed = 20; /* safe guess */
146: int avtyp;
147: const struct board *platform;
148:
149: vaddr_t first_addr;
150: vaddr_t last_addr;
151:
152: vaddr_t avail_start, avail_end;
153: vaddr_t virtual_avail, virtual_end;
154:
155: extern struct user *proc0paddr;
156:
157: /*
158: * This is to fake out the console routines, while booting.
159: * We could use directly the bugtty console, but we want to be able to
160: * configure a kernel without bugtty since we do not necessarily need a
161: * full-blown console driver.
162: */
163: cons_decl(boot);
164:
165: struct consdev bootcons = {
166: NULL,
167: NULL,
168: bootcngetc,
169: bootcnputc,
170: nullcnpollc,
171: NULL,
172: makedev(14, 0),
173: CN_NORMAL
174: };
175:
176: /*
177: * Early console initialization: called early on from main, before vm init.
178: * We want to stick to the BUG routines for now, and we'll switch to the
179: * real console in cpu_startup().
180: */
181: void
182: consinit()
183: {
184: cn_tab = NULL;
185: cninit();
186:
187: #if defined(DDB)
188: db_machine_init();
189: ddb_init();
190: if (boothowto & RB_KDB)
191: Debugger();
192: #endif
193: }
194:
195: void
196: identifycpu()
197: {
198: #if 0
199: /* XXX FILL ME */
200: cpuspeed = getcpuspeed(&brdid);
201: #endif
202:
203: strlcpy(cpu_model, platform->descr, sizeof cpu_model);
204: }
205:
206: /*
207: * Set up real-time clocks.
208: * These function pointers are set in dev/clock.c.
209: */
210: void
211: cpu_initclocks()
212: {
213: platform->init_clocks();
214: }
215:
216: void
217: setstatclockrate(int newhz)
218: {
219: /* function stub */
220: }
221:
222:
223: void
224: cpu_startup()
225: {
226: caddr_t v;
227: int sz, i;
228: vsize_t size;
229: int base, residual;
230: vaddr_t minaddr, maxaddr;
231:
232: /*
233: * Initialize error message buffer (at end of core).
234: * avail_end was pre-decremented in aviion_bootstrap() to compensate.
235: */
236: for (i = 0; i < btoc(MSGBUFSIZE); i++)
237: pmap_kenter_pa((paddr_t)msgbufp + i * PAGE_SIZE,
238: avail_end + i * PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE);
239: pmap_update(pmap_kernel());
240: initmsgbuf((caddr_t)msgbufp, round_page(MSGBUFSIZE));
241:
242: /*
243: * Good {morning,afternoon,evening,night}.
244: */
245: printf(version);
246: identifycpu();
247: printf("real mem = %d\n", ctob(physmem));
248:
249: /*
250: * Find out how much space we need, allocate it,
251: * and then give everything true virtual addresses.
252: */
253: sz = (int)allocsys((caddr_t)0);
254:
255: if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0)
256: panic("startup: no room for tables");
257: if (allocsys(v) - v != sz)
258: panic("startup: table size inconsistency");
259:
260: /*
261: * Grab machine dependent memory spaces
262: */
263: platform->startup();
264:
265: /*
266: * Determine how many buffers to allocate.
267: * We allocate bufcachepercent% of memory for buffer space.
268: */
269: if (bufpages == 0)
270: bufpages = physmem * bufcachepercent / 100;
271:
272: /* Restrict to at most 25% filled kvm */
273: if (bufpages >
274: (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
275: bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
276: PAGE_SIZE / 4;
277:
278: /*
279: * Allocate a submap for exec arguments. This map effectively
280: * limits the number of processes exec'ing at any time.
281: */
282: minaddr = vm_map_min(kernel_map);
283: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
284: 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
285:
286: /*
287: * Allocate map for physio.
288: */
289: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
290: VM_PHYS_SIZE, 0, FALSE, NULL);
291:
292: printf("avail mem = %ld (%d pages)\n", ptoa(uvmexp.free), uvmexp.free);
293:
294: /*
295: * Set up buffers, so they can be used to read disk labels.
296: */
297: bufinit();
298:
299: /*
300: * Set up interrupt handlers.
301: */
302: for (i = 0; i < NVMEINTR; i++)
303: SLIST_INIT(&intr_handlers[i]);
304:
305: /*
306: * Configure the system.
307: */
308: if (boothowto & RB_CONFIG) {
309: #ifdef BOOT_CONFIG
310: user_config();
311: #else
312: printf("kernel does not support -c; continuing..\n");
313: #endif
314: }
315: }
316:
317: /*
318: * Allocate space for system data structures. We are given
319: * a starting virtual address and we return a final virtual
320: * address; along the way we set each data structure pointer.
321: *
322: * We call allocsys() with 0 to find out how much space we want,
323: * allocate that much and fill it with zeroes, and then call
324: * allocsys() again with the correct base virtual address.
325: */
326: caddr_t
327: allocsys(v)
328: caddr_t v;
329: {
330:
331: #define valloc(name, type, num) \
332: v = (caddr_t)(((name) = (type *)v) + (num))
333:
334: #ifdef SYSVMSG
335: valloc(msgpool, char, msginfo.msgmax);
336: valloc(msgmaps, struct msgmap, msginfo.msgseg);
337: valloc(msghdrs, struct msg, msginfo.msgtql);
338: valloc(msqids, struct msqid_ds, msginfo.msgmni);
339: #endif
340:
341: return v;
342: }
343:
344: __dead void
345: doboot()
346: {
347: printf("Rebooting system...\n\n");
348: cmmu_shutdown();
349: scm_reboot(NULL);
350: /*NOTREACHED*/
351: for (;;); /* appease gcc */
352: }
353:
354: __dead void
355: boot(howto)
356: int howto;
357: {
358: /* take a snapshot before clobbering any registers */
359: if (curproc && curproc->p_addr)
360: savectx(curpcb);
361:
362: /* If system is cold, just halt. */
363: if (cold) {
364: /* (Unless the user explicitly asked for reboot.) */
365: if ((howto & RB_USERREQ) == 0)
366: howto |= RB_HALT;
367: goto haltsys;
368: }
369:
370: boothowto = howto;
371: if ((howto & RB_NOSYNC) == 0) {
372: vfs_shutdown();
373: /*
374: * If we've been adjusting the clock, the todr
375: * will be out of synch; adjust it now unless
376: * the system was sitting in ddb.
377: */
378: if ((howto & RB_TIMEBAD) == 0)
379: resettodr();
380: else
381: printf("WARNING: not updating battery clock\n");
382: }
383:
384: /* Disable interrupts. */
385: splhigh();
386:
387: /* If rebooting and a dump is requested, do it. */
388: if (howto & RB_DUMP)
389: dumpsys();
390:
391: haltsys:
392: /* Run any shutdown hooks. */
393: doshutdownhooks();
394:
395: if (howto & RB_HALT) {
396: printf("System halted.\n\n");
397: cmmu_shutdown();
398: scm_halt();
399: }
400:
401: doboot();
402:
403: for (;;);
404: /*NOTREACHED*/
405: }
406:
407: unsigned dumpmag = 0x8fca0101; /* magic number for savecore */
408: int dumpsize = 0; /* also for savecore */
409: long dumplo = 0;
410: cpu_kcore_hdr_t cpu_kcore_hdr;
411:
412: /*
413: * This is called by configure to set dumplo and dumpsize.
414: * Dumps always skip the first PAGE_SIZE of disk space
415: * in case there might be a disk label stored there.
416: * If there is extra space, put dump at the end to
417: * reduce the chance that swapping trashes it.
418: */
419: void
420: dumpconf(void)
421: {
422: int nblks; /* size of dump area */
423:
424: if (dumpdev == NODEV ||
425: (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
426: return;
427: if (nblks <= ctod(1))
428: return;
429:
430: dumpsize = physmem;
431:
432: /* aviion only uses a single segment. */
433: cpu_kcore_hdr.ram_segs[0].start = 0;
434: cpu_kcore_hdr.ram_segs[0].size = ctob(physmem);
435: cpu_kcore_hdr.cputype = cputyp;
436:
437: /*
438: * Don't dump on the first block
439: * in case the dump device includes a disk label.
440: */
441: if (dumplo < ctod(1))
442: dumplo = ctod(1);
443:
444: /* Put dump at end of partition, and make it fit. */
445: if (dumpsize + 1 > dtoc(nblks - dumplo))
446: dumpsize = dtoc(nblks - dumplo) - 1;
447: if (dumplo < nblks - ctod(dumpsize) - 1)
448: dumplo = nblks - ctod(dumpsize) - 1;
449: }
450:
451: /*
452: * Doadump comes here after turning off memory management and
453: * getting on the dump stack, either when called above, or by
454: * the auto-restart code.
455: */
456: void
457: dumpsys()
458: {
459: int maj;
460: int psize;
461: daddr64_t blkno; /* current block to write */
462: /* dump routine */
463: int (*dump)(dev_t, daddr64_t, caddr_t, size_t);
464: int pg; /* page being dumped */
465: paddr_t maddr; /* PA being dumped */
466: int error; /* error code from (*dump)() */
467: kcore_seg_t *kseg_p;
468: cpu_kcore_hdr_t *chdr_p;
469: char dump_hdr[dbtob(1)]; /* XXX assume hdr fits in 1 block */
470:
471: extern int msgbufmapped;
472:
473: msgbufmapped = 0;
474:
475: /* Make sure dump device is valid. */
476: if (dumpdev == NODEV)
477: return;
478: if (dumpsize == 0) {
479: dumpconf();
480: if (dumpsize == 0)
481: return;
482: }
483: maj = major(dumpdev);
484: if (dumplo < 0) {
485: printf("\ndump to dev %u,%u not possible\n", maj,
486: minor(dumpdev));
487: return;
488: }
489: dump = bdevsw[maj].d_dump;
490: blkno = dumplo;
491:
492: printf("\ndumping to dev %u,%u offset %ld\n", maj,
493: minor(dumpdev), dumplo);
494:
495: /* Setup the dump header */
496: kseg_p = (kcore_seg_t *)dump_hdr;
497: chdr_p = (cpu_kcore_hdr_t *)&dump_hdr[ALIGN(sizeof(*kseg_p))];
498: bzero(dump_hdr, sizeof(dump_hdr));
499:
500: CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
501: kseg_p->c_size = dbtob(1) - ALIGN(sizeof(*kseg_p));
502: *chdr_p = cpu_kcore_hdr;
503:
504: printf("dump ");
505: psize = (*bdevsw[maj].d_psize)(dumpdev);
506: if (psize == -1) {
507: printf("area unavailable\n");
508: return;
509: }
510:
511: /* Dump the header. */
512: error = (*dump)(dumpdev, blkno++, (caddr_t)dump_hdr, dbtob(1));
513: if (error != 0)
514: goto abort;
515:
516: maddr = (paddr_t)0;
517: for (pg = 0; pg < dumpsize; pg++) {
518: #define NPGMB (1024 * 1024 / PAGE_SIZE)
519: /* print out how many MBs we have dumped */
520: if (pg != 0 && (pg % NPGMB) == 0)
521: printf("%d ", pg / NPGMB);
522: #undef NPGMB
523: pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr,
524: VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
525:
526: error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE);
527: if (error == 0) {
528: maddr += PAGE_SIZE;
529: blkno += btodb(PAGE_SIZE);
530: } else
531: break;
532: }
533: abort:
534: switch (error) {
535: case 0:
536: printf("succeeded\n");
537: break;
538:
539: case ENXIO:
540: printf("device bad\n");
541: break;
542:
543: case EFAULT:
544: printf("device not ready\n");
545: break;
546:
547: case EINVAL:
548: printf("area improper\n");
549: break;
550:
551: case EIO:
552: printf("i/o error\n");
553: break;
554:
555: case EINTR:
556: printf("aborted from console\n");
557: break;
558:
559: default:
560: printf("error %d\n", error);
561: break;
562: }
563: }
564:
565: #ifdef MULTIPROCESSOR
566:
567: /*
568: * Secondary CPU early initialization routine.
569: * Determine CPU number and set it, then allocate the idle pcb (and stack).
570: *
571: * Running on a minimal stack here, with interrupts disabled; do nothing fancy.
572: */
573: void
574: secondary_pre_main()
575: {
576: struct cpu_info *ci;
577:
578: set_cpu_number(cmmu_cpu_number()); /* Determine cpu number by CMMU */
579: ci = curcpu();
580: ci->ci_curproc = &proc0;
581:
582: splhigh();
583:
584: /*
585: * Setup CMMUs and translation tables (shared with the master cpu).
586: */
587: pmap_bootstrap_cpu(ci->ci_cpuid);
588:
589: /*
590: * Allocate UPAGES contiguous pages for the idle PCB and stack.
591: */
592: ci->ci_idle_pcb = (struct pcb *)uvm_km_zalloc(kernel_map, USPACE);
593: if (ci->ci_idle_pcb == NULL) {
594: printf("cpu%d: unable to allocate idle stack\n", ci->ci_cpuid);
595: }
596: }
597:
598: /*
599: * Further secondary CPU initialization.
600: *
601: * We are now running on our idle stack, with proper page tables.
602: * There is nothing to do but display some details about the CPU and its CMMUs.
603: */
604: void
605: secondary_main()
606: {
607: struct cpu_info *ci = curcpu();
608:
609: cpu_configuration_print(0);
610: ncpus++;
611: __cpu_simple_unlock(&cpu_mutex);
612:
613: microuptime(&ci->ci_schedstate.spc_runtime);
614: ci->ci_curproc = NULL;
615:
616: /*
617: * Upon return, the secondary cpu bootstrap code in locore will
618: * enter the idle loop, waiting for some food to process on this
619: * processor.
620: */
621: }
622:
623: #endif /* MULTIPROCESSOR */
624:
625: /*
626: * Try to insert ihand in the list of handlers for vector vec.
627: */
628: int
629: intr_establish(int vec, struct intrhand *ihand, const char *name)
630: {
631: struct intrhand *intr;
632: intrhand_t *list;
633:
634: if (vec < 0 || vec >= NVMEINTR) {
635: #ifdef DIAGNOSTIC
636: printf("intr_establish: vec (0x%x) not between 0x00 and 0xff\n",
637: vec);
638: #endif /* DIAGNOSTIC */
639: return (EINVAL);
640: }
641:
642: list = &intr_handlers[vec];
643: if (!SLIST_EMPTY(list)) {
644: intr = SLIST_FIRST(list);
645: if (intr->ih_ipl != ihand->ih_ipl) {
646: #ifdef DIAGNOSTIC
647: printf("intr_establish: there are other handlers with "
648: "vec (0x%x) at ipl %x, but you want it at %x\n",
649: vec, intr->ih_ipl, ihand->ih_ipl);
650: #endif /* DIAGNOSTIC */
651: return (EINVAL);
652: }
653: }
654:
655: evcount_attach(&ihand->ih_count, name, (void *)&ihand->ih_ipl,
656: &evcount_intr);
657: SLIST_INSERT_HEAD(list, ihand, ih_link);
658: return (0);
659: }
660:
661: void
662: nmihand(void *frame)
663: {
664: #ifdef DDB
665: printf("Abort switch pressed\n");
666: if (db_console) {
667: /*
668: * We can't use Debugger() here, as we are coming from an
669: * exception, and can't assume anything on the state we are
670: * in. Invoke the post-trap ddb entry directly.
671: */
672: extern void m88k_db_trap(int, struct trapframe *);
673: m88k_db_trap(T_KDB_ENTRY, (struct trapframe *)frame);
674: }
675: #endif
676: }
677:
678: int
679: cpu_exec_aout_makecmds(p, epp)
680: struct proc *p;
681: struct exec_package *epp;
682: {
683:
684: return (ENOEXEC);
685: }
686:
687: int
688: sys_sysarch(p, v, retval)
689: struct proc *p;
690: void *v;
691: register_t *retval;
692: {
693: #if 0
694: struct sys_sysarch_args /* {
695: syscallarg(int) op;
696: syscallarg(char *) parm;
697: } */ *uap = v;
698: #endif
699:
700: return (ENOSYS);
701: }
702:
703: /*
704: * machine dependent system variables.
705: */
706:
707: int
708: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
709: int *name;
710: u_int namelen;
711: void *oldp;
712: size_t *oldlenp;
713: void *newp;
714: size_t newlen;
715: struct proc *p;
716: {
717: dev_t consdev;
718:
719: /* all sysctl names are this level are terminal */
720: if (namelen != 1)
721: return (ENOTDIR); /* overloaded */
722:
723: switch (name[0]) {
724: case CPU_CONSDEV:
725: if (cn_tab != NULL)
726: consdev = cn_tab->cn_dev;
727: else
728: consdev = NODEV;
729: return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
730: sizeof consdev));
731: default:
732: return (EOPNOTSUPP);
733: }
734: /*NOTREACHED*/
735: }
736:
737: /*
738: * Called from locore.S during boot,
739: * this is the first C code that's run.
740: */
741: void
742: aviion_bootstrap()
743: {
744: extern int kernelstart;
745: extern char *end;
746: #ifndef MULTIPROCESSOR
747: cpuid_t master_cpu;
748: #endif
749:
750: /* Save a copy of our commandline before it gets overwritten. */
751: strlcpy(bootargs, prom_bootargs, sizeof bootargs);
752:
753: avtyp = aviion_identify();
754:
755: /* Set up interrupt and fp exception handlers based on the machine. */
756: switch (avtyp) {
757: #ifdef AV400
758: case AV_400:
759: platform = &board_av400;
760: break;
761: #endif
762: #ifdef AV530
763: case AV_530:
764: platform = &board_av530;
765: break;
766: #endif
767: #ifdef AV5000
768: case AV_5000:
769: platform = &board_av5000;
770: break;
771: #endif
772: #ifdef AV6280
773: case AV_6280:
774: platform = &board_av6280;
775: break;
776: #endif
777: default:
778: scm_printf("Sorry, OpenBSD/" MACHINE
779: " does not support this model.\n");
780: scm_halt();
781: break;
782: };
783:
784: cn_tab = &bootcons;
785: /* we can use printf() from here. */
786:
787: platform->bootstrap();
788:
789: /* Parse the commandline */
790: cmdline_parse();
791:
792: uvmexp.pagesize = PAGE_SIZE;
793: uvm_setpagesize();
794:
795: #if defined(DDB) || NKSYMS > 0
796: if (esym != 0)
797: first_addr = esym;
798: else
799: #endif
800: first_addr = (vaddr_t)&end;
801: first_addr = round_page(first_addr);
802:
803: last_addr = platform->memsize();
804: physmem = btoc(last_addr);
805:
806: setup_board_config();
807: master_cpu = cmmu_init();
808: set_cpu_number(master_cpu);
809:
810: /*
811: * Now that set_cpu_number() set us with a valid cpu_info pointer,
812: * we need to initialize p_addr and curpcb before autoconf, for the
813: * fault handler to behave properly [except for badaddr() faults,
814: * which can be taken care of without a valid curcpu()].
815: */
816: proc0.p_addr = proc0paddr;
817: curproc = &proc0;
818: curpcb = &proc0paddr->u_pcb;
819:
820: avail_start = round_page(first_addr);
821: avail_end = last_addr;
822:
823: /* Steal MSGBUFSIZE at the top of physical memory for msgbuf. */
824: avail_end -= round_page(MSGBUFSIZE);
825: pmap_bootstrap((vaddr_t)trunc_page((unsigned)&kernelstart));
826:
827: /*
828: * Tell the VM system about available physical memory.
829: * The aviion systems only have one contiguous area.
830: *
831: * XXX However, on series 5000, SRAM overlaps a low memory range,
832: * XXX so we will need to upload two ranges of pages on them.
833: */
834: uvm_page_physload(atop(avail_start), atop(avail_end),
835: atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT);
836:
837: /* Initialize the "u-area" pages. */
838: bzero((caddr_t)curpcb, USPACE);
839: }
840:
841: #ifdef MULTIPROCESSOR
842: void
843: cpu_boot_secondary_processors()
844: {
845: cpuid_t cpu;
846: int rc;
847: extern void secondary_start(void);
848:
849: for (cpu = 0; cpu < max_cpus; cpu++) {
850: if (cpu != curcpu()->ci_cpuid) {
851: rc = scm_spincpu(cpu, (vaddr_t)secondary_start);
852: if (rc != 0)
853: printf("cpu%d: spin_cpu error %d\n", cpu, rc);
854: }
855: }
856: }
857: #endif
858:
859: /*
860: * Boot console routines:
861: * Enables printing of boot messages before consinit().
862: */
863: void
864: bootcnprobe(cp)
865: struct consdev *cp;
866: {
867: cp->cn_dev = makedev(0, 0);
868: cp->cn_pri = CN_NORMAL;
869: }
870:
871: void
872: bootcninit(cp)
873: struct consdev *cp;
874: {
875: /* Nothing to do */
876: }
877:
878: int
879: bootcngetc(dev)
880: dev_t dev;
881: {
882: return (scm_getc());
883: }
884:
885: void
886: bootcnputc(dev, c)
887: dev_t dev;
888: int c;
889: {
890: if (c == '\n')
891: scm_putcrlf();
892: else
893: scm_putc(c);
894: }
895:
896: u_int
897: getipl(void)
898: {
899: u_int curspl, psr;
900:
901: disable_interrupt(psr);
902: curspl = platform->getipl();
903: set_psr(psr);
904: return curspl;
905: }
906:
907: u_int
908: setipl(u_int level)
909: {
910: u_int curspl, psr;
911:
912: disable_interrupt(psr);
913: curspl = platform->setipl(level);
914:
915: /*
916: * The flush pipeline is required to make sure the above change gets
917: * through the data pipe and to the hardware; otherwise, the next
918: * bunch of instructions could execute at the wrong spl protection.
919: */
920: flush_pipeline();
921:
922: set_psr(psr);
923: return curspl;
924: }
925:
926: u_int
927: raiseipl(u_int level)
928: {
929: u_int curspl, psr;
930:
931: disable_interrupt(psr);
932: curspl = platform->raiseipl(level);
933:
934: /*
935: * The flush pipeline is required to make sure the above change gets
936: * through the data pipe and to the hardware; otherwise, the next
937: * bunch of instructions could execute at the wrong spl protection.
938: */
939: flush_pipeline();
940:
941: set_psr(psr);
942: return curspl;
943: }
944:
945: u_char hostaddr[6];
946:
947: void
948: myetheraddr(u_char *cp)
949: {
950: bcopy(hostaddr, cp, 6);
951: }
952:
953: /*
954: * Attempt to identify which AViiON flavour we are running on.
955: * The only thing we can do at this point is peek at random addresses and
956: * see if they cause bus errors, or not.
957: *
958: * These heuristics are probably not the best; feel free to come with better
959: * ones...
960: */
961: int
962: aviion_identify()
963: {
964: /*
965: * We don't know anything about 88110-based models.
966: * Note that we can't use CPU_IS81x0 here since these are optimized
967: * if the kernel you're running is compiled for only one processor
968: * type, and we want to check against the real hardware.
969: */
970: if (cputyp == CPU_88110)
971: return (0);
972:
973: /*
974: * Series 100/200/300/400/3000/4000/4300 do not have the VIRQLV
975: * register at 0xfff85000.
976: */
977: if (badaddr(0xfff85000, 4) != 0)
978: return (AV_400);
979:
980: /*
981: * Series 5000 and 6000 do not have an RTC counter at 0xfff8f084.
982: */
983: if (badaddr(0xfff8f084, 4) != 0)
984: return (AV_5000);
985:
986: /*
987: * Series 4600/530 have IOFUSEs at 0xfffb0040 and 0xfffb00c0.
988: */
989: if (badaddr(0xfffb0040, 1) == 0 && badaddr(0xfffb00c0, 1) == 0)
990: return (AV_530);
991:
992: /*
993: * Series 6280/8000-8 fall here.
994: */
995: return (AV_6280);
996: }
CVSweb