1 /* $OpenBSD: cpu.h,v 1.79 2024/10/22 12:51:56 mpi Exp $ */
2 /* $NetBSD: cpu.h,v 1.1 1996/09/30 16:34:21 ws Exp $ */
3
4 /*
5 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
6 * Copyright (C) 1995, 1996 TooLs GmbH.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by TooLs GmbH.
20 * 4. The name of TooLs GmbH may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34 #ifndef _POWERPC_CPU_H_
35 #define _POWERPC_CPU_H_
36
37 #include <machine/frame.h>
38
39 #include <sys/clockintr.h>
40 #include <sys/device.h>
41 #include <sys/sched.h>
42 #include <sys/srp.h>
43
44 struct cpu_info {
45 struct device *ci_dev; /* our device */
46 struct schedstate_percpu ci_schedstate; /* scheduler state */
47
48 struct proc *ci_curproc;
49
50 struct pcb *ci_curpcb;
51 struct pmap *ci_curpm;
52 struct proc *ci_fpuproc;
53 struct proc *ci_vecproc;
54 int ci_cpuid;
55
56 volatile int ci_want_resched;
57 volatile int ci_cpl;
58 volatile int ci_ipending;
59 volatile int ci_dec_deferred;
60
61 volatile int ci_flags;
62 #define CI_FLAGS_SLEEPING 2
63
64 #if defined(MULTIPROCESSOR)
65 struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM];
66 #endif
67
68 int ci_idepth;
69 char *ci_intstk;
70 #define CPUSAVE_LEN 8
71 register_t ci_tempsave[CPUSAVE_LEN];
72 register_t ci_ddbsave[CPUSAVE_LEN];
73 #define DISISAVE_LEN 4
74 register_t ci_disisave[DISISAVE_LEN];
75
76 struct clockqueue ci_queue;
77
78 volatile int ci_ddb_paused;
79 #define CI_DDB_RUNNING 0
80 #define CI_DDB_SHOULDSTOP 1
81 #define CI_DDB_STOPPED 2
82 #define CI_DDB_ENTERDDB 3
83 #define CI_DDB_INDDB 4
84
85 u_int32_t ci_randseed;
86
87 #ifdef DIAGNOSTIC
88 int ci_mutex_level;
89 #endif
90 #ifdef GPROF
91 struct gmonparam *ci_gmon;
92 struct clockintr ci_gmonclock;
93 #endif
94 char ci_panicbuf[512];
95 };
96
97 static __inline struct cpu_info *
curcpu(void)98 curcpu(void)
99 {
100 struct cpu_info *ci;
101
102 __asm volatile ("mfsprg %0,0" : "=r"(ci));
103 return ci;
104 }
105
106 #define curpcb (curcpu()->ci_curpcb)
107 #define curpm (curcpu()->ci_curpm)
108
109 #define CPU_INFO_UNIT(ci) ((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0)
110
111 #ifdef MULTIPROCESSOR
112
113 #define PPC_MAXPROCS 4
114
115 static __inline int
cpu_number(void)116 cpu_number(void)
117 {
118 int pir;
119
120 pir = curcpu()->ci_cpuid;
121 return pir;
122 }
123
124 void cpu_boot_secondary_processors(void);
125
126 #define CPU_IS_PRIMARY(ci) ((ci)->ci_cpuid == 0)
127 #define CPU_IS_RUNNING(ci) 1
128 #define CPU_INFO_ITERATOR int
129 #define CPU_INFO_FOREACH(cii, ci) \
130 for (cii = 0, ci = &cpu_info[0]; cii < ncpusfound; cii++, ci++)
131
132 void cpu_unidle(struct cpu_info *);
133
134 #else
135
136 #define PPC_MAXPROCS 1
137
138 #define cpu_number() 0
139
140 #define CPU_IS_PRIMARY(ci) 1
141 #define CPU_IS_RUNNING(ci) 1
142 #define CPU_INFO_ITERATOR int
143 #define CPU_INFO_FOREACH(cii, ci) \
144 for (cii = 0, ci = curcpu(); ci != NULL; ci = NULL)
145
146 #define cpu_unidle(ci)
147
148 #endif
149
150 #define CPU_BUSY_CYCLE() do {} while (0)
151
152 #define MAXCPUS PPC_MAXPROCS
153
154 extern struct cpu_info cpu_info[PPC_MAXPROCS];
155
156 #define CLKF_USERMODE(frame) (((frame)->srr1 & PSL_PR) != 0)
157 #define CLKF_PC(frame) ((frame)->srr0)
158 #define CLKF_INTR(frame) ((frame)->depth != 0)
159
160 extern int ppc_cpuidle;
161 extern int ppc_proc_is_64b;
162 extern int ppc_nobat;
163
164 void cpu_bootstrap(void);
165
166 static inline unsigned int
cpu_rnd_messybits(void)167 cpu_rnd_messybits(void)
168 {
169 unsigned int hi, lo;
170
171 __asm volatile("mftbu %0; mftb %1" : "=r" (hi), "=r" (lo));
172
173 return (hi ^ lo);
174 }
175
176 /*
177 * This is used during profiling to integrate system time.
178 */
179 #define PROC_PC(p) (trapframe(p)->srr0)
180 #define PROC_STACK(p) (trapframe(p)->fixreg[1])
181
182 void delay(unsigned);
183 #define DELAY(n) delay(n)
184
185 #define aston(p) ((p)->p_md.md_astpending = 1)
186
187 /*
188 * Preempt the current process if in interrupt from user mode,
189 * or after the current trap/syscall if in system mode.
190 */
191 #define need_resched(ci) \
192 do { \
193 ci->ci_want_resched = 1; \
194 if (ci->ci_curproc != NULL) \
195 aston(ci->ci_curproc); \
196 } while (0)
197 #define clear_resched(ci) (ci)->ci_want_resched = 0
198
199 #define need_proftick(p) aston(p)
200
201 void signotify(struct proc *);
202
203 extern char *bootpath;
204
205 #ifndef CACHELINESIZE
206 #define CACHELINESIZE 32 /* For now XXX */
207 #endif
208
209 static __inline void
syncicache(void * from,size_t len)210 syncicache(void *from, size_t len)
211 {
212 size_t by, i;
213
214 by = CACHELINESIZE;
215 i = 0;
216 do {
217 __asm volatile ("dcbst %0,%1" :: "r"(from), "r"(i));
218 i += by;
219 } while (i < len);
220 __asm volatile ("sync");
221 i = 0;
222 do {
223 __asm volatile ("icbi %0,%1" :: "r"(from), "r"(i));
224 i += by;
225 } while (i < len);
226 __asm volatile ("sync; isync");
227 }
228
229 static __inline void
invdcache(void * from,int len)230 invdcache(void *from, int len)
231 {
232 int l;
233 char *p = from;
234
235 len = len + (((u_int32_t) from) & (CACHELINESIZE - 1));
236 l = len;
237
238 do {
239 __asm volatile ("dcbi 0,%0" :: "r"(p));
240 p += CACHELINESIZE;
241 } while ((l -= CACHELINESIZE) > 0);
242 __asm volatile ("sync");
243 }
244
245 static __inline void
flushdcache(void * from,int len)246 flushdcache(void *from, int len)
247 {
248 int l;
249 char *p = from;
250
251 len = len + (((u_int32_t) from) & (CACHELINESIZE - 1));
252 l = len;
253
254 do {
255 __asm volatile ("dcbf 0,%0" :: "r"(p));
256 p += CACHELINESIZE;
257 } while ((l -= CACHELINESIZE) > 0);
258 __asm volatile ("sync");
259 }
260
261 #define FUNC_SPR(n, name) \
262 static __inline u_int32_t ppc_mf ## name(void) \
263 { \
264 u_int32_t ret; \
265 __asm volatile ("mfspr %0," # n : "=r" (ret)); \
266 return ret; \
267 } \
268 static __inline void ppc_mt ## name(u_int32_t val) \
269 { \
270 __asm volatile ("mtspr "# n ",%0" :: "r" (val)); \
271 } \
272
273 FUNC_SPR(0, mq)
274 FUNC_SPR(1, xer)
275 FUNC_SPR(4, rtcu)
276 FUNC_SPR(5, rtcl)
277 FUNC_SPR(8, lr)
278 FUNC_SPR(9, ctr)
279 FUNC_SPR(18, dsisr)
280 FUNC_SPR(19, dar)
281 FUNC_SPR(22, dec)
282 FUNC_SPR(25, sdr1)
283 FUNC_SPR(26, srr0)
284 FUNC_SPR(27, srr1)
285 FUNC_SPR(256, vrsave)
286 FUNC_SPR(272, sprg0)
287 FUNC_SPR(273, sprg1)
288 FUNC_SPR(274, sprg2)
289 FUNC_SPR(275, sprg3)
290 FUNC_SPR(280, asr)
291 FUNC_SPR(282, ear)
292 FUNC_SPR(287, pvr)
293 FUNC_SPR(311, hior)
294 FUNC_SPR(528, ibat0u)
295 FUNC_SPR(529, ibat0l)
296 FUNC_SPR(530, ibat1u)
297 FUNC_SPR(531, ibat1l)
298 FUNC_SPR(532, ibat2u)
299 FUNC_SPR(533, ibat2l)
300 FUNC_SPR(534, ibat3u)
301 FUNC_SPR(535, ibat3l)
302 FUNC_SPR(560, ibat4u)
303 FUNC_SPR(561, ibat4l)
304 FUNC_SPR(562, ibat5u)
305 FUNC_SPR(563, ibat5l)
306 FUNC_SPR(564, ibat6u)
307 FUNC_SPR(565, ibat6l)
308 FUNC_SPR(566, ibat7u)
309 FUNC_SPR(567, ibat7l)
310 FUNC_SPR(536, dbat0u)
311 FUNC_SPR(537, dbat0l)
312 FUNC_SPR(538, dbat1u)
313 FUNC_SPR(539, dbat1l)
314 FUNC_SPR(540, dbat2u)
315 FUNC_SPR(541, dbat2l)
316 FUNC_SPR(542, dbat3u)
317 FUNC_SPR(543, dbat3l)
318 FUNC_SPR(568, dbat4u)
319 FUNC_SPR(569, dbat4l)
320 FUNC_SPR(570, dbat5u)
321 FUNC_SPR(571, dbat5l)
322 FUNC_SPR(572, dbat6u)
323 FUNC_SPR(573, dbat6l)
324 FUNC_SPR(574, dbat7u)
325 FUNC_SPR(575, dbat7l)
326 FUNC_SPR(1009, hid1)
327 FUNC_SPR(1010, iabr)
328 FUNC_SPR(1017, l2cr)
329 FUNC_SPR(1018, l3cr)
330 FUNC_SPR(1013, dabr)
331 FUNC_SPR(1023, pir)
332
333 static __inline u_int32_t
ppc_mftbl(void)334 ppc_mftbl(void)
335 {
336 int ret;
337 __asm volatile ("mftb %0" : "=r" (ret));
338 return ret;
339 }
340
341
342 static __inline u_int64_t
ppc_mftb(void)343 ppc_mftb(void)
344 {
345 u_long scratch;
346 u_int64_t tb;
347
348 __asm volatile ("1: mftbu %0; mftb %L0; mftbu %1;"
349 " cmpw 0,%0,%1; bne 1b" : "=r"(tb), "=r"(scratch));
350 return tb;
351 }
352
353 static __inline void
ppc_mttb(u_int64_t tb)354 ppc_mttb(u_int64_t tb)
355 {
356 __asm volatile ("mttbl %0" :: "r"(0));
357 __asm volatile ("mttbu %0" :: "r"((u_int32_t)(tb >> 32)));
358 __asm volatile ("mttbl %0" :: "r"((u_int32_t)(tb & 0xffffffff)));
359 }
360
361 static __inline u_int32_t
ppc_mfmsr(void)362 ppc_mfmsr(void)
363 {
364 int ret;
365 __asm volatile ("mfmsr %0" : "=r" (ret));
366 return ret;
367 }
368
369 static __inline void
ppc_mtmsr(u_int32_t val)370 ppc_mtmsr(u_int32_t val)
371 {
372 __asm volatile ("mtmsr %0" :: "r" (val));
373 }
374
375 static __inline void
ppc_mtsrin(u_int32_t val,u_int32_t sn_shifted)376 ppc_mtsrin(u_int32_t val, u_int32_t sn_shifted)
377 {
378 __asm volatile ("mtsrin %0,%1" :: "r"(val), "r"(sn_shifted));
379 }
380
381 u_int64_t ppc64_mfscomc(void);
382 void ppc_mtscomc(u_int32_t);
383 void ppc64_mtscomc(u_int64_t);
384 u_int64_t ppc64_mfscomd(void);
385 void ppc_mtscomd(u_int32_t);
386 u_int32_t ppc_mfhid0(void);
387 void ppc_mthid0(u_int32_t);
388 u_int64_t ppc64_mfhid1(void);
389 void ppc64_mthid1(u_int64_t);
390 u_int64_t ppc64_mfhid4(void);
391 void ppc64_mthid4(u_int64_t);
392 u_int64_t ppc64_mfhid5(void);
393 void ppc64_mthid5(u_int64_t);
394
395 #include <machine/psl.h>
396
397 /*
398 * General functions to enable and disable interrupts
399 * without having inlined assembly code in many functions.
400 */
401 static __inline void
ppc_intr_enable(int enable)402 ppc_intr_enable(int enable)
403 {
404 u_int32_t msr;
405 if (enable != 0) {
406 msr = ppc_mfmsr();
407 msr |= PSL_EE;
408 ppc_mtmsr(msr);
409 }
410 }
411
412 static __inline int
ppc_intr_disable(void)413 ppc_intr_disable(void)
414 {
415 u_int32_t emsr, dmsr;
416 emsr = ppc_mfmsr();
417 dmsr = emsr & ~PSL_EE;
418 ppc_mtmsr(dmsr);
419 return (emsr & PSL_EE);
420 }
421
422 static inline void
intr_enable(void)423 intr_enable(void)
424 {
425 ppc_mtmsr(ppc_mfmsr() | PSL_EE);
426 }
427
428 static __inline u_long
intr_disable(void)429 intr_disable(void)
430 {
431 return ppc_intr_disable();
432 }
433
434 static __inline void
intr_restore(u_long s)435 intr_restore(u_long s)
436 {
437 ppc_intr_enable(s);
438 }
439
440 int ppc_cpuspeed(int *);
441
442 /*
443 * PowerPC CPU types
444 */
445 #define PPC_CPU_MPC601 1
446 #define PPC_CPU_MPC603 3
447 #define PPC_CPU_MPC604 4
448 #define PPC_CPU_MPC603e 6
449 #define PPC_CPU_MPC603ev 7
450 #define PPC_CPU_MPC750 8
451 #define PPC_CPU_MPC604ev 9
452 #define PPC_CPU_MPC7400 12
453 #define PPC_CPU_IBM970 0x0039
454 #define PPC_CPU_IBM970FX 0x003c
455 #define PPC_CPU_IBM970MP 0x0044
456 #define PPC_CPU_IBM750FX 0x7000
457 #define PPC_CPU_MPC7410 0x800c
458 #define PPC_CPU_MPC7447A 0x8003
459 #define PPC_CPU_MPC7448 0x8004
460 #define PPC_CPU_MPC7450 0x8000
461 #define PPC_CPU_MPC7455 0x8001
462 #define PPC_CPU_MPC7457 0x8002
463 #define PPC_CPU_MPC83xx 0x8083
464
465 /*
466 * This needs to be included late since it relies on definitions higher
467 * up in this file.
468 */
469 #if defined(MULTIPROCESSOR) && defined(_KERNEL)
470 #include <sys/mplock.h>
471 #endif
472
473 #endif /* _POWERPC_CPU_H_ */
474