1/* $NetBSD: arm_machdep.c,v 1.29 2010/07/07 01:17:26 chs Exp $ */ 2 3/* 4 * Copyright (c) 2001 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38/* 39 * Copyright (c) 1994-1998 Mark Brinicombe. 40 * Copyright (c) 1994 Brini. 41 * All rights reserved. 42 * 43 * This code is derived from software written for Brini by Mark Brinicombe 44 * 45 * Redistribution and use in source and binary forms, with or without 46 * modification, are permitted provided that the following conditions 47 * are met: 48 * 1. Redistributions of source code must retain the above copyright 49 * notice, this list of conditions and the following disclaimer. 50 * 2. Redistributions in binary form must reproduce the above copyright 51 * notice, this list of conditions and the following disclaimer in the 52 * documentation and/or other materials provided with the distribution. 53 * 3. All advertising materials mentioning features or use of this software 54 * must display the following acknowledgement: 55 * This product includes software developed by Mark Brinicombe 56 * for the NetBSD Project. 57 * 4. The name of the company nor the name of the author may be used to 58 * endorse or promote products derived from this software without specific 59 * prior written permission. 60 * 61 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 62 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 63 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 64 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 65 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 66 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 67 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 69 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 71 * SUCH DAMAGE. 72 */ 73 74#include "opt_execfmt.h" 75#include "opt_cpuoptions.h" 76#include "opt_cputypes.h" 77#include "opt_arm_debug.h" 78#include "opt_sa.h" 79 80#include <sys/param.h> 81 82__KERNEL_RCSID(0, "$NetBSD: arm_machdep.c,v 1.29 2010/07/07 01:17:26 chs Exp $"); 83 84#include <sys/exec.h> 85#include <sys/proc.h> 86#include <sys/systm.h> 87#include <sys/kmem.h> 88#include <sys/ucontext.h> 89#include <sys/evcnt.h> 90#include <sys/cpu.h> 91#include <sys/savar.h> 92 93#ifdef EXEC_AOUT 94#include <sys/exec_aout.h> 95#endif 96 97#include <arm/cpufunc.h> 98 99#include <machine/pcb.h> 100#include <machine/vmparam.h> 101 102/* the following is used externally (sysctl_hw) */ 103char machine[] = MACHINE; /* from <machine/param.h> */ 104char machine_arch[] = MACHINE_ARCH; /* from <machine/param.h> */ 105 106/* Our exported CPU info; we can have only one. */ 107struct cpu_info cpu_info_store = { 108 .ci_cpl = IPL_HIGH, 109#ifndef PROCESS_ID_IS_CURLWP 110 .ci_curlwp = &lwp0, 111#endif 112}; 113 114/* 115 * The ARM architecture places the vector page at address 0. 116 * Later ARM architecture versions, however, allow it to be 117 * relocated to a high address (0xffff0000). This is primarily 118 * to support the Fast Context Switch Extension. 119 * 120 * This variable contains the address of the vector page. It 121 * defaults to 0; it only needs to be initialized if we enable 122 * relocated vectors. 123 */ 124vaddr_t vector_page; 125 126#if defined(ARM_LOCK_CAS_DEBUG) 127/* 128 * Event counters for tracking activity of the RAS-based _lock_cas() 129 * routine. 130 */ 131struct evcnt _lock_cas_restart = 132 EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "_lock_cas", "restart"); 133EVCNT_ATTACH_STATIC(_lock_cas_restart); 134 135struct evcnt _lock_cas_success = 136 EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "_lock_cas", "success"); 137EVCNT_ATTACH_STATIC(_lock_cas_success); 138 139struct evcnt _lock_cas_fail = 140 EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "_lock_cas", "fail"); 141EVCNT_ATTACH_STATIC(_lock_cas_fail); 142#endif /* ARM_LOCK_CAS_DEBUG */ 143 144/* 145 * Clear registers on exec 146 */ 147 148void 149setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) 150{ 151 struct pcb *pcb; 152 struct trapframe *tf; 153 154 pcb = lwp_getpcb(l); 155 tf = pcb->pcb_tf; 156 157 memset(tf, 0, sizeof(*tf)); 158 tf->tf_r0 = l->l_proc->p_psstrp; 159 tf->tf_r12 = stack; /* needed by pre 1.4 crt0.c */ 160 tf->tf_usr_sp = stack; 161 tf->tf_usr_lr = pack->ep_entry; 162 tf->tf_svc_lr = 0x77777777; /* Something we can see */ 163 tf->tf_pc = pack->ep_entry; 164#ifdef __PROG32 165 tf->tf_spsr = PSR_USR32_MODE; 166#ifdef THUMB_CODE 167 if (pack->ep_entry & 1) 168 tf->tf_spsr |= PSR_T_bit; 169#endif 170#endif 171 172#ifdef EXEC_AOUT 173 if (pack->ep_esch->es_makecmds == exec_aout_makecmds) 174 pcb->pcb_flags = PCB_NOALIGNFLT; 175 else 176#endif 177 pcb->pcb_flags = 0; 178#ifdef FPU_VFP 179 l->l_md.md_flags &= ~MDP_VFPUSED; 180 if (pcb->pcb_vfpcpu != NULL) 181 vfp_saveregs_lwp(l, 0); 182#endif 183} 184 185/* 186 * startlwp: 187 * 188 * Start a new LWP. 189 */ 190void 191startlwp(void *arg) 192{ 193 ucontext_t *uc = arg; 194 lwp_t *l = curlwp; 195 int error; 196 197 error = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); 198 KASSERT(error == 0); 199 200 kmem_free(uc, sizeof(ucontext_t)); 201 userret(l); 202} 203 204#ifdef KERN_SA 205/* 206 * XXX This is a terrible name. 207 */ 208void 209upcallret(struct lwp *l) 210{ 211 212 userret(l); 213} 214 215/* 216 * cpu_upcall: 217 * 218 * Send an an upcall to userland. 219 */ 220void 221cpu_upcall(struct lwp *l, int type, int nevents, int ninterrupted, void *sas, 222 void *ap, void *sp, sa_upcall_t upcall) 223{ 224 struct trapframe *tf; 225 struct saframe *sf, frame; 226 227 tf = process_frame(l); 228 229 /* Finally, copy out the rest of the frame. */ 230#if 0 /* First 4 args in regs (see below). */ 231 frame.sa_type = type; 232 frame.sa_sas = sas; 233 frame.sa_events = nevents; 234 frame.sa_interrupted = ninterrupted; 235#endif 236 frame.sa_arg = ap; 237 238 sf = (struct saframe *)sp - 1; 239 if (copyout(&frame, sf, sizeof(frame)) != 0) { 240 /* Copying onto the stack didn't work. Die. */ 241 sigexit(l, SIGILL); 242 /* NOTREACHED */ 243 } 244 245 tf->tf_r0 = type; 246 tf->tf_r1 = (int) sas; 247 tf->tf_r2 = nevents; 248 tf->tf_r3 = ninterrupted; 249 tf->tf_pc = (int) upcall; 250#ifdef THUMB_CODE 251 if (((int) upcall) & 1) 252 tf->tf_spsr |= PSR_T_bit; 253 else 254 tf->tf_spsr &= ~PSR_T_bit; 255#endif 256 tf->tf_usr_sp = (int) sf; 257 tf->tf_usr_lr = 0; /* no return */ 258} 259 260#endif /* KERN_SA */ 261 262void 263cpu_need_resched(struct cpu_info *ci, int flags) 264{ 265 bool immed = (flags & RESCHED_IMMED) != 0; 266 267 if (ci->ci_want_resched && !immed) 268 return; 269 270 ci->ci_want_resched = 1; 271 if (curlwp != ci->ci_data.cpu_idlelwp) 272 setsoftast(); 273} 274 275bool 276cpu_intr_p(void) 277{ 278 return curcpu()->ci_intr_depth != 0; 279} 280 281void 282ucas_ras_check(trapframe_t *tf) 283{ 284 extern char ucas_32_ras_start[]; 285 extern char ucas_32_ras_end[]; 286 287 if (tf->tf_pc > (vaddr_t)ucas_32_ras_start && 288 tf->tf_pc < (vaddr_t)ucas_32_ras_end) { 289 tf->tf_pc = (vaddr_t)ucas_32_ras_start; 290 } 291} 292