xref: /openbsd/sys/arch/riscv64/riscv64/machdep.c (revision 285e3455)
1 /*	$OpenBSD: machdep.c,v 1.15 2021/05/13 19:26:25 kettenis Exp $	*/
2 
3 /*
4  * Copyright (c) 2014 Patrick Wildt <patrick@blueri.se>
5  * Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/param.h>
21 #include <sys/systm.h>
22 #include <sys/sched.h>
23 #include <sys/proc.h>
24 #include <sys/sysctl.h>
25 #include <sys/reboot.h>
26 #include <sys/mount.h>
27 #include <sys/exec.h>
28 #include <sys/user.h>
29 #include <sys/conf.h>
30 #include <sys/kcore.h>
31 #include <sys/core.h>
32 #include <sys/msgbuf.h>
33 #include <sys/buf.h>
34 #include <sys/termios.h>
35 #include <sys/sensors.h>
36 #include <sys/malloc.h>
37 #include <sys/syscallargs.h>
38 #include <sys/stdarg.h>
39 
40 #include <net/if.h>
41 #include <uvm/uvm.h>
42 #include <dev/cons.h>
43 #include <dev/ofw/fdt.h>
44 #include <dev/ofw/openfirm.h>
45 #include <machine/param.h>
46 #include <machine/bootconfig.h>
47 #include <machine/bus.h>
48 #include <machine/riscv64var.h>
49 #include <machine/sbi.h>
50 
51 #include <machine/db_machdep.h>
52 #include <ddb/db_extern.h>
53 
54 #include <dev/acpi/efi.h>
55 
56 #include "softraid.h"
57 #if NSOFTRAID > 0
58 #include <dev/softraidvar.h>
59 #endif
60 
61 extern vaddr_t virtual_avail;
62 extern uint64_t esym;
63 
64 extern char _start[];
65 
66 char *boot_args = NULL;
67 uint8_t *bootmac = NULL;
68 
69 int stdout_node;
70 int stdout_speed;
71 
72 void (*cpuresetfn)(void);
73 void (*powerdownfn)(void);
74 
75 int cold = 1;
76 
77 struct vm_map *exec_map = NULL;
78 struct vm_map *phys_map = NULL;
79 
80 int physmem;
81 
82 caddr_t msgbufaddr;
83 paddr_t msgbufphys;
84 
85 struct user *proc0paddr;
86 
87 struct uvm_constraint_range  dma_constraint = { 0x0, (paddr_t)-1 };
88 struct uvm_constraint_range *uvm_md_constraints[] = {
89 	&dma_constraint,
90 	NULL,
91 };
92 
93 /* the following is used externally (sysctl_hw) */
94 char    machine[] = MACHINE;		/* from <machine/param.h> */
95 
96 int safepri = 0;
97 
98 uint32_t boot_hart;	/* The hart we booted on. */
99 struct cpu_info cpu_info_primary;
100 struct cpu_info *cpu_info[MAXCPUS] = { &cpu_info_primary };
101 
102 uint32_t tb_freq = 1000000;
103 
104 struct fdt_reg memreg[VM_PHYSSEG_MAX];
105 int nmemreg;
106 
107 void memreg_add(const struct fdt_reg *);
108 void memreg_remove(const struct fdt_reg *);
109 
110 static int
111 atoi(const char *s)
112 {
113 	int n, neg;
114 
115 	n = 0;
116 	neg = 0;
117 
118 	while (*s == '-') {
119 		s++;
120 		neg = !neg;
121 	}
122 
123 	while (*s != '\0') {
124 		if (*s < '0' || *s > '9')
125 			break;
126 
127 		n = (10 * n) + (*s - '0');
128 		s++;
129 	}
130 
131 	return (neg ? -n : n);
132 }
133 
134 void *
135 fdt_find_cons(const char *name)
136 {
137 	char *alias = "serial0";
138 	char buf[128];
139 	char *stdout = NULL;
140 	char *p;
141 	void *node;
142 
143 	/* First check if "stdout-path" is set. */
144 	node = fdt_find_node("/chosen");
145 	if (node) {
146 		if (fdt_node_property(node, "stdout-path", &stdout) > 0) {
147 			if (strchr(stdout, ':') != NULL) {
148 				strlcpy(buf, stdout, sizeof(buf));
149 				if ((p = strchr(buf, ':')) != NULL) {
150 					*p++ = '\0';
151 					stdout_speed = atoi(p);
152 				}
153 				stdout = buf;
154 			}
155 			if (stdout[0] != '/') {
156 				/* It's an alias. */
157 				alias = stdout;
158 				stdout = NULL;
159 			}
160 		}
161 	}
162 
163 	/* Perform alias lookup if necessary. */
164 	if (stdout == NULL) {
165 		node = fdt_find_node("/aliases");
166 		if (node)
167 			fdt_node_property(node, alias, &stdout);
168 	}
169 
170 	/* Lookup the physical address of the interface. */
171 	if (stdout) {
172 		node = fdt_find_node(stdout);
173 		if (node && fdt_is_compatible(node, name)) {
174 			stdout_node = OF_finddevice(stdout);
175 			return (node);
176 		}
177 	}
178 
179 	return (NULL);
180 }
181 
182 void	com_fdt_init_cons(void);
183 
184 void
185 consinit(void)
186 {
187 	static int consinit_called = 0;
188 
189 	if (consinit_called != 0)
190 		return;
191 
192 	consinit_called = 1;
193 	com_fdt_init_cons();
194 }
195 
196 void
197 cpu_idle_enter(void)
198 {
199 }
200 
201 void
202 cpu_idle_cycle(void)
203 {
204 	// Enable interrupts
205 	intr_enable();
206 	// XXX Data Sync Barrier? (Maybe SFENCE???)
207 	__asm volatile("wfi");
208 }
209 
210 void
211 cpu_idle_leave(void)
212 {
213 }
214 
215 /* Dummy trapframe for proc0. */
216 struct trapframe proc0tf;
217 
218 void
219 cpu_startup(void)
220 {
221 	u_int loop;
222 	paddr_t minaddr;
223 	paddr_t maxaddr;
224 
225 	proc0.p_addr = proc0paddr;
226 
227 	/*
228 	 * Give pmap a chance to set up a few more things now the vm
229 	 * is initialised
230 	 */
231 	pmap_postinit();
232 
233 	/*
234 	 * Initialize error message buffer (at end of core).
235 	 */
236 
237 	/* msgbufphys was setup during the secondary boot strap */
238 	for (loop = 0; loop < atop(MSGBUFSIZE); ++loop)
239 		pmap_kenter_pa((vaddr_t)msgbufaddr + loop * PAGE_SIZE,
240 		    msgbufphys + loop * PAGE_SIZE, PROT_READ | PROT_WRITE);
241 	pmap_update(pmap_kernel());
242 	initmsgbuf(msgbufaddr, round_page(MSGBUFSIZE));
243 
244 	/*
245 	 * Identify ourselves for the msgbuf (everything printed earlier will
246 	 * not be buffered).
247 	 */
248 	printf("%s", version);
249 
250 	printf("real mem  = %lu (%luMB)\n", ptoa(physmem),
251 	    ptoa(physmem) / 1024 / 1024);
252 
253 	/*
254 	 * Allocate a submap for exec arguments.  This map effectively
255 	 * limits the number of processes exec'ing at any time.
256 	 */
257 	minaddr = vm_map_min(kernel_map);
258 	exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
259 	    16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
260 
261 	/*
262 	 * Allocate a submap for physio
263 	 */
264 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
265 	    VM_PHYS_SIZE, 0, FALSE, NULL);
266 
267 	/*
268 	 * Set up buffers, so they can be used to read disk labels.
269 	 */
270 	bufinit();
271 
272 	printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free),
273 	    ptoa(uvmexp.free) / 1024 / 1024);
274 
275 	curpcb = &proc0.p_addr->u_pcb;
276 	curpcb->pcb_flags = 0;
277 	curpcb->pcb_tf = &proc0tf;
278 
279 	if (boothowto & RB_CONFIG) {
280 #ifdef BOOT_CONFIG
281 		user_config();
282 #else
283 		printf("kernel does not support -c; continuing..\n");
284 #endif
285 	}
286 }
287 
288 /*
289  * machine dependent system variables.
290  */
291 
292 int
293 cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
294     size_t newlen, struct proc *p)
295 {
296 	char *compatible;
297 	int node, len, error;
298 
299 	/* all sysctl names at this level are terminal */
300 	if (namelen != 1)
301 		return (ENOTDIR);		/* overloaded */
302 
303 	switch (name[0]) {
304 	case CPU_COMPATIBLE:
305 		node = OF_finddevice("/");
306 		len = OF_getproplen(node, "compatible");
307 		if (len <= 0)
308 			return (EOPNOTSUPP);
309 		compatible = malloc(len, M_TEMP, M_WAITOK | M_ZERO);
310 		OF_getprop(node, "compatible", compatible, len);
311 		compatible[len - 1] = 0;
312 		error = sysctl_rdstring(oldp, oldlenp, newp, compatible);
313 		free(compatible, M_TEMP, len);
314 		return error;
315 	default:
316 		return (EOPNOTSUPP);
317 	}
318 	/* NOTREACHED */
319 }
320 
321 int	waittime = -1;
322 
323 __dead void
324 boot(int howto)
325 {
326 	if ((howto & RB_RESET) != 0)
327 		goto doreset;
328 
329 	if (cold) {
330 		if ((howto & RB_USERREQ) == 0)
331 			howto |= RB_HALT;
332 		goto haltsys;
333 	}
334 
335 	boothowto = howto;
336 	if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
337 		waittime = 0;
338 		vfs_shutdown(curproc);
339 
340 		if ((howto & RB_TIMEBAD) == 0) {
341 			resettodr();
342 		} else {
343 			printf("WARNING: not updating battery clock\n");
344 		}
345 	}
346 	if_downall();
347 
348 	uvm_shutdown();
349 	splhigh();
350 	cold = 1;
351 
352 	if ((howto & RB_DUMP) != 0)
353 		printf("no dump so far\n");
354 
355 haltsys:
356 	config_suspend_all(DVACT_POWERDOWN);
357 
358 	if ((howto & RB_HALT) != 0) {
359 		if ((howto & RB_POWERDOWN) != 0) {
360 			printf("\nAttempting to power down...\n");
361 			delay(500000);
362 			if (powerdownfn)
363 				(*powerdownfn)();
364 		}
365 
366 		printf("\n");
367 		printf("The operating system has halted.\n");
368 		printf("Please press any key to reboot.\n\n");
369 		cngetc();
370 	}
371 
372 doreset:
373 	printf("rebooting...\n");
374 	delay(500000);
375 	if (cpuresetfn)
376 		(*cpuresetfn)();
377 	printf("reboot failed; spinning\n");
378 	for (;;)
379 		continue;
380 	/* NOTREACHED */
381 }
382 
383 //Copied from ARM64, removed some registers. XXX
384 void
385 setregs(struct proc *p, struct exec_package *pack, u_long stack,
386     register_t *retval)
387 {
388 	struct trapframe *tf;
389 
390 	/* If we were using the FPU, forget about it. */
391 	if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
392 		fpu_discard(p);
393 	p->p_addr->u_pcb.pcb_flags &= ~PCB_FPU;
394 
395 	tf = p->p_addr->u_pcb.pcb_tf;
396 
397 	memset (tf,0, sizeof(*tf));
398 	tf->tf_a[0] = stack; // XXX Inherited from FreeBSD. Why?
399 	tf->tf_sp = STACKALIGN(stack);
400 	tf->tf_ra = pack->ep_entry;
401 	tf->tf_sepc = pack->ep_entry;
402 
403 	retval[1] = 0;
404 }
405 
406 void
407 need_resched(struct cpu_info *ci)
408 {
409 	ci->ci_want_resched = 1;
410 
411 	/* There's a risk we'll be called before the idle threads start */
412 	if (ci->ci_curproc) {
413 		aston(ci->ci_curproc);
414 		cpu_kick(ci);
415 	}
416 }
417 
418 
419 /*
420  * Size of memory segments, before any memory is stolen.
421  */
422 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
423 int	mem_cluster_cnt;
424 
425 /*
426  * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers.
427  */
428 int
429 cpu_dumpsize(void)
430 {
431 	int size;
432 
433 	size = ALIGN(sizeof(kcore_seg_t)) +
434 	    ALIGN(mem_cluster_cnt * sizeof(phys_ram_seg_t));
435 	if (roundup(size, dbtob(1)) != dbtob(1))
436 		return (-1);
437 
438 	return (1);
439 }
440 
441 int64_t dcache_line_size;	/* The minimum D cache line size */
442 int64_t icache_line_size;	/* The minimum I cache line size */
443 int64_t idcache_line_size;	/* The minimum cache line size */
444 
445 void
446 cache_setup(void)
447 {
448 // XXX TODO CMPE, following freebsd
449 	dcache_line_size = 0;
450 	icache_line_size = 0;
451 	idcache_line_size = 0;
452 }
453 
454 u_long
455 cpu_dump_mempagecnt(void)
456 {
457 	return 0;
458 }
459 
460 //Copied from ARM64
461 /*
462  * These variables are needed by /sbin/savecore
463  */
464 u_long	dumpmag = 0x8fca0101;	/* magic number */
465 int	dumpsize = 0;		/* pages */
466 long	dumplo = 0;		/* blocks */
467 
468 /*
469  * This is called by main to set dumplo and dumpsize.
470  * Dumps always skip the first PAGE_SIZE of disk space
471  * in case there might be a disk label stored there.
472  * If there is extra space, put dump at the end to
473  * reduce the chance that swapping trashes it.
474  */
475 void
476 dumpconf(void)
477 {
478 	int nblks, dumpblks;	/* size of dump area */
479 
480 	if (dumpdev == NODEV ||
481 	    (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
482 		return;
483 	if (nblks <= ctod(1))
484 		return;
485 
486 	dumpblks = cpu_dumpsize();
487 	if (dumpblks < 0)
488 		return;
489 	dumpblks += ctod(cpu_dump_mempagecnt());
490 
491 	/* If dump won't fit (incl. room for possible label), punt. */
492 	if (dumpblks > (nblks - ctod(1)))
493 		return;
494 
495 	/* Put dump at end of partition */
496 	dumplo = nblks - dumpblks;
497 
498 	/* dumpsize is in page units, and doesn't include headers. */
499 	dumpsize = cpu_dump_mempagecnt();
500 }
501 
502 //copied from arm64/sys_machdep.h
503 int
504 sys_sysarch(struct proc *p, void *v, register_t *retval)
505 {
506 	struct sys_sysarch_args /* {
507 		syscallarg(int) op;
508 		syscallarg(void *) parms;
509 	} */ *uap = v;
510 	int error = 0;
511 
512 	switch (SCARG(uap, op)) {
513 	default:
514 		error = EINVAL;
515 		break;
516 	}
517 
518 	return (error);
519 }
520 
521 uint64_t mmap_start;
522 uint32_t mmap_size;
523 uint32_t mmap_desc_size;
524 uint32_t mmap_desc_ver;
525 
526 EFI_MEMORY_DESCRIPTOR *mmap;
527 
528 void	collect_kernel_args(const char *);
529 void	process_kernel_args(void);
530 
531 int	pmap_bootstrap_bs_map(bus_space_tag_t, bus_addr_t,
532 	    bus_size_t, int, bus_space_handle_t *);
533 
534 void
535 initriscv(struct riscv_bootparams *rbp)
536 {
537 	long kernbase = (long)_start & ~PAGE_MASK;
538 	long kvo = rbp->kern_delta;
539 	paddr_t memstart, memend;
540 	vaddr_t vstart;
541 	void *config = (void *)rbp->dtbp_virt;
542 	void *fdt = NULL;
543 	paddr_t fdt_start = (paddr_t)rbp->dtbp_phys;
544 	size_t fdt_size;
545 	EFI_PHYSICAL_ADDRESS system_table = 0;
546 	int (*map_func_save)(bus_space_tag_t, bus_addr_t, bus_size_t, int,
547 	    bus_space_handle_t *);
548 	paddr_t ramstart, ramend;
549 	paddr_t start, end;
550 	int i;
551 
552 	/* Set the per-CPU pointer. */
553 	__asm volatile("mv tp, %0" :: "r"(&cpu_info_primary));
554 
555 	// NOTE that 1GB of ram is mapped in by default in
556 	// the bootstrap memory config, so nothing is necessary
557 	// until pmap_bootstrap_finalize is called??
558 
559 	//NOTE: FDT is already mapped (rbp->dtbp_virt => rbp->dtbp_phys)
560 	// Initialize the Flattened Device Tree
561 	if (!fdt_init(config) || fdt_get_size(config) == 0)
562 		panic("initriscv: no FDT");
563 	fdt_size = fdt_get_size(config);
564 
565 	struct fdt_reg reg;
566 	void *node;
567 
568 	node = fdt_find_node("/cpus");
569 	if (node != NULL) {
570 		char *prop;
571 		int len;
572 
573 		len = fdt_node_property(node, "timebase-frequency", &prop);
574 		if (len == sizeof(tb_freq))
575 			tb_freq = bemtoh32((uint32_t *)prop);
576 	}
577 
578 	node = fdt_find_node("/chosen");
579 	if (node != NULL) {
580 		char *prop;
581 		int len;
582 		static uint8_t lladdr[6];
583 
584 		len = fdt_node_property(node, "boot-hartid", &prop);
585 		if (len == sizeof(boot_hart))
586 			boot_hart = bemtoh32((uint32_t *)prop);
587 
588 		len = fdt_node_property(node, "bootargs", &prop);
589 		if (len > 0)
590 			collect_kernel_args(prop);
591 
592 		len = fdt_node_property(node, "openbsd,boothowto", &prop);
593 		if (len == sizeof(boothowto))
594 			boothowto = bemtoh32((uint32_t *)prop);
595 
596 		len = fdt_node_property(node, "openbsd,bootduid", &prop);
597 		if (len == sizeof(bootduid))
598 			memcpy(bootduid, prop, sizeof(bootduid));
599 
600 		len = fdt_node_property(node, "openbsd,bootmac", &prop);
601 		if (len == sizeof(lladdr)) {
602 			memcpy(lladdr, prop, sizeof(lladdr));
603 			bootmac = lladdr;
604 		}
605 
606 		len = fdt_node_property(node, "openbsd,sr-bootuuid", &prop);
607 #if NSOFTRAID > 0
608 		if (len == sizeof(sr_bootuuid))
609 			memcpy(&sr_bootuuid, prop, sizeof(sr_bootuuid));
610 #endif
611 		if (len > 0)
612 			explicit_bzero(prop, len);
613 
614 		len = fdt_node_property(node, "openbsd,sr-bootkey", &prop);
615 #if NSOFTRAID > 0
616 		if (len == sizeof(sr_bootkey))
617 			memcpy(&sr_bootkey, prop, sizeof(sr_bootkey));
618 #endif
619 		if (len > 0)
620 			explicit_bzero(prop, len);
621 
622 		len = fdt_node_property(node, "openbsd,uefi-mmap-start", &prop);
623 		if (len == sizeof(mmap_start))
624 			mmap_start = bemtoh64((uint64_t *)prop);
625 		len = fdt_node_property(node, "openbsd,uefi-mmap-size", &prop);
626 		if (len == sizeof(mmap_size))
627 			mmap_size = bemtoh32((uint32_t *)prop);
628 		len = fdt_node_property(node, "openbsd,uefi-mmap-desc-size", &prop);
629 		if (len == sizeof(mmap_desc_size))
630 			mmap_desc_size = bemtoh32((uint32_t *)prop);
631 		len = fdt_node_property(node, "openbsd,uefi-mmap-desc-ver", &prop);
632 		if (len == sizeof(mmap_desc_ver))
633 			mmap_desc_ver = bemtoh32((uint32_t *)prop);
634 
635 		len = fdt_node_property(node, "openbsd,uefi-system-table", &prop);
636 		if (len == sizeof(system_table))
637 			system_table = bemtoh64((uint64_t *)prop);
638 
639 		len = fdt_node_property(node, "openbsd,dma-constraint", &prop);
640 		if (len == sizeof(dma_constraint)) {
641 			dma_constraint.ucr_low = bemtoh64((uint64_t *)prop);
642 			dma_constraint.ucr_high = bemtoh64((uint64_t *)prop + 1);
643 		}
644 	}
645 
646 	sbi_init();
647 	cache_setup();//dummy for now
648 
649 	process_kernel_args();
650 
651 	/*
652 	 * Determine physical RAM address range from FDT.
653 	 */
654 	node = fdt_find_node("/memory");
655 	if (node == NULL)
656 		panic("%s: no memory specified", __func__);
657 	ramstart = (paddr_t)-1, ramend = 0;
658 	for (i = 0; i < VM_PHYSSEG_MAX; i++) {
659 		if (fdt_get_reg(node, i, &reg))
660 			break;
661 		if (reg.size == 0)
662 			continue;
663 
664 		start = reg.addr;
665 		end = reg.addr + reg.size;
666 
667 		if (start < ramstart)
668 			ramstart = start;
669 		if (end > ramend)
670 			ramend = end;
671 
672 		physmem += atop(ramend - ramstart);
673 	}
674 
675 	/* The bootloader has loaded us into a 64MB block. */
676 	memstart = KERNBASE + kvo;
677 	memend = memstart + 64 * 1024 * 1024;
678 
679 	/* XXX */
680 	kernbase = KERNBASE;
681 
682 	/* Bootstrap enough of pmap to enter the kernel proper. */
683 	vstart = pmap_bootstrap(kvo, rbp->kern_l1pt,
684 	    kernbase, esym, memstart, memend, ramstart, ramend);
685 
686 	proc0paddr = (struct user *)rbp->kern_stack;
687 
688 	msgbufaddr = (caddr_t)vstart;
689 	msgbufphys = pmap_steal_avail(round_page(MSGBUFSIZE), PAGE_SIZE, NULL);
690 	vstart += round_page(MSGBUFSIZE);
691 
692 	zero_page = vstart;
693 	vstart += MAXCPUS * PAGE_SIZE;
694 	copy_src_page = vstart;
695 	vstart += MAXCPUS * PAGE_SIZE;
696 	copy_dst_page = vstart;
697 	vstart += MAXCPUS * PAGE_SIZE;
698 
699 	/* Relocate the FDT to safe memory. */
700 	if (fdt_size != 0) {
701 		uint32_t csize, size = round_page(fdt_size);
702 		paddr_t pa;
703 		vaddr_t va;
704 
705 		pa = pmap_steal_avail(size, PAGE_SIZE, NULL);
706 		memcpy((void *)PHYS_TO_DMAP(pa),
707 		    (void *)PHYS_TO_DMAP(fdt_start), size);
708 		for (va = vstart, csize = size; csize > 0;
709 		    csize -= PAGE_SIZE, va += PAGE_SIZE, pa += PAGE_SIZE)
710 			pmap_kenter_pa(va, pa, PROT_READ);
711 
712 		fdt = (void *)vstart;
713 		vstart += size;
714 	}
715 
716 	/* Relocate the EFI memory map too. */
717 	if (mmap_start != 0) {
718 		uint32_t csize, size = round_page(mmap_size);
719 		paddr_t pa;
720 		vaddr_t va;
721 
722 		pa = pmap_steal_avail(size, PAGE_SIZE, NULL);
723 		memcpy((void *)PHYS_TO_DMAP(pa),
724 		    (void *)PHYS_TO_DMAP(mmap_start), size);
725 		for (va = vstart, csize = size; csize > 0;
726 		    csize -= PAGE_SIZE, va += PAGE_SIZE, pa += PAGE_SIZE)
727 			pmap_kenter_pa(va, pa, PROT_READ | PROT_WRITE);
728 
729 		mmap = (void *)vstart;
730 		vstart += size;
731 	}
732 
733 	/* No more KVA stealing after this point. */
734 	virtual_avail = vstart;
735 
736 	/* Now we can reinit the FDT, using the virtual address. */
737 	if (fdt)
738 		fdt_init(fdt);
739 
740 	map_func_save = riscv64_bs_tag._space_map;
741 	riscv64_bs_tag._space_map = pmap_bootstrap_bs_map;
742 
743 	consinit();
744 
745 	riscv64_bs_tag._space_map = map_func_save;
746 
747 	pmap_avail_fixup();
748 
749 	uvmexp.pagesize = PAGE_SIZE;
750 	uvm_setpagesize();
751 
752 	/* Make what's left of the initial 64MB block available to UVM. */
753 	pmap_physload_avail();
754 
755 	/* Make all other physical memory available to UVM. */
756 	if (mmap && mmap_desc_ver == EFI_MEMORY_DESCRIPTOR_VERSION) {
757 		EFI_MEMORY_DESCRIPTOR *desc = mmap;
758 
759 		/*
760 		 * Load all memory marked as EfiConventionalMemory,
761 		 * EfiBootServicesCode or EfiBootServicesData.
762 		 * Don't bother with blocks smaller than 64KB.  The
763 		 * initial 64MB memory block should be marked as
764 		 * EfiLoaderData so it won't be added here.
765 		 */
766 		for (i = 0; i < mmap_size / mmap_desc_size; i++) {
767 			printf("type 0x%x pa 0x%llx va 0x%llx pages 0x%llx attr 0x%llx\n",
768 			    desc->Type, desc->PhysicalStart,
769 			    desc->VirtualStart, desc->NumberOfPages,
770 			    desc->Attribute);
771 			if ((desc->Type == EfiConventionalMemory ||
772 			     desc->Type == EfiBootServicesCode ||
773 			     desc->Type == EfiBootServicesData) &&
774 			    desc->NumberOfPages >= 16) {
775 				reg.addr = desc->PhysicalStart;
776 				reg.size = ptoa(desc->NumberOfPages);
777 				memreg_add(&reg);
778 			}
779 			desc = NextMemoryDescriptor(desc, mmap_desc_size);
780 		}
781 	} else {
782 		node = fdt_find_node("/memory");
783 		if (node == NULL)
784 			panic("%s: no memory specified", __func__);
785 
786 		for (i = 0; nmemreg < nitems(memreg); i++) {
787 			if (fdt_get_reg(node, i, &reg))
788 				break;
789 			if (reg.size == 0)
790 				continue;
791 			memreg_add(&reg);
792 		}
793 	}
794 
795 	/* Remove reserved memory. */
796 	node = fdt_find_node("/reserved-memory");
797 	if (node) {
798 		for (node = fdt_child_node(node); node;
799 		    node = fdt_next_node(node)) {
800 			if (fdt_get_reg(node, 0, &reg))
801 				continue;
802 			if (reg.size == 0)
803 				continue;
804 			memreg_remove(&reg);
805 		}
806 	}
807 
808 	/* Remove the initial 64MB block. */
809 	reg.addr = memstart;
810 	reg.size = memend - memstart;
811 	memreg_remove(&reg);
812 
813 	for (i = 0; i < nmemreg; i++) {
814 		paddr_t start = memreg[i].addr;
815 		paddr_t end = start + memreg[i].size;
816 
817 		uvm_page_physload(atop(start), atop(end),
818 		    atop(start), atop(end), 0);
819 	}
820 
821 	/*
822 	 * Make sure that we have enough KVA to initialize UVM.  In
823 	 * particular, we need enough KVA to be able to allocate the
824 	 * vm_page structures.
825 	 */
826 	pmap_growkernel(VM_MIN_KERNEL_ADDRESS + 1024 * 1024 * 1024 +
827 	    physmem * sizeof(struct vm_page));
828 
829 #ifdef DDB
830 	db_machine_init();
831 
832 	/* Firmware doesn't load symbols. */
833 	ddb_init();
834 
835 	if (boothowto & RB_KDB)
836 		db_enter();
837 #endif
838 
839 	softintr_init();
840 	splraise(IPL_IPI);
841 }
842 
843 char bootargs[256];
844 
845 void
846 collect_kernel_args(const char *args)
847 {
848 	/* Make a local copy of the bootargs */
849 	strlcpy(bootargs, args, sizeof(bootargs));
850 }
851 
852 void
853 process_kernel_args(void)
854 {
855 	char *cp = bootargs;
856 
857 	if (*cp == 0)
858 		return;
859 
860 	/* Skip the kernel image filename */
861 	while (*cp != ' ' && *cp != 0)
862 		cp++;
863 
864 	if (*cp != 0)
865 		*cp++ = 0;
866 
867 	while (*cp == ' ')
868 		cp++;
869 
870 	boot_args = cp;
871 
872 	printf("bootargs: %s\n", boot_args);
873 
874 	/* Setup pointer to boot flags */
875 	while (*cp != '-')
876 		if (*cp++ == '\0')
877 			return;
878 
879 	while (*cp != 0) {
880 		switch (*cp) {
881 		case 'a':
882 			boothowto |= RB_ASKNAME;
883 			break;
884 		case 'c':
885 			boothowto |= RB_CONFIG;
886 			break;
887 		case 'd':
888 			boothowto |= RB_KDB;
889 			break;
890 		case 's':
891 			boothowto |= RB_SINGLE;
892 			break;
893 		default:
894 			printf("unknown option `%c'\n", *cp);
895 			break;
896 		}
897 		cp++;
898 	}
899 }
900 
901 /*
902  * Allow bootstrap to steal KVA after machdep has given it back to pmap.
903  */
904 int
905 pmap_bootstrap_bs_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size,
906     int flags, bus_space_handle_t *bshp)
907 {
908 	u_long startpa, pa, endpa;
909 	vaddr_t va;
910 
911 	va = virtual_avail;	/* steal memory from virtual avail. */
912 
913 	startpa = trunc_page(bpa);
914 	endpa = round_page((bpa + size));
915 
916 	*bshp = (bus_space_handle_t)(va + (bpa - startpa));
917 
918 	for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE)
919 		pmap_kenter_pa(va, pa, PROT_READ | PROT_WRITE);
920 
921 	virtual_avail = va;
922 
923 	return 0;
924 }
925 
926 void
927 memreg_add(const struct fdt_reg *reg)
928 {
929 	if (nmemreg >= nitems(memreg))
930 		return;
931 
932 	memreg[nmemreg++] = *reg;
933 }
934 
935 void
936 memreg_remove(const struct fdt_reg *reg)
937 {
938 	uint64_t start = reg->addr;
939 	uint64_t end = reg->addr + reg->size;
940 	int i, j;
941 
942 	for (i = 0; i < nmemreg; i++) {
943 		uint64_t memstart = memreg[i].addr;
944 		uint64_t memend = memreg[i].addr + memreg[i].size;
945 
946 		if (end <= memstart)
947 			continue;
948 		if (start >= memend)
949 			continue;
950 
951 		if (start <= memstart)
952 			memstart = MIN(end, memend);
953 		if (end >= memend)
954 			memend = MAX(start, memstart);
955 
956 		if (start > memstart && end < memend) {
957 			if (nmemreg < nitems(memreg)) {
958 				memreg[nmemreg].addr = end;
959 				memreg[nmemreg].size = memend - end;
960 				nmemreg++;
961 			}
962 			memend = start;
963 		}
964 		memreg[i].addr = memstart;
965 		memreg[i].size = memend - memstart;
966 	}
967 
968 	/* Remove empty slots. */
969 	for (i = nmemreg - 1; i >= 0; i--) {
970 		if (memreg[i].size == 0) {
971 			for (j = i; (j + 1) < nmemreg; j++)
972 				memreg[j] = memreg[j + 1];
973 			nmemreg--;
974 		}
975 	}
976 }
977