1281494Sandrew/*-
2281494Sandrew * Copyright (c) 2014 Andrew Turner
3281494Sandrew * All rights reserved.
4281494Sandrew *
5281494Sandrew * Redistribution and use in source and binary forms, with or without
6281494Sandrew * modification, are permitted provided that the following conditions
7281494Sandrew * are met:
8281494Sandrew * 1. Redistributions of source code must retain the above copyright
9281494Sandrew *    notice, this list of conditions and the following disclaimer.
10281494Sandrew * 2. Redistributions in binary form must reproduce the above copyright
11281494Sandrew *    notice, this list of conditions and the following disclaimer in the
12281494Sandrew *    documentation and/or other materials provided with the distribution.
13281494Sandrew *
14281494Sandrew * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15281494Sandrew * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16281494Sandrew * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17281494Sandrew * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18281494Sandrew * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19281494Sandrew * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20281494Sandrew * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21281494Sandrew * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22281494Sandrew * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23281494Sandrew * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24281494Sandrew * SUCH DAMAGE.
25281494Sandrew *
26281494Sandrew */
27281494Sandrew
28281494Sandrew#include "opt_platform.h"
29287487Sandrew#include "opt_ddb.h"
30281494Sandrew
31281494Sandrew#include <sys/cdefs.h>
32281494Sandrew__FBSDID("$FreeBSD: stable/11/sys/arm64/arm64/machdep.c 341166 2018-11-28 21:20:51Z vangyzen $");
33281494Sandrew
34281494Sandrew#include <sys/param.h>
35281494Sandrew#include <sys/systm.h>
36281494Sandrew#include <sys/buf.h>
37281494Sandrew#include <sys/bus.h>
38281494Sandrew#include <sys/cons.h>
39281494Sandrew#include <sys/cpu.h>
40298627Sbr#include <sys/devmap.h>
41281494Sandrew#include <sys/efi.h>
42281494Sandrew#include <sys/exec.h>
43281494Sandrew#include <sys/imgact.h>
44281494Sandrew#include <sys/kdb.h>
45281494Sandrew#include <sys/kernel.h>
46281494Sandrew#include <sys/limits.h>
47281494Sandrew#include <sys/linker.h>
48281494Sandrew#include <sys/msgbuf.h>
49281494Sandrew#include <sys/pcpu.h>
50281494Sandrew#include <sys/proc.h>
51281494Sandrew#include <sys/ptrace.h>
52281494Sandrew#include <sys/reboot.h>
53281494Sandrew#include <sys/rwlock.h>
54281494Sandrew#include <sys/sched.h>
55281494Sandrew#include <sys/signalvar.h>
56281494Sandrew#include <sys/syscallsubr.h>
57281494Sandrew#include <sys/sysent.h>
58281494Sandrew#include <sys/sysproto.h>
59281494Sandrew#include <sys/ucontext.h>
60291937Skib#include <sys/vdso.h>
61281494Sandrew
62281494Sandrew#include <vm/vm.h>
63281494Sandrew#include <vm/vm_kern.h>
64281494Sandrew#include <vm/vm_object.h>
65281494Sandrew#include <vm/vm_page.h>
66281494Sandrew#include <vm/pmap.h>
67281494Sandrew#include <vm/vm_map.h>
68281494Sandrew#include <vm/vm_pager.h>
69281494Sandrew
70281494Sandrew#include <machine/armreg.h>
71281494Sandrew#include <machine/cpu.h>
72281494Sandrew#include <machine/debug_monitor.h>
73281494Sandrew#include <machine/kdb.h>
74281494Sandrew#include <machine/machdep.h>
75281494Sandrew#include <machine/metadata.h>
76291937Skib#include <machine/md_var.h>
77281494Sandrew#include <machine/pcb.h>
78281494Sandrew#include <machine/reg.h>
79281494Sandrew#include <machine/vmparam.h>
80281494Sandrew
81281494Sandrew#ifdef VFP
82281494Sandrew#include <machine/vfp.h>
83281494Sandrew#endif
84281494Sandrew
85281494Sandrew#ifdef FDT
86296266Swma#include <dev/fdt/fdt_common.h>
87281494Sandrew#include <dev/ofw/openfirm.h>
88281494Sandrew#endif
89281494Sandrew
90281494Sandrewstruct pcpu __pcpu[MAXCPU];
91281494Sandrew
92281494Sandrewstatic struct trapframe proc0_tf;
93281494Sandrew
94281494Sandrewvm_paddr_t phys_avail[PHYS_AVAIL_SIZE + 2];
95281494Sandrewvm_paddr_t dump_avail[PHYS_AVAIL_SIZE + 2];
96281494Sandrew
97281494Sandrewint early_boot = 1;
98281494Sandrewint cold = 1;
99281494Sandrewlong realmem = 0;
100281494Sandrewlong Maxmem = 0;
101281494Sandrew
102281494Sandrew#define	PHYSMAP_SIZE	(2 * (VM_PHYSSEG_MAX - 1))
103281494Sandrewvm_paddr_t physmap[PHYSMAP_SIZE];
104281494Sandrewu_int physmap_idx;
105281494Sandrew
106281494Sandrewstruct kva_md_info kmi;
107281494Sandrew
108281494Sandrewint64_t dcache_line_size;	/* The minimum D cache line size */
109281494Sandrewint64_t icache_line_size;	/* The minimum I cache line size */
110281494Sandrewint64_t idcache_line_size;	/* The minimum cache line size */
111297536Swmaint64_t dczva_line_size;	/* The size of cache line the dc zva zeroes */
112319202Sandrewint has_pan;
113281494Sandrew
114297538Swma/* pagezero_* implementations are provided in support.S */
115297538Swmavoid pagezero_simple(void *);
116297538Swmavoid pagezero_cache(void *);
117297538Swma
118297538Swma/* pagezero_simple is default pagezero */
119297538Swmavoid (*pagezero)(void *p) = pagezero_simple;
120297538Swma
121281494Sandrewstatic void
122319202Sandrewpan_setup(void)
123319202Sandrew{
124319202Sandrew	uint64_t id_aa64mfr1;
125319202Sandrew
126319202Sandrew	id_aa64mfr1 = READ_SPECIALREG(id_aa64mmfr1_el1);
127319202Sandrew	if (ID_AA64MMFR1_PAN(id_aa64mfr1) != ID_AA64MMFR1_PAN_NONE)
128319202Sandrew		has_pan = 1;
129319202Sandrew}
130319202Sandrew
131319202Sandrewvoid
132319202Sandrewpan_enable(void)
133319202Sandrew{
134319202Sandrew
135319202Sandrew	/*
136319202Sandrew	 * The LLVM integrated assembler doesn't understand the PAN
137319202Sandrew	 * PSTATE field. Because of this we need to manually create
138319202Sandrew	 * the instruction in an asm block. This is equivalent to:
139319202Sandrew	 * msr pan, #1
140319202Sandrew	 *
141319202Sandrew	 * This sets the PAN bit, stopping the kernel from accessing
142319202Sandrew	 * memory when userspace can also access it unless the kernel
143319202Sandrew	 * uses the userspace load/store instructions.
144319202Sandrew	 */
145319202Sandrew	if (has_pan) {
146319202Sandrew		WRITE_SPECIALREG(sctlr_el1,
147319202Sandrew		    READ_SPECIALREG(sctlr_el1) & ~SCTLR_SPAN);
148319202Sandrew		__asm __volatile(".inst 0xd500409f | (0x1 << 8)");
149319202Sandrew	}
150319202Sandrew}
151319202Sandrew
152319202Sandrewstatic void
153281494Sandrewcpu_startup(void *dummy)
154281494Sandrew{
155281494Sandrew
156281494Sandrew	identify_cpu();
157281494Sandrew
158281494Sandrew	vm_ksubmap_init(&kmi);
159281494Sandrew	bufinit();
160281494Sandrew	vm_pager_bufferinit();
161281494Sandrew}
162281494Sandrew
163281494SandrewSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
164281494Sandrew
165285316Sandrewint
166285316Sandrewcpu_idle_wakeup(int cpu)
167285316Sandrew{
168285316Sandrew
169285316Sandrew	return (0);
170285316Sandrew}
171285316Sandrew
172281494Sandrewint
173281494Sandrewfill_regs(struct thread *td, struct reg *regs)
174281494Sandrew{
175281494Sandrew	struct trapframe *frame;
176281494Sandrew
177281494Sandrew	frame = td->td_frame;
178281494Sandrew	regs->sp = frame->tf_sp;
179281494Sandrew	regs->lr = frame->tf_lr;
180281494Sandrew	regs->elr = frame->tf_elr;
181281494Sandrew	regs->spsr = frame->tf_spsr;
182281494Sandrew
183281494Sandrew	memcpy(regs->x, frame->tf_x, sizeof(regs->x));
184281494Sandrew
185281494Sandrew	return (0);
186281494Sandrew}
187281494Sandrew
188281494Sandrewint
189281494Sandrewset_regs(struct thread *td, struct reg *regs)
190281494Sandrew{
191281494Sandrew	struct trapframe *frame;
192281494Sandrew
193281494Sandrew	frame = td->td_frame;
194281494Sandrew	frame->tf_sp = regs->sp;
195281494Sandrew	frame->tf_lr = regs->lr;
196281494Sandrew	frame->tf_elr = regs->elr;
197326313Sandrew	frame->tf_spsr &= ~PSR_FLAGS;
198326313Sandrew	frame->tf_spsr |= regs->spsr & PSR_FLAGS;
199281494Sandrew
200281494Sandrew	memcpy(frame->tf_x, regs->x, sizeof(frame->tf_x));
201281494Sandrew
202281494Sandrew	return (0);
203281494Sandrew}
204281494Sandrew
205281494Sandrewint
206281494Sandrewfill_fpregs(struct thread *td, struct fpreg *regs)
207281494Sandrew{
208281494Sandrew#ifdef VFP
209281494Sandrew	struct pcb *pcb;
210281494Sandrew
211281494Sandrew	pcb = td->td_pcb;
212281494Sandrew	if ((pcb->pcb_fpflags & PCB_FP_STARTED) != 0) {
213281494Sandrew		/*
214281494Sandrew		 * If we have just been running VFP instructions we will
215281494Sandrew		 * need to save the state to memcpy it below.
216281494Sandrew		 */
217322760Sjhb		if (td == curthread)
218322760Sjhb			vfp_save_state(td, pcb);
219281494Sandrew
220281494Sandrew		memcpy(regs->fp_q, pcb->pcb_vfp, sizeof(regs->fp_q));
221281494Sandrew		regs->fp_cr = pcb->pcb_fpcr;
222281494Sandrew		regs->fp_sr = pcb->pcb_fpsr;
223281494Sandrew	} else
224281494Sandrew#endif
225340017Sjhb		memset(regs, 0, sizeof(*regs));
226281494Sandrew	return (0);
227281494Sandrew}
228281494Sandrew
229281494Sandrewint
230281494Sandrewset_fpregs(struct thread *td, struct fpreg *regs)
231281494Sandrew{
232281494Sandrew#ifdef VFP
233281494Sandrew	struct pcb *pcb;
234281494Sandrew
235281494Sandrew	pcb = td->td_pcb;
236281494Sandrew	memcpy(pcb->pcb_vfp, regs->fp_q, sizeof(regs->fp_q));
237281494Sandrew	pcb->pcb_fpcr = regs->fp_cr;
238281494Sandrew	pcb->pcb_fpsr = regs->fp_sr;
239281494Sandrew#endif
240281494Sandrew	return (0);
241281494Sandrew}
242281494Sandrew
243281494Sandrewint
244281494Sandrewfill_dbregs(struct thread *td, struct dbreg *regs)
245281494Sandrew{
246281494Sandrew
247322748Semaste	printf("ARM64TODO: fill_dbregs");
248322748Semaste	return (EDOOFUS);
249281494Sandrew}
250281494Sandrew
251281494Sandrewint
252281494Sandrewset_dbregs(struct thread *td, struct dbreg *regs)
253281494Sandrew{
254281494Sandrew
255322748Semaste	printf("ARM64TODO: set_dbregs");
256322748Semaste	return (EDOOFUS);
257281494Sandrew}
258281494Sandrew
259281494Sandrewint
260281494Sandrewptrace_set_pc(struct thread *td, u_long addr)
261281494Sandrew{
262281494Sandrew
263322748Semaste	printf("ARM64TODO: ptrace_set_pc");
264322748Semaste	return (EDOOFUS);
265281494Sandrew}
266281494Sandrew
267281494Sandrewint
268281494Sandrewptrace_single_step(struct thread *td)
269281494Sandrew{
270281494Sandrew
271295142Sandrew	td->td_frame->tf_spsr |= PSR_SS;
272295142Sandrew	td->td_pcb->pcb_flags |= PCB_SINGLE_STEP;
273281494Sandrew	return (0);
274281494Sandrew}
275281494Sandrew
276281494Sandrewint
277281494Sandrewptrace_clear_single_step(struct thread *td)
278281494Sandrew{
279281494Sandrew
280295142Sandrew	td->td_frame->tf_spsr &= ~PSR_SS;
281295142Sandrew	td->td_pcb->pcb_flags &= ~PCB_SINGLE_STEP;
282281494Sandrew	return (0);
283281494Sandrew}
284281494Sandrew
285281494Sandrewvoid
286281494Sandrewexec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
287281494Sandrew{
288281494Sandrew	struct trapframe *tf = td->td_frame;
289281494Sandrew
290281494Sandrew	memset(tf, 0, sizeof(struct trapframe));
291281494Sandrew
292289502Sandrew	/*
293289502Sandrew	 * We need to set x0 for init as it doesn't call
294289502Sandrew	 * cpu_set_syscall_retval to copy the value. We also
295289502Sandrew	 * need to set td_retval for the cases where we do.
296289502Sandrew	 */
297289502Sandrew	tf->tf_x[0] = td->td_retval[0] = stack;
298289502Sandrew	tf->tf_sp = STACKALIGN(stack);
299281494Sandrew	tf->tf_lr = imgp->entry_addr;
300281494Sandrew	tf->tf_elr = imgp->entry_addr;
301281494Sandrew}
302281494Sandrew
303281494Sandrew/* Sanity check these are the same size, they will be memcpy'd to and fro */
304281494SandrewCTASSERT(sizeof(((struct trapframe *)0)->tf_x) ==
305281494Sandrew    sizeof((struct gpregs *)0)->gp_x);
306281494SandrewCTASSERT(sizeof(((struct trapframe *)0)->tf_x) ==
307281494Sandrew    sizeof((struct reg *)0)->x);
308281494Sandrew
309281494Sandrewint
310281494Sandrewget_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret)
311281494Sandrew{
312281494Sandrew	struct trapframe *tf = td->td_frame;
313281494Sandrew
314285334Sandrew	if (clear_ret & GET_MC_CLEAR_RET) {
315281494Sandrew		mcp->mc_gpregs.gp_x[0] = 0;
316285334Sandrew		mcp->mc_gpregs.gp_spsr = tf->tf_spsr & ~PSR_C;
317285334Sandrew	} else {
318281494Sandrew		mcp->mc_gpregs.gp_x[0] = tf->tf_x[0];
319285334Sandrew		mcp->mc_gpregs.gp_spsr = tf->tf_spsr;
320285334Sandrew	}
321281494Sandrew
322281494Sandrew	memcpy(&mcp->mc_gpregs.gp_x[1], &tf->tf_x[1],
323281494Sandrew	    sizeof(mcp->mc_gpregs.gp_x[1]) * (nitems(mcp->mc_gpregs.gp_x) - 1));
324281494Sandrew
325281494Sandrew	mcp->mc_gpregs.gp_sp = tf->tf_sp;
326281494Sandrew	mcp->mc_gpregs.gp_lr = tf->tf_lr;
327281494Sandrew	mcp->mc_gpregs.gp_elr = tf->tf_elr;
328281494Sandrew
329281494Sandrew	return (0);
330281494Sandrew}
331281494Sandrew
332281494Sandrewint
333281494Sandrewset_mcontext(struct thread *td, mcontext_t *mcp)
334281494Sandrew{
335281494Sandrew	struct trapframe *tf = td->td_frame;
336326313Sandrew	uint32_t spsr;
337281494Sandrew
338326313Sandrew	spsr = mcp->mc_gpregs.gp_spsr;
339326313Sandrew	if ((spsr & PSR_M_MASK) != PSR_M_EL0t ||
340326313Sandrew	    (spsr & (PSR_F | PSR_I | PSR_A | PSR_D)) != 0)
341326313Sandrew		return (EINVAL);
342326313Sandrew
343281494Sandrew	memcpy(tf->tf_x, mcp->mc_gpregs.gp_x, sizeof(tf->tf_x));
344281494Sandrew
345281494Sandrew	tf->tf_sp = mcp->mc_gpregs.gp_sp;
346281494Sandrew	tf->tf_lr = mcp->mc_gpregs.gp_lr;
347281494Sandrew	tf->tf_elr = mcp->mc_gpregs.gp_elr;
348281494Sandrew	tf->tf_spsr = mcp->mc_gpregs.gp_spsr;
349281494Sandrew
350281494Sandrew	return (0);
351281494Sandrew}
352281494Sandrew
353281494Sandrewstatic void
354281494Sandrewget_fpcontext(struct thread *td, mcontext_t *mcp)
355281494Sandrew{
356281494Sandrew#ifdef VFP
357281494Sandrew	struct pcb *curpcb;
358281494Sandrew
359281494Sandrew	critical_enter();
360281494Sandrew
361281494Sandrew	curpcb = curthread->td_pcb;
362281494Sandrew
363281494Sandrew	if ((curpcb->pcb_fpflags & PCB_FP_STARTED) != 0) {
364281494Sandrew		/*
365281494Sandrew		 * If we have just been running VFP instructions we will
366281494Sandrew		 * need to save the state to memcpy it below.
367281494Sandrew		 */
368286225Sandrew		vfp_save_state(td, curpcb);
369281494Sandrew
370281494Sandrew		memcpy(mcp->mc_fpregs.fp_q, curpcb->pcb_vfp,
371281494Sandrew		    sizeof(mcp->mc_fpregs));
372281494Sandrew		mcp->mc_fpregs.fp_cr = curpcb->pcb_fpcr;
373281494Sandrew		mcp->mc_fpregs.fp_sr = curpcb->pcb_fpsr;
374281494Sandrew		mcp->mc_fpregs.fp_flags = curpcb->pcb_fpflags;
375281494Sandrew		mcp->mc_flags |= _MC_FP_VALID;
376281494Sandrew	}
377281494Sandrew
378281494Sandrew	critical_exit();
379281494Sandrew#endif
380281494Sandrew}
381281494Sandrew
382281494Sandrewstatic void
383281494Sandrewset_fpcontext(struct thread *td, mcontext_t *mcp)
384281494Sandrew{
385281494Sandrew#ifdef VFP
386281494Sandrew	struct pcb *curpcb;
387281494Sandrew
388281494Sandrew	critical_enter();
389281494Sandrew
390281494Sandrew	if ((mcp->mc_flags & _MC_FP_VALID) != 0) {
391281494Sandrew		curpcb = curthread->td_pcb;
392281494Sandrew
393281494Sandrew		/*
394281494Sandrew		 * Discard any vfp state for the current thread, we
395281494Sandrew		 * are about to override it.
396281494Sandrew		 */
397281494Sandrew		vfp_discard(td);
398281494Sandrew
399281494Sandrew		memcpy(curpcb->pcb_vfp, mcp->mc_fpregs.fp_q,
400281494Sandrew		    sizeof(mcp->mc_fpregs));
401281494Sandrew		curpcb->pcb_fpcr = mcp->mc_fpregs.fp_cr;
402281494Sandrew		curpcb->pcb_fpsr = mcp->mc_fpregs.fp_sr;
403281494Sandrew		curpcb->pcb_fpflags = mcp->mc_fpregs.fp_flags;
404281494Sandrew	}
405281494Sandrew
406281494Sandrew	critical_exit();
407281494Sandrew#endif
408281494Sandrew}
409281494Sandrew
410281494Sandrewvoid
411281494Sandrewcpu_idle(int busy)
412281494Sandrew{
413281494Sandrew
414281494Sandrew	spinlock_enter();
415281494Sandrew	if (!busy)
416281494Sandrew		cpu_idleclock();
417281494Sandrew	if (!sched_runnable())
418281494Sandrew		__asm __volatile(
419281494Sandrew		    "dsb sy \n"
420281494Sandrew		    "wfi    \n");
421281494Sandrew	if (!busy)
422281494Sandrew		cpu_activeclock();
423281494Sandrew	spinlock_exit();
424281494Sandrew}
425281494Sandrew
426281494Sandrewvoid
427281494Sandrewcpu_halt(void)
428281494Sandrew{
429281494Sandrew
430286134Sandrew	/* We should have shutdown by now, if not enter a low power sleep */
431286134Sandrew	intr_disable();
432286134Sandrew	while (1) {
433286134Sandrew		__asm __volatile("wfi");
434286134Sandrew	}
435281494Sandrew}
436281494Sandrew
437281494Sandrew/*
438281494Sandrew * Flush the D-cache for non-DMA I/O so that the I-cache can
439281494Sandrew * be made coherent later.
440281494Sandrew */
441281494Sandrewvoid
442281494Sandrewcpu_flush_dcache(void *ptr, size_t len)
443281494Sandrew{
444281494Sandrew
445286073Semaste	/* ARM64TODO TBD */
446281494Sandrew}
447281494Sandrew
448281494Sandrew/* Get current clock frequency for the given CPU ID. */
449281494Sandrewint
450281494Sandrewcpu_est_clockrate(int cpu_id, uint64_t *rate)
451281494Sandrew{
452306085Sandrew	struct pcpu *pc;
453281494Sandrew
454306085Sandrew	pc = pcpu_find(cpu_id);
455306085Sandrew	if (pc == NULL || rate == NULL)
456306085Sandrew		return (EINVAL);
457306085Sandrew
458306085Sandrew	if (pc->pc_clock == 0)
459306085Sandrew		return (EOPNOTSUPP);
460306085Sandrew
461306085Sandrew	*rate = pc->pc_clock;
462306085Sandrew	return (0);
463281494Sandrew}
464281494Sandrew
465281494Sandrewvoid
466281494Sandrewcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
467281494Sandrew{
468284273Sandrew
469284273Sandrew	pcpu->pc_acpi_id = 0xffffffff;
470281494Sandrew}
471281494Sandrew
472281494Sandrewvoid
473281494Sandrewspinlock_enter(void)
474281494Sandrew{
475281494Sandrew	struct thread *td;
476281494Sandrew	register_t daif;
477281494Sandrew
478281494Sandrew	td = curthread;
479281494Sandrew	if (td->td_md.md_spinlock_count == 0) {
480281494Sandrew		daif = intr_disable();
481281494Sandrew		td->td_md.md_spinlock_count = 1;
482281494Sandrew		td->td_md.md_saved_daif = daif;
483281494Sandrew	} else
484281494Sandrew		td->td_md.md_spinlock_count++;
485281494Sandrew	critical_enter();
486281494Sandrew}
487281494Sandrew
488281494Sandrewvoid
489281494Sandrewspinlock_exit(void)
490281494Sandrew{
491281494Sandrew	struct thread *td;
492281494Sandrew	register_t daif;
493281494Sandrew
494281494Sandrew	td = curthread;
495281494Sandrew	critical_exit();
496281494Sandrew	daif = td->td_md.md_saved_daif;
497281494Sandrew	td->td_md.md_spinlock_count--;
498281494Sandrew	if (td->td_md.md_spinlock_count == 0)
499281494Sandrew		intr_restore(daif);
500281494Sandrew}
501281494Sandrew
502281494Sandrew#ifndef	_SYS_SYSPROTO_H_
503281494Sandrewstruct sigreturn_args {
504281494Sandrew	ucontext_t *ucp;
505281494Sandrew};
506281494Sandrew#endif
507281494Sandrew
508281494Sandrewint
509281494Sandrewsys_sigreturn(struct thread *td, struct sigreturn_args *uap)
510281494Sandrew{
511281494Sandrew	ucontext_t uc;
512326313Sandrew	int error;
513281494Sandrew
514281494Sandrew	if (uap == NULL)
515281494Sandrew		return (EFAULT);
516281494Sandrew	if (copyin(uap->sigcntxp, &uc, sizeof(uc)))
517281494Sandrew		return (EFAULT);
518281494Sandrew
519326313Sandrew	error = set_mcontext(td, &uc.uc_mcontext);
520326313Sandrew	if (error != 0)
521326313Sandrew		return (error);
522281494Sandrew	set_fpcontext(td, &uc.uc_mcontext);
523281494Sandrew
524281494Sandrew	/* Restore signal mask. */
525281494Sandrew	kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
526281494Sandrew
527281494Sandrew	return (EJUSTRETURN);
528281494Sandrew}
529281494Sandrew
530281494Sandrew/*
531281494Sandrew * Construct a PCB from a trapframe. This is called from kdb_trap() where
532281494Sandrew * we want to start a backtrace from the function that caused us to enter
533281494Sandrew * the debugger. We have the context in the trapframe, but base the trace
534281494Sandrew * on the PCB. The PCB doesn't have to be perfect, as long as it contains
535281494Sandrew * enough for a backtrace.
536281494Sandrew */
537281494Sandrewvoid
538281494Sandrewmakectx(struct trapframe *tf, struct pcb *pcb)
539281494Sandrew{
540281494Sandrew	int i;
541281494Sandrew
542281494Sandrew	for (i = 0; i < PCB_LR; i++)
543281494Sandrew		pcb->pcb_x[i] = tf->tf_x[i];
544281494Sandrew
545281494Sandrew	pcb->pcb_x[PCB_LR] = tf->tf_lr;
546281494Sandrew	pcb->pcb_pc = tf->tf_elr;
547281494Sandrew	pcb->pcb_sp = tf->tf_sp;
548281494Sandrew}
549281494Sandrew
550281494Sandrewvoid
551281494Sandrewsendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
552281494Sandrew{
553281494Sandrew	struct thread *td;
554281494Sandrew	struct proc *p;
555281494Sandrew	struct trapframe *tf;
556281494Sandrew	struct sigframe *fp, frame;
557281494Sandrew	struct sigacts *psp;
558291937Skib	struct sysentvec *sysent;
559281494Sandrew	int code, onstack, sig;
560281494Sandrew
561281494Sandrew	td = curthread;
562281494Sandrew	p = td->td_proc;
563281494Sandrew	PROC_LOCK_ASSERT(p, MA_OWNED);
564281494Sandrew
565281494Sandrew	sig = ksi->ksi_signo;
566281494Sandrew	code = ksi->ksi_code;
567281494Sandrew	psp = p->p_sigacts;
568281494Sandrew	mtx_assert(&psp->ps_mtx, MA_OWNED);
569281494Sandrew
570281494Sandrew	tf = td->td_frame;
571281494Sandrew	onstack = sigonstack(tf->tf_sp);
572281494Sandrew
573281494Sandrew	CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
574281494Sandrew	    catcher, sig);
575281494Sandrew
576281494Sandrew	/* Allocate and validate space for the signal handler context. */
577281494Sandrew	if ((td->td_pflags & TDP_ALTSTACK) != 0 && !onstack &&
578281494Sandrew	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
579294930Sjhb		fp = (struct sigframe *)((uintptr_t)td->td_sigstk.ss_sp +
580281494Sandrew		    td->td_sigstk.ss_size);
581281494Sandrew#if defined(COMPAT_43)
582281494Sandrew		td->td_sigstk.ss_flags |= SS_ONSTACK;
583281494Sandrew#endif
584281494Sandrew	} else {
585281494Sandrew		fp = (struct sigframe *)td->td_frame->tf_sp;
586281494Sandrew	}
587281494Sandrew
588281494Sandrew	/* Make room, keeping the stack aligned */
589281494Sandrew	fp--;
590281494Sandrew	fp = (struct sigframe *)STACKALIGN(fp);
591281494Sandrew
592281494Sandrew	/* Fill in the frame to copy out */
593341166Svangyzen	bzero(&frame, sizeof(frame));
594281494Sandrew	get_mcontext(td, &frame.sf_uc.uc_mcontext, 0);
595281494Sandrew	get_fpcontext(td, &frame.sf_uc.uc_mcontext);
596281494Sandrew	frame.sf_si = ksi->ksi_info;
597281494Sandrew	frame.sf_uc.uc_sigmask = *mask;
598281494Sandrew	frame.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) ?
599281494Sandrew	    ((onstack) ? SS_ONSTACK : 0) : SS_DISABLE;
600281494Sandrew	frame.sf_uc.uc_stack = td->td_sigstk;
601281494Sandrew	mtx_unlock(&psp->ps_mtx);
602281494Sandrew	PROC_UNLOCK(td->td_proc);
603281494Sandrew
604281494Sandrew	/* Copy the sigframe out to the user's stack. */
605281494Sandrew	if (copyout(&frame, fp, sizeof(*fp)) != 0) {
606281494Sandrew		/* Process has trashed its stack. Kill it. */
607281494Sandrew		CTR2(KTR_SIG, "sendsig: sigexit td=%p fp=%p", td, fp);
608281494Sandrew		PROC_LOCK(p);
609281494Sandrew		sigexit(td, SIGILL);
610281494Sandrew	}
611281494Sandrew
612281494Sandrew	tf->tf_x[0]= sig;
613281494Sandrew	tf->tf_x[1] = (register_t)&fp->sf_si;
614281494Sandrew	tf->tf_x[2] = (register_t)&fp->sf_uc;
615281494Sandrew
616281494Sandrew	tf->tf_elr = (register_t)catcher;
617281494Sandrew	tf->tf_sp = (register_t)fp;
618291937Skib	sysent = p->p_sysent;
619291937Skib	if (sysent->sv_sigcode_base != 0)
620291937Skib		tf->tf_lr = (register_t)sysent->sv_sigcode_base;
621291937Skib	else
622291937Skib		tf->tf_lr = (register_t)(sysent->sv_psstrings -
623291937Skib		    *(sysent->sv_szsigcode));
624281494Sandrew
625281494Sandrew	CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, tf->tf_elr,
626281494Sandrew	    tf->tf_sp);
627281494Sandrew
628281494Sandrew	PROC_LOCK(p);
629281494Sandrew	mtx_lock(&psp->ps_mtx);
630281494Sandrew}
631281494Sandrew
632281494Sandrewstatic void
633281494Sandrewinit_proc0(vm_offset_t kstack)
634281494Sandrew{
635281494Sandrew	struct pcpu *pcpup = &__pcpu[0];
636281494Sandrew
637281494Sandrew	proc_linkup0(&proc0, &thread0);
638281494Sandrew	thread0.td_kstack = kstack;
639281494Sandrew	thread0.td_pcb = (struct pcb *)(thread0.td_kstack) - 1;
640281494Sandrew	thread0.td_pcb->pcb_fpflags = 0;
641281494Sandrew	thread0.td_pcb->pcb_vfpcpu = UINT_MAX;
642281494Sandrew	thread0.td_frame = &proc0_tf;
643281494Sandrew	pcpup->pc_curpcb = thread0.td_pcb;
644281494Sandrew}
645281494Sandrew
646281494Sandrewtypedef struct {
647281494Sandrew	uint32_t type;
648281494Sandrew	uint64_t phys_start;
649281494Sandrew	uint64_t virt_start;
650281494Sandrew	uint64_t num_pages;
651281494Sandrew	uint64_t attr;
652281494Sandrew} EFI_MEMORY_DESCRIPTOR;
653281494Sandrew
654281494Sandrewstatic int
655281494Sandrewadd_physmap_entry(uint64_t base, uint64_t length, vm_paddr_t *physmap,
656281494Sandrew    u_int *physmap_idxp)
657281494Sandrew{
658281494Sandrew	u_int i, insert_idx, _physmap_idx;
659281494Sandrew
660281494Sandrew	_physmap_idx = *physmap_idxp;
661281494Sandrew
662281494Sandrew	if (length == 0)
663281494Sandrew		return (1);
664281494Sandrew
665281494Sandrew	/*
666281494Sandrew	 * Find insertion point while checking for overlap.  Start off by
667281494Sandrew	 * assuming the new entry will be added to the end.
668281494Sandrew	 */
669281494Sandrew	insert_idx = _physmap_idx;
670281494Sandrew	for (i = 0; i <= _physmap_idx; i += 2) {
671281494Sandrew		if (base < physmap[i + 1]) {
672281494Sandrew			if (base + length <= physmap[i]) {
673281494Sandrew				insert_idx = i;
674281494Sandrew				break;
675281494Sandrew			}
676281494Sandrew			if (boothowto & RB_VERBOSE)
677281494Sandrew				printf(
678281494Sandrew		    "Overlapping memory regions, ignoring second region\n");
679281494Sandrew			return (1);
680281494Sandrew		}
681281494Sandrew	}
682281494Sandrew
683281494Sandrew	/* See if we can prepend to the next entry. */
684281494Sandrew	if (insert_idx <= _physmap_idx &&
685281494Sandrew	    base + length == physmap[insert_idx]) {
686281494Sandrew		physmap[insert_idx] = base;
687281494Sandrew		return (1);
688281494Sandrew	}
689281494Sandrew
690281494Sandrew	/* See if we can append to the previous entry. */
691281494Sandrew	if (insert_idx > 0 && base == physmap[insert_idx - 1]) {
692281494Sandrew		physmap[insert_idx - 1] += length;
693281494Sandrew		return (1);
694281494Sandrew	}
695281494Sandrew
696281494Sandrew	_physmap_idx += 2;
697281494Sandrew	*physmap_idxp = _physmap_idx;
698281494Sandrew	if (_physmap_idx == PHYSMAP_SIZE) {
699281494Sandrew		printf(
700281494Sandrew		"Too many segments in the physical address map, giving up\n");
701281494Sandrew		return (0);
702281494Sandrew	}
703281494Sandrew
704281494Sandrew	/*
705281494Sandrew	 * Move the last 'N' entries down to make room for the new
706281494Sandrew	 * entry if needed.
707281494Sandrew	 */
708281494Sandrew	for (i = _physmap_idx; i > insert_idx; i -= 2) {
709281494Sandrew		physmap[i] = physmap[i - 2];
710281494Sandrew		physmap[i + 1] = physmap[i - 1];
711281494Sandrew	}
712281494Sandrew
713281494Sandrew	/* Insert the new entry. */
714281494Sandrew	physmap[insert_idx] = base;
715281494Sandrew	physmap[insert_idx + 1] = base + length;
716281494Sandrew	return (1);
717281494Sandrew}
718281494Sandrew
719296266Swma#ifdef FDT
720296266Swmastatic void
721296266Swmaadd_fdt_mem_regions(struct mem_region *mr, int mrcnt, vm_paddr_t *physmap,
722296266Swma    u_int *physmap_idxp)
723296266Swma{
724296266Swma
725296266Swma	for (int i = 0; i < mrcnt; i++) {
726296266Swma		if (!add_physmap_entry(mr[i].mr_start, mr[i].mr_size, physmap,
727296266Swma		    physmap_idxp))
728296266Swma			break;
729296266Swma	}
730296266Swma}
731296266Swma#endif
732296266Swma
733281494Sandrewstatic void
734281494Sandrewadd_efi_map_entries(struct efi_map_header *efihdr, vm_paddr_t *physmap,
735281494Sandrew    u_int *physmap_idxp)
736281494Sandrew{
737281494Sandrew	struct efi_md *map, *p;
738281494Sandrew	const char *type;
739281494Sandrew	size_t efisz;
740281494Sandrew	int ndesc, i;
741281494Sandrew
742281494Sandrew	static const char *types[] = {
743281494Sandrew		"Reserved",
744281494Sandrew		"LoaderCode",
745281494Sandrew		"LoaderData",
746281494Sandrew		"BootServicesCode",
747281494Sandrew		"BootServicesData",
748281494Sandrew		"RuntimeServicesCode",
749281494Sandrew		"RuntimeServicesData",
750281494Sandrew		"ConventionalMemory",
751281494Sandrew		"UnusableMemory",
752281494Sandrew		"ACPIReclaimMemory",
753281494Sandrew		"ACPIMemoryNVS",
754281494Sandrew		"MemoryMappedIO",
755281494Sandrew		"MemoryMappedIOPortSpace",
756317004Smmel		"PalCode",
757317004Smmel		"PersistentMemory"
758281494Sandrew	};
759281494Sandrew
760281494Sandrew	/*
761281494Sandrew	 * Memory map data provided by UEFI via the GetMemoryMap
762281494Sandrew	 * Boot Services API.
763281494Sandrew	 */
764281494Sandrew	efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf;
765281494Sandrew	map = (struct efi_md *)((uint8_t *)efihdr + efisz);
766281494Sandrew
767281494Sandrew	if (efihdr->descriptor_size == 0)
768281494Sandrew		return;
769281494Sandrew	ndesc = efihdr->memory_size / efihdr->descriptor_size;
770281494Sandrew
771281494Sandrew	if (boothowto & RB_VERBOSE)
772281494Sandrew		printf("%23s %12s %12s %8s %4s\n",
773281494Sandrew		    "Type", "Physical", "Virtual", "#Pages", "Attr");
774281494Sandrew
775281494Sandrew	for (i = 0, p = map; i < ndesc; i++,
776281494Sandrew	    p = efi_next_descriptor(p, efihdr->descriptor_size)) {
777281494Sandrew		if (boothowto & RB_VERBOSE) {
778317004Smmel			if (p->md_type < nitems(types))
779281494Sandrew				type = types[p->md_type];
780281494Sandrew			else
781281494Sandrew				type = "<INVALID>";
782281494Sandrew			printf("%23s %012lx %12p %08lx ", type, p->md_phys,
783281494Sandrew			    p->md_virt, p->md_pages);
784281494Sandrew			if (p->md_attr & EFI_MD_ATTR_UC)
785281494Sandrew				printf("UC ");
786281494Sandrew			if (p->md_attr & EFI_MD_ATTR_WC)
787281494Sandrew				printf("WC ");
788281494Sandrew			if (p->md_attr & EFI_MD_ATTR_WT)
789281494Sandrew				printf("WT ");
790281494Sandrew			if (p->md_attr & EFI_MD_ATTR_WB)
791281494Sandrew				printf("WB ");
792281494Sandrew			if (p->md_attr & EFI_MD_ATTR_UCE)
793281494Sandrew				printf("UCE ");
794281494Sandrew			if (p->md_attr & EFI_MD_ATTR_WP)
795281494Sandrew				printf("WP ");
796281494Sandrew			if (p->md_attr & EFI_MD_ATTR_RP)
797281494Sandrew				printf("RP ");
798281494Sandrew			if (p->md_attr & EFI_MD_ATTR_XP)
799281494Sandrew				printf("XP ");
800317004Smmel			if (p->md_attr & EFI_MD_ATTR_NV)
801317004Smmel				printf("NV ");
802317004Smmel			if (p->md_attr & EFI_MD_ATTR_MORE_RELIABLE)
803317004Smmel				printf("MORE_RELIABLE ");
804317004Smmel			if (p->md_attr & EFI_MD_ATTR_RO)
805317004Smmel				printf("RO ");
806281494Sandrew			if (p->md_attr & EFI_MD_ATTR_RT)
807281494Sandrew				printf("RUNTIME");
808281494Sandrew			printf("\n");
809281494Sandrew		}
810281494Sandrew
811281494Sandrew		switch (p->md_type) {
812281494Sandrew		case EFI_MD_TYPE_CODE:
813281494Sandrew		case EFI_MD_TYPE_DATA:
814281494Sandrew		case EFI_MD_TYPE_BS_CODE:
815281494Sandrew		case EFI_MD_TYPE_BS_DATA:
816281494Sandrew		case EFI_MD_TYPE_FREE:
817281494Sandrew			/*
818281494Sandrew			 * We're allowed to use any entry with these types.
819281494Sandrew			 */
820281494Sandrew			break;
821281494Sandrew		default:
822281494Sandrew			continue;
823281494Sandrew		}
824281494Sandrew
825281494Sandrew		if (!add_physmap_entry(p->md_phys, (p->md_pages * PAGE_SIZE),
826281494Sandrew		    physmap, physmap_idxp))
827281494Sandrew			break;
828281494Sandrew	}
829281494Sandrew}
830281494Sandrew
831281494Sandrew#ifdef FDT
832281494Sandrewstatic void
833281494Sandrewtry_load_dtb(caddr_t kmdp)
834281494Sandrew{
835281494Sandrew	vm_offset_t dtbp;
836281494Sandrew
837281494Sandrew	dtbp = MD_FETCH(kmdp, MODINFOMD_DTBP, vm_offset_t);
838281494Sandrew	if (dtbp == (vm_offset_t)NULL) {
839281494Sandrew		printf("ERROR loading DTB\n");
840281494Sandrew		return;
841281494Sandrew	}
842281494Sandrew
843281494Sandrew	if (OF_install(OFW_FDT, 0) == FALSE)
844281494Sandrew		panic("Cannot install FDT");
845281494Sandrew
846281494Sandrew	if (OF_init((void *)dtbp) != 0)
847281494Sandrew		panic("OF_init failed with the found device tree");
848281494Sandrew}
849281494Sandrew#endif
850281494Sandrew
851281494Sandrewstatic void
852281494Sandrewcache_setup(void)
853281494Sandrew{
854297536Swma	int dcache_line_shift, icache_line_shift, dczva_line_shift;
855281494Sandrew	uint32_t ctr_el0;
856297536Swma	uint32_t dczid_el0;
857281494Sandrew
858281494Sandrew	ctr_el0 = READ_SPECIALREG(ctr_el0);
859281494Sandrew
860281494Sandrew	/* Read the log2 words in each D cache line */
861281494Sandrew	dcache_line_shift = CTR_DLINE_SIZE(ctr_el0);
862281494Sandrew	/* Get the D cache line size */
863281494Sandrew	dcache_line_size = sizeof(int) << dcache_line_shift;
864281494Sandrew
865281494Sandrew	/* And the same for the I cache */
866281494Sandrew	icache_line_shift = CTR_ILINE_SIZE(ctr_el0);
867281494Sandrew	icache_line_size = sizeof(int) << icache_line_shift;
868281494Sandrew
869281494Sandrew	idcache_line_size = MIN(dcache_line_size, icache_line_size);
870297536Swma
871297536Swma	dczid_el0 = READ_SPECIALREG(dczid_el0);
872297536Swma
873297536Swma	/* Check if dc zva is not prohibited */
874297536Swma	if (dczid_el0 & DCZID_DZP)
875297536Swma		dczva_line_size = 0;
876297536Swma	else {
877297536Swma		/* Same as with above calculations */
878297536Swma		dczva_line_shift = DCZID_BS_SIZE(dczid_el0);
879297536Swma		dczva_line_size = sizeof(int) << dczva_line_shift;
880297538Swma
881297538Swma		/* Change pagezero function */
882297538Swma		pagezero = pagezero_cache;
883297536Swma	}
884281494Sandrew}
885281494Sandrew
886281494Sandrewvoid
887281494Sandrewinitarm(struct arm64_bootparams *abp)
888281494Sandrew{
889281494Sandrew	struct efi_map_header *efihdr;
890281494Sandrew	struct pcpu *pcpup;
891296266Swma#ifdef FDT
892296266Swma	struct mem_region mem_regions[FDT_MEM_REGIONS];
893296266Swma	int mem_regions_sz;
894296266Swma#endif
895281494Sandrew	vm_offset_t lastaddr;
896281494Sandrew	caddr_t kmdp;
897281494Sandrew	vm_paddr_t mem_len;
898281494Sandrew	int i;
899281494Sandrew
900281494Sandrew	/* Set the module data location */
901281494Sandrew	preload_metadata = (caddr_t)(uintptr_t)(abp->modulep);
902281494Sandrew
903281494Sandrew	/* Find the kernel address */
904281494Sandrew	kmdp = preload_search_by_type("elf kernel");
905281494Sandrew	if (kmdp == NULL)
906281494Sandrew		kmdp = preload_search_by_type("elf64 kernel");
907281494Sandrew
908281494Sandrew	boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
909293045Sian	init_static_kenv(MD_FETCH(kmdp, MODINFOMD_ENVP, char *), 0);
910281494Sandrew
911281494Sandrew#ifdef FDT
912281494Sandrew	try_load_dtb(kmdp);
913281494Sandrew#endif
914281494Sandrew
915281494Sandrew	/* Find the address to start allocating from */
916281494Sandrew	lastaddr = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t);
917281494Sandrew
918281494Sandrew	/* Load the physical memory ranges */
919281494Sandrew	physmap_idx = 0;
920281494Sandrew	efihdr = (struct efi_map_header *)preload_search_info(kmdp,
921281494Sandrew	    MODINFO_METADATA | MODINFOMD_EFI_MAP);
922296266Swma	if (efihdr != NULL)
923296266Swma		add_efi_map_entries(efihdr, physmap, &physmap_idx);
924296266Swma#ifdef FDT
925296266Swma	else {
926296266Swma		/* Grab physical memory regions information from device tree. */
927296266Swma		if (fdt_get_mem_regions(mem_regions, &mem_regions_sz,
928296266Swma		    NULL) != 0)
929296266Swma			panic("Cannot get physical memory regions");
930296266Swma		add_fdt_mem_regions(mem_regions, mem_regions_sz, physmap,
931296266Swma		    &physmap_idx);
932296266Swma	}
933296266Swma#endif
934281494Sandrew
935281494Sandrew	/* Print the memory map */
936281494Sandrew	mem_len = 0;
937286366Sandrew	for (i = 0; i < physmap_idx; i += 2) {
938286366Sandrew		dump_avail[i] = physmap[i];
939286366Sandrew		dump_avail[i + 1] = physmap[i + 1];
940281494Sandrew		mem_len += physmap[i + 1] - physmap[i];
941286366Sandrew	}
942286366Sandrew	dump_avail[i] = 0;
943286366Sandrew	dump_avail[i + 1] = 0;
944281494Sandrew
945281494Sandrew	/* Set the pcpu data, this is needed by pmap_bootstrap */
946281494Sandrew	pcpup = &__pcpu[0];
947281494Sandrew	pcpu_init(pcpup, 0, sizeof(struct pcpu));
948281494Sandrew
949281494Sandrew	/*
950281494Sandrew	 * Set the pcpu pointer with a backup in tpidr_el1 to be
951281494Sandrew	 * loaded when entering the kernel from userland.
952281494Sandrew	 */
953281494Sandrew	__asm __volatile(
954281494Sandrew	    "mov x18, %0 \n"
955281494Sandrew	    "msr tpidr_el1, %0" :: "r"(pcpup));
956281494Sandrew
957281494Sandrew	PCPU_SET(curthread, &thread0);
958281494Sandrew
959281494Sandrew	/* Do basic tuning, hz etc */
960281494Sandrew	init_param1();
961281494Sandrew
962281494Sandrew	cache_setup();
963319202Sandrew	pan_setup();
964281494Sandrew
965281494Sandrew	/* Bootstrap enough of pmap  to enter the kernel proper */
966297446Sandrew	pmap_bootstrap(abp->kern_l0pt, abp->kern_l1pt,
967297446Sandrew	    KERNBASE - abp->kern_delta, lastaddr - KERNBASE);
968281494Sandrew
969298627Sbr	devmap_bootstrap(0, NULL);
970281494Sandrew
971281494Sandrew	cninit();
972281494Sandrew
973281494Sandrew	init_proc0(abp->kern_stack);
974281494Sandrew	msgbufinit(msgbufp, msgbufsize);
975281494Sandrew	mutex_init();
976281494Sandrew	init_param2(physmem);
977281494Sandrew
978322761Sjhb	dbg_init();
979281494Sandrew	kdb_init();
980319202Sandrew	pan_enable();
981281494Sandrew
982281494Sandrew	early_boot = 0;
983281494Sandrew}
984281494Sandrew
985322761Sjhbvoid
986322761Sjhbdbg_init(void)
987322761Sjhb{
988322761Sjhb
989322761Sjhb	/* Clear OS lock */
990322761Sjhb	WRITE_SPECIALREG(OSLAR_EL1, 0);
991322761Sjhb
992322761Sjhb	/* This permits DDB to use debug registers for watchpoints. */
993322761Sjhb	dbg_monitor_init();
994322761Sjhb
995322761Sjhb	/* TODO: Eventually will need to initialize debug registers here. */
996322761Sjhb}
997322761Sjhb
998287487Sandrew#ifdef DDB
999287487Sandrew#include <ddb/ddb.h>
1000287487Sandrew
1001287487SandrewDB_SHOW_COMMAND(specialregs, db_show_spregs)
1002287487Sandrew{
1003287487Sandrew#define	PRINT_REG(reg)	\
1004287487Sandrew    db_printf(__STRING(reg) " = %#016lx\n", READ_SPECIALREG(reg))
1005287487Sandrew
1006287487Sandrew	PRINT_REG(actlr_el1);
1007287487Sandrew	PRINT_REG(afsr0_el1);
1008287487Sandrew	PRINT_REG(afsr1_el1);
1009287487Sandrew	PRINT_REG(aidr_el1);
1010287487Sandrew	PRINT_REG(amair_el1);
1011287487Sandrew	PRINT_REG(ccsidr_el1);
1012287487Sandrew	PRINT_REG(clidr_el1);
1013287487Sandrew	PRINT_REG(contextidr_el1);
1014287487Sandrew	PRINT_REG(cpacr_el1);
1015287487Sandrew	PRINT_REG(csselr_el1);
1016287487Sandrew	PRINT_REG(ctr_el0);
1017287487Sandrew	PRINT_REG(currentel);
1018287487Sandrew	PRINT_REG(daif);
1019287487Sandrew	PRINT_REG(dczid_el0);
1020287487Sandrew	PRINT_REG(elr_el1);
1021287487Sandrew	PRINT_REG(esr_el1);
1022287487Sandrew	PRINT_REG(far_el1);
1023287959Sandrew#if 0
1024287959Sandrew	/* ARM64TODO: Enable VFP before reading floating-point registers */
1025287487Sandrew	PRINT_REG(fpcr);
1026287487Sandrew	PRINT_REG(fpsr);
1027287959Sandrew#endif
1028287487Sandrew	PRINT_REG(id_aa64afr0_el1);
1029287487Sandrew	PRINT_REG(id_aa64afr1_el1);
1030287487Sandrew	PRINT_REG(id_aa64dfr0_el1);
1031287487Sandrew	PRINT_REG(id_aa64dfr1_el1);
1032287487Sandrew	PRINT_REG(id_aa64isar0_el1);
1033287487Sandrew	PRINT_REG(id_aa64isar1_el1);
1034287487Sandrew	PRINT_REG(id_aa64pfr0_el1);
1035287487Sandrew	PRINT_REG(id_aa64pfr1_el1);
1036287487Sandrew	PRINT_REG(id_afr0_el1);
1037287487Sandrew	PRINT_REG(id_dfr0_el1);
1038287487Sandrew	PRINT_REG(id_isar0_el1);
1039287487Sandrew	PRINT_REG(id_isar1_el1);
1040287487Sandrew	PRINT_REG(id_isar2_el1);
1041287487Sandrew	PRINT_REG(id_isar3_el1);
1042287487Sandrew	PRINT_REG(id_isar4_el1);
1043287487Sandrew	PRINT_REG(id_isar5_el1);
1044287487Sandrew	PRINT_REG(id_mmfr0_el1);
1045287487Sandrew	PRINT_REG(id_mmfr1_el1);
1046287487Sandrew	PRINT_REG(id_mmfr2_el1);
1047287487Sandrew	PRINT_REG(id_mmfr3_el1);
1048287487Sandrew#if 0
1049287487Sandrew	/* Missing from llvm */
1050287487Sandrew	PRINT_REG(id_mmfr4_el1);
1051287487Sandrew#endif
1052287487Sandrew	PRINT_REG(id_pfr0_el1);
1053287487Sandrew	PRINT_REG(id_pfr1_el1);
1054287487Sandrew	PRINT_REG(isr_el1);
1055287487Sandrew	PRINT_REG(mair_el1);
1056287487Sandrew	PRINT_REG(midr_el1);
1057287487Sandrew	PRINT_REG(mpidr_el1);
1058287487Sandrew	PRINT_REG(mvfr0_el1);
1059287487Sandrew	PRINT_REG(mvfr1_el1);
1060287487Sandrew	PRINT_REG(mvfr2_el1);
1061287487Sandrew	PRINT_REG(revidr_el1);
1062287487Sandrew	PRINT_REG(sctlr_el1);
1063287487Sandrew	PRINT_REG(sp_el0);
1064287487Sandrew	PRINT_REG(spsel);
1065287487Sandrew	PRINT_REG(spsr_el1);
1066287487Sandrew	PRINT_REG(tcr_el1);
1067287487Sandrew	PRINT_REG(tpidr_el0);
1068287487Sandrew	PRINT_REG(tpidr_el1);
1069287487Sandrew	PRINT_REG(tpidrro_el0);
1070287487Sandrew	PRINT_REG(ttbr0_el1);
1071287487Sandrew	PRINT_REG(ttbr1_el1);
1072287487Sandrew	PRINT_REG(vbar_el1);
1073287487Sandrew#undef PRINT_REG
1074287487Sandrew}
1075287487Sandrew
1076287487SandrewDB_SHOW_COMMAND(vtop, db_show_vtop)
1077287487Sandrew{
1078287487Sandrew	uint64_t phys;
1079287487Sandrew
1080287487Sandrew	if (have_addr) {
1081287487Sandrew		phys = arm64_address_translate_s1e1r(addr);
1082306084Sandrew		db_printf("Physical address reg (read):  0x%016lx\n", phys);
1083306084Sandrew		phys = arm64_address_translate_s1e1w(addr);
1084306084Sandrew		db_printf("Physical address reg (write): 0x%016lx\n", phys);
1085287487Sandrew	} else
1086287487Sandrew		db_printf("show vtop <virt_addr>\n");
1087287487Sandrew}
1088287487Sandrew#endif
1089