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