machdep_kdb.c revision 141378
1129198Scognet/* $NetBSD: arm32_machdep.c,v 1.44 2004/03/24 15:34:47 atatat Exp $ */ 2129198Scognet 3139735Simp/*- 4129198Scognet * Copyright (c) 2004 Olivier Houchard 5129198Scognet * Copyright (c) 1994-1998 Mark Brinicombe. 6129198Scognet * Copyright (c) 1994 Brini. 7129198Scognet * All rights reserved. 8129198Scognet * 9129198Scognet * This code is derived from software written for Brini by Mark Brinicombe 10129198Scognet * 11129198Scognet * Redistribution and use in source and binary forms, with or without 12129198Scognet * modification, are permitted provided that the following conditions 13129198Scognet * are met: 14129198Scognet * 1. Redistributions of source code must retain the above copyright 15129198Scognet * notice, this list of conditions and the following disclaimer. 16129198Scognet * 2. Redistributions in binary form must reproduce the above copyright 17129198Scognet * notice, this list of conditions and the following disclaimer in the 18129198Scognet * documentation and/or other materials provided with the distribution. 19129198Scognet * 3. All advertising materials mentioning features or use of this software 20129198Scognet * must display the following acknowledgement: 21129198Scognet * This product includes software developed by Mark Brinicombe 22129198Scognet * for the NetBSD Project. 23129198Scognet * 4. The name of the company nor the name of the author may be used to 24129198Scognet * endorse or promote products derived from this software without specific 25129198Scognet * prior written permission. 26129198Scognet * 27129198Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 28129198Scognet * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 29129198Scognet * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 30129198Scognet * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 31129198Scognet * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 32129198Scognet * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 33129198Scognet * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34129198Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35129198Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36129198Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37129198Scognet * SUCH DAMAGE. 38129198Scognet * 39129198Scognet * Machine dependant functions for kernel setup 40129198Scognet * 41129198Scognet * Created : 17/09/94 42129198Scognet * Updated : 18/04/01 updated for new wscons 43129198Scognet */ 44129198Scognet 45129198Scognet#include "opt_compat.h" 46129198Scognet#include <sys/cdefs.h> 47129198Scognet__FBSDID("$FreeBSD: head/sys/arm/arm/machdep.c 141378 2005-02-06 01:55:08Z njl $"); 48129198Scognet 49129198Scognet#include <sys/param.h> 50141378Snjl#include <sys/proc.h> 51129198Scognet#include <sys/systm.h> 52141249Snjl#include <sys/bio.h> 53141249Snjl#include <sys/buf.h> 54141249Snjl#include <sys/bus.h> 55141378Snjl#include <sys/cons.h> 56141237Snjl#include <sys/cpu.h> 57141378Snjl#include <sys/exec.h> 58129198Scognet#include <sys/imgact.h> 59129198Scognet#include <sys/kernel.h> 60129198Scognet#include <sys/linker.h> 61129198Scognet#include <sys/lock.h> 62129198Scognet#include <sys/malloc.h> 63129198Scognet#include <sys/mutex.h> 64129198Scognet#include <sys/pcpu.h> 65129198Scognet#include <sys/ptrace.h> 66141378Snjl#include <sys/signalvar.h> 67135653Scognet#include <sys/sysent.h> 68141378Snjl#include <sys/sysproto.h> 69140001Scognet#include <sys/uio.h> 70129198Scognet 71129198Scognet#include <vm/pmap.h> 72129198Scognet#include <vm/vm.h> 73141378Snjl#include <vm/vm_map.h> 74129198Scognet#include <vm/vm_object.h> 75129198Scognet#include <vm/vm_page.h> 76129198Scognet#include <vm/vm_pager.h> 77129198Scognet#include <vm/vnode_pager.h> 78141378Snjl 79141378Snjl#include <machine/armreg.h> 80141378Snjl#include <machine/cpu.h> 81141378Snjl#include <machine/machdep.h> 82141378Snjl#include <machine/md_var.h> 83141378Snjl#include <machine/metadata.h> 84141378Snjl#include <machine/pcb.h> 85129198Scognet#include <machine/pmap.h> 86141378Snjl#include <machine/reg.h> 87141378Snjl#include <machine/trap.h> 88141378Snjl#include <machine/undefined.h> 89129198Scognet#include <machine/vmparam.h> 90129198Scognet 91129198Scognet#define MDROOT_ADDR 0xd0400000 92129198Scognet 93129198Scognetuint32_t cpu_reset_address = 0; 94129198Scognetint cold = 1; 95129198Scognetvm_offset_t vector_page; 96129198Scognet 97129198Scognetvoid 98129198Scognetsendsig(catcher, sig, mask, code) 99129198Scognet sig_t catcher; 100129198Scognet int sig; 101129198Scognet sigset_t *mask; 102129198Scognet u_long code; 103129198Scognet{ 104129198Scognet struct thread *td = curthread; 105135653Scognet struct proc *p = td->td_proc; 106129198Scognet struct trapframe *tf = td->td_frame; 107129198Scognet struct sigframe *fp, frame; 108129198Scognet struct sigacts *psp = td->td_proc->p_sigacts; 109129198Scognet int onstack; 110129198Scognet 111137215Scognet onstack = sigonstack(td->td_frame->tf_usr_sp); 112137215Scognet 113137215Scognet if ((td->td_flags & TDP_ALTSTACK) && 114137215Scognet !(onstack) && 115137215Scognet SIGISMEMBER(td->td_proc->p_sigacts->ps_sigonstack, sig)) { 116137215Scognet fp = (void*)(td->td_sigstk.ss_sp + td->td_sigstk.ss_size); 117137215Scognet td->td_sigstk.ss_flags |= SS_ONSTACK; 118137215Scognet } else 119137215Scognet fp = (void*)td->td_frame->tf_usr_sp; 120137215Scognet 121129198Scognet /* make room on the stack */ 122129198Scognet fp--; 123129198Scognet 124129198Scognet /* make the stack aligned */ 125135653Scognet fp = (struct sigframe *)STACKALIGN(fp); 126129198Scognet /* Populate the siginfo frame. */ 127129198Scognet frame.sf_si.si_signo = sig; 128129198Scognet frame.sf_si.si_code = code; 129129198Scognet frame.sf_uc.uc_sigmask = *mask; 130129198Scognet frame.sf_uc.uc_link = NULL; 131137215Scognet frame.sf_uc.uc_flags = (td->td_pflags & TDP_ALTSTACK ) 132137215Scognet ? ((onstack) ? SS_ONSTACK : 0) : SS_DISABLE; 133135653Scognet frame.sf_uc.uc_stack = td->td_sigstk; 134129198Scognet memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack)); 135137215Scognet get_mcontext(td, &frame.sf_uc.uc_mcontext, 0); 136129198Scognet PROC_UNLOCK(td->td_proc); 137129198Scognet mtx_unlock(&psp->ps_mtx); 138129198Scognet if (copyout(&frame, (void*)fp, sizeof(frame)) != 0) 139129198Scognet sigexit(td, SIGILL); 140129198Scognet /* 141129198Scognet * Build context to run handler in. We invoke the handler 142129198Scognet * directly, only returning via the trampoline. Note the 143129198Scognet * trampoline version numbers are coordinated with machine- 144129198Scognet * dependent code in libc. 145129198Scognet */ 146129198Scognet 147129198Scognet tf->tf_r0 = sig; 148129198Scognet tf->tf_r1 = (int)&fp->sf_si; 149129198Scognet tf->tf_r2 = (int)&fp->sf_uc; 150129198Scognet 151129198Scognet /* the trampoline uses r5 as the uc address */ 152129198Scognet tf->tf_r5 = (int)&fp->sf_uc; 153129198Scognet tf->tf_pc = (int)catcher; 154129198Scognet tf->tf_usr_sp = (int)fp; 155135653Scognet tf->tf_usr_lr = (int)(PS_STRINGS - *(p->p_sysent->sv_szsigcode)); 156129198Scognet PROC_LOCK(td->td_proc); 157129198Scognet mtx_lock(&psp->ps_mtx); 158129198Scognet} 159129198Scognet 160129198Scognetstruct kva_md_info kmi; 161129198Scognet 162129198Scognet/* 163129198Scognet * arm32_vector_init: 164129198Scognet * 165129198Scognet * Initialize the vector page, and select whether or not to 166129198Scognet * relocate the vectors. 167129198Scognet * 168129198Scognet * NOTE: We expect the vector page to be mapped at its expected 169129198Scognet * destination. 170129198Scognet */ 171129198Scognet 172129198Scognetextern unsigned int page0[], page0_data[]; 173129198Scognetvoid 174129198Scognetarm_vector_init(vm_offset_t va, int which) 175129198Scognet{ 176129198Scognet unsigned int *vectors = (int *) va; 177129198Scognet unsigned int *vectors_data = vectors + (page0_data - page0); 178129198Scognet int vec; 179129198Scognet 180129198Scognet /* 181129198Scognet * Loop through the vectors we're taking over, and copy the 182129198Scognet * vector's insn and data word. 183129198Scognet */ 184129198Scognet for (vec = 0; vec < ARM_NVEC; vec++) { 185129198Scognet if ((which & (1 << vec)) == 0) { 186129198Scognet /* Don't want to take over this vector. */ 187129198Scognet continue; 188129198Scognet } 189129198Scognet vectors[vec] = page0[vec]; 190129198Scognet vectors_data[vec] = page0_data[vec]; 191129198Scognet } 192129198Scognet 193129198Scognet /* Now sync the vectors. */ 194129198Scognet cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int)); 195129198Scognet 196129198Scognet vector_page = va; 197129198Scognet 198129198Scognet if (va == ARM_VECTORS_HIGH) { 199129198Scognet /* 200129198Scognet * Assume the MD caller knows what it's doing here, and 201129198Scognet * really does want the vector page relocated. 202129198Scognet * 203129198Scognet * Note: This has to be done here (and not just in 204129198Scognet * cpu_setup()) because the vector page needs to be 205129198Scognet * accessible *before* cpu_startup() is called. 206129198Scognet * Think ddb(9) ... 207129198Scognet * 208129198Scognet * NOTE: If the CPU control register is not readable, 209129198Scognet * this will totally fail! We'll just assume that 210129198Scognet * any system that has high vector support has a 211129198Scognet * readable CPU control register, for now. If we 212129198Scognet * ever encounter one that does not, we'll have to 213129198Scognet * rethink this. 214129198Scognet */ 215129198Scognet cpu_control(CPU_CONTROL_VECRELOC, CPU_CONTROL_VECRELOC); 216129198Scognet } 217129198Scognet} 218129198Scognet 219129198Scognetstatic void 220129198Scognetcpu_startup(void *dummy) 221129198Scognet{ 222129198Scognet struct pcb *pcb = thread0.td_pcb; 223137215Scognet 224129198Scognet vm_ksubmap_init(&kmi); 225129198Scognet bufinit(); 226129198Scognet vm_pager_bufferinit(); 227129198Scognet pcb->un_32.pcb32_und_sp = (u_int)thread0.td_kstack + 228129198Scognet USPACE_UNDEF_STACK_TOP; 229129198Scognet pcb->un_32.pcb32_sp = (u_int)thread0.td_kstack + 230129198Scognet USPACE_SVC_STACK_TOP; 231129198Scognet vector_page_setprot(VM_PROT_READ); 232129198Scognet pmap_set_pcb_pagedir(pmap_kernel(), pcb); 233129198Scognet cpu_setup(""); 234129198Scognet identify_arm_cpu(); 235129198Scognet thread0.td_frame = (struct trapframe *)pcb->un_32.pcb32_sp - 1; 236137215Scognet 237129198Scognet} 238129198Scognet 239129198ScognetSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) 240129198Scognet 241141237Snjl/* Get current clock frequency for the given cpu id. */ 242141237Snjlint 243141237Snjlcpu_est_clockrate(int cpu_id, uint64_t *rate) 244141237Snjl{ 245141237Snjl 246141237Snjl return (ENXIO); 247141237Snjl} 248141237Snjl 249129198Scognetvoid 250129198Scognetcpu_idle(void) 251129198Scognet{ 252137215Scognet cpu_sleep(0); 253129198Scognet} 254129198Scognet 255129198Scognetint 256129198Scognetfill_regs(struct thread *td, struct reg *regs) 257129198Scognet{ 258129198Scognet struct trapframe *tf = td->td_frame; 259129198Scognet bcopy(&tf->tf_r0, regs->r, sizeof(regs->r)); 260129198Scognet regs->r_sp = tf->tf_usr_sp; 261129198Scognet regs->r_lr = tf->tf_usr_lr; 262129198Scognet regs->r_pc = tf->tf_pc; 263129198Scognet regs->r_cpsr = tf->tf_spsr; 264129198Scognet return (0); 265129198Scognet} 266129198Scognetint 267129198Scognetfill_fpregs(struct thread *td, struct fpreg *regs) 268129198Scognet{ 269129198Scognet bzero(regs, sizeof(*regs)); 270129198Scognet return (0); 271129198Scognet} 272129198Scognet 273129198Scognetint 274129198Scognetset_regs(struct thread *td, struct reg *regs) 275129198Scognet{ 276129198Scognet struct trapframe *tf = td->td_frame; 277129198Scognet 278137215Scognet bcopy(regs->r, &tf->tf_r0, sizeof(regs->r)); 279129198Scognet tf->tf_usr_sp = regs->r_sp; 280129198Scognet tf->tf_usr_lr = regs->r_lr; 281129198Scognet tf->tf_pc = regs->r_pc; 282129198Scognet tf->tf_spsr &= ~PSR_FLAGS; 283129198Scognet tf->tf_spsr |= regs->r_cpsr & PSR_FLAGS; 284129198Scognet return (0); 285129198Scognet} 286129198Scognet 287129198Scognetint 288129198Scognetset_fpregs(struct thread *td, struct fpreg *regs) 289129198Scognet{ 290129198Scognet return (0); 291129198Scognet} 292129198Scognet 293129198Scognetint 294129198Scognetfill_dbregs(struct thread *td, struct dbreg *regs) 295129198Scognet{ 296129198Scognet return (0); 297129198Scognet} 298129198Scognetint 299129198Scognetset_dbregs(struct thread *td, struct dbreg *regs) 300129198Scognet{ 301129198Scognet return (0); 302129198Scognet} 303129198Scognet 304140001Scognet 305140001Scognetstatic int 306140001Scognetptrace_read_int(struct thread *td, vm_offset_t addr, u_int32_t *v) 307140001Scognet{ 308140001Scognet struct iovec iov; 309140001Scognet struct uio uio; 310140001Scognet iov.iov_base = (caddr_t) v; 311140001Scognet iov.iov_len = sizeof(u_int32_t); 312140001Scognet uio.uio_iov = &iov; 313140001Scognet uio.uio_iovcnt = 1; 314140001Scognet uio.uio_offset = (off_t)addr; 315140001Scognet uio.uio_resid = sizeof(u_int32_t); 316140001Scognet uio.uio_segflg = UIO_SYSSPACE; 317140001Scognet uio.uio_rw = UIO_READ; 318140001Scognet uio.uio_td = td; 319140001Scognet return proc_rwmem(td->td_proc, &uio); 320140001Scognet} 321140001Scognet 322140001Scognetstatic int 323140001Scognetptrace_write_int(struct thread *td, vm_offset_t addr, u_int32_t v) 324140001Scognet{ 325140001Scognet struct iovec iov; 326140001Scognet struct uio uio; 327140001Scognet iov.iov_base = (caddr_t) &v; 328140001Scognet iov.iov_len = sizeof(u_int32_t); 329140001Scognet uio.uio_iov = &iov; 330140001Scognet uio.uio_iovcnt = 1; 331140001Scognet uio.uio_offset = (off_t)addr; 332140001Scognet uio.uio_resid = sizeof(u_int32_t); 333140001Scognet uio.uio_segflg = UIO_SYSSPACE; 334140001Scognet uio.uio_rw = UIO_WRITE; 335140001Scognet uio.uio_td = td; 336140001Scognet return proc_rwmem(td->td_proc, &uio); 337140001Scognet} 338140001Scognet 339129198Scognetint 340129198Scognetptrace_single_step(struct thread *td) 341129198Scognet{ 342140001Scognet int error; 343140001Scognet 344140001Scognet KASSERT(td->td_md.md_ptrace_instr == 0, 345140001Scognet ("Didn't clear single step")); 346140001Scognet error = ptrace_read_int(td, td->td_frame->tf_pc + 4, 347140001Scognet &td->td_md.md_ptrace_instr); 348140001Scognet if (error) 349140001Scognet return (error); 350140001Scognet error = ptrace_write_int(td, td->td_frame->tf_pc + 4, 351140001Scognet PTRACE_BREAKPOINT); 352140001Scognet if (error) 353140001Scognet td->td_md.md_ptrace_instr = 0; 354140001Scognet td->td_md.md_ptrace_addr = td->td_frame->tf_pc + 4; 355140001Scognet return (error); 356129198Scognet} 357129198Scognet 358129198Scognetint 359132474Scognetptrace_clear_single_step(struct thread *td) 360132474Scognet{ 361140001Scognet if (td->td_md.md_ptrace_instr) { 362140001Scognet ptrace_write_int(td, td->td_md.md_ptrace_addr, 363140001Scognet td->td_md.md_ptrace_instr); 364140001Scognet td->td_md.md_ptrace_instr = 0; 365140001Scognet } 366132474Scognet return (0); 367132474Scognet} 368132474Scognet 369132474Scognetint 370129198Scognetptrace_set_pc(struct thread *td, unsigned long addr) 371129198Scognet{ 372132474Scognet td->td_frame->tf_pc = addr; 373129198Scognet return (0); 374129198Scognet} 375129198Scognet 376129198Scognetvoid 377129198Scognetcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) 378129198Scognet{ 379129198Scognet} 380129198Scognet 381129198Scognet/* 382129198Scognet * Clear registers on exec 383129198Scognet */ 384129198Scognetvoid 385129198Scognetexec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) 386129198Scognet{ 387129198Scognet struct trapframe *tf = td->td_frame; 388129198Scognet 389129198Scognet memset(tf, 0, sizeof(*tf)); 390129198Scognet tf->tf_usr_sp = stack; 391129198Scognet tf->tf_usr_lr = entry; 392129198Scognet tf->tf_svc_lr = 0x77777777; 393129198Scognet tf->tf_pc = entry; 394129198Scognet tf->tf_spsr = PSR_USR32_MODE; 395129198Scognet} 396129198Scognet 397129198Scognet/* 398129198Scognet * Build siginfo_t for SA thread 399129198Scognet */ 400129198Scognetvoid 401129198Scognetcpu_thread_siginfo(int sig, u_long code, siginfo_t *si) 402129198Scognet{ 403137215Scognet bzero(si, sizeof(*si)); 404137215Scognet si->si_signo = sig; 405137215Scognet si->si_code = code; 406129198Scognet} 407129198Scognet 408129198Scognet/* 409129198Scognet * Get machine context. 410129198Scognet */ 411129198Scognetint 412129198Scognetget_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret) 413129198Scognet{ 414129198Scognet struct trapframe *tf = td->td_frame; 415129198Scognet __greg_t *gr = mcp->__gregs; 416129198Scognet 417137215Scognet if (clear_ret & GET_MC_CLEAR_RET) 418137215Scognet gr[_REG_R0] = 0; 419137215Scognet else 420137215Scognet gr[_REG_R0] = tf->tf_r0; 421129198Scognet gr[_REG_R1] = tf->tf_r1; 422129198Scognet gr[_REG_R2] = tf->tf_r2; 423129198Scognet gr[_REG_R3] = tf->tf_r3; 424129198Scognet gr[_REG_R4] = tf->tf_r4; 425129198Scognet gr[_REG_R5] = tf->tf_r5; 426129198Scognet gr[_REG_R6] = tf->tf_r6; 427129198Scognet gr[_REG_R7] = tf->tf_r7; 428129198Scognet gr[_REG_R8] = tf->tf_r8; 429129198Scognet gr[_REG_R9] = tf->tf_r9; 430129198Scognet gr[_REG_R10] = tf->tf_r10; 431129198Scognet gr[_REG_R11] = tf->tf_r11; 432129198Scognet gr[_REG_R12] = tf->tf_r12; 433129198Scognet gr[_REG_SP] = tf->tf_usr_sp; 434129198Scognet gr[_REG_LR] = tf->tf_usr_lr; 435129198Scognet gr[_REG_PC] = tf->tf_pc; 436129198Scognet gr[_REG_CPSR] = tf->tf_spsr; 437129198Scognet 438129198Scognet return (0); 439129198Scognet} 440129198Scognet 441129198Scognet/* 442129198Scognet * Set machine context. 443129198Scognet * 444129198Scognet * However, we don't set any but the user modifiable flags, and we won't 445129198Scognet * touch the cs selector. 446129198Scognet */ 447129198Scognetint 448129198Scognetset_mcontext(struct thread *td, const mcontext_t *mcp) 449129198Scognet{ 450137215Scognet struct trapframe *tf = td->td_frame; 451137215Scognet __greg_t *gr = mcp->__gregs; 452137215Scognet 453137215Scognet tf->tf_r0 = gr[_REG_R0]; 454137215Scognet tf->tf_r1 = gr[_REG_R1]; 455137215Scognet tf->tf_r2 = gr[_REG_R2]; 456137215Scognet tf->tf_r3 = gr[_REG_R3]; 457137215Scognet tf->tf_r4 = gr[_REG_R4]; 458137215Scognet tf->tf_r5 = gr[_REG_R5]; 459137215Scognet tf->tf_r6 = gr[_REG_R6]; 460137215Scognet tf->tf_r7 = gr[_REG_R7]; 461137215Scognet tf->tf_r8 = gr[_REG_R8]; 462137215Scognet tf->tf_r9 = gr[_REG_R9]; 463137215Scognet tf->tf_r10 = gr[_REG_R10]; 464137215Scognet tf->tf_r11 = gr[_REG_R11]; 465137215Scognet tf->tf_r12 = gr[_REG_R12]; 466137215Scognet tf->tf_usr_sp = gr[_REG_SP]; 467137215Scognet tf->tf_usr_lr = gr[_REG_LR]; 468137215Scognet tf->tf_pc = gr[_REG_PC]; 469137215Scognet tf->tf_spsr = gr[_REG_CPSR]; 470137215Scognet 471129198Scognet return (0); 472129198Scognet} 473129198Scognet 474129198Scognet/* 475129198Scognet * MPSAFE 476129198Scognet */ 477129198Scognetint 478129198Scognetsigreturn(td, uap) 479129198Scognet struct thread *td; 480129198Scognet struct sigreturn_args /* { 481129198Scognet const __ucontext *sigcntxp; 482129198Scognet } */ *uap; 483129198Scognet{ 484135653Scognet struct proc *p = td->td_proc; 485135653Scognet struct sigframe sf; 486135653Scognet struct trapframe *tf; 487135653Scognet int spsr; 488135653Scognet 489135653Scognet if (uap == NULL) 490135653Scognet return (EFAULT); 491135653Scognet if (copyin(uap->sigcntxp, &sf, sizeof(sf))) 492135653Scognet return (EFAULT); 493135653Scognet /* 494135653Scognet * Make sure the processor mode has not been tampered with and 495135653Scognet * interrupts have not been disabled. 496135653Scognet */ 497135653Scognet spsr = sf.sf_uc.uc_mcontext.__gregs[_REG_CPSR]; 498135653Scognet if ((spsr & PSR_MODE) != PSR_USR32_MODE || 499135653Scognet (spsr & (I32_bit | F32_bit)) != 0) 500135653Scognet return (EINVAL); 501135653Scognet /* Restore register context. */ 502135653Scognet tf = td->td_frame; 503137215Scognet set_mcontext(td, &sf.sf_uc.uc_mcontext); 504135653Scognet 505135653Scognet /* Restore signal mask. */ 506135653Scognet PROC_LOCK(p); 507135653Scognet td->td_sigmask = sf.sf_uc.uc_sigmask; 508135653Scognet SIG_CANTMASK(td->td_sigmask); 509135653Scognet signotify(td); 510135653Scognet PROC_UNLOCK(p); 511135653Scognet 512135653Scognet return (EJUSTRETURN); 513129198Scognet} 514129198Scognet 515129198Scognet 516132054Scognet/* 517132054Scognet * Construct a PCB from a trapframe. This is called from kdb_trap() where 518132054Scognet * we want to start a backtrace from the function that caused us to enter 519132054Scognet * the debugger. We have the context in the trapframe, but base the trace 520132054Scognet * on the PCB. The PCB doesn't have to be perfect, as long as it contains 521132054Scognet * enough for a backtrace. 522132054Scognet */ 523132054Scognetvoid 524132054Scognetmakectx(struct trapframe *tf, struct pcb *pcb) 525132054Scognet{ 526132054Scognet pcb->un_32.pcb32_r8 = tf->tf_r8; 527132054Scognet pcb->un_32.pcb32_r9 = tf->tf_r9; 528132054Scognet pcb->un_32.pcb32_r10 = tf->tf_r10; 529132054Scognet pcb->un_32.pcb32_r11 = tf->tf_r11; 530132054Scognet pcb->un_32.pcb32_r12 = tf->tf_r12; 531132054Scognet pcb->un_32.pcb32_pc = tf->tf_pc; 532132054Scognet pcb->un_32.pcb32_lr = tf->tf_usr_lr; 533132054Scognet pcb->un_32.pcb32_sp = tf->tf_usr_sp; 534132054Scognet} 535