machdep_kdb.c revision 141249
1/* $NetBSD: arm32_machdep.c,v 1.44 2004/03/24 15:34:47 atatat Exp $ */ 2 3/*- 4 * Copyright (c) 2004 Olivier Houchard 5 * Copyright (c) 1994-1998 Mark Brinicombe. 6 * Copyright (c) 1994 Brini. 7 * All rights reserved. 8 * 9 * This code is derived from software written for Brini by Mark Brinicombe 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by Mark Brinicombe 22 * for the NetBSD Project. 23 * 4. The name of the company nor the name of the author may be used to 24 * endorse or promote products derived from this software without specific 25 * prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 28 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 29 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 30 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 31 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 32 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 33 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * Machine dependant functions for kernel setup 40 * 41 * Created : 17/09/94 42 * Updated : 18/04/01 updated for new wscons 43 */ 44 45#include "opt_compat.h" 46#include <sys/cdefs.h> 47__FBSDID("$FreeBSD: head/sys/arm/arm/machdep.c 141249 2005-02-04 06:58:09Z njl $"); 48 49#include <sys/param.h> 50#include <sys/systm.h> 51#include <sys/bio.h> 52#include <sys/buf.h> 53#include <sys/bus.h> 54#include <sys/cpu.h> 55#include <sys/sysproto.h> 56#include <sys/signalvar.h> 57#include <sys/imgact.h> 58#include <sys/kernel.h> 59#include <sys/linker.h> 60#include <sys/lock.h> 61#include <sys/malloc.h> 62#include <sys/mutex.h> 63#include <sys/pcpu.h> 64#include <sys/proc.h> 65#include <sys/ptrace.h> 66#include <sys/cons.h> 67#include <sys/exec.h> 68#include <sys/sysent.h> 69#include <sys/uio.h> 70#include <machine/reg.h> 71#include <machine/cpu.h> 72#include <machine/trap.h> 73 74#include <vm/vm.h> 75#include <vm/pmap.h> 76#include <vm/vm.h> 77#include <vm/vm_object.h> 78#include <vm/vm_page.h> 79#include <vm/vm_pager.h> 80#include <vm/vm_map.h> 81#include <vm/vnode_pager.h> 82#include <machine/pmap.h> 83#include <machine/vmparam.h> 84#include <machine/pcb.h> 85#include <machine/undefined.h> 86#include <machine/machdep.h> 87#include <machine/metadata.h> 88#include <machine/armreg.h> 89#include <machine/md_var.h> 90 91#define MDROOT_ADDR 0xd0400000 92 93uint32_t cpu_reset_address = 0; 94int cold = 1; 95vm_offset_t vector_page; 96 97void 98sendsig(catcher, sig, mask, code) 99 sig_t catcher; 100 int sig; 101 sigset_t *mask; 102 u_long code; 103{ 104 struct thread *td = curthread; 105 struct proc *p = td->td_proc; 106 struct trapframe *tf = td->td_frame; 107 struct sigframe *fp, frame; 108 struct sigacts *psp = td->td_proc->p_sigacts; 109 int onstack; 110 111 onstack = sigonstack(td->td_frame->tf_usr_sp); 112 113 if ((td->td_flags & TDP_ALTSTACK) && 114 !(onstack) && 115 SIGISMEMBER(td->td_proc->p_sigacts->ps_sigonstack, sig)) { 116 fp = (void*)(td->td_sigstk.ss_sp + td->td_sigstk.ss_size); 117 td->td_sigstk.ss_flags |= SS_ONSTACK; 118 } else 119 fp = (void*)td->td_frame->tf_usr_sp; 120 121 /* make room on the stack */ 122 fp--; 123 124 /* make the stack aligned */ 125 fp = (struct sigframe *)STACKALIGN(fp); 126 /* Populate the siginfo frame. */ 127 frame.sf_si.si_signo = sig; 128 frame.sf_si.si_code = code; 129 frame.sf_uc.uc_sigmask = *mask; 130 frame.sf_uc.uc_link = NULL; 131 frame.sf_uc.uc_flags = (td->td_pflags & TDP_ALTSTACK ) 132 ? ((onstack) ? SS_ONSTACK : 0) : SS_DISABLE; 133 frame.sf_uc.uc_stack = td->td_sigstk; 134 memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack)); 135 get_mcontext(td, &frame.sf_uc.uc_mcontext, 0); 136 PROC_UNLOCK(td->td_proc); 137 mtx_unlock(&psp->ps_mtx); 138 if (copyout(&frame, (void*)fp, sizeof(frame)) != 0) 139 sigexit(td, SIGILL); 140 /* 141 * Build context to run handler in. We invoke the handler 142 * directly, only returning via the trampoline. Note the 143 * trampoline version numbers are coordinated with machine- 144 * dependent code in libc. 145 */ 146 147 tf->tf_r0 = sig; 148 tf->tf_r1 = (int)&fp->sf_si; 149 tf->tf_r2 = (int)&fp->sf_uc; 150 151 /* the trampoline uses r5 as the uc address */ 152 tf->tf_r5 = (int)&fp->sf_uc; 153 tf->tf_pc = (int)catcher; 154 tf->tf_usr_sp = (int)fp; 155 tf->tf_usr_lr = (int)(PS_STRINGS - *(p->p_sysent->sv_szsigcode)); 156 PROC_LOCK(td->td_proc); 157 mtx_lock(&psp->ps_mtx); 158} 159 160struct kva_md_info kmi; 161 162/* 163 * arm32_vector_init: 164 * 165 * Initialize the vector page, and select whether or not to 166 * relocate the vectors. 167 * 168 * NOTE: We expect the vector page to be mapped at its expected 169 * destination. 170 */ 171 172extern unsigned int page0[], page0_data[]; 173void 174arm_vector_init(vm_offset_t va, int which) 175{ 176 unsigned int *vectors = (int *) va; 177 unsigned int *vectors_data = vectors + (page0_data - page0); 178 int vec; 179 180 /* 181 * Loop through the vectors we're taking over, and copy the 182 * vector's insn and data word. 183 */ 184 for (vec = 0; vec < ARM_NVEC; vec++) { 185 if ((which & (1 << vec)) == 0) { 186 /* Don't want to take over this vector. */ 187 continue; 188 } 189 vectors[vec] = page0[vec]; 190 vectors_data[vec] = page0_data[vec]; 191 } 192 193 /* Now sync the vectors. */ 194 cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int)); 195 196 vector_page = va; 197 198 if (va == ARM_VECTORS_HIGH) { 199 /* 200 * Assume the MD caller knows what it's doing here, and 201 * really does want the vector page relocated. 202 * 203 * Note: This has to be done here (and not just in 204 * cpu_setup()) because the vector page needs to be 205 * accessible *before* cpu_startup() is called. 206 * Think ddb(9) ... 207 * 208 * NOTE: If the CPU control register is not readable, 209 * this will totally fail! We'll just assume that 210 * any system that has high vector support has a 211 * readable CPU control register, for now. If we 212 * ever encounter one that does not, we'll have to 213 * rethink this. 214 */ 215 cpu_control(CPU_CONTROL_VECRELOC, CPU_CONTROL_VECRELOC); 216 } 217} 218 219static void 220cpu_startup(void *dummy) 221{ 222 struct pcb *pcb = thread0.td_pcb; 223 224 vm_ksubmap_init(&kmi); 225 bufinit(); 226 vm_pager_bufferinit(); 227 pcb->un_32.pcb32_und_sp = (u_int)thread0.td_kstack + 228 USPACE_UNDEF_STACK_TOP; 229 pcb->un_32.pcb32_sp = (u_int)thread0.td_kstack + 230 USPACE_SVC_STACK_TOP; 231 vector_page_setprot(VM_PROT_READ); 232 pmap_set_pcb_pagedir(pmap_kernel(), pcb); 233 cpu_setup(""); 234 identify_arm_cpu(); 235 thread0.td_frame = (struct trapframe *)pcb->un_32.pcb32_sp - 1; 236 237} 238 239SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) 240 241/* Get current clock frequency for the given cpu id. */ 242int 243cpu_est_clockrate(int cpu_id, uint64_t *rate) 244{ 245 246 return (ENXIO); 247} 248 249void 250cpu_idle(void) 251{ 252 cpu_sleep(0); 253} 254 255int 256fill_regs(struct thread *td, struct reg *regs) 257{ 258 struct trapframe *tf = td->td_frame; 259 bcopy(&tf->tf_r0, regs->r, sizeof(regs->r)); 260 regs->r_sp = tf->tf_usr_sp; 261 regs->r_lr = tf->tf_usr_lr; 262 regs->r_pc = tf->tf_pc; 263 regs->r_cpsr = tf->tf_spsr; 264 return (0); 265} 266int 267fill_fpregs(struct thread *td, struct fpreg *regs) 268{ 269 bzero(regs, sizeof(*regs)); 270 return (0); 271} 272 273int 274set_regs(struct thread *td, struct reg *regs) 275{ 276 struct trapframe *tf = td->td_frame; 277 278 bcopy(regs->r, &tf->tf_r0, sizeof(regs->r)); 279 tf->tf_usr_sp = regs->r_sp; 280 tf->tf_usr_lr = regs->r_lr; 281 tf->tf_pc = regs->r_pc; 282 tf->tf_spsr &= ~PSR_FLAGS; 283 tf->tf_spsr |= regs->r_cpsr & PSR_FLAGS; 284 return (0); 285} 286 287int 288set_fpregs(struct thread *td, struct fpreg *regs) 289{ 290 return (0); 291} 292 293int 294fill_dbregs(struct thread *td, struct dbreg *regs) 295{ 296 return (0); 297} 298int 299set_dbregs(struct thread *td, struct dbreg *regs) 300{ 301 return (0); 302} 303 304 305static int 306ptrace_read_int(struct thread *td, vm_offset_t addr, u_int32_t *v) 307{ 308 struct iovec iov; 309 struct uio uio; 310 iov.iov_base = (caddr_t) v; 311 iov.iov_len = sizeof(u_int32_t); 312 uio.uio_iov = &iov; 313 uio.uio_iovcnt = 1; 314 uio.uio_offset = (off_t)addr; 315 uio.uio_resid = sizeof(u_int32_t); 316 uio.uio_segflg = UIO_SYSSPACE; 317 uio.uio_rw = UIO_READ; 318 uio.uio_td = td; 319 return proc_rwmem(td->td_proc, &uio); 320} 321 322static int 323ptrace_write_int(struct thread *td, vm_offset_t addr, u_int32_t v) 324{ 325 struct iovec iov; 326 struct uio uio; 327 iov.iov_base = (caddr_t) &v; 328 iov.iov_len = sizeof(u_int32_t); 329 uio.uio_iov = &iov; 330 uio.uio_iovcnt = 1; 331 uio.uio_offset = (off_t)addr; 332 uio.uio_resid = sizeof(u_int32_t); 333 uio.uio_segflg = UIO_SYSSPACE; 334 uio.uio_rw = UIO_WRITE; 335 uio.uio_td = td; 336 return proc_rwmem(td->td_proc, &uio); 337} 338 339int 340ptrace_single_step(struct thread *td) 341{ 342 int error; 343 344 KASSERT(td->td_md.md_ptrace_instr == 0, 345 ("Didn't clear single step")); 346 error = ptrace_read_int(td, td->td_frame->tf_pc + 4, 347 &td->td_md.md_ptrace_instr); 348 if (error) 349 return (error); 350 error = ptrace_write_int(td, td->td_frame->tf_pc + 4, 351 PTRACE_BREAKPOINT); 352 if (error) 353 td->td_md.md_ptrace_instr = 0; 354 td->td_md.md_ptrace_addr = td->td_frame->tf_pc + 4; 355 return (error); 356} 357 358int 359ptrace_clear_single_step(struct thread *td) 360{ 361 if (td->td_md.md_ptrace_instr) { 362 ptrace_write_int(td, td->td_md.md_ptrace_addr, 363 td->td_md.md_ptrace_instr); 364 td->td_md.md_ptrace_instr = 0; 365 } 366 return (0); 367} 368 369int 370ptrace_set_pc(struct thread *td, unsigned long addr) 371{ 372 td->td_frame->tf_pc = addr; 373 return (0); 374} 375 376void 377cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) 378{ 379} 380 381/* 382 * Clear registers on exec 383 */ 384void 385exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) 386{ 387 struct trapframe *tf = td->td_frame; 388 389 memset(tf, 0, sizeof(*tf)); 390 tf->tf_usr_sp = stack; 391 tf->tf_usr_lr = entry; 392 tf->tf_svc_lr = 0x77777777; 393 tf->tf_pc = entry; 394 tf->tf_spsr = PSR_USR32_MODE; 395} 396 397/* 398 * Build siginfo_t for SA thread 399 */ 400void 401cpu_thread_siginfo(int sig, u_long code, siginfo_t *si) 402{ 403 bzero(si, sizeof(*si)); 404 si->si_signo = sig; 405 si->si_code = code; 406} 407 408/* 409 * Get machine context. 410 */ 411int 412get_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret) 413{ 414 struct trapframe *tf = td->td_frame; 415 __greg_t *gr = mcp->__gregs; 416 417 if (clear_ret & GET_MC_CLEAR_RET) 418 gr[_REG_R0] = 0; 419 else 420 gr[_REG_R0] = tf->tf_r0; 421 gr[_REG_R1] = tf->tf_r1; 422 gr[_REG_R2] = tf->tf_r2; 423 gr[_REG_R3] = tf->tf_r3; 424 gr[_REG_R4] = tf->tf_r4; 425 gr[_REG_R5] = tf->tf_r5; 426 gr[_REG_R6] = tf->tf_r6; 427 gr[_REG_R7] = tf->tf_r7; 428 gr[_REG_R8] = tf->tf_r8; 429 gr[_REG_R9] = tf->tf_r9; 430 gr[_REG_R10] = tf->tf_r10; 431 gr[_REG_R11] = tf->tf_r11; 432 gr[_REG_R12] = tf->tf_r12; 433 gr[_REG_SP] = tf->tf_usr_sp; 434 gr[_REG_LR] = tf->tf_usr_lr; 435 gr[_REG_PC] = tf->tf_pc; 436 gr[_REG_CPSR] = tf->tf_spsr; 437 438 return (0); 439} 440 441/* 442 * Set machine context. 443 * 444 * However, we don't set any but the user modifiable flags, and we won't 445 * touch the cs selector. 446 */ 447int 448set_mcontext(struct thread *td, const mcontext_t *mcp) 449{ 450 struct trapframe *tf = td->td_frame; 451 __greg_t *gr = mcp->__gregs; 452 453 tf->tf_r0 = gr[_REG_R0]; 454 tf->tf_r1 = gr[_REG_R1]; 455 tf->tf_r2 = gr[_REG_R2]; 456 tf->tf_r3 = gr[_REG_R3]; 457 tf->tf_r4 = gr[_REG_R4]; 458 tf->tf_r5 = gr[_REG_R5]; 459 tf->tf_r6 = gr[_REG_R6]; 460 tf->tf_r7 = gr[_REG_R7]; 461 tf->tf_r8 = gr[_REG_R8]; 462 tf->tf_r9 = gr[_REG_R9]; 463 tf->tf_r10 = gr[_REG_R10]; 464 tf->tf_r11 = gr[_REG_R11]; 465 tf->tf_r12 = gr[_REG_R12]; 466 tf->tf_usr_sp = gr[_REG_SP]; 467 tf->tf_usr_lr = gr[_REG_LR]; 468 tf->tf_pc = gr[_REG_PC]; 469 tf->tf_spsr = gr[_REG_CPSR]; 470 471 return (0); 472} 473 474/* 475 * MPSAFE 476 */ 477int 478sigreturn(td, uap) 479 struct thread *td; 480 struct sigreturn_args /* { 481 const __ucontext *sigcntxp; 482 } */ *uap; 483{ 484 struct proc *p = td->td_proc; 485 struct sigframe sf; 486 struct trapframe *tf; 487 int spsr; 488 489 if (uap == NULL) 490 return (EFAULT); 491 if (copyin(uap->sigcntxp, &sf, sizeof(sf))) 492 return (EFAULT); 493 /* 494 * Make sure the processor mode has not been tampered with and 495 * interrupts have not been disabled. 496 */ 497 spsr = sf.sf_uc.uc_mcontext.__gregs[_REG_CPSR]; 498 if ((spsr & PSR_MODE) != PSR_USR32_MODE || 499 (spsr & (I32_bit | F32_bit)) != 0) 500 return (EINVAL); 501 /* Restore register context. */ 502 tf = td->td_frame; 503 set_mcontext(td, &sf.sf_uc.uc_mcontext); 504 505 /* Restore signal mask. */ 506 PROC_LOCK(p); 507 td->td_sigmask = sf.sf_uc.uc_sigmask; 508 SIG_CANTMASK(td->td_sigmask); 509 signotify(td); 510 PROC_UNLOCK(p); 511 512 return (EJUSTRETURN); 513} 514 515 516/* 517 * Construct a PCB from a trapframe. This is called from kdb_trap() where 518 * we want to start a backtrace from the function that caused us to enter 519 * the debugger. We have the context in the trapframe, but base the trace 520 * on the PCB. The PCB doesn't have to be perfect, as long as it contains 521 * enough for a backtrace. 522 */ 523void 524makectx(struct trapframe *tf, struct pcb *pcb) 525{ 526 pcb->un_32.pcb32_r8 = tf->tf_r8; 527 pcb->un_32.pcb32_r9 = tf->tf_r9; 528 pcb->un_32.pcb32_r10 = tf->tf_r10; 529 pcb->un_32.pcb32_r11 = tf->tf_r11; 530 pcb->un_32.pcb32_r12 = tf->tf_r12; 531 pcb->un_32.pcb32_pc = tf->tf_pc; 532 pcb->un_32.pcb32_lr = tf->tf_usr_lr; 533 pcb->un_32.pcb32_sp = tf->tf_usr_sp; 534} 535