1 /* $OpenBSD: cpu.h,v 1.74 2024/05/21 23:16:06 jsg Exp $ */
2 /* $NetBSD: cpu.h,v 1.45 2000/08/21 02:03:12 thorpej Exp $ */
3
4 /*-
5 * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
10 * NASA Ames Research Center.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * Copyright (c) 1988 University of Utah.
36 * Copyright (c) 1982, 1990, 1993
37 * The Regents of the University of California. All rights reserved.
38 *
39 * This code is derived from software contributed to Berkeley by
40 * the Systems Programming Group of the University of Utah Computer
41 * Science Department.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. Neither the name of the University nor the names of its contributors
52 * may be used to endorse or promote products derived from this software
53 * without specific prior written permission.
54 *
55 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
56 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
59 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
60 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
61 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 * SUCH DAMAGE.
66 *
67 * from: Utah $Hdr: cpu.h 1.16 91/03/25$
68 *
69 * @(#)cpu.h 8.4 (Berkeley) 1/5/94
70 */
71
72 #ifndef _MACHINE_CPU_H_
73 #define _MACHINE_CPU_H_
74
75 #ifndef NO_IEEE
76 typedef union alpha_s_float {
77 u_int32_t i;
78 u_int32_t frac: 23,
79 exp: 8,
80 sign: 1;
81 } s_float;
82
83 typedef union alpha_t_float {
84 u_int64_t i;
85 u_int64_t frac: 52,
86 exp: 11,
87 sign: 1;
88 } t_float;
89 #endif
90
91 /*
92 * Exported definitions unique to Alpha cpu support.
93 */
94
95 #ifdef _KERNEL
96
97 #include <machine/alpha_cpu.h>
98 #include <machine/frame.h>
99 #include <machine/bus.h>
100 #include <machine/intr.h>
101 #include <sys/cdefs.h>
102 #include <sys/clockintr.h>
103 #include <sys/device.h>
104 #include <sys/sched.h>
105 #include <sys/srp.h>
106
107 struct pcb;
108 struct proc;
109 struct reg;
110 struct rpb;
111 struct trapframe;
112
113 extern u_long cpu_implver; /* from IMPLVER instruction */
114 extern u_long cpu_amask; /* from AMASK instruction */
115 extern int bootdev_debug;
116 extern int alpha_fp_sync_complete;
117
118 void XentArith(u_int64_t, u_int64_t, u_int64_t); /* MAGIC */
119 void XentIF(u_int64_t, u_int64_t, u_int64_t); /* MAGIC */
120 void XentInt(u_int64_t, u_int64_t, u_int64_t); /* MAGIC */
121 void XentMM(u_int64_t, u_int64_t, u_int64_t); /* MAGIC */
122 void XentRestart(void); /* MAGIC */
123 void XentSys(u_int64_t, u_int64_t, u_int64_t); /* MAGIC */
124 void XentUna(u_int64_t, u_int64_t, u_int64_t); /* MAGIC */
125 void alpha_init(u_long, u_long, u_long, u_long, u_long);
126 int alpha_pa_access(u_long);
127 void ast(struct trapframe *);
128 int badaddr(void *, size_t);
129 int badaddr_read(void *, size_t, void *);
130 u_int64_t console_restart(struct trapframe *);
131 void do_sir(void);
132 void dumpconf(void);
133 void exception_return(void); /* MAGIC */
134 void frametoreg(struct trapframe *, struct reg *);
135 long fswintrberr(void); /* MAGIC */
136 void init_bootstrap_console(void);
137 void init_prom_interface(struct rpb *);
138 void interrupt(unsigned long, unsigned long, unsigned long,
139 struct trapframe *);
140 void machine_check(unsigned long, struct trapframe *, unsigned long,
141 unsigned long);
142 u_int64_t hwrpb_checksum(void);
143 void hwrpb_restart_setup(void);
144 void proc_trampoline(void); /* MAGIC */
145 void regdump(struct trapframe *);
146 void regtoframe(struct reg *, struct trapframe *);
147 void savectx(struct pcb *);
148 void syscall(u_int64_t, struct trapframe *);
149 void trap(unsigned long, unsigned long, unsigned long, unsigned long,
150 struct trapframe *);
151 void trap_init(void);
152 void enable_nsio_ide(bus_space_tag_t);
153
154 /* Multiprocessor glue; cpu.c */
155 struct cpu_info;
156 int cpu_iccb_send(cpuid_t, const char *);
157 void cpu_iccb_receive(void);
158 void cpu_hatch(struct cpu_info *);
159 __dead
160 void cpu_halt(void);
161 void cpu_halt_secondary(unsigned long);
162 void cpu_spinup_trampoline(void); /* MAGIC */
163 void cpu_pause(unsigned long);
164 void cpu_resume(unsigned long);
165
166 /*
167 * Machine check information.
168 */
169 struct mchkinfo {
170 volatile int mc_expected; /* machine check is expected */
171 volatile int mc_received; /* machine check was received */
172 };
173
174 struct cpu_info {
175 /*
176 * Private members accessed in assembly with 8 bit offsets.
177 */
178 struct proc *ci_curproc; /* current owner of the processor */
179 paddr_t ci_curpcb; /* PA of current HW PCB */
180
181 /*
182 * Public members.
183 */
184 struct schedstate_percpu ci_schedstate; /* scheduler state */
185 #ifdef DIAGNOSTIC
186 int ci_mutex_level;
187 #endif
188 cpuid_t ci_cpuid; /* our CPU ID */
189 struct cpu_info *ci_next;
190 u_int32_t ci_randseed;
191
192 #if defined(MULTIPROCESSOR)
193 struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM];
194 #endif
195
196 /*
197 * Private members.
198 */
199 struct mchkinfo ci_mcinfo; /* machine check info */
200 struct proc *ci_fpcurproc; /* current owner of the FPU */
201 struct pcb *ci_idle_pcb; /* our idle PCB */
202 paddr_t ci_idle_pcb_paddr; /* PA of idle PCB */
203 struct device *ci_dev; /* pointer to our device */
204 u_long ci_want_resched; /* preempt current process */
205 u_long ci_intrdepth; /* interrupt trap depth */
206 struct trapframe *ci_db_regs; /* registers for debuggers */
207
208 #if defined(MULTIPROCESSOR)
209 volatile u_long ci_flags; /* flags; see below */
210 volatile u_long ci_ipis; /* interprocessor interrupts pending */
211 #endif
212 #ifdef GPROF
213 struct gmonparam *ci_gmon;
214 struct clockintr ci_gmonclock;
215 #endif
216 struct clockqueue ci_queue;
217 char ci_panicbuf[512];
218 };
219
220 #define CPUF_PRIMARY 0x01 /* CPU is primary CPU */
221 #define CPUF_RUNNING 0x02 /* CPU is running */
222 #define CPUF_PAUSED 0x04 /* CPU is paused */
223 #define CPUF_FPUSAVE 0x08 /* CPU is currently in fpusave_cpu() */
224
225 void fpusave_cpu(struct cpu_info *, int);
226 void fpusave_proc(struct proc *, int);
227
228 extern struct cpu_info cpu_info_primary;
229 extern struct cpu_info *cpu_info_list;
230
231 #define CPU_INFO_UNIT(ci) ((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0)
232 #define CPU_INFO_ITERATOR int
233 #define CPU_INFO_FOREACH(cii, ci) for (cii = 0, ci = cpu_info_list; \
234 ci != NULL; ci = ci->ci_next)
235
236 #define MAXCPUS ALPHA_MAXPROCS
237
238 #if defined(MULTIPROCESSOR)
239 extern volatile u_long cpus_running;
240 extern volatile u_long cpus_paused;
241 extern struct cpu_info *cpu_info[];
242
243 #define curcpu() ((struct cpu_info *)alpha_pal_rdval())
244 #define CPU_IS_PRIMARY(ci) ((ci)->ci_flags & CPUF_PRIMARY)
245 #define CPU_IS_RUNNING(ci) ((ci)->ci_flags & CPUF_RUNNING)
246
247 void cpu_boot_secondary_processors(void);
248
249 void cpu_pause_resume(unsigned long, int);
250 void cpu_pause_resume_all(int);
251 void cpu_unidle(struct cpu_info *);
252
253 /*
254 * On the Alpha, interprocessor interrupts come in at device priority
255 * level. This can cause some problems while waiting for r/w spinlocks
256 * from a high'ish priority level: IPIs that come in will not be processed.
257 * This can lead to deadlock.
258 *
259 * This hook allows IPIs to be processed while a spinlock's interlock
260 * is released.
261 */
262 #define CPU_BUSY_CYCLE() \
263 do { \
264 struct cpu_info *__ci = curcpu(); \
265 int __s; \
266 \
267 if (__ci->ci_ipis != 0) { \
268 __s = splipi(); \
269 alpha_ipi_process_with_frame(__ci); \
270 splx(__s); \
271 } \
272 } while (0)
273
274 #else /* ! MULTIPROCESSOR */
275
276 #define curcpu() (&cpu_info_primary)
277 #define CPU_IS_PRIMARY(ci) 1
278 #define CPU_IS_RUNNING(ci) 1
279 #define cpu_unidle(ci) do { /* nothing */ } while (0)
280 #define CPU_BUSY_CYCLE() do {} while (0)
281
282 #endif /* MULTIPROCESSOR */
283
284
285 #define curproc curcpu()->ci_curproc
286 #define fpcurproc curcpu()->ci_fpcurproc
287 #define curpcb curcpu()->ci_curpcb
288
289 /*
290 * definitions of cpu-dependent requirements
291 * referenced in generic code
292 */
293 #define cpu_number() alpha_pal_whami()
294
295 static inline unsigned int
cpu_rnd_messybits(void)296 cpu_rnd_messybits(void)
297 {
298 return alpha_rpcc();
299 }
300
301 /*
302 * Arguments to clockintr_dispatch encapsulate the previous
303 * machine state in an opaque clockframe. On the Alpha, we use
304 * what we push on an interrupt (a trapframe).
305 */
306 struct clockframe {
307 struct trapframe cf_tf;
308 };
309 #define CLKF_USERMODE(framep) \
310 (((framep)->cf_tf.tf_regs[FRAME_PS] & ALPHA_PSL_USERMODE) != 0)
311 #define CLKF_PC(framep) ((framep)->cf_tf.tf_regs[FRAME_PC])
312
313 /*
314 * This isn't perfect; if the clock interrupt comes in before the
315 * r/m/w cycle is complete, we won't be counted... but it's not
316 * like this statistic has to be extremely accurate.
317 */
318 #define CLKF_INTR(framep) (curcpu()->ci_intrdepth)
319
320 /*
321 * This is used during profiling to integrate system time.
322 */
323 #define PROC_PC(p) ((p)->p_md.md_tf->tf_regs[FRAME_PC])
324 #define PROC_STACK(p) ((p)->p_md.md_tf->tf_regs[FRAME_SP])
325
326 /*
327 * Preempt the current process if in interrupt from user mode,
328 * or after the current trap/syscall if in system mode.
329 */
330 #define need_resched(ci) \
331 do { \
332 (ci)->ci_want_resched = 1; \
333 if ((ci)->ci_curproc != NULL) \
334 aston((ci)->ci_curproc); \
335 } while (/*CONSTCOND*/0)
336 #define clear_resched(ci) (ci)->ci_want_resched = 0
337
338 /*
339 * Give a profiling tick to the current process when the user profiling
340 * buffer pages are invalid. On the Alpha, request an AST to send us
341 * through trap, marking the proc as needing a profiling tick.
342 */
343 #define need_proftick(p) aston(p)
344
345 /*
346 * Notify the current process (p) that it has a signal pending,
347 * process as soon as possible.
348 */
349 #ifdef MULTIPROCESSOR
350 #define signotify(p) do { aston(p); cpu_unidle((p)->p_cpu); } while (0)
351 #else
352 #define signotify(p) aston(p)
353 #endif
354
355 #define aston(p) ((p)->p_md.md_astpending = 1)
356 #endif /* _KERNEL */
357
358 /*
359 * CTL_MACHDEP definitions.
360 */
361 #define CPU_CONSDEV 1 /* dev_t: console terminal device */
362 #define CPU_BOOTED_KERNEL 6 /* string: booted kernel name */
363 #define CPU_FP_SYNC_COMPLETE 7 /* int: always fixup sync fp traps */
364 #define CPU_CHIPSET 8 /* chipset information */
365 #define CPU_ALLOWAPERTURE 9
366 #define CPU_LED_BLINK 10 /* int: blink leds on DEC 3000 */
367
368 #define CPU_MAXID 11 /* valid machdep IDs */
369
370 #define CPU_CHIPSET_MEM 1 /* PCI memory address */
371 #define CPU_CHIPSET_BWX 2 /* PCI supports BWX */
372 #define CPU_CHIPSET_TYPE 3 /* PCI chipset name */
373 #define CPU_CHIPSET_DENSE 4 /* PCI chipset dense memory addr */
374 #define CPU_CHIPSET_PORTS 5 /* PCI port address */
375 #define CPU_CHIPSET_HAE_MASK 6 /* PCI chipset mask for HAE register */
376 #define CPU_CHIPSET_MAXID 7
377
378 #define CTL_MACHDEP_NAMES { \
379 { 0, 0 }, \
380 { "console_device", CTLTYPE_STRUCT }, \
381 { 0, 0 }, \
382 { 0, 0 }, \
383 { 0, 0 }, \
384 { 0, 0 }, \
385 { "booted_kernel", CTLTYPE_STRING }, \
386 { "fp_sync_complete", CTLTYPE_INT }, \
387 { "chipset", CTLTYPE_NODE }, \
388 { "allowaperture", CTLTYPE_INT }, \
389 { "led_blink", CTLTYPE_INT } \
390 }
391
392 #define CTL_CHIPSET_NAMES { \
393 { 0, 0 }, \
394 { "memory", CTLTYPE_QUAD }, \
395 { "bwx", CTLTYPE_INT }, \
396 { "type", CTLTYPE_STRING }, \
397 { "dense_base", CTLTYPE_QUAD }, \
398 { "ports_base", CTLTYPE_QUAD }, \
399 { "hae_mask", CTLTYPE_QUAD }, \
400 }
401
402 #ifdef _KERNEL
403
404 struct pcb;
405 struct proc;
406 struct reg;
407 struct rpb;
408 struct trapframe;
409
410 /* IEEE and VAX FP completion */
411
412 #ifndef NO_IEEE
413 void alpha_sts(int, s_float *); /* MAGIC */
414 void alpha_stt(int, t_float *); /* MAGIC */
415 void alpha_lds(int, s_float *); /* MAGIC */
416 void alpha_ldt(int, t_float *); /* MAGIC */
417
418 uint64_t alpha_read_fpcr(void); /* MAGIC */
419 void alpha_write_fpcr(u_int64_t); /* MAGIC */
420
421 u_int64_t alpha_read_fp_c(struct proc *);
422 void alpha_write_fp_c(struct proc *, u_int64_t);
423
424 int alpha_fp_complete(u_long, u_long, struct proc *, u_int64_t *);
425 int alpha_fp_complete_at(u_long, struct proc *, u_int64_t *);
426 #endif
427
428 void alpha_enable_fp(struct proc *, int);
429
430 #ifdef MULTIPROCESSOR
431 #include <sys/mplock.h>
432 #endif
433
434 static inline u_long
intr_disable(void)435 intr_disable(void)
436 {
437 return (u_long)splhigh();
438 }
439
440 static inline void
intr_restore(u_long s)441 intr_restore(u_long s)
442 {
443 splx((int)s);
444 }
445
446 #define copyinsn(p, v, ip) copyin32((v), (ip))
447
448 #endif /* _KERNEL */
449 #endif /* _MACHINE_CPU_H_ */
450