1 /* $NetBSD: machdep.c,v 1.124 2024/03/05 14:15:29 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 2006 Izumi Tsutsui. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 /*
28 * Copyright (c) 2000 Soren S. Jorvang. All rights reserved.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
32 * are met:
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions, and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
40 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
42 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
43 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
44 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
45 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
47 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
48 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
49 * SUCH DAMAGE.
50 */
51
52 #include <sys/cdefs.h>
53 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.124 2024/03/05 14:15:29 thorpej Exp $");
54
55 #include "opt_ddb.h"
56 #include "opt_kgdb.h"
57 #include "opt_modular.h"
58 #include "opt_execfmt.h"
59
60 #include <sys/param.h>
61 #include <sys/systm.h>
62 #include <sys/boot_flag.h>
63 #include <sys/bus.h>
64 #include <sys/cpu.h>
65 #include <sys/device.h>
66 #include <sys/kernel.h>
67 #include <sys/kcore.h>
68 #include <sys/ksyms.h>
69 #include <sys/mount.h>
70 #include <sys/proc.h>
71 #include <sys/reboot.h>
72
73 #include <uvm/uvm_extern.h>
74
75 #include <machine/bootinfo.h>
76
77 #include <mips/locore.h>
78 #include <mips/psl.h>
79
80 #include <dev/cons.h>
81
82 #include <cobalt/dev/gtreg.h>
83
84 #ifdef KGDB
85 #include <sys/kgdb.h>
86 #endif
87
88 #include "ksyms.h"
89
90 #if NKSYMS || defined(DDB) || defined(MODULAR)
91 #include <mips/db_machdep.h>
92 #include <ddb/db_extern.h>
93 #include <sys/exec_elf.h>
94 #endif
95
96 /* Maps for VM objects. */
97 struct vm_map *phys_map = NULL;
98
99 void *bootinfo = NULL; /* pointer to bootinfo structure */
100
101 char bootstring[512]; /* Boot command */
102 int netboot; /* Are we netbooting? */
103
104 char *nfsroot_bstr = NULL;
105 char *root_bstr = NULL;
106 int bootunit = -1;
107 int bootpart = -1;
108
109 #if 0
110 struct extent *cobalt_io_ex = NULL;
111 struct extent *cobalt_mem_ex = NULL;
112 struct mips_bus_space bonito_iot;
113 struct mips_bus_space bonito_memt;
114 struct mips_bus_dma_tag bonito_dmat;
115 struct mips_pci_chipset bonito_pc;
116 #endif
117
118
119 int cpuspeed;
120
121 u_int cobalt_id;
122 static const char * const cobalt_model[] =
123 {
124 [COBALT_ID_QUBE2700] = "Cobalt Qube 2700",
125 [COBALT_ID_RAQ] = "Cobalt RaQ",
126 [COBALT_ID_QUBE2] = "Cobalt Qube 2",
127 [COBALT_ID_RAQ2] = "Cobalt RaQ 2"
128 };
129 #define COBALT_MODELS __arraycount(cobalt_model)
130
131 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
132 int mem_cluster_cnt;
133
134 void mach_init(int32_t, u_int, int32_t);
135 void decode_bootstring(void);
136 static char *strtok_light(char *, const char);
137 static u_int read_board_id(void);
138
139 extern char *esym;
140
141 struct mips_bus_space cobalt_bs;
142 void mainbus_bus_mem_init(bus_space_tag_t, void *);
143
144
145 /*
146 * Do all the stuff that locore normally does before calling main().
147 */
148 void
mach_init(int32_t memsize32,u_int bim,int32_t bip32)149 mach_init(int32_t memsize32, u_int bim, int32_t bip32)
150 {
151 intptr_t memsize = (int32_t)memsize32;
152 char *kernend;
153 char *bip = (char *)(intptr_t)(int32_t)bip32;
154 u_long first, last;
155 extern char edata[], end[];
156 const char *bi_msg;
157 #if NKSYMS || defined(DDB) || defined(MODULAR)
158 char *ssym = 0;
159 struct btinfo_symtab *bi_syms;
160 #endif
161 struct btinfo_howto *bi_howto;
162
163 /*
164 * Clear the BSS segment (if needed).
165 */
166 if (memcmp(((Elf_Ehdr *)end)->e_ident, ELFMAG, SELFMAG) == 0 &&
167 ((Elf_Ehdr *)end)->e_ident[EI_CLASS] == ELFCLASS) {
168 esym = end;
169 #if NKSYMS || defined(DDB) || defined(MODULAR)
170 esym += ((Elf_Ehdr *)end)->e_entry;
171 #endif
172 kernend = (char *)mips_round_page(esym);
173 /*
174 * We don't have to clear BSS here
175 * since our bootloader already does it.
176 */
177 #if 0
178 memset(edata, 0, end - edata);
179 #endif
180 } else {
181 kernend = (void *)mips_round_page(end);
182 /*
183 * No symbol table, so assume we are loaded by
184 * the firmware directly with "bfd" command.
185 * The firmware loader doesn't clear BSS of
186 * a loaded kernel, so do it here.
187 */
188 memset(edata, 0, kernend - edata);
189
190 }
191
192 /*
193 * Copy exception-dispatch code down to exception vector.
194 * Initialize locore-function vector.
195 * Clear out the I and D caches.
196 */
197 mips_vector_init(NULL, false);
198
199 mainbus_bus_mem_init(&cobalt_bs, NULL);
200
201 /* Check for valid bootinfo passed from bootstrap */
202 if (bim == BOOTINFO_MAGIC) {
203 struct btinfo_magic *bi_magic;
204
205 bootinfo = bip;
206 bi_magic = lookup_bootinfo(BTINFO_MAGIC);
207 if (bi_magic == NULL) {
208 bi_msg = "missing bootinfo structure";
209 bim = (uintptr_t)bip;
210 } else if (bi_magic->magic != BOOTINFO_MAGIC) {
211 bi_msg = "invalid bootinfo structure";
212 bim = bi_magic->magic;
213 } else
214 bi_msg = NULL;
215 } else {
216 bi_msg = "invalid bootinfo (standalone boot?)";
217 }
218
219 #if NKSYMS || defined(DDB) || defined(MODULAR)
220 bi_syms = lookup_bootinfo(BTINFO_SYMTAB);
221
222 /* Load symbol table if present */
223 if (bi_syms != NULL) {
224 ssym = (void *)(intptr_t)bi_syms->ssym;
225 esym = (void *)(intptr_t)bi_syms->esym;
226 kernend = (void *)mips_round_page(esym);
227 }
228 #endif
229
230 bi_howto = lookup_bootinfo(BTINFO_HOWTO);
231 if (bi_howto != NULL)
232 boothowto = bi_howto->bi_howto;
233
234 cobalt_id = read_board_id();
235 if (cobalt_id >= COBALT_MODELS || cobalt_model[cobalt_id] == NULL)
236 cpu_setmodel("Cobalt unknown model (board ID %u)",
237 cobalt_id);
238 else
239 cpu_setmodel("%s", cobalt_model[cobalt_id]);
240
241 switch (cobalt_id) {
242 case COBALT_ID_QUBE2700:
243 case COBALT_ID_RAQ:
244 cpuspeed = 150; /* MHz */
245 break;
246 case COBALT_ID_QUBE2:
247 case COBALT_ID_RAQ2:
248 cpuspeed = 250; /* MHz */
249 break;
250 default:
251 /* assume the fastest, so that delay(9) works */
252 cpuspeed = 250;
253 break;
254 }
255 curcpu()->ci_cpu_freq = cpuspeed * 1000 * 1000;
256 curcpu()->ci_cycles_per_hz = (curcpu()->ci_cpu_freq + hz / 2) / hz;
257 curcpu()->ci_divisor_delay =
258 ((curcpu()->ci_cpu_freq + (1000000 / 2)) / 1000000);
259 /* all models have Rm5200, which is CPU_MIPS_DOUBLE_COUNT */
260 curcpu()->ci_cycles_per_hz /= 2;
261 curcpu()->ci_divisor_delay /= 2;
262
263 physmem = btoc(memsize - MIPS_KSEG0_START);
264
265 consinit();
266
267 KASSERT(&lwp0 == curlwp);
268 if (bi_msg != NULL)
269 printf("%s: magic=%#x bip=%p\n", bi_msg, bim, bip);
270
271 uvm_md_init();
272
273 /*
274 * The boot command is passed in the top 512 bytes,
275 * so don't clobber that.
276 */
277 mem_clusters[0].start = 0;
278 mem_clusters[0].size = ctob(physmem) - 512;
279 mem_cluster_cnt = 1;
280
281 memcpy(bootstring, (char *)(memsize - 512), 512);
282 memset((char *)(memsize - 512), 0, 512);
283 bootstring[511] = '\0';
284
285 decode_bootstring();
286
287 #if NKSYMS || defined(DDB) || defined(MODULAR)
288 /* init symbols if present */
289 if ((bi_syms != NULL) && (esym != NULL))
290 ksyms_addsyms_elf(esym - ssym, ssym, esym);
291 #endif
292 KASSERT(&lwp0 == curlwp);
293 /*
294 * Load the rest of the available pages into the VM system.
295 */
296 first = round_page(MIPS_KSEG0_TO_PHYS(kernend));
297 last = mem_clusters[0].start + mem_clusters[0].size;
298 uvm_page_physload(atop(first), atop(last), atop(first), atop(last),
299 VM_FREELIST_DEFAULT);
300
301 /*
302 * Initialize error message buffer (at end of core).
303 */
304 mips_init_msgbuf();
305
306 pmap_bootstrap();
307
308 /*
309 * Allocate space for proc0's USPACE.
310 */
311 mips_init_lwp0_uarea();
312
313 #ifdef DDB
314 if (boothowto & RB_KDB)
315 Debugger();
316 #endif
317 #ifdef KGDB
318 if (boothowto & RB_KDB)
319 kgdb_connect(0);
320 #endif
321
322 }
323
324 /*
325 * Allocate memory for variable-sized tables,
326 */
327 void
cpu_startup(void)328 cpu_startup(void)
329 {
330 cpu_startup_common();
331 }
332
333 static int waittime = -1;
334
335 void
cpu_reboot(int howto,char * bootstr)336 cpu_reboot(int howto, char *bootstr)
337 {
338
339 /* Take a snapshot before clobbering any registers. */
340 savectx(curpcb);
341
342 if (cold) {
343 howto |= RB_HALT;
344 goto haltsys;
345 }
346
347 /* If "always halt" was specified as a boot flag, obey. */
348 if (boothowto & RB_HALT)
349 howto |= RB_HALT;
350
351 boothowto = howto;
352 if ((howto & RB_NOSYNC) == 0 && (waittime < 0)) {
353 waittime = 0;
354 vfs_shutdown();
355 }
356
357 splhigh();
358
359 if (howto & RB_DUMP)
360 dumpsys();
361
362 haltsys:
363 doshutdownhooks();
364
365 pmf_system_shutdown(boothowto);
366
367 if (howto & RB_HALT) {
368 printf("\n");
369 printf("The operating system has halted.\n");
370 printf("Please press any key to reboot.\n\n");
371 cnpollc(1); /* For proper keyboard command handling */
372 cngetc();
373 cnpollc(0);
374 }
375
376 printf("rebooting...\n\n");
377 delay(500000);
378
379 *(volatile char *)MIPS_PHYS_TO_KSEG1(LED_ADDR) = LED_RESET;
380 printf("WARNING: reboot failed!\n");
381
382 for (;;)
383 ;
384 }
385
386
387 void
decode_bootstring(void)388 decode_bootstring(void)
389 {
390 char *work;
391 char *equ;
392 int i;
393
394 /* break apart bootstring on ' ' boundaries and iterate */
395 work = strtok_light(bootstring, ' ');
396 while (work != NULL) {
397 /* if starts with '-', we got options, walk its decode */
398 if (work[0] == '-') {
399 i = 1;
400 while (work[i] != ' ' && work[i] != '\0') {
401 BOOT_FLAG(work[i], boothowto);
402 i++;
403 }
404 } else
405
406 /* if it has a '=' its an assignment, switch and set */
407 if ((equ = strchr(work, '=')) != NULL) {
408 if (memcmp("nfsroot=", work, 8) == 0) {
409 nfsroot_bstr = (equ + 1);
410 } else
411 if (memcmp("root=", work, 5) == 0) {
412 root_bstr = (equ + 1);
413 }
414 } else
415
416 /* else it a single value, switch and process */
417 if (memcmp("single", work, 5) == 0) {
418 boothowto |= RB_SINGLE;
419 } else
420 if (memcmp("ro", work, 2) == 0) {
421 /* this is also inserted by the firmware */
422 }
423
424 /* grab next token */
425 work = strtok_light(NULL, ' ');
426 }
427
428 if (root_bstr != NULL) {
429 /* this should be of the form "/dev/hda1" */
430 /* [abcd][1234] drive partition linux probe order */
431 if ((memcmp("/dev/hd", root_bstr, 7) == 0) &&
432 (strlen(root_bstr) == 9) ){
433 bootunit = root_bstr[7] - 'a';
434 bootpart = root_bstr[8] - '1';
435 }
436 }
437
438 if (nfsroot_bstr != NULL)
439 netboot = 1;
440 }
441
442
443 static char *
strtok_light(char * str,const char sep)444 strtok_light(char *str, const char sep)
445 {
446 static char *proc;
447 char *head;
448 char *work;
449
450 if (str != NULL)
451 proc = str;
452 if (proc == NULL) /* end of string return NULL */
453 return proc;
454
455 head = proc;
456
457 work = strchr(proc, sep);
458 if (work == NULL) { /* we hit the end */
459 proc = work;
460 } else {
461 proc = (work + 1);
462 *work = '\0';
463 }
464
465 return head;
466 }
467
468 /*
469 * Look up information in bootinfo of boot loader.
470 */
471 void *
lookup_bootinfo(unsigned int type)472 lookup_bootinfo(unsigned int type)
473 {
474 struct btinfo_common *bt;
475 char *help = bootinfo;
476
477 /* Check for a bootinfo record first. */
478 if (help == NULL) {
479 printf("##### help == NULL\n");
480 return NULL;
481 }
482
483 do {
484 bt = (struct btinfo_common *)help;
485 printf("Type %d @%p\n", bt->type, (void *)(intptr_t)bt);
486 if (bt->type == type)
487 return (void *)help;
488 help += bt->next;
489 } while (bt->next != 0 &&
490 (uintptr_t)help < (uintptr_t)bootinfo + BOOTINFO_SIZE);
491
492 return NULL;
493 }
494
495 /*
496 * Get board ID of cobalt models.
497 *
498 * The board ID info is stored at the PCI config register
499 * on the PCI-ISA bridge part of the VIA VT82C586 chipset.
500 * We can't use pci_conf_read(9) yet here, so read it directly.
501 */
502 static u_int
read_board_id(void)503 read_board_id(void)
504 {
505 volatile uint32_t *pcicfg_addr, *pcicfg_data;
506 uint32_t reg;
507
508 #define PCIB_PCI_BUS 0
509 #define PCIB_PCI_DEV 9
510 #define PCIB_PCI_FUNC 0
511 #define PCIB_BOARD_ID_REG 0x94
512 #define COBALT_BOARD_ID(reg) ((reg & 0x000000f0) >> 4)
513
514 pcicfg_addr = (uint32_t *)MIPS_PHYS_TO_KSEG1(GT_BASE + GT_PCICFG_ADDR);
515 pcicfg_data = (uint32_t *)MIPS_PHYS_TO_KSEG1(GT_BASE + GT_PCICFG_DATA);
516
517 *pcicfg_addr = PCICFG_ENABLE |
518 (PCIB_PCI_BUS << 16) | (PCIB_PCI_DEV << 11) | (PCIB_PCI_FUNC << 8) |
519 PCIB_BOARD_ID_REG;
520 reg = *pcicfg_data;
521 *pcicfg_addr = 0;
522
523 return COBALT_BOARD_ID(reg);
524 }
525