xref: /netbsd-src/sys/arch/riscv/include/cpu.h (revision d16b7486a53dcb8072b60ec6fcb4373a2d0c27b7)
1 /* $NetBSD: cpu.h,v 1.13 2023/07/29 06:59:47 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 #define	CPUF_USERPMAP	__BIT(4)		/* CPU has a user pmap activated */
95 
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[];
122 extern struct cpu_info cpu_info_store[];
123 
124 
125 #ifdef MULTIPROCESSOR
126 extern u_int riscv_cpu_max;
127 extern cpuid_t cpu_hartid[];
128 
129 void cpu_hatch(struct cpu_info *);
130 
131 void cpu_init_secondary_processor(int);
132 void cpu_boot_secondary_processors(void);
133 void cpu_mpstart(void);
134 bool cpu_hatched_p(u_int);
135 
136 void cpu_clr_mbox(int);
137 void cpu_set_hatched(int);
138 
139 
140 void	cpu_halt(void);
141 void	cpu_halt_others(void);
142 bool	cpu_is_paused(cpuid_t);
143 void	cpu_pause(void);
144 void	cpu_pause_others(void);
145 void	cpu_resume(cpuid_t);
146 void	cpu_resume_others(void);
147 void	cpu_debug_dump(void);
148 
149 extern kcpuset_t *cpus_running;
150 extern kcpuset_t *cpus_hatched;
151 extern kcpuset_t *cpus_paused;
152 extern kcpuset_t *cpus_resumed;
153 extern kcpuset_t *cpus_halted;
154 
155 /*
156  * definitions of cpu-dependent requirements
157  * referenced in generic code
158  */
159 
160 /*
161  * Send an inter-processor interrupt to each other CPU (excludes curcpu())
162  */
163 void cpu_broadcast_ipi(int);
164 
165 /*
166  * Send an inter-processor interrupt to CPUs in kcpuset (excludes curcpu())
167  */
168 void cpu_multicast_ipi(const kcpuset_t *, int);
169 
170 /*
171  * Send an inter-processor interrupt to another CPU.
172  */
173 int cpu_send_ipi(struct cpu_info *, int);
174 
175 #endif
176 
177 struct lwp;
178 static inline struct cpu_info *lwp_getcpu(struct lwp *);
179 
180 register struct lwp *riscv_curlwp __asm("tp");
181 #define	curlwp		riscv_curlwp
182 #define	curcpu()	lwp_getcpu(curlwp)
183 #define	curpcb		((struct pcb *)lwp_getpcb(curlwp))
184 
185 static inline cpuid_t
186 cpu_number(void)
187 {
188 #ifdef MULTIPROCESSOR
189 	return curcpu()->ci_cpuid;
190 #else
191 	return 0;
192 #endif
193 }
194 
195 void	cpu_proc_fork(struct proc *, struct proc *);
196 void	cpu_signotify(struct lwp *);
197 void	cpu_need_proftick(struct lwp *l);
198 void	cpu_boot_secondary_processors(void);
199 
200 #define CPU_INFO_ITERATOR	cpuid_t
201 #ifdef MULTIPROCESSOR
202 #define	CPU_IS_PRIMARY(ci)	((ci)->ci_flags & CPUF_PRIMARY)
203 #define	CPU_INFO_FOREACH(cii, ci)		\
204     cii = 0, ci = &cpu_info_store[0]; 		\
205     ci != NULL; 				\
206     cii++, ncpu ? (ci = cpu_infos[cii]) 	\
207 		: (ci = NULL)
208 #else
209 #define CPU_IS_PRIMARY(ci)	true
210 #define CPU_INFO_FOREACH(cii, ci) \
211 	(cii) = 0, (ci) = curcpu(); (cii) == 0; (cii)++
212 #endif
213 
214 #define CPU_INFO_CURPMAP(ci)	(curlwp->l_proc->p_vmspace->vm_map.pmap)
215 
216 static inline void
217 cpu_dosoftints(void)
218 {
219 	extern void dosoftints(void);
220         struct cpu_info * const ci = curcpu();
221         if (ci->ci_intr_depth == 0
222 	    && (ci->ci_data.cpu_softints >> ci->ci_cpl) > 0)
223                 dosoftints();
224 }
225 
226 static inline bool
227 cpu_intr_p(void)
228 {
229 	return curcpu()->ci_intr_depth > 0;
230 }
231 
232 #define LWP_PC(l)	cpu_lwp_pc(l)
233 
234 vaddr_t	cpu_lwp_pc(struct lwp *);
235 
236 static inline void
237 cpu_idle(void)
238 {
239 	asm volatile("wfi" ::: "memory");
240 }
241 
242 #endif /* _KERNEL */
243 
244 #endif /* _RISCV_CPU_H_ */
245