cpu.h revision 1.16 1 /* $NetBSD: cpu.h,v 1.16 2024/08/04 08:16:25 skrll Exp $ */
2
3 /*-
4 * Copyright (c) 2014 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Matt Thomas of 3am Software Foundry.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #ifndef _RISCV_CPU_H_
33 #define _RISCV_CPU_H_
34
35 #if defined(_KERNEL) || defined(_KMEMUSER)
36
37 struct clockframe {
38 vaddr_t cf_epc;
39 register_t cf_status;
40 int cf_intr_depth;
41 };
42
43 #define CLKF_USERMODE(cf) (((cf)->cf_status & SR_SPP) == 0)
44 #define CLKF_PC(cf) ((cf)->cf_epc)
45 #define CLKF_INTR(cf) ((cf)->cf_intr_depth > 1)
46
47 #include <sys/cpu_data.h>
48 #include <sys/device_if.h>
49 #include <sys/evcnt.h>
50 #include <sys/intr.h>
51
52 struct cpu_info {
53 struct cpu_data ci_data;
54 device_t ci_dev;
55 cpuid_t ci_cpuid;
56 struct lwp *ci_curlwp;
57 struct lwp *ci_onproc; /* current user LWP / kthread */
58 struct lwp *ci_softlwps[SOFTINT_COUNT];
59 struct trapframe *ci_ddb_regs;
60
61 uint64_t ci_lastintr;
62 uint64_t ci_lastintr_scheduled;
63 struct evcnt ci_ev_timer;
64 struct evcnt ci_ev_timer_missed;
65
66 u_long ci_cpu_freq; /* CPU frequency */
67 int ci_mtx_oldspl;
68 int ci_mtx_count;
69 int ci_cpl;
70 volatile u_int ci_intr_depth;
71
72 int ci_want_resched __aligned(COHERENCY_UNIT);
73 u_int ci_softints;
74
75 tlb_asid_t ci_pmap_asid_cur;
76
77 union pmap_segtab *ci_pmap_user_segtab;
78 #ifdef _LP64
79 union pmap_segtab *ci_pmap_user_seg0tab;
80 #endif
81
82 struct evcnt ci_ev_fpu_saves;
83 struct evcnt ci_ev_fpu_loads;
84 struct evcnt ci_ev_fpu_reenables;
85
86 struct pmap_tlb_info *ci_tlb_info;
87
88 #ifdef MULTIPROCESSOR
89 volatile u_long ci_flags;
90 #define CPUF_PRIMARY __BIT(0) /* CPU is primary CPU */
91 #define CPUF_PRESENT __BIT(1) /* CPU is present */
92 #define CPUF_RUNNING __BIT(2) /* CPU is running */
93 #define CPUF_PAUSED __BIT(3) /* CPU is paused */
94
95 void *ci_intcsoftc;
96 volatile u_long ci_request_ipis;
97 /* bitmask of IPIs requested */
98 u_long ci_active_ipis; /* bitmask of IPIs being serviced */
99
100 struct evcnt ci_evcnt_all_ipis; /* aggregated IPI counter */
101 struct evcnt ci_evcnt_per_ipi[NIPIS]; /* individual IPI counters */
102 struct evcnt ci_evcnt_synci_onproc_rqst;
103 struct evcnt ci_evcnt_synci_deferred_rqst;
104 struct evcnt ci_evcnt_synci_ipi_rqst;
105
106 kcpuset_t *ci_shootdowncpus;
107 kcpuset_t *ci_multicastcpus;
108 kcpuset_t *ci_watchcpus;
109 kcpuset_t *ci_ddbcpus;
110 #endif
111
112 #if defined(GPROF) && defined(MULTIPROCESSOR)
113 struct gmonparam *ci_gmon; /* MI per-cpu GPROF */
114 #endif
115 };
116
117 #endif /* _KERNEL || _KMEMUSER */
118
119 #ifdef _KERNEL
120
121 extern struct cpu_info cpu_info_store[];
122 extern cpuid_t cpu_bphartid;
123 extern u_int cpu_hartindex[];
124
125 #ifdef MULTIPROCESSOR
126
127 void cpu_hatch(struct cpu_info *, unsigned long);
128
129 void cpu_init_secondary_processor(u_int);
130 void cpu_boot_secondary_processors(void);
131 void cpu_mpstart(void);
132 bool cpu_hatched_p(u_int);
133
134 void cpu_clr_mbox(u_int);
135 void cpu_set_hatched(u_int);
136
137
138 void cpu_halt(void);
139 void cpu_halt_others(void);
140 bool cpu_is_paused(cpuid_t);
141 void cpu_pause(void);
142 void cpu_pause_others(void);
143 void cpu_resume(cpuid_t);
144 void cpu_resume_others(void);
145 void cpu_debug_dump(void);
146
147 extern kcpuset_t *cpus_running;
148 extern kcpuset_t *cpus_hatched;
149 extern kcpuset_t *cpus_paused;
150 extern kcpuset_t *cpus_resumed;
151 extern kcpuset_t *cpus_halted;
152
153 /*
154 * definitions of cpu-dependent requirements
155 * referenced in generic code
156 */
157
158 /*
159 * Send an inter-processor interrupt to each other CPU (excludes curcpu())
160 */
161 void cpu_broadcast_ipi(int);
162
163 /*
164 * Send an inter-processor interrupt to CPUs in kcpuset (excludes curcpu())
165 */
166 void cpu_multicast_ipi(const kcpuset_t *, int);
167
168 /*
169 * Send an inter-processor interrupt to another CPU.
170 */
171 int cpu_send_ipi(struct cpu_info *, int);
172
173 #endif
174
175 struct lwp;
176 static inline struct cpu_info *lwp_getcpu(struct lwp *);
177
178 register struct lwp *riscv_curlwp __asm("tp");
179 #define curlwp riscv_curlwp
180 #define curcpu() lwp_getcpu(curlwp)
181 #define curpcb ((struct pcb *)lwp_getpcb(curlwp))
182
183 static inline cpuid_t
184 cpu_number(void)
185 {
186 #ifdef MULTIPROCESSOR
187 return curcpu()->ci_cpuid;
188 #else
189 return 0;
190 #endif
191 }
192
193 void cpu_proc_fork(struct proc *, struct proc *);
194 void cpu_signotify(struct lwp *);
195 void cpu_need_proftick(struct lwp *l);
196 void cpu_boot_secondary_processors(void);
197
198 #define CPU_INFO_ITERATOR cpuid_t
199 #ifdef MULTIPROCESSOR
200 #define CPU_IS_PRIMARY(ci) ((ci)->ci_flags & CPUF_PRIMARY)
201 #define CPU_INFO_FOREACH(cii, ci) \
202 cii = 0, ci = &cpu_info_store[0]; \
203 ci != NULL; \
204 cii++, ncpu ? (ci = cpu_infos[cii]) \
205 : (ci = NULL)
206 #else
207 #define CPU_IS_PRIMARY(ci) true
208 #define CPU_INFO_FOREACH(cii, ci) \
209 (cii) = 0, (ci) = curcpu(); (cii) == 0; (cii)++
210 #endif
211
212 #define CPU_INFO_CURPMAP(ci) (curlwp->l_proc->p_vmspace->vm_map.pmap)
213
214 static inline void
215 cpu_dosoftints(void)
216 {
217 extern void dosoftints(void);
218 struct cpu_info * const ci = curcpu();
219 if (ci->ci_intr_depth == 0
220 && (ci->ci_data.cpu_softints >> ci->ci_cpl) > 0)
221 dosoftints();
222 }
223
224 static inline bool
225 cpu_intr_p(void)
226 {
227 return curcpu()->ci_intr_depth > 0;
228 }
229
230 #define LWP_PC(l) cpu_lwp_pc(l)
231
232 vaddr_t cpu_lwp_pc(struct lwp *);
233
234 static inline void
235 cpu_idle(void)
236 {
237 asm volatile("wfi" ::: "memory");
238 }
239
240 #endif /* _KERNEL */
241
242 #endif /* _RISCV_CPU_H_ */
243