1 /* $OpenBSD: machdep.c,v 1.144 2023/10/24 13:20:10 claudio 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 * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
46 * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
47 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
48 *
49 * Carnegie Mellon requests users of this software to return to
50 *
51 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
52 * School of Computer Science
53 * Carnegie Mellon University
54 * Pittsburgh PA 15213-3890
55 *
56 * any improvements or extensions that they make and grant Carnegie the
57 * rights to redistribute these changes.
58 */
59
60 #include <sys/param.h>
61 #include <sys/systm.h>
62 #include <sys/kernel.h>
63 #include <sys/clockintr.h>
64 #include <sys/proc.h>
65 #include <sys/user.h>
66 #include <sys/buf.h>
67 #include <sys/reboot.h>
68 #include <sys/conf.h>
69 #include <sys/device.h>
70 #include <sys/malloc.h>
71 #include <sys/mount.h>
72 #include <sys/msgbuf.h>
73 #include <sys/syscallargs.h>
74 #include <sys/exec.h>
75 #include <sys/sysctl.h>
76 #include <sys/errno.h>
77 #include <sys/extent.h>
78 #include <sys/core.h>
79 #include <sys/kcore.h>
80
81 #include <machine/asm.h>
82 #include <machine/asm_macro.h>
83 #include <machine/board.h>
84 #include <machine/cmmu.h>
85 #include <machine/cpu.h>
86 #include <machine/kcore.h>
87 #include <machine/reg.h>
88 #include <machine/trap.h>
89 #include <machine/m88100.h>
90
91 #include <luna88k/luna88k/isr.h>
92
93 #include <dev/cons.h>
94
95 #include <net/if.h>
96 #include <uvm/uvm_extern.h>
97
98 #include "ksyms.h"
99 #if DDB
100 #include <machine/db_machdep.h>
101 #include <ddb/db_extern.h>
102 #include <ddb/db_interface.h>
103 #include <ddb/db_output.h> /* db_printf() */
104 #endif /* DDB */
105
106 void consinit(void);
107 #ifdef MULTIPROCESSOR
108 void cpu_boot_secondary_processors(void);
109 #endif
110 void cpu_setup_secondary_processors(void);
111 void dumpconf(void);
112 void dumpsys(void);
113 int getcpuspeed(void);
114 void get_fuse_rom_data(void);
115 void get_nvram_data(void);
116 void identifycpu(void);
117 void luna88k_bootstrap(void);
118 #ifdef MULTIPROCESSOR
119 void luna88k_ipi_handler(struct trapframe *);
120 #endif
121 struct cpu_info *luna88k_set_cpu_number(cpuid_t);
122 void luna88k_vector_init(uint32_t *, uint32_t *);
123 char *nvram_by_symbol(char *);
124 void powerdown(void);
125 void savectx(struct pcb *);
126 void secondary_main(void);
127 void *secondary_pre_main(void);
128 void setlevel(u_int);
129 vaddr_t size_memory(void);
130
131 extern int clockintr(void *); /* in clock.c */
132 extern void get_autoboot_device(void); /* in autoconf.c */
133
134 u_int32_t int_set_val[INT_LEVEL] = {
135 INT_SET_LV0,
136 INT_SET_LV1,
137 INT_SET_LV2,
138 INT_SET_LV3,
139 INT_SET_LV4,
140 INT_SET_LV5,
141 INT_SET_LV6,
142 INT_SET_LV7
143 };
144
145 /*
146 * FUSE ROM and NVRAM data
147 */
148 struct fuse_rom_byte {
149 u_int32_t h;
150 u_int32_t l;
151 };
152 #define FUSE_ROM_BYTES (FUSE_ROM_SPACE / sizeof(struct fuse_rom_byte))
153 char fuse_rom_data[FUSE_ROM_BYTES];
154
155 #define NNVSYM 8
156 #define NVSYMLEN 16
157 #define NVVALLEN 16
158 struct nvram_t {
159 char symbol[NVSYMLEN];
160 char value[NVVALLEN];
161 } nvram[NNVSYM];
162
163 register_t kernel_vbr;
164 int physmem; /* available physical memory, in pages */
165
166 struct vm_map *exec_map = NULL;
167 struct vm_map *phys_map = NULL;
168
169 __cpu_simple_lock_t cpu_hatch_mutex = __SIMPLELOCK_UNLOCKED;
170 #ifdef MULTIPROCESSOR
171 __cpu_simple_lock_t cpu_boot_mutex = __SIMPLELOCK_LOCKED;
172 unsigned int hatch_pending_count;
173 vaddr_t hatch_stacks[MAXCPUS - 1];
174 #endif
175
176 struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 };
177 struct uvm_constraint_range *uvm_md_constraints[] = { NULL };
178
179 /*
180 * Info for CTL_HW
181 */
182 char machine[] = MACHINE; /* cpu "architecture" */
183 char cpu_model[120];
184
185 #if defined(DDB) || NKSYMS > 0
186 extern char *esym;
187 #endif
188
189 int machtype = LUNA_88K; /* may be overwritten in cpu_startup() */
190 int cputyp = CPU_88100;
191 int cpuspeed = 33; /* safe guess */
192 int sysconsole = 0; /* 0 = ttya, may be overwritten in locore0.S */
193 u_int16_t dipswitch = 0; /* set in locore0.S */
194 int hwplanebits; /* set in locore0.S */
195
196 extern struct consdev syscons; /* in dev/siotty.c */
197
198 extern void syscnattach(int); /* in dev/siotty.c */
199 extern int omfb_cnattach(void); /* in dev/lunafb.c */
200 extern void ws_cnattach(void); /* in dev/lunaws.c */
201
202 vaddr_t first_addr;
203 vaddr_t last_addr;
204
205 extern struct user *proc0paddr;
206
207 /*
208 * Early console initialization: called early on from main, before vm init.
209 */
210 void
consinit()211 consinit()
212 {
213 /*
214 * Initialize the console before we print anything out.
215 */
216 if (sysconsole == 0) {
217 syscnattach(0);
218 } else {
219 omfb_cnattach();
220 ws_cnattach();
221 }
222
223 #if defined(DDB)
224 db_machine_init();
225 ddb_init();
226 if (boothowto & RB_KDB)
227 db_enter();
228 #endif
229 }
230
231 /*
232 * Figure out how much real memory is available.
233 * Start looking from the megabyte after the end of the kernel data,
234 * until we find non-memory.
235 */
236 vaddr_t
size_memory()237 size_memory()
238 {
239 unsigned int *volatile look;
240 unsigned int *max;
241 #define PATTERN 0x5a5a5a5a
242 #define STRIDE (4*1024) /* 4k at a time */
243 #define Roundup(value, stride) (((unsigned)(value) + (stride) - 1) & ~((stride)-1))
244 /*
245 * count it up.
246 */
247 max = (void *)MAXPHYSMEM;
248 for (look = (void *)first_addr; look < max;
249 look = (int *)((unsigned)look + STRIDE)) {
250 unsigned save;
251
252 /* if can't access, we've reached the end */
253 if (badaddr((vaddr_t)look, 4)) {
254 look = (int *)((int)look - STRIDE);
255 break;
256 }
257
258 /*
259 * If we write a value, we expect to read the same value back.
260 * We'll do this twice, the 2nd time with the opposite bit
261 * pattern from the first, to make sure we check all bits.
262 */
263 save = *look;
264 if (*look = PATTERN, *look != PATTERN)
265 break;
266 if (*look = ~PATTERN, *look != ~PATTERN)
267 break;
268 *look = save;
269 }
270
271 return (trunc_page((vaddr_t)look));
272 }
273
274 int
getcpuspeed()275 getcpuspeed()
276 {
277 switch(machtype) {
278 case LUNA_88K:
279 return 25;
280 case LUNA_88K2:
281 return 33;
282 default:
283 panic("getcpuspeed: can not determine CPU speed");
284 }
285 }
286
287 void
identifycpu()288 identifycpu()
289 {
290 cpuspeed = getcpuspeed();
291 snprintf(cpu_model, sizeof cpu_model,
292 "OMRON LUNA-88K%s, %dMHz",
293 machtype == LUNA_88K2 ? "2" : "", cpuspeed);
294 }
295
296 void
cpu_startup()297 cpu_startup()
298 {
299 vaddr_t minaddr, maxaddr;
300
301 /* Determine the machine type from FUSE ROM data. */
302 get_fuse_rom_data();
303 if (strncmp(fuse_rom_data, "MNAME=LUNA88K+", 14) == 0) {
304 machtype = LUNA_88K2;
305 }
306
307 /* Determine the 'auto-boot' device from NVRAM data */
308 get_nvram_data();
309 get_autoboot_device();
310
311 /*
312 * Good {morning,afternoon,evening,night}.
313 */
314 printf("%s", version);
315 identifycpu();
316 printf("real mem = %lu (%luMB)\n", ptoa(physmem),
317 ptoa(physmem) / 1024 / 1024);
318
319 /*
320 * Check front DIP switch setting
321 */
322 #ifdef DEBUG
323 printf("dipsw = 0x%x\n", dipswitch);
324 #endif
325
326 /* Check DIP switch 1 - 1 */
327 if ((0x8000 & dipswitch) == 0) {
328 boothowto |= RB_SINGLE;
329 }
330
331 /* Check DIP switch 1 - 3 */
332 if ((0x2000 & dipswitch) == 0) {
333 boothowto |= RB_ASKNAME;
334 }
335
336 /* Check DIP switch 1 - 4 */
337 if ((0x1000 & dipswitch) == 0) {
338 boothowto |= RB_CONFIG;
339 }
340
341 /*
342 * Check frame buffer depth.
343 */
344 switch (hwplanebits) {
345 case 0: /* No frame buffer */
346 case 1:
347 case 4:
348 case 8:
349 break;
350 default:
351 printf("unexpected frame buffer depth = %d\n", hwplanebits);
352 hwplanebits = 0;
353 break;
354 }
355
356 /*
357 * Allocate a submap for exec arguments. This map effectively
358 * limits the number of processes exec'ing at any time.
359 */
360 minaddr = vm_map_min(kernel_map);
361 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
362 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
363
364 /*
365 * Allocate map for physio.
366 */
367 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
368 VM_PHYS_SIZE, 0, FALSE, NULL);
369
370 printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free),
371 ptoa(uvmexp.free) / 1024 / 1024);
372
373 /*
374 * Set up buffers, so they can be used to read disk labels.
375 */
376 bufinit();
377
378 /*
379 * Initialize the autovectored interrupt list.
380 */
381 isrinit();
382
383 /*
384 * Configure the system.
385 */
386 if (boothowto & RB_CONFIG) {
387 #ifdef BOOT_CONFIG
388 user_config();
389 #else
390 printf("kernel does not support -c; continuing..\n");
391 #endif
392 }
393 }
394
395 __dead void
boot(int howto)396 boot(int howto)
397 {
398 if ((howto & RB_RESET) != 0)
399 goto doreset;
400
401 if (curproc && curproc->p_addr)
402 savectx(curpcb);
403
404 if (cold) {
405 if ((howto & RB_USERREQ) == 0)
406 howto |= RB_HALT;
407 goto haltsys;
408 }
409
410 boothowto = howto;
411 if ((howto & RB_NOSYNC) == 0) {
412 vfs_shutdown(curproc);
413
414 if ((howto & RB_TIMEBAD) == 0) {
415 resettodr();
416 } else {
417 printf("WARNING: not updating battery clock\n");
418 }
419 }
420 if_downall();
421
422 uvm_shutdown();
423 splhigh();
424 cold = 1;
425
426 if ((howto & RB_DUMP) != 0)
427 dumpsys();
428
429 haltsys:
430 config_suspend_all(DVACT_POWERDOWN);
431
432 /* LUNA-88K supports automatic powerdown */
433 if ((howto & RB_POWERDOWN) != 0) {
434 printf("attempting to power down...\n");
435 powerdown();
436 /* if failed, fall through. */
437 }
438
439 if ((howto & RB_HALT) != 0) {
440 printf("halted\n\n");
441 } else {
442 doreset:
443 /* Reset all cpus, which causes reboot */
444 *((volatile uint32_t *)RESET_CPU_ALL) = 0;
445 }
446
447 for (;;)
448 continue;
449 /* NOTREACHED */
450 }
451
452 u_long dumpmag = 0x8fca0101; /* magic number for savecore */
453 int dumpsize = 0; /* also for savecore */
454 long dumplo = 0;
455 cpu_kcore_hdr_t cpu_kcore_hdr;
456
457 /*
458 * This is called by configure to set dumplo and dumpsize.
459 * Dumps always skip the first PAGE_SIZE of disk space
460 * in case there might be a disk label stored there.
461 * If there is extra space, put dump at the end to
462 * reduce the chance that swapping trashes it.
463 */
464 void
dumpconf(void)465 dumpconf(void)
466 {
467 int nblks; /* size of dump area */
468
469 if (dumpdev == NODEV ||
470 (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
471 return;
472 if (nblks <= ctod(1))
473 return;
474
475 dumpsize = physmem;
476
477 /* luna88k only uses a single segment. */
478 cpu_kcore_hdr.ram_segs[0].start = 0;
479 cpu_kcore_hdr.ram_segs[0].size = ptoa(physmem);
480 cpu_kcore_hdr.cputype = cputyp;
481
482 /*
483 * Don't dump on the first block
484 * in case the dump device includes a disk label.
485 */
486 if (dumplo < ctod(1))
487 dumplo = ctod(1);
488
489 /* Put dump at end of partition, and make it fit. */
490 if (dumpsize + 1 > dtoc(nblks - dumplo))
491 dumpsize = dtoc(nblks - dumplo) - 1;
492 if (dumplo < nblks - ctod(dumpsize) - 1)
493 dumplo = nblks - ctod(dumpsize) - 1;
494 }
495
496 /*
497 * Doadump comes here after turning off memory management and
498 * getting on the dump stack, either when called above, or by
499 * the auto-restart code.
500 */
501 void
dumpsys()502 dumpsys()
503 {
504 int maj;
505 int psize;
506 daddr_t blkno; /* current block to write */
507 /* dump routine */
508 int (*dump)(dev_t, daddr_t, caddr_t, size_t);
509 int pg; /* page being dumped */
510 paddr_t maddr; /* PA being dumped */
511 int error; /* error code from (*dump)() */
512 kcore_seg_t *kseg_p;
513 cpu_kcore_hdr_t *chdr_p;
514 char dump_hdr[dbtob(1)]; /* XXX assume hdr fits in 1 block */
515
516 extern int msgbufmapped;
517
518 msgbufmapped = 0;
519
520 /* Make sure dump device is valid. */
521 if (dumpdev == NODEV)
522 return;
523 if (dumpsize == 0) {
524 dumpconf();
525 if (dumpsize == 0)
526 return;
527 }
528 maj = major(dumpdev);
529 if (dumplo < 0) {
530 printf("\ndump to dev %u,%u not possible\n", maj,
531 minor(dumpdev));
532 return;
533 }
534 dump = bdevsw[maj].d_dump;
535 blkno = dumplo;
536
537 printf("\ndumping to dev %u,%u offset %ld\n", maj,
538 minor(dumpdev), dumplo);
539
540 /* Setup the dump header */
541 kseg_p = (kcore_seg_t *)dump_hdr;
542 chdr_p = (cpu_kcore_hdr_t *)&dump_hdr[ALIGN(sizeof(*kseg_p))];
543 bzero(dump_hdr, sizeof(dump_hdr));
544
545 CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
546 kseg_p->c_size = dbtob(1) - ALIGN(sizeof(*kseg_p));
547 *chdr_p = cpu_kcore_hdr;
548
549 printf("dump ");
550 psize = (*bdevsw[maj].d_psize)(dumpdev);
551 if (psize == -1) {
552 printf("area unavailable\n");
553 return;
554 }
555
556 /* Dump the header. */
557 error = (*dump)(dumpdev, blkno++, (caddr_t)dump_hdr, dbtob(1));
558 if (error != 0)
559 goto abort;
560
561 maddr = (paddr_t)0;
562 for (pg = 0; pg < dumpsize; pg++) {
563 #define NPGMB (1024 * 1024 / PAGE_SIZE)
564 /* print out how many MBs we have dumped */
565 if (pg != 0 && (pg % NPGMB) == 0)
566 printf("%d ", pg / NPGMB);
567 #undef NPGMB
568 error = (*dump)(dumpdev, blkno, (caddr_t)maddr, PAGE_SIZE);
569 if (error == 0) {
570 maddr += PAGE_SIZE;
571 blkno += btodb(PAGE_SIZE);
572 } else
573 break;
574 }
575 abort:
576 switch (error) {
577 case 0:
578 printf("succeeded\n");
579 break;
580
581 case ENXIO:
582 printf("device bad\n");
583 break;
584
585 case EFAULT:
586 printf("device not ready\n");
587 break;
588
589 case EINVAL:
590 printf("area improper\n");
591 break;
592
593 case EIO:
594 printf("i/o error\n");
595 break;
596
597 case EINTR:
598 printf("aborted from console\n");
599 break;
600
601 default:
602 printf("error %d\n", error);
603 break;
604 }
605 }
606
607 /*
608 * Release cpu_hatch_mutex to let secondary processors initialize.
609 */
610 void
cpu_setup_secondary_processors()611 cpu_setup_secondary_processors()
612 {
613 #ifdef MULTIPROCESSOR
614 unsigned int cpu;
615
616 hatch_pending_count = ncpusfound - 1;
617
618 /*
619 * Allocate idle stack for all the secondary processors here.
620 *
621 * We can't have this done by the secondaries themselves, because
622 * the main processor owns the kernel lock at this point; and we
623 * can't know in advance which cpuid our secondary processors will
624 * have, so we can't fill m88k_cpus[] directly.
625 *
626 * Allocation failure will be checked by the secondary processors
627 * so that we can still run in degraded mode if hell gets loose.
628 */
629 for (cpu = 0; cpu < hatch_pending_count; cpu++)
630 hatch_stacks[cpu] = (vaddr_t)km_alloc(USPACE, &kv_any,
631 &kp_zero, &kd_waitok);
632 #endif
633
634 __cpu_simple_unlock(&cpu_hatch_mutex);
635
636 #ifdef MULTIPROCESSOR
637 while (hatch_pending_count != 0)
638 delay(10000); /* 10ms */
639 #endif
640 }
641
642 struct cpu_info *
luna88k_set_cpu_number(cpuid_t number)643 luna88k_set_cpu_number(cpuid_t number)
644 {
645 struct cpu_info *ci;
646
647 /* clock register for each CPU. */
648 static const uint32_t clock_ack[] = {
649 OBIO_CLOCK0,
650 OBIO_CLOCK1,
651 OBIO_CLOCK2,
652 OBIO_CLOCK3
653 };
654
655 /* hardware interrupt mask and status register for each CPU.
656 *
657 * When written to:
658 * Bits 31 to 26 are used to enable ('1') or disable ('0') each
659 * interrupt level. Bit 31 is for level 6, bit 26 is for level 1.
660 *
661 * When read:
662 * Bits 31 to 29 shows the highest level of current (or most recent?)
663 * interrupt in 3 bits binary value (0 to 7).
664 * Bits 23 to 18 shows the current mask, which is the most recent
665 * written value in bits 31 to 26 as described above.
666 */
667 static const uint32_t intr_mask[] = {
668 INT_ST_MASK0,
669 INT_ST_MASK1,
670 INT_ST_MASK2,
671 INT_ST_MASK3
672 };
673
674 /* software interrupt register for each CPU. */
675 static const uint32_t swi_reg[] = {
676 SOFT_INT0,
677 SOFT_INT1,
678 SOFT_INT2,
679 SOFT_INT3
680 };
681
682 ci = set_cpu_number(number);
683 ci->ci_curspl = IPL_HIGH;
684 ci->ci_swireg = swi_reg[number];
685 ci->ci_intr_mask = intr_mask[number];
686 ci->ci_clock_ack = clock_ack[number];
687 return ci;
688 }
689
690 #ifdef MULTIPROCESSOR
691 /*
692 * Release cpu_boot_mutex to let secondary processors start running
693 * processes.
694 */
695 void
cpu_boot_secondary_processors()696 cpu_boot_secondary_processors()
697 {
698 __cpu_simple_unlock(&cpu_boot_mutex);
699 }
700
701 /*
702 * Secondary CPU early initialization routine.
703 * Determine CPU number and set it, then return the startup stack.
704 *
705 * Running on a minimal stack here, with interrupts disabled; do nothing fancy.
706 */
707 void *
secondary_pre_main()708 secondary_pre_main()
709 {
710 struct cpu_info *ci;
711
712 /*
713 * Invoke the CMMU initialization routine as early as possible,
714 * so that we do not risk any memory writes to be lost during
715 * cache setup.
716 */
717 cmmu_initialize_cpu(cmmu_cpu_number());
718
719 /*
720 * Now initialize your cpu_info structure.
721 */
722 ci = luna88k_set_cpu_number(cmmu_cpu_number());
723 ci->ci_curproc = &proc0;
724 m88100_smp_setup(ci);
725
726 splhigh();
727
728 /*
729 * Enable MMU on this processor.
730 */
731 pmap_bootstrap_cpu(ci->ci_cpuid);
732
733 /*
734 * Return our idle stack for the caller to switch to it.
735 */
736 ci->ci_curpcb = (void *)hatch_stacks[hatch_pending_count - 1];
737 if (ci->ci_curpcb == NULL) {
738 printf("cpu%d: unable to get startup stack\n", ci->ci_cpuid);
739 hatch_pending_count--;
740 __cpu_simple_unlock(&cpu_hatch_mutex);
741 for (;;)
742 continue;
743 /* NOTREACHED */
744 }
745
746 return ci->ci_curpcb;
747 }
748
749 /*
750 * Further secondary CPU initialization.
751 *
752 * We are now running on our startup stack, with proper page tables.
753 * There is nothing to do but display some details about the CPU and its CMMUs.
754 */
755
756 void
secondary_main()757 secondary_main()
758 {
759 struct cpu_info *ci = curcpu();
760
761 cpu_configuration_print(0);
762 ncpus++;
763
764 clockqueue_init(&ci->ci_queue);
765 sched_init_cpu(ci);
766 ci->ci_curproc = NULL;
767 ci->ci_randseed = (arc4random() & 0x7fffffff) + 1;
768
769 /*
770 * Release cpu_hatch_mutex to let other secondary processors
771 * have a chance to run.
772 */
773 hatch_pending_count--;
774 __cpu_simple_unlock(&cpu_hatch_mutex);
775
776 /* wait for cpu_boot_secondary_processors() */
777 __cpu_simple_lock(&cpu_boot_mutex);
778 __cpu_simple_unlock(&cpu_boot_mutex);
779
780 set_vbr(kernel_vbr);
781
782 clockintr_cpu_init(NULL);
783
784 spl0();
785 set_psr(get_psr() & ~PSR_IND);
786
787 SET(ci->ci_flags, CIF_ALIVE);
788
789 sched_toidle();
790 }
791
792 #endif /* MULTIPROCESSOR */
793
794 /*
795 * Device interrupt handler for LUNA-88K
796 */
797
798 void
luna88k_ext_int(struct trapframe * eframe)799 luna88k_ext_int(struct trapframe *eframe)
800 {
801 struct cpu_info *ci = curcpu();
802 uint32_t cur_isr;
803 u_int level, cur_int_level, old_spl;
804 int unmasked = 0;
805
806 cur_isr = *(volatile uint32_t *)ci->ci_intr_mask;
807 old_spl = eframe->tf_mask;
808
809 cur_int_level = cur_isr >> 29;
810
811 /*
812 * Ignore level 0 interrupt and 'hardware lied' interrupt,
813 * as same as CMU Mach do. The 'hardware lied' means that
814 * the received interrupt level is what we have masked before.
815 */
816 if (cur_int_level == 0 ||
817 !(cur_isr & (1 << (cur_int_level + 17))))
818 goto out;
819
820 uvmexp.intrs++;
821
822 #ifdef MULTIPROCESSOR
823 /*
824 * Handle unmaskable IPIs immediately, so that we can reenable
825 * interrupts before further processing. We rely on the interrupt
826 * mask to make sure that if we get an IPI, it's really for us
827 * and no other processor.
828 *
829 * On luna88k, IPL_SOFTINT (level 1 interrupt) is used as IPI.
830 */
831 while (cur_int_level == IPL_SOFTINT) {
832 luna88k_ipi_handler(eframe);
833
834 cur_isr = *(volatile uint32_t *)ci->ci_intr_mask;
835 cur_int_level = cur_isr >> 29;
836 }
837 if (cur_int_level == 0)
838 goto out;
839 #endif
840
841 /*
842 * Service the highest interrupt, in order.
843 */
844 do {
845 level = (cur_int_level > old_spl ? cur_int_level : old_spl);
846 setipl(level);
847
848 if (unmasked == 0) {
849 set_psr(get_psr() & ~PSR_IND);
850 unmasked = 1;
851 }
852
853 switch (cur_int_level) {
854 case 6:
855 clockintr((void *)eframe);
856 break;
857 case 5:
858 case 4:
859 case 3:
860 if (CPU_IS_PRIMARY(ci))
861 isrdispatch_autovec(cur_int_level);
862 break;
863 #ifdef MULTIPROCESSOR
864 case 1:
865 /*
866 * Another processor may have sent us an IPI
867 * while we were servicing a device interrupt.
868 */
869 set_psr(get_psr() | PSR_IND);
870 luna88k_ipi_handler(eframe);
871 set_psr(get_psr() & ~PSR_IND);
872 break;
873 #endif
874 default:
875 printf("%s: cpu%d level %d interrupt.\n",
876 __func__, ci->ci_cpuid, cur_int_level);
877 break;
878 }
879
880 cur_isr = *(volatile uint32_t *)ci->ci_intr_mask;
881 cur_int_level = cur_isr >> 29;
882
883 /* Again, ignore 'hardware lied' interrupt */
884 if ( !(cur_isr & (1 << (cur_int_level + 17))))
885 goto out;
886
887 } while (cur_int_level != 0);
888
889 out:
890 /*
891 * process any remaining data access exceptions before
892 * returning to assembler
893 */
894 if (eframe->tf_dmt0 & DMT_VALID)
895 m88100_trap(T_DATAFLT, eframe);
896
897 /*
898 * Disable interrupts before returning to assembler, the spl will
899 * be restored later.
900 */
901 set_psr(get_psr() | PSR_IND);
902 }
903
904 int
sys_sysarch(p,v,retval)905 sys_sysarch(p, v, retval)
906 struct proc *p;
907 void *v;
908 register_t *retval;
909 {
910 #if 0
911 struct sys_sysarch_args /* {
912 syscallarg(int) op;
913 syscallarg(char *) parm;
914 } */ *uap = v;
915 #endif
916
917 return (ENOSYS);
918 }
919
920 /*
921 * machine dependent system variables.
922 */
923
924 int
cpu_sysctl(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen,struct proc * p)925 cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
926 size_t newlen, struct proc *p)
927 {
928 dev_t consdev;
929
930 /* all sysctl names at this level are terminal */
931 if (namelen != 1)
932 return (ENOTDIR); /* overloaded */
933
934 switch (name[0]) {
935 case CPU_CONSDEV:
936 if (cn_tab != NULL)
937 consdev = cn_tab->cn_dev;
938 else
939 consdev = NODEV;
940 return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
941 sizeof consdev));
942 case CPU_CPUTYPE:
943 return (sysctl_rdint(oldp, oldlenp, newp, cputyp));
944 default:
945 return (EOPNOTSUPP);
946 }
947 /*NOTREACHED*/
948 }
949
950 void
luna88k_vector_init(uint32_t * bootvbr,uint32_t * vectors)951 luna88k_vector_init(uint32_t *bootvbr, uint32_t *vectors)
952 {
953 extern vaddr_t vector_init(uint32_t *, uint32_t *, int); /* gross */
954 extern int kernelstart;
955
956 /*
957 * Set up bootstrap vectors, overwriting the existing PROM vbr
958 * page.
959 */
960 vector_init(bootvbr, vectors, 1);
961
962 /*
963 * Set up final vectors. These will be used by all processors,
964 * once autoconf is over.
965 */
966 kernel_vbr = trunc_page((vaddr_t)&kernelstart);
967 vector_init((uint32_t *)kernel_vbr, vectors, 0);
968 }
969
970 /*
971 * Called from locore0.S during boot,
972 * this is the first C code that's run.
973 */
974 void
luna88k_bootstrap()975 luna88k_bootstrap()
976 {
977 extern const struct cmmu_p cmmu8820x;
978 extern vaddr_t avail_start;
979 extern vaddr_t avail_end;
980 #ifndef MULTIPROCESSOR
981 cpuid_t master_cpu;
982 #endif
983
984 cmmu = &cmmu8820x;
985
986 /* clear and disable all interrupts */
987 *(volatile uint32_t *)INT_ST_MASK0 = 0;
988 *(volatile uint32_t *)INT_ST_MASK1 = 0;
989 *(volatile uint32_t *)INT_ST_MASK2 = 0;
990 *(volatile uint32_t *)INT_ST_MASK3 = 0;
991
992 /* clear software interrupts; just read registers */
993 *(volatile uint32_t *)SOFT_INT0;
994 *(volatile uint32_t *)SOFT_INT1;
995 *(volatile uint32_t *)SOFT_INT2;
996 *(volatile uint32_t *)SOFT_INT3;
997
998 uvmexp.pagesize = PAGE_SIZE;
999 uvm_setpagesize();
1000
1001 first_addr = round_page(first_addr);
1002 last_addr = size_memory();
1003 physmem = atop(last_addr);
1004
1005 setup_board_config();
1006 master_cpu = cmmu_init();
1007 (void)luna88k_set_cpu_number(master_cpu);
1008 #ifdef MULTIPROCESSOR
1009 m88100_smp_setup(curcpu());
1010 #endif
1011 SET(curcpu()->ci_flags, CIF_ALIVE | CIF_PRIMARY);
1012
1013 m88100_apply_patches();
1014
1015 /*
1016 * Now that set_cpu_number() set us with a valid cpu_info pointer,
1017 * we need to initialize p_addr and curpcb before autoconf, for the
1018 * fault handler to behave properly [except for badaddr() faults,
1019 * which can be taken care of without a valid curcpu()].
1020 */
1021 proc0.p_addr = proc0paddr;
1022 curproc = &proc0;
1023 curpcb = &proc0paddr->u_pcb;
1024
1025 avail_start = first_addr;
1026 avail_end = last_addr;
1027
1028 #ifdef DEBUG
1029 printf("LUNA-88K boot: memory from 0x%x to 0x%x\n",
1030 avail_start, avail_end);
1031 #endif
1032
1033 /*
1034 * Tell the VM system about available physical memory.
1035 * luna88k only has one segment.
1036 */
1037 uvm_page_physload(atop(avail_start), atop(avail_end),
1038 atop(avail_start), atop(avail_end), 0);
1039
1040 /*
1041 * Initialize message buffer.
1042 */
1043 initmsgbuf((caddr_t)pmap_steal_memory(MSGBUFSIZE, NULL, NULL),
1044 MSGBUFSIZE);
1045
1046 pmap_bootstrap(0, 0x20000); /* ROM needs 128KB */
1047
1048 /* Initialize the "u-area" pages. */
1049 bzero((caddr_t)curpcb, USPACE);
1050
1051 #ifndef MULTIPROCESSOR
1052 /* Release the cpu_hatch_mutex */
1053 cpu_setup_secondary_processors();
1054 #endif
1055
1056 #ifdef DEBUG
1057 printf("leaving luna88k_bootstrap()\n");
1058 #endif
1059 }
1060
1061 /* powerdown */
1062
1063 struct pio {
1064 volatile u_int8_t portA;
1065 volatile unsigned : 24;
1066 volatile u_int8_t portB;
1067 volatile unsigned : 24;
1068 volatile u_int8_t portC;
1069 volatile unsigned : 24;
1070 volatile u_int8_t cntrl;
1071 volatile unsigned : 24;
1072 };
1073
1074 #define PIO1_POWER 0x04
1075
1076 #define PIO1_ENABLE 0x01
1077 #define PIO1_DISABLE 0x00
1078
1079 void
powerdown(void)1080 powerdown(void)
1081 {
1082 struct pio *p1 = (struct pio *)OBIO_PIO1_BASE;
1083
1084 DELAY(100000);
1085 p1->cntrl = (PIO1_POWER << 1) | PIO1_DISABLE;
1086 *(volatile u_int8_t *)&p1->portC;
1087 }
1088
1089 /* Get data from FUSE ROM */
1090
1091 void
get_fuse_rom_data(void)1092 get_fuse_rom_data(void)
1093 {
1094 int i;
1095 struct fuse_rom_byte *p = (struct fuse_rom_byte *)FUSE_ROM_ADDR;
1096
1097 for (i = 0; i < FUSE_ROM_BYTES; i++) {
1098 fuse_rom_data[i] =
1099 (char)((((p->h) >> 24) & 0x000000f0) |
1100 (((p->l) >> 28) & 0x0000000f));
1101 p++;
1102 }
1103 }
1104
1105 /* Get data from NVRAM */
1106
1107 void
get_nvram_data(void)1108 get_nvram_data(void)
1109 {
1110 int i, j;
1111 u_int8_t *page;
1112 char buf[NVSYMLEN], *data;
1113
1114 if (machtype == LUNA_88K) {
1115 data = (char *)(NVRAM_ADDR + 0x80);
1116
1117 for (i = 0; i < NNVSYM; i++) {
1118 for (j = 0; j < NVSYMLEN; j++) {
1119 buf[j] = *data;
1120 data += 4;
1121 }
1122 strlcpy(nvram[i].symbol, buf, sizeof(nvram[i].symbol));
1123
1124 for (j = 0; j < NVVALLEN; j++) {
1125 buf[j] = *data;
1126 data += 4;
1127 }
1128 strlcpy(nvram[i].value, buf, sizeof(nvram[i].value));
1129 }
1130 } else if (machtype == LUNA_88K2) {
1131 page = (u_int8_t *)(NVRAM_ADDR_88K2 + 0x20);
1132
1133 for (i = 0; i < NNVSYM; i++) {
1134 *page = (u_int8_t)i;
1135
1136 data = (char *)NVRAM_ADDR_88K2;
1137 strlcpy(nvram[i].symbol, data, sizeof(nvram[i].symbol));
1138
1139 data = (char *)(NVRAM_ADDR_88K2 + 0x10);
1140 strlcpy(nvram[i].value, data, sizeof(nvram[i].value));
1141 }
1142 }
1143 }
1144
1145 char *
nvram_by_symbol(symbol)1146 nvram_by_symbol(symbol)
1147 char *symbol;
1148 {
1149 char *value;
1150 int i;
1151
1152 value = NULL;
1153
1154 for (i = 0; i < NNVSYM; i++) {
1155 if (strncmp(nvram[i].symbol, symbol, NVSYMLEN) == 0) {
1156 value = nvram[i].value;
1157 break;
1158 }
1159 }
1160
1161 return value;
1162 }
1163
1164 void
setlevel(u_int level)1165 setlevel(u_int level)
1166 {
1167 u_int32_t set_value;
1168 struct cpu_info *ci = curcpu();
1169
1170 set_value = int_set_val[level];
1171
1172 #ifdef MULTIPROCESSOR
1173 if (!CPU_IS_PRIMARY(ci))
1174 set_value &= INT_SLAVE_MASK;
1175 #endif
1176
1177 ci->ci_curspl = level;
1178 *(volatile uint32_t *)ci->ci_intr_mask = set_value;
1179 /*
1180 * We do not flush the pipeline here, because we are invoked
1181 * with interrupts disabled, and the caller will synchronize
1182 * the pipeline when restoring the psr.
1183 */
1184 }
1185
1186 int
getipl(void)1187 getipl(void)
1188 {
1189 return (int)curcpu()->ci_curspl;
1190 }
1191
1192 int
setipl(int level)1193 setipl(int level)
1194 {
1195 int curspl;
1196 uint32_t psr;
1197 struct cpu_info *ci = curcpu();
1198
1199 psr = get_psr();
1200 set_psr(psr | PSR_IND);
1201
1202 curspl = (int)ci->ci_curspl;
1203 setlevel((u_int)level);
1204
1205 set_psr(psr);
1206 return curspl;
1207 }
1208
1209 int
splraise(int level)1210 splraise(int level)
1211 {
1212 int curspl;
1213 uint32_t psr;
1214 struct cpu_info *ci = curcpu();
1215
1216 psr = get_psr();
1217 set_psr(psr | PSR_IND);
1218
1219 curspl = (int)ci->ci_curspl;
1220 if (curspl < (u_int)level)
1221 setlevel((u_int)level);
1222
1223 set_psr(psr);
1224 return curspl;
1225 }
1226
1227 #ifdef MULTIPROCESSOR
1228 void
m88k_send_ipi(int ipi,cpuid_t cpu)1229 m88k_send_ipi(int ipi, cpuid_t cpu)
1230 {
1231 struct cpu_info *ci = &m88k_cpus[cpu];
1232
1233 if (ci->ci_ipi & ipi)
1234 return;
1235
1236 atomic_setbits_int(&ci->ci_ipi, ipi);
1237 *(volatile uint32_t *)ci->ci_swireg = ~0;
1238 }
1239
1240 /*
1241 * Process inter-processor interrupts.
1242 */
1243
1244 /*
1245 * Unmaskable IPIs - those are processed with interrupts disabled,
1246 * and no lock held.
1247 */
1248 void
luna88k_ipi_handler(struct trapframe * eframe)1249 luna88k_ipi_handler(struct trapframe *eframe)
1250 {
1251 struct cpu_info *ci = curcpu();
1252 int ipi = ci->ci_ipi & (CI_IPI_DDB | CI_IPI_NOTIFY);
1253
1254 /* just read; reset software interrupt */
1255 *(volatile uint32_t *)ci->ci_swireg;
1256 atomic_clearbits_int(&ci->ci_ipi, ipi);
1257
1258 if (ipi & CI_IPI_DDB) {
1259 #ifdef DDB
1260 /*
1261 * Another processor has entered DDB. Spin on the ddb lock
1262 * until it is done.
1263 */
1264 extern struct __mp_lock ddb_mp_lock;
1265
1266 __mp_lock(&ddb_mp_lock);
1267 __mp_unlock(&ddb_mp_lock);
1268
1269 /*
1270 * If ddb is hoping to us, it's our turn to enter ddb now.
1271 */
1272 if (ci->ci_cpuid == ddb_mp_nextcpu)
1273 db_enter();
1274 #endif
1275 }
1276 if (ipi & CI_IPI_NOTIFY) {
1277 /* nothing to do */
1278 }
1279 }
1280
1281 void
m88k_broadcast_ipi(int ipi)1282 m88k_broadcast_ipi(int ipi)
1283 {
1284 struct cpu_info *us = curcpu();
1285 struct cpu_info *ci;
1286 CPU_INFO_ITERATOR cii;
1287
1288 CPU_INFO_FOREACH(cii, ci) {
1289 if (ci == us)
1290 continue;
1291
1292 if (ISSET(ci->ci_flags, CIF_ALIVE))
1293 m88k_send_ipi(ipi, ci->ci_cpuid);
1294 }
1295 }
1296 #endif
1297
1298 unsigned int
cpu_rnd_messybits(void)1299 cpu_rnd_messybits(void)
1300 {
1301 struct timespec ts;
1302
1303 nanotime(&ts);
1304 return (ts.tv_nsec ^ (ts.tv_sec << 20));
1305 }
1306