machdep_kdb.c revision 135653
1129198Scognet/* $NetBSD: arm32_machdep.c,v 1.44 2004/03/24 15:34:47 atatat Exp $ */ 2129198Scognet 3129198Scognet/* 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 135653 2004-09-23 22:12:28Z cognet $"); 48129198Scognet 49129198Scognet#include <sys/param.h> 50129198Scognet#include <sys/systm.h> 51129198Scognet#include <sys/sysproto.h> 52129198Scognet#include <sys/signalvar.h> 53129198Scognet#include <sys/imgact.h> 54129198Scognet#include <sys/kernel.h> 55129198Scognet#include <sys/linker.h> 56129198Scognet#include <sys/lock.h> 57129198Scognet#include <sys/malloc.h> 58129198Scognet#include <sys/mutex.h> 59129198Scognet#include <sys/pcpu.h> 60129198Scognet#include <sys/proc.h> 61129198Scognet#include <sys/ptrace.h> 62129198Scognet#include <sys/cons.h> 63129198Scognet#include <sys/bio.h> 64129198Scognet#include <sys/buf.h> 65129198Scognet#include <sys/exec.h> 66135653Scognet#include <sys/sysent.h> 67129198Scognet#include <machine/reg.h> 68129198Scognet#include <machine/cpu.h> 69129198Scognet 70129198Scognet#include <vm/vm.h> 71129198Scognet#include <vm/pmap.h> 72129198Scognet#include <vm/vm.h> 73129198Scognet#include <vm/vm_object.h> 74129198Scognet#include <vm/vm_page.h> 75129198Scognet#include <vm/vm_pager.h> 76129198Scognet#include <vm/vm_map.h> 77129198Scognet#include <vm/vnode_pager.h> 78129198Scognet#include <machine/pmap.h> 79129198Scognet#include <machine/vmparam.h> 80129198Scognet#include <machine/pcb.h> 81129198Scognet#include <machine/undefined.h> 82129198Scognet#include <machine/machdep.h> 83129198Scognet#include <machine/metadata.h> 84129198Scognet#include <machine/armreg.h> 85135653Scognet#include <machine/md_var.h> 86129198Scognet 87129198Scognet#define MDROOT_ADDR 0xd0400000 88129198Scognet 89129198Scognetuint32_t cpu_reset_address = 0; 90129198Scognetint cold = 1; 91129198Scognetvm_offset_t vector_page; 92129198Scognet 93129198Scognetstatic void * 94129198Scognetgetframe(struct thread *td, int sig, int *onstack) 95129198Scognet{ 96129198Scognet struct trapframe *tf = td->td_frame; 97129198Scognet 98129198Scognet *onstack = sigonstack(tf->tf_usr_sp); 99129198Scognet if (*onstack) 100129198Scognet return (void*)(td->td_sigstk.ss_sp + td->td_sigstk.ss_size); 101129198Scognet return (void*)(tf->tf_usr_sp); 102129198Scognet} 103129198Scognet 104129198Scognetvoid 105129198Scognetsendsig(catcher, sig, mask, code) 106129198Scognet sig_t catcher; 107129198Scognet int sig; 108129198Scognet sigset_t *mask; 109129198Scognet u_long code; 110129198Scognet{ 111129198Scognet struct thread *td = curthread; 112135653Scognet struct proc *p = td->td_proc; 113129198Scognet struct trapframe *tf = td->td_frame; 114129198Scognet struct sigframe *fp, frame; 115129198Scognet struct sigacts *psp = td->td_proc->p_sigacts; 116129198Scognet int onstack; 117129198Scognet 118129198Scognet fp = getframe(td, sig, &onstack); 119129198Scognet /* make room on the stack */ 120129198Scognet fp--; 121129198Scognet 122129198Scognet /* make the stack aligned */ 123135653Scognet fp = (struct sigframe *)STACKALIGN(fp); 124129198Scognet /* Populate the siginfo frame. */ 125129198Scognet frame.sf_si.si_signo = sig; 126129198Scognet frame.sf_si.si_code = code; 127129198Scognet frame.sf_uc.uc_sigmask = *mask; 128129198Scognet frame.sf_uc.uc_link = NULL; 129129198Scognet frame.sf_uc.uc_flags |= td->td_sigstk.ss_flags & SS_ONSTACK ? 130129198Scognet _UC_SETSTACK : _UC_CLRSTACK; 131135653Scognet frame.sf_uc.uc_stack = td->td_sigstk; 132129198Scognet memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack)); 133129198Scognet get_mcontext(td, &frame.sf_uc.uc_mcontext, 134129198Scognet (uint32_t)&frame.sf_uc.uc_flags); 135129198Scognet PROC_UNLOCK(td->td_proc); 136129198Scognet mtx_unlock(&psp->ps_mtx); 137129198Scognet if (copyout(&frame, (void*)fp, sizeof(frame)) != 0) 138129198Scognet sigexit(td, SIGILL); 139129198Scognet /* 140129198Scognet * Build context to run handler in. We invoke the handler 141129198Scognet * directly, only returning via the trampoline. Note the 142129198Scognet * trampoline version numbers are coordinated with machine- 143129198Scognet * dependent code in libc. 144129198Scognet */ 145129198Scognet 146129198Scognet tf->tf_r0 = sig; 147129198Scognet tf->tf_r1 = (int)&fp->sf_si; 148129198Scognet tf->tf_r2 = (int)&fp->sf_uc; 149129198Scognet 150129198Scognet /* the trampoline uses r5 as the uc address */ 151129198Scognet tf->tf_r5 = (int)&fp->sf_uc; 152129198Scognet tf->tf_pc = (int)catcher; 153129198Scognet tf->tf_usr_sp = (int)fp; 154135653Scognet tf->tf_usr_lr = (int)(PS_STRINGS - *(p->p_sysent->sv_szsigcode)); 155129198Scognet if (onstack) 156129198Scognet td->td_sigstk.ss_flags |= SS_ONSTACK; 157129198Scognet PROC_LOCK(td->td_proc); 158129198Scognet mtx_lock(&psp->ps_mtx); 159129198Scognet} 160129198Scognet 161129198Scognetstruct kva_md_info kmi; 162129198Scognet 163129198Scognet/* 164129198Scognet * arm32_vector_init: 165129198Scognet * 166129198Scognet * Initialize the vector page, and select whether or not to 167129198Scognet * relocate the vectors. 168129198Scognet * 169129198Scognet * NOTE: We expect the vector page to be mapped at its expected 170129198Scognet * destination. 171129198Scognet */ 172129198Scognet 173129198Scognetextern unsigned int page0[], page0_data[]; 174129198Scognetvoid 175129198Scognetarm_vector_init(vm_offset_t va, int which) 176129198Scognet{ 177129198Scognet unsigned int *vectors = (int *) va; 178129198Scognet unsigned int *vectors_data = vectors + (page0_data - page0); 179129198Scognet int vec; 180129198Scognet 181129198Scognet /* 182129198Scognet * Loop through the vectors we're taking over, and copy the 183129198Scognet * vector's insn and data word. 184129198Scognet */ 185129198Scognet for (vec = 0; vec < ARM_NVEC; vec++) { 186129198Scognet if ((which & (1 << vec)) == 0) { 187129198Scognet /* Don't want to take over this vector. */ 188129198Scognet continue; 189129198Scognet } 190129198Scognet vectors[vec] = page0[vec]; 191129198Scognet vectors_data[vec] = page0_data[vec]; 192129198Scognet } 193129198Scognet 194129198Scognet /* Now sync the vectors. */ 195129198Scognet cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int)); 196129198Scognet 197129198Scognet vector_page = va; 198129198Scognet 199129198Scognet if (va == ARM_VECTORS_HIGH) { 200129198Scognet /* 201129198Scognet * Assume the MD caller knows what it's doing here, and 202129198Scognet * really does want the vector page relocated. 203129198Scognet * 204129198Scognet * Note: This has to be done here (and not just in 205129198Scognet * cpu_setup()) because the vector page needs to be 206129198Scognet * accessible *before* cpu_startup() is called. 207129198Scognet * Think ddb(9) ... 208129198Scognet * 209129198Scognet * NOTE: If the CPU control register is not readable, 210129198Scognet * this will totally fail! We'll just assume that 211129198Scognet * any system that has high vector support has a 212129198Scognet * readable CPU control register, for now. If we 213129198Scognet * ever encounter one that does not, we'll have to 214129198Scognet * rethink this. 215129198Scognet */ 216129198Scognet cpu_control(CPU_CONTROL_VECRELOC, CPU_CONTROL_VECRELOC); 217129198Scognet } 218129198Scognet} 219129198Scognet 220129198Scognetstatic void 221129198Scognetcpu_startup(void *dummy) 222129198Scognet{ 223129198Scognet struct pcb *pcb = thread0.td_pcb; 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_update(pmap_kernel()); 233129198Scognet pmap_set_pcb_pagedir(pmap_kernel(), pcb); 234129198Scognet cpu_setup(""); 235129198Scognet identify_arm_cpu(); 236129198Scognet thread0.td_frame = (struct trapframe *)pcb->un_32.pcb32_sp - 1; 237129198Scognet} 238129198Scognet 239129198ScognetSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) 240129198Scognet 241129198Scognetvoid 242129198Scognetcpu_idle(void) 243129198Scognet{ 244129198Scognet} 245129198Scognet 246129198Scognetint 247129198Scognetfill_regs(struct thread *td, struct reg *regs) 248129198Scognet{ 249129198Scognet struct trapframe *tf = td->td_frame; 250129198Scognet bcopy(&tf->tf_r0, regs->r, sizeof(regs->r)); 251129198Scognet regs->r_sp = tf->tf_usr_sp; 252129198Scognet regs->r_lr = tf->tf_usr_lr; 253129198Scognet regs->r_pc = tf->tf_pc; 254129198Scognet regs->r_cpsr = tf->tf_spsr; 255129198Scognet return (0); 256129198Scognet} 257129198Scognetint 258129198Scognetfill_fpregs(struct thread *td, struct fpreg *regs) 259129198Scognet{ 260129198Scognet bzero(regs, sizeof(*regs)); 261129198Scognet return (0); 262129198Scognet} 263129198Scognet 264129198Scognetint 265129198Scognetset_regs(struct thread *td, struct reg *regs) 266129198Scognet{ 267129198Scognet struct trapframe *tf = td->td_frame; 268129198Scognet 269129198Scognet bcopy(regs->r, &tf->tf_r0, sizeof(*regs->r)); 270129198Scognet tf->tf_usr_sp = regs->r_sp; 271129198Scognet tf->tf_usr_lr = regs->r_lr; 272129198Scognet tf->tf_pc = regs->r_pc; 273129198Scognet tf->tf_spsr &= ~PSR_FLAGS; 274129198Scognet tf->tf_spsr |= regs->r_cpsr & PSR_FLAGS; 275129198Scognet return (0); 276129198Scognet} 277129198Scognet 278129198Scognetint 279129198Scognetset_fpregs(struct thread *td, struct fpreg *regs) 280129198Scognet{ 281129198Scognet return (0); 282129198Scognet} 283129198Scognet 284129198Scognetint 285129198Scognetfill_dbregs(struct thread *td, struct dbreg *regs) 286129198Scognet{ 287129198Scognet return (0); 288129198Scognet} 289129198Scognetint 290129198Scognetset_dbregs(struct thread *td, struct dbreg *regs) 291129198Scognet{ 292129198Scognet return (0); 293129198Scognet} 294129198Scognet 295129198Scognetint 296129198Scognetptrace_single_step(struct thread *td) 297129198Scognet{ 298132474Scognet /* XXX */ 299129198Scognet return (0); 300129198Scognet} 301129198Scognet 302129198Scognetint 303132474Scognetptrace_clear_single_step(struct thread *td) 304132474Scognet{ 305132474Scognet /* XXX */ 306132474Scognet return (0); 307132474Scognet} 308132474Scognet 309132474Scognetint 310129198Scognetptrace_set_pc(struct thread *td, unsigned long addr) 311129198Scognet{ 312132474Scognet td->td_frame->tf_pc = addr; 313129198Scognet return (0); 314129198Scognet} 315129198Scognet 316129198Scognetvoid 317129198Scognetcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) 318129198Scognet{ 319129198Scognet} 320129198Scognet 321129198Scognet/* 322129198Scognet * Clear registers on exec 323129198Scognet */ 324129198Scognetvoid 325129198Scognetexec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) 326129198Scognet{ 327129198Scognet struct trapframe *tf = td->td_frame; 328129198Scognet 329129198Scognet memset(tf, 0, sizeof(*tf)); 330129198Scognet tf->tf_usr_sp = stack; 331129198Scognet tf->tf_usr_lr = entry; 332129198Scognet tf->tf_svc_lr = 0x77777777; 333129198Scognet tf->tf_pc = entry; 334129198Scognet tf->tf_spsr = PSR_USR32_MODE; 335129198Scognet} 336129198Scognet 337129198Scognet/* 338129198Scognet * Build siginfo_t for SA thread 339129198Scognet */ 340129198Scognetvoid 341129198Scognetcpu_thread_siginfo(int sig, u_long code, siginfo_t *si) 342129198Scognet{ 343129198Scognet printf("cpu_thread_siginfo\n"); 344129198Scognet} 345129198Scognet 346129198Scognet/* 347129198Scognet * Get machine context. 348129198Scognet */ 349129198Scognetint 350129198Scognetget_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret) 351129198Scognet{ 352129198Scognet struct trapframe *tf = td->td_frame; 353129198Scognet __greg_t *gr = mcp->__gregs; 354129198Scognet 355129198Scognet /* Save General Register context. */ 356129198Scognet gr[_REG_R0] = tf->tf_r0; 357129198Scognet gr[_REG_R1] = tf->tf_r1; 358129198Scognet gr[_REG_R2] = tf->tf_r2; 359129198Scognet gr[_REG_R3] = tf->tf_r3; 360129198Scognet gr[_REG_R4] = tf->tf_r4; 361129198Scognet gr[_REG_R5] = tf->tf_r5; 362129198Scognet gr[_REG_R6] = tf->tf_r6; 363129198Scognet gr[_REG_R7] = tf->tf_r7; 364129198Scognet gr[_REG_R8] = tf->tf_r8; 365129198Scognet gr[_REG_R9] = tf->tf_r9; 366129198Scognet gr[_REG_R10] = tf->tf_r10; 367129198Scognet gr[_REG_R11] = tf->tf_r11; 368129198Scognet gr[_REG_R12] = tf->tf_r12; 369129198Scognet gr[_REG_SP] = tf->tf_usr_sp; 370129198Scognet gr[_REG_LR] = tf->tf_usr_lr; 371129198Scognet gr[_REG_PC] = tf->tf_pc; 372129198Scognet gr[_REG_CPSR] = tf->tf_spsr; 373129198Scognet 374129198Scognet return (0); 375129198Scognet} 376129198Scognet 377129198Scognet/* 378129198Scognet * Set machine context. 379129198Scognet * 380129198Scognet * However, we don't set any but the user modifiable flags, and we won't 381129198Scognet * touch the cs selector. 382129198Scognet */ 383129198Scognetint 384129198Scognetset_mcontext(struct thread *td, const mcontext_t *mcp) 385129198Scognet{ 386129198Scognet panic("SET_MCONTEXT AHAHAH\n"); 387129198Scognet return (0); 388129198Scognet} 389129198Scognet 390129198Scognet/* 391129198Scognet * MPSAFE 392129198Scognet */ 393129198Scognetint 394129198Scognetsigreturn(td, uap) 395129198Scognet struct thread *td; 396129198Scognet struct sigreturn_args /* { 397129198Scognet const __ucontext *sigcntxp; 398129198Scognet } */ *uap; 399129198Scognet{ 400135653Scognet struct proc *p = td->td_proc; 401135653Scognet struct sigframe sf; 402135653Scognet struct trapframe *tf; 403135653Scognet int spsr; 404135653Scognet 405135653Scognet if (uap == NULL) 406135653Scognet return (EFAULT); 407135653Scognet if (copyin(uap->sigcntxp, &sf, sizeof(sf))) 408135653Scognet return (EFAULT); 409135653Scognet /* 410135653Scognet * Make sure the processor mode has not been tampered with and 411135653Scognet * interrupts have not been disabled. 412135653Scognet */ 413135653Scognet spsr = sf.sf_uc.uc_mcontext.__gregs[_REG_CPSR]; 414135653Scognet if ((spsr & PSR_MODE) != PSR_USR32_MODE || 415135653Scognet (spsr & (I32_bit | F32_bit)) != 0) 416135653Scognet return (EINVAL); 417135653Scognet /* Restore register context. */ 418135653Scognet tf = td->td_frame; 419135653Scognet memcpy((register_t *)tf + 1, &sf.sf_uc.uc_mcontext, sizeof(*tf) - 420135653Scognet 4 * sizeof(register_t)); 421135653Scognet#if 0 422135653Scognet tf->tf_r0 = context.sc_r0; 423135653Scognet tf->tf_r1 = context.sc_r1; 424135653Scognet tf->tf_r2 = context.sc_r2; 425135653Scognet tf->tf_r3 = context.sc_r3; 426135653Scognet tf->tf_r4 = context.sc_r4; 427135653Scognet tf->tf_r5 = context.sc_r5; 428135653Scognet tf->tf_r6 = context.sc_r6; 429135653Scognet tf->tf_r7 = context.sc_r7; 430135653Scognet tf->tf_r8 = context.sc_r8; 431135653Scognet tf->tf_r9 = context.sc_r9; 432135653Scognet tf->tf_r10 = context.sc_r10; 433135653Scognet tf->tf_r11 = context.sc_r11; 434135653Scognet tf->tf_r12 = context.sc_r12; 435135653Scognet tf->tf_usr_sp = context.sc_usr_sp; 436135653Scognet tf->tf_usr_lr = context.sc_usr_lr; 437135653Scognet tf->tf_svc_lr = context.sc_svc_lr; 438135653Scognet tf->tf_pc = context.sc_pc; 439135653Scognet#endif 440135653Scognet tf->tf_pc = sf.sf_uc.uc_mcontext.__gregs[_REG_PC]; 441135653Scognet tf->tf_spsr = spsr; 442135653Scognet 443135653Scognet /* Restore signal stack. */ 444135653Scognet if (sf.sf_uc.uc_flags & _UC_SETSTACK) 445135653Scognet td->td_sigstk.ss_flags |= SS_ONSTACK; 446135653Scognet else 447135653Scognet td->td_sigstk.ss_flags &= ~SS_ONSTACK; 448135653Scognet 449135653Scognet /* Restore signal mask. */ 450135653Scognet PROC_LOCK(p); 451135653Scognet td->td_sigmask = sf.sf_uc.uc_sigmask; 452135653Scognet SIG_CANTMASK(td->td_sigmask); 453135653Scognet signotify(td); 454135653Scognet PROC_UNLOCK(p); 455135653Scognet 456135653Scognet return (EJUSTRETURN); 457129198Scognet} 458129198Scognet 459129198Scognet 460132054Scognet/* 461132054Scognet * Construct a PCB from a trapframe. This is called from kdb_trap() where 462132054Scognet * we want to start a backtrace from the function that caused us to enter 463132054Scognet * the debugger. We have the context in the trapframe, but base the trace 464132054Scognet * on the PCB. The PCB doesn't have to be perfect, as long as it contains 465132054Scognet * enough for a backtrace. 466132054Scognet */ 467132054Scognetvoid 468132054Scognetmakectx(struct trapframe *tf, struct pcb *pcb) 469132054Scognet{ 470132054Scognet pcb->un_32.pcb32_r8 = tf->tf_r8; 471132054Scognet pcb->un_32.pcb32_r9 = tf->tf_r9; 472132054Scognet pcb->un_32.pcb32_r10 = tf->tf_r10; 473132054Scognet pcb->un_32.pcb32_r11 = tf->tf_r11; 474132054Scognet pcb->un_32.pcb32_r12 = tf->tf_r12; 475132054Scognet pcb->un_32.pcb32_pc = tf->tf_pc; 476132054Scognet pcb->un_32.pcb32_lr = tf->tf_usr_lr; 477132054Scognet pcb->un_32.pcb32_sp = tf->tf_usr_sp; 478132054Scognet} 479