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