1 /* cpu.h,v 1.45.4.7 2008/01/28 18:20:39 matt Exp */ 2 3 /* 4 * Copyright (c) 1994-1996 Mark Brinicombe. 5 * Copyright (c) 1994 Brini. 6 * All rights reserved. 7 * 8 * This code is derived from software written for Brini by Mark Brinicombe 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by Brini. 21 * 4. The name of the company nor the name of the author may be used to 22 * endorse or promote products derived from this software without specific 23 * prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED 26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28 * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * RiscBSD kernel project 38 * 39 * cpu.h 40 * 41 * CPU specific symbols 42 * 43 * Created : 18/09/94 44 * 45 * Based on kate/katelib/arm6.h 46 */ 47 48 #ifndef _ARM_CPU_H_ 49 #define _ARM_CPU_H_ 50 51 /* 52 * User-visible definitions 53 */ 54 55 /* CTL_MACHDEP definitions. */ 56 #define CPU_DEBUG 1 /* int: misc kernel debug control */ 57 #define CPU_BOOTED_DEVICE 2 /* string: device we booted from */ 58 #define CPU_BOOTED_KERNEL 3 /* string: kernel we booted */ 59 #define CPU_CONSDEV 4 /* struct: dev_t of our console */ 60 #define CPU_POWERSAVE 5 /* int: use CPU powersave mode */ 61 #define CPU_MAXID 6 /* number of valid machdep ids */ 62 63 #ifdef _KERNEL 64 65 /* 66 * Kernel-only definitions 67 */ 68 69 #ifndef _LKM 70 #include "opt_multiprocessor.h" 71 #include "opt_cpuoptions.h" 72 #include "opt_lockdebug.h" 73 #include "opt_cputypes.h" 74 #endif /* !_LKM */ 75 76 #include <arm/cpuconf.h> 77 78 #ifndef _LOCORE 79 #include <machine/frame.h> 80 #include <machine/pcb.h> 81 #ifdef FPU_VFP 82 #include <arm/vfpvar.h> 83 #endif 84 #endif /* !_LOCORE */ 85 86 #include <arm/armreg.h> 87 88 89 #ifndef _LOCORE 90 /* 1 == use cpu_sleep(), 0 == don't */ 91 extern int cpu_do_powersave; 92 #endif 93 94 #ifdef _LOCORE 95 96 #if defined(_ARM_ARCH_6) 97 #define IRQdisable cprid i 98 #define IRQenable cpsie i 99 #elif defined(__PROG32) 100 #define IRQdisable \ 101 stmfd sp!, {r0} ; \ 102 mrs r0, cpsr ; \ 103 orr r0, r0, #(I32_bit) ; \ 104 msr cpsr_c, r0 ; \ 105 ldmfd sp!, {r0} 106 107 #define IRQenable \ 108 stmfd sp!, {r0} ; \ 109 mrs r0, cpsr ; \ 110 bic r0, r0, #(I32_bit) ; \ 111 msr cpsr_c, r0 ; \ 112 ldmfd sp!, {r0} 113 #else 114 /* Not yet used in 26-bit code */ 115 #endif 116 117 #if defined (PROCESS_ID_IS_CURCPU) 118 #define GET_CURCPU(rX) mrc p15, 0, rX, c13, c0, 4 119 #define GET_CURLWP(rX) GET_CURCPU(rX); ldr rX, [rX, #CI_CURLWP] 120 #define GET_CURPCB(rX) GET_CURCPU(rX); ldr rX, [rX, #CI_CURPCB] 121 #elif defined (PROCESS_ID_IS_CURLWP) 122 #define GET_CURLWP(rX) mrc p15, 0, rX, c13, c0, 4 123 #define GET_CURCPU(rX) GET_CURLWP(rX); ldr rX, [rX, #L_CPU] 124 #define GET_CURPCB(rX) GET_CURLWP(rX); ldr rX, [rX, #L_PCB] 125 #elif !defined(MULTIPROCESSOR) 126 #define GET_CURCPU(rX) ldr rX, =_C_LABEL(cpu_info_store) 127 #define GET_CURLWP(rX) GET_CURCPU(rX); ldr rX, [rX, #CI_CURLWP] 128 #define GET_CURPCB(rX) GET_CURCPU(rX); ldr rX, [rX, #CI_CURPCB] 129 #endif 130 131 #else /* !_LOCORE */ 132 133 #ifdef __PROG32 134 #define IRQdisable __set_cpsr_c(I32_bit, I32_bit); 135 #define IRQenable __set_cpsr_c(I32_bit, 0); 136 #else 137 #define IRQdisable set_r15(R15_IRQ_DISABLE, R15_IRQ_DISABLE); 138 #define IRQenable set_r15(R15_IRQ_DISABLE, 0); 139 #endif 140 141 #endif /* !_LOCORE */ 142 143 #ifndef _LOCORE 144 145 /* All the CLKF_* macros take a struct clockframe * as an argument. */ 146 147 /* 148 * CLKF_USERMODE: Return TRUE/FALSE (1/0) depending on whether the 149 * frame came from USR mode or not. 150 */ 151 #ifdef __PROG32 152 #define CLKF_USERMODE(frame) ((frame->cf_if.if_spsr & PSR_MODE) == PSR_USR32_MODE) 153 #else 154 #define CLKF_USERMODE(frame) ((frame->cf_if.if_r15 & R15_MODE) == R15_MODE_USR) 155 #endif 156 157 /* 158 * CLKF_INTR: True if we took the interrupt from inside another 159 * interrupt handler. 160 */ 161 #ifdef __PROG32 162 /* Hack to treat FPE time as interrupt time so we can measure it */ 163 #define CLKF_INTR(frame) \ 164 ((curcpu()->ci_intr_depth > 1) || \ 165 (frame->cf_if.if_spsr & PSR_MODE) == PSR_UND32_MODE) 166 #else 167 #define CLKF_INTR(frame) (curcpu()->ci_intr_depth > 1) 168 #endif 169 170 /* 171 * CLKF_PC: Extract the program counter from a clockframe 172 */ 173 #ifdef __PROG32 174 #define CLKF_PC(frame) (frame->cf_if.if_pc) 175 #else 176 #define CLKF_PC(frame) (frame->cf_if.if_r15 & R15_PC) 177 #endif 178 179 /* 180 * LWP_PC: Find out the program counter for the given lwp. 181 */ 182 #ifdef __PROG32 183 #define LWP_PC(l) (((struct pcb *)lwp_getpcb(l))->pcb_tf->tf_pc) 184 #else 185 #define LWP_PC(l) (((struct pcb *)lwp_getpcb(l))->pcb_tf->tf_r15 & R15_PC) 186 #endif 187 188 /* 189 * Validate a PC or PSR for a user process. Used by various system calls 190 * that take a context passed by the user and restore it. 191 */ 192 193 #ifdef __PROG32 194 #define VALID_R15_PSR(r15,psr) \ 195 (((psr) & PSR_MODE) == PSR_USR32_MODE && \ 196 ((psr) & (I32_bit | F32_bit)) == 0) 197 #else 198 #define VALID_R15_PSR(r15,psr) \ 199 (((r15) & R15_MODE) == R15_MODE_USR && \ 200 ((r15) & (R15_IRQ_DISABLE | R15_FIQ_DISABLE)) == 0) 201 #endif 202 203 204 205 /* The address of the vector page. */ 206 extern vaddr_t vector_page; 207 #ifdef __PROG32 208 void arm32_vector_init(vaddr_t, int); 209 210 #define ARM_VEC_RESET (1 << 0) 211 #define ARM_VEC_UNDEFINED (1 << 1) 212 #define ARM_VEC_SWI (1 << 2) 213 #define ARM_VEC_PREFETCH_ABORT (1 << 3) 214 #define ARM_VEC_DATA_ABORT (1 << 4) 215 #define ARM_VEC_ADDRESS_EXCEPTION (1 << 5) 216 #define ARM_VEC_IRQ (1 << 6) 217 #define ARM_VEC_FIQ (1 << 7) 218 219 #define ARM_NVEC 8 220 #define ARM_VEC_ALL 0xffffffff 221 #endif 222 223 /* 224 * Per-CPU information. For now we assume one CPU. 225 */ 226 static inline int curcpl(void); 227 static inline void set_curcpl(int); 228 #ifdef __HAVE_FAST_SOFTINTS 229 static inline void cpu_dosoftints(void); 230 #endif 231 232 #include <sys/device_if.h> 233 #include <sys/evcnt.h> 234 #include <sys/cpu_data.h> 235 struct cpu_info { 236 struct cpu_data ci_data; /* MI per-cpu data */ 237 struct device *ci_dev; /* Device corresponding to this CPU */ 238 cpuid_t ci_cpuid; 239 u_int32_t ci_arm_cpuid; /* aggregate CPU id */ 240 u_int32_t ci_arm_cputype; /* CPU type */ 241 u_int32_t ci_arm_cpurev; /* CPU revision */ 242 u_int32_t ci_ctrl; /* The CPU control register */ 243 int ci_cpl; /* current processor level (spl) */ 244 int ci_astpending; /* */ 245 int ci_want_resched; /* resched() was called */ 246 int ci_intr_depth; /* */ 247 struct pcb *ci_curpcb; /* current pcb */ 248 #ifdef __HAVE_FAST_SOFTINTS 249 lwp_t *ci_softlwps[SOFTINT_COUNT]; 250 uint32_t ci_softints; 251 #endif 252 #if !defined(PROCESS_ID_IS_CURLWP) 253 lwp_t *ci_curlwp; /* current lwp */ 254 #endif 255 #ifdef _ARM_ARCH_6 256 uint32_t ci_ccnt_freq; /* cycle count frequency */ 257 #endif 258 struct evcnt ci_arm700bugcount; 259 int32_t ci_mtx_count; 260 int ci_mtx_oldspl; 261 #ifdef MULTIPROCESSOR 262 MP_CPU_INFO_MEMBERS 263 #endif 264 #ifdef FPU_VFP 265 struct vfp_info ci_vfp; 266 #endif 267 }; 268 269 #ifndef MULTIPROCESSOR 270 extern struct cpu_info cpu_info_store; 271 #if defined(PROCESS_ID_IS_CURLWP) 272 static inline struct lwp * 273 _curlwp(void) 274 { 275 struct lwp *l; 276 __asm("mrc\tp15, 0, %0, c13, c0, 4" : "=r"(l)); 277 return l; 278 } 279 280 static inline void 281 _curlwp_set(struct lwp *l) 282 { 283 __asm("mcr\tp15, 0, %0, c13, c0, 4" : "=r"(l)); 284 } 285 286 #define curlwp (_curlwp()) 287 static inline struct cpu_info * 288 curcpu(void) 289 { 290 return curlwp->l_cpu; 291 } 292 #elif defined(PROCESS_ID_IS_CURCPU) 293 static inline struct cpu_info * 294 curcpu(void) 295 { 296 struct cpu_info *ci; 297 __asm("mrc\tp15, 0, %0, c13, c0, 4" : "=r"(ci)); 298 return ci; 299 } 300 #else 301 #define curcpu() (&cpu_info_store) 302 #endif /* !PROCESS_ID_IS_CURCPU && !PROCESS_ID_IS_CURLWP */ 303 #ifndef curpcb 304 #define curpcb (curcpu()->ci_curpcb) 305 #endif 306 #ifndef curlwp 307 #define curlwp (curcpu()->ci_curlwp) 308 #endif 309 #define cpu_number() 0 310 #define LWP0_CPU_INFO (&cpu_info_store) 311 #endif /* !MULTIPROCESSOR */ 312 313 static inline int 314 curcpl(void) 315 { 316 return curcpu()->ci_cpl; 317 } 318 319 static inline void 320 set_curcpl(int pri) 321 { 322 curcpu()->ci_cpl = pri; 323 } 324 325 #ifdef __HAVE_FAST_SOFTINTS 326 void dosoftints(void); 327 static inline void 328 cpu_dosoftints(void) 329 { 330 struct cpu_info * const ci = curcpu(); 331 if (ci->ci_intr_depth == 0 && (ci->ci_softints >> ci->ci_cpl) > 0) 332 dosoftints(); 333 } 334 #endif 335 336 #ifdef __PROG32 337 void cpu_proc_fork(struct proc *, struct proc *); 338 #else 339 #define cpu_proc_fork(p1, p2) 340 #endif 341 342 /* 343 * Scheduling glue 344 */ 345 346 #define setsoftast() (curcpu()->ci_astpending = 1) 347 348 /* 349 * Notify the current process (p) that it has a signal pending, 350 * process as soon as possible. 351 */ 352 353 #define cpu_signotify(l) setsoftast() 354 355 /* 356 * Give a profiling tick to the current process when the user profiling 357 * buffer pages are invalid. On the i386, request an ast to send us 358 * through trap(), marking the proc as needing a profiling tick. 359 */ 360 #define cpu_need_proftick(l) ((l)->l_pflag |= LP_OWEUPC, setsoftast()) 361 362 #ifndef acorn26 363 /* 364 * cpu device glue (belongs in cpuvar.h) 365 */ 366 367 struct device; 368 void cpu_attach(struct device *); 369 #endif 370 371 /* 372 * Random cruft 373 */ 374 375 struct lwp; 376 377 /* locore.S */ 378 void atomic_set_bit(u_int *, u_int); 379 void atomic_clear_bit(u_int *, u_int); 380 381 /* cpuswitch.S */ 382 struct pcb; 383 void savectx(struct pcb *); 384 385 /* ast.c */ 386 void userret(register struct lwp *); 387 388 /* *_machdep.c */ 389 void bootsync(void); 390 391 /* fault.c */ 392 int badaddr_read(void *, size_t, void *); 393 394 /* syscall.c */ 395 void swi_handler(trapframe_t *); 396 397 /* arm_machdep.c */ 398 void ucas_ras_check(trapframe_t *); 399 400 #endif /* !_LOCORE */ 401 402 #endif /* _KERNEL */ 403 404 #endif /* !_ARM_CPU_H_ */ 405