1 /* $OpenBSD: cpu.h,v 1.82 2024/10/23 07:41:44 mpi Exp $ */
2 /*
3 * Copyright (c) 1996 Nivas Madhur
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This software was developed by the Computer Systems Engineering group
8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 * contributed to Berkeley.
10 *
11 * All advertising materials mentioning features or use of this software
12 * must display the following acknowledgement:
13 * This product includes software developed by the University of
14 * California, Lawrence Berkeley Laboratory.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 */
40
41 #ifndef _M88K_CPU_H_
42 #define _M88K_CPU_H_
43
44 /*
45 * CTL_MACHDEP definitions.
46 */
47 #define CPU_CONSDEV 1 /* dev_t: console terminal device */
48 #define CPU_CPUTYPE 2 /* int: cpu type */
49 #define CPU_MAXID 3 /* number of valid machdep ids */
50
51 #define CTL_MACHDEP_NAMES { \
52 { 0, 0 }, \
53 { "console_device", CTLTYPE_STRUCT }, \
54 { "cputype", CTLTYPE_INT }, \
55 }
56
57 #ifdef _KERNEL
58
59 #include <machine/atomic.h>
60 #include <machine/pcb.h>
61 #include <machine/psl.h>
62 #include <machine/intr.h>
63 #include <sys/clockintr.h>
64 #include <sys/queue.h>
65 #include <sys/sched.h>
66 #include <sys/srp.h>
67 #include <uvm/uvm_percpu.h>
68
69 #if defined(MULTIPROCESSOR)
70 #if !defined(MAX_CPUS) || MAX_CPUS > 4
71 #undef MAX_CPUS
72 #define MAX_CPUS 4
73 #endif
74 #else
75 #if !defined(MAX_CPUS)
76 #undef MAX_CPUS
77 #define MAX_CPUS 1
78 #endif
79 #endif
80
81 #ifndef _LOCORE
82
83 #include <machine/lock.h>
84
85 /*
86 * Per-CPU data structure
87 */
88
89 struct pmap;
90
91 struct cpu_info {
92 volatile u_int ci_flags;
93 #define CIF_ALIVE 0x01 /* cpu initialized */
94 #define CIF_PRIMARY 0x02 /* primary cpu */
95
96 struct proc *ci_curproc; /* current process... */
97 struct pcb *ci_curpcb; /* ...its pcb... */
98 struct pmap *ci_curpmap; /* ...and its pmap */
99
100 u_int ci_cpuid; /* cpu number */
101
102 /*
103 * Function pointers used within mplock to ensure
104 * non-interruptability.
105 */
106 uint32_t (*ci_mp_atomic_begin)
107 (__cpu_simple_lock_t *lock, uint *csr);
108 void (*ci_mp_atomic_end)
109 (uint32_t psr, __cpu_simple_lock_t *lock, uint csr);
110
111 /*
112 * Other processor-dependent routines
113 */
114 void (*ci_zeropage)(vaddr_t);
115 void (*ci_copypage)(vaddr_t, vaddr_t);
116
117 /*
118 * The following fields are used differently depending on
119 * the processor type. Think of them as an anonymous union
120 * of two anonymous structs.
121 */
122 u_int ci_cpudep0;
123 u_int ci_cpudep1;
124 u_int ci_cpudep2;
125 u_int ci_cpudep3;
126 u_int ci_cpudep4;
127 u_int ci_cpudep5;
128 u_int ci_cpudep6;
129 u_int ci_cpudep7;
130
131 /* 88100 fields */
132 #define ci_pfsr_i0 ci_cpudep0 /* instruction... */
133 #define ci_pfsr_i1 ci_cpudep1
134 #define ci_pfsr_d0 ci_cpudep2 /* ...and data CMMU PFSRs */
135 #define ci_pfsr_d1 ci_cpudep3
136
137 /* 88110 fields */
138 #define ci_ipi_arg1 ci_cpudep0 /* Complex IPI arguments */
139 #define ci_ipi_arg2 ci_cpudep1
140 #define ci_h_sxip ci_cpudep2 /* trapframe values */
141 #define ci_h_epsr ci_cpudep3 /* for hardclock */
142 #define ci_s_sxip ci_cpudep4 /* and softclock */
143 #define ci_s_epsr ci_cpudep5
144
145 struct schedstate_percpu
146 ci_schedstate; /* scheduling state */
147 int ci_want_resched; /* need_resched() invoked */
148
149 u_int ci_idepth; /* interrupt depth */
150
151 int ci_ddb_state; /* ddb status */
152 #define CI_DDB_RUNNING 0
153 #define CI_DDB_ENTERDDB 1
154 #define CI_DDB_INDDB 2
155 #define CI_DDB_PAUSE 3
156
157 u_int32_t ci_randseed; /* per-cpu random seed */
158
159 int ci_ipi; /* pending ipis */
160 #define CI_IPI_NOTIFY 0x00000001
161 #define CI_IPI_HARDCLOCK 0x00000002
162 #define CI_IPI_STATCLOCK 0x00000004
163 #define CI_IPI_DDB 0x00000008
164 /* 88110 simple ipi */
165 #define CI_IPI_TLB_FLUSH_KERNEL 0x00000010
166 #define CI_IPI_TLB_FLUSH_USER 0x00000020
167 /* 88110 complex ipi */
168 #define CI_IPI_CACHE_FLUSH 0x00000040
169 #define CI_IPI_ICACHE_FLUSH 0x00000080
170 #define CI_IPI_DMA_CACHECTL 0x00000100
171 void (*ci_softipi_cb)(void); /* 88110 softipi callback */
172
173 #if defined(MULTIPROCESSOR)
174 struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM];
175 #define __HAVE_UVM_PERCPU
176 struct uvm_pmr_cache ci_uvm; /* [o] page cache */
177 #endif
178 #ifdef DIAGNOSTIC
179 int ci_mutex_level;
180 #endif
181 #ifdef GPROF
182 struct gmonparam *ci_gmon;
183 struct clockintr ci_gmonclock;
184 #endif
185 struct clockqueue ci_queue;
186 char ci_panicbuf[512];
187 };
188
189 extern cpuid_t master_cpu;
190 extern struct cpu_info m88k_cpus[MAX_CPUS];
191
192 #define CPU_INFO_ITERATOR cpuid_t
193 #define CPU_INFO_FOREACH(cii, ci) \
194 for ((cii) = 0; (cii) < MAX_CPUS; (cii)++) \
195 if (((ci) = &m88k_cpus[cii])->ci_flags & CIF_ALIVE)
196 #define CPU_INFO_UNIT(ci) ((ci)->ci_cpuid)
197 #define MAXCPUS MAX_CPUS
198
199 #if defined(MULTIPROCESSOR)
200
201 static __inline__ struct cpu_info *
curcpu(void)202 curcpu(void)
203 {
204 struct cpu_info *cpuptr;
205
206 __asm__ volatile ("ldcr %0, %%cr17" : "=r" (cpuptr));
207 return cpuptr;
208 }
209
210 #define CPU_IS_PRIMARY(ci) ((ci)->ci_flags & CIF_PRIMARY)
211 #define CPU_IS_RUNNING(ci) ((ci)->ci_flags & CIF_ALIVE)
212
213 void cpu_boot_secondary_processors(void);
214 void cpu_unidle(struct cpu_info *);
215 void m88k_send_ipi(int, cpuid_t);
216 void m88k_broadcast_ipi(int);
217
218 #else /* MULTIPROCESSOR */
219
220 #define curcpu() (&m88k_cpus[0])
221 #define cpu_unidle(ci) do { /* nothing */ } while (0)
222 #define CPU_IS_PRIMARY(ci) 1
223 #define CPU_IS_RUNNING(ci) 1
224
225 #endif /* MULTIPROCESSOR */
226
227 #define CPU_BUSY_CYCLE() __asm volatile ("" ::: "memory")
228
229 struct cpu_info *set_cpu_number(cpuid_t);
230
231 /*
232 * The md code may hardcode this in some very specific situations.
233 */
234 #if !defined(cpu_number)
235 #define cpu_number() curcpu()->ci_cpuid
236 #endif
237
238 #define curpcb curcpu()->ci_curpcb
239
240 unsigned int cpu_rnd_messybits(void);
241
242 #endif /* _LOCORE */
243
244 /*
245 * definitions of cpu-dependent requirements
246 * referenced in generic code
247 */
248
249 #define cpu_idle_enter() do { /* nothing */ } while (0)
250 #define cpu_idle_cycle() do { /* nothing */ } while (0)
251 #define cpu_idle_leave() do { /* nothing */ } while (0)
252
253 #if defined(MULTIPROCESSOR)
254 #include <sys/mplock.h>
255 #endif
256
257 /*
258 * Arguments to clockintr_dispatch encapsulate the previous
259 * machine state in an opaque clockframe. CLKF_INTR is only valid
260 * if the process is in kernel mode. Clockframe is really trapframe,
261 * so pointer to clockframe can be safely cast into a pointer to
262 * trapframe.
263 */
264 struct clockframe {
265 struct trapframe tf;
266 };
267
268 #define CLKF_USERMODE(framep) (((framep)->tf.tf_epsr & PSR_MODE) == 0)
269 #define CLKF_PC(framep) ((framep)->tf.tf_sxip & XIP_ADDR)
270 #define CLKF_INTR(framep) \
271 (((struct cpu_info *)(framep)->tf.tf_cpu)->ci_idepth > 1)
272
273 #define aston(p) ((p)->p_md.md_astpending = 1)
274
275 /*
276 * This is used during profiling to integrate system time.
277 */
278 #define PC_REGS(regs) \
279 (CPU_IS88110 ? ((regs)->exip & XIP_ADDR) : \
280 ((regs)->sxip & XIP_V ? (regs)->sxip & XIP_ADDR : \
281 ((regs)->snip & NIP_V ? (regs)->snip & NIP_ADDR : \
282 (regs)->sfip & FIP_ADDR)))
283 #define PROC_PC(p) PC_REGS((struct reg *)((p)->p_md.md_tf))
284 #define PROC_STACK(p) ((p)->p_md.md_tf->tf_sp)
285
286 #define clear_resched(ci) (ci)->ci_want_resched = 0
287
288 /*
289 * Give a profiling tick to the current process when the user profiling
290 * buffer pages are invalid. On the m88k, request an ast to send us
291 * through trap(), marking the proc as needing a profiling tick.
292 */
293 #define need_proftick(p) aston(p)
294
295 void need_resched(struct cpu_info *);
296 void signotify(struct proc *);
297 void softipi(void);
298
299 int badaddr(vaddr_t addr, int size);
300 void set_vbr(register_t);
301 extern register_t kernel_vbr;
302
303 #define copyinsn(p, v, ip) copyin32((v), (ip))
304
305 #endif /* _KERNEL */
306 #endif /* _M88K_CPU_H_ */
307