xref: /netbsd-src/sys/arch/riscv/include/cpu.h (revision 0ad349337a874f932507463a034e8710784222b7)
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