xref: /netbsd-src/sys/arch/cesfic/cesfic/machdep.c (revision 924795e69c8bb3f17afd8fcbb799710cc1719dc4)
1 /*	$NetBSD: machdep.c,v 1.72 2021/10/09 20:00:41 tsutsui Exp $	*/
2 
3 /*
4  * Copyright (c) 1988 University of Utah.
5  * Copyright (c) 1982, 1986, 1990, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * the Systems Programming Group of the University of Utah Computer
10  * Science Department.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * from: Utah $Hdr: machdep.c 1.74 92/12/20$
37  *
38  *	@(#)machdep.c	8.10 (Berkeley) 4/20/94
39  */
40 
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.72 2021/10/09 20:00:41 tsutsui Exp $");
43 
44 #include "opt_bufcache.h"
45 #include "opt_ddb.h"
46 #include "opt_kgdb.h"
47 #include "opt_compat_netbsd.h"
48 #include "opt_sysv.h"
49 #include "opt_panicbutton.h"
50 #include "opt_modular.h"
51 
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/buf.h>
55 #include <sys/callout.h>
56 #include <sys/conf.h>
57 #include <sys/exec.h>
58 #include <sys/exec_aout.h>		/* for MID_* */
59 #include <sys/file.h>
60 #include <sys/ioctl.h>
61 #include <sys/kernel.h>
62 #include <sys/malloc.h>
63 #include <sys/mbuf.h>
64 #include <sys/mount.h>
65 #include <sys/msgbuf.h>
66 #include <sys/proc.h>
67 #include <sys/reboot.h>
68 #include <sys/signalvar.h>
69 #include <sys/syscallargs.h>
70 #include <sys/tty.h>
71 #include <sys/vnode.h>
72 #include <sys/ksyms.h>
73 #include <sys/module.h>
74 #include <sys/cpu.h>
75 #include <sys/kgdb.h>
76 
77 #include <machine/db_machdep.h>
78 #include <ddb/db_sym.h>
79 #include <ddb/db_extern.h>
80 
81 #include <machine/autoconf.h>
82 #include <machine/cpu.h>
83 #include <machine/reg.h>
84 #include <machine/pcb.h>
85 #include <machine/psl.h>
86 #include <machine/pte.h>
87 
88 #define	MAXMEM	64*1024	/* XXX - from cmap.h */
89 
90 #include <uvm/uvm_extern.h>
91 
92 #include <sys/sysctl.h>
93 #include <sys/device.h>
94 #include <dev/cons.h>
95 #include <dev/mm.h>
96 #include <dev/ic/z8530reg.h>
97 #include <machine/z8530var.h>
98 #include <cesfic/dev/zsvar.h>
99 
100 #include "ksyms.h"
101 
102 /* the following is used externally (sysctl_hw) */
103 char machine[] = MACHINE;		/* CPU "architecture" */
104 
105 /* Our exported CPU info; we can have only one. */
106 struct cpu_info cpu_info_store;
107 
108 struct vm_map *phys_map = NULL;
109 
110 /*
111  * Declare these as initialized data so we can patch them.
112  */
113 /*int	maxmem;*/			/* max memory per process */
114 extern psize_t physmem;			/* max supported memory, changes to actual */
115 
116 extern	u_int lowram;
117 
118 void fic_init(void);
119 
120 /* prototypes for local functions */
121 void    identifycpu(void);
122 char	*hexstr(int, int);
123 
124 /* functions called from locore.s */
125 void    dumpsys(void);
126 void    straytrap(int, u_short);
127 void	nmihand(struct frame);
128 
129 int	delay_divisor;		/* delay constant */
130 
131 extern void sicinit(void*);
132 
133 void fic_init(void)
134 {
135 	int i;
136 
137 	extern paddr_t avail_start, avail_end;
138 
139 	boothowto = RB_SINGLE; /* XXX for now */
140 	boothowto |= RB_KDB; /* XXX for now */
141 
142 	delay_divisor = 30; /* XXX */
143 
144 	/*
145 	 * Tell the VM system about available physical memory.  The
146 	 * fic uses one segment.
147 	 */
148 	uvm_page_physload(atop(avail_start), atop(avail_end),
149 	    atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT);
150 
151 	/*
152 	 * map and init interrupt controller
153 	 */
154 	physaccess((void*)virtual_avail, (void*)0x44000000,
155 	    PAGE_SIZE, PG_RW|PG_CI);
156 	sicinit((void*)virtual_avail);
157 	virtual_avail += PAGE_SIZE;
158 
159 	/*
160 	 * Initialize error message buffer (at end of core).
161 	 * avail_end was pre-decremented in pmap_bootstrap to compensate.
162 	 */
163 	for (i = 0; i < btoc(MSGBUFSIZE); i++)
164 		pmap_enter(pmap_kernel(), (vaddr_t)msgbufaddr + i * PAGE_SIZE,
165 		    avail_end + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE,
166 		    VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED);
167 	pmap_update(pmap_kernel());
168 	initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE));
169 }
170 
171 int
172 zs_check_kgdb(struct zs_chanstate *cs, int dev)
173 {
174 
175 	if((boothowto & RB_KDB) && (dev == makedev(10, 0)))
176 		return (1);
177 	return (0);
178 }
179 
180 void zs_kgdb_cnputc(dev_t, int);
181 void zs_kgdb_cnputc(dev_t dev, int c)
182 {
183 	zscnputc(dev, c);
184 }
185 int zs_kgdb_cngetc(dev_t);
186 int zs_kgdb_cngetc(dev_t dev)
187 {
188 	return (zscngetc(dev));
189 }
190 
191 /*
192  * Console initialization: called early on from main,
193  * before vm init or startup.  Do enough configuration
194  * to choose and initialize a console.
195  */
196 extern void sic_enable_int(int, int, int, int, int);
197 void
198 consinit(void)
199 {
200 
201 	/*
202 	 * Initialize the console before we print anything out.
203 	 */
204 	physaccess((void*)virtual_avail,
205 	    (void*)0x58000000, PAGE_SIZE, PG_RW|PG_CI);
206 	zs_cnattach((void*)virtual_avail);
207 	virtual_avail += PAGE_SIZE;
208 
209 #ifdef KGDB
210         kgdb_dev = 1;
211         kgdb_attach((void*)zscngetc, (void*)zscnputc, (void *)0);
212 
213 	if (boothowto & RB_KDB) {
214 		kgdb_connect(1);
215 		zscons.cn_putc = zs_kgdb_cnputc;
216 		zscons.cn_getc = zs_kgdb_cngetc;
217 	}
218 #endif
219 #ifdef DDB
220 	if (boothowto & RB_KDB)
221 		Debugger();
222 #endif
223 	sic_enable_int(39, 2, 1, 7, 0); /* NMI */
224 }
225 
226 /*
227  * cpu_startup: allocate memory for variable-sized tables,
228  * initialize CPU, and do autoconfiguration.
229  */
230 void
231 cpu_startup(void)
232 {
233 	vaddr_t minaddr, maxaddr;
234 #ifdef DEBUG
235 	extern int pmapdebug;
236 	int opmapdebug = pmapdebug;
237 
238 	pmapdebug = 0;
239 #endif
240 
241 	cpu_setmodel("FIC8234");
242 	if (fputype != FPU_NONE)
243 		m68k_make_fpu_idle_frame();
244 
245 	/*
246 	 * Good {morning,afternoon,evening,night}.
247 	 */
248 	printf("%s%s", copyright, version);
249 	identifycpu();
250 	printf("real mem  = %d\n", ctob(physmem));
251 
252 	minaddr = 0;
253 
254 	/*
255 	 * Allocate a submap for physio
256 	 */
257 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
258 				   VM_PHYS_SIZE, 0, false, NULL);
259 
260 #ifdef DEBUG
261 	pmapdebug = opmapdebug;
262 #endif
263 	printf("avail mem = %ld\n", ptoa(uvm_availmem(false)));
264 }
265 
266 /*
267  * Info for CTL_HW
268  */
269 
270 void
271 identifycpu(void)
272 {
273 	printf("%s\n", cpu_getmodel());
274 	printf("delay constant: %d\n", delay_divisor);
275 }
276 
277 /*
278  * machine dependent system variables.
279  */
280 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
281 {
282 
283 	sysctl_createv(clog, 0, NULL, NULL,
284 		       CTLFLAG_PERMANENT,
285 		       CTLTYPE_NODE, "machdep", NULL,
286 		       NULL, 0, NULL, 0,
287 		       CTL_MACHDEP, CTL_EOL);
288 
289 	sysctl_createv(clog, 0, NULL, NULL,
290 		       CTLFLAG_PERMANENT,
291 		       CTLTYPE_STRUCT, "console_device", NULL,
292 		       sysctl_consdev, 0, NULL, sizeof(dev_t),
293 		       CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
294 }
295 
296 int	waittime = -1;
297 
298 void
299 cpu_reboot(int howto, char *bootstr)
300 {
301 	struct pcb *pcb = lwp_getpcb(curlwp);
302 
303 	/* take a snap shot before clobbering any registers */
304 	if (pcb != NULL)
305 		savectx(pcb);
306 
307 	/* If system is cold, just halt. */
308 	if (cold) {
309 		howto |= RB_HALT;
310 		goto haltsys;
311 	}
312 
313 	boothowto = howto;
314 	if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
315 		waittime = 0;
316 		vfs_shutdown();
317 		/*
318 		 * If we've been adjusting the clock, the todr
319 		 * will be out of synch; adjust it now.
320 		 */
321 		resettodr();
322 	}
323 
324 	/* Disable interrupts. */
325 	splhigh();
326 
327 	/* If rebooting and a dump is requested do it. */
328 	if (howto & RB_DUMP)
329 		dumpsys();
330 
331  haltsys:
332 	/* Run any shutdown hooks. */
333 	doshutdownhooks();
334 
335 	pmf_system_shutdown(boothowto);
336 
337 #if defined(PANICWAIT) && !defined(DDB)
338 	if ((howto & RB_HALT) == 0 && panicstr) {
339 		printf("hit any key to reboot...\n");
340 		cnpollc(1);
341 		(void)cngetc();
342 		cnpollc(0);
343 		printf("\n");
344 	}
345 #endif
346 
347 	/* Finally, halt/reboot the system. */
348 	if (howto & RB_HALT) {
349 		printf("System halted.  Hit any key to reboot.\n\n");
350 		cnpollc(1);
351 		(void)cngetc();
352 		cnpollc(0);
353 	}
354 
355 	printf("rebooting...\n");
356 	DELAY(1000000);
357 	doboot();
358 	/*NOTREACHED*/
359 }
360 
361 /*
362  * These variables are needed by /sbin/savecore
363  */
364 u_int32_t dumpmag = 0x8fca0101;	/* magic number */
365 int	dumpsize = 0;		/* pages */
366 long	dumplo = 0;		/* blocks */
367 
368 /*
369  * This is called by main to set dumplo and dumpsize.
370  * Dumps always skip the first CLBYTES of disk space
371  * in case there might be a disk label stored there.
372  * If there is extra space, put dump at the end to
373  * reduce the chance that swapping trashes it.
374  */
375 void
376 cpu_dumpconf(void)
377 {
378 	int nblks;	/* size of dump area */
379 
380 	if (dumpdev == NODEV)
381 		return;
382 	nblks = bdev_size(dumpdev);
383 	if (nblks <= ctod(1))
384 		return;
385 
386 	/*
387 	 * XXX include the final RAM page which is not included in physmem.
388 	 */
389 	dumpsize = physmem + 1;
390 
391 	/* Always skip the first CLBYTES, in case there is a label there. */
392 	if (dumplo < ctod(1))
393 		dumplo = ctod(1);
394 
395 	/* Put dump at end of partition, and make it fit. */
396 	if (dumpsize > dtoc(nblks - dumplo))
397 		dumpsize = dtoc(nblks - dumplo);
398 	if (dumplo < nblks - ctod(dumpsize))
399 		dumplo = nblks - ctod(dumpsize);
400 }
401 
402 /*
403  * Dump physical memory onto the dump device.  Called by doadump()
404  * in locore.s or by cpu_reboot() here in machdep.c
405  */
406 void
407 dumpsys(void)
408 {
409 	const struct bdevsw *bdev;
410 	daddr_t blkno;		/* current block to write */
411 				/* dump routine */
412 	int (*dump)(dev_t, daddr_t, void *, size_t);
413 	int pg;			/* page being dumped */
414 	vm_offset_t maddr;	/* PA being dumped */
415 	int error;		/* error code from (*dump)() */
416 
417 	/* Don't put dump messages in msgbuf. */
418 	msgbufmapped = 0;
419 
420 	/* Make sure dump device is valid. */
421 	if (dumpdev == NODEV)
422 		return;
423 	bdev = bdevsw_lookup(dumpdev);
424 	if (bdev == NULL)
425 		return;
426 	if (dumpsize == 0) {
427 		cpu_dumpconf();
428 		if (dumpsize == 0)
429 			return;
430 	}
431 	if (dumplo < 0)
432 		return;
433 	dump = bdev->d_dump;
434 	blkno = dumplo;
435 
436 	printf("\ndumping to dev %"PRIx64", offset %ld\n", dumpdev, dumplo);
437 
438 	printf("dump ");
439 	maddr = lowram;
440 	for (pg = 0; pg < dumpsize; pg++) {
441 #define NPGMB	(1024*1024/PAGE_SIZE)
442 		/* print out how many MBs we have dumped */
443 		if (pg && (pg % NPGMB) == 0)
444 			printf("%d ", pg / NPGMB);
445 #undef NPGMB
446 		pmap_enter(pmap_kernel(), (vm_offset_t)vmmap, maddr,
447 		    VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
448 		pmap_update(pmap_kernel());
449 
450 		error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE);
451 		switch (error) {
452 		case 0:
453 			maddr += PAGE_SIZE;
454 			blkno += btodb(PAGE_SIZE);
455 			break;
456 
457 		case ENXIO:
458 			printf("device bad\n");
459 			return;
460 
461 		case EFAULT:
462 			printf("device not ready\n");
463 			return;
464 
465 		case EINVAL:
466 			printf("area improper\n");
467 			return;
468 
469 		case EIO:
470 			printf("i/o error\n");
471 			return;
472 
473 		case EINTR:
474 			printf("aborted from console\n");
475 			return;
476 
477 		default:
478 			printf("error %d\n", error);
479 			return;
480 		}
481 	}
482 	printf("succeeded\n");
483 }
484 
485 void
486 straytrap(int pc, u_short evec)
487 {
488 	printf("unexpected trap (vector offset %x) from %x\n",
489 	       evec & 0xFFF, pc);
490 }
491 
492 /* XXX should change the interface, and make one badaddr() function */
493 
494 int	*nofault;
495 
496 int
497 badaddr(void *addr)
498 {
499 	int i;
500 	label_t	faultbuf;
501 
502 	nofault = (int *) &faultbuf;
503 	if (setjmp((label_t *)nofault)) {
504 		nofault = (int *) 0;
505 		return (1);
506 	}
507 	i = *(volatile short *)addr;
508 	__USE(i);
509 	nofault = (int *) 0;
510 	return (0);
511 }
512 
513 int
514 badbaddr(void *addr)
515 {
516 	int i;
517 	label_t	faultbuf;
518 
519 	nofault = (int *) &faultbuf;
520 	if (setjmp((label_t *)nofault)) {
521 		nofault = (int *) 0;
522 		return (1);
523 	}
524 	i = *(volatile char *)addr;
525 	__USE(i);
526 	nofault = (int *) 0;
527 	return (0);
528 }
529 
530 #ifdef PANICBUTTON
531 /*
532  * Declare these so they can be patched.
533  */
534 int panicbutton = 1;	/* non-zero if panic buttons are enabled */
535 int candbdiv = 2;	/* give em half a second (hz / candbdiv) */
536 
537 void	candbtimer(void *);
538 
539 int crashandburn;
540 
541 void
542 candbtimer(void *arg)
543 {
544 
545 	crashandburn = 0;
546 }
547 #endif /* PANICBUTTON */
548 
549 static int innmihand;	/* simple mutex */
550 
551 /*
552  * Level 7 interrupts can be caused by the keyboard or parity errors.
553  */
554 void
555 nmihand(struct frame frame)
556 {
557 
558 	/* Prevent unwanted recursion. */
559 	if (innmihand)
560 		return;
561 	innmihand = 1;
562 
563 	printf("NMI\n");
564 #if defined(DDB) || defined(KGDB)
565 	Debugger();
566 #endif
567 
568 	innmihand = 0;
569 }
570 
571 
572 /*
573  * cpu_exec_aout_makecmds():
574  *	CPU-dependent a.out format hook for execve().
575  *
576  * Determine of the given exec package refers to something which we
577  * understand and, if so, set up the vmcmds for it.
578  *
579  * XXX what are the special cases for the hp300?
580  * XXX why is this COMPAT_NOMID?  was something generating
581  *	hp300 binaries with an a_mid of 0?  i thought that was only
582  *	done on little-endian machines...  -- cgd
583  */
584 int
585 cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp)
586 {
587 #if defined(COMPAT_NOMID) || defined(COMPAT_44)
588 	u_long midmag, magic;
589 	u_short mid;
590 	int error;
591 	struct exec *execp = epp->ep_hdr;
592 
593 	midmag = ntohl(execp->a_midmag);
594 	mid = (midmag >> 16) & 0xffff;
595 	magic = midmag & 0xffff;
596 
597 	midmag = mid << 16 | magic;
598 
599 	switch (midmag) {
600 #ifdef COMPAT_NOMID
601 	case (MID_ZERO << 16) | ZMAGIC:
602 		error = exec_aout_prep_oldzmagic(l, epp);
603 		return (error);
604 #endif
605 #ifdef COMPAT_44
606 	case (MID_HP300 << 16) | ZMAGIC:
607 		error = exec_aout_prep_oldzmagic(l, epp);
608 		return (error);
609 #endif
610 	}
611 #endif /* !(defined(COMPAT_NOMID) || defined(COMPAT_44)) */
612 
613 	return ENOEXEC;
614 }
615 
616 int
617 mm_md_physacc(paddr_t pa, vm_prot_t prot)
618 {
619 
620 	return (pa < lowram || pa >= 0xfffffffc) ? EFAULT : 0;
621 }
622 
623 #ifdef MODULAR
624 /*
625  * Push any modules loaded by the bootloader etc.
626  */
627 void
628 module_init_md(void)
629 {
630 }
631 #endif
632