1 /* $NetBSD: machdep.c,v 1.58 2024/03/05 14:15:28 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * Copyright (c) 1988 University of Utah.
34 * Copyright (c) 1992, 1993
35 * The Regents of the University of California. All rights reserved.
36 *
37 * This code is derived from software contributed to Berkeley by
38 * the Systems Programming Group of the University of Utah Computer
39 * Science Department, The Mach Operating System project at
40 * Carnegie-Mellon University and Ralph Campbell.
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution.
50 * 3. Neither the name of the University nor the names of its contributors
51 * may be used to endorse or promote products derived from this software
52 * without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * SUCH DAMAGE.
65 *
66 * @(#)machdep.c 8.3 (Berkeley) 1/12/94
67 * from: Utah Hdr: machdep.c 1.63 91/04/24
68 */
69
70 #include <sys/cdefs.h>
71 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.58 2024/03/05 14:15:28 thorpej Exp $");
72
73 #include "opt_algor_p4032.h"
74 #include "opt_algor_p5064.h"
75 #include "opt_algor_p6032.h"
76
77 #include "opt_ddb.h"
78 #include "opt_kgdb.h"
79
80 #include "opt_memsize.h"
81 #include "opt_ethaddr.h"
82
83 #include <sys/param.h>
84 #include <sys/boot_flag.h>
85 #include <sys/buf.h>
86 #include <sys/bus.h>
87 #include <sys/device.h>
88 #include <sys/kernel.h>
89 #include <sys/kcore.h>
90 #include <sys/ksyms.h>
91 #include <sys/lwp.h>
92 #include <sys/mount.h>
93 #include <sys/reboot.h>
94 #include <sys/systm.h>
95 #include <sys/termios.h>
96 #include <sys/cpu.h>
97
98 #include <net/if.h>
99 #include <net/if_ether.h>
100
101 #include <uvm/uvm_extern.h>
102
103 #include <dev/cons.h>
104
105 #include <mips/locore.h>
106 #include <mips/pcb.h>
107
108 #ifdef DDB
109 #include <mips/db_machdep.h>
110 #include <ddb/db_extern.h>
111 #endif
112
113 #include <machine/pmon.h>
114 #include <algor/autoconf.h>
115
116 #include <algor/pci/vtpbcvar.h>
117
118 #include "ksyms.h"
119
120 #include "com.h"
121 #if NCOM > 0
122 #include <dev/ic/comreg.h>
123 #include <dev/ic/comvar.h>
124
125 int comcnrate = TTYDEF_SPEED;
126 #endif /* NCOM > 0 */
127
128 #if defined(ALGOR_P4032) + \
129 defined(ALGOR_P5064) + \
130 defined(ALGOR_P6032) + \
131 0 != 1
132 #error Must configure exactly one platform.
133 #endif
134
135 #ifdef ALGOR_P4032
136 #include <algor/algor/algor_p4032reg.h>
137 #include <algor/algor/algor_p4032var.h>
138 struct p4032_config p4032_configuration;
139 #endif
140
141 #ifdef ALGOR_P5064
142 #include <algor/algor/algor_p5064reg.h>
143 #include <algor/algor/algor_p5064var.h>
144 struct p5064_config p5064_configuration;
145 #endif
146
147 #ifdef ALGOR_P6032
148 #include <algor/algor/algor_p6032reg.h>
149 #include <algor/algor/algor_p6032var.h>
150 struct p6032_config p6032_configuration;
151 #endif
152
153 /* Maps for VM objects. */
154 struct vm_map *phys_map = NULL;
155
156 int maxmem; /* max memory per process */
157
158 int mem_cluster_cnt;
159 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
160
161 char algor_ethaddr[ETHER_ADDR_LEN];
162
163 void mach_init(int, char *[], char *[]); /* XXX */
164
165 int cpuspeed = 150; /* XXX XXX XXX */
166
167 /* The ALGOR kernels only support little endian */
168 CTASSERT(_BYTE_ORDER == _LITTLE_ENDIAN);
169
170 void
mach_init(int argc,char * argv[],char * envp[])171 mach_init(int argc, char *argv[], char *envp[])
172 {
173 extern char kernel_text[], edata[], end[];
174 vaddr_t kernstart, kernend;
175 vsize_t size;
176 const char *cp;
177 char *cp0;
178 size_t i;
179
180 /*
181 * First, find the start and end of the kernel and clear
182 * the BSS segment. Account for a bit of space for the
183 * bootstrap stack.
184 */
185 led_display('b', 's', 's', ' ');
186 kernstart = (vaddr_t) mips_trunc_page(kernel_text) - 2 * NBPG;
187 kernend = (vaddr_t) mips_round_page(end);
188 memset(edata, 0, kernend - (vaddr_t)edata);
189
190 /*
191 * Copy the exception-dispatch code down to the exception vector.
192 * Initialize the locore function vector. Clear out the I- and
193 * D-caches.
194 *
195 * We can no longer call into PMON after this.
196 */
197 led_display('v', 'e', 'c', 'i');
198 mips_vector_init(NULL, false);
199
200 /*
201 * Initialize PAGE_SIZE-dependent variables.
202 */
203 led_display('p', 'g', 's', 'z');
204 uvm_md_init();
205
206 /*
207 * Initialize bus space tags and bring up the console.
208 */
209 #if defined(ALGOR_P4032)
210 {
211 struct p4032_config *acp = &p4032_configuration;
212 struct vtpbc_config *vt = &vtpbc_configuration;
213 bus_space_handle_t sh;
214
215 cpu_setmodel("Algorithmics P-4032");
216
217 vt->vt_addr = MIPS_PHYS_TO_KSEG1(P4032_V962PBC);
218 vt->vt_cfgbase = MIPS_PHYS_TO_KSEG1(P4032_PCICFG);
219 vt->vt_adbase = 11;
220
221 led_display('v', '9', '6', '2');
222 vtpbc_init(&acp->ac_pc, vt);
223
224 led_display('l', 'i', 'o', ' ');
225 algor_p4032loc_bus_io_init(&acp->ac_lociot, acp);
226
227 led_display('i', 'o', ' ', ' ');
228 algor_p4032_bus_io_init(&acp->ac_iot, acp);
229
230 led_display('m', 'e', 'm', ' ');
231 algor_p4032_bus_mem_init(&acp->ac_memt, acp);
232
233 led_display('d', 'm', 'a', ' ');
234 algor_p4032_dma_init(acp);
235 #if NCOM > 0
236 /*
237 * Delay to allow firmware putchars to complete.
238 * FIFO depth * character time.
239 * character time = (1000000 / (defaultrate / 10))
240 */
241 led_display('c', 'o', 'n', 's');
242 DELAY(160000000 / comcnrate);
243 if (comcnattach(&acp->ac_lociot, P4032_COM1, comcnrate,
244 COM_FREQ, COM_TYPE_NORMAL,
245 (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8) != 0)
246 panic("p4032: unable to initialize serial console");
247 #else
248 panic("p4032: not configured to use serial console");
249 #endif /* NCOM > 0 */
250
251 led_display('h', 'z', ' ', ' ');
252 bus_space_map(&acp->ac_lociot, P4032_RTC, 2, 0, &sh);
253 algor_p4032_cal_timer(&acp->ac_lociot, sh);
254 bus_space_unmap(&acp->ac_lociot, sh, 2);
255 }
256 #elif defined(ALGOR_P5064)
257 {
258 struct p5064_config *acp = &p5064_configuration;
259 struct vtpbc_config *vt = &vtpbc_configuration;
260 bus_space_handle_t sh;
261
262 cpu_setmodel("Algorithmics P-5064");
263
264 vt->vt_addr = MIPS_PHYS_TO_KSEG1(P5064_V360EPC);
265 vt->vt_cfgbase = MIPS_PHYS_TO_KSEG1(P5064_PCICFG);
266 vt->vt_adbase = 24;
267
268 led_display('v', '3', '6', '0');
269 vtpbc_init(&acp->ac_pc, vt);
270
271 led_display('i', 'o', ' ', ' ');
272 algor_p5064_bus_io_init(&acp->ac_iot, acp);
273
274 led_display('m', 'e', 'm', ' ');
275 algor_p5064_bus_mem_init(&acp->ac_memt, acp);
276
277 led_display('d', 'm', 'a', ' ');
278 algor_p5064_dma_init(acp);
279 #if NCOM > 0
280 /*
281 * Delay to allow firmware putchars to complete.
282 * FIFO depth * character time.
283 * character time = (1000000 / (defaultrate / 10))
284 */
285 led_display('c', 'o', 'n', 's');
286 DELAY(160000000 / comcnrate);
287 if (comcnattach(&acp->ac_iot, 0x3f8, comcnrate,
288 COM_FREQ, COM_TYPE_NORMAL,
289 (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8) != 0)
290 panic("p5064: unable to initialize serial console");
291 #else
292 panic("p5064: not configured to use serial console");
293 #endif /* NCOM > 0 */
294
295 led_display('h', 'z', ' ', ' ');
296 bus_space_map(&acp->ac_iot, 0x70, 2, 0, &sh);
297 algor_p5064_cal_timer(&acp->ac_iot, sh);
298 bus_space_unmap(&acp->ac_iot, sh, 2);
299 }
300 #elif defined(ALGOR_P6032)
301 {
302 struct p6032_config *acp = &p6032_configuration;
303 struct bonito_config *bc = &acp->ac_bonito;
304 bus_space_handle_t sh;
305
306 cpu_setmodel("Algorithmics P-6032");
307
308 bc->bc_adbase = 11;
309
310 led_display('b','n','t','o');
311 bonito_pci_init(&acp->ac_pc, bc);
312
313 led_display('i','o',' ',' ');
314 algor_p6032_bus_io_init(&acp->ac_iot, acp);
315
316 led_display('m','e','m',' ');
317 algor_p6032_bus_mem_init(&acp->ac_memt, acp);
318
319 led_display('d','m','a',' ');
320 algor_p6032_dma_init(acp);
321 #if NCOM > 0
322 /*
323 * Delay to allow firmware putchars to complete.
324 * FIFO depth * character time.
325 * character time = (1000000 / (defaultrate / 10))
326 */
327 led_display('c','o','n','s');
328 DELAY(160000000 / comcnrate);
329 if (comcnattach(&acp->ac_iot, 0x3f8, comcnrate,
330 COM_FREQ, COM_TYPE_NORMAL,
331 (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8) != 0)
332 panic("p6032: unable to initialize serial console");
333 #else
334 panic("p6032: not configured to use serial console");
335 #endif /* NCOM > 0 */
336
337 led_display('h','z',' ',' ');
338 bus_space_map(&acp->ac_iot, 0x70, 2, 0, &sh);
339 algor_p6032_cal_timer(&acp->ac_iot, sh);
340 bus_space_unmap(&acp->ac_iot, sh, 2);
341 }
342 #endif /* ALGOR_P4032 || ALGOR_P5064 || ALGOR_P6032 */
343
344 /*
345 * The Algorithmics boards have PMON firmware; set up our
346 * PMON state.
347 */
348 led_display('p', 'm', 'o', 'n');
349 pmon_init(envp);
350
351 /*
352 * Get the Ethernet address of the on-board Ethernet.
353 */
354 #if defined(ETHADDR)
355 cp = ETHADDR;
356 #else
357 cp = pmon_getenv("ethaddr");
358 #endif
359 if (cp != NULL) {
360 for (i = 0; i < ETHER_ADDR_LEN; i++) {
361 algor_ethaddr[i] = strtoul(cp, &cp0, 16);
362 cp = cp0 + 1;
363 }
364 }
365
366 /*
367 * Get the boot options.
368 */
369 led_display('b', 'o', 'p', 't');
370 boothowto = 0;
371 if (argc > 1) {
372 #ifdef _LP64
373 cp = (void *)(intptr_t)((int32_t *)argv)[1];
374 #else
375 cp = argv[1];
376 #endif
377 for (; cp != NULL && *cp != '\0'; cp++) {
378 switch (*cp) {
379 #if defined(KGDB) || defined(DDB)
380 case 'd': /* break into kernel debugger */
381 boothowto |= RB_KDB;
382 break;
383 #endif
384
385 case 'h': /* always halt, never reboot */
386 boothowto |= RB_HALT;
387 break;
388
389 case 'n': /* askname */
390 boothowto |= RB_ASKNAME;
391 break;
392
393 case 's': /* single-user mode */
394 boothowto |= RB_SINGLE;
395 break;
396
397 case 'q': /* quiet boot */
398 boothowto |= AB_QUIET;
399 break;
400
401 case 'v': /* verbose boot */
402 boothowto |= AB_VERBOSE;
403 break;
404
405 case '-':
406 /*
407 * Just ignore this. It's not required,
408 * but it's common for it to be passed
409 * regardless.
410 */
411 break;
412
413 default:
414 printf("Unrecognized boto flag '%c'.\n", *cp);
415 break;
416 }
417 }
418 }
419
420 /*
421 * Determine the memory size. Use the `memsize' PMON
422 * variable. If that's not available, panic.
423 *
424 * Note: Reserve the first page! That's where the trap
425 * vectors are located.
426 */
427 #if defined(MEMSIZE)
428 size = MEMSIZE;
429 #else
430 if ((cp = pmon_getenv("memsize")) != NULL)
431 size = strtoul(cp, NULL, 0);
432 else {
433 printf("FATAL: `memsize' PMON variable not set. Set it to\n");
434 printf(" the amount of memory (in MB) and try again.\n");
435 printf(" Or, build a kernel with the `MEMSIZE' "
436 "option.\n");
437 panic("algor_init");
438 }
439 #endif /* MEMSIZE */
440 /*
441 * Deal with 2 different conventions of the contents
442 * of the memsize variable -- if it's > 1024, assume
443 * it's already in bytes, not megabytes.
444 */
445 if (size < 1024) {
446 printf("Memory size: %#"PRIxVSIZE" (%"PRIxVSIZE")\n",
447 size * 1024 * 1024, size);
448 size *= 1024 * 1024;
449 } else
450 printf("Memory size: %#"PRIxVSIZE"\n", size);
451
452 mem_clusters[mem_cluster_cnt].start = PAGE_SIZE;
453 mem_clusters[mem_cluster_cnt].size =
454 size - mem_clusters[mem_cluster_cnt].start;
455 mem_cluster_cnt++;
456
457 /*
458 * Load the physical memory clusters into the VM system.
459 */
460 led_display('v', 'm', 'p', 'g');
461 for (i = 0; i < mem_cluster_cnt; i++) {
462 physmem += atop(mem_clusters[i].size);
463 }
464 if (physmem == 0)
465 panic("can't happen: system seems to have no memory!");
466 maxmem = physmem;
467
468 static const struct mips_vmfreelist isadma = {
469 .fl_start = 8*1024*1024,
470 .fl_end = 16*1024*1024,
471 .fl_freelist = VM_FREELIST_ISADMA,
472 };
473 mips_page_physload(kernstart, kernend,
474 mem_clusters, mem_cluster_cnt, &isadma, 1);
475
476 /*
477 * Initialize message buffer (at end of core).
478 */
479 mips_init_msgbuf();
480
481 /*
482 * Initialize the virtual memory system.
483 */
484 led_display('p', 'm', 'a', 'p');
485 pmap_bootstrap();
486
487 /*
488 * Allocate uarea page for lwp0 and set it.
489 */
490 led_display('u', 's', 'p', 'c');
491 mips_init_lwp0_uarea();
492
493 /*
494 * Initialize debuggers, and break into them, if appropriate.
495 */
496 if (boothowto & RB_KDB) {
497 #if defined(DDB)
498 Debugger();
499 #endif
500 }
501 }
502
503 void
consinit(void)504 consinit(void)
505 {
506
507 /*
508 * Everything related to console initialization is done
509 * in mach_init().
510 */
511 led_display('N', 'B', 'S', 'D');
512 }
513
514 void
cpu_startup(void)515 cpu_startup(void)
516 {
517 /*
518 * Virtual memory is bootstrapped -- notify the bus spaces
519 * that memory allocation is now safe.
520 */
521 #if defined(ALGOR_P4032)
522 struct p4032_config * const acp = &p4032_configuration;
523
524 acp->ac_mallocsafe = 1;
525 #elif defined(ALGOR_P5064)
526 struct p5064_config * const acp = &p5064_configuration;
527
528 acp->ac_mallocsafe = 1;
529 #elif defined(ALGOR_P6032)
530 struct p6032_config * const acp = &p6032_configuration;
531
532 acp->ac_mallocsafe = 1;
533 #endif
534 cpu_startup_common();
535 }
536
537 int waittime = -1;
538
539 void
cpu_reboot(int howto,char * bootstr)540 cpu_reboot(int howto, char *bootstr)
541 {
542 int tmp;
543
544 /* Take a snapshot before clobbering any registers. */
545 savectx(curpcb);
546
547 /* If "always halt" was specified as a boot flag, obey. */
548 if (boothowto & RB_HALT)
549 howto |= RB_HALT;
550
551 boothowto = howto;
552
553 /* If system is cold, just halt. */
554 if (cold) {
555 boothowto |= RB_HALT;
556 goto haltsys;
557 }
558
559 if ((boothowto & RB_NOSYNC) == 0 && waittime < 0) {
560 waittime = 0;
561 vfs_shutdown();
562 }
563
564 /* Disable interrupts. */
565 (void) splhigh();
566
567 if (boothowto & RB_DUMP)
568 dumpsys();
569
570 haltsys:
571 /* Run any shutdown hooks. */
572 doshutdownhooks();
573
574 pmf_system_shutdown(boothowto);
575
576 if (boothowto & RB_HALT) {
577 printf("\n");
578 printf("The operating system has halted.\n");
579 printf("Please press any key to return to the monitor.\n\n");
580 led_display('h','a','l','t');
581 cnpollc(1);
582 (void) cngetc();
583 cnpollc(0);
584 }
585
586 printf("Returning to the monitor...\n\n");
587 led_display('r', 'v', 'e', 'c');
588 /* Jump to the reset vector. */
589 __asm volatile("li %0, 0xbfc00000; jr %0; nop"
590 : "=r" (tmp)
591 : /* no inputs */
592 : "memory");
593 led_display('R', 'S', 'T', 'F');
594 for (;;)
595 /* spin forever */ ;
596 }
597