1 /* $OpenBSD: cpu.h,v 1.77 2024/10/25 08:08:24 mpi 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 #include <uvm/uvm_percpu.h>
107
108 struct pcb;
109 struct proc;
110 struct reg;
111 struct rpb;
112 struct trapframe;
113
114 extern u_long cpu_implver; /* from IMPLVER instruction */
115 extern u_long cpu_amask; /* from AMASK instruction */
116 extern int bootdev_debug;
117 extern int alpha_fp_sync_complete;
118
119 void XentArith(u_int64_t, u_int64_t, u_int64_t); /* MAGIC */
120 void XentIF(u_int64_t, u_int64_t, u_int64_t); /* MAGIC */
121 void XentInt(u_int64_t, u_int64_t, u_int64_t); /* MAGIC */
122 void XentMM(u_int64_t, u_int64_t, u_int64_t); /* MAGIC */
123 void XentRestart(void); /* MAGIC */
124 void XentSys(u_int64_t, u_int64_t, u_int64_t); /* MAGIC */
125 void XentUna(u_int64_t, u_int64_t, u_int64_t); /* MAGIC */
126 void alpha_init(u_long, u_long, u_long, u_long, u_long);
127 int alpha_pa_access(u_long);
128 void ast(struct trapframe *);
129 int badaddr(void *, size_t);
130 int badaddr_read(void *, size_t, void *);
131 u_int64_t console_restart(struct trapframe *);
132 void do_sir(void);
133 void dumpconf(void);
134 void exception_return(void); /* MAGIC */
135 void frametoreg(struct trapframe *, struct reg *);
136 long fswintrberr(void); /* MAGIC */
137 void init_bootstrap_console(void);
138 void init_prom_interface(struct rpb *);
139 void interrupt(unsigned long, unsigned long, unsigned long,
140 struct trapframe *);
141 void machine_check(unsigned long, struct trapframe *, unsigned long,
142 unsigned long);
143 u_int64_t hwrpb_checksum(void);
144 void hwrpb_restart_setup(void);
145 void proc_trampoline(void); /* MAGIC */
146 void regdump(struct trapframe *);
147 void regtoframe(struct reg *, struct trapframe *);
148 void savectx(struct pcb *);
149 void syscall(u_int64_t, struct trapframe *);
150 void trap(unsigned long, unsigned long, unsigned long, unsigned long,
151 struct trapframe *);
152 void trap_init(void);
153 void enable_nsio_ide(bus_space_tag_t);
154
155 /* Multiprocessor glue; cpu.c */
156 struct cpu_info;
157 int cpu_iccb_send(cpuid_t, const char *);
158 void cpu_iccb_receive(void);
159 void cpu_hatch(struct cpu_info *);
160 __dead
161 void cpu_halt(void);
162 void cpu_halt_secondary(unsigned long);
163 void cpu_spinup_trampoline(void); /* MAGIC */
164 void cpu_pause(unsigned long);
165 void cpu_resume(unsigned long);
166
167 /*
168 * Machine check information.
169 */
170 struct mchkinfo {
171 volatile int mc_expected; /* machine check is expected */
172 volatile int mc_received; /* machine check was received */
173 };
174
175 struct cpu_info {
176 /*
177 * Private members accessed in assembly with 8 bit offsets.
178 */
179 struct proc *ci_curproc; /* current owner of the processor */
180 paddr_t ci_curpcb; /* PA of current HW PCB */
181
182 /*
183 * Public members.
184 */
185 struct schedstate_percpu ci_schedstate; /* scheduler state */
186 #ifdef DIAGNOSTIC
187 int ci_mutex_level;
188 #endif
189 cpuid_t ci_cpuid; /* our CPU ID */
190 struct cpu_info *ci_next;
191 u_int32_t ci_randseed;
192
193 #if defined(MULTIPROCESSOR)
194 struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM];
195 #define __HAVE_UVM_PERCPU
196 struct uvm_pmr_cache ci_uvm;
197 #endif
198
199 /*
200 * Private members.
201 */
202 struct mchkinfo ci_mcinfo; /* machine check info */
203 struct proc *ci_fpcurproc; /* current owner of the FPU */
204 struct pcb *ci_idle_pcb; /* our idle PCB */
205 paddr_t ci_idle_pcb_paddr; /* PA of idle PCB */
206 struct device *ci_dev; /* pointer to our device */
207 u_long ci_want_resched; /* preempt current process */
208 u_long ci_idepth; /* interrupt trap depth */
209 struct trapframe *ci_db_regs; /* registers for debuggers */
210
211 #if defined(MULTIPROCESSOR)
212 volatile u_long ci_flags; /* flags; see below */
213 volatile u_long ci_ipis; /* interprocessor interrupts pending */
214 #endif
215 #ifdef GPROF
216 struct gmonparam *ci_gmon;
217 struct clockintr ci_gmonclock;
218 #endif
219 struct clockqueue ci_queue;
220 char ci_panicbuf[512];
221 };
222
223 #define CPUF_PRIMARY 0x01 /* CPU is primary CPU */
224 #define CPUF_RUNNING 0x02 /* CPU is running */
225 #define CPUF_PAUSED 0x04 /* CPU is paused */
226 #define CPUF_FPUSAVE 0x08 /* CPU is currently in fpusave_cpu() */
227
228 void fpusave_cpu(struct cpu_info *, int);
229 void fpusave_proc(struct proc *, int);
230
231 extern struct cpu_info cpu_info_primary;
232 extern struct cpu_info *cpu_info_list;
233
234 #define CPU_INFO_UNIT(ci) ((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0)
235 #define CPU_INFO_ITERATOR int
236 #define CPU_INFO_FOREACH(cii, ci) for (cii = 0, ci = cpu_info_list; \
237 ci != NULL; ci = ci->ci_next)
238
239 #define MAXCPUS ALPHA_MAXPROCS
240
241 #if defined(MULTIPROCESSOR)
242 extern volatile u_long cpus_running;
243 extern volatile u_long cpus_paused;
244 extern struct cpu_info *cpu_info[];
245
246 #define curcpu() ((struct cpu_info *)alpha_pal_rdval())
247 #define CPU_IS_PRIMARY(ci) ((ci)->ci_flags & CPUF_PRIMARY)
248 #define CPU_IS_RUNNING(ci) ((ci)->ci_flags & CPUF_RUNNING)
249
250 void cpu_boot_secondary_processors(void);
251
252 void cpu_pause_resume(unsigned long, int);
253 void cpu_pause_resume_all(int);
254 void cpu_unidle(struct cpu_info *);
255
256 /*
257 * On the Alpha, interprocessor interrupts come in at device priority
258 * level. This can cause some problems while waiting for r/w spinlocks
259 * from a high'ish priority level: IPIs that come in will not be processed.
260 * This can lead to deadlock.
261 *
262 * This hook allows IPIs to be processed while a spinlock's interlock
263 * is released.
264 */
265 #define CPU_BUSY_CYCLE() \
266 do { \
267 struct cpu_info *__ci = curcpu(); \
268 int __s; \
269 \
270 __asm volatile ("" ::: "memory"); \
271 \
272 if (__ci->ci_ipis != 0) { \
273 __s = splipi(); \
274 alpha_ipi_process_with_frame(__ci); \
275 splx(__s); \
276 } \
277 } while (0)
278
279 #else /* ! MULTIPROCESSOR */
280
281 #define curcpu() (&cpu_info_primary)
282 #define CPU_IS_PRIMARY(ci) 1
283 #define CPU_IS_RUNNING(ci) 1
284 #define cpu_unidle(ci) do { /* nothing */ } while (0)
285 #define CPU_BUSY_CYCLE() __asm volatile ("" ::: "memory")
286
287 #endif /* MULTIPROCESSOR */
288
289
290 #define curproc curcpu()->ci_curproc
291 #define fpcurproc curcpu()->ci_fpcurproc
292 #define curpcb curcpu()->ci_curpcb
293
294 /*
295 * definitions of cpu-dependent requirements
296 * referenced in generic code
297 */
298 #define cpu_number() alpha_pal_whami()
299
300 static inline unsigned int
cpu_rnd_messybits(void)301 cpu_rnd_messybits(void)
302 {
303 return alpha_rpcc();
304 }
305
306 /*
307 * Arguments to clockintr_dispatch encapsulate the previous
308 * machine state in an opaque clockframe. On the Alpha, we use
309 * what we push on an interrupt (a trapframe).
310 */
311 struct clockframe {
312 struct trapframe cf_tf;
313 };
314 #define CLKF_USERMODE(framep) \
315 (((framep)->cf_tf.tf_regs[FRAME_PS] & ALPHA_PSL_USERMODE) != 0)
316 #define CLKF_PC(framep) ((framep)->cf_tf.tf_regs[FRAME_PC])
317
318 /*
319 * This isn't perfect; if the clock interrupt comes in before the
320 * r/m/w cycle is complete, we won't be counted... but it's not
321 * like this statistic has to be extremely accurate.
322 */
323 #define CLKF_INTR(framep) (curcpu()->ci_idepth)
324
325 /*
326 * This is used during profiling to integrate system time.
327 */
328 #define PROC_PC(p) ((p)->p_md.md_tf->tf_regs[FRAME_PC])
329 #define PROC_STACK(p) ((p)->p_md.md_tf->tf_regs[FRAME_SP])
330
331 /*
332 * Preempt the current process if in interrupt from user mode,
333 * or after the current trap/syscall if in system mode.
334 */
335 #define need_resched(ci) \
336 do { \
337 (ci)->ci_want_resched = 1; \
338 if ((ci)->ci_curproc != NULL) \
339 aston((ci)->ci_curproc); \
340 } while (/*CONSTCOND*/0)
341 #define clear_resched(ci) (ci)->ci_want_resched = 0
342
343 /*
344 * Give a profiling tick to the current process when the user profiling
345 * buffer pages are invalid. On the Alpha, request an AST to send us
346 * through trap, marking the proc as needing a profiling tick.
347 */
348 #define need_proftick(p) aston(p)
349
350 /*
351 * Notify the current process (p) that it has a signal pending,
352 * process as soon as possible.
353 */
354 #ifdef MULTIPROCESSOR
355 #define signotify(p) do { aston(p); cpu_unidle((p)->p_cpu); } while (0)
356 #else
357 #define signotify(p) aston(p)
358 #endif
359
360 #define aston(p) ((p)->p_md.md_astpending = 1)
361 #endif /* _KERNEL */
362
363 /*
364 * CTL_MACHDEP definitions.
365 */
366 #define CPU_CONSDEV 1 /* dev_t: console terminal device */
367 #define CPU_BOOTED_KERNEL 6 /* string: booted kernel name */
368 #define CPU_FP_SYNC_COMPLETE 7 /* int: always fixup sync fp traps */
369 #define CPU_CHIPSET 8 /* chipset information */
370 #define CPU_ALLOWAPERTURE 9
371 #define CPU_LED_BLINK 10 /* int: blink leds on DEC 3000 */
372
373 #define CPU_MAXID 11 /* valid machdep IDs */
374
375 #define CPU_CHIPSET_MEM 1 /* PCI memory address */
376 #define CPU_CHIPSET_BWX 2 /* PCI supports BWX */
377 #define CPU_CHIPSET_TYPE 3 /* PCI chipset name */
378 #define CPU_CHIPSET_DENSE 4 /* PCI chipset dense memory addr */
379 #define CPU_CHIPSET_PORTS 5 /* PCI port address */
380 #define CPU_CHIPSET_HAE_MASK 6 /* PCI chipset mask for HAE register */
381 #define CPU_CHIPSET_MAXID 7
382
383 #define CTL_MACHDEP_NAMES { \
384 { 0, 0 }, \
385 { "console_device", CTLTYPE_STRUCT }, \
386 { 0, 0 }, \
387 { 0, 0 }, \
388 { 0, 0 }, \
389 { 0, 0 }, \
390 { "booted_kernel", CTLTYPE_STRING }, \
391 { "fp_sync_complete", CTLTYPE_INT }, \
392 { "chipset", CTLTYPE_NODE }, \
393 { "allowaperture", CTLTYPE_INT }, \
394 { "led_blink", CTLTYPE_INT } \
395 }
396
397 #define CTL_CHIPSET_NAMES { \
398 { 0, 0 }, \
399 { "memory", CTLTYPE_QUAD }, \
400 { "bwx", CTLTYPE_INT }, \
401 { "type", CTLTYPE_STRING }, \
402 { "dense_base", CTLTYPE_QUAD }, \
403 { "ports_base", CTLTYPE_QUAD }, \
404 { "hae_mask", CTLTYPE_QUAD }, \
405 }
406
407 #ifdef _KERNEL
408
409 struct pcb;
410 struct proc;
411 struct reg;
412 struct rpb;
413 struct trapframe;
414
415 /* IEEE and VAX FP completion */
416
417 #ifndef NO_IEEE
418 void alpha_sts(int, s_float *); /* MAGIC */
419 void alpha_stt(int, t_float *); /* MAGIC */
420 void alpha_lds(int, s_float *); /* MAGIC */
421 void alpha_ldt(int, t_float *); /* MAGIC */
422
423 uint64_t alpha_read_fpcr(void); /* MAGIC */
424 void alpha_write_fpcr(u_int64_t); /* MAGIC */
425
426 u_int64_t alpha_read_fp_c(struct proc *);
427 void alpha_write_fp_c(struct proc *, u_int64_t);
428
429 int alpha_fp_complete(u_long, u_long, struct proc *, u_int64_t *);
430 int alpha_fp_complete_at(u_long, struct proc *, u_int64_t *);
431 #endif
432
433 void alpha_enable_fp(struct proc *, int);
434
435 #ifdef MULTIPROCESSOR
436 #include <sys/mplock.h>
437 #endif
438
439 static inline u_long
intr_disable(void)440 intr_disable(void)
441 {
442 return (u_long)splhigh();
443 }
444
445 static inline void
intr_restore(u_long s)446 intr_restore(u_long s)
447 {
448 splx((int)s);
449 }
450
451 #define copyinsn(p, v, ip) copyin32((v), (ip))
452
453 #endif /* _KERNEL */
454 #endif /* _MACHINE_CPU_H_ */
455