1 /* $NetBSD: cpu.h,v 1.93 2009/11/27 03:23:11 rmind Exp $ */
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Ralph Campbell and Rick Macklem.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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
34 * @(#)cpu.h 8.4 (Berkeley) 1/4/94
40 #include <mips/cpuregs.h>
43 * Exported definitions unique to NetBSD/mips cpu support.
48 #include <sys/cpu_data.h>
50 #if defined(_KERNEL_OPT)
51 #include "opt_lockdebug.h"
57 int cpu_rev
; /* -1 == wildcard */
58 int cpu_copts
; /* -1 == wildcard */
59 int cpu_isa
; /* -1 == probed (mips32/mips64) */
60 int cpu_ntlb
; /* -1 == unknown, 0 == probed */
62 u_int cpu_cp0flags
; /* presence of some cp0 regs */
63 u_int cpu_cidflags
; /* company-specific flags */
67 extern const struct pridtab
*mycpu
;
70 * bitfield defines for cpu_cp0flags
72 #define MIPS_CP0FL_USE __BIT(0) /* use these flags */
73 #define MIPS_CP0FL_ECC __BIT(1)
74 #define MIPS_CP0FL_CACHE_ERR __BIT(2)
75 #define MIPS_CP0FL_EIRR __BIT(3)
76 #define MIPS_CP0FL_EIMR __BIT(4)
77 #define MIPS_CP0FL_EBASE __BIT(5)
78 #define MIPS_CP0FL_CONFIG __BIT(6)
79 #define MIPS_CP0FL_CONFIGn(n) (__BIT(7) << ((n) & 7))
82 * cpu_cidflags defines, by company
85 * RMI company-specific cpu_cidflags
87 #define MIPS_CIDFL_RMI_TYPE __BITS(0,2)
88 #define CIDFL_RMI_TYPE_XLR 0
89 #define CIDFL_RMI_TYPE_XLS 1
90 #define CIDFL_RMI_TYPE_XLP 2
94 struct cpu_data ci_data
; /* MI per-cpu data */
95 struct cpu_info
*ci_next
; /* Next CPU in list */
96 cpuid_t ci_cpuid
; /* Machine-level identifier */
97 u_long ci_cpu_freq
; /* CPU frequency */
98 u_long ci_cycles_per_hz
; /* CPU freq / hz */
99 u_long ci_divisor_delay
; /* for delay/DELAY */
100 u_long ci_divisor_recip
; /* unused, for obsolete microtime(9) */
101 struct lwp
*ci_curlwp
; /* currently running lwp */
102 struct lwp
*ci_fpcurlwp
; /* the current FPU owner */
103 int ci_want_resched
; /* user preemption pending */
104 int ci_mtx_count
; /* negative count of held mutexes */
105 int ci_mtx_oldspl
; /* saved SPL value */
106 int ci_idepth
; /* hardware interrupt depth */
109 #define CPU_INFO_ITERATOR int
110 #define CPU_INFO_FOREACH(cii, ci) \
111 (void)(cii), ci = &cpu_info_store; ci != NULL; ci = ci->ci_next
113 #endif /* !_LOCORE */
117 * CTL_MACHDEP definitions.
119 #define CPU_CONSDEV 1 /* dev_t: console terminal device */
120 #define CPU_BOOTED_KERNEL 2 /* string: booted kernel name */
121 #define CPU_ROOT_DEVICE 3 /* string: root device name */
122 #define CPU_LLSC 4 /* OS/CPU supports LL/SC instruction */
125 * Platform can override, but note this breaks userland compatibility
126 * with other mips platforms.
129 #define CPU_MAXID 5 /* number of valid machdep ids */
134 #if defined(_LKM) || defined(_STANDALONE)
135 /* Assume all CPU architectures are valid for LKM's and standlone progs */
143 #if (MIPS1 + MIPS3 + MIPS4 + MIPS32 + MIPS64) == 0
144 #error at least one of MIPS1, MIPS3, MIPS4, MIPS32 or MIPS64 must be specified
147 /* Shortcut for MIPS3 or above defined */
148 #if defined(MIPS3) || defined(MIPS4) || defined(MIPS32) || defined(MIPS64)
155 * Macros to find the CPU architecture we're on at run-time,
156 * or if possible, at compile-time.
159 #define CPU_ARCH_MIPSx 0 /* XXX unknown */
160 #define CPU_ARCH_MIPS1 (1 << 0)
161 #define CPU_ARCH_MIPS2 (1 << 1)
162 #define CPU_ARCH_MIPS3 (1 << 2)
163 #define CPU_ARCH_MIPS4 (1 << 3)
164 #define CPU_ARCH_MIPS5 (1 << 4)
165 #define CPU_ARCH_MIPS32 (1 << 5)
166 #define CPU_ARCH_MIPS64 (1 << 6)
168 /* Note: must be kept in sync with -ffixed-?? Makefile.mips. */
169 #define MIPS_CURLWP $23
170 #define MIPS_CURLWP_QUOTED "$23"
171 #define MIPS_CURLWP_CARD 23
172 #define MIPS_CURLWP_FRAME(x) FRAME_S7(x)
176 extern struct cpu_info cpu_info_store
;
177 register struct lwp
*mips_curlwp
asm(MIPS_CURLWP_QUOTED
);
179 #define curlwp mips_curlwp
180 #define curcpu() (curlwp->l_cpu)
181 #define curpcb ((struct pcb *)lwp_getpcb(curlwp))
182 #define fpcurlwp (curcpu()->ci_fpcurlwp)
183 #define cpu_number() (0)
184 #define cpu_proc_fork(p1, p2) ((void)((p2)->p_md.md_abi = (p1)->p_md.md_abi))
187 * Should the following be in a cpu_info type structure?
188 * And how many of these are per-cpu vs. per-system? (Ie,
189 * we can assume that all cpus have the same mmu-type, but
190 * maybe not that all cpus run at the same clock speed.
191 * Some SGI's apparently support R12k and R14k in the same
195 extern int mips_cpu_flags
;
196 extern int mips_has_r4k_mmu
;
197 extern int mips_has_llsc
;
198 extern int mips3_pg_cached
;
200 extern uint64_t mips3_xkphys_cached
;
202 extern u_int mips3_pg_shift
;
204 #define CPU_MIPS_R4K_MMU 0x0001
205 #define CPU_MIPS_NO_LLSC 0x0002
206 #define CPU_MIPS_CAUSE_IV 0x0004
207 #define CPU_MIPS_HAVE_SPECIAL_CCA 0x0008 /* Defaults to '3' if not set. */
208 #define CPU_MIPS_CACHED_CCA_MASK 0x0070
209 #define CPU_MIPS_CACHED_CCA_SHIFT 4
210 #define CPU_MIPS_DOUBLE_COUNT 0x0080 /* 1 cp0 count == 2 clock cycles */
211 #define CPU_MIPS_USE_WAIT 0x0100 /* Use "wait"-based cpu_idle() */
212 #define CPU_MIPS_NO_WAIT 0x0200 /* Inverse of previous, for mips32/64 */
213 #define CPU_MIPS_D_CACHE_COHERENT 0x0400 /* D-cache is fully coherent */
214 #define CPU_MIPS_I_D_CACHE_COHERENT 0x0800 /* I-cache funcs don't need to flush the D-cache */
215 #define CPU_MIPS_NO_LLADDR 0x1000
216 #define CPU_MIPS_HAVE_MxCR 0x2000 /* have mfcr, mtcr insns */
217 #define MIPS_NOT_SUPP 0x8000
219 #endif /* !_LOCORE */
221 #if ((MIPS1 + MIPS3 + MIPS4 + MIPS32 + MIPS64) == 1) || defined(_LOCORE)
225 # define CPUISMIPS3 0
226 # define CPUIS64BITS 0
227 # define CPUISMIPS32 0
228 # define CPUISMIPS64 0
229 # define CPUISMIPSNN 0
230 # define MIPS_HAS_R4K_MMU 0
231 # define MIPS_HAS_CLOCK 0
232 # define MIPS_HAS_LLSC 0
233 # define MIPS_HAS_LLADDR 0
235 #elif defined(MIPS3) || defined(MIPS4)
237 # define CPUISMIPS3 1
238 # define CPUIS64BITS 1
239 # define CPUISMIPS32 0
240 # define CPUISMIPS64 0
241 # define CPUISMIPSNN 0
242 # define MIPS_HAS_R4K_MMU 1
243 # define MIPS_HAS_CLOCK 1
244 # if defined(_LOCORE)
245 # if !defined(MIPS3_5900) && !defined(MIPS3_4100)
246 # define MIPS_HAS_LLSC 1
248 # define MIPS_HAS_LLSC 0
251 # define MIPS_HAS_LLSC (mips_has_llsc)
252 # endif /* _LOCORE */
253 # define MIPS_HAS_LLADDR ((mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0)
255 #elif defined(MIPS32)
257 # define CPUISMIPS3 1
258 # define CPUIS64BITS 0
259 # define CPUISMIPS32 1
260 # define CPUISMIPS64 0
261 # define CPUISMIPSNN 1
262 # define MIPS_HAS_R4K_MMU 1
263 # define MIPS_HAS_CLOCK 1
264 # define MIPS_HAS_LLSC 1
265 # define MIPS_HAS_LLADDR ((mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0)
267 #elif defined(MIPS64)
269 # define CPUISMIPS3 1
270 # define CPUIS64BITS 1
271 # define CPUISMIPS32 0
272 # define CPUISMIPS64 1
273 # define CPUISMIPSNN 1
274 # define MIPS_HAS_R4K_MMU 1
275 # define MIPS_HAS_CLOCK 1
276 # define MIPS_HAS_LLSC 1
277 # define MIPS_HAS_LLADDR ((mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0)
281 #else /* run-time test */
285 #define MIPS_HAS_R4K_MMU (mips_has_r4k_mmu)
286 #define MIPS_HAS_LLSC (mips_has_llsc)
287 #define MIPS_HAS_LLADDR ((mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0)
289 /* This test is ... rather bogus */
290 #define CPUISMIPS3 ((cpu_arch & \
291 (CPU_ARCH_MIPS3 | CPU_ARCH_MIPS4 | CPU_ARCH_MIPS32 | CPU_ARCH_MIPS64)) != 0)
293 /* And these aren't much better while the previous test exists as is... */
294 #define CPUISMIPS32 ((cpu_arch & CPU_ARCH_MIPS32) != 0)
295 #define CPUISMIPS64 ((cpu_arch & CPU_ARCH_MIPS64) != 0)
296 #define CPUISMIPSNN ((cpu_arch & (CPU_ARCH_MIPS32 | CPU_ARCH_MIPS64)) != 0)
297 #define CPUIS64BITS ((cpu_arch & \
298 (CPU_ARCH_MIPS3 | CPU_ARCH_MIPS4 | CPU_ARCH_MIPS64)) != 0)
300 #define MIPS_HAS_CLOCK (cpu_arch >= CPU_ARCH_MIPS3)
304 #define MIPS_HAS_LLSC 0
306 #endif /* !_LOCORE */
308 #endif /* run-time test */
313 * definitions of cpu-dependent requirements
314 * referenced in generic code
317 void cpu_intr(uint32_t, uint32_t, vaddr_t
, uint32_t);
320 * Arguments to hardclock and gatherstats encapsulate the previous
321 * machine state in an opaque clockframe.
324 vaddr_t pc
; /* program counter at time of interrupt */
325 uint32_t sr
; /* status register at time of interrupt */
326 u_int ppl
; /* previous priority level at time of interrupt */
330 * A port must provde CLKF_USERMODE() for use in machine-independent code.
331 * These differ on r4000 and r3000 systems; provide them in the
332 * port-dependent file that includes this one, using the macros below.
336 #define MIPS1_CLKF_USERMODE(framep) ((framep)->sr & MIPS_SR_KU_PREV)
339 #define MIPS3_CLKF_USERMODE(framep) ((framep)->sr & MIPS_SR_KSU_USER)
341 #define CLKF_PC(framep) ((framep)->pc)
342 #define CLKF_INTR(framep) (0)
344 #if defined(MIPS3_PLUS) && !defined(MIPS1) /* XXX bogus! */
345 #define CLKF_USERMODE(framep) MIPS3_CLKF_USERMODE(framep)
348 #if !defined(MIPS3_PLUS) && defined(MIPS1) /* XXX bogus! */
349 #define CLKF_USERMODE(framep) MIPS1_CLKF_USERMODE(framep)
352 #if defined(MIPS3_PLUS) && defined(MIPS1) /* XXX bogus! */
353 #define CLKF_USERMODE(framep) \
354 ((CPUISMIPS3) ? MIPS3_CLKF_USERMODE(framep): MIPS1_CLKF_USERMODE(framep))
358 * This is used during profiling to integrate system time. It can safely
359 * assume that the process is resident.
362 (((struct frame *)(p)->p_md.md_regs)->f_regs[37]) /* XXX PC */
365 * Preempt the current process if in interrupt from user mode,
366 * or after the current trap/syscall if in system mode.
368 void cpu_need_resched(struct cpu_info
*, int);
371 * Give a profiling tick to the current process when the user profiling
372 * buffer pages are invalid. On the MIPS, request an ast to send us
373 * through trap, marking the proc as needing a profiling tick.
375 #define cpu_need_proftick(l) \
377 (l)->l_pflag |= LP_OWEUPC; \
379 } while (/*CONSTCOND*/0)
382 * Notify the current lwp (l) that it has a signal pending,
383 * process as soon as possible.
385 #define cpu_signotify(l) aston(l)
387 #define aston(l) ((l)->l_md.md_astpending = 1)
390 * Misc prototypes and variable declarations.
395 extern struct segtab
*segbase
; /* current segtab base */
398 int8_t ufetch_int8(void *);
399 int16_t ufetch_int16(void *);
400 int32_t ufetch_int32(void *);
401 uint8_t ufetch_uint8(void *);
402 uint16_t ufetch_uint16(void *);
403 uint32_t ufetch_uint32(void *);
404 int8_t ufetch_int8_intrsafe(void *);
405 int16_t ufetch_int16_intrsafe(void *);
406 int32_t ufetch_int32_intrsafe(void *);
407 uint8_t ufetch_uint8_intrsafe(void *);
408 uint16_t ufetch_uint16_intrsafe(void *);
409 uint32_t ufetch_uint32_intrsafe(void *);
411 int64_t ufetch_int64(void *);
412 uint64_t ufetch_uint64(void *);
413 int64_t ufetch_int64_intrsafe(void *);
414 uint64_t ufetch_uint64_intrsafe(void *);
416 char ufetch_char(void *);
417 short ufetch_short(void *);
418 int ufetch_int(void *);
419 long ufetch_long(void *);
420 char ufetch_char_intrsafe(void *);
421 short ufetch_short_intrsafe(void *);
422 int ufetch_int_intrsafe(void *);
423 long ufetch_long_intrsafe(void *);
425 u_char
ufetch_uchar(void *);
426 u_short
ufetch_ushort(void *);
427 u_int
ufetch_uint(void *);
428 u_long
ufetch_ulong(void *);
429 u_char
ufetch_uchar_intrsafe(void *);
430 u_short
ufetch_ushort_intrsafe(void *);
431 u_int
ufetch_uint_intrsafe(void *);
432 u_long
ufetch_ulong_intrsafe(void *);
433 void *ufetch_ptr(void *);
435 int ustore_int8(void *, int8_t);
436 int ustore_int16(void *, int16_t);
437 int ustore_int32(void *, int32_t);
438 int ustore_uint8(void *, uint8_t);
439 int ustore_uint16(void *, uint16_t);
440 int ustore_uint32(void *, uint32_t);
441 int ustore_int8_intrsafe(void *, int8_t);
442 int ustore_int16_intrsafe(void *, int16_t);
443 int ustore_int32_intrsafe(void *, int32_t);
444 int ustore_uint8_intrsafe(void *, uint8_t);
445 int ustore_uint16_intrsafe(void *, uint16_t);
446 int ustore_uint32_intrsafe(void *, uint32_t);
448 int ustore_int64(void *, int64_t);
449 int ustore_uint64(void *, uint64_t);
450 int ustore_int64_intrsafe(void *, int64_t);
451 int ustore_uint64_intrsafe(void *, uint64_t);
453 int ustore_char(void *, char);
454 int ustore_char_intrsafe(void *, char);
455 int ustore_short(void *, short);
456 int ustore_short_intrsafe(void *, short);
457 int ustore_int(void *, int);
458 int ustore_int_intrsafe(void *, int);
459 int ustore_long(void *, long);
460 int ustore_long_intrsafe(void *, long);
461 int ustore_uchar(void *, u_char
);
462 int ustore_uchar_intrsafe(void *, u_char
);
463 int ustore_ushort(void *, u_short
);
464 int ustore_ushort_intrsafe(void *, u_short
);
465 int ustore_uint(void *, u_int
);
466 int ustore_uint_intrsafe(void *, u_int
);
467 int ustore_ulong(void *, u_long
);
468 int ustore_ulong_intrsafe(void *, u_long
);
469 int ustore_ptr(void *, void *);
470 int ustore_ptr_intrsafe(void *, void *);
472 int ustore_uint32_isync(void *, uint32_t);
476 int kdbpeek(vaddr_t
);
480 int savectx(struct pcb
*);
481 void mips_init_msgbuf(void);
482 void mips_init_lwp0_uarea(void);
483 void savefpregs(struct lwp
*);
484 void loadfpregs(struct lwp
*);
487 int badaddr(void *, size_t);
488 int badaddr64(uint64_t, size_t);
491 void cpu_identify(void);
492 void mips_vector_init(void);
494 #endif /* ! _LOCORE */