Annotation of sys/arch/sgi/sgi/machdep.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: machdep.c,v 1.47 2007/07/18 20:05:25 miod Exp $ */
2:
3: /*
4: * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: *
15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25: * SUCH DAMAGE.
26: *
27: */
28: #include <sys/param.h>
29: #include <sys/systm.h>
30: #include <sys/signalvar.h>
31: #include <sys/kernel.h>
32: #include <sys/proc.h>
33: #include <sys/buf.h>
34: #include <sys/reboot.h>
35: #include <sys/conf.h>
36: #include <sys/file.h>
37: #include <sys/malloc.h>
38: #include <sys/mbuf.h>
39: #include <sys/msgbuf.h>
40: #include <sys/ioctl.h>
41: #include <sys/tty.h>
42: #include <sys/user.h>
43: #include <sys/exec.h>
44: #include <sys/sysctl.h>
45: #include <sys/mount.h>
46: #include <sys/syscallargs.h>
47: #include <sys/exec_elf.h>
48: #include <sys/extent.h>
49: #ifdef SYSVSHM
50: #include <sys/shm.h>
51: #endif
52: #ifdef SYSVSEM
53: #include <sys/sem.h>
54: #endif
55: #ifdef SYSVMSG
56: #include <sys/msg.h>
57: #endif
58:
59: #include <uvm/uvm_extern.h>
60:
61: #include <machine/db_machdep.h>
62: #include <ddb/db_interface.h>
63:
64: #include <machine/pte.h>
65: #include <machine/cpu.h>
66: #include <machine/frame.h>
67: #include <machine/pio.h>
68: #include <machine/psl.h>
69: #include <machine/autoconf.h>
70: #include <machine/memconf.h>
71: #include <machine/regnum.h>
72: #if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000)
73: #include <machine/mnode.h>
74: #endif
75:
76: #include <mips64/rm7000.h>
77:
78: #include <dev/cons.h>
79:
80: #include <mips64/arcbios.h>
81: #include <mips64/archtype.h>
82: #include <machine/bus.h>
83:
84: #include <sgi/localbus/crimebus.h>
85: #include <sgi/localbus/macebus.h>
86: #if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000)
87: #include <sgi/localbus/xbowmux.h>
88: #endif
89:
90: extern struct consdev *cn_tab;
91: extern char kernel_text[];
92: extern int makebootdev(const char *, int);
93: extern void stacktrace(void);
94:
95: #ifdef DEBUG
96: void dump_tlb(void);
97: #endif
98:
99: /* the following is used externally (sysctl_hw) */
100: char machine[] = MACHINE; /* machine "architecture" */
101: char cpu_model[30];
102:
103: /*
104: * Declare these as initialized data so we can patch them.
105: */
106: #ifndef BUFCACHEPERCENT
107: #define BUFCACHEPERCENT 5 /* Can be changed in config */
108: #endif
109: #ifndef BUFPAGES
110: #define BUFPAGES 0 /* Can be changed in config */
111: #endif
112:
113: int bufpages = BUFPAGES;
114: int bufcachepercent = BUFCACHEPERCENT;
115:
116: vm_map_t exec_map;
117: vm_map_t phys_map;
118:
119: int extent_malloc_flags = 0;
120:
121: caddr_t msgbufbase;
122:
123: int physmem; /* max supported memory, changes to actual */
124: int rsvdmem; /* reserved memory not usable */
125: int ncpu = 1; /* At least one cpu in the system */
126: struct user *proc0paddr;
127: struct user *curprocpaddr;
128: int console_ok; /* set when console initialized */
129: int bootdriveoffs = 0;
130:
131: int32_t *environment;
132: struct sys_rec sys_config;
133:
134:
135: /* ddb symbol init stuff */
136: caddr_t ssym;
137: caddr_t esym;
138: caddr_t ekern;
139:
140: struct phys_mem_desc mem_layout[MAXMEMSEGS];
141:
142: void crime_configure_memory(void);
143:
144: caddr_t mips_init(int, void *);
145: void initcpu(void);
146: void dumpsys(void);
147: void dumpconf(void);
148: caddr_t allocsys(caddr_t);
149:
150: void db_command_loop(void);
151:
152: static void dobootopts(int, void *);
153: static int atoi(const char *, int, const char **);
154:
155: #if BYTE_ORDER == BIG_ENDIAN
156: int my_endian = 1;
157: #else
158: int my_endian = 0;
159: #endif
160:
161: #if defined(TGT_O2)
162: void
163: crime_configure_memory(void)
164: {
165: struct phys_mem_desc *m;
166: volatile u_int64_t *bank_ctrl;
167: paddr_t addr;
168: psize_t size;
169: u_int32_t first_page, last_page;
170: int bank, i;
171:
172: bank_ctrl = (void *)PHYS_TO_KSEG1(CRIMEBUS_BASE + CRIME_MEM_BANK0_CONTROL);
173: for (bank = 0; bank < CRIME_MAX_BANKS; bank++) {
174: addr = (bank_ctrl[bank] & CRIME_MEM_BANK_ADDR) << 25;
175: size = (bank_ctrl[bank] & CRIME_MEM_BANK_128MB) ? 128 : 32;
176: #ifdef DEBUG
177: bios_printf("crime: bank %d contains %ld MB at 0x%lx\n",
178: bank, size, addr);
179: #endif
180:
181: /*
182: * Do not report memory regions below 256MB, since
183: * arcbios will do. Moreover, empty banks are reported
184: * at address zero.
185: */
186: if (addr < 256 * 1024 * 1024)
187: continue;
188:
189: addr += 1024 * 1024 * 1024;
190: size *= 1024 * 1024;
191: first_page = atop(addr);
192: last_page = atop(addr + size);
193:
194: /*
195: * Try to coalesce with other memory segments if banks
196: * are contiguous.
197: */
198: m = NULL;
199: for (i = 0; i < MAXMEMSEGS; i++) {
200: if (mem_layout[i].mem_last_page == 0) {
201: if (m == NULL)
202: m = &mem_layout[i];
203: } else if (last_page == mem_layout[i].mem_first_page) {
204: m = &mem_layout[i];
205: m->mem_first_page = first_page;
206: } else if (mem_layout[i].mem_last_page == first_page) {
207: m = &mem_layout[i];
208: m->mem_last_page = last_page;
209: }
210: }
211: if (m != NULL && m->mem_last_page == 0) {
212: m->mem_first_page = first_page;
213: m->mem_last_page = last_page;
214: }
215: if (m != NULL)
216: physmem += atop(size);
217: }
218:
219: #ifdef DEBUG
220: for (i = 0; i < MAXMEMSEGS; i++)
221: if (mem_layout[i].mem_first_page)
222: bios_printf("MEM %d, 0x%x to 0x%x\n",i,
223: ptoa(mem_layout[i].mem_first_page),
224: ptoa(mem_layout[i].mem_last_page));
225: #endif
226: }
227: #endif
228:
229: /*
230: * Do all the stuff that locore normally does before calling main().
231: * Reset mapping and set up mapping to hardware and init "wired" reg.
232: */
233:
234: caddr_t
235: mips_init(int argc, void *argv)
236: {
237: char *cp;
238: int i;
239: caddr_t sd;
240: extern char start[], edata[], end[];
241: extern char tlb_miss_tramp[], e_tlb_miss_tramp[];
242: extern char xtlb_miss_tramp[], e_xtlb_miss_tramp[];
243: extern char exception[], e_exception[];
244:
245: /*
246: * Make sure we can access the extended address space.
247: * Note that r10k and later do not allow XUSEG accesses
248: * from kernel mode unless SR_UX is set.
249: */
250: setsr(getsr() | SR_KX | SR_UX);
251:
252: /*
253: * Clear the compiled BSS segment in OpenBSD code
254: */
255: bzero(edata, end - edata);
256:
257: /*
258: * Reserve symbol table space. If invalid pointers no table.
259: */
260: ssym = (char *)*(u_int64_t *)end;
261: esym = (char *)*((u_int64_t *)end + 1);
262: ekern = esym;
263: if (((long)ssym - (long)end) < 0 ||
264: ((long)ssym - (long)end) > 0x1000 ||
265: ssym[0] != ELFMAG0 || ssym[1] != ELFMAG1 ||
266: ssym[2] != ELFMAG2 || ssym[3] != ELFMAG3 ) {
267: ssym = NULL;
268: esym = NULL;
269: ekern = end;
270: }
271:
272: /*
273: * Initialize the system type and set up memory layout
274: * Note that some systems have more complex memory setup.
275: */
276: bios_ident();
277:
278: bios_printf("SR=%08x\n", getsr()); /* leave this in for now. need to see sr */
279:
280: /*
281: * Determine system type and set up configuration record data.
282: */
283: switch (sys_config.system_type) {
284: #if defined(TGT_O2)
285: case SGI_O2:
286: bios_printf("Found SGI-IP32, setting up.\n");
287: strlcpy(cpu_model, "SGI-O2 (IP32)", sizeof(cpu_model));
288: sys_config.cons_ioaddr[0] = MACE_ISA_SER1_OFFS;
289: sys_config.cons_ioaddr[1] = MACE_ISA_SER2_OFFS;
290: sys_config.cons_baudclk = 1843200; /*XXX*/
291: sys_config.cons_iot = &macebus_tag;
292: sys_config.local.bus_base = 0x0; /*XXX*/
293: sys_config.pci_io[0].bus_base = 0xffffffff00000000;/*XXX*/
294: sys_config.pci_mem[0].bus_base = 0xffffffff00000000;/*XXX*/
295: sys_config.pci_mem[0].bus_base_dma = 0x00000000;/*XXX*/
296: sys_config.pci_mem[0].bus_reverse = my_endian;
297: sys_config.cpu[0].tlbwired = 2;
298:
299: crime_configure_memory();
300:
301: sys_config.cpu[0].clock = 180000000; /* Reasonable default */
302: cp = Bios_GetEnvironmentVariable("cpufreq");
303: if (cp && atoi(cp, 10, NULL) > 100)
304: sys_config.cpu[0].clock = atoi(cp, 10, NULL) * 1000000;
305:
306: /* R1xK O2's are one disk slot machines. Offset slotno */
307: switch ((cp0_get_prid() >> 8) & 0xff) {
308: case MIPS_R10000:
309: case MIPS_R12000:
310: bootdriveoffs = -1;
311: break;
312: }
313: /* R12K O2's must run with DSD on */
314: switch ((cp0_get_prid() >> 8) & 0xff) {
315: case MIPS_R12000:
316: setsr(getsr() | SR_DSD);
317: break;
318: }
319: break;
320: #endif
321:
322: #if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000)
323: case SGI_O200:
324: bios_printf("Found SGI-IP27, setting up.\n");
325: strlcpy(cpu_model, "SGI- Origin200 (IP27)", sizeof(cpu_model));
326:
327: kl_scan_config(0);
328:
329: sys_config.cons_ioaddr[0] = kl_get_console_base();
330: sys_config.cons_ioaddr[1] = kl_get_console_base() - 8;
331: sys_config.cons_baudclk = 22000000 / 3; /*XXX*/
332: sys_config.cons_iot = &xbowmux_tag;
333: sys_config.local.bus_base = 0x0; /*XXX*/
334: sys_config.pci_io[0].bus_base = 0xffffffff00000000;/*XXX*/
335: sys_config.pci_mem[0].bus_base = 0xffffffff00000000;/*XXX*/
336: sys_config.pci_mem[0].bus_base_dma = 0x00000000;/*XXX*/
337: sys_config.pci_mem[0].bus_reverse = my_endian;
338: sys_config.cpu[0].tlbwired = 2;
339: break;
340: #endif
341:
342: default:
343: bios_printf("Kernel doesn't support this system type!\n");
344: bios_printf("Halting system.\n");
345: Bios_Halt();
346: while(1);
347: }
348:
349: /*
350: * Look at arguments passed to us and compute boothowto.
351: * Default to SINGLE and ASKNAME if no args or
352: * SINGLE and DFLTROOT if this is a ramdisk kernel.
353: */
354: #ifdef RAMDISK_HOOKS
355: boothowto = RB_SINGLE | RB_DFLTROOT;
356: #else
357: boothowto = RB_SINGLE | RB_ASKNAME;
358: #endif /* RAMDISK_HOOKS */
359:
360: dobootopts(argc, argv);
361:
362: /*
363: * Figure out where we was booted from.
364: */
365: cp = Bios_GetEnvironmentVariable("OSLoadPartition");
366: if (cp == NULL)
367: cp = "unknown";
368: if (makebootdev(cp, bootdriveoffs))
369: bios_printf("Boot device unrecognized: '%s'\n", cp);
370:
371: /*
372: * Read platform-specific environment variables.
373: */
374: switch (sys_config.system_type) {
375: #if defined(TGT_O2)
376: case SGI_O2:
377: /* get ethernet address from ARCBIOS */
378: cp = Bios_GetEnvironmentVariable("eaddr");
379: if (cp != NULL && strlen(cp) > 0)
380: strlcpy(bios_enaddr, cp, sizeof bios_enaddr);
381: break;
382: #endif
383: default:
384: break;
385: }
386:
387: /*
388: * Set pagesize to enable use of page macros and functions.
389: * Commit available memory to UVM system
390: */
391: uvmexp.pagesize = PAGE_SIZE;
392: uvm_setpagesize();
393:
394: for (i = 0; i < MAXMEMSEGS && mem_layout[i].mem_first_page != 0; i++) {
395: u_int32_t fp, lp;
396: u_int32_t firstkernpage, lastkernpage;
397: paddr_t firstkernpa, lastkernpa;
398:
399: if (IS_XKPHYS((vaddr_t)start))
400: firstkernpa = XKPHYS_TO_PHYS((vaddr_t)start);
401: else
402: firstkernpa = KSEG0_TO_PHYS((vaddr_t)start);
403: if (IS_XKPHYS((vaddr_t)ekern))
404: lastkernpa = XKPHYS_TO_PHYS((vaddr_t)ekern);
405: else
406: lastkernpa = KSEG0_TO_PHYS((vaddr_t)ekern);
407:
408: firstkernpage = atop(trunc_page(firstkernpa));
409: lastkernpage = atop(round_page(lastkernpa));
410:
411: fp = mem_layout[i].mem_first_page;
412: lp = mem_layout[i].mem_last_page;
413:
414: /* Account for kernel and kernel symbol table */
415: if (fp >= firstkernpage && lp < lastkernpage)
416: continue; /* In kernel */
417:
418: if (lp < firstkernpage || fp > lastkernpage) {
419: uvm_page_physload(fp, lp, fp, lp, VM_FREELIST_DEFAULT);
420: continue; /* Outside kernel */
421: }
422:
423: if (fp >= firstkernpage)
424: fp = lastkernpage;
425: else if (lp < lastkernpage)
426: lp = firstkernpage;
427: else { /* Need to split! */
428: u_int32_t xp = firstkernpage;
429: uvm_page_physload(fp, xp, fp, xp, VM_FREELIST_DEFAULT);
430: fp = lastkernpage;
431: }
432: if (lp >= fp)
433: uvm_page_physload(fp, lp, fp, lp, VM_FREELIST_DEFAULT);
434: }
435:
436:
437: switch (sys_config.system_type) {
438: #if defined(TGT_O2)
439: case SGI_O2:
440: sys_config.cpu[0].type = (cp0_get_prid() >> 8) & 0xff;
441: sys_config.cpu[0].vers_maj = (cp0_get_prid() >> 4) & 0x0f;
442: sys_config.cpu[0].vers_min = cp0_get_prid() & 0x0f;
443: sys_config.cpu[0].fptype = (cp1_get_prid() >> 8) & 0xff;
444: sys_config.cpu[0].fpvers_maj = (cp1_get_prid() >> 4) & 0x0f;
445: sys_config.cpu[0].fpvers_min = cp1_get_prid() & 0x0f;
446:
447: /*
448: * Configure TLB.
449: */
450: switch(sys_config.cpu[0].type) {
451: case MIPS_RM7000:
452: /* Rev A (version >= 2) CPU's have 64 TLB entries. */
453: if (sys_config.cpu[0].vers_maj < 2) {
454: sys_config.cpu[0].tlbsize = 48;
455: } else {
456: sys_config.cpu[0].tlbsize = 64;
457: }
458: break;
459:
460: case MIPS_R10000:
461: case MIPS_R12000:
462: sys_config.cpu[0].tlbsize = 64;
463: break;
464:
465: default:
466: sys_config.cpu[0].tlbsize = 48;
467: break;
468: }
469: break;
470: #endif
471: default:
472: break;
473: }
474:
475: /*
476: * Configure Cache.
477: */
478: switch(sys_config.cpu[0].type) {
479: case MIPS_R10000:
480: case MIPS_R12000:
481: case MIPS_R14000:
482: sys_config.cpu[0].cfg_reg = Mips10k_ConfigCache();
483: sys_config._SyncCache = Mips10k_SyncCache;
484: sys_config._InvalidateICache = Mips10k_InvalidateICache;
485: sys_config._InvalidateICachePage = Mips10k_InvalidateICachePage;
486: sys_config._SyncDCachePage = Mips10k_SyncDCachePage;
487: sys_config._HitSyncDCache = Mips10k_HitSyncDCache;
488: sys_config._IOSyncDCache = Mips10k_IOSyncDCache;
489: sys_config._HitInvalidateDCache = Mips10k_HitInvalidateDCache;
490: break;
491:
492: default:
493: sys_config.cpu[0].cfg_reg = Mips5k_ConfigCache();
494: sys_config._SyncCache = Mips5k_SyncCache;
495: sys_config._InvalidateICache = Mips5k_InvalidateICache;
496: sys_config._InvalidateICachePage = Mips5k_InvalidateICachePage;
497: sys_config._SyncDCachePage = Mips5k_SyncDCachePage;
498: sys_config._HitSyncDCache = Mips5k_HitSyncDCache;
499: sys_config._IOSyncDCache = Mips5k_IOSyncDCache;
500: sys_config._HitInvalidateDCache = Mips5k_HitInvalidateDCache;
501: break;
502: }
503:
504: /*
505: * Last chance to call the bios. Wiping the TLB means
506: * bios data areas are demapped on most systems.
507: * O2's are OK. Does not have mapped bios text or data.
508: */
509: delay(20*1000); /* Let any uart fifo drain... */
510: tlb_set_wired(0);
511: tlb_flush(sys_config.cpu[0].tlbsize);
512: tlb_set_wired(sys_config.cpu[0].tlbwired);
513:
514: #if 0
515: /* XXX Save the following as an example on how to optimize I/O mapping */
516:
517: /*
518: * Set up some fixed mappings. These are so frequently
519: * used so faulting them in will waste to many cycles.
520: */
521: if (sys_config.system_type == MOMENTUM_CP7000G ||
522: sys_config.system_type == MOMENTUM_CP7000 ||
523: sys_config.system_type == GALILEO_EV64240) {
524: struct tlb tlb;
525:
526: tlb.tlb_mask = PG_SIZE_16M;
527: #if defined(LP64)
528: tlb.tlb_hi = vad_to_vpn(0xfffffffffc000000) | 1;
529: tlb.tlb_lo0 = vad_to_pfn(0xfffffffff4000000) | PG_IOPAGE;
530: #else
531: tlb.tlb_hi = vad_to_vpn(0xfc000000) | 1;
532: tlb.tlb_lo0 = vad_to_pfn(0xf4000000) | PG_IOPAGE;
533: #endif
534: tlb.tlb_lo1 = vad_to_pfn(sys_config.cons_ioaddr[0]) | PG_IOPAGE;
535: tlb_write_indexed(2, &tlb);
536:
537: if (sys_config.system_type == GALILEO_EV64240) {
538: tlb.tlb_mask = PG_SIZE_16M;
539: tlb.tlb_hi = vad_to_vpn(0xf8000000) | 1;
540: tlb.tlb_lo0 = vad_to_pfn(sys_config.pci_io[0].bus_base) | PG_IOPAGE;
541: tlb.tlb_lo1 = vad_to_pfn(sys_config.pci_mem[0].bus_base) | PG_IOPAGE;
542: tlb_write_indexed(3, &tlb);
543: }
544: }
545: /* XXX */
546: #endif
547:
548: #if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000)
549: /*
550: * If an IP27 system set up Node 0's HUB.
551: */
552: if (sys_config.system_type == SGI_O200) {
553: IP27_LHUB_S(PI_REGION_PRESENT, 1);
554: IP27_LHUB_S(PI_CALIAS_SIZE, PI_CALIAS_SIZE_0);
555: }
556: #endif
557:
558: /*
559: * Get a console, very early but after initial mapping setup.
560: */
561: consinit();
562: printf("Initial setup done, switching console.\n");
563:
564: /*
565: * Init message buffer.
566: */
567: msgbufbase = (caddr_t)pmap_steal_memory(MSGBUFSIZE, NULL,NULL);
568: initmsgbuf(msgbufbase, MSGBUFSIZE);
569:
570: /*
571: * Allocate U page(s) for proc[0], pm_tlbpid 1.
572: */
573: proc0.p_addr = proc0paddr = curprocpaddr =
574: (struct user *)pmap_steal_memory(USPACE, NULL, NULL);
575: proc0.p_md.md_regs = (struct trap_frame *)&proc0paddr->u_pcb.pcb_regs;
576: tlb_set_pid(1);
577:
578: /*
579: * Allocate system data structures.
580: */
581: i = (vsize_t)allocsys(NULL);
582: sd = (caddr_t)pmap_steal_memory(i, NULL, NULL);
583: allocsys(sd);
584:
585: /*
586: * Bootstrap VM system.
587: */
588: pmap_bootstrap();
589:
590:
591: /*
592: * Copy down exception vector code.
593: */
594: bcopy(tlb_miss_tramp, (char *)TLB_MISS_EXC_VEC,
595: e_tlb_miss_tramp - tlb_miss_tramp);
596: bcopy(xtlb_miss_tramp, (char *)XTLB_MISS_EXC_VEC,
597: e_xtlb_miss_tramp - xtlb_miss_tramp);
598: bcopy(exception, (char *)CACHE_ERR_EXC_VEC, e_exception - exception);
599: bcopy(exception, (char *)GEN_EXC_VEC, e_exception - exception);
600:
601: /*
602: * Turn off bootstrap exception vectors.
603: */
604: setsr(getsr() & ~SR_BOOT_EXC_VEC);
605: proc0.p_md.md_regs->sr = getsr();
606:
607: /*
608: * Clear out the I and D caches.
609: */
610: Mips_SyncCache();
611:
612: #ifdef DDB
613: db_machine_init();
614: if (boothowto & RB_KDB)
615: Debugger();
616: #endif
617:
618: /*
619: * Return new stack pointer.
620: */
621: return ((caddr_t)proc0paddr + USPACE - 64);
622: }
623:
624: /*
625: * Allocate space for system data structures. Doesn't need to be mapped.
626: */
627: caddr_t
628: allocsys(caddr_t v)
629: {
630: caddr_t start;
631:
632: start = v;
633:
634: #define valloc(name, type, num) \
635: (name) = (type *)v; v = (caddr_t)((name)+(num))
636: #ifdef SYSVMSG
637: valloc(msgpool, char, msginfo.msgmax);
638: valloc(msgmaps, struct msgmap, msginfo.msgseg);
639: valloc(msghdrs, struct msg, msginfo.msgtql);
640: valloc(msqids, struct msqid_ds, msginfo.msgmni);
641: #endif
642:
643: return(v);
644: }
645:
646:
647: /*
648: * Decode boot options.
649: */
650: static void
651: dobootopts(int argc, void *argv)
652: {
653: char *cp;
654: int i;
655:
656: /* XXX Should this be done differently, eg env vs. args? */
657: for (i = 1; i < argc; i++) {
658: if (bios_is_32bit)
659: cp = (char *)(long)((int32_t *)argv)[i];
660: else
661: cp = ((char **)argv)[i];
662: if (cp != NULL && strncmp(cp, "OSLoadOptions=", 14) == 0) {
663: if (strcmp(&cp[14], "auto") == 0)
664: boothowto &= ~(RB_SINGLE|RB_ASKNAME);
665: else if (strcmp(&cp[14], "single") == 0)
666: boothowto |= RB_SINGLE;
667: else if (strcmp(&cp[14], "debug") == 0)
668: boothowto |= RB_KDB;
669: }
670: }
671:
672: /* Catch serial consoles on O2's */
673: cp = Bios_GetEnvironmentVariable("ConsoleOut");
674: if (cp != NULL && strncmp(cp, "serial", 6) == 0)
675: boothowto |= RB_SERCONS;
676: }
677:
678:
679: /*
680: * Console initialization: called early on from main,
681: * before vm init or startup. Do enough configuration
682: * to choose and initialize a console.
683: */
684: void
685: consinit()
686: {
687: if (console_ok) {
688: return;
689: }
690: cninit();
691: console_ok = 1;
692: }
693:
694: /*
695: * cpu_startup: allocate memory for variable-sized tables,
696: * initialize cpu, and do autoconfiguration.
697: */
698: void
699: cpu_startup()
700: {
701: vaddr_t minaddr, maxaddr;
702: #ifdef PMAPDEBUG
703: extern int pmapdebug;
704: int opmapdebug = pmapdebug;
705:
706: pmapdebug = 0; /* Shut up pmap debug during bootstrap */
707: #endif
708:
709: /*
710: * Good {morning,afternoon,evening,night}.
711: */
712: printf(version);
713: printf("real mem = %u (%uMB)\n", ptoa(physmem),
714: ptoa(physmem)/1024/1024);
715: printf("rsvd mem = %u (%uMB)\n", ptoa(rsvdmem),
716: ptoa(rsvdmem)/1024/1024);
717:
718: /*
719: * Determine how many buffers to allocate.
720: * We allocate bufcachepercent% of memory for buffer space.
721: */
722: if (bufpages == 0)
723: bufpages = physmem * bufcachepercent / 100;
724:
725: /* Restrict to at most 25% filled kvm */
726: if (bufpages >
727: (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
728: bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
729: PAGE_SIZE / 4;
730:
731: /*
732: * Allocate a submap for exec arguments. This map effectively
733: * limits the number of processes exec'ing at any time.
734: */
735: minaddr = vm_map_min(kernel_map);
736: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
737: 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
738: /* Allocate a submap for physio */
739: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
740: VM_PHYS_SIZE, 0, FALSE, NULL);
741:
742: #ifdef PMAPDEBUG
743: pmapdebug = opmapdebug;
744: #endif
745: printf("avail mem = %u (%uMB)\n", ptoa(uvmexp.free),
746: ptoa(uvmexp.free)/1024/1024);
747:
748: extent_malloc_flags = EX_MALLOCOK;
749:
750: /*
751: * Set up CPU-specific registers, cache, etc.
752: */
753: initcpu();
754:
755: /*
756: * Set up buffers, so they can be used to read disk labels.
757: */
758: bufinit();
759:
760: /*
761: * Configure the system.
762: */
763: if (boothowto & RB_CONFIG) {
764: #ifdef BOOT_CONFIG
765: user_config();
766: #else
767: printf("kernel does not support -c; continuing..\n");
768: #endif
769: }
770: }
771:
772: /*
773: * machine dependent system variables.
774: */
775: int
776: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
777: int *name;
778: u_int namelen;
779: void *oldp;
780: size_t *oldlenp;
781: void *newp;
782: size_t newlen;
783: struct proc *p;
784: {
785: /* all sysctl names at this level are terminal */
786: if (namelen != 1)
787: return ENOTDIR; /* overloaded */
788:
789: switch (name[0]) {
790: default:
791: return EOPNOTSUPP;
792: }
793: }
794:
795: /*
796: * Set registers on exec for native exec format. For o64/64.
797: */
798: void
799: setregs(p, pack, stack, retval)
800: struct proc *p;
801: struct exec_package *pack;
802: u_long stack;
803: register_t *retval;
804: {
805: extern struct proc *machFPCurProcPtr;
806: #if 0
807: /* XXX should check validity of header and perhaps be 32/64 indep. */
808: Elf64_Ehdr *eh = pack->ep_hdr;
809:
810: if ((((eh->e_flags & EF_MIPS_ABI) != E_MIPS_ABI_NONE) &&
811: ((eh->e_flags & EF_MIPS_ABI) != E_MIPS_ABI_O32)) ||
812: ((eh->e_flags & EF_MIPS_ARCH) >= E_MIPS_ARCH_3) ||
813: (eh->e_ident[EI_CLASS] != ELFCLASS32)) {
814: p->p_md.md_flags |= MDP_O32;
815: }
816: #endif
817:
818: #if !defined(__LP64__)
819: p->p_md.md_flags |= MDP_O32;
820: #else
821: p->p_md.md_flags &= ~MDP_O32;
822: #endif
823:
824: bzero((caddr_t)p->p_md.md_regs, sizeof(struct trap_frame));
825: p->p_md.md_regs->sp = stack;
826: p->p_md.md_regs->pc = pack->ep_entry & ~3;
827: p->p_md.md_regs->t9 = pack->ep_entry & ~3; /* abicall req */
828: #if defined(__LP64__)
829: p->p_md.md_regs->sr = SR_FR_32 | SR_XX | SR_KSU_USER | SR_KX | SR_UX |
830: SR_EXL | SR_INT_ENAB;
831: if (sys_config.cpu[0].type == MIPS_R12000 &&
832: sys_config.system_type == SGI_O2)
833: p->p_md.md_regs->sr |= SR_DSD;
834: #else
835: p->p_md.md_regs->sr = SR_KSU_USER|SR_XX|SR_EXL|SR_INT_ENAB;
836: #endif
837: p->p_md.md_regs->sr |= idle_mask & SR_INT_MASK;
838: p->p_md.md_regs->ic = (idle_mask << 8) & IC_INT_MASK;
839: p->p_md.md_flags &= ~MDP_FPUSED;
840: if (machFPCurProcPtr == p)
841: machFPCurProcPtr = (struct proc *)0;
842: p->p_md.md_ss_addr = 0;
843: p->p_md.md_pc_ctrl = 0;
844: p->p_md.md_watch_1 = 0;
845: p->p_md.md_watch_2 = 0;
846:
847: retval[1] = 0;
848: }
849:
850:
851: int waittime = -1;
852:
853: void
854: boot(int howto)
855: {
856:
857: /* take a snap shot before clobbering any registers */
858: if (curproc)
859: savectx(curproc->p_addr, 0);
860:
861: #ifdef DEBUG
862: if (panicstr)
863: stacktrace();
864: #endif
865:
866: if (cold) {
867: /*
868: * If the system is cold, just halt, unless the user
869: * explicitely asked for reboot.
870: */
871: if ((howto & RB_USERREQ) == 0)
872: howto |= RB_HALT;
873: goto haltsys;
874: }
875:
876: boothowto = howto;
877: if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
878: extern struct proc proc0;
879: /* fill curproc with live object */
880: if (curproc == NULL)
881: curproc = &proc0;
882: /*
883: * Synchronize the disks....
884: */
885: waittime = 0;
886: vfs_shutdown();
887:
888: /*
889: * If we've been adjusting the clock, the todr
890: * will be out of synch; adjust it now.
891: */
892: if ((howto & RB_TIMEBAD) == 0) {
893: resettodr();
894: } else {
895: printf("WARNING: not updating battery clock\n");
896: }
897: }
898:
899: (void) splhigh(); /* extreme priority */
900:
901: if (howto & RB_DUMP)
902: dumpsys();
903:
904: haltsys:
905: doshutdownhooks();
906:
907: if (howto & RB_HALT) {
908: if (howto & RB_POWERDOWN) {
909: printf("System Power Down.\n");
910: delay(1000000);
911: Bios_PowerDown();
912: } else {
913: printf("System Halt.\n");
914: delay(1000000);
915: Bios_EnterInteractiveMode();
916: }
917: printf("Didn't want to die!!! Reset manually.\n");
918: } else {
919: printf("System restart.\n");
920: delay(1000000);
921: Bios_Reboot();
922: printf("Restart failed!!! Reset manually.\n");
923: }
924: for (;;) ;
925: /*NOTREACHED*/
926: }
927:
928: int dumpmag = (int)0x8fca0101; /* magic number for savecore */
929: int dumpsize = 0; /* also for savecore */
930: long dumplo = 0;
931:
932: void
933: dumpconf(void)
934: {
935: int nblks;
936:
937: if (dumpdev == NODEV ||
938: (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
939: return;
940: if (nblks <= ctod(1))
941: return;
942:
943: dumpsize = ptoa(physmem);
944: if (dumpsize > btoc(dbtob(nblks - dumplo)))
945: dumpsize = btoc(dbtob(nblks - dumplo));
946: else if (dumplo == 0)
947: dumplo = nblks - btodb(ctob(physmem));
948:
949: /*
950: * Don't dump on the first page
951: * in case the dump device includes a disk label.
952: */
953: if (dumplo < btodb(PAGE_SIZE))
954: dumplo = btodb(PAGE_SIZE);
955: }
956:
957: /*
958: * Doadump comes here after turning off memory management and
959: * getting on the dump stack, either when called above, or by
960: * the auto-restart code.
961: */
962: void
963: dumpsys()
964: {
965: extern int msgbufmapped;
966:
967: msgbufmapped = 0;
968: if (dumpdev == NODEV)
969: return;
970: /*
971: * For dumps during autoconfiguration,
972: * if dump device has already configured...
973: */
974: if (dumpsize == 0)
975: dumpconf();
976: if (dumplo < 0)
977: return;
978: printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
979: printf("dump not yet implemented");
980: #if 0 /* XXX HAVE TO FIX XXX */
981: switch (error = (*bdevsw[major(dumpdev)].d_dump)(dumpdev, dumplo,)) {
982:
983: case ENXIO:
984: printf("device bad\n");
985: break;
986:
987: case EFAULT:
988: printf("device not ready\n");
989: break;
990:
991: case EINVAL:
992: printf("area improper\n");
993: break;
994:
995: case EIO:
996: printf("i/o error\n");
997: break;
998:
999: default:
1000: printf("error %d\n", error);
1001: break;
1002:
1003: case 0:
1004: printf("succeeded\n");
1005: }
1006: #endif
1007: }
1008:
1009: void
1010: initcpu()
1011: {
1012: }
1013:
1014: /*
1015: * Convert "xx:xx:xx:xx:xx:xx" string to ethernet hardware address.
1016: */
1017: void
1018: enaddr_aton(const char *s, u_int8_t *a)
1019: {
1020: int i;
1021:
1022: if (s != NULL) {
1023: for(i = 0; i < 6; i++) {
1024: a[i] = atoi(s, 16, &s);
1025: if (*s == ':')
1026: s++;
1027: }
1028: }
1029: }
1030:
1031: /*
1032: * Convert an ASCII string into an integer.
1033: */
1034: static int
1035: atoi(const char *s, int b, const char **o)
1036: {
1037: int c;
1038: unsigned base = b, d;
1039: int neg = 0, val = 0;
1040:
1041: if (s == NULL || *s == 0) {
1042: if (o != NULL)
1043: *o = s;
1044: return 0;
1045: }
1046:
1047: /* skip spaces if any */
1048: do {
1049: c = *s++;
1050: } while (c == ' ' || c == '\t');
1051:
1052: /* parse sign, allow more than one (compat) */
1053: while (c == '-') {
1054: neg = !neg;
1055: c = *s++;
1056: }
1057:
1058: /* parse base specification, if any */
1059: if (c == '0') {
1060: c = *s++;
1061: switch (c) {
1062: case 'X':
1063: case 'x':
1064: base = 16;
1065: c = *s++;
1066: break;
1067: case 'B':
1068: case 'b':
1069: base = 2;
1070: c = *s++;
1071: break;
1072: default:
1073: base = 8;
1074: }
1075: }
1076:
1077: /* parse number proper */
1078: for (;;) {
1079: if (c >= '0' && c <= '9')
1080: d = c - '0';
1081: else if (c >= 'a' && c <= 'z')
1082: d = c - 'a' + 10;
1083: else if (c >= 'A' && c <= 'Z')
1084: d = c - 'A' + 10;
1085: else
1086: break;
1087: val *= base;
1088: val += d;
1089: c = *s++;
1090: }
1091: if (neg)
1092: val = -val;
1093: if (o != NULL)
1094: *o = s - 1;
1095: return val;
1096: }
1097:
1098: /*
1099: * RM7000 Performance counter support.
1100: */
1101:
1102: int
1103: rm7k_perfcntr(cmd, arg1, arg2, arg3)
1104: int cmd;
1105: long arg1, arg2, arg3;
1106: {
1107: int result;
1108: quad_t cntval;
1109: struct proc *p = curproc;
1110:
1111:
1112: switch(cmd) {
1113: case PCNT_FNC_SELECT:
1114: if ((arg1 & 0xff) > PCNT_SRC_MAX ||
1115: (arg1 & ~(PCNT_CE|PCNT_UM|PCNT_KM|0xff)) != 0) {
1116: result = EINVAL;
1117: break;
1118: }
1119: #ifdef DEBUG
1120: printf("perfcnt select %x, proc %p\n", arg1, p);
1121: #endif
1122: p->p_md.md_pc_count = 0;
1123: p->p_md.md_pc_spill = 0;
1124: p->p_md.md_pc_ctrl = arg1;
1125: result = 0;
1126: break;
1127:
1128: case PCNT_FNC_READ:
1129: cntval = p->p_md.md_pc_count;
1130: cntval += (quad_t)p->p_md.md_pc_spill << 31;
1131: result = copyout(&cntval, (void *)arg1, sizeof(cntval));
1132: break;
1133:
1134: default:
1135: #ifdef DEBUG
1136: printf("perfcnt error %d\n", cmd);
1137: #endif
1138: result = -1;
1139: break;
1140: }
1141: return(result);
1142: }
1143:
1144: /*
1145: * Called when the performance counter d31 gets set.
1146: * Increase spill value and reset d31.
1147: */
1148: void
1149: rm7k_perfintr(trapframe)
1150: struct trap_frame *trapframe;
1151: {
1152: struct proc *p = curproc;
1153:
1154: printf("perfintr proc %p!\n", p);
1155: cp0_setperfcount(cp0_getperfcount() & 0x7fffffff);
1156: if (p != NULL) {
1157: p->p_md.md_pc_spill++;
1158: }
1159: }
1160:
1161: int
1162: rm7k_watchintr(trapframe)
1163: struct trap_frame *trapframe;
1164: {
1165: return(0);
1166: }
1167:
1168: #ifdef DEBUG
1169: /*
1170: * Dump TLB contents.
1171: */
1172: void
1173: dump_tlb()
1174: {
1175: char *attr[] = {
1176: "CWTNA", "CWTA ", "UCBL ", "CWB ", "RES ", "RES ", "UCNB ", "BPASS"
1177: };
1178:
1179: int tlbno, last;
1180: struct tlb_entry tlb;
1181:
1182: last = 64;
1183:
1184: for (tlbno = 0; tlbno < last; tlbno++) {
1185: tlb_read(tlbno, &tlb);
1186:
1187: if (tlb.tlb_lo0 & PG_V || tlb.tlb_lo1 & PG_V) {
1188: bios_printf("%2d v=%p", tlbno, tlb.tlb_hi & 0xffffffffffffff00);
1189: bios_printf("/%02x ", tlb.tlb_hi & 0xff);
1190:
1191: if (tlb.tlb_lo0 & PG_V) {
1192: bios_printf("0x%09x ", pfn_to_pad(tlb.tlb_lo0));
1193: bios_printf("%c", tlb.tlb_lo0 & PG_M ? 'M' : ' ');
1194: bios_printf("%c", tlb.tlb_lo0 & PG_G ? 'G' : ' ');
1195: bios_printf(" %s ", attr[(tlb.tlb_lo0 >> 3) & 7]);
1196: } else {
1197: bios_printf("invalid ");
1198: }
1199:
1200: if (tlb.tlb_lo1 & PG_V) {
1201: bios_printf("0x%08x ", pfn_to_pad(tlb.tlb_lo1));
1202: bios_printf("%c", tlb.tlb_lo1 & PG_M ? 'M' : ' ');
1203: bios_printf("%c", tlb.tlb_lo1 & PG_G ? 'G' : ' ');
1204: bios_printf(" %s ", attr[(tlb.tlb_lo1 >> 3) & 7]);
1205: } else {
1206: bios_printf("invalid ");
1207: }
1208: bios_printf(" sz=%x", tlb.tlb_mask);
1209: }
1210: else {
1211: bios_printf("%2d v=invalid ", tlbno);
1212: }
1213: bios_printf("\n");
1214: }
1215: }
1216: #endif
CVSweb