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