1 /* $NetBSD: cpu.h,v 1.89 2008/02/27 18:26:16 xtraeme Exp $ */ 2 3 /*- 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Ralph Campbell and Rick Macklem. 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. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)cpu.h 8.4 (Berkeley) 1/4/94 35 */ 36 37 #ifndef _CPU_H_ 38 #define _CPU_H_ 39 40 #include <mips/cpuregs.h> 41 42 /* 43 * Exported definitions unique to NetBSD/mips cpu support. 44 */ 45 46 #ifdef _KERNEL 47 #ifndef _LOCORE 48 #include <sys/cpu_data.h> 49 50 #if defined(_KERNEL_OPT) 51 #include "opt_lockdebug.h" 52 #endif 53 54 struct cpu_info { 55 struct cpu_data ci_data; /* MI per-cpu data */ 56 struct cpu_info *ci_next; /* Next CPU in list */ 57 cpuid_t ci_cpuid; /* Machine-level identifier */ 58 u_long ci_cpu_freq; /* CPU frequency */ 59 u_long ci_cycles_per_hz; /* CPU freq / hz */ 60 u_long ci_divisor_delay; /* for delay/DELAY */ 61 u_long ci_divisor_recip; /* scaled reciprocal of previous; 62 see below */ 63 struct lwp *ci_curlwp; /* currently running lwp */ 64 struct lwp *ci_fpcurlwp; /* the current FPU owner */ 65 int ci_want_resched; /* user preemption pending */ 66 int ci_mtx_count; /* negative count of held mutexes */ 67 int ci_mtx_oldspl; /* saved SPL value */ 68 int ci_idepth; /* hardware interrupt depth */ 69 }; 70 71 #define CPU_INFO_ITERATOR int 72 #define CPU_INFO_FOREACH(cii, ci) \ 73 (void)(cii), ci = &cpu_info_store; ci != NULL; ci = ci->ci_next 74 75 /* 76 * To implement a more accurate microtime using the CP0 COUNT register 77 * we need to divide that register by the number of cycles per MHz. 78 * But... 79 * 80 * DIV and DIVU are expensive on MIPS (eg 75 clocks on the R4000). MULT 81 * and MULTU are only 12 clocks on the same CPU. 82 * 83 * The strategy we use is to calculate the reciprocal of cycles per MHz, 84 * scaled by 1<<32. Then we can simply issue a MULTU and pluck of the 85 * HI register and have the results of the division. 86 */ 87 #define MIPS_SET_CI_RECIPROCAL(cpu) \ 88 do { \ 89 KASSERT((cpu)->ci_divisor_delay != 0); \ 90 (cpu)->ci_divisor_recip = 0x100000000ULL / (cpu)->ci_divisor_delay; \ 91 } while (0) 92 93 #define MIPS_COUNT_TO_MHZ(cpu, count, res) \ 94 __asm volatile("multu %1,%2 ; mfhi %0" \ 95 : "=r"((res)) : "r"((count)), "r"((cpu)->ci_divisor_recip)) 96 97 #endif /* !_LOCORE */ 98 #endif /* _KERNEL */ 99 100 /* 101 * CTL_MACHDEP definitions. 102 */ 103 #define CPU_CONSDEV 1 /* dev_t: console terminal device */ 104 #define CPU_BOOTED_KERNEL 2 /* string: booted kernel name */ 105 #define CPU_ROOT_DEVICE 3 /* string: root device name */ 106 #define CPU_LLSC 4 /* OS/CPU supports LL/SC instruction */ 107 108 /* 109 * Platform can override, but note this breaks userland compatibility 110 * with other mips platforms. 111 */ 112 #ifndef CPU_MAXID 113 #define CPU_MAXID 5 /* number of valid machdep ids */ 114 115 #endif 116 117 #ifdef _KERNEL 118 #if defined(_LKM) || defined(_STANDALONE) 119 /* Assume all CPU architectures are valid for LKM's and standlone progs */ 120 #define MIPS1 1 121 #define MIPS3 1 122 #define MIPS4 1 123 #define MIPS32 1 124 #define MIPS64 1 125 #endif 126 127 #if (MIPS1 + MIPS3 + MIPS4 + MIPS32 + MIPS64) == 0 128 #error at least one of MIPS1, MIPS3, MIPS4, MIPS32 or MIPS64 must be specified 129 #endif 130 131 /* Shortcut for MIPS3 or above defined */ 132 #if defined(MIPS3) || defined(MIPS4) || defined(MIPS32) || defined(MIPS64) 133 #define MIPS3_PLUS 1 134 #else 135 #undef MIPS3_PLUS 136 #endif 137 138 /* 139 * Macros to find the CPU architecture we're on at run-time, 140 * or if possible, at compile-time. 141 */ 142 143 #define CPU_ARCH_MIPSx 0 /* XXX unknown */ 144 #define CPU_ARCH_MIPS1 (1 << 0) 145 #define CPU_ARCH_MIPS2 (1 << 1) 146 #define CPU_ARCH_MIPS3 (1 << 2) 147 #define CPU_ARCH_MIPS4 (1 << 3) 148 #define CPU_ARCH_MIPS5 (1 << 4) 149 #define CPU_ARCH_MIPS32 (1 << 5) 150 #define CPU_ARCH_MIPS64 (1 << 6) 151 152 /* Note: must be kept in sync with -ffixed-?? Makefile.mips. */ 153 #define MIPS_CURLWP $23 154 #define MIPS_CURLWP_QUOTED "$23" 155 #define MIPS_CURLWP_CARD 23 156 #define MIPS_CURLWP_FRAME(x) FRAME_S7(x) 157 158 #ifndef _LOCORE 159 160 extern struct cpu_info cpu_info_store; 161 register struct lwp *mips_curlwp asm(MIPS_CURLWP_QUOTED); 162 163 #define curlwp mips_curlwp 164 #define curcpu() (curlwp->l_cpu) 165 #define curpcb ((struct pcb *)curlwp->l_addr) 166 #define fpcurlwp (curcpu()->ci_fpcurlwp) 167 #define cpu_number() (0) 168 #define cpu_proc_fork(p1, p2) 169 170 /* XXX simonb 171 * Should the following be in a cpu_info type structure? 172 * And how many of these are per-cpu vs. per-system? (Ie, 173 * we can assume that all cpus have the same mmu-type, but 174 * maybe not that all cpus run at the same clock speed. 175 * Some SGI's apparently support R12k and R14k in the same 176 * box.) 177 */ 178 extern int cpu_arch; 179 extern int mips_cpu_flags; 180 extern int mips_has_r4k_mmu; 181 extern int mips_has_llsc; 182 extern int mips3_pg_cached; 183 extern u_int mips3_pg_shift; 184 185 #define CPU_MIPS_R4K_MMU 0x0001 186 #define CPU_MIPS_NO_LLSC 0x0002 187 #define CPU_MIPS_CAUSE_IV 0x0004 188 #define CPU_MIPS_HAVE_SPECIAL_CCA 0x0008 /* Defaults to '3' if not set. */ 189 #define CPU_MIPS_CACHED_CCA_MASK 0x0070 190 #define CPU_MIPS_CACHED_CCA_SHIFT 4 191 #define CPU_MIPS_DOUBLE_COUNT 0x0080 /* 1 cp0 count == 2 clock cycles */ 192 #define CPU_MIPS_USE_WAIT 0x0100 /* Use "wait"-based cpu_idle() */ 193 #define CPU_MIPS_NO_WAIT 0x0200 /* Inverse of previous, for mips32/64 */ 194 #define CPU_MIPS_D_CACHE_COHERENT 0x0400 /* D-cache is fully coherent */ 195 #define CPU_MIPS_I_D_CACHE_COHERENT 0x0800 /* I-cache funcs don't need to flush the D-cache */ 196 #define MIPS_NOT_SUPP 0x8000 197 198 #endif /* !_LOCORE */ 199 200 #if ((MIPS1 + MIPS3 + MIPS4 + MIPS32 + MIPS64) == 1) || defined(_LOCORE) 201 202 #if defined(MIPS1) 203 204 # define CPUISMIPS3 0 205 # define CPUIS64BITS 0 206 # define CPUISMIPS32 0 207 # define CPUISMIPS64 0 208 # define CPUISMIPSNN 0 209 # define MIPS_HAS_R4K_MMU 0 210 # define MIPS_HAS_CLOCK 0 211 # define MIPS_HAS_LLSC 0 212 213 #elif defined(MIPS3) || defined(MIPS4) 214 215 # define CPUISMIPS3 1 216 # define CPUIS64BITS 1 217 # define CPUISMIPS32 0 218 # define CPUISMIPS64 0 219 # define CPUISMIPSNN 0 220 # define MIPS_HAS_R4K_MMU 1 221 # define MIPS_HAS_CLOCK 1 222 # if defined(_LOCORE) 223 # if !defined(MIPS3_5900) && !defined(MIPS3_4100) 224 # define MIPS_HAS_LLSC 1 225 # else 226 # define MIPS_HAS_LLSC 0 227 # endif 228 # else /* _LOCORE */ 229 # define MIPS_HAS_LLSC (mips_has_llsc) 230 # endif /* _LOCORE */ 231 232 #elif defined(MIPS32) 233 234 # define CPUISMIPS3 1 235 # define CPUIS64BITS 0 236 # define CPUISMIPS32 1 237 # define CPUISMIPS64 0 238 # define CPUISMIPSNN 1 239 # define MIPS_HAS_R4K_MMU 1 240 # define MIPS_HAS_CLOCK 1 241 # define MIPS_HAS_LLSC 1 242 243 #elif defined(MIPS64) 244 245 # define CPUISMIPS3 1 246 # define CPUIS64BITS 1 247 # define CPUISMIPS32 0 248 # define CPUISMIPS64 1 249 # define CPUISMIPSNN 1 250 # define MIPS_HAS_R4K_MMU 1 251 # define MIPS_HAS_CLOCK 1 252 # define MIPS_HAS_LLSC 1 253 254 #endif 255 256 #else /* run-time test */ 257 258 #ifndef _LOCORE 259 260 #define MIPS_HAS_R4K_MMU (mips_has_r4k_mmu) 261 #define MIPS_HAS_LLSC (mips_has_llsc) 262 263 /* This test is ... rather bogus */ 264 #define CPUISMIPS3 ((cpu_arch & \ 265 (CPU_ARCH_MIPS3 | CPU_ARCH_MIPS4 | CPU_ARCH_MIPS32 | CPU_ARCH_MIPS64)) != 0) 266 267 /* And these aren't much better while the previous test exists as is... */ 268 #define CPUISMIPS32 ((cpu_arch & CPU_ARCH_MIPS32) != 0) 269 #define CPUISMIPS64 ((cpu_arch & CPU_ARCH_MIPS64) != 0) 270 #define CPUISMIPSNN ((cpu_arch & (CPU_ARCH_MIPS32 | CPU_ARCH_MIPS64)) != 0) 271 #define CPUIS64BITS ((cpu_arch & \ 272 (CPU_ARCH_MIPS3 | CPU_ARCH_MIPS4 | CPU_ARCH_MIPS64)) != 0) 273 274 #define MIPS_HAS_CLOCK (cpu_arch >= CPU_ARCH_MIPS3) 275 276 #else /* !_LOCORE */ 277 278 #define MIPS_HAS_LLSC 0 279 280 #endif /* !_LOCORE */ 281 282 #endif /* run-time test */ 283 284 #ifndef _LOCORE 285 286 /* 287 * definitions of cpu-dependent requirements 288 * referenced in generic code 289 */ 290 #define cpu_swapout(p) panic("cpu_swapout: can't get here"); 291 292 void cpu_intr(u_int32_t, u_int32_t, u_int32_t, u_int32_t); 293 294 /* 295 * Arguments to hardclock and gatherstats encapsulate the previous 296 * machine state in an opaque clockframe. 297 */ 298 struct clockframe { 299 int pc; /* program counter at time of interrupt */ 300 int sr; /* status register at time of interrupt */ 301 int ppl; /* previous priority level at time of interrupt */ 302 }; 303 304 /* 305 * A port must provde CLKF_USERMODE() for use in machine-independent code. 306 * These differ on r4000 and r3000 systems; provide them in the 307 * port-dependent file that includes this one, using the macros below. 308 */ 309 310 /* mips1 versions */ 311 #define MIPS1_CLKF_USERMODE(framep) ((framep)->sr & MIPS_SR_KU_PREV) 312 313 /* mips3 versions */ 314 #define MIPS3_CLKF_USERMODE(framep) ((framep)->sr & MIPS_SR_KSU_USER) 315 316 #define CLKF_PC(framep) ((framep)->pc) 317 #define CLKF_INTR(framep) (0) 318 319 #if defined(MIPS3_PLUS) && !defined(MIPS1) /* XXX bogus! */ 320 #define CLKF_USERMODE(framep) MIPS3_CLKF_USERMODE(framep) 321 #endif 322 323 #if !defined(MIPS3_PLUS) && defined(MIPS1) /* XXX bogus! */ 324 #define CLKF_USERMODE(framep) MIPS1_CLKF_USERMODE(framep) 325 #endif 326 327 #if defined(MIPS3_PLUS) && defined(MIPS1) /* XXX bogus! */ 328 #define CLKF_USERMODE(framep) \ 329 ((CPUISMIPS3) ? MIPS3_CLKF_USERMODE(framep): MIPS1_CLKF_USERMODE(framep)) 330 #endif 331 332 /* 333 * This is used during profiling to integrate system time. It can safely 334 * assume that the process is resident. 335 */ 336 #define PROC_PC(p) \ 337 (((struct frame *)(p)->p_md.md_regs)->f_regs[37]) /* XXX PC */ 338 339 /* 340 * Preempt the current process if in interrupt from user mode, 341 * or after the current trap/syscall if in system mode. 342 */ 343 void cpu_need_resched(struct cpu_info *, int); 344 345 /* 346 * Give a profiling tick to the current process when the user profiling 347 * buffer pages are invalid. On the MIPS, request an ast to send us 348 * through trap, marking the proc as needing a profiling tick. 349 */ 350 #define cpu_need_proftick(l) \ 351 do { \ 352 (l)->l_pflag |= LP_OWEUPC; \ 353 aston(l); \ 354 } while (/*CONSTCOND*/0) 355 356 /* 357 * Notify the current lwp (l) that it has a signal pending, 358 * process as soon as possible. 359 */ 360 #define cpu_signotify(l) aston(l) 361 362 #define aston(l) ((l)->l_md.md_astpending = 1) 363 364 /* 365 * Misc prototypes and variable declarations. 366 */ 367 struct lwp; 368 struct user; 369 370 extern struct segtab *segbase; /* current segtab base */ 371 372 /* trap.c */ 373 void netintr(void); 374 int kdbpeek(vaddr_t); 375 376 /* mips_machdep.c */ 377 void dumpsys(void); 378 int savectx(struct user *); 379 void mips_init_msgbuf(void); 380 void savefpregs(struct lwp *); 381 void loadfpregs(struct lwp *); 382 383 /* locore*.S */ 384 int badaddr(void *, size_t); 385 int badaddr64(uint64_t, size_t); 386 387 /* mips_machdep.c */ 388 void cpu_identify(void); 389 void mips_vector_init(void); 390 391 #endif /* ! _LOCORE */ 392 #endif /* _KERNEL */ 393 #endif /* _CPU_H_ */ 394