machdep.c revision 297446
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: head/sys/arm64/arm64/machdep.c 297446 2016-03-31 11:07:24Z andrew $");
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>
40281494Sandrew#include <sys/efi.h>
41281494Sandrew#include <sys/exec.h>
42281494Sandrew#include <sys/imgact.h>
43281494Sandrew#include <sys/kdb.h>
44281494Sandrew#include <sys/kernel.h>
45281494Sandrew#include <sys/limits.h>
46281494Sandrew#include <sys/linker.h>
47281494Sandrew#include <sys/msgbuf.h>
48281494Sandrew#include <sys/pcpu.h>
49281494Sandrew#include <sys/proc.h>
50281494Sandrew#include <sys/ptrace.h>
51281494Sandrew#include <sys/reboot.h>
52281494Sandrew#include <sys/rwlock.h>
53281494Sandrew#include <sys/sched.h>
54281494Sandrew#include <sys/signalvar.h>
55281494Sandrew#include <sys/syscallsubr.h>
56281494Sandrew#include <sys/sysent.h>
57281494Sandrew#include <sys/sysproto.h>
58281494Sandrew#include <sys/ucontext.h>
59291937Skib#include <sys/vdso.h>
60281494Sandrew
61281494Sandrew#include <vm/vm.h>
62281494Sandrew#include <vm/vm_kern.h>
63281494Sandrew#include <vm/vm_object.h>
64281494Sandrew#include <vm/vm_page.h>
65281494Sandrew#include <vm/pmap.h>
66281494Sandrew#include <vm/vm_map.h>
67281494Sandrew#include <vm/vm_pager.h>
68281494Sandrew
69281494Sandrew#include <machine/armreg.h>
70281494Sandrew#include <machine/cpu.h>
71281494Sandrew#include <machine/debug_monitor.h>
72281494Sandrew#include <machine/kdb.h>
73281494Sandrew#include <machine/devmap.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 */
111281494Sandrew
112281494Sandrewstatic void
113281494Sandrewcpu_startup(void *dummy)
114281494Sandrew{
115281494Sandrew
116281494Sandrew	identify_cpu();
117281494Sandrew
118281494Sandrew	vm_ksubmap_init(&kmi);
119281494Sandrew	bufinit();
120281494Sandrew	vm_pager_bufferinit();
121281494Sandrew}
122281494Sandrew
123281494SandrewSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
124281494Sandrew
125285316Sandrewint
126285316Sandrewcpu_idle_wakeup(int cpu)
127285316Sandrew{
128285316Sandrew
129285316Sandrew	return (0);
130285316Sandrew}
131285316Sandrew
132281494Sandrewvoid
133281494Sandrewbzero(void *buf, size_t len)
134281494Sandrew{
135281494Sandrew	uint8_t *p;
136281494Sandrew
137281494Sandrew	p = buf;
138281494Sandrew	while(len-- > 0)
139281494Sandrew		*p++ = 0;
140281494Sandrew}
141281494Sandrew
142281494Sandrewint
143281494Sandrewfill_regs(struct thread *td, struct reg *regs)
144281494Sandrew{
145281494Sandrew	struct trapframe *frame;
146281494Sandrew
147281494Sandrew	frame = td->td_frame;
148281494Sandrew	regs->sp = frame->tf_sp;
149281494Sandrew	regs->lr = frame->tf_lr;
150281494Sandrew	regs->elr = frame->tf_elr;
151281494Sandrew	regs->spsr = frame->tf_spsr;
152281494Sandrew
153281494Sandrew	memcpy(regs->x, frame->tf_x, sizeof(regs->x));
154281494Sandrew
155281494Sandrew	return (0);
156281494Sandrew}
157281494Sandrew
158281494Sandrewint
159281494Sandrewset_regs(struct thread *td, struct reg *regs)
160281494Sandrew{
161281494Sandrew	struct trapframe *frame;
162281494Sandrew
163281494Sandrew	frame = td->td_frame;
164281494Sandrew	frame->tf_sp = regs->sp;
165281494Sandrew	frame->tf_lr = regs->lr;
166281494Sandrew	frame->tf_elr = regs->elr;
167281494Sandrew	frame->tf_spsr = regs->spsr;
168281494Sandrew
169281494Sandrew	memcpy(frame->tf_x, regs->x, sizeof(frame->tf_x));
170281494Sandrew
171281494Sandrew	return (0);
172281494Sandrew}
173281494Sandrew
174281494Sandrewint
175281494Sandrewfill_fpregs(struct thread *td, struct fpreg *regs)
176281494Sandrew{
177281494Sandrew#ifdef VFP
178281494Sandrew	struct pcb *pcb;
179281494Sandrew
180281494Sandrew	pcb = td->td_pcb;
181281494Sandrew	if ((pcb->pcb_fpflags & PCB_FP_STARTED) != 0) {
182281494Sandrew		/*
183281494Sandrew		 * If we have just been running VFP instructions we will
184281494Sandrew		 * need to save the state to memcpy it below.
185281494Sandrew		 */
186286225Sandrew		vfp_save_state(td, pcb);
187281494Sandrew
188281494Sandrew		memcpy(regs->fp_q, pcb->pcb_vfp, sizeof(regs->fp_q));
189281494Sandrew		regs->fp_cr = pcb->pcb_fpcr;
190281494Sandrew		regs->fp_sr = pcb->pcb_fpsr;
191281494Sandrew	} else
192281494Sandrew#endif
193281494Sandrew		memset(regs->fp_q, 0, sizeof(regs->fp_q));
194281494Sandrew	return (0);
195281494Sandrew}
196281494Sandrew
197281494Sandrewint
198281494Sandrewset_fpregs(struct thread *td, struct fpreg *regs)
199281494Sandrew{
200281494Sandrew#ifdef VFP
201281494Sandrew	struct pcb *pcb;
202281494Sandrew
203281494Sandrew	pcb = td->td_pcb;
204281494Sandrew	memcpy(pcb->pcb_vfp, regs->fp_q, sizeof(regs->fp_q));
205281494Sandrew	pcb->pcb_fpcr = regs->fp_cr;
206281494Sandrew	pcb->pcb_fpsr = regs->fp_sr;
207281494Sandrew#endif
208281494Sandrew	return (0);
209281494Sandrew}
210281494Sandrew
211281494Sandrewint
212281494Sandrewfill_dbregs(struct thread *td, struct dbreg *regs)
213281494Sandrew{
214281494Sandrew
215286073Semaste	panic("ARM64TODO: fill_dbregs");
216281494Sandrew}
217281494Sandrew
218281494Sandrewint
219281494Sandrewset_dbregs(struct thread *td, struct dbreg *regs)
220281494Sandrew{
221281494Sandrew
222286073Semaste	panic("ARM64TODO: set_dbregs");
223281494Sandrew}
224281494Sandrew
225281494Sandrewint
226281494Sandrewptrace_set_pc(struct thread *td, u_long addr)
227281494Sandrew{
228281494Sandrew
229286073Semaste	panic("ARM64TODO: ptrace_set_pc");
230281494Sandrew	return (0);
231281494Sandrew}
232281494Sandrew
233281494Sandrewint
234281494Sandrewptrace_single_step(struct thread *td)
235281494Sandrew{
236281494Sandrew
237295142Sandrew	td->td_frame->tf_spsr |= PSR_SS;
238295142Sandrew	td->td_pcb->pcb_flags |= PCB_SINGLE_STEP;
239281494Sandrew	return (0);
240281494Sandrew}
241281494Sandrew
242281494Sandrewint
243281494Sandrewptrace_clear_single_step(struct thread *td)
244281494Sandrew{
245281494Sandrew
246295142Sandrew	td->td_frame->tf_spsr &= ~PSR_SS;
247295142Sandrew	td->td_pcb->pcb_flags &= ~PCB_SINGLE_STEP;
248281494Sandrew	return (0);
249281494Sandrew}
250281494Sandrew
251281494Sandrewvoid
252281494Sandrewexec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
253281494Sandrew{
254281494Sandrew	struct trapframe *tf = td->td_frame;
255281494Sandrew
256281494Sandrew	memset(tf, 0, sizeof(struct trapframe));
257281494Sandrew
258289502Sandrew	/*
259289502Sandrew	 * We need to set x0 for init as it doesn't call
260289502Sandrew	 * cpu_set_syscall_retval to copy the value. We also
261289502Sandrew	 * need to set td_retval for the cases where we do.
262289502Sandrew	 */
263289502Sandrew	tf->tf_x[0] = td->td_retval[0] = stack;
264289502Sandrew	tf->tf_sp = STACKALIGN(stack);
265281494Sandrew	tf->tf_lr = imgp->entry_addr;
266281494Sandrew	tf->tf_elr = imgp->entry_addr;
267281494Sandrew}
268281494Sandrew
269281494Sandrew/* Sanity check these are the same size, they will be memcpy'd to and fro */
270281494SandrewCTASSERT(sizeof(((struct trapframe *)0)->tf_x) ==
271281494Sandrew    sizeof((struct gpregs *)0)->gp_x);
272281494SandrewCTASSERT(sizeof(((struct trapframe *)0)->tf_x) ==
273281494Sandrew    sizeof((struct reg *)0)->x);
274281494Sandrew
275281494Sandrewint
276281494Sandrewget_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret)
277281494Sandrew{
278281494Sandrew	struct trapframe *tf = td->td_frame;
279281494Sandrew
280285334Sandrew	if (clear_ret & GET_MC_CLEAR_RET) {
281281494Sandrew		mcp->mc_gpregs.gp_x[0] = 0;
282285334Sandrew		mcp->mc_gpregs.gp_spsr = tf->tf_spsr & ~PSR_C;
283285334Sandrew	} else {
284281494Sandrew		mcp->mc_gpregs.gp_x[0] = tf->tf_x[0];
285285334Sandrew		mcp->mc_gpregs.gp_spsr = tf->tf_spsr;
286285334Sandrew	}
287281494Sandrew
288281494Sandrew	memcpy(&mcp->mc_gpregs.gp_x[1], &tf->tf_x[1],
289281494Sandrew	    sizeof(mcp->mc_gpregs.gp_x[1]) * (nitems(mcp->mc_gpregs.gp_x) - 1));
290281494Sandrew
291281494Sandrew	mcp->mc_gpregs.gp_sp = tf->tf_sp;
292281494Sandrew	mcp->mc_gpregs.gp_lr = tf->tf_lr;
293281494Sandrew	mcp->mc_gpregs.gp_elr = tf->tf_elr;
294281494Sandrew
295281494Sandrew	return (0);
296281494Sandrew}
297281494Sandrew
298281494Sandrewint
299281494Sandrewset_mcontext(struct thread *td, mcontext_t *mcp)
300281494Sandrew{
301281494Sandrew	struct trapframe *tf = td->td_frame;
302281494Sandrew
303281494Sandrew	memcpy(tf->tf_x, mcp->mc_gpregs.gp_x, sizeof(tf->tf_x));
304281494Sandrew
305281494Sandrew	tf->tf_sp = mcp->mc_gpregs.gp_sp;
306281494Sandrew	tf->tf_lr = mcp->mc_gpregs.gp_lr;
307281494Sandrew	tf->tf_elr = mcp->mc_gpregs.gp_elr;
308281494Sandrew	tf->tf_spsr = mcp->mc_gpregs.gp_spsr;
309281494Sandrew
310281494Sandrew	return (0);
311281494Sandrew}
312281494Sandrew
313281494Sandrewstatic void
314281494Sandrewget_fpcontext(struct thread *td, mcontext_t *mcp)
315281494Sandrew{
316281494Sandrew#ifdef VFP
317281494Sandrew	struct pcb *curpcb;
318281494Sandrew
319281494Sandrew	critical_enter();
320281494Sandrew
321281494Sandrew	curpcb = curthread->td_pcb;
322281494Sandrew
323281494Sandrew	if ((curpcb->pcb_fpflags & PCB_FP_STARTED) != 0) {
324281494Sandrew		/*
325281494Sandrew		 * If we have just been running VFP instructions we will
326281494Sandrew		 * need to save the state to memcpy it below.
327281494Sandrew		 */
328286225Sandrew		vfp_save_state(td, curpcb);
329281494Sandrew
330281494Sandrew		memcpy(mcp->mc_fpregs.fp_q, curpcb->pcb_vfp,
331281494Sandrew		    sizeof(mcp->mc_fpregs));
332281494Sandrew		mcp->mc_fpregs.fp_cr = curpcb->pcb_fpcr;
333281494Sandrew		mcp->mc_fpregs.fp_sr = curpcb->pcb_fpsr;
334281494Sandrew		mcp->mc_fpregs.fp_flags = curpcb->pcb_fpflags;
335281494Sandrew		mcp->mc_flags |= _MC_FP_VALID;
336281494Sandrew	}
337281494Sandrew
338281494Sandrew	critical_exit();
339281494Sandrew#endif
340281494Sandrew}
341281494Sandrew
342281494Sandrewstatic void
343281494Sandrewset_fpcontext(struct thread *td, mcontext_t *mcp)
344281494Sandrew{
345281494Sandrew#ifdef VFP
346281494Sandrew	struct pcb *curpcb;
347281494Sandrew
348281494Sandrew	critical_enter();
349281494Sandrew
350281494Sandrew	if ((mcp->mc_flags & _MC_FP_VALID) != 0) {
351281494Sandrew		curpcb = curthread->td_pcb;
352281494Sandrew
353281494Sandrew		/*
354281494Sandrew		 * Discard any vfp state for the current thread, we
355281494Sandrew		 * are about to override it.
356281494Sandrew		 */
357281494Sandrew		vfp_discard(td);
358281494Sandrew
359281494Sandrew		memcpy(curpcb->pcb_vfp, mcp->mc_fpregs.fp_q,
360281494Sandrew		    sizeof(mcp->mc_fpregs));
361281494Sandrew		curpcb->pcb_fpcr = mcp->mc_fpregs.fp_cr;
362281494Sandrew		curpcb->pcb_fpsr = mcp->mc_fpregs.fp_sr;
363281494Sandrew		curpcb->pcb_fpflags = mcp->mc_fpregs.fp_flags;
364281494Sandrew	}
365281494Sandrew
366281494Sandrew	critical_exit();
367281494Sandrew#endif
368281494Sandrew}
369281494Sandrew
370281494Sandrewvoid
371281494Sandrewcpu_idle(int busy)
372281494Sandrew{
373281494Sandrew
374281494Sandrew	spinlock_enter();
375281494Sandrew	if (!busy)
376281494Sandrew		cpu_idleclock();
377281494Sandrew	if (!sched_runnable())
378281494Sandrew		__asm __volatile(
379281494Sandrew		    "dsb sy \n"
380281494Sandrew		    "wfi    \n");
381281494Sandrew	if (!busy)
382281494Sandrew		cpu_activeclock();
383281494Sandrew	spinlock_exit();
384281494Sandrew}
385281494Sandrew
386281494Sandrewvoid
387281494Sandrewcpu_halt(void)
388281494Sandrew{
389281494Sandrew
390286134Sandrew	/* We should have shutdown by now, if not enter a low power sleep */
391286134Sandrew	intr_disable();
392286134Sandrew	while (1) {
393286134Sandrew		__asm __volatile("wfi");
394286134Sandrew	}
395281494Sandrew}
396281494Sandrew
397281494Sandrew/*
398281494Sandrew * Flush the D-cache for non-DMA I/O so that the I-cache can
399281494Sandrew * be made coherent later.
400281494Sandrew */
401281494Sandrewvoid
402281494Sandrewcpu_flush_dcache(void *ptr, size_t len)
403281494Sandrew{
404281494Sandrew
405286073Semaste	/* ARM64TODO TBD */
406281494Sandrew}
407281494Sandrew
408281494Sandrew/* Get current clock frequency for the given CPU ID. */
409281494Sandrewint
410281494Sandrewcpu_est_clockrate(int cpu_id, uint64_t *rate)
411281494Sandrew{
412281494Sandrew
413286073Semaste	panic("ARM64TODO: cpu_est_clockrate");
414281494Sandrew}
415281494Sandrew
416281494Sandrewvoid
417281494Sandrewcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
418281494Sandrew{
419284273Sandrew
420284273Sandrew	pcpu->pc_acpi_id = 0xffffffff;
421281494Sandrew}
422281494Sandrew
423281494Sandrewvoid
424281494Sandrewspinlock_enter(void)
425281494Sandrew{
426281494Sandrew	struct thread *td;
427281494Sandrew	register_t daif;
428281494Sandrew
429281494Sandrew	td = curthread;
430281494Sandrew	if (td->td_md.md_spinlock_count == 0) {
431281494Sandrew		daif = intr_disable();
432281494Sandrew		td->td_md.md_spinlock_count = 1;
433281494Sandrew		td->td_md.md_saved_daif = daif;
434281494Sandrew	} else
435281494Sandrew		td->td_md.md_spinlock_count++;
436281494Sandrew	critical_enter();
437281494Sandrew}
438281494Sandrew
439281494Sandrewvoid
440281494Sandrewspinlock_exit(void)
441281494Sandrew{
442281494Sandrew	struct thread *td;
443281494Sandrew	register_t daif;
444281494Sandrew
445281494Sandrew	td = curthread;
446281494Sandrew	critical_exit();
447281494Sandrew	daif = td->td_md.md_saved_daif;
448281494Sandrew	td->td_md.md_spinlock_count--;
449281494Sandrew	if (td->td_md.md_spinlock_count == 0)
450281494Sandrew		intr_restore(daif);
451281494Sandrew}
452281494Sandrew
453281494Sandrew#ifndef	_SYS_SYSPROTO_H_
454281494Sandrewstruct sigreturn_args {
455281494Sandrew	ucontext_t *ucp;
456281494Sandrew};
457281494Sandrew#endif
458281494Sandrew
459281494Sandrewint
460281494Sandrewsys_sigreturn(struct thread *td, struct sigreturn_args *uap)
461281494Sandrew{
462281494Sandrew	ucontext_t uc;
463281494Sandrew	uint32_t spsr;
464281494Sandrew
465281494Sandrew	if (uap == NULL)
466281494Sandrew		return (EFAULT);
467281494Sandrew	if (copyin(uap->sigcntxp, &uc, sizeof(uc)))
468281494Sandrew		return (EFAULT);
469281494Sandrew
470281494Sandrew	spsr = uc.uc_mcontext.mc_gpregs.gp_spsr;
471281494Sandrew	if ((spsr & PSR_M_MASK) != PSR_M_EL0t ||
472281494Sandrew	    (spsr & (PSR_F | PSR_I | PSR_A | PSR_D)) != 0)
473281494Sandrew		return (EINVAL);
474281494Sandrew
475281494Sandrew	set_mcontext(td, &uc.uc_mcontext);
476281494Sandrew	set_fpcontext(td, &uc.uc_mcontext);
477281494Sandrew
478281494Sandrew	/* Restore signal mask. */
479281494Sandrew	kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
480281494Sandrew
481281494Sandrew	return (EJUSTRETURN);
482281494Sandrew}
483281494Sandrew
484281494Sandrew/*
485281494Sandrew * Construct a PCB from a trapframe. This is called from kdb_trap() where
486281494Sandrew * we want to start a backtrace from the function that caused us to enter
487281494Sandrew * the debugger. We have the context in the trapframe, but base the trace
488281494Sandrew * on the PCB. The PCB doesn't have to be perfect, as long as it contains
489281494Sandrew * enough for a backtrace.
490281494Sandrew */
491281494Sandrewvoid
492281494Sandrewmakectx(struct trapframe *tf, struct pcb *pcb)
493281494Sandrew{
494281494Sandrew	int i;
495281494Sandrew
496281494Sandrew	for (i = 0; i < PCB_LR; i++)
497281494Sandrew		pcb->pcb_x[i] = tf->tf_x[i];
498281494Sandrew
499281494Sandrew	pcb->pcb_x[PCB_LR] = tf->tf_lr;
500281494Sandrew	pcb->pcb_pc = tf->tf_elr;
501281494Sandrew	pcb->pcb_sp = tf->tf_sp;
502281494Sandrew}
503281494Sandrew
504281494Sandrewvoid
505281494Sandrewsendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
506281494Sandrew{
507281494Sandrew	struct thread *td;
508281494Sandrew	struct proc *p;
509281494Sandrew	struct trapframe *tf;
510281494Sandrew	struct sigframe *fp, frame;
511281494Sandrew	struct sigacts *psp;
512291937Skib	struct sysentvec *sysent;
513281494Sandrew	int code, onstack, sig;
514281494Sandrew
515281494Sandrew	td = curthread;
516281494Sandrew	p = td->td_proc;
517281494Sandrew	PROC_LOCK_ASSERT(p, MA_OWNED);
518281494Sandrew
519281494Sandrew	sig = ksi->ksi_signo;
520281494Sandrew	code = ksi->ksi_code;
521281494Sandrew	psp = p->p_sigacts;
522281494Sandrew	mtx_assert(&psp->ps_mtx, MA_OWNED);
523281494Sandrew
524281494Sandrew	tf = td->td_frame;
525281494Sandrew	onstack = sigonstack(tf->tf_sp);
526281494Sandrew
527281494Sandrew	CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
528281494Sandrew	    catcher, sig);
529281494Sandrew
530281494Sandrew	/* Allocate and validate space for the signal handler context. */
531281494Sandrew	if ((td->td_pflags & TDP_ALTSTACK) != 0 && !onstack &&
532281494Sandrew	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
533294930Sjhb		fp = (struct sigframe *)((uintptr_t)td->td_sigstk.ss_sp +
534281494Sandrew		    td->td_sigstk.ss_size);
535281494Sandrew#if defined(COMPAT_43)
536281494Sandrew		td->td_sigstk.ss_flags |= SS_ONSTACK;
537281494Sandrew#endif
538281494Sandrew	} else {
539281494Sandrew		fp = (struct sigframe *)td->td_frame->tf_sp;
540281494Sandrew	}
541281494Sandrew
542281494Sandrew	/* Make room, keeping the stack aligned */
543281494Sandrew	fp--;
544281494Sandrew	fp = (struct sigframe *)STACKALIGN(fp);
545281494Sandrew
546281494Sandrew	/* Fill in the frame to copy out */
547281494Sandrew	get_mcontext(td, &frame.sf_uc.uc_mcontext, 0);
548281494Sandrew	get_fpcontext(td, &frame.sf_uc.uc_mcontext);
549281494Sandrew	frame.sf_si = ksi->ksi_info;
550281494Sandrew	frame.sf_uc.uc_sigmask = *mask;
551281494Sandrew	frame.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) ?
552281494Sandrew	    ((onstack) ? SS_ONSTACK : 0) : SS_DISABLE;
553281494Sandrew	frame.sf_uc.uc_stack = td->td_sigstk;
554281494Sandrew	mtx_unlock(&psp->ps_mtx);
555281494Sandrew	PROC_UNLOCK(td->td_proc);
556281494Sandrew
557281494Sandrew	/* Copy the sigframe out to the user's stack. */
558281494Sandrew	if (copyout(&frame, fp, sizeof(*fp)) != 0) {
559281494Sandrew		/* Process has trashed its stack. Kill it. */
560281494Sandrew		CTR2(KTR_SIG, "sendsig: sigexit td=%p fp=%p", td, fp);
561281494Sandrew		PROC_LOCK(p);
562281494Sandrew		sigexit(td, SIGILL);
563281494Sandrew	}
564281494Sandrew
565281494Sandrew	tf->tf_x[0]= sig;
566281494Sandrew	tf->tf_x[1] = (register_t)&fp->sf_si;
567281494Sandrew	tf->tf_x[2] = (register_t)&fp->sf_uc;
568281494Sandrew
569281494Sandrew	tf->tf_elr = (register_t)catcher;
570281494Sandrew	tf->tf_sp = (register_t)fp;
571291937Skib	sysent = p->p_sysent;
572291937Skib	if (sysent->sv_sigcode_base != 0)
573291937Skib		tf->tf_lr = (register_t)sysent->sv_sigcode_base;
574291937Skib	else
575291937Skib		tf->tf_lr = (register_t)(sysent->sv_psstrings -
576291937Skib		    *(sysent->sv_szsigcode));
577281494Sandrew
578281494Sandrew	CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, tf->tf_elr,
579281494Sandrew	    tf->tf_sp);
580281494Sandrew
581281494Sandrew	PROC_LOCK(p);
582281494Sandrew	mtx_lock(&psp->ps_mtx);
583281494Sandrew}
584281494Sandrew
585281494Sandrewstatic void
586281494Sandrewinit_proc0(vm_offset_t kstack)
587281494Sandrew{
588281494Sandrew	struct pcpu *pcpup = &__pcpu[0];
589281494Sandrew
590281494Sandrew	proc_linkup0(&proc0, &thread0);
591281494Sandrew	thread0.td_kstack = kstack;
592281494Sandrew	thread0.td_pcb = (struct pcb *)(thread0.td_kstack) - 1;
593281494Sandrew	thread0.td_pcb->pcb_fpflags = 0;
594281494Sandrew	thread0.td_pcb->pcb_vfpcpu = UINT_MAX;
595281494Sandrew	thread0.td_frame = &proc0_tf;
596281494Sandrew	pcpup->pc_curpcb = thread0.td_pcb;
597281494Sandrew}
598281494Sandrew
599281494Sandrewtypedef struct {
600281494Sandrew	uint32_t type;
601281494Sandrew	uint64_t phys_start;
602281494Sandrew	uint64_t virt_start;
603281494Sandrew	uint64_t num_pages;
604281494Sandrew	uint64_t attr;
605281494Sandrew} EFI_MEMORY_DESCRIPTOR;
606281494Sandrew
607281494Sandrewstatic int
608281494Sandrewadd_physmap_entry(uint64_t base, uint64_t length, vm_paddr_t *physmap,
609281494Sandrew    u_int *physmap_idxp)
610281494Sandrew{
611281494Sandrew	u_int i, insert_idx, _physmap_idx;
612281494Sandrew
613281494Sandrew	_physmap_idx = *physmap_idxp;
614281494Sandrew
615281494Sandrew	if (length == 0)
616281494Sandrew		return (1);
617281494Sandrew
618281494Sandrew	/*
619281494Sandrew	 * Find insertion point while checking for overlap.  Start off by
620281494Sandrew	 * assuming the new entry will be added to the end.
621281494Sandrew	 */
622281494Sandrew	insert_idx = _physmap_idx;
623281494Sandrew	for (i = 0; i <= _physmap_idx; i += 2) {
624281494Sandrew		if (base < physmap[i + 1]) {
625281494Sandrew			if (base + length <= physmap[i]) {
626281494Sandrew				insert_idx = i;
627281494Sandrew				break;
628281494Sandrew			}
629281494Sandrew			if (boothowto & RB_VERBOSE)
630281494Sandrew				printf(
631281494Sandrew		    "Overlapping memory regions, ignoring second region\n");
632281494Sandrew			return (1);
633281494Sandrew		}
634281494Sandrew	}
635281494Sandrew
636281494Sandrew	/* See if we can prepend to the next entry. */
637281494Sandrew	if (insert_idx <= _physmap_idx &&
638281494Sandrew	    base + length == physmap[insert_idx]) {
639281494Sandrew		physmap[insert_idx] = base;
640281494Sandrew		return (1);
641281494Sandrew	}
642281494Sandrew
643281494Sandrew	/* See if we can append to the previous entry. */
644281494Sandrew	if (insert_idx > 0 && base == physmap[insert_idx - 1]) {
645281494Sandrew		physmap[insert_idx - 1] += length;
646281494Sandrew		return (1);
647281494Sandrew	}
648281494Sandrew
649281494Sandrew	_physmap_idx += 2;
650281494Sandrew	*physmap_idxp = _physmap_idx;
651281494Sandrew	if (_physmap_idx == PHYSMAP_SIZE) {
652281494Sandrew		printf(
653281494Sandrew		"Too many segments in the physical address map, giving up\n");
654281494Sandrew		return (0);
655281494Sandrew	}
656281494Sandrew
657281494Sandrew	/*
658281494Sandrew	 * Move the last 'N' entries down to make room for the new
659281494Sandrew	 * entry if needed.
660281494Sandrew	 */
661281494Sandrew	for (i = _physmap_idx; i > insert_idx; i -= 2) {
662281494Sandrew		physmap[i] = physmap[i - 2];
663281494Sandrew		physmap[i + 1] = physmap[i - 1];
664281494Sandrew	}
665281494Sandrew
666281494Sandrew	/* Insert the new entry. */
667281494Sandrew	physmap[insert_idx] = base;
668281494Sandrew	physmap[insert_idx + 1] = base + length;
669281494Sandrew	return (1);
670281494Sandrew}
671281494Sandrew
672296266Swma#ifdef FDT
673296266Swmastatic void
674296266Swmaadd_fdt_mem_regions(struct mem_region *mr, int mrcnt, vm_paddr_t *physmap,
675296266Swma    u_int *physmap_idxp)
676296266Swma{
677296266Swma
678296266Swma	for (int i = 0; i < mrcnt; i++) {
679296266Swma		if (!add_physmap_entry(mr[i].mr_start, mr[i].mr_size, physmap,
680296266Swma		    physmap_idxp))
681296266Swma			break;
682296266Swma	}
683296266Swma}
684296266Swma#endif
685296266Swma
686281494Sandrew#define efi_next_descriptor(ptr, size) \
687281494Sandrew	((struct efi_md *)(((uint8_t *) ptr) + size))
688281494Sandrew
689281494Sandrewstatic void
690281494Sandrewadd_efi_map_entries(struct efi_map_header *efihdr, vm_paddr_t *physmap,
691281494Sandrew    u_int *physmap_idxp)
692281494Sandrew{
693281494Sandrew	struct efi_md *map, *p;
694281494Sandrew	const char *type;
695281494Sandrew	size_t efisz;
696281494Sandrew	int ndesc, i;
697281494Sandrew
698281494Sandrew	static const char *types[] = {
699281494Sandrew		"Reserved",
700281494Sandrew		"LoaderCode",
701281494Sandrew		"LoaderData",
702281494Sandrew		"BootServicesCode",
703281494Sandrew		"BootServicesData",
704281494Sandrew		"RuntimeServicesCode",
705281494Sandrew		"RuntimeServicesData",
706281494Sandrew		"ConventionalMemory",
707281494Sandrew		"UnusableMemory",
708281494Sandrew		"ACPIReclaimMemory",
709281494Sandrew		"ACPIMemoryNVS",
710281494Sandrew		"MemoryMappedIO",
711281494Sandrew		"MemoryMappedIOPortSpace",
712281494Sandrew		"PalCode"
713281494Sandrew	};
714281494Sandrew
715281494Sandrew	/*
716281494Sandrew	 * Memory map data provided by UEFI via the GetMemoryMap
717281494Sandrew	 * Boot Services API.
718281494Sandrew	 */
719281494Sandrew	efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf;
720281494Sandrew	map = (struct efi_md *)((uint8_t *)efihdr + efisz);
721281494Sandrew
722281494Sandrew	if (efihdr->descriptor_size == 0)
723281494Sandrew		return;
724281494Sandrew	ndesc = efihdr->memory_size / efihdr->descriptor_size;
725281494Sandrew
726281494Sandrew	if (boothowto & RB_VERBOSE)
727281494Sandrew		printf("%23s %12s %12s %8s %4s\n",
728281494Sandrew		    "Type", "Physical", "Virtual", "#Pages", "Attr");
729281494Sandrew
730281494Sandrew	for (i = 0, p = map; i < ndesc; i++,
731281494Sandrew	    p = efi_next_descriptor(p, efihdr->descriptor_size)) {
732281494Sandrew		if (boothowto & RB_VERBOSE) {
733281494Sandrew			if (p->md_type <= EFI_MD_TYPE_PALCODE)
734281494Sandrew				type = types[p->md_type];
735281494Sandrew			else
736281494Sandrew				type = "<INVALID>";
737281494Sandrew			printf("%23s %012lx %12p %08lx ", type, p->md_phys,
738281494Sandrew			    p->md_virt, p->md_pages);
739281494Sandrew			if (p->md_attr & EFI_MD_ATTR_UC)
740281494Sandrew				printf("UC ");
741281494Sandrew			if (p->md_attr & EFI_MD_ATTR_WC)
742281494Sandrew				printf("WC ");
743281494Sandrew			if (p->md_attr & EFI_MD_ATTR_WT)
744281494Sandrew				printf("WT ");
745281494Sandrew			if (p->md_attr & EFI_MD_ATTR_WB)
746281494Sandrew				printf("WB ");
747281494Sandrew			if (p->md_attr & EFI_MD_ATTR_UCE)
748281494Sandrew				printf("UCE ");
749281494Sandrew			if (p->md_attr & EFI_MD_ATTR_WP)
750281494Sandrew				printf("WP ");
751281494Sandrew			if (p->md_attr & EFI_MD_ATTR_RP)
752281494Sandrew				printf("RP ");
753281494Sandrew			if (p->md_attr & EFI_MD_ATTR_XP)
754281494Sandrew				printf("XP ");
755281494Sandrew			if (p->md_attr & EFI_MD_ATTR_RT)
756281494Sandrew				printf("RUNTIME");
757281494Sandrew			printf("\n");
758281494Sandrew		}
759281494Sandrew
760281494Sandrew		switch (p->md_type) {
761281494Sandrew		case EFI_MD_TYPE_CODE:
762281494Sandrew		case EFI_MD_TYPE_DATA:
763281494Sandrew		case EFI_MD_TYPE_BS_CODE:
764281494Sandrew		case EFI_MD_TYPE_BS_DATA:
765281494Sandrew		case EFI_MD_TYPE_FREE:
766281494Sandrew			/*
767281494Sandrew			 * We're allowed to use any entry with these types.
768281494Sandrew			 */
769281494Sandrew			break;
770281494Sandrew		default:
771281494Sandrew			continue;
772281494Sandrew		}
773281494Sandrew
774281494Sandrew		if (!add_physmap_entry(p->md_phys, (p->md_pages * PAGE_SIZE),
775281494Sandrew		    physmap, physmap_idxp))
776281494Sandrew			break;
777281494Sandrew	}
778281494Sandrew}
779281494Sandrew
780281494Sandrew#ifdef FDT
781281494Sandrewstatic void
782281494Sandrewtry_load_dtb(caddr_t kmdp)
783281494Sandrew{
784281494Sandrew	vm_offset_t dtbp;
785281494Sandrew
786281494Sandrew	dtbp = MD_FETCH(kmdp, MODINFOMD_DTBP, vm_offset_t);
787281494Sandrew	if (dtbp == (vm_offset_t)NULL) {
788281494Sandrew		printf("ERROR loading DTB\n");
789281494Sandrew		return;
790281494Sandrew	}
791281494Sandrew
792281494Sandrew	if (OF_install(OFW_FDT, 0) == FALSE)
793281494Sandrew		panic("Cannot install FDT");
794281494Sandrew
795281494Sandrew	if (OF_init((void *)dtbp) != 0)
796281494Sandrew		panic("OF_init failed with the found device tree");
797281494Sandrew}
798281494Sandrew#endif
799281494Sandrew
800281494Sandrewstatic void
801281494Sandrewcache_setup(void)
802281494Sandrew{
803281494Sandrew	int dcache_line_shift, icache_line_shift;
804281494Sandrew	uint32_t ctr_el0;
805281494Sandrew
806281494Sandrew	ctr_el0 = READ_SPECIALREG(ctr_el0);
807281494Sandrew
808281494Sandrew	/* Read the log2 words in each D cache line */
809281494Sandrew	dcache_line_shift = CTR_DLINE_SIZE(ctr_el0);
810281494Sandrew	/* Get the D cache line size */
811281494Sandrew	dcache_line_size = sizeof(int) << dcache_line_shift;
812281494Sandrew
813281494Sandrew	/* And the same for the I cache */
814281494Sandrew	icache_line_shift = CTR_ILINE_SIZE(ctr_el0);
815281494Sandrew	icache_line_size = sizeof(int) << icache_line_shift;
816281494Sandrew
817281494Sandrew	idcache_line_size = MIN(dcache_line_size, icache_line_size);
818281494Sandrew}
819281494Sandrew
820281494Sandrewvoid
821281494Sandrewinitarm(struct arm64_bootparams *abp)
822281494Sandrew{
823281494Sandrew	struct efi_map_header *efihdr;
824281494Sandrew	struct pcpu *pcpup;
825296266Swma#ifdef FDT
826296266Swma	struct mem_region mem_regions[FDT_MEM_REGIONS];
827296266Swma	int mem_regions_sz;
828296266Swma#endif
829281494Sandrew	vm_offset_t lastaddr;
830281494Sandrew	caddr_t kmdp;
831281494Sandrew	vm_paddr_t mem_len;
832281494Sandrew	int i;
833281494Sandrew
834281494Sandrew	/* Set the module data location */
835281494Sandrew	preload_metadata = (caddr_t)(uintptr_t)(abp->modulep);
836281494Sandrew
837281494Sandrew	/* Find the kernel address */
838281494Sandrew	kmdp = preload_search_by_type("elf kernel");
839281494Sandrew	if (kmdp == NULL)
840281494Sandrew		kmdp = preload_search_by_type("elf64 kernel");
841281494Sandrew
842281494Sandrew	boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
843293045Sian	init_static_kenv(MD_FETCH(kmdp, MODINFOMD_ENVP, char *), 0);
844281494Sandrew
845281494Sandrew#ifdef FDT
846281494Sandrew	try_load_dtb(kmdp);
847281494Sandrew#endif
848281494Sandrew
849281494Sandrew	/* Find the address to start allocating from */
850281494Sandrew	lastaddr = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t);
851281494Sandrew
852281494Sandrew	/* Load the physical memory ranges */
853281494Sandrew	physmap_idx = 0;
854281494Sandrew	efihdr = (struct efi_map_header *)preload_search_info(kmdp,
855281494Sandrew	    MODINFO_METADATA | MODINFOMD_EFI_MAP);
856296266Swma	if (efihdr != NULL)
857296266Swma		add_efi_map_entries(efihdr, physmap, &physmap_idx);
858296266Swma#ifdef FDT
859296266Swma	else {
860296266Swma		/* Grab physical memory regions information from device tree. */
861296266Swma		if (fdt_get_mem_regions(mem_regions, &mem_regions_sz,
862296266Swma		    NULL) != 0)
863296266Swma			panic("Cannot get physical memory regions");
864296266Swma		add_fdt_mem_regions(mem_regions, mem_regions_sz, physmap,
865296266Swma		    &physmap_idx);
866296266Swma	}
867296266Swma#endif
868281494Sandrew
869281494Sandrew	/* Print the memory map */
870281494Sandrew	mem_len = 0;
871286366Sandrew	for (i = 0; i < physmap_idx; i += 2) {
872286366Sandrew		dump_avail[i] = physmap[i];
873286366Sandrew		dump_avail[i + 1] = physmap[i + 1];
874281494Sandrew		mem_len += physmap[i + 1] - physmap[i];
875286366Sandrew	}
876286366Sandrew	dump_avail[i] = 0;
877286366Sandrew	dump_avail[i + 1] = 0;
878281494Sandrew
879281494Sandrew	/* Set the pcpu data, this is needed by pmap_bootstrap */
880281494Sandrew	pcpup = &__pcpu[0];
881281494Sandrew	pcpu_init(pcpup, 0, sizeof(struct pcpu));
882281494Sandrew
883281494Sandrew	/*
884281494Sandrew	 * Set the pcpu pointer with a backup in tpidr_el1 to be
885281494Sandrew	 * loaded when entering the kernel from userland.
886281494Sandrew	 */
887281494Sandrew	__asm __volatile(
888281494Sandrew	    "mov x18, %0 \n"
889281494Sandrew	    "msr tpidr_el1, %0" :: "r"(pcpup));
890281494Sandrew
891281494Sandrew	PCPU_SET(curthread, &thread0);
892281494Sandrew
893281494Sandrew	/* Do basic tuning, hz etc */
894281494Sandrew	init_param1();
895281494Sandrew
896281494Sandrew	cache_setup();
897281494Sandrew
898281494Sandrew	/* Bootstrap enough of pmap  to enter the kernel proper */
899297446Sandrew	pmap_bootstrap(abp->kern_l0pt, abp->kern_l1pt,
900297446Sandrew	    KERNBASE - abp->kern_delta, lastaddr - KERNBASE);
901281494Sandrew
902281494Sandrew	arm_devmap_bootstrap(0, NULL);
903281494Sandrew
904281494Sandrew	cninit();
905281494Sandrew
906281494Sandrew	init_proc0(abp->kern_stack);
907281494Sandrew	msgbufinit(msgbufp, msgbufsize);
908281494Sandrew	mutex_init();
909281494Sandrew	init_param2(physmem);
910281494Sandrew
911281494Sandrew	dbg_monitor_init();
912281494Sandrew	kdb_init();
913281494Sandrew
914281494Sandrew	early_boot = 0;
915281494Sandrew}
916281494Sandrew
917291937Skibuint32_t (*arm_cpu_fill_vdso_timehands)(struct vdso_timehands *,
918291937Skib    struct timecounter *);
919291937Skib
920291937Skibuint32_t
921291937Skibcpu_fill_vdso_timehands(struct vdso_timehands *vdso_th, struct timecounter *tc)
922291937Skib{
923291937Skib
924291937Skib	return (arm_cpu_fill_vdso_timehands != NULL ?
925291937Skib	    arm_cpu_fill_vdso_timehands(vdso_th, tc) : 0);
926291937Skib}
927291937Skib
928287487Sandrew#ifdef DDB
929287487Sandrew#include <ddb/ddb.h>
930287487Sandrew
931287487SandrewDB_SHOW_COMMAND(specialregs, db_show_spregs)
932287487Sandrew{
933287487Sandrew#define	PRINT_REG(reg)	\
934287487Sandrew    db_printf(__STRING(reg) " = %#016lx\n", READ_SPECIALREG(reg))
935287487Sandrew
936287487Sandrew	PRINT_REG(actlr_el1);
937287487Sandrew	PRINT_REG(afsr0_el1);
938287487Sandrew	PRINT_REG(afsr1_el1);
939287487Sandrew	PRINT_REG(aidr_el1);
940287487Sandrew	PRINT_REG(amair_el1);
941287487Sandrew	PRINT_REG(ccsidr_el1);
942287487Sandrew	PRINT_REG(clidr_el1);
943287487Sandrew	PRINT_REG(contextidr_el1);
944287487Sandrew	PRINT_REG(cpacr_el1);
945287487Sandrew	PRINT_REG(csselr_el1);
946287487Sandrew	PRINT_REG(ctr_el0);
947287487Sandrew	PRINT_REG(currentel);
948287487Sandrew	PRINT_REG(daif);
949287487Sandrew	PRINT_REG(dczid_el0);
950287487Sandrew	PRINT_REG(elr_el1);
951287487Sandrew	PRINT_REG(esr_el1);
952287487Sandrew	PRINT_REG(far_el1);
953287959Sandrew#if 0
954287959Sandrew	/* ARM64TODO: Enable VFP before reading floating-point registers */
955287487Sandrew	PRINT_REG(fpcr);
956287487Sandrew	PRINT_REG(fpsr);
957287959Sandrew#endif
958287487Sandrew	PRINT_REG(id_aa64afr0_el1);
959287487Sandrew	PRINT_REG(id_aa64afr1_el1);
960287487Sandrew	PRINT_REG(id_aa64dfr0_el1);
961287487Sandrew	PRINT_REG(id_aa64dfr1_el1);
962287487Sandrew	PRINT_REG(id_aa64isar0_el1);
963287487Sandrew	PRINT_REG(id_aa64isar1_el1);
964287487Sandrew	PRINT_REG(id_aa64pfr0_el1);
965287487Sandrew	PRINT_REG(id_aa64pfr1_el1);
966287487Sandrew	PRINT_REG(id_afr0_el1);
967287487Sandrew	PRINT_REG(id_dfr0_el1);
968287487Sandrew	PRINT_REG(id_isar0_el1);
969287487Sandrew	PRINT_REG(id_isar1_el1);
970287487Sandrew	PRINT_REG(id_isar2_el1);
971287487Sandrew	PRINT_REG(id_isar3_el1);
972287487Sandrew	PRINT_REG(id_isar4_el1);
973287487Sandrew	PRINT_REG(id_isar5_el1);
974287487Sandrew	PRINT_REG(id_mmfr0_el1);
975287487Sandrew	PRINT_REG(id_mmfr1_el1);
976287487Sandrew	PRINT_REG(id_mmfr2_el1);
977287487Sandrew	PRINT_REG(id_mmfr3_el1);
978287487Sandrew#if 0
979287487Sandrew	/* Missing from llvm */
980287487Sandrew	PRINT_REG(id_mmfr4_el1);
981287487Sandrew#endif
982287487Sandrew	PRINT_REG(id_pfr0_el1);
983287487Sandrew	PRINT_REG(id_pfr1_el1);
984287487Sandrew	PRINT_REG(isr_el1);
985287487Sandrew	PRINT_REG(mair_el1);
986287487Sandrew	PRINT_REG(midr_el1);
987287487Sandrew	PRINT_REG(mpidr_el1);
988287487Sandrew	PRINT_REG(mvfr0_el1);
989287487Sandrew	PRINT_REG(mvfr1_el1);
990287487Sandrew	PRINT_REG(mvfr2_el1);
991287487Sandrew	PRINT_REG(revidr_el1);
992287487Sandrew	PRINT_REG(sctlr_el1);
993287487Sandrew	PRINT_REG(sp_el0);
994287487Sandrew	PRINT_REG(spsel);
995287487Sandrew	PRINT_REG(spsr_el1);
996287487Sandrew	PRINT_REG(tcr_el1);
997287487Sandrew	PRINT_REG(tpidr_el0);
998287487Sandrew	PRINT_REG(tpidr_el1);
999287487Sandrew	PRINT_REG(tpidrro_el0);
1000287487Sandrew	PRINT_REG(ttbr0_el1);
1001287487Sandrew	PRINT_REG(ttbr1_el1);
1002287487Sandrew	PRINT_REG(vbar_el1);
1003287487Sandrew#undef PRINT_REG
1004287487Sandrew}
1005287487Sandrew
1006287487SandrewDB_SHOW_COMMAND(vtop, db_show_vtop)
1007287487Sandrew{
1008287487Sandrew	uint64_t phys;
1009287487Sandrew
1010287487Sandrew	if (have_addr) {
1011287487Sandrew		phys = arm64_address_translate_s1e1r(addr);
1012287487Sandrew		db_printf("Physical address reg: 0x%016lx\n", phys);
1013287487Sandrew	} else
1014287487Sandrew		db_printf("show vtop <virt_addr>\n");
1015287487Sandrew}
1016287487Sandrew#endif
1017