machdep.c revision 141237
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 141237 2005-02-04 05:32:56Z njl $"); 48 49#include <sys/param.h> 50#include <sys/systm.h> 51#include <sys/cpu.h> 52#include <sys/sysproto.h> 53#include <sys/signalvar.h> 54#include <sys/imgact.h> 55#include <sys/kernel.h> 56#include <sys/linker.h> 57#include <sys/lock.h> 58#include <sys/malloc.h> 59#include <sys/mutex.h> 60#include <sys/pcpu.h> 61#include <sys/proc.h> 62#include <sys/ptrace.h> 63#include <sys/cons.h> 64#include <sys/bio.h> 65#include <sys/buf.h> 66#include <sys/exec.h> 67#include <sys/sysent.h> 68#include <sys/uio.h> 69#include <machine/reg.h> 70#include <machine/cpu.h> 71#include <machine/trap.h> 72 73#include <vm/vm.h> 74#include <vm/pmap.h> 75#include <vm/vm.h> 76#include <vm/vm_object.h> 77#include <vm/vm_page.h> 78#include <vm/vm_pager.h> 79#include <vm/vm_map.h> 80#include <vm/vnode_pager.h> 81#include <machine/pmap.h> 82#include <machine/vmparam.h> 83#include <machine/pcb.h> 84#include <machine/undefined.h> 85#include <machine/machdep.h> 86#include <machine/metadata.h> 87#include <machine/armreg.h> 88#include <machine/md_var.h> 89 90#define MDROOT_ADDR 0xd0400000 91 92uint32_t cpu_reset_address = 0; 93int cold = 1; 94vm_offset_t vector_page; 95 96void 97sendsig(catcher, sig, mask, code) 98 sig_t catcher; 99 int sig; 100 sigset_t *mask; 101 u_long code; 102{ 103 struct thread *td = curthread; 104 struct proc *p = td->td_proc; 105 struct trapframe *tf = td->td_frame; 106 struct sigframe *fp, frame; 107 struct sigacts *psp = td->td_proc->p_sigacts; 108 int onstack; 109 110 onstack = sigonstack(td->td_frame->tf_usr_sp); 111 112 if ((td->td_flags & TDP_ALTSTACK) && 113 !(onstack) && 114 SIGISMEMBER(td->td_proc->p_sigacts->ps_sigonstack, sig)) { 115 fp = (void*)(td->td_sigstk.ss_sp + td->td_sigstk.ss_size); 116 td->td_sigstk.ss_flags |= SS_ONSTACK; 117 } else 118 fp = (void*)td->td_frame->tf_usr_sp; 119 120 /* make room on the stack */ 121 fp--; 122 123 /* make the stack aligned */ 124 fp = (struct sigframe *)STACKALIGN(fp); 125 /* Populate the siginfo frame. */ 126 frame.sf_si.si_signo = sig; 127 frame.sf_si.si_code = code; 128 frame.sf_uc.uc_sigmask = *mask; 129 frame.sf_uc.uc_link = NULL; 130 frame.sf_uc.uc_flags = (td->td_pflags & TDP_ALTSTACK ) 131 ? ((onstack) ? SS_ONSTACK : 0) : SS_DISABLE; 132 frame.sf_uc.uc_stack = td->td_sigstk; 133 memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack)); 134 get_mcontext(td, &frame.sf_uc.uc_mcontext, 0); 135 PROC_UNLOCK(td->td_proc); 136 mtx_unlock(&psp->ps_mtx); 137 if (copyout(&frame, (void*)fp, sizeof(frame)) != 0) 138 sigexit(td, SIGILL); 139 /* 140 * Build context to run handler in. We invoke the handler 141 * directly, only returning via the trampoline. Note the 142 * trampoline version numbers are coordinated with machine- 143 * dependent code in libc. 144 */ 145 146 tf->tf_r0 = sig; 147 tf->tf_r1 = (int)&fp->sf_si; 148 tf->tf_r2 = (int)&fp->sf_uc; 149 150 /* the trampoline uses r5 as the uc address */ 151 tf->tf_r5 = (int)&fp->sf_uc; 152 tf->tf_pc = (int)catcher; 153 tf->tf_usr_sp = (int)fp; 154 tf->tf_usr_lr = (int)(PS_STRINGS - *(p->p_sysent->sv_szsigcode)); 155 PROC_LOCK(td->td_proc); 156 mtx_lock(&psp->ps_mtx); 157} 158 159struct kva_md_info kmi; 160 161/* 162 * arm32_vector_init: 163 * 164 * Initialize the vector page, and select whether or not to 165 * relocate the vectors. 166 * 167 * NOTE: We expect the vector page to be mapped at its expected 168 * destination. 169 */ 170 171extern unsigned int page0[], page0_data[]; 172void 173arm_vector_init(vm_offset_t va, int which) 174{ 175 unsigned int *vectors = (int *) va; 176 unsigned int *vectors_data = vectors + (page0_data - page0); 177 int vec; 178 179 /* 180 * Loop through the vectors we're taking over, and copy the 181 * vector's insn and data word. 182 */ 183 for (vec = 0; vec < ARM_NVEC; vec++) { 184 if ((which & (1 << vec)) == 0) { 185 /* Don't want to take over this vector. */ 186 continue; 187 } 188 vectors[vec] = page0[vec]; 189 vectors_data[vec] = page0_data[vec]; 190 } 191 192 /* Now sync the vectors. */ 193 cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int)); 194 195 vector_page = va; 196 197 if (va == ARM_VECTORS_HIGH) { 198 /* 199 * Assume the MD caller knows what it's doing here, and 200 * really does want the vector page relocated. 201 * 202 * Note: This has to be done here (and not just in 203 * cpu_setup()) because the vector page needs to be 204 * accessible *before* cpu_startup() is called. 205 * Think ddb(9) ... 206 * 207 * NOTE: If the CPU control register is not readable, 208 * this will totally fail! We'll just assume that 209 * any system that has high vector support has a 210 * readable CPU control register, for now. If we 211 * ever encounter one that does not, we'll have to 212 * rethink this. 213 */ 214 cpu_control(CPU_CONTROL_VECRELOC, CPU_CONTROL_VECRELOC); 215 } 216} 217 218static void 219cpu_startup(void *dummy) 220{ 221 struct pcb *pcb = thread0.td_pcb; 222 223 vm_ksubmap_init(&kmi); 224 bufinit(); 225 vm_pager_bufferinit(); 226 pcb->un_32.pcb32_und_sp = (u_int)thread0.td_kstack + 227 USPACE_UNDEF_STACK_TOP; 228 pcb->un_32.pcb32_sp = (u_int)thread0.td_kstack + 229 USPACE_SVC_STACK_TOP; 230 vector_page_setprot(VM_PROT_READ); 231 pmap_set_pcb_pagedir(pmap_kernel(), pcb); 232 cpu_setup(""); 233 identify_arm_cpu(); 234 thread0.td_frame = (struct trapframe *)pcb->un_32.pcb32_sp - 1; 235 236} 237 238SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) 239 240/* Get current clock frequency for the given cpu id. */ 241int 242cpu_est_clockrate(int cpu_id, uint64_t *rate) 243{ 244 245 return (ENXIO); 246} 247 248void 249cpu_idle(void) 250{ 251 cpu_sleep(0); 252} 253 254int 255fill_regs(struct thread *td, struct reg *regs) 256{ 257 struct trapframe *tf = td->td_frame; 258 bcopy(&tf->tf_r0, regs->r, sizeof(regs->r)); 259 regs->r_sp = tf->tf_usr_sp; 260 regs->r_lr = tf->tf_usr_lr; 261 regs->r_pc = tf->tf_pc; 262 regs->r_cpsr = tf->tf_spsr; 263 return (0); 264} 265int 266fill_fpregs(struct thread *td, struct fpreg *regs) 267{ 268 bzero(regs, sizeof(*regs)); 269 return (0); 270} 271 272int 273set_regs(struct thread *td, struct reg *regs) 274{ 275 struct trapframe *tf = td->td_frame; 276 277 bcopy(regs->r, &tf->tf_r0, sizeof(regs->r)); 278 tf->tf_usr_sp = regs->r_sp; 279 tf->tf_usr_lr = regs->r_lr; 280 tf->tf_pc = regs->r_pc; 281 tf->tf_spsr &= ~PSR_FLAGS; 282 tf->tf_spsr |= regs->r_cpsr & PSR_FLAGS; 283 return (0); 284} 285 286int 287set_fpregs(struct thread *td, struct fpreg *regs) 288{ 289 return (0); 290} 291 292int 293fill_dbregs(struct thread *td, struct dbreg *regs) 294{ 295 return (0); 296} 297int 298set_dbregs(struct thread *td, struct dbreg *regs) 299{ 300 return (0); 301} 302 303 304static int 305ptrace_read_int(struct thread *td, vm_offset_t addr, u_int32_t *v) 306{ 307 struct iovec iov; 308 struct uio uio; 309 iov.iov_base = (caddr_t) v; 310 iov.iov_len = sizeof(u_int32_t); 311 uio.uio_iov = &iov; 312 uio.uio_iovcnt = 1; 313 uio.uio_offset = (off_t)addr; 314 uio.uio_resid = sizeof(u_int32_t); 315 uio.uio_segflg = UIO_SYSSPACE; 316 uio.uio_rw = UIO_READ; 317 uio.uio_td = td; 318 return proc_rwmem(td->td_proc, &uio); 319} 320 321static int 322ptrace_write_int(struct thread *td, vm_offset_t addr, u_int32_t v) 323{ 324 struct iovec iov; 325 struct uio uio; 326 iov.iov_base = (caddr_t) &v; 327 iov.iov_len = sizeof(u_int32_t); 328 uio.uio_iov = &iov; 329 uio.uio_iovcnt = 1; 330 uio.uio_offset = (off_t)addr; 331 uio.uio_resid = sizeof(u_int32_t); 332 uio.uio_segflg = UIO_SYSSPACE; 333 uio.uio_rw = UIO_WRITE; 334 uio.uio_td = td; 335 return proc_rwmem(td->td_proc, &uio); 336} 337 338int 339ptrace_single_step(struct thread *td) 340{ 341 int error; 342 343 KASSERT(td->td_md.md_ptrace_instr == 0, 344 ("Didn't clear single step")); 345 error = ptrace_read_int(td, td->td_frame->tf_pc + 4, 346 &td->td_md.md_ptrace_instr); 347 if (error) 348 return (error); 349 error = ptrace_write_int(td, td->td_frame->tf_pc + 4, 350 PTRACE_BREAKPOINT); 351 if (error) 352 td->td_md.md_ptrace_instr = 0; 353 td->td_md.md_ptrace_addr = td->td_frame->tf_pc + 4; 354 return (error); 355} 356 357int 358ptrace_clear_single_step(struct thread *td) 359{ 360 if (td->td_md.md_ptrace_instr) { 361 ptrace_write_int(td, td->td_md.md_ptrace_addr, 362 td->td_md.md_ptrace_instr); 363 td->td_md.md_ptrace_instr = 0; 364 } 365 return (0); 366} 367 368int 369ptrace_set_pc(struct thread *td, unsigned long addr) 370{ 371 td->td_frame->tf_pc = addr; 372 return (0); 373} 374 375void 376cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) 377{ 378} 379 380/* 381 * Clear registers on exec 382 */ 383void 384exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) 385{ 386 struct trapframe *tf = td->td_frame; 387 388 memset(tf, 0, sizeof(*tf)); 389 tf->tf_usr_sp = stack; 390 tf->tf_usr_lr = entry; 391 tf->tf_svc_lr = 0x77777777; 392 tf->tf_pc = entry; 393 tf->tf_spsr = PSR_USR32_MODE; 394} 395 396/* 397 * Build siginfo_t for SA thread 398 */ 399void 400cpu_thread_siginfo(int sig, u_long code, siginfo_t *si) 401{ 402 bzero(si, sizeof(*si)); 403 si->si_signo = sig; 404 si->si_code = code; 405} 406 407/* 408 * Get machine context. 409 */ 410int 411get_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret) 412{ 413 struct trapframe *tf = td->td_frame; 414 __greg_t *gr = mcp->__gregs; 415 416 if (clear_ret & GET_MC_CLEAR_RET) 417 gr[_REG_R0] = 0; 418 else 419 gr[_REG_R0] = tf->tf_r0; 420 gr[_REG_R1] = tf->tf_r1; 421 gr[_REG_R2] = tf->tf_r2; 422 gr[_REG_R3] = tf->tf_r3; 423 gr[_REG_R4] = tf->tf_r4; 424 gr[_REG_R5] = tf->tf_r5; 425 gr[_REG_R6] = tf->tf_r6; 426 gr[_REG_R7] = tf->tf_r7; 427 gr[_REG_R8] = tf->tf_r8; 428 gr[_REG_R9] = tf->tf_r9; 429 gr[_REG_R10] = tf->tf_r10; 430 gr[_REG_R11] = tf->tf_r11; 431 gr[_REG_R12] = tf->tf_r12; 432 gr[_REG_SP] = tf->tf_usr_sp; 433 gr[_REG_LR] = tf->tf_usr_lr; 434 gr[_REG_PC] = tf->tf_pc; 435 gr[_REG_CPSR] = tf->tf_spsr; 436 437 return (0); 438} 439 440/* 441 * Set machine context. 442 * 443 * However, we don't set any but the user modifiable flags, and we won't 444 * touch the cs selector. 445 */ 446int 447set_mcontext(struct thread *td, const mcontext_t *mcp) 448{ 449 struct trapframe *tf = td->td_frame; 450 __greg_t *gr = mcp->__gregs; 451 452 tf->tf_r0 = gr[_REG_R0]; 453 tf->tf_r1 = gr[_REG_R1]; 454 tf->tf_r2 = gr[_REG_R2]; 455 tf->tf_r3 = gr[_REG_R3]; 456 tf->tf_r4 = gr[_REG_R4]; 457 tf->tf_r5 = gr[_REG_R5]; 458 tf->tf_r6 = gr[_REG_R6]; 459 tf->tf_r7 = gr[_REG_R7]; 460 tf->tf_r8 = gr[_REG_R8]; 461 tf->tf_r9 = gr[_REG_R9]; 462 tf->tf_r10 = gr[_REG_R10]; 463 tf->tf_r11 = gr[_REG_R11]; 464 tf->tf_r12 = gr[_REG_R12]; 465 tf->tf_usr_sp = gr[_REG_SP]; 466 tf->tf_usr_lr = gr[_REG_LR]; 467 tf->tf_pc = gr[_REG_PC]; 468 tf->tf_spsr = gr[_REG_CPSR]; 469 470 return (0); 471} 472 473/* 474 * MPSAFE 475 */ 476int 477sigreturn(td, uap) 478 struct thread *td; 479 struct sigreturn_args /* { 480 const __ucontext *sigcntxp; 481 } */ *uap; 482{ 483 struct proc *p = td->td_proc; 484 struct sigframe sf; 485 struct trapframe *tf; 486 int spsr; 487 488 if (uap == NULL) 489 return (EFAULT); 490 if (copyin(uap->sigcntxp, &sf, sizeof(sf))) 491 return (EFAULT); 492 /* 493 * Make sure the processor mode has not been tampered with and 494 * interrupts have not been disabled. 495 */ 496 spsr = sf.sf_uc.uc_mcontext.__gregs[_REG_CPSR]; 497 if ((spsr & PSR_MODE) != PSR_USR32_MODE || 498 (spsr & (I32_bit | F32_bit)) != 0) 499 return (EINVAL); 500 /* Restore register context. */ 501 tf = td->td_frame; 502 set_mcontext(td, &sf.sf_uc.uc_mcontext); 503 504 /* Restore signal mask. */ 505 PROC_LOCK(p); 506 td->td_sigmask = sf.sf_uc.uc_sigmask; 507 SIG_CANTMASK(td->td_sigmask); 508 signotify(td); 509 PROC_UNLOCK(p); 510 511 return (EJUSTRETURN); 512} 513 514 515/* 516 * Construct a PCB from a trapframe. This is called from kdb_trap() where 517 * we want to start a backtrace from the function that caused us to enter 518 * the debugger. We have the context in the trapframe, but base the trace 519 * on the PCB. The PCB doesn't have to be perfect, as long as it contains 520 * enough for a backtrace. 521 */ 522void 523makectx(struct trapframe *tf, struct pcb *pcb) 524{ 525 pcb->un_32.pcb32_r8 = tf->tf_r8; 526 pcb->un_32.pcb32_r9 = tf->tf_r9; 527 pcb->un_32.pcb32_r10 = tf->tf_r10; 528 pcb->un_32.pcb32_r11 = tf->tf_r11; 529 pcb->un_32.pcb32_r12 = tf->tf_r12; 530 pcb->un_32.pcb32_pc = tf->tf_pc; 531 pcb->un_32.pcb32_lr = tf->tf_usr_lr; 532 pcb->un_32.pcb32_sp = tf->tf_usr_sp; 533} 534