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