machdep.c revision 132473
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 132473 2004-07-20 22:39:56Z cognet $"); 48 49#include <sys/param.h> 50#include <sys/systm.h> 51#include <sys/sysproto.h> 52#include <sys/signalvar.h> 53#include <sys/imgact.h> 54#include <sys/kernel.h> 55#include <sys/linker.h> 56#include <sys/lock.h> 57#include <sys/malloc.h> 58#include <sys/mutex.h> 59#include <sys/pcpu.h> 60#include <sys/proc.h> 61#include <sys/ptrace.h> 62#include <sys/cons.h> 63#include <sys/bio.h> 64#include <sys/buf.h> 65#include <sys/exec.h> 66#include <machine/reg.h> 67#include <machine/cpu.h> 68 69#include <vm/vm.h> 70#include <vm/pmap.h> 71#include <vm/vm.h> 72#include <vm/vm_object.h> 73#include <vm/vm_page.h> 74#include <vm/vm_pager.h> 75#include <vm/vm_map.h> 76#include <vm/vnode_pager.h> 77#include <machine/pmap.h> 78#include <machine/vmparam.h> 79#include <machine/pcb.h> 80#include <machine/undefined.h> 81#include <machine/machdep.h> 82#include <machine/metadata.h> 83#include <machine/armreg.h> 84 85#define MDROOT_ADDR 0xd0400000 86 87uint32_t cpu_reset_address = 0; 88int cold = 1; 89vm_offset_t vector_page; 90 91static void * 92getframe(struct thread *td, int sig, int *onstack) 93{ 94 struct trapframe *tf = td->td_frame; 95 96 *onstack = sigonstack(tf->tf_usr_sp); 97 if (*onstack) 98 return (void*)(td->td_sigstk.ss_sp + td->td_sigstk.ss_size); 99 return (void*)(tf->tf_usr_sp); 100} 101 102void 103sendsig(catcher, sig, mask, code) 104 sig_t catcher; 105 int sig; 106 sigset_t *mask; 107 u_long code; 108{ 109 struct thread *td = curthread; 110 struct trapframe *tf = td->td_frame; 111 struct sigframe *fp, frame; 112 struct sigacts *psp = td->td_proc->p_sigacts; 113 int onstack; 114 115 fp = getframe(td, sig, &onstack); 116 /* make room on the stack */ 117 fp--; 118 119 /* make the stack aligned */ 120 (u_int)fp = _ALIGN(fp); 121 /* Populate the siginfo frame. */ 122 frame.sf_si.si_signo = sig; 123 frame.sf_si.si_code = code; 124 frame.sf_uc.uc_sigmask = *mask; 125 frame.sf_uc.uc_link = NULL; 126 frame.sf_uc.uc_flags |= td->td_sigstk.ss_flags & SS_ONSTACK ? 127 _UC_SETSTACK : _UC_CLRSTACK; 128 memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack)); 129 get_mcontext(td, &frame.sf_uc.uc_mcontext, 130 (uint32_t)&frame.sf_uc.uc_flags); 131 PROC_UNLOCK(td->td_proc); 132 mtx_unlock(&psp->ps_mtx); 133 if (copyout(&frame, (void*)fp, sizeof(frame)) != 0) 134 sigexit(td, SIGILL); 135 /* 136 * Build context to run handler in. We invoke the handler 137 * directly, only returning via the trampoline. Note the 138 * trampoline version numbers are coordinated with machine- 139 * dependent code in libc. 140 */ 141 142 tf->tf_r0 = sig; 143 tf->tf_r1 = (int)&fp->sf_si; 144 tf->tf_r2 = (int)&fp->sf_uc; 145 146 /* the trampoline uses r5 as the uc address */ 147 tf->tf_r5 = (int)&fp->sf_uc; 148 tf->tf_pc = (int)catcher; 149 tf->tf_usr_sp = (int)fp; 150 if (onstack) 151 td->td_sigstk.ss_flags |= SS_ONSTACK; 152 PROC_LOCK(td->td_proc); 153 mtx_lock(&psp->ps_mtx); 154} 155 156struct kva_md_info kmi; 157 158/* 159 * arm32_vector_init: 160 * 161 * Initialize the vector page, and select whether or not to 162 * relocate the vectors. 163 * 164 * NOTE: We expect the vector page to be mapped at its expected 165 * destination. 166 */ 167 168extern unsigned int page0[], page0_data[]; 169void 170arm_vector_init(vm_offset_t va, int which) 171{ 172 unsigned int *vectors = (int *) va; 173 unsigned int *vectors_data = vectors + (page0_data - page0); 174 int vec; 175 176 /* 177 * Loop through the vectors we're taking over, and copy the 178 * vector's insn and data word. 179 */ 180 for (vec = 0; vec < ARM_NVEC; vec++) { 181 if ((which & (1 << vec)) == 0) { 182 /* Don't want to take over this vector. */ 183 continue; 184 } 185 vectors[vec] = page0[vec]; 186 vectors_data[vec] = page0_data[vec]; 187 } 188 189 /* Now sync the vectors. */ 190 cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int)); 191 192 vector_page = va; 193 194 if (va == ARM_VECTORS_HIGH) { 195 /* 196 * Assume the MD caller knows what it's doing here, and 197 * really does want the vector page relocated. 198 * 199 * Note: This has to be done here (and not just in 200 * cpu_setup()) because the vector page needs to be 201 * accessible *before* cpu_startup() is called. 202 * Think ddb(9) ... 203 * 204 * NOTE: If the CPU control register is not readable, 205 * this will totally fail! We'll just assume that 206 * any system that has high vector support has a 207 * readable CPU control register, for now. If we 208 * ever encounter one that does not, we'll have to 209 * rethink this. 210 */ 211 cpu_control(CPU_CONTROL_VECRELOC, CPU_CONTROL_VECRELOC); 212 } 213} 214 215static void 216cpu_startup(void *dummy) 217{ 218 struct pcb *pcb = thread0.td_pcb; 219 vm_ksubmap_init(&kmi); 220 bufinit(); 221 vm_pager_bufferinit(); 222 pcb->un_32.pcb32_und_sp = (u_int)thread0.td_kstack + 223 USPACE_UNDEF_STACK_TOP; 224 pcb->un_32.pcb32_sp = (u_int)thread0.td_kstack + 225 USPACE_SVC_STACK_TOP; 226 vector_page_setprot(VM_PROT_READ); 227 pmap_update(pmap_kernel()); 228 pmap_set_pcb_pagedir(pmap_kernel(), pcb); 229 cpu_setup(""); 230 identify_arm_cpu(); 231 thread0.td_frame = (struct trapframe *)pcb->un_32.pcb32_sp - 1; 232} 233 234SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) 235 236void 237cpu_idle(void) 238{ 239} 240 241int 242fill_regs(struct thread *td, struct reg *regs) 243{ 244 struct trapframe *tf = td->td_frame; 245 bcopy(&tf->tf_r0, regs->r, sizeof(regs->r)); 246 regs->r_sp = tf->tf_usr_sp; 247 regs->r_lr = tf->tf_usr_lr; 248 regs->r_pc = tf->tf_pc; 249 regs->r_cpsr = tf->tf_spsr; 250 return (0); 251} 252int 253fill_fpregs(struct thread *td, struct fpreg *regs) 254{ 255 bzero(regs, sizeof(*regs)); 256 return (0); 257} 258 259int 260set_regs(struct thread *td, struct reg *regs) 261{ 262 struct trapframe *tf = td->td_frame; 263 264 bcopy(regs->r, &tf->tf_r0, sizeof(*regs->r)); 265 tf->tf_usr_sp = regs->r_sp; 266 tf->tf_usr_lr = regs->r_lr; 267 tf->tf_pc = regs->r_pc; 268 tf->tf_spsr &= ~PSR_FLAGS; 269 tf->tf_spsr |= regs->r_cpsr & PSR_FLAGS; 270 while(1); 271 return (0); 272} 273 274int 275set_fpregs(struct thread *td, struct fpreg *regs) 276{ 277 return (0); 278} 279 280int 281fill_dbregs(struct thread *td, struct dbreg *regs) 282{ 283 return (0); 284} 285int 286set_dbregs(struct thread *td, struct dbreg *regs) 287{ 288 return (0); 289} 290 291void 292cpu_halt(void) 293{ 294 cpu_reset(); 295} 296 297int 298ptrace_single_step(struct thread *td) 299{ 300 return (0); 301} 302 303int 304ptrace_set_pc(struct thread *td, unsigned long addr) 305{ 306 return (0); 307} 308 309void 310cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) 311{ 312} 313 314/* 315 * Clear registers on exec 316 */ 317void 318exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) 319{ 320 struct trapframe *tf = td->td_frame; 321 322 memset(tf, 0, sizeof(*tf)); 323 tf->tf_usr_sp = stack; 324 tf->tf_usr_lr = entry; 325 tf->tf_svc_lr = 0x77777777; 326 tf->tf_pc = entry; 327 tf->tf_spsr = PSR_USR32_MODE; 328} 329 330/* 331 * Build siginfo_t for SA thread 332 */ 333void 334cpu_thread_siginfo(int sig, u_long code, siginfo_t *si) 335{ 336 printf("cpu_thread_siginfo\n"); 337} 338 339/* 340 * Get machine context. 341 */ 342int 343get_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret) 344{ 345 struct trapframe *tf = td->td_frame; 346 __greg_t *gr = mcp->__gregs; 347 348 /* Save General Register context. */ 349 gr[_REG_R0] = tf->tf_r0; 350 gr[_REG_R1] = tf->tf_r1; 351 gr[_REG_R2] = tf->tf_r2; 352 gr[_REG_R3] = tf->tf_r3; 353 gr[_REG_R4] = tf->tf_r4; 354 gr[_REG_R5] = tf->tf_r5; 355 gr[_REG_R6] = tf->tf_r6; 356 gr[_REG_R7] = tf->tf_r7; 357 gr[_REG_R8] = tf->tf_r8; 358 gr[_REG_R9] = tf->tf_r9; 359 gr[_REG_R10] = tf->tf_r10; 360 gr[_REG_R11] = tf->tf_r11; 361 gr[_REG_R12] = tf->tf_r12; 362 gr[_REG_SP] = tf->tf_usr_sp; 363 gr[_REG_LR] = tf->tf_usr_lr; 364 gr[_REG_PC] = tf->tf_pc; 365 gr[_REG_CPSR] = tf->tf_spsr; 366 367 return (0); 368} 369 370/* 371 * Set machine context. 372 * 373 * However, we don't set any but the user modifiable flags, and we won't 374 * touch the cs selector. 375 */ 376int 377set_mcontext(struct thread *td, const mcontext_t *mcp) 378{ 379 panic("SET_MCONTEXT AHAHAH\n"); 380 return (0); 381} 382 383#ifdef COMPAT_FREEBSD4 384int 385freebsd4_sigreturn(td, uap) 386 struct thread *td; 387 struct freebsd4_sigreturn_args /* { 388 const ucontext4 *sigcntxp; 389 } */ *uap; 390{ 391 return (0); 392} 393#endif 394 395/* 396 * MPSAFE 397 */ 398int 399sigreturn(td, uap) 400 struct thread *td; 401 struct sigreturn_args /* { 402 const __ucontext *sigcntxp; 403 } */ *uap; 404{ 405 return (0); 406} 407 408 409/* 410 * Construct a PCB from a trapframe. This is called from kdb_trap() where 411 * we want to start a backtrace from the function that caused us to enter 412 * the debugger. We have the context in the trapframe, but base the trace 413 * on the PCB. The PCB doesn't have to be perfect, as long as it contains 414 * enough for a backtrace. 415 */ 416void 417makectx(struct trapframe *tf, struct pcb *pcb) 418{ 419 pcb->un_32.pcb32_r8 = tf->tf_r8; 420 pcb->un_32.pcb32_r9 = tf->tf_r9; 421 pcb->un_32.pcb32_r10 = tf->tf_r10; 422 pcb->un_32.pcb32_r11 = tf->tf_r11; 423 pcb->un_32.pcb32_r12 = tf->tf_r12; 424 pcb->un_32.pcb32_pc = tf->tf_pc; 425 pcb->un_32.pcb32_lr = tf->tf_usr_lr; 426 pcb->un_32.pcb32_sp = tf->tf_usr_sp; 427} 428