machdep_kdb.c revision 132054
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 132054 2004-07-12 21:19:43Z 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> 66129198Scognet#include <machine/reg.h> 67129198Scognet#include <machine/cpu.h> 68129198Scognet 69129198Scognet#include <vm/vm.h> 70129198Scognet#include <vm/pmap.h> 71129198Scognet#include <vm/vm.h> 72129198Scognet#include <vm/vm_object.h> 73129198Scognet#include <vm/vm_page.h> 74129198Scognet#include <vm/vm_pager.h> 75129198Scognet#include <vm/vm_map.h> 76129198Scognet#include <vm/vnode_pager.h> 77129198Scognet#include <machine/pmap.h> 78129198Scognet#include <machine/vmparam.h> 79129198Scognet#include <machine/pcb.h> 80129198Scognet#include <machine/undefined.h> 81129198Scognet#include <machine/machdep.h> 82129198Scognet#include <machine/metadata.h> 83129198Scognet#include <machine/armreg.h> 84129198Scognet 85129198Scognet#define MDROOT_ADDR 0xd0400000 86129198Scognet 87129198Scognetuint32_t cpu_reset_address = 0; 88129198Scognetint cold = 1; 89129198Scognetint astpending = 0; 90129198Scognetvm_offset_t vector_page; 91129198Scognet 92129198Scognetstatic void * 93129198Scognetgetframe(struct thread *td, int sig, int *onstack) 94129198Scognet{ 95129198Scognet struct trapframe *tf = td->td_frame; 96129198Scognet 97129198Scognet *onstack = sigonstack(tf->tf_usr_sp); 98129198Scognet if (*onstack) 99129198Scognet return (void*)(td->td_sigstk.ss_sp + td->td_sigstk.ss_size); 100129198Scognet return (void*)(tf->tf_usr_sp); 101129198Scognet} 102129198Scognet 103129198Scognetvoid 104129198Scognetsendsig(catcher, sig, mask, code) 105129198Scognet sig_t catcher; 106129198Scognet int sig; 107129198Scognet sigset_t *mask; 108129198Scognet u_long code; 109129198Scognet{ 110129198Scognet struct thread *td = curthread; 111129198Scognet struct trapframe *tf = td->td_frame; 112129198Scognet struct sigframe *fp, frame; 113129198Scognet struct sigacts *psp = td->td_proc->p_sigacts; 114129198Scognet int onstack; 115129198Scognet 116129198Scognet fp = getframe(td, sig, &onstack); 117129198Scognet /* make room on the stack */ 118129198Scognet fp--; 119129198Scognet 120129198Scognet /* make the stack aligned */ 121129198Scognet (u_int)fp = _ALIGN(fp); 122129198Scognet /* Populate the siginfo frame. */ 123129198Scognet frame.sf_si.si_signo = sig; 124129198Scognet frame.sf_si.si_code = code; 125129198Scognet frame.sf_uc.uc_sigmask = *mask; 126129198Scognet frame.sf_uc.uc_link = NULL; 127129198Scognet frame.sf_uc.uc_flags |= td->td_sigstk.ss_flags & SS_ONSTACK ? 128129198Scognet _UC_SETSTACK : _UC_CLRSTACK; 129129198Scognet memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack)); 130129198Scognet get_mcontext(td, &frame.sf_uc.uc_mcontext, 131129198Scognet (uint32_t)&frame.sf_uc.uc_flags); 132129198Scognet PROC_UNLOCK(td->td_proc); 133129198Scognet mtx_unlock(&psp->ps_mtx); 134129198Scognet if (copyout(&frame, (void*)fp, sizeof(frame)) != 0) 135129198Scognet sigexit(td, SIGILL); 136129198Scognet /* 137129198Scognet * Build context to run handler in. We invoke the handler 138129198Scognet * directly, only returning via the trampoline. Note the 139129198Scognet * trampoline version numbers are coordinated with machine- 140129198Scognet * dependent code in libc. 141129198Scognet */ 142129198Scognet 143129198Scognet tf->tf_r0 = sig; 144129198Scognet tf->tf_r1 = (int)&fp->sf_si; 145129198Scognet tf->tf_r2 = (int)&fp->sf_uc; 146129198Scognet 147129198Scognet /* the trampoline uses r5 as the uc address */ 148129198Scognet tf->tf_r5 = (int)&fp->sf_uc; 149129198Scognet tf->tf_pc = (int)catcher; 150129198Scognet tf->tf_usr_sp = (int)fp; 151129198Scognet if (onstack) 152129198Scognet td->td_sigstk.ss_flags |= SS_ONSTACK; 153129198Scognet PROC_LOCK(td->td_proc); 154129198Scognet mtx_lock(&psp->ps_mtx); 155129198Scognet} 156129198Scognet 157129198Scognetstruct kva_md_info kmi; 158129198Scognet 159129198Scognet/* 160129198Scognet * arm32_vector_init: 161129198Scognet * 162129198Scognet * Initialize the vector page, and select whether or not to 163129198Scognet * relocate the vectors. 164129198Scognet * 165129198Scognet * NOTE: We expect the vector page to be mapped at its expected 166129198Scognet * destination. 167129198Scognet */ 168129198Scognet 169129198Scognetextern unsigned int page0[], page0_data[]; 170129198Scognetvoid 171129198Scognetarm_vector_init(vm_offset_t va, int which) 172129198Scognet{ 173129198Scognet unsigned int *vectors = (int *) va; 174129198Scognet unsigned int *vectors_data = vectors + (page0_data - page0); 175129198Scognet int vec; 176129198Scognet 177129198Scognet /* 178129198Scognet * Loop through the vectors we're taking over, and copy the 179129198Scognet * vector's insn and data word. 180129198Scognet */ 181129198Scognet for (vec = 0; vec < ARM_NVEC; vec++) { 182129198Scognet if ((which & (1 << vec)) == 0) { 183129198Scognet /* Don't want to take over this vector. */ 184129198Scognet continue; 185129198Scognet } 186129198Scognet vectors[vec] = page0[vec]; 187129198Scognet vectors_data[vec] = page0_data[vec]; 188129198Scognet } 189129198Scognet 190129198Scognet /* Now sync the vectors. */ 191129198Scognet cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int)); 192129198Scognet 193129198Scognet vector_page = va; 194129198Scognet 195129198Scognet if (va == ARM_VECTORS_HIGH) { 196129198Scognet /* 197129198Scognet * Assume the MD caller knows what it's doing here, and 198129198Scognet * really does want the vector page relocated. 199129198Scognet * 200129198Scognet * Note: This has to be done here (and not just in 201129198Scognet * cpu_setup()) because the vector page needs to be 202129198Scognet * accessible *before* cpu_startup() is called. 203129198Scognet * Think ddb(9) ... 204129198Scognet * 205129198Scognet * NOTE: If the CPU control register is not readable, 206129198Scognet * this will totally fail! We'll just assume that 207129198Scognet * any system that has high vector support has a 208129198Scognet * readable CPU control register, for now. If we 209129198Scognet * ever encounter one that does not, we'll have to 210129198Scognet * rethink this. 211129198Scognet */ 212129198Scognet cpu_control(CPU_CONTROL_VECRELOC, CPU_CONTROL_VECRELOC); 213129198Scognet } 214129198Scognet} 215129198Scognet 216129198Scognetstatic void 217129198Scognetcpu_startup(void *dummy) 218129198Scognet{ 219129198Scognet struct pcb *pcb = thread0.td_pcb; 220129198Scognet vm_ksubmap_init(&kmi); 221129198Scognet bufinit(); 222129198Scognet vm_pager_bufferinit(); 223129198Scognet pcb->un_32.pcb32_und_sp = (u_int)thread0.td_kstack + 224129198Scognet USPACE_UNDEF_STACK_TOP; 225129198Scognet pcb->un_32.pcb32_sp = (u_int)thread0.td_kstack + 226129198Scognet USPACE_SVC_STACK_TOP; 227129198Scognet vector_page_setprot(VM_PROT_READ); 228129198Scognet pmap_update(pmap_kernel()); 229129198Scognet pmap_set_pcb_pagedir(pmap_kernel(), pcb); 230129198Scognet cpu_setup(""); 231129198Scognet identify_arm_cpu(); 232129198Scognet thread0.td_frame = (struct trapframe *)pcb->un_32.pcb32_sp - 1; 233129198Scognet} 234129198Scognet 235129198ScognetSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) 236129198Scognet 237129198Scognetvoid 238129198Scognetcpu_idle(void) 239129198Scognet{ 240129198Scognet} 241129198Scognet 242129198Scognetint 243129198Scognetfill_regs(struct thread *td, struct reg *regs) 244129198Scognet{ 245129198Scognet struct trapframe *tf = td->td_frame; 246129198Scognet bcopy(&tf->tf_r0, regs->r, sizeof(regs->r)); 247129198Scognet regs->r_sp = tf->tf_usr_sp; 248129198Scognet regs->r_lr = tf->tf_usr_lr; 249129198Scognet regs->r_pc = tf->tf_pc; 250129198Scognet regs->r_cpsr = tf->tf_spsr; 251129198Scognet return (0); 252129198Scognet} 253129198Scognetint 254129198Scognetfill_fpregs(struct thread *td, struct fpreg *regs) 255129198Scognet{ 256129198Scognet bzero(regs, sizeof(*regs)); 257129198Scognet return (0); 258129198Scognet} 259129198Scognet 260129198Scognetint 261129198Scognetset_regs(struct thread *td, struct reg *regs) 262129198Scognet{ 263129198Scognet struct trapframe *tf = td->td_frame; 264129198Scognet 265129198Scognet bcopy(regs->r, &tf->tf_r0, sizeof(*regs->r)); 266129198Scognet tf->tf_usr_sp = regs->r_sp; 267129198Scognet tf->tf_usr_lr = regs->r_lr; 268129198Scognet tf->tf_pc = regs->r_pc; 269129198Scognet tf->tf_spsr &= ~PSR_FLAGS; 270129198Scognet tf->tf_spsr |= regs->r_cpsr & PSR_FLAGS; 271129198Scognet while(1); 272129198Scognet return (0); 273129198Scognet} 274129198Scognet 275129198Scognetint 276129198Scognetset_fpregs(struct thread *td, struct fpreg *regs) 277129198Scognet{ 278129198Scognet return (0); 279129198Scognet} 280129198Scognet 281129198Scognetint 282129198Scognetfill_dbregs(struct thread *td, struct dbreg *regs) 283129198Scognet{ 284129198Scognet return (0); 285129198Scognet} 286129198Scognetint 287129198Scognetset_dbregs(struct thread *td, struct dbreg *regs) 288129198Scognet{ 289129198Scognet return (0); 290129198Scognet} 291129198Scognet 292129198Scognetvoid 293129198Scognetcpu_halt(void) 294129198Scognet{ 295129198Scognet cpu_reset(); 296129198Scognet} 297129198Scognet 298129198Scognetint 299129198Scognetptrace_single_step(struct thread *td) 300129198Scognet{ 301129198Scognet return (0); 302129198Scognet} 303129198Scognet 304129198Scognetint 305129198Scognetptrace_set_pc(struct thread *td, unsigned long addr) 306129198Scognet{ 307129198Scognet return (0); 308129198Scognet} 309129198Scognet 310129198Scognetvoid 311129198Scognetcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) 312129198Scognet{ 313129198Scognet} 314129198Scognet 315129198Scognet/* 316129198Scognet * Clear registers on exec 317129198Scognet */ 318129198Scognetvoid 319129198Scognetexec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) 320129198Scognet{ 321129198Scognet struct trapframe *tf = td->td_frame; 322129198Scognet 323129198Scognet memset(tf, 0, sizeof(*tf)); 324129198Scognet tf->tf_usr_sp = stack; 325129198Scognet tf->tf_usr_lr = entry; 326129198Scognet tf->tf_svc_lr = 0x77777777; 327129198Scognet tf->tf_pc = entry; 328129198Scognet tf->tf_spsr = PSR_USR32_MODE; 329129198Scognet} 330129198Scognet 331129198Scognet/* 332129198Scognet * Build siginfo_t for SA thread 333129198Scognet */ 334129198Scognetvoid 335129198Scognetcpu_thread_siginfo(int sig, u_long code, siginfo_t *si) 336129198Scognet{ 337129198Scognet printf("cpu_thread_siginfo\n"); 338129198Scognet} 339129198Scognet 340129198Scognet/* 341129198Scognet * Get machine context. 342129198Scognet */ 343129198Scognetint 344129198Scognetget_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret) 345129198Scognet{ 346129198Scognet struct trapframe *tf = td->td_frame; 347129198Scognet __greg_t *gr = mcp->__gregs; 348129198Scognet 349129198Scognet /* Save General Register context. */ 350129198Scognet gr[_REG_R0] = tf->tf_r0; 351129198Scognet gr[_REG_R1] = tf->tf_r1; 352129198Scognet gr[_REG_R2] = tf->tf_r2; 353129198Scognet gr[_REG_R3] = tf->tf_r3; 354129198Scognet gr[_REG_R4] = tf->tf_r4; 355129198Scognet gr[_REG_R5] = tf->tf_r5; 356129198Scognet gr[_REG_R6] = tf->tf_r6; 357129198Scognet gr[_REG_R7] = tf->tf_r7; 358129198Scognet gr[_REG_R8] = tf->tf_r8; 359129198Scognet gr[_REG_R9] = tf->tf_r9; 360129198Scognet gr[_REG_R10] = tf->tf_r10; 361129198Scognet gr[_REG_R11] = tf->tf_r11; 362129198Scognet gr[_REG_R12] = tf->tf_r12; 363129198Scognet gr[_REG_SP] = tf->tf_usr_sp; 364129198Scognet gr[_REG_LR] = tf->tf_usr_lr; 365129198Scognet gr[_REG_PC] = tf->tf_pc; 366129198Scognet gr[_REG_CPSR] = tf->tf_spsr; 367129198Scognet 368129198Scognet return (0); 369129198Scognet} 370129198Scognet 371129198Scognet/* 372129198Scognet * Set machine context. 373129198Scognet * 374129198Scognet * However, we don't set any but the user modifiable flags, and we won't 375129198Scognet * touch the cs selector. 376129198Scognet */ 377129198Scognetint 378129198Scognetset_mcontext(struct thread *td, const mcontext_t *mcp) 379129198Scognet{ 380129198Scognet panic("SET_MCONTEXT AHAHAH\n"); 381129198Scognet return (0); 382129198Scognet} 383129198Scognet 384129198Scognet#ifdef COMPAT_FREEBSD4 385129198Scognetint 386129198Scognetfreebsd4_sigreturn(td, uap) 387129198Scognet struct thread *td; 388129198Scognet struct freebsd4_sigreturn_args /* { 389129198Scognet const ucontext4 *sigcntxp; 390129198Scognet } */ *uap; 391129198Scognet{ 392129198Scognet return (0); 393129198Scognet} 394129198Scognet#endif 395129198Scognet 396129198Scognet/* 397129198Scognet * MPSAFE 398129198Scognet */ 399129198Scognetint 400129198Scognetsigreturn(td, uap) 401129198Scognet struct thread *td; 402129198Scognet struct sigreturn_args /* { 403129198Scognet const __ucontext *sigcntxp; 404129198Scognet } */ *uap; 405129198Scognet{ 406129198Scognet return (0); 407129198Scognet} 408129198Scognet 409129198Scognet 410132054Scognet/* 411132054Scognet * Construct a PCB from a trapframe. This is called from kdb_trap() where 412132054Scognet * we want to start a backtrace from the function that caused us to enter 413132054Scognet * the debugger. We have the context in the trapframe, but base the trace 414132054Scognet * on the PCB. The PCB doesn't have to be perfect, as long as it contains 415132054Scognet * enough for a backtrace. 416132054Scognet */ 417132054Scognetvoid 418132054Scognetmakectx(struct trapframe *tf, struct pcb *pcb) 419132054Scognet{ 420132054Scognet pcb->un_32.pcb32_r8 = tf->tf_r8; 421132054Scognet pcb->un_32.pcb32_r9 = tf->tf_r9; 422132054Scognet pcb->un_32.pcb32_r10 = tf->tf_r10; 423132054Scognet pcb->un_32.pcb32_r11 = tf->tf_r11; 424132054Scognet pcb->un_32.pcb32_r12 = tf->tf_r12; 425132054Scognet pcb->un_32.pcb32_pc = tf->tf_pc; 426132054Scognet pcb->un_32.pcb32_lr = tf->tf_usr_lr; 427132054Scognet pcb->un_32.pcb32_sp = tf->tf_usr_sp; 428132054Scognet} 429