1 /* $OpenBSD: cpu.h,v 1.67 2024/06/09 21:15:29 jca Exp $ */
2 /* $NetBSD: cpu.h,v 1.34 2003/06/23 11:01:08 martin Exp $ */
3
4 /*
5 * Copyright (c) 1994-1996 Mark Brinicombe.
6 * Copyright (c) 1994 Brini.
7 * All rights reserved.
8 *
9 * This code is derived from software written for Brini by Mark Brinicombe
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by Brini.
22 * 4. The name of the company nor the name of the author may be used to
23 * endorse or promote products derived from this software without specific
24 * prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
30 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * RiscBSD kernel project
39 *
40 * cpu.h
41 *
42 * CPU specific symbols
43 *
44 * Created : 18/09/94
45 *
46 * Based on kate/katelib/arm6.h
47 */
48
49 #ifndef _ARM_CPU_H_
50 #define _ARM_CPU_H_
51
52 /*
53 * User-visible definitions
54 */
55
56 /* CTL_MACHDEP definitions. */
57 /* 1 formerly int: CPU_DEBUG */
58 /* 2 formerly string: CPU_BOOTED_DEVICE */
59 /* 3 formerly string: CPU_BOOTED_KERNEL */
60 #define CPU_CONSDEV 4 /* struct: dev_t of our console */
61 #define CPU_POWERSAVE 5 /* int: use CPU powersave mode */
62 #define CPU_ALLOWAPERTURE 6 /* int: allow mmap of /dev/xf86 */
63 /* 7 formerly int: apmwarn */
64 /* 8 formerly int: keyboard reset */
65 /* 9 formerly int: CPU_ZTSRAWMODE */
66 /* 10 formerly struct: CPU_ZTSSCALE */
67 #define CPU_MAXSPEED 11 /* int: number of valid machdep ids */
68 /* 12 formerly int: CPU_LIDSUSPEND */
69 #define CPU_LIDACTION 13 /* action caused by lid close */
70 #define CPU_COMPATIBLE 14 /* compatible property */
71 #define CPU_MAXID 15 /* number of valid machdep ids */
72
73 #define CTL_MACHDEP_NAMES { \
74 { 0, 0 }, \
75 { 0, 0 }, \
76 { 0, 0 }, \
77 { 0, 0 }, \
78 { "console_device", CTLTYPE_STRUCT }, \
79 { "powersave", CTLTYPE_INT }, \
80 { "allowaperture", CTLTYPE_INT }, \
81 { 0, 0 }, \
82 { 0, 0 }, \
83 { 0, 0 }, \
84 { 0, 0 }, \
85 { "maxspeed", CTLTYPE_INT }, \
86 { 0, 0 }, \
87 { "lidaction", CTLTYPE_INT }, \
88 { "compatible", CTLTYPE_STRING }, \
89 }
90
91 #ifdef _KERNEL
92
93 /*
94 * Kernel-only definitions
95 */
96
97 #include <arm/cpuconf.h>
98
99 #include <machine/intr.h>
100 #include <machine/frame.h>
101 #include <machine/pcb.h>
102 #include <arm/armreg.h>
103
104 /* 1 == use cpu_sleep(), 0 == don't */
105 extern int cpu_do_powersave;
106
107 /* All the CLKF_* macros take a struct clockframe * as an argument. */
108
109 /*
110 * CLKF_USERMODE: Return TRUE/FALSE (1/0) depending on whether the
111 * frame came from USR mode or not.
112 */
113 #define CLKF_USERMODE(frame) ((frame->if_spsr & PSR_MODE) == PSR_USR32_MODE)
114
115 /*
116 * CLKF_INTR: True if we took the interrupt from inside another
117 * interrupt handler.
118 */
119 #define CLKF_INTR(frame) (curcpu()->ci_idepth > 1)
120
121 /*
122 * CLKF_PC: Extract the program counter from a clockframe
123 */
124 #define CLKF_PC(frame) (frame->if_pc)
125
126 /*
127 * PROC_PC: Find out the program counter for the given process.
128 */
129 #define PROC_PC(p) ((p)->p_addr->u_pcb.pcb_tf->tf_pc)
130 #define PROC_STACK(p) ((p)->p_addr->u_pcb.pcb_tf->tf_usr_sp)
131
132 /* The address of the vector page. */
133 extern vaddr_t vector_page;
134 void arm32_vector_init(vaddr_t, int);
135
136 #define ARM_VEC_RESET (1 << 0)
137 #define ARM_VEC_UNDEFINED (1 << 1)
138 #define ARM_VEC_SWI (1 << 2)
139 #define ARM_VEC_PREFETCH_ABORT (1 << 3)
140 #define ARM_VEC_DATA_ABORT (1 << 4)
141 #define ARM_VEC_ADDRESS_EXCEPTION (1 << 5)
142 #define ARM_VEC_IRQ (1 << 6)
143 #define ARM_VEC_FIQ (1 << 7)
144
145 #define ARM_NVEC 8
146 #define ARM_VEC_ALL 0xffffffff
147
148 /*
149 * Per-CPU information. For now we assume one CPU.
150 */
151
152 #include <sys/clockintr.h>
153 #include <sys/device.h>
154 #include <sys/sched.h>
155 #include <sys/srp.h>
156
157 struct cpu_info {
158 struct device *ci_dev; /* Device corresponding to this CPU */
159 struct cpu_info *ci_next;
160 struct schedstate_percpu ci_schedstate; /* scheduler state */
161
162 u_int32_t ci_cpuid;
163 uint64_t ci_mpidr;
164 int ci_node;
165 struct cpu_info *ci_self;
166
167 struct proc *ci_curproc;
168 struct proc *ci_fpuproc;
169 u_int32_t ci_randseed;
170
171 struct pcb *ci_curpcb;
172 struct pcb *ci_idle_pcb;
173
174 uint32_t ci_cpl;
175 uint32_t ci_ipending;
176 uint32_t ci_idepth;
177 #ifdef DIAGNOSTIC
178 int ci_mutex_level;
179 #endif
180 int ci_want_resched;
181
182 void (*ci_flush_bp)(void);
183
184 struct opp_table *ci_opp_table;
185 volatile int ci_opp_idx;
186 volatile int ci_opp_max;
187 uint32_t ci_cpu_supply;
188
189 #ifdef MULTIPROCESSOR
190 struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM];
191 volatile int ci_flags;
192 uint32_t ci_ttbr0;
193 vaddr_t ci_pl1_stkend;
194 vaddr_t ci_irq_stkend;
195 vaddr_t ci_abt_stkend;
196 vaddr_t ci_und_stkend;
197 #endif
198
199 #ifdef GPROF
200 struct gmonparam *ci_gmon;
201 struct clockintr ci_gmonclock;
202 #endif
203 struct clockqueue ci_queue;
204 char ci_panicbuf[512];
205 };
206
207 #define CPUF_PRIMARY (1<<0)
208 #define CPUF_AP (1<<1)
209 #define CPUF_IDENTIFY (1<<2)
210 #define CPUF_IDENTIFIED (1<<3)
211 #define CPUF_PRESENT (1<<4)
212 #define CPUF_GO (1<<5)
213 #define CPUF_RUNNING (1<<6)
214
215 static inline struct cpu_info *
curcpu(void)216 curcpu(void)
217 {
218 struct cpu_info *__ci;
219 __asm volatile("mrc p15, 0, %0, c13, c0, 4" : "=r" (__ci));
220 return (__ci);
221 }
222
223 extern struct cpu_info cpu_info_primary;
224 extern struct cpu_info *cpu_info_list;
225
226 #ifndef MULTIPROCESSOR
227 #define cpu_number() 0
228 #define CPU_IS_PRIMARY(ci) 1
229 #define CPU_IS_RUNNING(ci) 1
230 #define CPU_INFO_ITERATOR int
231 #define CPU_INFO_FOREACH(cii, ci) \
232 for (cii = 0, ci = curcpu(); ci != NULL; ci = NULL)
233 #define CPU_INFO_UNIT(ci) 0
234 #define MAXCPUS 1
235 #define cpu_kick(ci)
236 #define cpu_unidle(ci)
237 #else
238 #define cpu_number() (curcpu()->ci_cpuid)
239 #define CPU_IS_PRIMARY(ci) ((ci) == &cpu_info_primary)
240 #define CPU_IS_RUNNING(ci) ((ci)->ci_flags & CPUF_RUNNING)
241 #define CPU_INFO_ITERATOR int
242 #define CPU_INFO_FOREACH(cii, ci) for (cii = 0, ci = cpu_info_list; \
243 ci != NULL; ci = ci->ci_next)
244 #define CPU_INFO_UNIT(ci) ((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0)
245 #define MAXCPUS 4
246 void cpu_kick(struct cpu_info *);
247 void cpu_unidle(struct cpu_info *ci);
248
249 extern struct cpu_info *cpu_info[MAXCPUS];
250
251 void cpu_boot_secondary_processors(void);
252 #endif /* !MULTIPROCESSOR */
253
254 #define CPU_BUSY_CYCLE() __asm volatile ("" ::: "memory")
255
256 #define curpcb curcpu()->ci_curpcb
257
258 unsigned int cpu_rnd_messybits(void);
259
260 /*
261 * Scheduling glue
262 */
263
264 extern int astpending;
265 #define setsoftast() (astpending = 1)
266
267 /*
268 * Notify the current process (p) that it has a signal pending,
269 * process as soon as possible.
270 */
271
272 #define signotify(p) setsoftast()
273
274 /*
275 * Preempt the current process if in interrupt from user mode,
276 * or after the current trap/syscall if in system mode.
277 */
278 extern int want_resched; /* resched() was called */
279 #define need_resched(ci) (want_resched = 1, setsoftast())
280 #define clear_resched(ci) want_resched = 0
281
282 /*
283 * Give a profiling tick to the current process when the user profiling
284 * buffer pages are invalid. On the i386, request an ast to send us
285 * through trap(), marking the proc as needing a profiling tick.
286 */
287 #define need_proftick(p) setsoftast()
288
289 /*
290 * cpu device glue (belongs in cpuvar.h)
291 */
292
293 int cpu_alloc_idle_pcb(struct cpu_info *);
294
295 /*
296 * Random cruft
297 */
298
299 /* cpuswitch.S */
300 struct pcb;
301 void savectx (struct pcb *pcb);
302
303 /* machdep.h */
304 void bootsync (int);
305
306 /* fault.c */
307 int badaddr_read (void *, size_t, void *);
308
309 /* syscall.c */
310 void swi_handler (trapframe_t *);
311
312 /* machine_machdep.c */
313 void board_startup(void);
314
315 static inline u_long
intr_disable(void)316 intr_disable(void)
317 {
318 uint32_t cpsr;
319
320 __asm volatile ("mrs %0, cpsr" : "=r"(cpsr));
321 __asm volatile ("msr cpsr_c, %0" :: "r"(cpsr | PSR_I));
322
323 return cpsr;
324 }
325
326 static inline void
intr_restore(u_long cpsr)327 intr_restore(u_long cpsr)
328 {
329 __asm volatile ("msr cpsr_c, %0" :: "r"(cpsr));
330 }
331
332 #endif /* _KERNEL */
333
334 #ifdef MULTIPROCESSOR
335 #include <sys/mplock.h>
336 #endif /* MULTIPROCESSOR */
337
338 #endif /* !_ARM_CPU_H_ */
339