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.h> 233 #include <sys/cpu_data.h> 234 struct cpu_info { 235 struct cpu_data ci_data; /* MI per-cpu data */ 236 struct device *ci_dev; /* Device corresponding to this CPU */ 237 cpuid_t ci_cpuid; 238 u_int32_t ci_arm_cpuid; /* aggregate CPU id */ 239 u_int32_t ci_arm_cputype; /* CPU type */ 240 u_int32_t ci_arm_cpurev; /* CPU revision */ 241 u_int32_t ci_ctrl; /* The CPU control register */ 242 int ci_cpl; /* current processor level (spl) */ 243 int ci_astpending; /* */ 244 int ci_want_resched; /* resched() was called */ 245 int ci_intr_depth; /* */ 246 struct pcb *ci_curpcb; /* current pcb */ 247 #ifdef __HAVE_FAST_SOFTINTS 248 lwp_t *ci_softlwps[SOFTINT_COUNT]; 249 uint32_t ci_softints; 250 #endif 251 #if !defined(PROCESS_ID_IS_CURLWP) 252 lwp_t *ci_curlwp; /* current lwp */ 253 #endif 254 #ifdef _ARM_ARCH_6 255 uint32_t ci_ccnt_freq; /* cycle count frequency */ 256 #endif 257 struct evcnt ci_arm700bugcount; 258 int32_t ci_mtx_count; 259 int ci_mtx_oldspl; 260 #ifdef MULTIPROCESSOR 261 MP_CPU_INFO_MEMBERS 262 #endif 263 #ifdef FPU_VFP 264 struct vfp_info ci_vfp; 265 #endif 266 }; 267 268 #ifndef MULTIPROCESSOR 269 extern struct cpu_info cpu_info_store; 270 #if defined(PROCESS_ID_IS_CURLWP) 271 static inline struct lwp * 272 _curlwp(void) 273 { 274 struct lwp *l; 275 __asm("mrc\tp15, 0, %0, c13, c0, 4" : "=r"(l)); 276 return l; 277 } 278 279 static inline void 280 _curlwp_set(struct lwp *l) 281 { 282 __asm("mcr\tp15, 0, %0, c13, c0, 4" : "=r"(l)); 283 } 284 285 #define curlwp (_curlwp()) 286 static inline struct cpu_info * 287 curcpu(void) 288 { 289 return curlwp->l_cpu; 290 } 291 #elif defined(PROCESS_ID_IS_CURCPU) 292 static inline struct cpu_info * 293 curcpu(void) 294 { 295 struct cpu_info *ci; 296 __asm("mrc\tp15, 0, %0, c13, c0, 4" : "=r"(ci)); 297 return ci; 298 } 299 #else 300 #define curcpu() (&cpu_info_store) 301 #endif /* !PROCESS_ID_IS_CURCPU && !PROCESS_ID_IS_CURLWP */ 302 #ifndef curpcb 303 #define curpcb (curcpu()->ci_curpcb) 304 #endif 305 #ifndef curlwp 306 #define curlwp (curcpu()->ci_curlwp) 307 #endif 308 #define cpu_number() 0 309 #define LWP0_CPU_INFO (&cpu_info_store) 310 #endif /* !MULTIPROCESSOR */ 311 312 static inline int 313 curcpl(void) 314 { 315 return curcpu()->ci_cpl; 316 } 317 318 static inline void 319 set_curcpl(int pri) 320 { 321 curcpu()->ci_cpl = pri; 322 } 323 324 #ifdef __HAVE_FAST_SOFTINTS 325 void dosoftints(void); 326 static inline void 327 cpu_dosoftints(void) 328 { 329 struct cpu_info * const ci = curcpu(); 330 if (ci->ci_intr_depth == 0 && (ci->ci_softints >> ci->ci_cpl) > 0) 331 dosoftints(); 332 } 333 #endif 334 335 #ifdef __PROG32 336 void cpu_proc_fork(struct proc *, struct proc *); 337 #else 338 #define cpu_proc_fork(p1, p2) 339 #endif 340 341 /* 342 * Scheduling glue 343 */ 344 345 #define setsoftast() (curcpu()->ci_astpending = 1) 346 347 /* 348 * Notify the current process (p) that it has a signal pending, 349 * process as soon as possible. 350 */ 351 352 #define cpu_signotify(l) setsoftast() 353 354 /* 355 * Give a profiling tick to the current process when the user profiling 356 * buffer pages are invalid. On the i386, request an ast to send us 357 * through trap(), marking the proc as needing a profiling tick. 358 */ 359 #define cpu_need_proftick(l) ((l)->l_pflag |= LP_OWEUPC, setsoftast()) 360 361 #ifndef acorn26 362 /* 363 * cpu device glue (belongs in cpuvar.h) 364 */ 365 366 struct device; 367 void cpu_attach(struct device *); 368 #endif 369 370 /* 371 * Random cruft 372 */ 373 374 struct lwp; 375 376 /* locore.S */ 377 void atomic_set_bit(u_int *, u_int); 378 void atomic_clear_bit(u_int *, u_int); 379 380 /* cpuswitch.S */ 381 struct pcb; 382 void savectx(struct pcb *); 383 384 /* ast.c */ 385 void userret(register struct lwp *); 386 387 /* *_machdep.c */ 388 void bootsync(void); 389 390 /* fault.c */ 391 int badaddr_read(void *, size_t, void *); 392 393 /* syscall.c */ 394 void swi_handler(trapframe_t *); 395 396 /* arm_machdep.c */ 397 void ucas_ras_check(trapframe_t *); 398 399 #endif /* !_LOCORE */ 400 401 #endif /* _KERNEL */ 402 403 #endif /* !_ARM_CPU_H_ */ 404