machdep_kdb.c revision 141378
140783Snsouch/* $NetBSD: arm32_machdep.c,v 1.44 2004/03/24 15:34:47 atatat Exp $ */ 293023Snsouch 340783Snsouch/*- 440783Snsouch * Copyright (c) 2004 Olivier Houchard 540783Snsouch * Copyright (c) 1994-1998 Mark Brinicombe. 640783Snsouch * Copyright (c) 1994 Brini. 740783Snsouch * All rights reserved. 840783Snsouch * 940783Snsouch * This code is derived from software written for Brini by Mark Brinicombe 1040783Snsouch * 1140783Snsouch * Redistribution and use in source and binary forms, with or without 1240783Snsouch * modification, are permitted provided that the following conditions 1340783Snsouch * are met: 1440783Snsouch * 1. Redistributions of source code must retain the above copyright 1540783Snsouch * notice, this list of conditions and the following disclaimer. 1640783Snsouch * 2. Redistributions in binary form must reproduce the above copyright 1740783Snsouch * notice, this list of conditions and the following disclaimer in the 1840783Snsouch * documentation and/or other materials provided with the distribution. 1940783Snsouch * 3. All advertising materials mentioning features or use of this software 2040783Snsouch * must display the following acknowledgement: 2140783Snsouch * This product includes software developed by Mark Brinicombe 2240783Snsouch * for the NetBSD Project. 2340783Snsouch * 4. The name of the company nor the name of the author may be used to 2440783Snsouch * endorse or promote products derived from this software without specific 2540783Snsouch * prior written permission. 2640783Snsouch * 2740783Snsouch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 2840783Snsouch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 29119418Sobrien * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 30119418Sobrien * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 31119418Sobrien * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 3240783Snsouch * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 3340783Snsouch * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3440783Snsouch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3540783Snsouch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3640783Snsouch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3740783Snsouch * SUCH DAMAGE. 3840783Snsouch * 39181303Sjhb * Machine dependant functions for kernel setup 40181303Sjhb * 4140783Snsouch * Created : 17/09/94 42181303Sjhb * Updated : 18/04/01 updated for new wscons 43181303Sjhb */ 4440783Snsouch 4540783Snsouch#include "opt_compat.h" 4640783Snsouch#include <sys/cdefs.h> 4740783Snsouch__FBSDID("$FreeBSD: head/sys/arm/arm/machdep.c 141378 2005-02-06 01:55:08Z njl $"); 4840783Snsouch 4955939Snsouch#include <sys/param.h> 5055939Snsouch#include <sys/proc.h> 5140783Snsouch#include <sys/systm.h> 5240783Snsouch#include <sys/bio.h> 5340783Snsouch#include <sys/buf.h> 5440783Snsouch#include <sys/bus.h> 5540783Snsouch#include <sys/cons.h> 5640783Snsouch#include <sys/cpu.h> 5755939Snsouch#include <sys/exec.h> 5840783Snsouch#include <sys/imgact.h> 5956455Speter#include <sys/kernel.h> 6056455Speter#include <sys/linker.h> 6156455Speter#include <sys/lock.h> 6240783Snsouch#include <sys/malloc.h> 63127189Sguido#include <sys/mutex.h> 64127189Sguido#include <sys/pcpu.h> 65184130Sjhb#include <sys/ptrace.h> 66127189Sguido#include <sys/signalvar.h> 67127189Sguido#include <sys/sysent.h> 6856455Speter#include <sys/sysproto.h> 6940783Snsouch#include <sys/uio.h> 7040783Snsouch 7140783Snsouch#include <vm/pmap.h> 7240783Snsouch#include <vm/vm.h> 7340783Snsouch#include <vm/vm_map.h> 7456455Speter#include <vm/vm_object.h> 7555939Snsouch#include <vm/vm_page.h> 7655939Snsouch#include <vm/vm_pager.h> 7740783Snsouch#include <vm/vnode_pager.h> 7856455Speter 7956455Speter#include <machine/armreg.h> 8040783Snsouch#include <machine/cpu.h> 8140783Snsouch#include <machine/machdep.h> 8240783Snsouch#include <machine/md_var.h> 8340783Snsouch#include <machine/metadata.h> 8440783Snsouch#include <machine/pcb.h> 8540783Snsouch#include <machine/pmap.h> 8693023Snsouch#include <machine/reg.h> 87185003Sjhb#include <machine/trap.h> 8840783Snsouch#include <machine/undefined.h> 8954073Smdodd#include <machine/vmparam.h> 9040783Snsouch 9140783Snsouch#define MDROOT_ADDR 0xd0400000 9240783Snsouch 9340783Snsouchuint32_t cpu_reset_address = 0; 9440783Snsouchint cold = 1; 9540783Snsouchvm_offset_t vector_page; 96189725Simp 9740783Snsouchvoid 9855939Snsouchsendsig(catcher, sig, mask, code) 9940783Snsouch sig_t catcher; 10040783Snsouch int sig; 10140783Snsouch sigset_t *mask; 10240783Snsouch u_long code; 10340783Snsouch{ 10440783Snsouch struct thread *td = curthread; 10540783Snsouch struct proc *p = td->td_proc; 106187576Sjhb struct trapframe *tf = td->td_frame; 10755939Snsouch struct sigframe *fp, frame; 108187576Sjhb struct sigacts *psp = td->td_proc->p_sigacts; 10940783Snsouch int onstack; 11040783Snsouch 11140783Snsouch onstack = sigonstack(td->td_frame->tf_usr_sp); 11240783Snsouch 113187576Sjhb if ((td->td_flags & TDP_ALTSTACK) && 11455939Snsouch !(onstack) && 115187576Sjhb SIGISMEMBER(td->td_proc->p_sigacts->ps_sigonstack, sig)) { 11640783Snsouch fp = (void*)(td->td_sigstk.ss_sp + td->td_sigstk.ss_size); 11740783Snsouch td->td_sigstk.ss_flags |= SS_ONSTACK; 11840783Snsouch } else 11940783Snsouch fp = (void*)td->td_frame->tf_usr_sp; 12040783Snsouch 12140783Snsouch /* make room on the stack */ 12240783Snsouch fp--; 12340783Snsouch 12440783Snsouch /* make the stack aligned */ 12540783Snsouch fp = (struct sigframe *)STACKALIGN(fp); 12640783Snsouch /* Populate the siginfo frame. */ 12740783Snsouch frame.sf_si.si_signo = sig; 12840783Snsouch frame.sf_si.si_code = code; 12940783Snsouch frame.sf_uc.uc_sigmask = *mask; 13040783Snsouch frame.sf_uc.uc_link = NULL; 13140783Snsouch frame.sf_uc.uc_flags = (td->td_pflags & TDP_ALTSTACK ) 132187576Sjhb ? ((onstack) ? SS_ONSTACK : 0) : SS_DISABLE; 133187576Sjhb frame.sf_uc.uc_stack = td->td_sigstk; 134187576Sjhb memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack)); 135187576Sjhb get_mcontext(td, &frame.sf_uc.uc_mcontext, 0); 136187576Sjhb PROC_UNLOCK(td->td_proc); 137187576Sjhb mtx_unlock(&psp->ps_mtx); 138187576Sjhb if (copyout(&frame, (void*)fp, sizeof(frame)) != 0) 139187576Sjhb sigexit(td, SIGILL); 140187576Sjhb /* 141187576Sjhb * Build context to run handler in. We invoke the handler 142187576Sjhb * directly, only returning via the trampoline. Note the 143181303Sjhb * trampoline version numbers are coordinated with machine- 144181303Sjhb * dependent code in libc. 14540783Snsouch */ 146187576Sjhb 147181303Sjhb tf->tf_r0 = sig; 148181303Sjhb tf->tf_r1 = (int)&fp->sf_si; 149187576Sjhb tf->tf_r2 = (int)&fp->sf_uc; 150187576Sjhb 151187576Sjhb /* the trampoline uses r5 as the uc address */ 152181303Sjhb tf->tf_r5 = (int)&fp->sf_uc; 15340783Snsouch tf->tf_pc = (int)catcher; 15440783Snsouch tf->tf_usr_sp = (int)fp; 155181303Sjhb tf->tf_usr_lr = (int)(PS_STRINGS - *(p->p_sysent->sv_szsigcode)); 156181303Sjhb PROC_LOCK(td->td_proc); 15740783Snsouch mtx_lock(&psp->ps_mtx); 158187576Sjhb} 159181303Sjhb 160181303Sjhbstruct kva_md_info kmi; 161187576Sjhb 162187576Sjhb/* 163187576Sjhb * arm32_vector_init: 164181303Sjhb * 16593023Snsouch * Initialize the vector page, and select whether or not to 16693023Snsouch * relocate the vectors. 167181303Sjhb * 168189725Simp * NOTE: We expect the vector page to be mapped at its expected 16993023Snsouch * destination. 17093023Snsouch */ 17193023Snsouch 172187576Sjhbextern unsigned int page0[], page0_data[]; 173181303Sjhbvoid 17455939Snsoucharm_vector_init(vm_offset_t va, int which) 175185003Sjhb{ 17655939Snsouch unsigned int *vectors = (int *) va; 177187576Sjhb unsigned int *vectors_data = vectors + (page0_data - page0); 17840783Snsouch int vec; 17940783Snsouch 180181303Sjhb /* 181189725Simp * Loop through the vectors we're taking over, and copy the 18240783Snsouch * vector's insn and data word. 18393023Snsouch */ 18493023Snsouch for (vec = 0; vec < ARM_NVEC; vec++) { 185187576Sjhb if ((which & (1 << vec)) == 0) { 186181303Sjhb /* Don't want to take over this vector. */ 187181303Sjhb continue; 188185003Sjhb } 189185003Sjhb vectors[vec] = page0[vec]; 190187576Sjhb vectors_data[vec] = page0_data[vec]; 19140783Snsouch } 19240783Snsouch 193181303Sjhb /* Now sync the vectors. */ 194181303Sjhb cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int)); 19540783Snsouch 19655939Snsouch vector_page = va; 19755939Snsouch 198187576Sjhb if (va == ARM_VECTORS_HIGH) { 19955939Snsouch /* 200187576Sjhb * Assume the MD caller knows what it's doing here, and 20155939Snsouch * really does want the vector page relocated. 20240783Snsouch * 20340783Snsouch * Note: This has to be done here (and not just in 20440783Snsouch * cpu_setup()) because the vector page needs to be 205187576Sjhb * accessible *before* cpu_startup() is called. 20640783Snsouch * Think ddb(9) ... 20755939Snsouch * 20855939Snsouch * NOTE: If the CPU control register is not readable, 20955939Snsouch * this will totally fail! We'll just assume that 210187576Sjhb * any system that has high vector support has a 21140783Snsouch * readable CPU control register, for now. If we 21241042Snsouch * ever encounter one that does not, we'll have to 21340783Snsouch * rethink this. 21455939Snsouch */ 215187576Sjhb cpu_control(CPU_CONTROL_VECRELOC, CPU_CONTROL_VECRELOC); 21640783Snsouch } 21740783Snsouch} 21840783Snsouch 21940783Snsouchstatic void 22040783Snsouchcpu_startup(void *dummy) 22140783Snsouch{ 22240783Snsouch struct pcb *pcb = thread0.td_pcb; 22355939Snsouch 22440783Snsouch vm_ksubmap_init(&kmi); 225187576Sjhb bufinit(); 22693023Snsouch vm_pager_bufferinit(); 227187576Sjhb pcb->un_32.pcb32_und_sp = (u_int)thread0.td_kstack + 22893023Snsouch USPACE_UNDEF_STACK_TOP; 22993023Snsouch pcb->un_32.pcb32_sp = (u_int)thread0.td_kstack + 23093023Snsouch USPACE_SVC_STACK_TOP; 23193023Snsouch vector_page_setprot(VM_PROT_READ); 232187576Sjhb pmap_set_pcb_pagedir(pmap_kernel(), pcb); 23340783Snsouch cpu_setup(""); 23493023Snsouch identify_arm_cpu(); 235187576Sjhb thread0.td_frame = (struct trapframe *)pcb->un_32.pcb32_sp - 1; 23693023Snsouch 23740783Snsouch} 23840783Snsouch 23940783SnsouchSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) 24056455Speter 24156455Speter/* Get current clock frequency for the given cpu id. */ 24256455Speterint 24356455Spetercpu_est_clockrate(int cpu_id, uint64_t *rate) 24456455Speter{ 24556455Speter 24656455Speter return (ENXIO); 24756455Speter} 24856455Speter 24956455Spetervoid 25093023Snsouchcpu_idle(void) 25193023Snsouch{ 25293023Snsouch cpu_sleep(0); 25393023Snsouch} 25456455Speter 25556455Speterint 256227843Smariusfill_regs(struct thread *td, struct reg *regs) 25756455Speter{ 25856455Speter struct trapframe *tf = td->td_frame; 25956455Speter bcopy(&tf->tf_r0, regs->r, sizeof(regs->r)); 26056455Speter regs->r_sp = tf->tf_usr_sp; 26156455Speter regs->r_lr = tf->tf_usr_lr; 26256455Speter regs->r_pc = tf->tf_pc; 26356455Speter regs->r_cpsr = tf->tf_spsr; 26456455Speter return (0); 26555939Snsouch} 266181303Sjhbint 267153610Srufill_fpregs(struct thread *td, struct fpreg *regs) 26893023Snsouch{ 26993023Snsouch 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