xref: /openbsd/sys/arch/luna88k/luna88k/machdep.c (revision bb00e811)
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