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 <sys/user.h> 80 #include <machine/frame.h> 81 #include <machine/pcb.h> 82 #ifdef FPU_VFP 83 #include <arm/vfpvar.h> 84 #endif 85 #endif /* !_LOCORE */ 86 87 #include <arm/armreg.h> 88 89 90 #ifndef _LOCORE 91 /* 1 == use cpu_sleep(), 0 == don't */ 92 extern int cpu_do_powersave; 93 #endif 94 95 #ifdef _LOCORE 96 97 #if defined(_ARM_ARCH_6) 98 #define IRQdisable cprid i 99 #define IRQenable cpsie i 100 #elif defined(__PROG32) 101 #define IRQdisable \ 102 stmfd sp!, {r0} ; \ 103 mrs r0, cpsr ; \ 104 orr r0, r0, #(I32_bit) ; \ 105 msr cpsr_c, r0 ; \ 106 ldmfd sp!, {r0} 107 108 #define IRQenable \ 109 stmfd sp!, {r0} ; \ 110 mrs r0, cpsr ; \ 111 bic r0, r0, #(I32_bit) ; \ 112 msr cpsr_c, r0 ; \ 113 ldmfd sp!, {r0} 114 #else 115 /* Not yet used in 26-bit code */ 116 #endif 117 118 #if defined (PROCESS_ID_IS_CURCPU) 119 #define GET_CURCPU(rX) mrc p15, 0, rX, c13, c0, 4 120 #define GET_CURLWP(rX) GET_CURCPU(rX); ldr rX, [rX, #CI_CURLWP] 121 #define GET_CURPCB(rX) GET_CURCPU(rX); ldr rX, [rX, #CI_CURPCB] 122 #elif defined (PROCESS_ID_IS_CURLWP) 123 #define GET_CURLWP(rX) mrc p15, 0, rX, c13, c0, 4 124 #define GET_CURCPU(rX) GET_CURLWP(rX); ldr rX, [rX, #L_CPU] 125 #define GET_CURPCB(rX) GET_CURLWP(rX); ldr rX, [rX, #L_ADDR] 126 #elif !defined(MULTIPROCESSOR) 127 #define GET_CURCPU(rX) ldr rX, =_C_LABEL(cpu_info_store) 128 #define GET_CURLWP(rX) GET_CURCPU(rX); ldr rX, [rX, #CI_CURLWP] 129 #define GET_CURPCB(rX) GET_CURCPU(rX); ldr rX, [rX, #CI_CURPCB] 130 #endif 131 132 #else /* !_LOCORE */ 133 134 #ifdef __PROG32 135 #define IRQdisable __set_cpsr_c(I32_bit, I32_bit); 136 #define IRQenable __set_cpsr_c(I32_bit, 0); 137 #else 138 #define IRQdisable set_r15(R15_IRQ_DISABLE, R15_IRQ_DISABLE); 139 #define IRQenable set_r15(R15_IRQ_DISABLE, 0); 140 #endif 141 142 #endif /* !_LOCORE */ 143 144 #ifndef _LOCORE 145 146 /* All the CLKF_* macros take a struct clockframe * as an argument. */ 147 148 /* 149 * CLKF_USERMODE: Return TRUE/FALSE (1/0) depending on whether the 150 * frame came from USR mode or not. 151 */ 152 #ifdef __PROG32 153 #define CLKF_USERMODE(frame) ((frame->cf_if.if_spsr & PSR_MODE) == PSR_USR32_MODE) 154 #else 155 #define CLKF_USERMODE(frame) ((frame->cf_if.if_r15 & R15_MODE) == R15_MODE_USR) 156 #endif 157 158 /* 159 * CLKF_INTR: True if we took the interrupt from inside another 160 * interrupt handler. 161 */ 162 #ifdef __PROG32 163 /* Hack to treat FPE time as interrupt time so we can measure it */ 164 #define CLKF_INTR(frame) \ 165 ((curcpu()->ci_intr_depth > 1) || \ 166 (frame->cf_if.if_spsr & PSR_MODE) == PSR_UND32_MODE) 167 #else 168 #define CLKF_INTR(frame) (curcpu()->ci_intr_depth > 1) 169 #endif 170 171 /* 172 * CLKF_PC: Extract the program counter from a clockframe 173 */ 174 #ifdef __PROG32 175 #define CLKF_PC(frame) (frame->cf_if.if_pc) 176 #else 177 #define CLKF_PC(frame) (frame->cf_if.if_r15 & R15_PC) 178 #endif 179 180 /* 181 * LWP_PC: Find out the program counter for the given lwp. 182 */ 183 #ifdef __PROG32 184 #define LWP_PC(l) ((l)->l_addr->u_pcb.pcb_tf->tf_pc) 185 #else 186 #define LWP_PC(l) ((l)->l_addr->u_pcb.pcb_tf->tf_r15 & R15_PC) 187 #endif 188 189 /* 190 * Validate a PC or PSR for a user process. Used by various system calls 191 * that take a context passed by the user and restore it. 192 */ 193 194 #ifdef __PROG32 195 #define VALID_R15_PSR(r15,psr) \ 196 (((psr) & PSR_MODE) == PSR_USR32_MODE && \ 197 ((psr) & (I32_bit | F32_bit)) == 0) 198 #else 199 #define VALID_R15_PSR(r15,psr) \ 200 (((r15) & R15_MODE) == R15_MODE_USR && \ 201 ((r15) & (R15_IRQ_DISABLE | R15_FIQ_DISABLE)) == 0) 202 #endif 203 204 205 206 /* The address of the vector page. */ 207 extern vaddr_t vector_page; 208 #ifdef __PROG32 209 void arm32_vector_init(vaddr_t, int); 210 211 #define ARM_VEC_RESET (1 << 0) 212 #define ARM_VEC_UNDEFINED (1 << 1) 213 #define ARM_VEC_SWI (1 << 2) 214 #define ARM_VEC_PREFETCH_ABORT (1 << 3) 215 #define ARM_VEC_DATA_ABORT (1 << 4) 216 #define ARM_VEC_ADDRESS_EXCEPTION (1 << 5) 217 #define ARM_VEC_IRQ (1 << 6) 218 #define ARM_VEC_FIQ (1 << 7) 219 220 #define ARM_NVEC 8 221 #define ARM_VEC_ALL 0xffffffff 222 #endif 223 224 /* 225 * Per-CPU information. For now we assume one CPU. 226 */ 227 static inline int curcpl(void); 228 static inline void set_curcpl(int); 229 #ifdef __HAVE_FAST_SOFTINTS 230 static inline void cpu_dosoftints(void); 231 #endif 232 233 #include <sys/device.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.h */ 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 #endif /* !_LOCORE */ 398 399 #endif /* _KERNEL */ 400 401 #endif /* !_ARM_CPU_H_ */ 402