1 /*        $NetBSD: machdep.c,v 1.191 2024/03/05 14:15:29 thorpej Exp $          */
2 
3 /*
4  * Copyright (c) 1988 University of Utah.
5  * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
6  * 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.63 91/04/24$
37  *
38  *        @(#)machdep.c       7.16 (Berkeley) 6/3/91
39  */
40 
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.191 2024/03/05 14:15:29 thorpej Exp $");
43 
44 #include "opt_ddb.h"
45 #include "opt_compat_netbsd.h"
46 #include "opt_mbtype.h"
47 #include "opt_modular.h"
48 #include "opt_panicbutton.h"
49 
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/signalvar.h>
53 #include <sys/kernel.h>
54 #include <sys/proc.h>
55 #include <sys/buf.h>
56 #include <sys/reboot.h>
57 #include <sys/conf.h>
58 #include <sys/file.h>
59 #include <sys/device.h>
60 #include <sys/kmem.h>
61 #include <sys/mbuf.h>
62 #include <sys/msgbuf.h>
63 #include <sys/vnode.h>
64 #include <sys/queue.h>
65 #include <sys/mount.h>
66 #include <sys/syscallargs.h>
67 #include <sys/ksyms.h>
68 #include <sys/module.h>
69 #include <sys/intr.h>
70 #include <sys/exec.h>
71 #include <sys/exec_aout.h>
72 #include <sys/cpu.h>
73 #include <sys/exec_elf.h>
74 #include <sys/bus.h>
75 
76 #include <uvm/uvm_extern.h>
77 
78 #include <sys/sysctl.h>
79 
80 #include <machine/db_machdep.h>
81 #include <ddb/db_sym.h>
82 #include <ddb/db_extern.h>
83 
84 #include <machine/reg.h>
85 #include <machine/psl.h>
86 #include <machine/pte.h>
87 
88 #include <dev/cons.h>
89 #include <dev/mm.h>
90 
91 #include "ksyms.h"
92 #include "nvr.h"
93 
94 #define   DEV_NVRAM 11        /* Nvram minor-number */
95 
96 static void bootsync(void);
97 static void call_sicallbacks(void);
98 static void identifycpu(void);
99 void      straymfpint(int, u_short);
100 void      straytrap(int, u_short);
101 
102 #ifdef _MILANHW_
103 void      nmihandler(void);
104 #endif
105 
106 struct vm_map *phys_map = NULL;
107 
108 void *    msgbufaddr;
109 vaddr_t   msgbufpa;
110 
111 extern  int   freebufspace;
112 extern    u_int lowram;
113 
114 /*
115  * For the fpu emulation and the fpu driver
116  */
117 int       fputype = 0;
118 
119 /* the following is used externally (sysctl_hw) */
120 char      machine[] = MACHINE;          /* from <machine/param.h> */
121 
122 /* Our exported CPU info; we can have only one. */
123 struct cpu_info cpu_info_store;
124 
125  /*
126  * Console initialization: called early on from main,
127  * before vm init or startup.  Do enough configuration
128  * to choose and initialize a console.
129  */
130 void
consinit(void)131 consinit(void)
132 {
133           int i;
134 
135           /*
136            * Initialize error message buffer. pmap_bootstrap() has
137            * positioned this at the end of kernel memory segment - map
138            * and initialize it now.
139            */
140           for (i = 0; i < btoc(MSGBUFSIZE); i++)
141                     pmap_kenter_pa((vaddr_t)msgbufaddr + i * PAGE_SIZE,
142                         msgbufpa + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, 0);
143           pmap_update(pmap_kernel());
144           initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE));
145 
146           /*
147            * Initialize hardware that support various console types like
148            * the grf and PCI busses.
149            */
150           config_console();
151 
152           /*
153            * Now pick the best console candidate.
154            */
155           cninit();
156 
157 #if NKSYMS || defined(DDB) || defined(MODULAR)
158           {
159                     extern int end;
160                     extern int *esym;
161 
162                     ksyms_addsyms_elf((int)esym - (int)&end - sizeof(Elf32_Ehdr),
163                         (void *)&end, esym);
164           }
165 #endif
166 #if defined (DDB)
167           if (boothowto & RB_KDB)
168                     Debugger();
169 #endif
170 }
171 
172 /*
173  * cpu_startup: allocate memory for variable-sized tables,
174  * initialize CPU, and do autoconfiguration.
175  */
176 void
cpu_startup(void)177 cpu_startup(void)
178 {
179           char pbuf[9];
180 #ifdef DEBUG
181           extern int pmapdebug;
182           int opmapdebug = pmapdebug;
183 #endif
184           vaddr_t minaddr, maxaddr;
185           extern vsize_t mem_size;      /* from pmap.c */
186 
187 #ifdef DEBUG
188           pmapdebug = 0;
189 #endif
190 
191           if (fputype != FPU_NONE)
192                     m68k_make_fpu_idle_frame();
193 
194           /*
195            * Good {morning,afternoon,evening,night}.
196            */
197           printf("%s%s", copyright, version);
198           identifycpu();
199 
200           format_bytes(pbuf, sizeof(pbuf), mem_size);
201           printf("total memory = %s\n", pbuf);
202 
203           minaddr = 0;
204 
205           /*
206            * Allocate a submap for physio
207            */
208           phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
209               VM_PHYS_SIZE, 0, false, NULL);
210 
211 #ifdef DEBUG
212           pmapdebug = opmapdebug;
213 #endif
214           format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false)));
215           printf("avail memory = %s\n", pbuf);
216 }
217 
218 /*
219  * Info for CTL_HW
220  */
221 static void
identifycpu(void)222 identifycpu(void)
223 {
224           const char *mach, *mmu, *fpu, *cpu;
225           uint32_t pcr;
226           char cputxt[30];
227 
228           switch (machineid & ATARI_ANYMACH) {
229           case ATARI_TT:
230                     mach = "Atari TT";
231                     break;
232           case ATARI_FALCON:
233                     mach = "Atari Falcon";
234                     break;
235           case ATARI_HADES:
236                     mach = "Atari Hades";
237                     break;
238           case ATARI_MILAN:
239                     mach = "Atari Milan";
240                     break;
241           default:
242                     mach = "Atari UNKNOWN";
243                     break;
244           }
245 
246           cpu     = "m68k";
247           fputype = fpu_probe();
248           fpu     = fpu_describe(fputype);
249 
250           switch (cputype) {
251           case CPU_68060:
252                     __asm(".word 0x4e7a,0x0808;"
253                         "movl %%d0,%0" : "=d"(pcr) : : "d0");
254                     snprintf(cputxt, sizeof(cputxt), "MC68%s060 rev.%d",
255                         pcr & 0x10000 ? "LC/EC" : "", (pcr >> 8) & 0xff);
256                     cpu = cputxt;
257                     mmu = "/MMU";
258                     break;
259           case CPU_68040:
260                     cpu = "MC68040";
261                     mmu = "/MMU";
262                     break;
263           case CPU_68030:
264                     cpu = "MC68030";
265                     mmu = "/MMU";
266                     break;
267           default: /* XXX */
268                     cpu = "MC68020";
269                     mmu = " MC68851 MMU";
270           }
271           cpu_setmodel("%s (%s CPU%s%sFPU)", mach, cpu, mmu, fpu);
272           printf("%s\n", cpu_getmodel());
273 }
274 
275 /*
276  * machine dependent system variables.
277  */
278 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
279 {
280 
281           sysctl_createv(clog, 0, NULL, NULL,
282                            CTLFLAG_PERMANENT,
283                            CTLTYPE_NODE, "machdep", NULL,
284                            NULL, 0, NULL, 0,
285                            CTL_MACHDEP, CTL_EOL);
286 
287           sysctl_createv(clog, 0, NULL, NULL,
288                            CTLFLAG_PERMANENT,
289                            CTLTYPE_STRUCT, "console_device", NULL,
290                            sysctl_consdev, 0, NULL, sizeof(dev_t),
291                            CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
292 }
293 
294 static int waittime = -1;
295 
296 static void
bootsync(void)297 bootsync(void)
298 {
299           if (waittime < 0) {
300                     waittime = 0;
301                     vfs_shutdown();
302           }
303 }
304 
305 void
cpu_reboot(int howto,char * bootstr)306 cpu_reboot(int howto, char *bootstr)
307 {
308           struct pcb *pcb = lwp_getpcb(curlwp);
309 
310           /* take a snap shot before clobbering any registers */
311           if (pcb != NULL)
312                     savectx(pcb);
313 
314           boothowto = howto;
315           if ((howto & RB_NOSYNC) == 0)
316                     bootsync();
317 
318           /*
319            * Call shutdown hooks. Do this _before_ anything might be
320            * asked to the user in case nobody is there....
321            */
322           doshutdownhooks();
323 
324           pmf_system_shutdown(boothowto);
325 
326           splhigh();                              /* extreme priority */
327           if (howto & RB_HALT) {
328                     printf("halted\n\n");
329                     __asm("   stop      #0x2700");
330           } else {
331                     if (howto & RB_DUMP)
332                               dumpsys();
333 
334                     doboot();
335                     /*NOTREACHED*/
336           }
337           panic("Boot() should never come here");
338           /*NOTREACHED*/
339 }
340 
341 #define   BYTES_PER_DUMP      PAGE_SIZE /* Must be a multiple of PAGE_SIZE */
342 static vaddr_t      dumpspace;          /* Virt. space to map dumppages         */
343 
344 /*
345  * Reserve _virtual_ memory to map in the page to be dumped
346  */
347 vaddr_t
reserve_dumppages(vaddr_t p)348 reserve_dumppages(vaddr_t p)
349 {
350 
351           dumpspace = p;
352           return p + BYTES_PER_DUMP;
353 }
354 
355 uint32_t  dumpmag  = 0x8fca0101;        /* magic number for savecore  */
356 int                 dumpsize = 0;                 /* also for savecore (pages)  */
357 long                dumplo   = 0;                 /* (disk blocks)              */
358 
359 void
cpu_dumpconf(void)360 cpu_dumpconf(void)
361 {
362           int       nblks, i;
363 
364           for (i = dumpsize = 0; i < NMEM_SEGS; i++) {
365                     if (boot_segs[i].start == boot_segs[i].end)
366                               break;
367                     dumpsize += boot_segs[i].end - boot_segs[i].start;
368           }
369           dumpsize = btoc(dumpsize);
370 
371           if (dumpdev != NODEV) {
372                     nblks = bdev_size(dumpdev);
373                     if (nblks > 0) {
374                               if (dumpsize > btoc(dbtob(nblks - dumplo)))
375                                         dumpsize = btoc(dbtob(nblks - dumplo));
376                               else if (dumplo == 0)
377                                         dumplo = nblks - btodb(ctob(dumpsize));
378                     }
379           }
380           dumplo -= cpu_dumpsize();
381 
382           /*
383            * Don't dump on the first PAGE_SIZE (why PAGE_SIZE?)
384            * in case the dump device includes a disk label.
385            */
386           if (dumplo < btodb(PAGE_SIZE))
387                     dumplo = btodb(PAGE_SIZE);
388 }
389 
390 /*
391  * Doadump comes here after turning off memory management and
392  * getting on the dump stack, either when called above, or by
393  * the auto-restart code.
394  */
395 void
dumpsys(void)396 dumpsys(void)
397 {
398           const struct bdevsw *bdev;
399           daddr_t   blkno;              /* Current block to write     */
400           int       (*dump)(dev_t, daddr_t, void *, size_t);
401                                         /* Dumping function           */
402           u_long    maddr;              /* PA being dumped            */
403           int       segbytes; /* Number of bytes in this seg.         */
404           int       segnum;             /* Segment we are dumping     */
405           int       nbytes;             /* Bytes left to dump                   */
406           int       i, n, error;
407 
408           error = segnum = 0;
409           if (dumpdev == NODEV)
410                     return;
411           bdev = bdevsw_lookup(dumpdev);
412           if (bdev == NULL)
413                     return;
414           /*
415            * For dumps during autoconfiguration,
416            * if dump device has already configured...
417            */
418           if (dumpsize == 0)
419                     cpu_dumpconf();
420           if (dumplo <= 0) {
421                     printf("\ndump to dev %u,%u not possible\n",
422                         major(dumpdev), minor(dumpdev));
423                     return;
424           }
425           printf("\ndumping to dev %u,%u offset %ld\n",
426               major(dumpdev), minor(dumpdev), dumplo);
427 
428 #if defined(DDB) || defined(PANICWAIT)
429           printf("Do you want to dump memory? [y]");
430           cnpollc(1);
431           i = cngetc();
432           cnpollc(0);
433           cnputc(i);
434           switch (i) {
435           case 'n':
436           case 'N':
437                     return;
438           case '\n':
439                     break;
440           default :
441                     cnputc('\n');
442           }
443 #endif /* defined(DDB) || defined(PANICWAIT) */
444 
445           maddr    = 0;
446           segbytes = boot_segs[0].end;
447           blkno    = dumplo;
448           dump     = bdev->d_dump;
449           nbytes   = dumpsize * PAGE_SIZE;
450 
451           printf("dump ");
452 
453           error = cpu_dump(dump, &blkno);
454           if (!error) {
455                     for (i = 0; i < nbytes; i += n, segbytes -= n) {
456                               /*
457                                * Skip the hole
458                                */
459                               if (segbytes == 0) {
460                                         segnum++;
461                                         maddr    = boot_segs[segnum].start;
462                                         segbytes = boot_segs[segnum].end -
463                                             boot_segs[segnum].start;
464                               }
465                               /*
466                                * Print Mb's to go
467                                */
468                               n = nbytes - i;
469                               if (n && (n % (1024 * 1024)) == 0)
470                                         printf_nolog("%d ", n / (1024 * 1024));
471 
472                               /*
473                                * Limit transfer to BYTES_PER_DUMP
474                                */
475                               if (n > BYTES_PER_DUMP)
476                                         n = BYTES_PER_DUMP;
477 
478                               /*
479                                * Map to a VA and write it
480                                */
481                               if (maddr != 0) { /* XXX kvtop chokes on this     */
482                                         (void)pmap_map(dumpspace, maddr, maddr + n,
483                                             VM_PROT_READ);
484                                         error = (*dump)(dumpdev, blkno,
485                                             (void *)dumpspace, n);
486                                         if (error)
487                                                   break;
488                               }
489 
490                               maddr += n;
491                               blkno += btodb(n);
492                     }
493           }
494           switch (error) {
495 
496           case ENXIO:
497                     printf("device bad\n");
498                     break;
499 
500           case EFAULT:
501                     printf("device not ready\n");
502                     break;
503 
504           case EINVAL:
505                     printf("area improper\n");
506                     break;
507 
508           case EIO:
509                     printf("i/o error\n");
510                     break;
511 
512           default:
513                     printf("succeeded\n");
514                     break;
515           }
516           printf("\n\n");
517           delay(5000000);               /* 5 seconds */
518 }
519 
520 void
straytrap(int pc,u_short evec)521 straytrap(int pc, u_short evec)
522 {
523           static int prev_evec;
524 
525           printf("unexpected trap (vector offset 0x%x) from 0x%x\n",
526               evec & 0xFFF, pc);
527 
528           if (prev_evec == evec) {
529                     delay(1000000);
530                     prev_evec = 0;
531           } else
532                     prev_evec = evec;
533 }
534 
535 void
straymfpint(int pc,u_short evec)536 straymfpint(int pc, u_short evec)
537 {
538 
539           printf("unexpected mfp-interrupt (vector offset 0x%x) from 0x%x\n",
540                  evec & 0xFFF, pc);
541 }
542 
543 int       *nofault;
544 
545 int
badbaddr(void * addr,int size)546 badbaddr(void *addr, int size)
547 {
548           int i;
549           label_t   faultbuf;
550 
551           nofault = (int *) &faultbuf;
552           if (setjmp((label_t *)nofault)) {
553                     nofault = (int *) 0;
554                     return 1;
555           }
556           switch (size) {
557           case 1:
558                     i = *(volatile uint8_t *)addr;
559                     break;
560           case 2:
561                     i = *(volatile uint16_t *)addr;
562                     break;
563           case 4:
564                     i = *(volatile uint32_t *)addr;
565                     break;
566           default:
567                     panic("badbaddr: unknown size");
568           }
569           __USE(i);
570           nofault = (int *)0;
571           return 0;
572 }
573 
574 /*
575  * this is a handy package to have asynchronously executed
576  * function calls executed at very low interrupt priority.
577  * Example for use is keyboard repeat, where the repeat
578  * handler running at splclock() triggers such a (hardware
579  * aided) software interrupt.
580  * Note: the installed functions are currently called in a
581  * LIFO fashion, might want to change this to FIFO
582  * later.
583  *
584  * XXX: Some of functions which use this callback should be rewritten
585  * XXX: to use MI softintr(9) directly.
586  */
587 struct si_callback {
588           struct si_callback *next;
589           void (*function)(void *rock1, void *rock2);
590           void *rock1, *rock2;
591 };
592 static void *si_callback_cookie;
593 static struct si_callback *si_callbacks;
594 static struct si_callback *si_free;
595 #ifdef DIAGNOSTIC
596 static int ncbd;    /* number of callback blocks dynamically allocated */
597 #endif
598 
599 void
init_sicallback(void)600 init_sicallback(void)
601 {
602 
603           si_callback_cookie = softint_establish(SOFTINT_NET,
604               (void (*)(void *))call_sicallbacks, NULL);
605 }
606 
607 void
add_sicallback(void (* function)(void *,void *),void * rock1,void * rock2)608 add_sicallback(void (*function)(void *, void *), void *rock1, void *rock2)
609 {
610           struct si_callback *si;
611           int s;
612 
613           /*
614            * this function may be called from high-priority interrupt handlers.
615            * We may NOT block for  memory-allocation in here!.
616            */
617           s = splhigh();
618           if ((si = si_free) != NULL)
619                     si_free = si->next;
620           splx(s);
621 
622           if (si == NULL) {
623                     si = kmem_intr_alloc(sizeof(*si), KM_NOSLEEP);
624 #ifdef DIAGNOSTIC
625                     if (si)
626                               ++ncbd;             /* count # dynamically allocated */
627 #endif
628                     if (si == NULL)
629                               return;
630           }
631 
632           si->function = function;
633           si->rock1    = rock1;
634           si->rock2    = rock2;
635 
636           s = splhigh();
637           si->next     = si_callbacks;
638           si_callbacks = si;
639           splx(s);
640 
641           /*
642            * and cause a software interrupt (spl1). This interrupt might
643            * happen immediately, or after returning to a safe enough level.
644            *
645            * XXX:
646            * According to <machine/scu.h> and lev1intr() handler in locore.s,
647            * at least _ATARIHW_ machines (ATARITT and HADES?) seem to have
648            * some hardware support which can initiate real hardware interrupt
649            * at ipl 1 for software interrupt. But as per <machine/mtpr.h>,
650            * this feature was not used at all on setsoft*() calls and
651            * traditional hp300 derived ssir (simulated software interrupt
652            * request) on VAX REI emulation in locore.s is used.
653            */
654           softint_schedule(si_callback_cookie);
655 }
656 
657 void
rem_sicallback(void (* function)(void * rock1,void * rock2))658 rem_sicallback(void (*function)(void *rock1, void *rock2))
659 {
660           struct si_callback *si, *psi, *nsi;
661           int s;
662 
663           s = splhigh();
664           for (psi = 0, si = si_callbacks; si; ) {
665                     nsi = si->next;
666 
667                     if (si->function != function)
668                               psi = si;
669                     else {
670                               si->next = si_free;
671                               si_free  = si;
672                               if (psi != NULL)
673                                         psi->next = nsi;
674                               else
675                                         si_callbacks = nsi;
676                     }
677                     si = nsi;
678           }
679           splx(s);
680 }
681 
682 /* purge the list */
683 static void
call_sicallbacks(void)684 call_sicallbacks(void)
685 {
686           struct si_callback *si;
687           int s;
688           void *rock1, *rock2;
689           void (*function)(void *, void *);
690 
691           do {
692                     s = splhigh();
693                     if ((si = si_callbacks) != NULL)
694                               si_callbacks = si->next;
695                     splx(s);
696 
697                     if (si != NULL) {
698                               function = si->function;
699                               rock1    = si->rock1;
700                               rock2    = si->rock2;
701                               s = splhigh();
702                               if (si_callbacks)
703                                         softint_schedule(si_callback_cookie);
704                               si->next = si_free;
705                               si_free  = si;
706                               splx(s);
707 
708                               /*
709                                * Raise spl for BASEPRI() checks to see
710                                * nested interrupts in some drivers using callbacks
711                                * since modern MI softint(9) doesn't seem to do it
712                                * in !__HAVE_FAST_SOFTINTS case.
713                                *
714                                * XXX: This is just a workaround hack.
715                                *      Each driver should raise spl in its handler
716                                *      to avoid nested interrupts if necessary.
717                                */
718                               s = splsoftnet();   /* XXX */
719                               function(rock1, rock2);
720                               splx(s);
721                     }
722           } while (si != NULL);
723 #ifdef DIAGNOSTIC
724           if (ncbd) {
725 #ifdef DEBUG
726                     printf("call_sicallback: %d more dynamic structures\n", ncbd);
727 #endif
728                     ncbd = 0;
729           }
730 #endif
731 }
732 
733 #if defined(DEBUG) && !defined(PANICBUTTON)
734 #define PANICBUTTON
735 #endif
736 
737 #ifdef PANICBUTTON
738 int panicbutton = 1;          /* non-zero if panic buttons are enabled */
739 int crashandburn = 0;
740 int candbdelay = 50;          /* give em half a second */
741 
742 void candbtimer(void);
743 
744 void
candbtimer(void)745 candbtimer(void)
746 {
747 
748           crashandburn = 0;
749 }
750 #endif
751 
752 /*
753  * should only get here, if no standard executable. This can currently
754  * only mean, we're reading an old ZMAGIC file without MID, but since Atari
755  * ZMAGIC always worked the `right' way (;-)) just ignore the missing
756  * MID and proceed to new zmagic code ;-)
757  */
758 int
cpu_exec_aout_makecmds(struct lwp * l,struct exec_package * epp)759 cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp)
760 {
761           int error = ENOEXEC;
762 #ifdef COMPAT_NOMID
763           struct exec *execp = epp->ep_hdr;
764 #endif
765 
766 #ifdef COMPAT_NOMID
767           if (!((execp->a_midmag >> 16) & 0x0fff)
768               && execp->a_midmag == ZMAGIC)
769                     return exec_aout_prep_zmagic(l->l_proc, epp);
770 #endif
771           return error;
772 }
773 
774 #ifdef MODULAR
775 /*
776  * Push any modules loaded by the bootloader etc.
777  */
778 void
module_init_md(void)779 module_init_md(void)
780 {
781 }
782 #endif
783 
784 #ifdef _MILANHW_
785 
786 /*
787  * Currently the only source of NMI interrupts on the Milan is the PLX9080.
788  * On access errors to the PCI bus, an NMI is generated. This NMI is shorted
789  * in locore in case of a PCI config cycle to a non-existing address to allow
790  * for probes. On other occasions, it ShouldNotHappen(TM).
791  * Note: The handler in locore clears the errors, to make further PCI access
792  * possible.
793  */
794 void
nmihandler(void)795 nmihandler(void)
796 {
797           extern unsigned long          plx_status;
798 
799           printf("nmihandler: plx_status = 0x%08lx\n", plx_status);
800 }
801 #endif
802 
803 int
mm_md_physacc(paddr_t pa,vm_prot_t prot)804 mm_md_physacc(paddr_t pa, vm_prot_t prot)
805 {
806           struct memseg *ms;
807 
808           for (ms = boot_segs; ms->start != ms->end; ms++) {
809                     if ((pa >= ms->start) && (pa < ms->end))
810                               return 0;
811           }
812           return EFAULT;
813 }
814 
815 int
mm_md_readwrite(dev_t dev,struct uio * uio)816 mm_md_readwrite(dev_t dev, struct uio *uio)
817 {
818           switch (minor(dev)) {
819           case DEV_NVRAM:
820 #if NNVR > 0
821                     return nvram_uio(uio);
822 #else
823                     return ENXIO;
824 #endif
825           default:
826                     return ENXIO;
827           }
828 }
829