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