]> Git Repo - qemu.git/blame - target/riscv/csr.c
target/riscv: optimize helper for vmv<nr>r.v
[qemu.git] / target / riscv / csr.c
CommitLineData
c7b95171
MC
1/*
2 * RISC-V Control and Status Registers.
3 *
4 * Copyright (c) 2016-2017 Sagar Karandikar, [email protected]
5 * Copyright (c) 2017-2018 SiFive, Inc.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2 or later, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "qemu/osdep.h"
21#include "qemu/log.h"
b8012ecf 22#include "qemu/timer.h"
c7b95171
MC
23#include "cpu.h"
24#include "qemu/main-loop.h"
25#include "exec/exec-all.h"
03ff4f8d 26#include "sysemu/cpu-timers.h"
c7b95171 27
c7b95171
MC
28/* CSR function table public API */
29void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops)
30{
31 *ops = csr_ops[csrno & (CSR_TABLE_SIZE - 1)];
32}
33
34void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops)
35{
36 csr_ops[csrno & (CSR_TABLE_SIZE - 1)] = *ops;
37}
38
a88365c1 39/* Predicates */
0e62f92e 40static RISCVException fs(CPURISCVState *env, int csrno)
a88365c1
MC
41{
42#if !defined(CONFIG_USER_ONLY)
c163b3ba
WL
43 if (!env->debugger && !riscv_cpu_fp_enabled(env) &&
44 !RISCV_CPU(env_cpu(env))->cfg.ext_zfinx) {
0e62f92e 45 return RISCV_EXCP_ILLEGAL_INST;
a88365c1
MC
46 }
47#endif
0e62f92e 48 return RISCV_EXCP_NONE;
a88365c1
MC
49}
50
0e62f92e 51static RISCVException vs(CPURISCVState *env, int csrno)
8e3a1f18 52{
b4a99d40
FC
53 CPUState *cs = env_cpu(env);
54 RISCVCPU *cpu = RISCV_CPU(cs);
55
56 if (env->misa_ext & RVV ||
32e579b8 57 cpu->cfg.ext_zve32f || cpu->cfg.ext_zve64f) {
6bc3dfa9
FC
58#if !defined(CONFIG_USER_ONLY)
59 if (!env->debugger && !riscv_cpu_vector_enabled(env)) {
60 return RISCV_EXCP_ILLEGAL_INST;
61 }
62#endif
0e62f92e 63 return RISCV_EXCP_NONE;
8e3a1f18 64 }
0e62f92e 65 return RISCV_EXCP_ILLEGAL_INST;
8e3a1f18
LZ
66}
67
0e62f92e 68static RISCVException ctr(CPURISCVState *env, int csrno)
a88365c1
MC
69{
70#if !defined(CONFIG_USER_ONLY)
0a13a5b8
AF
71 CPUState *cs = env_cpu(env);
72 RISCVCPU *cpu = RISCV_CPU(cs);
0a13a5b8
AF
73
74 if (!cpu->cfg.ext_counters) {
75 /* The Counters extensions is not enabled */
0e62f92e 76 return RISCV_EXCP_ILLEGAL_INST;
0a13a5b8 77 }
e39a8320
AF
78
79 if (riscv_cpu_virt_enabled(env)) {
80 switch (csrno) {
81 case CSR_CYCLE:
db70794e
BM
82 if (!get_field(env->hcounteren, COUNTEREN_CY) &&
83 get_field(env->mcounteren, COUNTEREN_CY)) {
0e62f92e 84 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
e39a8320
AF
85 }
86 break;
87 case CSR_TIME:
db70794e
BM
88 if (!get_field(env->hcounteren, COUNTEREN_TM) &&
89 get_field(env->mcounteren, COUNTEREN_TM)) {
0e62f92e 90 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
e39a8320
AF
91 }
92 break;
93 case CSR_INSTRET:
db70794e
BM
94 if (!get_field(env->hcounteren, COUNTEREN_IR) &&
95 get_field(env->mcounteren, COUNTEREN_IR)) {
0e62f92e 96 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
e39a8320
AF
97 }
98 break;
99 case CSR_HPMCOUNTER3...CSR_HPMCOUNTER31:
100 if (!get_field(env->hcounteren, 1 << (csrno - CSR_HPMCOUNTER3)) &&
101 get_field(env->mcounteren, 1 << (csrno - CSR_HPMCOUNTER3))) {
0e62f92e 102 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
e39a8320
AF
103 }
104 break;
8987cdc4 105 }
db23e5d9 106 if (riscv_cpu_mxl(env) == MXL_RV32) {
8987cdc4
AF
107 switch (csrno) {
108 case CSR_CYCLEH:
db70794e
BM
109 if (!get_field(env->hcounteren, COUNTEREN_CY) &&
110 get_field(env->mcounteren, COUNTEREN_CY)) {
0e62f92e 111 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
8987cdc4
AF
112 }
113 break;
114 case CSR_TIMEH:
db70794e
BM
115 if (!get_field(env->hcounteren, COUNTEREN_TM) &&
116 get_field(env->mcounteren, COUNTEREN_TM)) {
0e62f92e 117 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
8987cdc4
AF
118 }
119 break;
120 case CSR_INSTRETH:
db70794e
BM
121 if (!get_field(env->hcounteren, COUNTEREN_IR) &&
122 get_field(env->mcounteren, COUNTEREN_IR)) {
0e62f92e 123 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
8987cdc4
AF
124 }
125 break;
126 case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H:
127 if (!get_field(env->hcounteren, 1 << (csrno - CSR_HPMCOUNTER3H)) &&
128 get_field(env->mcounteren, 1 << (csrno - CSR_HPMCOUNTER3H))) {
0e62f92e 129 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
8987cdc4
AF
130 }
131 break;
e39a8320 132 }
e39a8320
AF
133 }
134 }
a88365c1 135#endif
0e62f92e 136 return RISCV_EXCP_NONE;
a88365c1
MC
137}
138
0e62f92e 139static RISCVException ctr32(CPURISCVState *env, int csrno)
8987cdc4 140{
db23e5d9 141 if (riscv_cpu_mxl(env) != MXL_RV32) {
0e62f92e 142 return RISCV_EXCP_ILLEGAL_INST;
8987cdc4
AF
143 }
144
145 return ctr(env, csrno);
146}
147
a88365c1 148#if !defined(CONFIG_USER_ONLY)
0e62f92e 149static RISCVException any(CPURISCVState *env, int csrno)
a88365c1 150{
0e62f92e 151 return RISCV_EXCP_NONE;
a88365c1
MC
152}
153
0e62f92e 154static RISCVException any32(CPURISCVState *env, int csrno)
8987cdc4 155{
db23e5d9 156 if (riscv_cpu_mxl(env) != MXL_RV32) {
0e62f92e 157 return RISCV_EXCP_ILLEGAL_INST;
8987cdc4
AF
158 }
159
160 return any(env, csrno);
161
162}
163
d0237b4d
AP
164static int aia_any(CPURISCVState *env, int csrno)
165{
166 if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
167 return RISCV_EXCP_ILLEGAL_INST;
168 }
169
170 return any(env, csrno);
171}
172
d028ac75
AP
173static int aia_any32(CPURISCVState *env, int csrno)
174{
175 if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
176 return RISCV_EXCP_ILLEGAL_INST;
177 }
178
179 return any32(env, csrno);
180}
181
0e62f92e 182static RISCVException smode(CPURISCVState *env, int csrno)
a88365c1 183{
0e62f92e
AF
184 if (riscv_has_ext(env, RVS)) {
185 return RISCV_EXCP_NONE;
186 }
187
188 return RISCV_EXCP_ILLEGAL_INST;
a88365c1
MC
189}
190
d028ac75
AP
191static int smode32(CPURISCVState *env, int csrno)
192{
193 if (riscv_cpu_mxl(env) != MXL_RV32) {
194 return RISCV_EXCP_ILLEGAL_INST;
195 }
196
197 return smode(env, csrno);
198}
199
c7de92b4
AP
200static int aia_smode(CPURISCVState *env, int csrno)
201{
202 if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
203 return RISCV_EXCP_ILLEGAL_INST;
204 }
205
206 return smode(env, csrno);
207}
208
d028ac75
AP
209static int aia_smode32(CPURISCVState *env, int csrno)
210{
211 if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
212 return RISCV_EXCP_ILLEGAL_INST;
213 }
214
215 return smode32(env, csrno);
216}
217
0e62f92e 218static RISCVException hmode(CPURISCVState *env, int csrno)
ff2cc129
AF
219{
220 if (riscv_has_ext(env, RVS) &&
221 riscv_has_ext(env, RVH)) {
222 /* Hypervisor extension is supported */
223 if ((env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
224 env->priv == PRV_M) {
0e62f92e 225 return RISCV_EXCP_NONE;
e39a8320 226 } else {
0e62f92e 227 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
ff2cc129
AF
228 }
229 }
230
0e62f92e 231 return RISCV_EXCP_ILLEGAL_INST;
ff2cc129
AF
232}
233
0e62f92e 234static RISCVException hmode32(CPURISCVState *env, int csrno)
8987cdc4 235{
db23e5d9 236 if (riscv_cpu_mxl(env) != MXL_RV32) {
dceecac8 237 if (!riscv_cpu_virt_enabled(env)) {
d6f20dac
AF
238 return RISCV_EXCP_ILLEGAL_INST;
239 } else {
240 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
241 }
8987cdc4
AF
242 }
243
244 return hmode(env, csrno);
245
246}
247
4bbe8033
AB
248/* Checks if PointerMasking registers could be accessed */
249static RISCVException pointer_masking(CPURISCVState *env, int csrno)
250{
251 /* Check if j-ext is present */
252 if (riscv_has_ext(env, RVJ)) {
253 return RISCV_EXCP_NONE;
254 }
255 return RISCV_EXCP_ILLEGAL_INST;
256}
257
2b602398
AP
258static int aia_hmode(CPURISCVState *env, int csrno)
259{
260 if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
261 return RISCV_EXCP_ILLEGAL_INST;
262 }
263
264 return hmode(env, csrno);
265}
266
d028ac75
AP
267static int aia_hmode32(CPURISCVState *env, int csrno)
268{
269 if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
270 return RISCV_EXCP_ILLEGAL_INST;
271 }
272
273 return hmode32(env, csrno);
274}
275
0e62f92e 276static RISCVException pmp(CPURISCVState *env, int csrno)
a88365c1 277{
0e62f92e
AF
278 if (riscv_feature(env, RISCV_FEATURE_PMP)) {
279 return RISCV_EXCP_NONE;
280 }
281
282 return RISCV_EXCP_ILLEGAL_INST;
a88365c1 283}
2582a95c
HW
284
285static RISCVException epmp(CPURISCVState *env, int csrno)
286{
287 if (env->priv == PRV_M && riscv_feature(env, RISCV_FEATURE_EPMP)) {
288 return RISCV_EXCP_NONE;
289 }
290
291 return RISCV_EXCP_ILLEGAL_INST;
292}
a88365c1
MC
293#endif
294
c7b95171 295/* User Floating-Point CSRs */
605def6e
AF
296static RISCVException read_fflags(CPURISCVState *env, int csrno,
297 target_ulong *val)
c7b95171 298{
fb738839 299 *val = riscv_cpu_get_fflags(env);
605def6e 300 return RISCV_EXCP_NONE;
c7b95171
MC
301}
302
605def6e
AF
303static RISCVException write_fflags(CPURISCVState *env, int csrno,
304 target_ulong val)
c7b95171
MC
305{
306#if !defined(CONFIG_USER_ONLY)
c163b3ba
WL
307 if (riscv_has_ext(env, RVF)) {
308 env->mstatus |= MSTATUS_FS;
309 }
c7b95171 310#endif
fb738839 311 riscv_cpu_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
605def6e 312 return RISCV_EXCP_NONE;
c7b95171
MC
313}
314
605def6e
AF
315static RISCVException read_frm(CPURISCVState *env, int csrno,
316 target_ulong *val)
c7b95171 317{
c7b95171 318 *val = env->frm;
605def6e 319 return RISCV_EXCP_NONE;
c7b95171
MC
320}
321
605def6e
AF
322static RISCVException write_frm(CPURISCVState *env, int csrno,
323 target_ulong val)
c7b95171
MC
324{
325#if !defined(CONFIG_USER_ONLY)
c163b3ba
WL
326 if (riscv_has_ext(env, RVF)) {
327 env->mstatus |= MSTATUS_FS;
328 }
c7b95171
MC
329#endif
330 env->frm = val & (FSR_RD >> FSR_RD_SHIFT);
605def6e 331 return RISCV_EXCP_NONE;
c7b95171
MC
332}
333
605def6e
AF
334static RISCVException read_fcsr(CPURISCVState *env, int csrno,
335 target_ulong *val)
c7b95171 336{
fb738839 337 *val = (riscv_cpu_get_fflags(env) << FSR_AEXC_SHIFT)
c7b95171 338 | (env->frm << FSR_RD_SHIFT);
605def6e 339 return RISCV_EXCP_NONE;
c7b95171
MC
340}
341
605def6e
AF
342static RISCVException write_fcsr(CPURISCVState *env, int csrno,
343 target_ulong val)
c7b95171
MC
344{
345#if !defined(CONFIG_USER_ONLY)
c163b3ba
WL
346 if (riscv_has_ext(env, RVF)) {
347 env->mstatus |= MSTATUS_FS;
348 }
c7b95171
MC
349#endif
350 env->frm = (val & FSR_RD) >> FSR_RD_SHIFT;
fb738839 351 riscv_cpu_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
605def6e 352 return RISCV_EXCP_NONE;
c7b95171
MC
353}
354
605def6e
AF
355static RISCVException read_vtype(CPURISCVState *env, int csrno,
356 target_ulong *val)
8e3a1f18 357{
d96a271a
LZ
358 uint64_t vill;
359 switch (env->xl) {
360 case MXL_RV32:
361 vill = (uint32_t)env->vill << 31;
362 break;
363 case MXL_RV64:
364 vill = (uint64_t)env->vill << 63;
365 break;
366 default:
367 g_assert_not_reached();
368 }
369 *val = (target_ulong)vill | env->vtype;
605def6e 370 return RISCV_EXCP_NONE;
8e3a1f18
LZ
371}
372
605def6e
AF
373static RISCVException read_vl(CPURISCVState *env, int csrno,
374 target_ulong *val)
8e3a1f18
LZ
375{
376 *val = env->vl;
605def6e 377 return RISCV_EXCP_NONE;
8e3a1f18
LZ
378}
379
2e565054
GH
380static int read_vlenb(CPURISCVState *env, int csrno, target_ulong *val)
381{
382 *val = env_archcpu(env)->cfg.vlen >> 3;
383 return RISCV_EXCP_NONE;
384}
385
605def6e
AF
386static RISCVException read_vxrm(CPURISCVState *env, int csrno,
387 target_ulong *val)
8e3a1f18
LZ
388{
389 *val = env->vxrm;
605def6e 390 return RISCV_EXCP_NONE;
8e3a1f18
LZ
391}
392
605def6e
AF
393static RISCVException write_vxrm(CPURISCVState *env, int csrno,
394 target_ulong val)
8e3a1f18 395{
61b4b69d
LZ
396#if !defined(CONFIG_USER_ONLY)
397 env->mstatus |= MSTATUS_VS;
398#endif
8e3a1f18 399 env->vxrm = val;
605def6e 400 return RISCV_EXCP_NONE;
8e3a1f18
LZ
401}
402
605def6e
AF
403static RISCVException read_vxsat(CPURISCVState *env, int csrno,
404 target_ulong *val)
8e3a1f18
LZ
405{
406 *val = env->vxsat;
605def6e 407 return RISCV_EXCP_NONE;
8e3a1f18
LZ
408}
409
605def6e
AF
410static RISCVException write_vxsat(CPURISCVState *env, int csrno,
411 target_ulong val)
8e3a1f18 412{
61b4b69d
LZ
413#if !defined(CONFIG_USER_ONLY)
414 env->mstatus |= MSTATUS_VS;
415#endif
8e3a1f18 416 env->vxsat = val;
605def6e 417 return RISCV_EXCP_NONE;
8e3a1f18
LZ
418}
419
605def6e
AF
420static RISCVException read_vstart(CPURISCVState *env, int csrno,
421 target_ulong *val)
8e3a1f18
LZ
422{
423 *val = env->vstart;
605def6e 424 return RISCV_EXCP_NONE;
8e3a1f18
LZ
425}
426
605def6e
AF
427static RISCVException write_vstart(CPURISCVState *env, int csrno,
428 target_ulong val)
8e3a1f18 429{
61b4b69d
LZ
430#if !defined(CONFIG_USER_ONLY)
431 env->mstatus |= MSTATUS_VS;
432#endif
f714361e
FC
433 /*
434 * The vstart CSR is defined to have only enough writable bits
435 * to hold the largest element index, i.e. lg2(VLEN) bits.
436 */
437 env->vstart = val & ~(~0ULL << ctzl(env_archcpu(env)->cfg.vlen));
605def6e 438 return RISCV_EXCP_NONE;
8e3a1f18
LZ
439}
440
4594fa5a
LZ
441static int read_vcsr(CPURISCVState *env, int csrno, target_ulong *val)
442{
443 *val = (env->vxrm << VCSR_VXRM_SHIFT) | (env->vxsat << VCSR_VXSAT_SHIFT);
444 return RISCV_EXCP_NONE;
445}
446
447static int write_vcsr(CPURISCVState *env, int csrno, target_ulong val)
448{
449#if !defined(CONFIG_USER_ONLY)
450 env->mstatus |= MSTATUS_VS;
451#endif
452 env->vxrm = (val & VCSR_VXRM) >> VCSR_VXRM_SHIFT;
453 env->vxsat = (val & VCSR_VXSAT) >> VCSR_VXSAT_SHIFT;
454 return RISCV_EXCP_NONE;
455}
456
c7b95171 457/* User Timers and Counters */
605def6e
AF
458static RISCVException read_instret(CPURISCVState *env, int csrno,
459 target_ulong *val)
c7b95171 460{
c7b95171 461#if !defined(CONFIG_USER_ONLY)
740b1759 462 if (icount_enabled()) {
8191d368 463 *val = icount_get();
c7b95171
MC
464 } else {
465 *val = cpu_get_host_ticks();
466 }
467#else
468 *val = cpu_get_host_ticks();
469#endif
605def6e 470 return RISCV_EXCP_NONE;
c7b95171
MC
471}
472
605def6e
AF
473static RISCVException read_instreth(CPURISCVState *env, int csrno,
474 target_ulong *val)
c7b95171 475{
c7b95171 476#if !defined(CONFIG_USER_ONLY)
740b1759 477 if (icount_enabled()) {
8191d368 478 *val = icount_get() >> 32;
c7b95171
MC
479 } else {
480 *val = cpu_get_host_ticks() >> 32;
481 }
482#else
483 *val = cpu_get_host_ticks() >> 32;
484#endif
605def6e 485 return RISCV_EXCP_NONE;
c7b95171 486}
c7b95171
MC
487
488#if defined(CONFIG_USER_ONLY)
605def6e
AF
489static RISCVException read_time(CPURISCVState *env, int csrno,
490 target_ulong *val)
c7b95171
MC
491{
492 *val = cpu_get_host_ticks();
605def6e 493 return RISCV_EXCP_NONE;
c7b95171
MC
494}
495
605def6e
AF
496static RISCVException read_timeh(CPURISCVState *env, int csrno,
497 target_ulong *val)
c7b95171
MC
498{
499 *val = cpu_get_host_ticks() >> 32;
605def6e 500 return RISCV_EXCP_NONE;
c7b95171 501}
c7b95171
MC
502
503#else /* CONFIG_USER_ONLY */
504
605def6e
AF
505static RISCVException read_time(CPURISCVState *env, int csrno,
506 target_ulong *val)
c6957248
AP
507{
508 uint64_t delta = riscv_cpu_virt_enabled(env) ? env->htimedelta : 0;
509
510 if (!env->rdtime_fn) {
605def6e 511 return RISCV_EXCP_ILLEGAL_INST;
c6957248
AP
512 }
513
a47ef6e9 514 *val = env->rdtime_fn(env->rdtime_fn_arg) + delta;
605def6e 515 return RISCV_EXCP_NONE;
c6957248
AP
516}
517
605def6e
AF
518static RISCVException read_timeh(CPURISCVState *env, int csrno,
519 target_ulong *val)
c6957248
AP
520{
521 uint64_t delta = riscv_cpu_virt_enabled(env) ? env->htimedelta : 0;
522
523 if (!env->rdtime_fn) {
605def6e 524 return RISCV_EXCP_ILLEGAL_INST;
c6957248
AP
525 }
526
a47ef6e9 527 *val = (env->rdtime_fn(env->rdtime_fn_arg) + delta) >> 32;
605def6e 528 return RISCV_EXCP_NONE;
c6957248 529}
c6957248 530
c7b95171
MC
531/* Machine constants */
532
d028ac75
AP
533#define M_MODE_INTERRUPTS ((uint64_t)(MIP_MSIP | MIP_MTIP | MIP_MEIP))
534#define S_MODE_INTERRUPTS ((uint64_t)(MIP_SSIP | MIP_STIP | MIP_SEIP))
535#define VS_MODE_INTERRUPTS ((uint64_t)(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP))
536#define HS_MODE_INTERRUPTS ((uint64_t)(MIP_SGEIP | VS_MODE_INTERRUPTS))
c7b95171 537
c7de92b4
AP
538#define VSTOPI_NUM_SRCS 5
539
d028ac75 540static const uint64_t delegable_ints = S_MODE_INTERRUPTS |
d0e53ce3 541 VS_MODE_INTERRUPTS;
d028ac75
AP
542static const uint64_t vs_delegable_ints = VS_MODE_INTERRUPTS;
543static const uint64_t all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS |
881df35d 544 HS_MODE_INTERRUPTS;
bc083a51
JM
545#define DELEGABLE_EXCPS ((1ULL << (RISCV_EXCP_INST_ADDR_MIS)) | \
546 (1ULL << (RISCV_EXCP_INST_ACCESS_FAULT)) | \
547 (1ULL << (RISCV_EXCP_ILLEGAL_INST)) | \
548 (1ULL << (RISCV_EXCP_BREAKPOINT)) | \
549 (1ULL << (RISCV_EXCP_LOAD_ADDR_MIS)) | \
550 (1ULL << (RISCV_EXCP_LOAD_ACCESS_FAULT)) | \
551 (1ULL << (RISCV_EXCP_STORE_AMO_ADDR_MIS)) | \
552 (1ULL << (RISCV_EXCP_STORE_AMO_ACCESS_FAULT)) | \
553 (1ULL << (RISCV_EXCP_U_ECALL)) | \
554 (1ULL << (RISCV_EXCP_S_ECALL)) | \
555 (1ULL << (RISCV_EXCP_VS_ECALL)) | \
556 (1ULL << (RISCV_EXCP_M_ECALL)) | \
557 (1ULL << (RISCV_EXCP_INST_PAGE_FAULT)) | \
558 (1ULL << (RISCV_EXCP_LOAD_PAGE_FAULT)) | \
559 (1ULL << (RISCV_EXCP_STORE_PAGE_FAULT)) | \
560 (1ULL << (RISCV_EXCP_INST_GUEST_PAGE_FAULT)) | \
561 (1ULL << (RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT)) | \
562 (1ULL << (RISCV_EXCP_VIRT_INSTRUCTION_FAULT)) | \
563 (1ULL << (RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT)))
564static const target_ulong vs_delegable_excps = DELEGABLE_EXCPS &
565 ~((1ULL << (RISCV_EXCP_S_ECALL)) |
566 (1ULL << (RISCV_EXCP_VS_ECALL)) |
567 (1ULL << (RISCV_EXCP_M_ECALL)) |
568 (1ULL << (RISCV_EXCP_INST_GUEST_PAGE_FAULT)) |
569 (1ULL << (RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT)) |
570 (1ULL << (RISCV_EXCP_VIRT_INSTRUCTION_FAULT)) |
571 (1ULL << (RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT)));
c7b95171
MC
572static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE |
573 SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
f310df58 574 SSTATUS_SUM | SSTATUS_MXR | SSTATUS_VS;
087b051a 575static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP;
e89b631c
GK
576static const target_ulong hip_writable_mask = MIP_VSSIP;
577static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP;
8747c9ee 578static const target_ulong vsip_writable_mask = MIP_VSSIP;
c7b95171 579
8987cdc4 580static const char valid_vm_1_10_32[16] = {
c7b95171
MC
581 [VM_1_10_MBARE] = 1,
582 [VM_1_10_SV32] = 1
583};
8987cdc4
AF
584
585static const char valid_vm_1_10_64[16] = {
c7b95171
MC
586 [VM_1_10_MBARE] = 1,
587 [VM_1_10_SV39] = 1,
588 [VM_1_10_SV48] = 1,
589 [VM_1_10_SV57] = 1
590};
c7b95171
MC
591
592/* Machine Information Registers */
605def6e
AF
593static RISCVException read_zero(CPURISCVState *env, int csrno,
594 target_ulong *val)
c7b95171 595{
605def6e
AF
596 *val = 0;
597 return RISCV_EXCP_NONE;
c7b95171
MC
598}
599
d0237b4d
AP
600static RISCVException write_ignore(CPURISCVState *env, int csrno,
601 target_ulong val)
602{
603 return RISCV_EXCP_NONE;
604}
605
605def6e
AF
606static RISCVException read_mhartid(CPURISCVState *env, int csrno,
607 target_ulong *val)
c7b95171
MC
608{
609 *val = env->mhartid;
605def6e 610 return RISCV_EXCP_NONE;
c7b95171
MC
611}
612
613/* Machine Trap Setup */
b550f894
RH
614
615/* We do not store SD explicitly, only compute it on demand. */
616static uint64_t add_status_sd(RISCVMXL xl, uint64_t status)
617{
618 if ((status & MSTATUS_FS) == MSTATUS_FS ||
c36b2f1a 619 (status & MSTATUS_VS) == MSTATUS_VS ||
b550f894
RH
620 (status & MSTATUS_XS) == MSTATUS_XS) {
621 switch (xl) {
622 case MXL_RV32:
623 return status | MSTATUS32_SD;
624 case MXL_RV64:
625 return status | MSTATUS64_SD;
457c360f
FP
626 case MXL_RV128:
627 return MSTATUSH128_SD;
b550f894
RH
628 default:
629 g_assert_not_reached();
630 }
631 }
632 return status;
633}
634
605def6e
AF
635static RISCVException read_mstatus(CPURISCVState *env, int csrno,
636 target_ulong *val)
c7b95171 637{
b550f894 638 *val = add_status_sd(riscv_cpu_mxl(env), env->mstatus);
605def6e 639 return RISCV_EXCP_NONE;
c7b95171
MC
640}
641
642static int validate_vm(CPURISCVState *env, target_ulong vm)
643{
db23e5d9 644 if (riscv_cpu_mxl(env) == MXL_RV32) {
8987cdc4
AF
645 return valid_vm_1_10_32[vm & 0xf];
646 } else {
647 return valid_vm_1_10_64[vm & 0xf];
648 }
c7b95171
MC
649}
650
605def6e
AF
651static RISCVException write_mstatus(CPURISCVState *env, int csrno,
652 target_ulong val)
c7b95171 653{
284d697c
YJ
654 uint64_t mstatus = env->mstatus;
655 uint64_t mask = 0;
f310df58 656 RISCVMXL xl = riscv_cpu_mxl(env);
c7b95171
MC
657
658 /* flush tlb on mstatus fields that affect VM */
1a9540d1
AF
659 if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV |
660 MSTATUS_MPRV | MSTATUS_SUM)) {
661 tlb_flush(env_cpu(env));
c7b95171 662 }
1a9540d1 663 mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
c163b3ba 664 MSTATUS_SPP | MSTATUS_MPRV | MSTATUS_SUM |
1a9540d1 665 MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR |
61b4b69d 666 MSTATUS_TW | MSTATUS_VS;
8987cdc4 667
c163b3ba
WL
668 if (riscv_has_ext(env, RVF)) {
669 mask |= MSTATUS_FS;
670 }
671
f297245f 672 if (xl != MXL_RV32 || env->debugger) {
8987cdc4
AF
673 /*
674 * RV32: MPV and GVA are not in mstatus. The current plan is to
675 * add them to mstatush. For now, we just don't support it.
676 */
677 mask |= MSTATUS_MPV | MSTATUS_GVA;
f310df58
LZ
678 if ((val & MSTATUS64_UXL) != 0) {
679 mask |= MSTATUS64_UXL;
680 }
8987cdc4 681 }
c7b95171
MC
682
683 mstatus = (mstatus & ~mask) | (val & mask);
684
457c360f 685 if (xl > MXL_RV32) {
f310df58 686 /* SXL field is for now read only */
457c360f 687 mstatus = set_field(mstatus, MSTATUS64_SXL, xl);
4fd7455b 688 }
c7b95171 689 env->mstatus = mstatus;
440544e1 690 env->xl = cpu_recompute_xl(env);
c7b95171 691
605def6e 692 return RISCV_EXCP_NONE;
c7b95171
MC
693}
694
605def6e
AF
695static RISCVException read_mstatush(CPURISCVState *env, int csrno,
696 target_ulong *val)
551fa7e8 697{
284d697c 698 *val = env->mstatus >> 32;
605def6e 699 return RISCV_EXCP_NONE;
551fa7e8
AF
700}
701
605def6e
AF
702static RISCVException write_mstatush(CPURISCVState *env, int csrno,
703 target_ulong val)
551fa7e8 704{
284d697c
YJ
705 uint64_t valh = (uint64_t)val << 32;
706 uint64_t mask = MSTATUS_MPV | MSTATUS_GVA;
707
708 if ((valh ^ env->mstatus) & (MSTATUS_MPV)) {
551fa7e8
AF
709 tlb_flush(env_cpu(env));
710 }
711
284d697c 712 env->mstatus = (env->mstatus & ~mask) | (valh & mask);
551fa7e8 713
605def6e 714 return RISCV_EXCP_NONE;
551fa7e8 715}
551fa7e8 716
457c360f
FP
717static RISCVException read_mstatus_i128(CPURISCVState *env, int csrno,
718 Int128 *val)
719{
720 *val = int128_make128(env->mstatus, add_status_sd(MXL_RV128, env->mstatus));
721 return RISCV_EXCP_NONE;
722}
723
724static RISCVException read_misa_i128(CPURISCVState *env, int csrno,
725 Int128 *val)
726{
727 *val = int128_make128(env->misa_ext, (uint64_t)MXL_RV128 << 62);
728 return RISCV_EXCP_NONE;
729}
730
605def6e
AF
731static RISCVException read_misa(CPURISCVState *env, int csrno,
732 target_ulong *val)
c7b95171 733{
e91a7227
RH
734 target_ulong misa;
735
736 switch (env->misa_mxl) {
737 case MXL_RV32:
738 misa = (target_ulong)MXL_RV32 << 30;
739 break;
740#ifdef TARGET_RISCV64
741 case MXL_RV64:
742 misa = (target_ulong)MXL_RV64 << 62;
743 break;
744#endif
745 default:
746 g_assert_not_reached();
747 }
748
749 *val = misa | env->misa_ext;
605def6e 750 return RISCV_EXCP_NONE;
c7b95171
MC
751}
752
605def6e
AF
753static RISCVException write_misa(CPURISCVState *env, int csrno,
754 target_ulong val)
f18637cd
MC
755{
756 if (!riscv_feature(env, RISCV_FEATURE_MISA)) {
757 /* drop write to misa */
605def6e 758 return RISCV_EXCP_NONE;
f18637cd
MC
759 }
760
761 /* 'I' or 'E' must be present */
762 if (!(val & (RVI | RVE))) {
763 /* It is not, drop write to misa */
605def6e 764 return RISCV_EXCP_NONE;
f18637cd
MC
765 }
766
767 /* 'E' excludes all other extensions */
768 if (val & RVE) {
769 /* when we support 'E' we can do "val = RVE;" however
770 * for now we just drop writes if 'E' is present.
771 */
605def6e 772 return RISCV_EXCP_NONE;
f18637cd
MC
773 }
774
e91a7227
RH
775 /*
776 * misa.MXL writes are not supported by QEMU.
777 * Drop writes to those bits.
778 */
779
f18637cd 780 /* Mask extensions that are not supported by this hart */
e91a7227 781 val &= env->misa_ext_mask;
f18637cd
MC
782
783 /* Mask extensions that are not supported by QEMU */
7b07a37c 784 val &= (RVI | RVE | RVM | RVA | RVF | RVD | RVC | RVS | RVU | RVV);
f18637cd
MC
785
786 /* 'D' depends on 'F', so clear 'D' if 'F' is not present */
787 if ((val & RVD) && !(val & RVF)) {
788 val &= ~RVD;
789 }
790
791 /* Suppress 'C' if next instruction is not aligned
792 * TODO: this should check next_pc
793 */
794 if ((val & RVC) && (GETPC() & ~3) != 0) {
795 val &= ~RVC;
796 }
797
e91a7227
RH
798 /* If nothing changed, do nothing. */
799 if (val == env->misa_ext) {
800 return RISCV_EXCP_NONE;
4fd7455b 801 }
f18637cd 802
c163b3ba
WL
803 if (!(val & RVF)) {
804 env->mstatus &= ~MSTATUS_FS;
805 }
806
f18637cd 807 /* flush translation cache */
e91a7227
RH
808 tb_flush(env_cpu(env));
809 env->misa_ext = val;
440544e1 810 env->xl = riscv_cpu_mxl(env);
605def6e 811 return RISCV_EXCP_NONE;
f18637cd
MC
812}
813
605def6e
AF
814static RISCVException read_medeleg(CPURISCVState *env, int csrno,
815 target_ulong *val)
c7b95171
MC
816{
817 *val = env->medeleg;
605def6e 818 return RISCV_EXCP_NONE;
c7b95171
MC
819}
820
605def6e
AF
821static RISCVException write_medeleg(CPURISCVState *env, int csrno,
822 target_ulong val)
c7b95171 823{
bc083a51 824 env->medeleg = (env->medeleg & ~DELEGABLE_EXCPS) | (val & DELEGABLE_EXCPS);
605def6e 825 return RISCV_EXCP_NONE;
c7b95171
MC
826}
827
d028ac75
AP
828static RISCVException rmw_mideleg64(CPURISCVState *env, int csrno,
829 uint64_t *ret_val,
830 uint64_t new_val, uint64_t wr_mask)
c7b95171 831{
d028ac75
AP
832 uint64_t mask = wr_mask & delegable_ints;
833
834 if (ret_val) {
835 *ret_val = env->mideleg;
836 }
837
838 env->mideleg = (env->mideleg & ~mask) | (new_val & mask);
c7b95171 839
713d8363 840 if (riscv_has_ext(env, RVH)) {
881df35d 841 env->mideleg |= HS_MODE_INTERRUPTS;
713d8363 842 }
d028ac75 843
605def6e 844 return RISCV_EXCP_NONE;
c7b95171
MC
845}
846
d028ac75
AP
847static RISCVException rmw_mideleg(CPURISCVState *env, int csrno,
848 target_ulong *ret_val,
849 target_ulong new_val, target_ulong wr_mask)
c7b95171 850{
d028ac75
AP
851 uint64_t rval;
852 RISCVException ret;
853
854 ret = rmw_mideleg64(env, csrno, &rval, new_val, wr_mask);
855 if (ret_val) {
856 *ret_val = rval;
857 }
858
859 return ret;
c7b95171
MC
860}
861
d028ac75
AP
862static RISCVException rmw_midelegh(CPURISCVState *env, int csrno,
863 target_ulong *ret_val,
864 target_ulong new_val,
865 target_ulong wr_mask)
c7b95171 866{
d028ac75
AP
867 uint64_t rval;
868 RISCVException ret;
869
870 ret = rmw_mideleg64(env, csrno, &rval,
871 ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
872 if (ret_val) {
873 *ret_val = rval >> 32;
874 }
875
876 return ret;
877}
878
879static RISCVException rmw_mie64(CPURISCVState *env, int csrno,
880 uint64_t *ret_val,
881 uint64_t new_val, uint64_t wr_mask)
882{
883 uint64_t mask = wr_mask & all_ints;
884
885 if (ret_val) {
886 *ret_val = env->mie;
887 }
888
889 env->mie = (env->mie & ~mask) | (new_val & mask);
890
881df35d 891 if (!riscv_has_ext(env, RVH)) {
d028ac75 892 env->mie &= ~((uint64_t)MIP_SGEIP);
881df35d 893 }
d028ac75 894
605def6e 895 return RISCV_EXCP_NONE;
c7b95171
MC
896}
897
d028ac75
AP
898static RISCVException rmw_mie(CPURISCVState *env, int csrno,
899 target_ulong *ret_val,
900 target_ulong new_val, target_ulong wr_mask)
901{
902 uint64_t rval;
903 RISCVException ret;
904
905 ret = rmw_mie64(env, csrno, &rval, new_val, wr_mask);
906 if (ret_val) {
907 *ret_val = rval;
908 }
909
910 return ret;
911}
912
913static RISCVException rmw_mieh(CPURISCVState *env, int csrno,
914 target_ulong *ret_val,
915 target_ulong new_val, target_ulong wr_mask)
916{
917 uint64_t rval;
918 RISCVException ret;
919
920 ret = rmw_mie64(env, csrno, &rval,
921 ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
922 if (ret_val) {
923 *ret_val = rval >> 32;
924 }
925
926 return ret;
927}
928
c7de92b4
AP
929static int read_mtopi(CPURISCVState *env, int csrno, target_ulong *val)
930{
931 int irq;
932 uint8_t iprio;
933
934 irq = riscv_cpu_mirq_pending(env);
935 if (irq <= 0 || irq > 63) {
936 *val = 0;
937 } else {
938 iprio = env->miprio[irq];
939 if (!iprio) {
940 if (riscv_cpu_default_priority(irq) > IPRIO_DEFAULT_M) {
941 iprio = IPRIO_MMAXIPRIO;
942 }
943 }
944 *val = (irq & TOPI_IID_MASK) << TOPI_IID_SHIFT;
945 *val |= iprio;
946 }
947
948 return RISCV_EXCP_NONE;
949}
950
d1ceff40
AP
951static int aia_xlate_vs_csrno(CPURISCVState *env, int csrno)
952{
953 if (!riscv_cpu_virt_enabled(env)) {
954 return csrno;
955 }
956
957 switch (csrno) {
958 case CSR_SISELECT:
959 return CSR_VSISELECT;
960 case CSR_SIREG:
961 return CSR_VSIREG;
ac4b0302
AP
962 case CSR_SSETEIPNUM:
963 return CSR_VSSETEIPNUM;
964 case CSR_SCLREIPNUM:
965 return CSR_VSCLREIPNUM;
966 case CSR_SSETEIENUM:
967 return CSR_VSSETEIENUM;
968 case CSR_SCLREIENUM:
969 return CSR_VSCLREIENUM;
970 case CSR_STOPEI:
971 return CSR_VSTOPEI;
d1ceff40
AP
972 default:
973 return csrno;
974 };
975}
976
977static int rmw_xiselect(CPURISCVState *env, int csrno, target_ulong *val,
978 target_ulong new_val, target_ulong wr_mask)
979{
980 target_ulong *iselect;
981
982 /* Translate CSR number for VS-mode */
983 csrno = aia_xlate_vs_csrno(env, csrno);
984
985 /* Find the iselect CSR based on CSR number */
986 switch (csrno) {
987 case CSR_MISELECT:
988 iselect = &env->miselect;
989 break;
990 case CSR_SISELECT:
991 iselect = &env->siselect;
992 break;
993 case CSR_VSISELECT:
994 iselect = &env->vsiselect;
995 break;
996 default:
997 return RISCV_EXCP_ILLEGAL_INST;
998 };
999
1000 if (val) {
1001 *val = *iselect;
1002 }
1003
1004 wr_mask &= ISELECT_MASK;
1005 if (wr_mask) {
1006 *iselect = (*iselect & ~wr_mask) | (new_val & wr_mask);
1007 }
1008
1009 return RISCV_EXCP_NONE;
1010}
1011
1012static int rmw_iprio(target_ulong xlen,
1013 target_ulong iselect, uint8_t *iprio,
1014 target_ulong *val, target_ulong new_val,
1015 target_ulong wr_mask, int ext_irq_no)
1016{
1017 int i, firq, nirqs;
1018 target_ulong old_val;
1019
1020 if (iselect < ISELECT_IPRIO0 || ISELECT_IPRIO15 < iselect) {
1021 return -EINVAL;
1022 }
1023 if (xlen != 32 && iselect & 0x1) {
1024 return -EINVAL;
1025 }
1026
1027 nirqs = 4 * (xlen / 32);
1028 firq = ((iselect - ISELECT_IPRIO0) / (xlen / 32)) * (nirqs);
1029
1030 old_val = 0;
1031 for (i = 0; i < nirqs; i++) {
1032 old_val |= ((target_ulong)iprio[firq + i]) << (IPRIO_IRQ_BITS * i);
1033 }
1034
1035 if (val) {
1036 *val = old_val;
1037 }
1038
1039 if (wr_mask) {
1040 new_val = (old_val & ~wr_mask) | (new_val & wr_mask);
1041 for (i = 0; i < nirqs; i++) {
1042 /*
1043 * M-level and S-level external IRQ priority always read-only
1044 * zero. This means default priority order is always preferred
1045 * for M-level and S-level external IRQs.
1046 */
1047 if ((firq + i) == ext_irq_no) {
1048 continue;
1049 }
1050 iprio[firq + i] = (new_val >> (IPRIO_IRQ_BITS * i)) & 0xff;
1051 }
1052 }
1053
1054 return 0;
1055}
1056
1057static int rmw_xireg(CPURISCVState *env, int csrno, target_ulong *val,
1058 target_ulong new_val, target_ulong wr_mask)
1059{
1060 bool virt;
1061 uint8_t *iprio;
1062 int ret = -EINVAL;
1063 target_ulong priv, isel, vgein;
1064
1065 /* Translate CSR number for VS-mode */
1066 csrno = aia_xlate_vs_csrno(env, csrno);
1067
1068 /* Decode register details from CSR number */
1069 virt = false;
1070 switch (csrno) {
1071 case CSR_MIREG:
1072 iprio = env->miprio;
1073 isel = env->miselect;
1074 priv = PRV_M;
1075 break;
1076 case CSR_SIREG:
1077 iprio = env->siprio;
1078 isel = env->siselect;
1079 priv = PRV_S;
1080 break;
1081 case CSR_VSIREG:
1082 iprio = env->hviprio;
1083 isel = env->vsiselect;
1084 priv = PRV_S;
1085 virt = true;
1086 break;
1087 default:
1088 goto done;
1089 };
1090
1091 /* Find the selected guest interrupt file */
1092 vgein = (virt) ? get_field(env->hstatus, HSTATUS_VGEIN) : 0;
1093
1094 if (ISELECT_IPRIO0 <= isel && isel <= ISELECT_IPRIO15) {
1095 /* Local interrupt priority registers not available for VS-mode */
1096 if (!virt) {
1097 ret = rmw_iprio(riscv_cpu_mxl_bits(env),
1098 isel, iprio, val, new_val, wr_mask,
1099 (priv == PRV_M) ? IRQ_M_EXT : IRQ_S_EXT);
1100 }
1101 } else if (ISELECT_IMSIC_FIRST <= isel && isel <= ISELECT_IMSIC_LAST) {
1102 /* IMSIC registers only available when machine implements it. */
1103 if (env->aia_ireg_rmw_fn[priv]) {
1104 /* Selected guest interrupt file should not be zero */
1105 if (virt && (!vgein || env->geilen < vgein)) {
1106 goto done;
1107 }
1108 /* Call machine specific IMSIC register emulation */
1109 ret = env->aia_ireg_rmw_fn[priv](env->aia_ireg_rmw_fn_arg[priv],
1110 AIA_MAKE_IREG(isel, priv, virt, vgein,
1111 riscv_cpu_mxl_bits(env)),
1112 val, new_val, wr_mask);
1113 }
1114 }
1115
1116done:
1117 if (ret) {
1118 return (riscv_cpu_virt_enabled(env) && virt) ?
1119 RISCV_EXCP_VIRT_INSTRUCTION_FAULT : RISCV_EXCP_ILLEGAL_INST;
1120 }
1121 return RISCV_EXCP_NONE;
1122}
1123
ac4b0302
AP
1124static int rmw_xsetclreinum(CPURISCVState *env, int csrno, target_ulong *val,
1125 target_ulong new_val, target_ulong wr_mask)
1126{
1127 int ret = -EINVAL;
1128 bool set, pend, virt;
1129 target_ulong priv, isel, vgein, xlen, nval, wmask;
1130
1131 /* Translate CSR number for VS-mode */
1132 csrno = aia_xlate_vs_csrno(env, csrno);
1133
1134 /* Decode register details from CSR number */
1135 virt = set = pend = false;
1136 switch (csrno) {
1137 case CSR_MSETEIPNUM:
1138 priv = PRV_M;
1139 set = true;
1140 pend = true;
1141 break;
1142 case CSR_MCLREIPNUM:
1143 priv = PRV_M;
1144 pend = true;
1145 break;
1146 case CSR_MSETEIENUM:
1147 priv = PRV_M;
1148 set = true;
1149 break;
1150 case CSR_MCLREIENUM:
1151 priv = PRV_M;
1152 break;
1153 case CSR_SSETEIPNUM:
1154 priv = PRV_S;
1155 set = true;
1156 pend = true;
1157 break;
1158 case CSR_SCLREIPNUM:
1159 priv = PRV_S;
1160 pend = true;
1161 break;
1162 case CSR_SSETEIENUM:
1163 priv = PRV_S;
1164 set = true;
1165 break;
1166 case CSR_SCLREIENUM:
1167 priv = PRV_S;
1168 break;
1169 case CSR_VSSETEIPNUM:
1170 priv = PRV_S;
1171 virt = true;
1172 set = true;
1173 pend = true;
1174 break;
1175 case CSR_VSCLREIPNUM:
1176 priv = PRV_S;
1177 virt = true;
1178 pend = true;
1179 break;
1180 case CSR_VSSETEIENUM:
1181 priv = PRV_S;
1182 virt = true;
1183 set = true;
1184 break;
1185 case CSR_VSCLREIENUM:
1186 priv = PRV_S;
1187 virt = true;
1188 break;
1189 default:
1190 goto done;
1191 };
1192
1193 /* IMSIC CSRs only available when machine implements IMSIC. */
1194 if (!env->aia_ireg_rmw_fn[priv]) {
1195 goto done;
1196 }
1197
1198 /* Find the selected guest interrupt file */
1199 vgein = (virt) ? get_field(env->hstatus, HSTATUS_VGEIN) : 0;
1200
1201 /* Selected guest interrupt file should be valid */
1202 if (virt && (!vgein || env->geilen < vgein)) {
1203 goto done;
1204 }
1205
1206 /* Set/Clear CSRs always read zero */
1207 if (val) {
1208 *val = 0;
1209 }
1210
1211 if (wr_mask) {
1212 /* Get interrupt number */
1213 new_val &= wr_mask;
1214
1215 /* Find target interrupt pending/enable register */
1216 xlen = riscv_cpu_mxl_bits(env);
1217 isel = (new_val / xlen);
1218 isel *= (xlen / IMSIC_EIPx_BITS);
1219 isel += (pend) ? ISELECT_IMSIC_EIP0 : ISELECT_IMSIC_EIE0;
1220
1221 /* Find the interrupt bit to be set/clear */
1222 wmask = ((target_ulong)1) << (new_val % xlen);
1223 nval = (set) ? wmask : 0;
1224
1225 /* Call machine specific IMSIC register emulation */
1226 ret = env->aia_ireg_rmw_fn[priv](env->aia_ireg_rmw_fn_arg[priv],
1227 AIA_MAKE_IREG(isel, priv, virt,
1228 vgein, xlen),
1229 NULL, nval, wmask);
1230 } else {
1231 ret = 0;
1232 }
1233
1234done:
1235 if (ret) {
1236 return (riscv_cpu_virt_enabled(env) && virt) ?
1237 RISCV_EXCP_VIRT_INSTRUCTION_FAULT : RISCV_EXCP_ILLEGAL_INST;
1238 }
1239 return RISCV_EXCP_NONE;
1240}
1241
1242static int rmw_xtopei(CPURISCVState *env, int csrno, target_ulong *val,
1243 target_ulong new_val, target_ulong wr_mask)
1244{
1245 bool virt;
1246 int ret = -EINVAL;
1247 target_ulong priv, vgein;
1248
1249 /* Translate CSR number for VS-mode */
1250 csrno = aia_xlate_vs_csrno(env, csrno);
1251
1252 /* Decode register details from CSR number */
1253 virt = false;
1254 switch (csrno) {
1255 case CSR_MTOPEI:
1256 priv = PRV_M;
1257 break;
1258 case CSR_STOPEI:
1259 priv = PRV_S;
1260 break;
1261 case CSR_VSTOPEI:
1262 priv = PRV_S;
1263 virt = true;
1264 break;
1265 default:
1266 goto done;
1267 };
1268
1269 /* IMSIC CSRs only available when machine implements IMSIC. */
1270 if (!env->aia_ireg_rmw_fn[priv]) {
1271 goto done;
1272 }
1273
1274 /* Find the selected guest interrupt file */
1275 vgein = (virt) ? get_field(env->hstatus, HSTATUS_VGEIN) : 0;
1276
1277 /* Selected guest interrupt file should be valid */
1278 if (virt && (!vgein || env->geilen < vgein)) {
1279 goto done;
1280 }
1281
1282 /* Call machine specific IMSIC register emulation for TOPEI */
1283 ret = env->aia_ireg_rmw_fn[priv](env->aia_ireg_rmw_fn_arg[priv],
1284 AIA_MAKE_IREG(ISELECT_IMSIC_TOPEI, priv, virt, vgein,
1285 riscv_cpu_mxl_bits(env)),
1286 val, new_val, wr_mask);
1287
1288done:
1289 if (ret) {
1290 return (riscv_cpu_virt_enabled(env) && virt) ?
1291 RISCV_EXCP_VIRT_INSTRUCTION_FAULT : RISCV_EXCP_ILLEGAL_INST;
1292 }
1293 return RISCV_EXCP_NONE;
1294}
1295
605def6e
AF
1296static RISCVException read_mtvec(CPURISCVState *env, int csrno,
1297 target_ulong *val)
c7b95171
MC
1298{
1299 *val = env->mtvec;
605def6e 1300 return RISCV_EXCP_NONE;
c7b95171
MC
1301}
1302
605def6e
AF
1303static RISCVException write_mtvec(CPURISCVState *env, int csrno,
1304 target_ulong val)
c7b95171
MC
1305{
1306 /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */
acbbb94e
MC
1307 if ((val & 3) < 2) {
1308 env->mtvec = val;
c7b95171 1309 } else {
acbbb94e 1310 qemu_log_mask(LOG_UNIMP, "CSR_MTVEC: reserved mode not supported\n");
c7b95171 1311 }
605def6e 1312 return RISCV_EXCP_NONE;
c7b95171
MC
1313}
1314
605def6e
AF
1315static RISCVException read_mcounteren(CPURISCVState *env, int csrno,
1316 target_ulong *val)
c7b95171 1317{
c7b95171 1318 *val = env->mcounteren;
605def6e 1319 return RISCV_EXCP_NONE;
c7b95171
MC
1320}
1321
605def6e
AF
1322static RISCVException write_mcounteren(CPURISCVState *env, int csrno,
1323 target_ulong val)
c7b95171 1324{
c7b95171 1325 env->mcounteren = val;
605def6e 1326 return RISCV_EXCP_NONE;
c7b95171
MC
1327}
1328
c7b95171 1329/* Machine Trap Handling */
457c360f
FP
1330static RISCVException read_mscratch_i128(CPURISCVState *env, int csrno,
1331 Int128 *val)
1332{
1333 *val = int128_make128(env->mscratch, env->mscratchh);
1334 return RISCV_EXCP_NONE;
1335}
1336
1337static RISCVException write_mscratch_i128(CPURISCVState *env, int csrno,
1338 Int128 val)
1339{
1340 env->mscratch = int128_getlo(val);
1341 env->mscratchh = int128_gethi(val);
1342 return RISCV_EXCP_NONE;
1343}
1344
605def6e
AF
1345static RISCVException read_mscratch(CPURISCVState *env, int csrno,
1346 target_ulong *val)
c7b95171
MC
1347{
1348 *val = env->mscratch;
605def6e 1349 return RISCV_EXCP_NONE;
c7b95171
MC
1350}
1351
605def6e
AF
1352static RISCVException write_mscratch(CPURISCVState *env, int csrno,
1353 target_ulong val)
c7b95171
MC
1354{
1355 env->mscratch = val;
605def6e 1356 return RISCV_EXCP_NONE;
c7b95171
MC
1357}
1358
605def6e
AF
1359static RISCVException read_mepc(CPURISCVState *env, int csrno,
1360 target_ulong *val)
c7b95171
MC
1361{
1362 *val = env->mepc;
605def6e 1363 return RISCV_EXCP_NONE;
c7b95171
MC
1364}
1365
605def6e
AF
1366static RISCVException write_mepc(CPURISCVState *env, int csrno,
1367 target_ulong val)
c7b95171
MC
1368{
1369 env->mepc = val;
605def6e 1370 return RISCV_EXCP_NONE;
c7b95171
MC
1371}
1372
605def6e
AF
1373static RISCVException read_mcause(CPURISCVState *env, int csrno,
1374 target_ulong *val)
c7b95171
MC
1375{
1376 *val = env->mcause;
605def6e 1377 return RISCV_EXCP_NONE;
c7b95171
MC
1378}
1379
605def6e
AF
1380static RISCVException write_mcause(CPURISCVState *env, int csrno,
1381 target_ulong val)
c7b95171
MC
1382{
1383 env->mcause = val;
605def6e 1384 return RISCV_EXCP_NONE;
c7b95171
MC
1385}
1386
605def6e
AF
1387static RISCVException read_mtval(CPURISCVState *env, int csrno,
1388 target_ulong *val)
c7b95171 1389{
ac12b601 1390 *val = env->mtval;
605def6e 1391 return RISCV_EXCP_NONE;
c7b95171
MC
1392}
1393
605def6e
AF
1394static RISCVException write_mtval(CPURISCVState *env, int csrno,
1395 target_ulong val)
c7b95171 1396{
ac12b601 1397 env->mtval = val;
605def6e 1398 return RISCV_EXCP_NONE;
c7b95171
MC
1399}
1400
29a9ec9b
AP
1401/* Execution environment configuration setup */
1402static RISCVException read_menvcfg(CPURISCVState *env, int csrno,
1403 target_ulong *val)
1404{
1405 *val = env->menvcfg;
1406 return RISCV_EXCP_NONE;
1407}
1408
1409static RISCVException write_menvcfg(CPURISCVState *env, int csrno,
1410 target_ulong val)
1411{
1412 uint64_t mask = MENVCFG_FIOM | MENVCFG_CBIE | MENVCFG_CBCFE | MENVCFG_CBZE;
1413
1414 if (riscv_cpu_mxl(env) == MXL_RV64) {
1415 mask |= MENVCFG_PBMTE | MENVCFG_STCE;
1416 }
1417 env->menvcfg = (env->menvcfg & ~mask) | (val & mask);
1418
1419 return RISCV_EXCP_NONE;
1420}
1421
1422static RISCVException read_menvcfgh(CPURISCVState *env, int csrno,
1423 target_ulong *val)
1424{
1425 *val = env->menvcfg >> 32;
1426 return RISCV_EXCP_NONE;
1427}
1428
1429static RISCVException write_menvcfgh(CPURISCVState *env, int csrno,
1430 target_ulong val)
1431{
1432 uint64_t mask = MENVCFG_PBMTE | MENVCFG_STCE;
1433 uint64_t valh = (uint64_t)val << 32;
1434
1435 env->menvcfg = (env->menvcfg & ~mask) | (valh & mask);
1436
1437 return RISCV_EXCP_NONE;
1438}
1439
1440static RISCVException read_senvcfg(CPURISCVState *env, int csrno,
1441 target_ulong *val)
1442{
1443 *val = env->senvcfg;
1444 return RISCV_EXCP_NONE;
1445}
1446
1447static RISCVException write_senvcfg(CPURISCVState *env, int csrno,
1448 target_ulong val)
1449{
1450 uint64_t mask = SENVCFG_FIOM | SENVCFG_CBIE | SENVCFG_CBCFE | SENVCFG_CBZE;
1451
1452 env->senvcfg = (env->senvcfg & ~mask) | (val & mask);
1453
1454 return RISCV_EXCP_NONE;
1455}
1456
1457static RISCVException read_henvcfg(CPURISCVState *env, int csrno,
1458 target_ulong *val)
1459{
1460 *val = env->henvcfg;
1461 return RISCV_EXCP_NONE;
1462}
1463
1464static RISCVException write_henvcfg(CPURISCVState *env, int csrno,
1465 target_ulong val)
1466{
1467 uint64_t mask = HENVCFG_FIOM | HENVCFG_CBIE | HENVCFG_CBCFE | HENVCFG_CBZE;
1468
1469 if (riscv_cpu_mxl(env) == MXL_RV64) {
1470 mask |= HENVCFG_PBMTE | HENVCFG_STCE;
1471 }
1472
1473 env->henvcfg = (env->henvcfg & ~mask) | (val & mask);
1474
1475 return RISCV_EXCP_NONE;
1476}
1477
1478static RISCVException read_henvcfgh(CPURISCVState *env, int csrno,
1479 target_ulong *val)
1480{
1481 *val = env->henvcfg >> 32;
1482 return RISCV_EXCP_NONE;
1483}
1484
1485static RISCVException write_henvcfgh(CPURISCVState *env, int csrno,
1486 target_ulong val)
1487{
1488 uint64_t mask = HENVCFG_PBMTE | HENVCFG_STCE;
1489 uint64_t valh = (uint64_t)val << 32;
1490
1491 env->henvcfg = (env->henvcfg & ~mask) | (valh & mask);
1492
1493 return RISCV_EXCP_NONE;
1494}
1495
d028ac75
AP
1496static RISCVException rmw_mip64(CPURISCVState *env, int csrno,
1497 uint64_t *ret_val,
1498 uint64_t new_val, uint64_t wr_mask)
c7b95171 1499{
3109cd98 1500 RISCVCPU *cpu = env_archcpu(env);
33fe584f 1501 uint64_t old_mip, mask = wr_mask & delegable_ints;
d028ac75 1502 uint32_t gin;
71877e29 1503
33fe584f
AF
1504 if (mask & MIP_SEIP) {
1505 env->software_seip = new_val & MIP_SEIP;
1506 new_val |= env->external_seip * MIP_SEIP;
1507 }
1508
71877e29 1509 if (mask) {
d028ac75 1510 old_mip = riscv_cpu_update_mip(cpu, mask, (new_val & mask));
71877e29 1511 } else {
7ec5d303 1512 old_mip = env->mip;
71877e29 1513 }
c7b95171 1514
cd032fe7
AP
1515 if (csrno != CSR_HVIP) {
1516 gin = get_field(env->hstatus, HSTATUS_VGEIN);
1517 old_mip |= (env->hgeip & ((target_ulong)1 << gin)) ? MIP_VSEIP : 0;
1518 }
1519
d028ac75
AP
1520 if (ret_val) {
1521 *ret_val = old_mip;
71877e29 1522 }
c7b95171 1523
605def6e 1524 return RISCV_EXCP_NONE;
c7b95171
MC
1525}
1526
d028ac75
AP
1527static RISCVException rmw_mip(CPURISCVState *env, int csrno,
1528 target_ulong *ret_val,
1529 target_ulong new_val, target_ulong wr_mask)
1530{
1531 uint64_t rval;
1532 RISCVException ret;
1533
1534 ret = rmw_mip64(env, csrno, &rval, new_val, wr_mask);
1535 if (ret_val) {
1536 *ret_val = rval;
1537 }
1538
1539 return ret;
1540}
1541
1542static RISCVException rmw_miph(CPURISCVState *env, int csrno,
1543 target_ulong *ret_val,
1544 target_ulong new_val, target_ulong wr_mask)
1545{
1546 uint64_t rval;
1547 RISCVException ret;
1548
1549 ret = rmw_mip64(env, csrno, &rval,
1550 ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
1551 if (ret_val) {
1552 *ret_val = rval >> 32;
1553 }
1554
1555 return ret;
1556}
1557
c7b95171 1558/* Supervisor Trap Setup */
457c360f
FP
1559static RISCVException read_sstatus_i128(CPURISCVState *env, int csrno,
1560 Int128 *val)
1561{
1562 uint64_t mask = sstatus_v1_10_mask;
1563 uint64_t sstatus = env->mstatus & mask;
f297245f 1564 if (env->xl != MXL_RV32 || env->debugger) {
f310df58
LZ
1565 mask |= SSTATUS64_UXL;
1566 }
457c360f
FP
1567
1568 *val = int128_make128(sstatus, add_status_sd(MXL_RV128, sstatus));
1569 return RISCV_EXCP_NONE;
1570}
1571
605def6e
AF
1572static RISCVException read_sstatus(CPURISCVState *env, int csrno,
1573 target_ulong *val)
c7b95171 1574{
1a9540d1 1575 target_ulong mask = (sstatus_v1_10_mask);
f297245f 1576 if (env->xl != MXL_RV32 || env->debugger) {
f310df58
LZ
1577 mask |= SSTATUS64_UXL;
1578 }
b550f894
RH
1579 /* TODO: Use SXL not MXL. */
1580 *val = add_status_sd(riscv_cpu_mxl(env), env->mstatus & mask);
605def6e 1581 return RISCV_EXCP_NONE;
c7b95171
MC
1582}
1583
605def6e
AF
1584static RISCVException write_sstatus(CPURISCVState *env, int csrno,
1585 target_ulong val)
c7b95171 1586{
1a9540d1 1587 target_ulong mask = (sstatus_v1_10_mask);
f310df58 1588
f297245f 1589 if (env->xl != MXL_RV32 || env->debugger) {
f310df58
LZ
1590 if ((val & SSTATUS64_UXL) != 0) {
1591 mask |= SSTATUS64_UXL;
1592 }
1593 }
c7b95171
MC
1594 target_ulong newval = (env->mstatus & ~mask) | (val & mask);
1595 return write_mstatus(env, CSR_MSTATUS, newval);
1596}
1597
d028ac75
AP
1598static RISCVException rmw_vsie64(CPURISCVState *env, int csrno,
1599 uint64_t *ret_val,
1600 uint64_t new_val, uint64_t wr_mask)
9d5451e0 1601{
d028ac75
AP
1602 RISCVException ret;
1603 uint64_t rval, vsbits, mask = env->hideleg & VS_MODE_INTERRUPTS;
1604
1605 /* Bring VS-level bits to correct position */
1606 vsbits = new_val & (VS_MODE_INTERRUPTS >> 1);
1607 new_val &= ~(VS_MODE_INTERRUPTS >> 1);
1608 new_val |= vsbits << 1;
1609 vsbits = wr_mask & (VS_MODE_INTERRUPTS >> 1);
1610 wr_mask &= ~(VS_MODE_INTERRUPTS >> 1);
1611 wr_mask |= vsbits << 1;
1612
1613 ret = rmw_mie64(env, csrno, &rval, new_val, wr_mask & mask);
1614 if (ret_val) {
1615 rval &= mask;
1616 vsbits = rval & VS_MODE_INTERRUPTS;
1617 rval &= ~VS_MODE_INTERRUPTS;
1618 *ret_val = rval | (vsbits >> 1);
1619 }
1620
1621 return ret;
9d5451e0
GK
1622}
1623
d028ac75
AP
1624static RISCVException rmw_vsie(CPURISCVState *env, int csrno,
1625 target_ulong *ret_val,
1626 target_ulong new_val, target_ulong wr_mask)
c7b95171 1627{
d028ac75
AP
1628 uint64_t rval;
1629 RISCVException ret;
1630
1631 ret = rmw_vsie64(env, csrno, &rval, new_val, wr_mask);
1632 if (ret_val) {
1633 *ret_val = rval;
d0e53ce3 1634 }
d028ac75
AP
1635
1636 return ret;
c7b95171
MC
1637}
1638
d028ac75
AP
1639static RISCVException rmw_vsieh(CPURISCVState *env, int csrno,
1640 target_ulong *ret_val,
1641 target_ulong new_val, target_ulong wr_mask)
c7b95171 1642{
d028ac75
AP
1643 uint64_t rval;
1644 RISCVException ret;
1645
1646 ret = rmw_vsie64(env, csrno, &rval,
1647 ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
1648 if (ret_val) {
1649 *ret_val = rval >> 32;
1650 }
1651
1652 return ret;
9d5451e0 1653}
d0e53ce3 1654
d028ac75
AP
1655static RISCVException rmw_sie64(CPURISCVState *env, int csrno,
1656 uint64_t *ret_val,
1657 uint64_t new_val, uint64_t wr_mask)
9d5451e0 1658{
d028ac75
AP
1659 RISCVException ret;
1660 uint64_t mask = env->mideleg & S_MODE_INTERRUPTS;
1661
d0e53ce3 1662 if (riscv_cpu_virt_enabled(env)) {
2b602398
AP
1663 if (env->hvictl & HVICTL_VTI) {
1664 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
1665 }
d028ac75 1666 ret = rmw_vsie64(env, CSR_VSIE, ret_val, new_val, wr_mask);
d0e53ce3 1667 } else {
d028ac75 1668 ret = rmw_mie64(env, csrno, ret_val, new_val, wr_mask & mask);
d0e53ce3
AF
1669 }
1670
d028ac75
AP
1671 if (ret_val) {
1672 *ret_val &= mask;
1673 }
1674
1675 return ret;
1676}
1677
1678static RISCVException rmw_sie(CPURISCVState *env, int csrno,
1679 target_ulong *ret_val,
1680 target_ulong new_val, target_ulong wr_mask)
1681{
1682 uint64_t rval;
1683 RISCVException ret;
1684
1685 ret = rmw_sie64(env, csrno, &rval, new_val, wr_mask);
2b602398 1686 if (ret == RISCV_EXCP_NONE && ret_val) {
d028ac75
AP
1687 *ret_val = rval;
1688 }
1689
1690 return ret;
1691}
1692
1693static RISCVException rmw_sieh(CPURISCVState *env, int csrno,
1694 target_ulong *ret_val,
1695 target_ulong new_val, target_ulong wr_mask)
1696{
1697 uint64_t rval;
1698 RISCVException ret;
1699
1700 ret = rmw_sie64(env, csrno, &rval,
1701 ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
1702 if (ret_val) {
1703 *ret_val = rval >> 32;
1704 }
1705
1706 return ret;
c7b95171
MC
1707}
1708
605def6e
AF
1709static RISCVException read_stvec(CPURISCVState *env, int csrno,
1710 target_ulong *val)
c7b95171
MC
1711{
1712 *val = env->stvec;
605def6e 1713 return RISCV_EXCP_NONE;
c7b95171
MC
1714}
1715
605def6e
AF
1716static RISCVException write_stvec(CPURISCVState *env, int csrno,
1717 target_ulong val)
c7b95171
MC
1718{
1719 /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */
acbbb94e
MC
1720 if ((val & 3) < 2) {
1721 env->stvec = val;
c7b95171 1722 } else {
acbbb94e 1723 qemu_log_mask(LOG_UNIMP, "CSR_STVEC: reserved mode not supported\n");
c7b95171 1724 }
605def6e 1725 return RISCV_EXCP_NONE;
c7b95171
MC
1726}
1727
605def6e
AF
1728static RISCVException read_scounteren(CPURISCVState *env, int csrno,
1729 target_ulong *val)
c7b95171 1730{
c7b95171 1731 *val = env->scounteren;
605def6e 1732 return RISCV_EXCP_NONE;
c7b95171
MC
1733}
1734
605def6e
AF
1735static RISCVException write_scounteren(CPURISCVState *env, int csrno,
1736 target_ulong val)
c7b95171 1737{
c7b95171 1738 env->scounteren = val;
605def6e 1739 return RISCV_EXCP_NONE;
c7b95171
MC
1740}
1741
1742/* Supervisor Trap Handling */
457c360f
FP
1743static RISCVException read_sscratch_i128(CPURISCVState *env, int csrno,
1744 Int128 *val)
1745{
1746 *val = int128_make128(env->sscratch, env->sscratchh);
1747 return RISCV_EXCP_NONE;
1748}
1749
1750static RISCVException write_sscratch_i128(CPURISCVState *env, int csrno,
1751 Int128 val)
1752{
1753 env->sscratch = int128_getlo(val);
1754 env->sscratchh = int128_gethi(val);
1755 return RISCV_EXCP_NONE;
1756}
1757
605def6e
AF
1758static RISCVException read_sscratch(CPURISCVState *env, int csrno,
1759 target_ulong *val)
c7b95171
MC
1760{
1761 *val = env->sscratch;
605def6e 1762 return RISCV_EXCP_NONE;
c7b95171
MC
1763}
1764
605def6e
AF
1765static RISCVException write_sscratch(CPURISCVState *env, int csrno,
1766 target_ulong val)
c7b95171
MC
1767{
1768 env->sscratch = val;
605def6e 1769 return RISCV_EXCP_NONE;
c7b95171
MC
1770}
1771
605def6e
AF
1772static RISCVException read_sepc(CPURISCVState *env, int csrno,
1773 target_ulong *val)
c7b95171
MC
1774{
1775 *val = env->sepc;
605def6e 1776 return RISCV_EXCP_NONE;
c7b95171
MC
1777}
1778
605def6e
AF
1779static RISCVException write_sepc(CPURISCVState *env, int csrno,
1780 target_ulong val)
c7b95171
MC
1781{
1782 env->sepc = val;
605def6e 1783 return RISCV_EXCP_NONE;
c7b95171
MC
1784}
1785
605def6e
AF
1786static RISCVException read_scause(CPURISCVState *env, int csrno,
1787 target_ulong *val)
c7b95171
MC
1788{
1789 *val = env->scause;
605def6e 1790 return RISCV_EXCP_NONE;
c7b95171
MC
1791}
1792
605def6e
AF
1793static RISCVException write_scause(CPURISCVState *env, int csrno,
1794 target_ulong val)
c7b95171
MC
1795{
1796 env->scause = val;
605def6e 1797 return RISCV_EXCP_NONE;
c7b95171
MC
1798}
1799
605def6e
AF
1800static RISCVException read_stval(CPURISCVState *env, int csrno,
1801 target_ulong *val)
c7b95171 1802{
ac12b601 1803 *val = env->stval;
605def6e 1804 return RISCV_EXCP_NONE;
c7b95171
MC
1805}
1806
605def6e
AF
1807static RISCVException write_stval(CPURISCVState *env, int csrno,
1808 target_ulong val)
c7b95171 1809{
ac12b601 1810 env->stval = val;
605def6e 1811 return RISCV_EXCP_NONE;
c7b95171
MC
1812}
1813
d028ac75
AP
1814static RISCVException rmw_vsip64(CPURISCVState *env, int csrno,
1815 uint64_t *ret_val,
1816 uint64_t new_val, uint64_t wr_mask)
1817{
1818 RISCVException ret;
1819 uint64_t rval, vsbits, mask = env->hideleg & vsip_writable_mask;
1820
1821 /* Bring VS-level bits to correct position */
1822 vsbits = new_val & (VS_MODE_INTERRUPTS >> 1);
1823 new_val &= ~(VS_MODE_INTERRUPTS >> 1);
1824 new_val |= vsbits << 1;
1825 vsbits = wr_mask & (VS_MODE_INTERRUPTS >> 1);
1826 wr_mask &= ~(VS_MODE_INTERRUPTS >> 1);
1827 wr_mask |= vsbits << 1;
1828
1829 ret = rmw_mip64(env, csrno, &rval, new_val, wr_mask & mask);
1830 if (ret_val) {
1831 rval &= mask;
1832 vsbits = rval & VS_MODE_INTERRUPTS;
1833 rval &= ~VS_MODE_INTERRUPTS;
1834 *ret_val = rval | (vsbits >> 1);
1835 }
1836
1837 return ret;
1838}
1839
605def6e 1840static RISCVException rmw_vsip(CPURISCVState *env, int csrno,
d028ac75
AP
1841 target_ulong *ret_val,
1842 target_ulong new_val, target_ulong wr_mask)
9d5451e0 1843{
d028ac75
AP
1844 uint64_t rval;
1845 RISCVException ret;
33979526 1846
d028ac75
AP
1847 ret = rmw_vsip64(env, csrno, &rval, new_val, wr_mask);
1848 if (ret_val) {
1849 *ret_val = rval;
33979526 1850 }
d028ac75 1851
9d5451e0
GK
1852 return ret;
1853}
1854
d028ac75
AP
1855static RISCVException rmw_vsiph(CPURISCVState *env, int csrno,
1856 target_ulong *ret_val,
1857 target_ulong new_val, target_ulong wr_mask)
c7b95171 1858{
d028ac75
AP
1859 uint64_t rval;
1860 RISCVException ret;
1861
1862 ret = rmw_vsip64(env, csrno, &rval,
1863 ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
1864 if (ret_val) {
1865 *ret_val = rval >> 32;
1866 }
1867
1868 return ret;
1869}
1870
1871static RISCVException rmw_sip64(CPURISCVState *env, int csrno,
1872 uint64_t *ret_val,
1873 uint64_t new_val, uint64_t wr_mask)
1874{
1875 RISCVException ret;
1876 uint64_t mask = env->mideleg & sip_writable_mask;
a2e9f57d
AF
1877
1878 if (riscv_cpu_virt_enabled(env)) {
2b602398
AP
1879 if (env->hvictl & HVICTL_VTI) {
1880 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
1881 }
d028ac75 1882 ret = rmw_vsip64(env, CSR_VSIP, ret_val, new_val, wr_mask);
a2e9f57d 1883 } else {
d028ac75 1884 ret = rmw_mip64(env, csrno, ret_val, new_val, wr_mask & mask);
a2e9f57d
AF
1885 }
1886
d028ac75
AP
1887 if (ret_val) {
1888 *ret_val &= env->mideleg & S_MODE_INTERRUPTS;
1889 }
1890
1891 return ret;
1892}
1893
1894static RISCVException rmw_sip(CPURISCVState *env, int csrno,
1895 target_ulong *ret_val,
1896 target_ulong new_val, target_ulong wr_mask)
1897{
1898 uint64_t rval;
1899 RISCVException ret;
1900
1901 ret = rmw_sip64(env, csrno, &rval, new_val, wr_mask);
1902 if (ret_val) {
1903 *ret_val = rval;
33979526 1904 }
d028ac75
AP
1905
1906 return ret;
1907}
1908
1909static RISCVException rmw_siph(CPURISCVState *env, int csrno,
1910 target_ulong *ret_val,
1911 target_ulong new_val, target_ulong wr_mask)
1912{
1913 uint64_t rval;
1914 RISCVException ret;
1915
1916 ret = rmw_sip64(env, csrno, &rval,
1917 ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
1918 if (ret_val) {
1919 *ret_val = rval >> 32;
1920 }
1921
087b051a 1922 return ret;
c7b95171
MC
1923}
1924
1925/* Supervisor Protection and Translation */
605def6e
AF
1926static RISCVException read_satp(CPURISCVState *env, int csrno,
1927 target_ulong *val)
c7b95171
MC
1928{
1929 if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
1930 *val = 0;
605def6e 1931 return RISCV_EXCP_NONE;
1a9540d1
AF
1932 }
1933
1934 if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
605def6e 1935 return RISCV_EXCP_ILLEGAL_INST;
c7b95171 1936 } else {
1a9540d1 1937 *val = env->satp;
c7b95171 1938 }
1a9540d1 1939
605def6e 1940 return RISCV_EXCP_NONE;
c7b95171
MC
1941}
1942
605def6e
AF
1943static RISCVException write_satp(CPURISCVState *env, int csrno,
1944 target_ulong val)
c7b95171 1945{
5242ef88 1946 target_ulong vm, mask;
419ddf00 1947
c7b95171 1948 if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
605def6e 1949 return RISCV_EXCP_NONE;
c7b95171 1950 }
419ddf00 1951
db23e5d9 1952 if (riscv_cpu_mxl(env) == MXL_RV32) {
419ddf00
AF
1953 vm = validate_vm(env, get_field(val, SATP32_MODE));
1954 mask = (val ^ env->satp) & (SATP32_MODE | SATP32_ASID | SATP32_PPN);
419ddf00
AF
1955 } else {
1956 vm = validate_vm(env, get_field(val, SATP64_MODE));
1957 mask = (val ^ env->satp) & (SATP64_MODE | SATP64_ASID | SATP64_PPN);
419ddf00
AF
1958 }
1959
1960 if (vm && mask) {
7f2b5ff1 1961 if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
605def6e 1962 return RISCV_EXCP_ILLEGAL_INST;
7f2b5ff1 1963 } else {
5242ef88
PD
1964 /*
1965 * The ISA defines SATP.MODE=Bare as "no translation", but we still
1966 * pass these through QEMU's TLB emulation as it improves
1967 * performance. Flushing the TLB on SATP writes with paging
1968 * enabled avoids leaking those invalid cached mappings.
1969 */
1970 tlb_flush(env_cpu(env));
7f2b5ff1
MC
1971 env->satp = val;
1972 }
c7b95171 1973 }
605def6e 1974 return RISCV_EXCP_NONE;
c7b95171
MC
1975}
1976
c7de92b4
AP
1977static int read_vstopi(CPURISCVState *env, int csrno, target_ulong *val)
1978{
1979 int irq, ret;
1980 target_ulong topei;
1981 uint64_t vseip, vsgein;
1982 uint32_t iid, iprio, hviid, hviprio, gein;
1983 uint32_t s, scount = 0, siid[VSTOPI_NUM_SRCS], siprio[VSTOPI_NUM_SRCS];
1984
1985 gein = get_field(env->hstatus, HSTATUS_VGEIN);
1986 hviid = get_field(env->hvictl, HVICTL_IID);
1987 hviprio = get_field(env->hvictl, HVICTL_IPRIO);
1988
1989 if (gein) {
1990 vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0;
1991 vseip = env->mie & (env->mip | vsgein) & MIP_VSEIP;
1992 if (gein <= env->geilen && vseip) {
1993 siid[scount] = IRQ_S_EXT;
1994 siprio[scount] = IPRIO_MMAXIPRIO + 1;
1995 if (env->aia_ireg_rmw_fn[PRV_S]) {
1996 /*
1997 * Call machine specific IMSIC register emulation for
1998 * reading TOPEI.
1999 */
2000 ret = env->aia_ireg_rmw_fn[PRV_S](
2001 env->aia_ireg_rmw_fn_arg[PRV_S],
2002 AIA_MAKE_IREG(ISELECT_IMSIC_TOPEI, PRV_S, true, gein,
2003 riscv_cpu_mxl_bits(env)),
2004 &topei, 0, 0);
2005 if (!ret && topei) {
2006 siprio[scount] = topei & IMSIC_TOPEI_IPRIO_MASK;
2007 }
2008 }
2009 scount++;
2010 }
2011 } else {
2012 if (hviid == IRQ_S_EXT && hviprio) {
2013 siid[scount] = IRQ_S_EXT;
2014 siprio[scount] = hviprio;
2015 scount++;
2016 }
2017 }
2018
2019 if (env->hvictl & HVICTL_VTI) {
2020 if (hviid != IRQ_S_EXT) {
2021 siid[scount] = hviid;
2022 siprio[scount] = hviprio;
2023 scount++;
2024 }
2025 } else {
2026 irq = riscv_cpu_vsirq_pending(env);
2027 if (irq != IRQ_S_EXT && 0 < irq && irq <= 63) {
2028 siid[scount] = irq;
2029 siprio[scount] = env->hviprio[irq];
2030 scount++;
2031 }
2032 }
2033
2034 iid = 0;
2035 iprio = UINT_MAX;
2036 for (s = 0; s < scount; s++) {
2037 if (siprio[s] < iprio) {
2038 iid = siid[s];
2039 iprio = siprio[s];
2040 }
2041 }
2042
2043 if (iid) {
2044 if (env->hvictl & HVICTL_IPRIOM) {
2045 if (iprio > IPRIO_MMAXIPRIO) {
2046 iprio = IPRIO_MMAXIPRIO;
2047 }
2048 if (!iprio) {
2049 if (riscv_cpu_default_priority(iid) > IPRIO_DEFAULT_S) {
2050 iprio = IPRIO_MMAXIPRIO;
2051 }
2052 }
2053 } else {
2054 iprio = 1;
2055 }
2056 } else {
2057 iprio = 0;
2058 }
2059
2060 *val = (iid & TOPI_IID_MASK) << TOPI_IID_SHIFT;
2061 *val |= iprio;
2062 return RISCV_EXCP_NONE;
2063}
2064
2065static int read_stopi(CPURISCVState *env, int csrno, target_ulong *val)
2066{
2067 int irq;
2068 uint8_t iprio;
2069
2070 if (riscv_cpu_virt_enabled(env)) {
2071 return read_vstopi(env, CSR_VSTOPI, val);
2072 }
2073
2074 irq = riscv_cpu_sirq_pending(env);
2075 if (irq <= 0 || irq > 63) {
2076 *val = 0;
2077 } else {
2078 iprio = env->siprio[irq];
2079 if (!iprio) {
2080 if (riscv_cpu_default_priority(irq) > IPRIO_DEFAULT_S) {
2081 iprio = IPRIO_MMAXIPRIO;
2082 }
2083 }
2084 *val = (irq & TOPI_IID_MASK) << TOPI_IID_SHIFT;
2085 *val |= iprio;
2086 }
2087
2088 return RISCV_EXCP_NONE;
2089}
2090
ff2cc129 2091/* Hypervisor Extensions */
605def6e
AF
2092static RISCVException read_hstatus(CPURISCVState *env, int csrno,
2093 target_ulong *val)
ff2cc129
AF
2094{
2095 *val = env->hstatus;
db23e5d9 2096 if (riscv_cpu_mxl(env) != MXL_RV32) {
8987cdc4
AF
2097 /* We only support 64-bit VSXL */
2098 *val = set_field(*val, HSTATUS_VSXL, 2);
2099 }
30f663b1
AF
2100 /* We only support little endian */
2101 *val = set_field(*val, HSTATUS_VSBE, 0);
605def6e 2102 return RISCV_EXCP_NONE;
ff2cc129
AF
2103}
2104
605def6e
AF
2105static RISCVException write_hstatus(CPURISCVState *env, int csrno,
2106 target_ulong val)
ff2cc129
AF
2107{
2108 env->hstatus = val;
db23e5d9 2109 if (riscv_cpu_mxl(env) != MXL_RV32 && get_field(val, HSTATUS_VSXL) != 2) {
f8dc878e
AF
2110 qemu_log_mask(LOG_UNIMP, "QEMU does not support mixed HSXLEN options.");
2111 }
30f663b1
AF
2112 if (get_field(val, HSTATUS_VSBE) != 0) {
2113 qemu_log_mask(LOG_UNIMP, "QEMU does not support big endian guests.");
2114 }
605def6e 2115 return RISCV_EXCP_NONE;
ff2cc129
AF
2116}
2117
605def6e
AF
2118static RISCVException read_hedeleg(CPURISCVState *env, int csrno,
2119 target_ulong *val)
ff2cc129
AF
2120{
2121 *val = env->hedeleg;
605def6e 2122 return RISCV_EXCP_NONE;
ff2cc129
AF
2123}
2124
605def6e
AF
2125static RISCVException write_hedeleg(CPURISCVState *env, int csrno,
2126 target_ulong val)
ff2cc129 2127{
bc083a51 2128 env->hedeleg = val & vs_delegable_excps;
605def6e 2129 return RISCV_EXCP_NONE;
ff2cc129
AF
2130}
2131
d028ac75
AP
2132static RISCVException rmw_hideleg64(CPURISCVState *env, int csrno,
2133 uint64_t *ret_val,
2134 uint64_t new_val, uint64_t wr_mask)
ff2cc129 2135{
d028ac75
AP
2136 uint64_t mask = wr_mask & vs_delegable_ints;
2137
2138 if (ret_val) {
2139 *ret_val = env->hideleg & vs_delegable_ints;
2140 }
2141
2142 env->hideleg = (env->hideleg & ~mask) | (new_val & mask);
605def6e 2143 return RISCV_EXCP_NONE;
ff2cc129
AF
2144}
2145
d028ac75
AP
2146static RISCVException rmw_hideleg(CPURISCVState *env, int csrno,
2147 target_ulong *ret_val,
2148 target_ulong new_val, target_ulong wr_mask)
ff2cc129 2149{
d028ac75
AP
2150 uint64_t rval;
2151 RISCVException ret;
2152
2153 ret = rmw_hideleg64(env, csrno, &rval, new_val, wr_mask);
2154 if (ret_val) {
2155 *ret_val = rval;
2156 }
2157
2158 return ret;
2159}
2160
2161static RISCVException rmw_hidelegh(CPURISCVState *env, int csrno,
2162 target_ulong *ret_val,
2163 target_ulong new_val, target_ulong wr_mask)
2164{
2165 uint64_t rval;
2166 RISCVException ret;
2167
2168 ret = rmw_hideleg64(env, csrno, &rval,
2169 ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
2170 if (ret_val) {
2171 *ret_val = rval >> 32;
2172 }
2173
2174 return ret;
2175}
2176
2177static RISCVException rmw_hvip64(CPURISCVState *env, int csrno,
2178 uint64_t *ret_val,
2179 uint64_t new_val, uint64_t wr_mask)
2180{
2181 RISCVException ret;
2182
2183 ret = rmw_mip64(env, csrno, ret_val, new_val,
2184 wr_mask & hvip_writable_mask);
2185 if (ret_val) {
2186 *ret_val &= VS_MODE_INTERRUPTS;
2187 }
2188
2189 return ret;
ff2cc129
AF
2190}
2191
605def6e 2192static RISCVException rmw_hvip(CPURISCVState *env, int csrno,
d028ac75
AP
2193 target_ulong *ret_val,
2194 target_ulong new_val, target_ulong wr_mask)
83028098 2195{
d028ac75
AP
2196 uint64_t rval;
2197 RISCVException ret;
83028098 2198
d028ac75
AP
2199 ret = rmw_hvip64(env, csrno, &rval, new_val, wr_mask);
2200 if (ret_val) {
2201 *ret_val = rval;
2202 }
2203
2204 return ret;
2205}
2206
2207static RISCVException rmw_hviph(CPURISCVState *env, int csrno,
2208 target_ulong *ret_val,
2209 target_ulong new_val, target_ulong wr_mask)
2210{
2211 uint64_t rval;
2212 RISCVException ret;
2213
2214 ret = rmw_hvip64(env, csrno, &rval,
2215 ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
2216 if (ret_val) {
2217 *ret_val = rval >> 32;
33979526 2218 }
d028ac75 2219
83028098
AF
2220 return ret;
2221}
2222
605def6e
AF
2223static RISCVException rmw_hip(CPURISCVState *env, int csrno,
2224 target_ulong *ret_value,
2225 target_ulong new_value, target_ulong write_mask)
ff2cc129 2226{
cd032fe7 2227 int ret = rmw_mip(env, csrno, ret_value, new_value,
ff2cc129
AF
2228 write_mask & hip_writable_mask);
2229
33979526 2230 if (ret_value) {
881df35d 2231 *ret_value &= HS_MODE_INTERRUPTS;
33979526 2232 }
ff2cc129
AF
2233 return ret;
2234}
2235
d028ac75
AP
2236static RISCVException rmw_hie(CPURISCVState *env, int csrno,
2237 target_ulong *ret_val,
2238 target_ulong new_val, target_ulong wr_mask)
ff2cc129 2239{
d028ac75
AP
2240 uint64_t rval;
2241 RISCVException ret;
ff2cc129 2242
d028ac75
AP
2243 ret = rmw_mie64(env, csrno, &rval, new_val, wr_mask & HS_MODE_INTERRUPTS);
2244 if (ret_val) {
2245 *ret_val = rval & HS_MODE_INTERRUPTS;
2246 }
2247
2248 return ret;
ff2cc129
AF
2249}
2250
605def6e
AF
2251static RISCVException read_hcounteren(CPURISCVState *env, int csrno,
2252 target_ulong *val)
ff2cc129
AF
2253{
2254 *val = env->hcounteren;
605def6e 2255 return RISCV_EXCP_NONE;
ff2cc129
AF
2256}
2257
605def6e
AF
2258static RISCVException write_hcounteren(CPURISCVState *env, int csrno,
2259 target_ulong val)
ff2cc129
AF
2260{
2261 env->hcounteren = val;
605def6e 2262 return RISCV_EXCP_NONE;
ff2cc129
AF
2263}
2264
cd032fe7
AP
2265static RISCVException read_hgeie(CPURISCVState *env, int csrno,
2266 target_ulong *val)
83028098 2267{
377cbb4b 2268 if (val) {
cd032fe7 2269 *val = env->hgeie;
377cbb4b 2270 }
605def6e 2271 return RISCV_EXCP_NONE;
83028098
AF
2272}
2273
cd032fe7
AP
2274static RISCVException write_hgeie(CPURISCVState *env, int csrno,
2275 target_ulong val)
2276{
2277 /* Only GEILEN:1 bits implemented and BIT0 is never implemented */
2278 val &= ((((target_ulong)1) << env->geilen) - 1) << 1;
2279 env->hgeie = val;
2280 /* Update mip.SGEIP bit */
2281 riscv_cpu_update_mip(env_archcpu(env), MIP_SGEIP,
2282 BOOL_TO_MASK(!!(env->hgeie & env->hgeip)));
2283 return RISCV_EXCP_NONE;
2284}
2285
605def6e
AF
2286static RISCVException read_htval(CPURISCVState *env, int csrno,
2287 target_ulong *val)
ff2cc129
AF
2288{
2289 *val = env->htval;
605def6e 2290 return RISCV_EXCP_NONE;
ff2cc129
AF
2291}
2292
605def6e
AF
2293static RISCVException write_htval(CPURISCVState *env, int csrno,
2294 target_ulong val)
ff2cc129
AF
2295{
2296 env->htval = val;
605def6e 2297 return RISCV_EXCP_NONE;
ff2cc129
AF
2298}
2299
605def6e
AF
2300static RISCVException read_htinst(CPURISCVState *env, int csrno,
2301 target_ulong *val)
ff2cc129
AF
2302{
2303 *val = env->htinst;
605def6e 2304 return RISCV_EXCP_NONE;
ff2cc129
AF
2305}
2306
605def6e
AF
2307static RISCVException write_htinst(CPURISCVState *env, int csrno,
2308 target_ulong val)
ff2cc129 2309{
605def6e 2310 return RISCV_EXCP_NONE;
ff2cc129
AF
2311}
2312
cd032fe7
AP
2313static RISCVException read_hgeip(CPURISCVState *env, int csrno,
2314 target_ulong *val)
83028098 2315{
377cbb4b 2316 if (val) {
cd032fe7 2317 *val = env->hgeip;
377cbb4b 2318 }
605def6e 2319 return RISCV_EXCP_NONE;
83028098
AF
2320}
2321
605def6e
AF
2322static RISCVException read_hgatp(CPURISCVState *env, int csrno,
2323 target_ulong *val)
ff2cc129
AF
2324{
2325 *val = env->hgatp;
605def6e 2326 return RISCV_EXCP_NONE;
ff2cc129
AF
2327}
2328
605def6e
AF
2329static RISCVException write_hgatp(CPURISCVState *env, int csrno,
2330 target_ulong val)
ff2cc129
AF
2331{
2332 env->hgatp = val;
605def6e 2333 return RISCV_EXCP_NONE;
ff2cc129
AF
2334}
2335
605def6e
AF
2336static RISCVException read_htimedelta(CPURISCVState *env, int csrno,
2337 target_ulong *val)
c6957248
AP
2338{
2339 if (!env->rdtime_fn) {
605def6e 2340 return RISCV_EXCP_ILLEGAL_INST;
c6957248
AP
2341 }
2342
c6957248 2343 *val = env->htimedelta;
605def6e 2344 return RISCV_EXCP_NONE;
c6957248
AP
2345}
2346
605def6e
AF
2347static RISCVException write_htimedelta(CPURISCVState *env, int csrno,
2348 target_ulong val)
c6957248
AP
2349{
2350 if (!env->rdtime_fn) {
605def6e 2351 return RISCV_EXCP_ILLEGAL_INST;
c6957248
AP
2352 }
2353
db23e5d9 2354 if (riscv_cpu_mxl(env) == MXL_RV32) {
8987cdc4
AF
2355 env->htimedelta = deposit64(env->htimedelta, 0, 32, (uint64_t)val);
2356 } else {
2357 env->htimedelta = val;
2358 }
605def6e 2359 return RISCV_EXCP_NONE;
c6957248
AP
2360}
2361
605def6e
AF
2362static RISCVException read_htimedeltah(CPURISCVState *env, int csrno,
2363 target_ulong *val)
c6957248
AP
2364{
2365 if (!env->rdtime_fn) {
605def6e 2366 return RISCV_EXCP_ILLEGAL_INST;
c6957248
AP
2367 }
2368
2369 *val = env->htimedelta >> 32;
605def6e 2370 return RISCV_EXCP_NONE;
c6957248
AP
2371}
2372
605def6e
AF
2373static RISCVException write_htimedeltah(CPURISCVState *env, int csrno,
2374 target_ulong val)
c6957248
AP
2375{
2376 if (!env->rdtime_fn) {
605def6e 2377 return RISCV_EXCP_ILLEGAL_INST;
c6957248
AP
2378 }
2379
2380 env->htimedelta = deposit64(env->htimedelta, 32, 32, (uint64_t)val);
605def6e 2381 return RISCV_EXCP_NONE;
c6957248 2382}
c6957248 2383
2b602398
AP
2384static int read_hvictl(CPURISCVState *env, int csrno, target_ulong *val)
2385{
2386 *val = env->hvictl;
2387 return RISCV_EXCP_NONE;
2388}
2389
2390static int write_hvictl(CPURISCVState *env, int csrno, target_ulong val)
2391{
2392 env->hvictl = val & HVICTL_VALID_MASK;
2393 return RISCV_EXCP_NONE;
2394}
2395
2396static int read_hvipriox(CPURISCVState *env, int first_index,
2397 uint8_t *iprio, target_ulong *val)
2398{
2399 int i, irq, rdzero, num_irqs = 4 * (riscv_cpu_mxl_bits(env) / 32);
2400
2401 /* First index has to be a multiple of number of irqs per register */
2402 if (first_index % num_irqs) {
2403 return (riscv_cpu_virt_enabled(env)) ?
2404 RISCV_EXCP_VIRT_INSTRUCTION_FAULT : RISCV_EXCP_ILLEGAL_INST;
2405 }
2406
2407 /* Fill-up return value */
2408 *val = 0;
2409 for (i = 0; i < num_irqs; i++) {
2410 if (riscv_cpu_hviprio_index2irq(first_index + i, &irq, &rdzero)) {
2411 continue;
2412 }
2413 if (rdzero) {
2414 continue;
2415 }
2416 *val |= ((target_ulong)iprio[irq]) << (i * 8);
2417 }
2418
2419 return RISCV_EXCP_NONE;
2420}
2421
2422static int write_hvipriox(CPURISCVState *env, int first_index,
2423 uint8_t *iprio, target_ulong val)
2424{
2425 int i, irq, rdzero, num_irqs = 4 * (riscv_cpu_mxl_bits(env) / 32);
2426
2427 /* First index has to be a multiple of number of irqs per register */
2428 if (first_index % num_irqs) {
2429 return (riscv_cpu_virt_enabled(env)) ?
2430 RISCV_EXCP_VIRT_INSTRUCTION_FAULT : RISCV_EXCP_ILLEGAL_INST;
2431 }
2432
2433 /* Fill-up priority arrary */
2434 for (i = 0; i < num_irqs; i++) {
2435 if (riscv_cpu_hviprio_index2irq(first_index + i, &irq, &rdzero)) {
2436 continue;
2437 }
2438 if (rdzero) {
2439 iprio[irq] = 0;
2440 } else {
2441 iprio[irq] = (val >> (i * 8)) & 0xff;
2442 }
2443 }
2444
2445 return RISCV_EXCP_NONE;
2446}
2447
2448static int read_hviprio1(CPURISCVState *env, int csrno, target_ulong *val)
2449{
2450 return read_hvipriox(env, 0, env->hviprio, val);
2451}
2452
2453static int write_hviprio1(CPURISCVState *env, int csrno, target_ulong val)
2454{
2455 return write_hvipriox(env, 0, env->hviprio, val);
2456}
2457
2458static int read_hviprio1h(CPURISCVState *env, int csrno, target_ulong *val)
2459{
2460 return read_hvipriox(env, 4, env->hviprio, val);
2461}
2462
2463static int write_hviprio1h(CPURISCVState *env, int csrno, target_ulong val)
2464{
2465 return write_hvipriox(env, 4, env->hviprio, val);
2466}
2467
2468static int read_hviprio2(CPURISCVState *env, int csrno, target_ulong *val)
2469{
2470 return read_hvipriox(env, 8, env->hviprio, val);
2471}
2472
2473static int write_hviprio2(CPURISCVState *env, int csrno, target_ulong val)
2474{
2475 return write_hvipriox(env, 8, env->hviprio, val);
2476}
2477
2478static int read_hviprio2h(CPURISCVState *env, int csrno, target_ulong *val)
2479{
2480 return read_hvipriox(env, 12, env->hviprio, val);
2481}
2482
2483static int write_hviprio2h(CPURISCVState *env, int csrno, target_ulong val)
2484{
2485 return write_hvipriox(env, 12, env->hviprio, val);
2486}
2487
8747c9ee 2488/* Virtual CSR Registers */
605def6e
AF
2489static RISCVException read_vsstatus(CPURISCVState *env, int csrno,
2490 target_ulong *val)
8747c9ee
AF
2491{
2492 *val = env->vsstatus;
605def6e 2493 return RISCV_EXCP_NONE;
8747c9ee
AF
2494}
2495
605def6e
AF
2496static RISCVException write_vsstatus(CPURISCVState *env, int csrno,
2497 target_ulong val)
8747c9ee 2498{
284d697c 2499 uint64_t mask = (target_ulong)-1;
f310df58
LZ
2500 if ((val & VSSTATUS64_UXL) == 0) {
2501 mask &= ~VSSTATUS64_UXL;
2502 }
284d697c 2503 env->vsstatus = (env->vsstatus & ~mask) | (uint64_t)val;
605def6e 2504 return RISCV_EXCP_NONE;
8747c9ee
AF
2505}
2506
8747c9ee
AF
2507static int read_vstvec(CPURISCVState *env, int csrno, target_ulong *val)
2508{
2509 *val = env->vstvec;
605def6e 2510 return RISCV_EXCP_NONE;
8747c9ee
AF
2511}
2512
605def6e
AF
2513static RISCVException write_vstvec(CPURISCVState *env, int csrno,
2514 target_ulong val)
8747c9ee
AF
2515{
2516 env->vstvec = val;
605def6e 2517 return RISCV_EXCP_NONE;
8747c9ee
AF
2518}
2519
605def6e
AF
2520static RISCVException read_vsscratch(CPURISCVState *env, int csrno,
2521 target_ulong *val)
8747c9ee
AF
2522{
2523 *val = env->vsscratch;
605def6e 2524 return RISCV_EXCP_NONE;
8747c9ee
AF
2525}
2526
605def6e
AF
2527static RISCVException write_vsscratch(CPURISCVState *env, int csrno,
2528 target_ulong val)
8747c9ee
AF
2529{
2530 env->vsscratch = val;
605def6e 2531 return RISCV_EXCP_NONE;
8747c9ee
AF
2532}
2533
605def6e
AF
2534static RISCVException read_vsepc(CPURISCVState *env, int csrno,
2535 target_ulong *val)
8747c9ee
AF
2536{
2537 *val = env->vsepc;
605def6e 2538 return RISCV_EXCP_NONE;
8747c9ee
AF
2539}
2540
605def6e
AF
2541static RISCVException write_vsepc(CPURISCVState *env, int csrno,
2542 target_ulong val)
8747c9ee
AF
2543{
2544 env->vsepc = val;
605def6e 2545 return RISCV_EXCP_NONE;
8747c9ee
AF
2546}
2547
605def6e
AF
2548static RISCVException read_vscause(CPURISCVState *env, int csrno,
2549 target_ulong *val)
8747c9ee
AF
2550{
2551 *val = env->vscause;
605def6e 2552 return RISCV_EXCP_NONE;
8747c9ee
AF
2553}
2554
605def6e
AF
2555static RISCVException write_vscause(CPURISCVState *env, int csrno,
2556 target_ulong val)
8747c9ee
AF
2557{
2558 env->vscause = val;
605def6e 2559 return RISCV_EXCP_NONE;
8747c9ee
AF
2560}
2561
605def6e
AF
2562static RISCVException read_vstval(CPURISCVState *env, int csrno,
2563 target_ulong *val)
8747c9ee
AF
2564{
2565 *val = env->vstval;
605def6e 2566 return RISCV_EXCP_NONE;
8747c9ee
AF
2567}
2568
605def6e
AF
2569static RISCVException write_vstval(CPURISCVState *env, int csrno,
2570 target_ulong val)
8747c9ee
AF
2571{
2572 env->vstval = val;
605def6e 2573 return RISCV_EXCP_NONE;
8747c9ee
AF
2574}
2575
605def6e
AF
2576static RISCVException read_vsatp(CPURISCVState *env, int csrno,
2577 target_ulong *val)
8747c9ee
AF
2578{
2579 *val = env->vsatp;
605def6e 2580 return RISCV_EXCP_NONE;
8747c9ee
AF
2581}
2582
605def6e
AF
2583static RISCVException write_vsatp(CPURISCVState *env, int csrno,
2584 target_ulong val)
8747c9ee
AF
2585{
2586 env->vsatp = val;
605def6e 2587 return RISCV_EXCP_NONE;
8747c9ee
AF
2588}
2589
605def6e
AF
2590static RISCVException read_mtval2(CPURISCVState *env, int csrno,
2591 target_ulong *val)
34cfb5f6
AF
2592{
2593 *val = env->mtval2;
605def6e 2594 return RISCV_EXCP_NONE;
34cfb5f6
AF
2595}
2596
605def6e
AF
2597static RISCVException write_mtval2(CPURISCVState *env, int csrno,
2598 target_ulong val)
34cfb5f6
AF
2599{
2600 env->mtval2 = val;
605def6e 2601 return RISCV_EXCP_NONE;
34cfb5f6
AF
2602}
2603
605def6e
AF
2604static RISCVException read_mtinst(CPURISCVState *env, int csrno,
2605 target_ulong *val)
34cfb5f6
AF
2606{
2607 *val = env->mtinst;
605def6e 2608 return RISCV_EXCP_NONE;
34cfb5f6
AF
2609}
2610
605def6e
AF
2611static RISCVException write_mtinst(CPURISCVState *env, int csrno,
2612 target_ulong val)
34cfb5f6
AF
2613{
2614 env->mtinst = val;
605def6e 2615 return RISCV_EXCP_NONE;
34cfb5f6
AF
2616}
2617
c7b95171 2618/* Physical Memory Protection */
2582a95c
HW
2619static RISCVException read_mseccfg(CPURISCVState *env, int csrno,
2620 target_ulong *val)
2621{
2622 *val = mseccfg_csr_read(env);
2623 return RISCV_EXCP_NONE;
2624}
2625
2626static RISCVException write_mseccfg(CPURISCVState *env, int csrno,
2627 target_ulong val)
2628{
2629 mseccfg_csr_write(env, val);
2630 return RISCV_EXCP_NONE;
2631}
2632
79f26b3b
LZ
2633static bool check_pmp_reg_index(CPURISCVState *env, uint32_t reg_index)
2634{
2635 /* TODO: RV128 restriction check */
2636 if ((reg_index & 1) && (riscv_cpu_mxl(env) == MXL_RV64)) {
2637 return false;
2638 }
2639 return true;
2640}
2641
605def6e
AF
2642static RISCVException read_pmpcfg(CPURISCVState *env, int csrno,
2643 target_ulong *val)
c7b95171 2644{
79f26b3b
LZ
2645 uint32_t reg_index = csrno - CSR_PMPCFG0;
2646
2647 if (!check_pmp_reg_index(env, reg_index)) {
2648 return RISCV_EXCP_ILLEGAL_INST;
2649 }
c7b95171 2650 *val = pmpcfg_csr_read(env, csrno - CSR_PMPCFG0);
605def6e 2651 return RISCV_EXCP_NONE;
c7b95171
MC
2652}
2653
605def6e
AF
2654static RISCVException write_pmpcfg(CPURISCVState *env, int csrno,
2655 target_ulong val)
c7b95171 2656{
79f26b3b
LZ
2657 uint32_t reg_index = csrno - CSR_PMPCFG0;
2658
2659 if (!check_pmp_reg_index(env, reg_index)) {
2660 return RISCV_EXCP_ILLEGAL_INST;
2661 }
c7b95171 2662 pmpcfg_csr_write(env, csrno - CSR_PMPCFG0, val);
605def6e 2663 return RISCV_EXCP_NONE;
c7b95171
MC
2664}
2665
605def6e
AF
2666static RISCVException read_pmpaddr(CPURISCVState *env, int csrno,
2667 target_ulong *val)
c7b95171
MC
2668{
2669 *val = pmpaddr_csr_read(env, csrno - CSR_PMPADDR0);
605def6e 2670 return RISCV_EXCP_NONE;
c7b95171
MC
2671}
2672
605def6e
AF
2673static RISCVException write_pmpaddr(CPURISCVState *env, int csrno,
2674 target_ulong val)
c7b95171
MC
2675{
2676 pmpaddr_csr_write(env, csrno - CSR_PMPADDR0, val);
605def6e 2677 return RISCV_EXCP_NONE;
c7b95171
MC
2678}
2679
4bbe8033
AB
2680/*
2681 * Functions to access Pointer Masking feature registers
2682 * We have to check if current priv lvl could modify
2683 * csr in given mode
2684 */
2685static bool check_pm_current_disabled(CPURISCVState *env, int csrno)
2686{
2687 int csr_priv = get_field(csrno, 0x300);
2688 int pm_current;
2689
47bdec82
LZ
2690 if (env->debugger) {
2691 return false;
2692 }
4bbe8033
AB
2693 /*
2694 * If priv lvls differ that means we're accessing csr from higher priv lvl,
2695 * so allow the access
2696 */
2697 if (env->priv != csr_priv) {
2698 return false;
2699 }
2700 switch (env->priv) {
2701 case PRV_M:
2702 pm_current = get_field(env->mmte, M_PM_CURRENT);
2703 break;
2704 case PRV_S:
2705 pm_current = get_field(env->mmte, S_PM_CURRENT);
2706 break;
2707 case PRV_U:
2708 pm_current = get_field(env->mmte, U_PM_CURRENT);
2709 break;
2710 default:
2711 g_assert_not_reached();
2712 }
2713 /* It's same priv lvl, so we allow to modify csr only if pm.current==1 */
2714 return !pm_current;
2715}
2716
2717static RISCVException read_mmte(CPURISCVState *env, int csrno,
2718 target_ulong *val)
2719{
2720 *val = env->mmte & MMTE_MASK;
2721 return RISCV_EXCP_NONE;
2722}
2723
2724static RISCVException write_mmte(CPURISCVState *env, int csrno,
2725 target_ulong val)
2726{
2727 uint64_t mstatus;
2728 target_ulong wpri_val = val & MMTE_MASK;
2729
2730 if (val != wpri_val) {
2731 qemu_log_mask(LOG_GUEST_ERROR, "%s" TARGET_FMT_lx " %s" TARGET_FMT_lx "\n",
2732 "MMTE: WPRI violation written 0x", val,
2733 "vs expected 0x", wpri_val);
2734 }
2735 /* for machine mode pm.current is hardwired to 1 */
2736 wpri_val |= MMTE_M_PM_CURRENT;
2737
2738 /* hardwiring pm.instruction bit to 0, since it's not supported yet */
2739 wpri_val &= ~(MMTE_M_PM_INSN | MMTE_S_PM_INSN | MMTE_U_PM_INSN);
2740 env->mmte = wpri_val | PM_EXT_DIRTY;
40bfa5f6 2741 riscv_cpu_update_mask(env);
4bbe8033
AB
2742
2743 /* Set XS and SD bits, since PM CSRs are dirty */
2744 mstatus = env->mstatus | MSTATUS_XS;
2745 write_mstatus(env, csrno, mstatus);
2746 return RISCV_EXCP_NONE;
2747}
2748
2749static RISCVException read_smte(CPURISCVState *env, int csrno,
2750 target_ulong *val)
2751{
2752 *val = env->mmte & SMTE_MASK;
2753 return RISCV_EXCP_NONE;
2754}
2755
2756static RISCVException write_smte(CPURISCVState *env, int csrno,
2757 target_ulong val)
2758{
2759 target_ulong wpri_val = val & SMTE_MASK;
2760
2761 if (val != wpri_val) {
2762 qemu_log_mask(LOG_GUEST_ERROR, "%s" TARGET_FMT_lx " %s" TARGET_FMT_lx "\n",
2763 "SMTE: WPRI violation written 0x", val,
2764 "vs expected 0x", wpri_val);
2765 }
2766
2767 /* if pm.current==0 we can't modify current PM CSRs */
2768 if (check_pm_current_disabled(env, csrno)) {
2769 return RISCV_EXCP_NONE;
2770 }
2771
2772 wpri_val |= (env->mmte & ~SMTE_MASK);
2773 write_mmte(env, csrno, wpri_val);
2774 return RISCV_EXCP_NONE;
2775}
2776
2777static RISCVException read_umte(CPURISCVState *env, int csrno,
2778 target_ulong *val)
2779{
2780 *val = env->mmte & UMTE_MASK;
2781 return RISCV_EXCP_NONE;
2782}
2783
2784static RISCVException write_umte(CPURISCVState *env, int csrno,
2785 target_ulong val)
2786{
2787 target_ulong wpri_val = val & UMTE_MASK;
2788
2789 if (val != wpri_val) {
2790 qemu_log_mask(LOG_GUEST_ERROR, "%s" TARGET_FMT_lx " %s" TARGET_FMT_lx "\n",
2791 "UMTE: WPRI violation written 0x", val,
2792 "vs expected 0x", wpri_val);
2793 }
2794
2795 if (check_pm_current_disabled(env, csrno)) {
2796 return RISCV_EXCP_NONE;
2797 }
2798
2799 wpri_val |= (env->mmte & ~UMTE_MASK);
2800 write_mmte(env, csrno, wpri_val);
2801 return RISCV_EXCP_NONE;
2802}
2803
2804static RISCVException read_mpmmask(CPURISCVState *env, int csrno,
2805 target_ulong *val)
2806{
2807 *val = env->mpmmask;
2808 return RISCV_EXCP_NONE;
2809}
2810
2811static RISCVException write_mpmmask(CPURISCVState *env, int csrno,
2812 target_ulong val)
2813{
2814 uint64_t mstatus;
2815
2816 env->mpmmask = val;
40bfa5f6
LZ
2817 if ((env->priv == PRV_M) && (env->mmte & M_PM_ENABLE)) {
2818 env->cur_pmmask = val;
2819 }
4bbe8033
AB
2820 env->mmte |= PM_EXT_DIRTY;
2821
2822 /* Set XS and SD bits, since PM CSRs are dirty */
2823 mstatus = env->mstatus | MSTATUS_XS;
2824 write_mstatus(env, csrno, mstatus);
2825 return RISCV_EXCP_NONE;
2826}
2827
2828static RISCVException read_spmmask(CPURISCVState *env, int csrno,
2829 target_ulong *val)
2830{
2831 *val = env->spmmask;
2832 return RISCV_EXCP_NONE;
2833}
2834
2835static RISCVException write_spmmask(CPURISCVState *env, int csrno,
2836 target_ulong val)
2837{
2838 uint64_t mstatus;
2839
2840 /* if pm.current==0 we can't modify current PM CSRs */
2841 if (check_pm_current_disabled(env, csrno)) {
2842 return RISCV_EXCP_NONE;
2843 }
2844 env->spmmask = val;
40bfa5f6
LZ
2845 if ((env->priv == PRV_S) && (env->mmte & S_PM_ENABLE)) {
2846 env->cur_pmmask = val;
2847 }
4bbe8033
AB
2848 env->mmte |= PM_EXT_DIRTY;
2849
2850 /* Set XS and SD bits, since PM CSRs are dirty */
2851 mstatus = env->mstatus | MSTATUS_XS;
2852 write_mstatus(env, csrno, mstatus);
2853 return RISCV_EXCP_NONE;
2854}
2855
2856static RISCVException read_upmmask(CPURISCVState *env, int csrno,
2857 target_ulong *val)
2858{
2859 *val = env->upmmask;
2860 return RISCV_EXCP_NONE;
2861}
2862
2863static RISCVException write_upmmask(CPURISCVState *env, int csrno,
2864 target_ulong val)
2865{
2866 uint64_t mstatus;
2867
2868 /* if pm.current==0 we can't modify current PM CSRs */
2869 if (check_pm_current_disabled(env, csrno)) {
2870 return RISCV_EXCP_NONE;
2871 }
2872 env->upmmask = val;
40bfa5f6
LZ
2873 if ((env->priv == PRV_U) && (env->mmte & U_PM_ENABLE)) {
2874 env->cur_pmmask = val;
2875 }
4bbe8033
AB
2876 env->mmte |= PM_EXT_DIRTY;
2877
2878 /* Set XS and SD bits, since PM CSRs are dirty */
2879 mstatus = env->mstatus | MSTATUS_XS;
2880 write_mstatus(env, csrno, mstatus);
2881 return RISCV_EXCP_NONE;
2882}
2883
2884static RISCVException read_mpmbase(CPURISCVState *env, int csrno,
2885 target_ulong *val)
2886{
2887 *val = env->mpmbase;
2888 return RISCV_EXCP_NONE;
2889}
2890
2891static RISCVException write_mpmbase(CPURISCVState *env, int csrno,
2892 target_ulong val)
2893{
2894 uint64_t mstatus;
2895
2896 env->mpmbase = val;
40bfa5f6
LZ
2897 if ((env->priv == PRV_M) && (env->mmte & M_PM_ENABLE)) {
2898 env->cur_pmbase = val;
2899 }
4bbe8033
AB
2900 env->mmte |= PM_EXT_DIRTY;
2901
2902 /* Set XS and SD bits, since PM CSRs are dirty */
2903 mstatus = env->mstatus | MSTATUS_XS;
2904 write_mstatus(env, csrno, mstatus);
2905 return RISCV_EXCP_NONE;
2906}
2907
2908static RISCVException read_spmbase(CPURISCVState *env, int csrno,
2909 target_ulong *val)
2910{
2911 *val = env->spmbase;
2912 return RISCV_EXCP_NONE;
2913}
2914
2915static RISCVException write_spmbase(CPURISCVState *env, int csrno,
2916 target_ulong val)
2917{
2918 uint64_t mstatus;
2919
2920 /* if pm.current==0 we can't modify current PM CSRs */
2921 if (check_pm_current_disabled(env, csrno)) {
2922 return RISCV_EXCP_NONE;
2923 }
2924 env->spmbase = val;
40bfa5f6
LZ
2925 if ((env->priv == PRV_S) && (env->mmte & S_PM_ENABLE)) {
2926 env->cur_pmbase = val;
2927 }
4bbe8033
AB
2928 env->mmte |= PM_EXT_DIRTY;
2929
2930 /* Set XS and SD bits, since PM CSRs are dirty */
2931 mstatus = env->mstatus | MSTATUS_XS;
2932 write_mstatus(env, csrno, mstatus);
2933 return RISCV_EXCP_NONE;
2934}
2935
2936static RISCVException read_upmbase(CPURISCVState *env, int csrno,
2937 target_ulong *val)
2938{
2939 *val = env->upmbase;
2940 return RISCV_EXCP_NONE;
2941}
2942
2943static RISCVException write_upmbase(CPURISCVState *env, int csrno,
2944 target_ulong val)
2945{
2946 uint64_t mstatus;
2947
2948 /* if pm.current==0 we can't modify current PM CSRs */
2949 if (check_pm_current_disabled(env, csrno)) {
2950 return RISCV_EXCP_NONE;
2951 }
2952 env->upmbase = val;
40bfa5f6
LZ
2953 if ((env->priv == PRV_U) && (env->mmte & U_PM_ENABLE)) {
2954 env->cur_pmbase = val;
2955 }
4bbe8033
AB
2956 env->mmte |= PM_EXT_DIRTY;
2957
2958 /* Set XS and SD bits, since PM CSRs are dirty */
2959 mstatus = env->mstatus | MSTATUS_XS;
2960 write_mstatus(env, csrno, mstatus);
2961 return RISCV_EXCP_NONE;
2962}
2963
c7b95171
MC
2964#endif
2965
2966/*
2967 * riscv_csrrw - read and/or update control and status register
2968 *
2969 * csrr <-> riscv_csrrw(env, csrno, ret_value, 0, 0);
2970 * csrrw <-> riscv_csrrw(env, csrno, ret_value, value, -1);
2971 * csrrs <-> riscv_csrrw(env, csrno, ret_value, -1, value);
2972 * csrrc <-> riscv_csrrw(env, csrno, ret_value, 0, value);
2973 */
2974
457c360f
FP
2975static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
2976 int csrno,
2977 bool write_mask,
2978 RISCVCPU *cpu)
c7b95171 2979{
65e728a2 2980 /* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */
457c360f 2981 int read_only = get_field(csrno, 0xC00) == 3;
7100fe6c 2982 int csr_min_priv = csr_ops[csrno].min_priv_ver;
c7b95171 2983#if !defined(CONFIG_USER_ONLY)
0a42f4c4 2984 int effective_priv = env->priv;
0a42f4c4
AF
2985
2986 if (riscv_has_ext(env, RVH) &&
2987 env->priv == PRV_S &&
2988 !riscv_cpu_virt_enabled(env)) {
2989 /*
2990 * We are in S mode without virtualisation, therefore we are in HS Mode.
2991 * Add 1 to the effective privledge level to allow us to access the
2992 * Hypervisor CSRs.
2993 */
2994 effective_priv++;
e6e03dcf 2995 }
0a42f4c4 2996
42109837 2997 if (!env->debugger && (effective_priv < get_field(csrno, 0x300))) {
533c91e8 2998 return RISCV_EXCP_ILLEGAL_INST;
c7b95171
MC
2999 }
3000#endif
42109837
LZ
3001 if (write_mask && read_only) {
3002 return RISCV_EXCP_ILLEGAL_INST;
3003 }
c7b95171 3004
591bddea
PD
3005 /* ensure the CSR extension is enabled. */
3006 if (!cpu->cfg.ext_icsr) {
533c91e8 3007 return RISCV_EXCP_ILLEGAL_INST;
591bddea
PD
3008 }
3009
a88365c1 3010 /* check predicate */
e39a8320 3011 if (!csr_ops[csrno].predicate) {
533c91e8 3012 return RISCV_EXCP_ILLEGAL_INST;
a88365c1 3013 }
457c360f 3014
7100fe6c
AP
3015 if (env->priv_ver < csr_min_priv) {
3016 return RISCV_EXCP_ILLEGAL_INST;
3017 }
3018
457c360f
FP
3019 return csr_ops[csrno].predicate(env, csrno);
3020}
3021
3022static RISCVException riscv_csrrw_do64(CPURISCVState *env, int csrno,
3023 target_ulong *ret_value,
3024 target_ulong new_value,
3025 target_ulong write_mask)
3026{
3027 RISCVException ret;
3028 target_ulong old_value;
a88365c1 3029
c7b95171
MC
3030 /* execute combined read/write operation if it exists */
3031 if (csr_ops[csrno].op) {
533c91e8 3032 return csr_ops[csrno].op(env, csrno, ret_value, new_value, write_mask);
c7b95171
MC
3033 }
3034
3035 /* if no accessor exists then return failure */
3036 if (!csr_ops[csrno].read) {
533c91e8 3037 return RISCV_EXCP_ILLEGAL_INST;
c7b95171 3038 }
c7b95171
MC
3039 /* read old value */
3040 ret = csr_ops[csrno].read(env, csrno, &old_value);
605def6e 3041 if (ret != RISCV_EXCP_NONE) {
533c91e8 3042 return ret;
c7b95171
MC
3043 }
3044
3045 /* write value if writable and write mask set, otherwise drop writes */
3046 if (write_mask) {
3047 new_value = (old_value & ~write_mask) | (new_value & write_mask);
3048 if (csr_ops[csrno].write) {
3049 ret = csr_ops[csrno].write(env, csrno, new_value);
605def6e 3050 if (ret != RISCV_EXCP_NONE) {
533c91e8 3051 return ret;
c7b95171
MC
3052 }
3053 }
3054 }
3055
3056 /* return old value */
3057 if (ret_value) {
3058 *ret_value = old_value;
3059 }
3060
533c91e8 3061 return RISCV_EXCP_NONE;
c7b95171
MC
3062}
3063
457c360f
FP
3064RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
3065 target_ulong *ret_value,
3066 target_ulong new_value, target_ulong write_mask)
3067{
3068 RISCVCPU *cpu = env_archcpu(env);
3069
3070 RISCVException ret = riscv_csrrw_check(env, csrno, write_mask, cpu);
3071 if (ret != RISCV_EXCP_NONE) {
3072 return ret;
3073 }
3074
3075 return riscv_csrrw_do64(env, csrno, ret_value, new_value, write_mask);
3076}
3077
3078static RISCVException riscv_csrrw_do128(CPURISCVState *env, int csrno,
3079 Int128 *ret_value,
3080 Int128 new_value,
3081 Int128 write_mask)
961738ff 3082{
457c360f
FP
3083 RISCVException ret;
3084 Int128 old_value;
3085
3086 /* read old value */
3087 ret = csr_ops[csrno].read128(env, csrno, &old_value);
3088 if (ret != RISCV_EXCP_NONE) {
3089 return ret;
3090 }
3091
3092 /* write value if writable and write mask set, otherwise drop writes */
3093 if (int128_nz(write_mask)) {
3094 new_value = int128_or(int128_and(old_value, int128_not(write_mask)),
3095 int128_and(new_value, write_mask));
3096 if (csr_ops[csrno].write128) {
3097 ret = csr_ops[csrno].write128(env, csrno, new_value);
3098 if (ret != RISCV_EXCP_NONE) {
3099 return ret;
3100 }
3101 } else if (csr_ops[csrno].write) {
3102 /* avoids having to write wrappers for all registers */
3103 ret = csr_ops[csrno].write(env, csrno, int128_getlo(new_value));
3104 if (ret != RISCV_EXCP_NONE) {
3105 return ret;
3106 }
3107 }
3108 }
961738ff 3109
457c360f 3110 /* return old value */
961738ff 3111 if (ret_value) {
457c360f
FP
3112 *ret_value = old_value;
3113 }
3114
3115 return RISCV_EXCP_NONE;
3116}
3117
3118RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
3119 Int128 *ret_value,
3120 Int128 new_value, Int128 write_mask)
3121{
3122 RISCVException ret;
3123 RISCVCPU *cpu = env_archcpu(env);
3124
3125 ret = riscv_csrrw_check(env, csrno, int128_nz(write_mask), cpu);
3126 if (ret != RISCV_EXCP_NONE) {
3127 return ret;
961738ff
FP
3128 }
3129
457c360f
FP
3130 if (csr_ops[csrno].read128) {
3131 return riscv_csrrw_do128(env, csrno, ret_value, new_value, write_mask);
3132 }
3133
3134 /*
3135 * Fall back to 64-bit version for now, if the 128-bit alternative isn't
3136 * at all defined.
3137 * Note, some CSRs don't need to extend to MXLEN (64 upper bits non
3138 * significant), for those, this fallback is correctly handling the accesses
3139 */
3140 target_ulong old_value;
3141 ret = riscv_csrrw_do64(env, csrno, &old_value,
3142 int128_getlo(new_value),
3143 int128_getlo(write_mask));
3144 if (ret == RISCV_EXCP_NONE && ret_value) {
3145 *ret_value = int128_make64(old_value);
3146 }
961738ff
FP
3147 return ret;
3148}
3149
753e3fe2
JW
3150/*
3151 * Debugger support. If not in user mode, set env->debugger before the
3152 * riscv_csrrw call and clear it after the call.
3153 */
533c91e8
AF
3154RISCVException riscv_csrrw_debug(CPURISCVState *env, int csrno,
3155 target_ulong *ret_value,
3156 target_ulong new_value,
3157 target_ulong write_mask)
753e3fe2 3158{
533c91e8 3159 RISCVException ret;
753e3fe2
JW
3160#if !defined(CONFIG_USER_ONLY)
3161 env->debugger = true;
3162#endif
3163 ret = riscv_csrrw(env, csrno, ret_value, new_value, write_mask);
3164#if !defined(CONFIG_USER_ONLY)
3165 env->debugger = false;
3166#endif
3167 return ret;
3168}
3169
c7b95171 3170/* Control and Status Register function table */
56118ee8 3171riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
c7b95171 3172 /* User Floating-Point CSRs */
8ceac5dc
BM
3173 [CSR_FFLAGS] = { "fflags", fs, read_fflags, write_fflags },
3174 [CSR_FRM] = { "frm", fs, read_frm, write_frm },
3175 [CSR_FCSR] = { "fcsr", fs, read_fcsr, write_fcsr },
8e3a1f18 3176 /* Vector CSRs */
a4b2fa43
AP
3177 [CSR_VSTART] = { "vstart", vs, read_vstart, write_vstart,
3178 .min_priv_ver = PRIV_VERSION_1_12_0 },
3179 [CSR_VXSAT] = { "vxsat", vs, read_vxsat, write_vxsat,
3180 .min_priv_ver = PRIV_VERSION_1_12_0 },
3181 [CSR_VXRM] = { "vxrm", vs, read_vxrm, write_vxrm,
3182 .min_priv_ver = PRIV_VERSION_1_12_0 },
3183 [CSR_VCSR] = { "vcsr", vs, read_vcsr, write_vcsr,
3184 .min_priv_ver = PRIV_VERSION_1_12_0 },
3185 [CSR_VL] = { "vl", vs, read_vl,
3186 .min_priv_ver = PRIV_VERSION_1_12_0 },
3187 [CSR_VTYPE] = { "vtype", vs, read_vtype,
3188 .min_priv_ver = PRIV_VERSION_1_12_0 },
3189 [CSR_VLENB] = { "vlenb", vs, read_vlenb,
3190 .min_priv_ver = PRIV_VERSION_1_12_0 },
c7b95171 3191 /* User Timers and Counters */
8ceac5dc
BM
3192 [CSR_CYCLE] = { "cycle", ctr, read_instret },
3193 [CSR_INSTRET] = { "instret", ctr, read_instret },
3194 [CSR_CYCLEH] = { "cycleh", ctr32, read_instreth },
3195 [CSR_INSTRETH] = { "instreth", ctr32, read_instreth },
3196
3197 /*
3198 * In privileged mode, the monitor will have to emulate TIME CSRs only if
3199 * rdtime callback is not provided by machine/platform emulation.
3200 */
3201 [CSR_TIME] = { "time", ctr, read_time },
3202 [CSR_TIMEH] = { "timeh", ctr32, read_timeh },
c7b95171
MC
3203
3204#if !defined(CONFIG_USER_ONLY)
3205 /* Machine Timers and Counters */
8ceac5dc
BM
3206 [CSR_MCYCLE] = { "mcycle", any, read_instret },
3207 [CSR_MINSTRET] = { "minstret", any, read_instret },
3208 [CSR_MCYCLEH] = { "mcycleh", any32, read_instreth },
3209 [CSR_MINSTRETH] = { "minstreth", any32, read_instreth },
c7b95171
MC
3210
3211 /* Machine Information Registers */
8ceac5dc
BM
3212 [CSR_MVENDORID] = { "mvendorid", any, read_zero },
3213 [CSR_MARCHID] = { "marchid", any, read_zero },
3214 [CSR_MIMPID] = { "mimpid", any, read_zero },
3215 [CSR_MHARTID] = { "mhartid", any, read_mhartid },
c7b95171 3216
3e6a417c
AP
3217 [CSR_MCONFIGPTR] = { "mconfigptr", any, read_zero,
3218 .min_priv_ver = PRIV_VERSION_1_12_0 },
c7b95171 3219 /* Machine Trap Setup */
457c360f
FP
3220 [CSR_MSTATUS] = { "mstatus", any, read_mstatus, write_mstatus, NULL,
3221 read_mstatus_i128 },
3222 [CSR_MISA] = { "misa", any, read_misa, write_misa, NULL,
3223 read_misa_i128 },
d028ac75 3224 [CSR_MIDELEG] = { "mideleg", any, NULL, NULL, rmw_mideleg },
8ceac5dc 3225 [CSR_MEDELEG] = { "medeleg", any, read_medeleg, write_medeleg },
d028ac75 3226 [CSR_MIE] = { "mie", any, NULL, NULL, rmw_mie },
8ceac5dc
BM
3227 [CSR_MTVEC] = { "mtvec", any, read_mtvec, write_mtvec },
3228 [CSR_MCOUNTEREN] = { "mcounteren", any, read_mcounteren, write_mcounteren },
c7b95171 3229
8ceac5dc 3230 [CSR_MSTATUSH] = { "mstatush", any32, read_mstatush, write_mstatush },
551fa7e8 3231
c7b95171 3232 /* Machine Trap Handling */
457c360f
FP
3233 [CSR_MSCRATCH] = { "mscratch", any, read_mscratch, write_mscratch, NULL,
3234 read_mscratch_i128, write_mscratch_i128 },
8ceac5dc
BM
3235 [CSR_MEPC] = { "mepc", any, read_mepc, write_mepc },
3236 [CSR_MCAUSE] = { "mcause", any, read_mcause, write_mcause },
ac12b601 3237 [CSR_MTVAL] = { "mtval", any, read_mtval, write_mtval },
8ceac5dc 3238 [CSR_MIP] = { "mip", any, NULL, NULL, rmw_mip },
c7b95171 3239
d1ceff40
AP
3240 /* Machine-Level Window to Indirectly Accessed Registers (AIA) */
3241 [CSR_MISELECT] = { "miselect", aia_any, NULL, NULL, rmw_xiselect },
3242 [CSR_MIREG] = { "mireg", aia_any, NULL, NULL, rmw_xireg },
3243
c7de92b4
AP
3244 /* Machine-Level Interrupts (AIA) */
3245 [CSR_MTOPI] = { "mtopi", aia_any, read_mtopi },
3246
ac4b0302
AP
3247 /* Machine-Level IMSIC Interface (AIA) */
3248 [CSR_MSETEIPNUM] = { "mseteipnum", aia_any, NULL, NULL, rmw_xsetclreinum },
3249 [CSR_MCLREIPNUM] = { "mclreipnum", aia_any, NULL, NULL, rmw_xsetclreinum },
3250 [CSR_MSETEIENUM] = { "mseteienum", aia_any, NULL, NULL, rmw_xsetclreinum },
3251 [CSR_MCLREIENUM] = { "mclreienum", aia_any, NULL, NULL, rmw_xsetclreinum },
3252 [CSR_MTOPEI] = { "mtopei", aia_any, NULL, NULL, rmw_xtopei },
3253
d0237b4d
AP
3254 /* Virtual Interrupts for Supervisor Level (AIA) */
3255 [CSR_MVIEN] = { "mvien", aia_any, read_zero, write_ignore },
3256 [CSR_MVIP] = { "mvip", aia_any, read_zero, write_ignore },
3257
d028ac75
AP
3258 /* Machine-Level High-Half CSRs (AIA) */
3259 [CSR_MIDELEGH] = { "midelegh", aia_any32, NULL, NULL, rmw_midelegh },
3260 [CSR_MIEH] = { "mieh", aia_any32, NULL, NULL, rmw_mieh },
d0237b4d
AP
3261 [CSR_MVIENH] = { "mvienh", aia_any32, read_zero, write_ignore },
3262 [CSR_MVIPH] = { "mviph", aia_any32, read_zero, write_ignore },
d028ac75
AP
3263 [CSR_MIPH] = { "miph", aia_any32, NULL, NULL, rmw_miph },
3264
29a9ec9b
AP
3265 /* Execution environment configuration */
3266 [CSR_MENVCFG] = { "menvcfg", any, read_menvcfg, write_menvcfg,
3267 .min_priv_ver = PRIV_VERSION_1_12_0 },
3268 [CSR_MENVCFGH] = { "menvcfgh", any32, read_menvcfgh, write_menvcfgh,
3269 .min_priv_ver = PRIV_VERSION_1_12_0 },
3270 [CSR_SENVCFG] = { "senvcfg", smode, read_senvcfg, write_senvcfg,
3271 .min_priv_ver = PRIV_VERSION_1_12_0 },
3272 [CSR_HENVCFG] = { "henvcfg", hmode, read_henvcfg, write_henvcfg,
3273 .min_priv_ver = PRIV_VERSION_1_12_0 },
3274 [CSR_HENVCFGH] = { "henvcfgh", hmode32, read_henvcfgh, write_henvcfgh,
3275 .min_priv_ver = PRIV_VERSION_1_12_0 },
3276
c7b95171 3277 /* Supervisor Trap Setup */
457c360f
FP
3278 [CSR_SSTATUS] = { "sstatus", smode, read_sstatus, write_sstatus, NULL,
3279 read_sstatus_i128 },
d028ac75 3280 [CSR_SIE] = { "sie", smode, NULL, NULL, rmw_sie },
8ceac5dc
BM
3281 [CSR_STVEC] = { "stvec", smode, read_stvec, write_stvec },
3282 [CSR_SCOUNTEREN] = { "scounteren", smode, read_scounteren, write_scounteren },
c7b95171
MC
3283
3284 /* Supervisor Trap Handling */
457c360f
FP
3285 [CSR_SSCRATCH] = { "sscratch", smode, read_sscratch, write_sscratch, NULL,
3286 read_sscratch_i128, write_sscratch_i128 },
8ceac5dc
BM
3287 [CSR_SEPC] = { "sepc", smode, read_sepc, write_sepc },
3288 [CSR_SCAUSE] = { "scause", smode, read_scause, write_scause },
ac12b601 3289 [CSR_STVAL] = { "stval", smode, read_stval, write_stval },
8ceac5dc 3290 [CSR_SIP] = { "sip", smode, NULL, NULL, rmw_sip },
c7b95171
MC
3291
3292 /* Supervisor Protection and Translation */
8ceac5dc
BM
3293 [CSR_SATP] = { "satp", smode, read_satp, write_satp },
3294
d1ceff40
AP
3295 /* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */
3296 [CSR_SISELECT] = { "siselect", aia_smode, NULL, NULL, rmw_xiselect },
3297 [CSR_SIREG] = { "sireg", aia_smode, NULL, NULL, rmw_xireg },
3298
c7de92b4
AP
3299 /* Supervisor-Level Interrupts (AIA) */
3300 [CSR_STOPI] = { "stopi", aia_smode, read_stopi },
3301
ac4b0302
AP
3302 /* Supervisor-Level IMSIC Interface (AIA) */
3303 [CSR_SSETEIPNUM] = { "sseteipnum", aia_smode, NULL, NULL, rmw_xsetclreinum },
3304 [CSR_SCLREIPNUM] = { "sclreipnum", aia_smode, NULL, NULL, rmw_xsetclreinum },
3305 [CSR_SSETEIENUM] = { "sseteienum", aia_smode, NULL, NULL, rmw_xsetclreinum },
3306 [CSR_SCLREIENUM] = { "sclreienum", aia_smode, NULL, NULL, rmw_xsetclreinum },
3307 [CSR_STOPEI] = { "stopei", aia_smode, NULL, NULL, rmw_xtopei },
3308
d028ac75
AP
3309 /* Supervisor-Level High-Half CSRs (AIA) */
3310 [CSR_SIEH] = { "sieh", aia_smode32, NULL, NULL, rmw_sieh },
3311 [CSR_SIPH] = { "siph", aia_smode32, NULL, NULL, rmw_siph },
3312
a4b2fa43
AP
3313 [CSR_HSTATUS] = { "hstatus", hmode, read_hstatus, write_hstatus,
3314 .min_priv_ver = PRIV_VERSION_1_12_0 },
3315 [CSR_HEDELEG] = { "hedeleg", hmode, read_hedeleg, write_hedeleg,
3316 .min_priv_ver = PRIV_VERSION_1_12_0 },
3317 [CSR_HIDELEG] = { "hideleg", hmode, NULL, NULL, rmw_hideleg,
3318 .min_priv_ver = PRIV_VERSION_1_12_0 },
3319 [CSR_HVIP] = { "hvip", hmode, NULL, NULL, rmw_hvip,
3320 .min_priv_ver = PRIV_VERSION_1_12_0 },
3321 [CSR_HIP] = { "hip", hmode, NULL, NULL, rmw_hip,
3322 .min_priv_ver = PRIV_VERSION_1_12_0 },
3323 [CSR_HIE] = { "hie", hmode, NULL, NULL, rmw_hie,
3324 .min_priv_ver = PRIV_VERSION_1_12_0 },
3325 [CSR_HCOUNTEREN] = { "hcounteren", hmode, read_hcounteren, write_hcounteren,
3326 .min_priv_ver = PRIV_VERSION_1_12_0 },
3327 [CSR_HGEIE] = { "hgeie", hmode, read_hgeie, write_hgeie,
3328 .min_priv_ver = PRIV_VERSION_1_12_0 },
3329 [CSR_HTVAL] = { "htval", hmode, read_htval, write_htval,
3330 .min_priv_ver = PRIV_VERSION_1_12_0 },
3331 [CSR_HTINST] = { "htinst", hmode, read_htinst, write_htinst,
3332 .min_priv_ver = PRIV_VERSION_1_12_0 },
3333 [CSR_HGEIP] = { "hgeip", hmode, read_hgeip,
3334 .min_priv_ver = PRIV_VERSION_1_12_0 },
3335 [CSR_HGATP] = { "hgatp", hmode, read_hgatp, write_hgatp,
3336 .min_priv_ver = PRIV_VERSION_1_12_0 },
3337 [CSR_HTIMEDELTA] = { "htimedelta", hmode, read_htimedelta, write_htimedelta,
3338 .min_priv_ver = PRIV_VERSION_1_12_0 },
3339 [CSR_HTIMEDELTAH] = { "htimedeltah", hmode32, read_htimedeltah, write_htimedeltah,
3340 .min_priv_ver = PRIV_VERSION_1_12_0 },
3341
3342 [CSR_VSSTATUS] = { "vsstatus", hmode, read_vsstatus, write_vsstatus,
3343 .min_priv_ver = PRIV_VERSION_1_12_0 },
3344 [CSR_VSIP] = { "vsip", hmode, NULL, NULL, rmw_vsip,
3345 .min_priv_ver = PRIV_VERSION_1_12_0 },
3346 [CSR_VSIE] = { "vsie", hmode, NULL, NULL, rmw_vsie ,
3347 .min_priv_ver = PRIV_VERSION_1_12_0 },
3348 [CSR_VSTVEC] = { "vstvec", hmode, read_vstvec, write_vstvec,
3349 .min_priv_ver = PRIV_VERSION_1_12_0 },
3350 [CSR_VSSCRATCH] = { "vsscratch", hmode, read_vsscratch, write_vsscratch,
3351 .min_priv_ver = PRIV_VERSION_1_12_0 },
3352 [CSR_VSEPC] = { "vsepc", hmode, read_vsepc, write_vsepc,
3353 .min_priv_ver = PRIV_VERSION_1_12_0 },
3354 [CSR_VSCAUSE] = { "vscause", hmode, read_vscause, write_vscause,
3355 .min_priv_ver = PRIV_VERSION_1_12_0 },
3356 [CSR_VSTVAL] = { "vstval", hmode, read_vstval, write_vstval,
3357 .min_priv_ver = PRIV_VERSION_1_12_0 },
3358 [CSR_VSATP] = { "vsatp", hmode, read_vsatp, write_vsatp,
3359 .min_priv_ver = PRIV_VERSION_1_12_0 },
3360
3361 [CSR_MTVAL2] = { "mtval2", hmode, read_mtval2, write_mtval2,
3362 .min_priv_ver = PRIV_VERSION_1_12_0 },
3363 [CSR_MTINST] = { "mtinst", hmode, read_mtinst, write_mtinst,
3364 .min_priv_ver = PRIV_VERSION_1_12_0 },
34cfb5f6 3365
2b602398 3366 /* Virtual Interrupts and Interrupt Priorities (H-extension with AIA) */
d0237b4d 3367 [CSR_HVIEN] = { "hvien", aia_hmode, read_zero, write_ignore },
2b602398
AP
3368 [CSR_HVICTL] = { "hvictl", aia_hmode, read_hvictl, write_hvictl },
3369 [CSR_HVIPRIO1] = { "hviprio1", aia_hmode, read_hviprio1, write_hviprio1 },
3370 [CSR_HVIPRIO2] = { "hviprio2", aia_hmode, read_hviprio2, write_hviprio2 },
3371
d1ceff40
AP
3372 /*
3373 * VS-Level Window to Indirectly Accessed Registers (H-extension with AIA)
3374 */
3375 [CSR_VSISELECT] = { "vsiselect", aia_hmode, NULL, NULL, rmw_xiselect },
3376 [CSR_VSIREG] = { "vsireg", aia_hmode, NULL, NULL, rmw_xireg },
3377
c7de92b4
AP
3378 /* VS-Level Interrupts (H-extension with AIA) */
3379 [CSR_VSTOPI] = { "vstopi", aia_hmode, read_vstopi },
3380
ac4b0302
AP
3381 /* VS-Level IMSIC Interface (H-extension with AIA) */
3382 [CSR_VSSETEIPNUM] = { "vsseteipnum", aia_hmode, NULL, NULL, rmw_xsetclreinum },
3383 [CSR_VSCLREIPNUM] = { "vsclreipnum", aia_hmode, NULL, NULL, rmw_xsetclreinum },
3384 [CSR_VSSETEIENUM] = { "vsseteienum", aia_hmode, NULL, NULL, rmw_xsetclreinum },
3385 [CSR_VSCLREIENUM] = { "vsclreienum", aia_hmode, NULL, NULL, rmw_xsetclreinum },
3386 [CSR_VSTOPEI] = { "vstopei", aia_hmode, NULL, NULL, rmw_xtopei },
3387
d028ac75
AP
3388 /* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */
3389 [CSR_HIDELEGH] = { "hidelegh", aia_hmode32, NULL, NULL, rmw_hidelegh },
d0237b4d 3390 [CSR_HVIENH] = { "hvienh", aia_hmode32, read_zero, write_ignore },
d028ac75 3391 [CSR_HVIPH] = { "hviph", aia_hmode32, NULL, NULL, rmw_hviph },
2b602398
AP
3392 [CSR_HVIPRIO1H] = { "hviprio1h", aia_hmode32, read_hviprio1h, write_hviprio1h },
3393 [CSR_HVIPRIO2H] = { "hviprio2h", aia_hmode32, read_hviprio2h, write_hviprio2h },
d028ac75
AP
3394 [CSR_VSIEH] = { "vsieh", aia_hmode32, NULL, NULL, rmw_vsieh },
3395 [CSR_VSIPH] = { "vsiph", aia_hmode32, NULL, NULL, rmw_vsiph },
3396
c7b95171 3397 /* Physical Memory Protection */
a4b2fa43
AP
3398 [CSR_MSECCFG] = { "mseccfg", epmp, read_mseccfg, write_mseccfg,
3399 .min_priv_ver = PRIV_VERSION_1_12_0 },
8ceac5dc
BM
3400 [CSR_PMPCFG0] = { "pmpcfg0", pmp, read_pmpcfg, write_pmpcfg },
3401 [CSR_PMPCFG1] = { "pmpcfg1", pmp, read_pmpcfg, write_pmpcfg },
3402 [CSR_PMPCFG2] = { "pmpcfg2", pmp, read_pmpcfg, write_pmpcfg },
3403 [CSR_PMPCFG3] = { "pmpcfg3", pmp, read_pmpcfg, write_pmpcfg },
3404 [CSR_PMPADDR0] = { "pmpaddr0", pmp, read_pmpaddr, write_pmpaddr },
3405 [CSR_PMPADDR1] = { "pmpaddr1", pmp, read_pmpaddr, write_pmpaddr },
3406 [CSR_PMPADDR2] = { "pmpaddr2", pmp, read_pmpaddr, write_pmpaddr },
3407 [CSR_PMPADDR3] = { "pmpaddr3", pmp, read_pmpaddr, write_pmpaddr },
3408 [CSR_PMPADDR4] = { "pmpaddr4", pmp, read_pmpaddr, write_pmpaddr },
3409 [CSR_PMPADDR5] = { "pmpaddr5", pmp, read_pmpaddr, write_pmpaddr },
3410 [CSR_PMPADDR6] = { "pmpaddr6", pmp, read_pmpaddr, write_pmpaddr },
3411 [CSR_PMPADDR7] = { "pmpaddr7", pmp, read_pmpaddr, write_pmpaddr },
3412 [CSR_PMPADDR8] = { "pmpaddr8", pmp, read_pmpaddr, write_pmpaddr },
3413 [CSR_PMPADDR9] = { "pmpaddr9", pmp, read_pmpaddr, write_pmpaddr },
3414 [CSR_PMPADDR10] = { "pmpaddr10", pmp, read_pmpaddr, write_pmpaddr },
3415 [CSR_PMPADDR11] = { "pmpaddr11", pmp, read_pmpaddr, write_pmpaddr },
3416 [CSR_PMPADDR12] = { "pmpaddr12", pmp, read_pmpaddr, write_pmpaddr },
3417 [CSR_PMPADDR13] = { "pmpaddr13", pmp, read_pmpaddr, write_pmpaddr },
3418 [CSR_PMPADDR14] = { "pmpaddr14", pmp, read_pmpaddr, write_pmpaddr },
3419 [CSR_PMPADDR15] = { "pmpaddr15", pmp, read_pmpaddr, write_pmpaddr },
c7b95171 3420
4bbe8033
AB
3421 /* User Pointer Masking */
3422 [CSR_UMTE] = { "umte", pointer_masking, read_umte, write_umte },
3423 [CSR_UPMMASK] = { "upmmask", pointer_masking, read_upmmask, write_upmmask },
3424 [CSR_UPMBASE] = { "upmbase", pointer_masking, read_upmbase, write_upmbase },
3425 /* Machine Pointer Masking */
3426 [CSR_MMTE] = { "mmte", pointer_masking, read_mmte, write_mmte },
3427 [CSR_MPMMASK] = { "mpmmask", pointer_masking, read_mpmmask, write_mpmmask },
3428 [CSR_MPMBASE] = { "mpmbase", pointer_masking, read_mpmbase, write_mpmbase },
3429 /* Supervisor Pointer Masking */
3430 [CSR_SMTE] = { "smte", pointer_masking, read_smte, write_smte },
3431 [CSR_SPMMASK] = { "spmmask", pointer_masking, read_spmmask, write_spmmask },
3432 [CSR_SPMBASE] = { "spmbase", pointer_masking, read_spmbase, write_spmbase },
3433
c7b95171 3434 /* Performance Counters */
8ceac5dc
BM
3435 [CSR_HPMCOUNTER3] = { "hpmcounter3", ctr, read_zero },
3436 [CSR_HPMCOUNTER4] = { "hpmcounter4", ctr, read_zero },
3437 [CSR_HPMCOUNTER5] = { "hpmcounter5", ctr, read_zero },
3438 [CSR_HPMCOUNTER6] = { "hpmcounter6", ctr, read_zero },
3439 [CSR_HPMCOUNTER7] = { "hpmcounter7", ctr, read_zero },
3440 [CSR_HPMCOUNTER8] = { "hpmcounter8", ctr, read_zero },
3441 [CSR_HPMCOUNTER9] = { "hpmcounter9", ctr, read_zero },
3442 [CSR_HPMCOUNTER10] = { "hpmcounter10", ctr, read_zero },
3443 [CSR_HPMCOUNTER11] = { "hpmcounter11", ctr, read_zero },
3444 [CSR_HPMCOUNTER12] = { "hpmcounter12", ctr, read_zero },
3445 [CSR_HPMCOUNTER13] = { "hpmcounter13", ctr, read_zero },
3446 [CSR_HPMCOUNTER14] = { "hpmcounter14", ctr, read_zero },
3447 [CSR_HPMCOUNTER15] = { "hpmcounter15", ctr, read_zero },
3448 [CSR_HPMCOUNTER16] = { "hpmcounter16", ctr, read_zero },
3449 [CSR_HPMCOUNTER17] = { "hpmcounter17", ctr, read_zero },
3450 [CSR_HPMCOUNTER18] = { "hpmcounter18", ctr, read_zero },
3451 [CSR_HPMCOUNTER19] = { "hpmcounter19", ctr, read_zero },
3452 [CSR_HPMCOUNTER20] = { "hpmcounter20", ctr, read_zero },
3453 [CSR_HPMCOUNTER21] = { "hpmcounter21", ctr, read_zero },
3454 [CSR_HPMCOUNTER22] = { "hpmcounter22", ctr, read_zero },
3455 [CSR_HPMCOUNTER23] = { "hpmcounter23", ctr, read_zero },
3456 [CSR_HPMCOUNTER24] = { "hpmcounter24", ctr, read_zero },
3457 [CSR_HPMCOUNTER25] = { "hpmcounter25", ctr, read_zero },
3458 [CSR_HPMCOUNTER26] = { "hpmcounter26", ctr, read_zero },
3459 [CSR_HPMCOUNTER27] = { "hpmcounter27", ctr, read_zero },
3460 [CSR_HPMCOUNTER28] = { "hpmcounter28", ctr, read_zero },
3461 [CSR_HPMCOUNTER29] = { "hpmcounter29", ctr, read_zero },
3462 [CSR_HPMCOUNTER30] = { "hpmcounter30", ctr, read_zero },
3463 [CSR_HPMCOUNTER31] = { "hpmcounter31", ctr, read_zero },
3464
3465 [CSR_MHPMCOUNTER3] = { "mhpmcounter3", any, read_zero },
3466 [CSR_MHPMCOUNTER4] = { "mhpmcounter4", any, read_zero },
3467 [CSR_MHPMCOUNTER5] = { "mhpmcounter5", any, read_zero },
3468 [CSR_MHPMCOUNTER6] = { "mhpmcounter6", any, read_zero },
3469 [CSR_MHPMCOUNTER7] = { "mhpmcounter7", any, read_zero },
3470 [CSR_MHPMCOUNTER8] = { "mhpmcounter8", any, read_zero },
3471 [CSR_MHPMCOUNTER9] = { "mhpmcounter9", any, read_zero },
3472 [CSR_MHPMCOUNTER10] = { "mhpmcounter10", any, read_zero },
3473 [CSR_MHPMCOUNTER11] = { "mhpmcounter11", any, read_zero },
3474 [CSR_MHPMCOUNTER12] = { "mhpmcounter12", any, read_zero },
3475 [CSR_MHPMCOUNTER13] = { "mhpmcounter13", any, read_zero },
3476 [CSR_MHPMCOUNTER14] = { "mhpmcounter14", any, read_zero },
3477 [CSR_MHPMCOUNTER15] = { "mhpmcounter15", any, read_zero },
3478 [CSR_MHPMCOUNTER16] = { "mhpmcounter16", any, read_zero },
3479 [CSR_MHPMCOUNTER17] = { "mhpmcounter17", any, read_zero },
3480 [CSR_MHPMCOUNTER18] = { "mhpmcounter18", any, read_zero },
3481 [CSR_MHPMCOUNTER19] = { "mhpmcounter19", any, read_zero },
3482 [CSR_MHPMCOUNTER20] = { "mhpmcounter20", any, read_zero },
3483 [CSR_MHPMCOUNTER21] = { "mhpmcounter21", any, read_zero },
3484 [CSR_MHPMCOUNTER22] = { "mhpmcounter22", any, read_zero },
3485 [CSR_MHPMCOUNTER23] = { "mhpmcounter23", any, read_zero },
3486 [CSR_MHPMCOUNTER24] = { "mhpmcounter24", any, read_zero },
3487 [CSR_MHPMCOUNTER25] = { "mhpmcounter25", any, read_zero },
3488 [CSR_MHPMCOUNTER26] = { "mhpmcounter26", any, read_zero },
3489 [CSR_MHPMCOUNTER27] = { "mhpmcounter27", any, read_zero },
3490 [CSR_MHPMCOUNTER28] = { "mhpmcounter28", any, read_zero },
3491 [CSR_MHPMCOUNTER29] = { "mhpmcounter29", any, read_zero },
3492 [CSR_MHPMCOUNTER30] = { "mhpmcounter30", any, read_zero },
3493 [CSR_MHPMCOUNTER31] = { "mhpmcounter31", any, read_zero },
3494
3495 [CSR_MHPMEVENT3] = { "mhpmevent3", any, read_zero },
3496 [CSR_MHPMEVENT4] = { "mhpmevent4", any, read_zero },
3497 [CSR_MHPMEVENT5] = { "mhpmevent5", any, read_zero },
3498 [CSR_MHPMEVENT6] = { "mhpmevent6", any, read_zero },
3499 [CSR_MHPMEVENT7] = { "mhpmevent7", any, read_zero },
3500 [CSR_MHPMEVENT8] = { "mhpmevent8", any, read_zero },
3501 [CSR_MHPMEVENT9] = { "mhpmevent9", any, read_zero },
3502 [CSR_MHPMEVENT10] = { "mhpmevent10", any, read_zero },
3503 [CSR_MHPMEVENT11] = { "mhpmevent11", any, read_zero },
3504 [CSR_MHPMEVENT12] = { "mhpmevent12", any, read_zero },
3505 [CSR_MHPMEVENT13] = { "mhpmevent13", any, read_zero },
3506 [CSR_MHPMEVENT14] = { "mhpmevent14", any, read_zero },
3507 [CSR_MHPMEVENT15] = { "mhpmevent15", any, read_zero },
3508 [CSR_MHPMEVENT16] = { "mhpmevent16", any, read_zero },
3509 [CSR_MHPMEVENT17] = { "mhpmevent17", any, read_zero },
3510 [CSR_MHPMEVENT18] = { "mhpmevent18", any, read_zero },
3511 [CSR_MHPMEVENT19] = { "mhpmevent19", any, read_zero },
3512 [CSR_MHPMEVENT20] = { "mhpmevent20", any, read_zero },
3513 [CSR_MHPMEVENT21] = { "mhpmevent21", any, read_zero },
3514 [CSR_MHPMEVENT22] = { "mhpmevent22", any, read_zero },
3515 [CSR_MHPMEVENT23] = { "mhpmevent23", any, read_zero },
3516 [CSR_MHPMEVENT24] = { "mhpmevent24", any, read_zero },
3517 [CSR_MHPMEVENT25] = { "mhpmevent25", any, read_zero },
3518 [CSR_MHPMEVENT26] = { "mhpmevent26", any, read_zero },
3519 [CSR_MHPMEVENT27] = { "mhpmevent27", any, read_zero },
3520 [CSR_MHPMEVENT28] = { "mhpmevent28", any, read_zero },
3521 [CSR_MHPMEVENT29] = { "mhpmevent29", any, read_zero },
3522 [CSR_MHPMEVENT30] = { "mhpmevent30", any, read_zero },
3523 [CSR_MHPMEVENT31] = { "mhpmevent31", any, read_zero },
3524
3525 [CSR_HPMCOUNTER3H] = { "hpmcounter3h", ctr32, read_zero },
3526 [CSR_HPMCOUNTER4H] = { "hpmcounter4h", ctr32, read_zero },
3527 [CSR_HPMCOUNTER5H] = { "hpmcounter5h", ctr32, read_zero },
3528 [CSR_HPMCOUNTER6H] = { "hpmcounter6h", ctr32, read_zero },
3529 [CSR_HPMCOUNTER7H] = { "hpmcounter7h", ctr32, read_zero },
3530 [CSR_HPMCOUNTER8H] = { "hpmcounter8h", ctr32, read_zero },
3531 [CSR_HPMCOUNTER9H] = { "hpmcounter9h", ctr32, read_zero },
3532 [CSR_HPMCOUNTER10H] = { "hpmcounter10h", ctr32, read_zero },
3533 [CSR_HPMCOUNTER11H] = { "hpmcounter11h", ctr32, read_zero },
3534 [CSR_HPMCOUNTER12H] = { "hpmcounter12h", ctr32, read_zero },
3535 [CSR_HPMCOUNTER13H] = { "hpmcounter13h", ctr32, read_zero },
3536 [CSR_HPMCOUNTER14H] = { "hpmcounter14h", ctr32, read_zero },
3537 [CSR_HPMCOUNTER15H] = { "hpmcounter15h", ctr32, read_zero },
3538 [CSR_HPMCOUNTER16H] = { "hpmcounter16h", ctr32, read_zero },
3539 [CSR_HPMCOUNTER17H] = { "hpmcounter17h", ctr32, read_zero },
3540 [CSR_HPMCOUNTER18H] = { "hpmcounter18h", ctr32, read_zero },
3541 [CSR_HPMCOUNTER19H] = { "hpmcounter19h", ctr32, read_zero },
3542 [CSR_HPMCOUNTER20H] = { "hpmcounter20h", ctr32, read_zero },
3543 [CSR_HPMCOUNTER21H] = { "hpmcounter21h", ctr32, read_zero },
3544 [CSR_HPMCOUNTER22H] = { "hpmcounter22h", ctr32, read_zero },
3545 [CSR_HPMCOUNTER23H] = { "hpmcounter23h", ctr32, read_zero },
3546 [CSR_HPMCOUNTER24H] = { "hpmcounter24h", ctr32, read_zero },
3547 [CSR_HPMCOUNTER25H] = { "hpmcounter25h", ctr32, read_zero },
3548 [CSR_HPMCOUNTER26H] = { "hpmcounter26h", ctr32, read_zero },
3549 [CSR_HPMCOUNTER27H] = { "hpmcounter27h", ctr32, read_zero },
3550 [CSR_HPMCOUNTER28H] = { "hpmcounter28h", ctr32, read_zero },
3551 [CSR_HPMCOUNTER29H] = { "hpmcounter29h", ctr32, read_zero },
3552 [CSR_HPMCOUNTER30H] = { "hpmcounter30h", ctr32, read_zero },
3553 [CSR_HPMCOUNTER31H] = { "hpmcounter31h", ctr32, read_zero },
3554
3555 [CSR_MHPMCOUNTER3H] = { "mhpmcounter3h", any32, read_zero },
3556 [CSR_MHPMCOUNTER4H] = { "mhpmcounter4h", any32, read_zero },
3557 [CSR_MHPMCOUNTER5H] = { "mhpmcounter5h", any32, read_zero },
3558 [CSR_MHPMCOUNTER6H] = { "mhpmcounter6h", any32, read_zero },
3559 [CSR_MHPMCOUNTER7H] = { "mhpmcounter7h", any32, read_zero },
3560 [CSR_MHPMCOUNTER8H] = { "mhpmcounter8h", any32, read_zero },
3561 [CSR_MHPMCOUNTER9H] = { "mhpmcounter9h", any32, read_zero },
3562 [CSR_MHPMCOUNTER10H] = { "mhpmcounter10h", any32, read_zero },
3563 [CSR_MHPMCOUNTER11H] = { "mhpmcounter11h", any32, read_zero },
3564 [CSR_MHPMCOUNTER12H] = { "mhpmcounter12h", any32, read_zero },
3565 [CSR_MHPMCOUNTER13H] = { "mhpmcounter13h", any32, read_zero },
3566 [CSR_MHPMCOUNTER14H] = { "mhpmcounter14h", any32, read_zero },
3567 [CSR_MHPMCOUNTER15H] = { "mhpmcounter15h", any32, read_zero },
3568 [CSR_MHPMCOUNTER16H] = { "mhpmcounter16h", any32, read_zero },
3569 [CSR_MHPMCOUNTER17H] = { "mhpmcounter17h", any32, read_zero },
3570 [CSR_MHPMCOUNTER18H] = { "mhpmcounter18h", any32, read_zero },
3571 [CSR_MHPMCOUNTER19H] = { "mhpmcounter19h", any32, read_zero },
3572 [CSR_MHPMCOUNTER20H] = { "mhpmcounter20h", any32, read_zero },
3573 [CSR_MHPMCOUNTER21H] = { "mhpmcounter21h", any32, read_zero },
3574 [CSR_MHPMCOUNTER22H] = { "mhpmcounter22h", any32, read_zero },
3575 [CSR_MHPMCOUNTER23H] = { "mhpmcounter23h", any32, read_zero },
3576 [CSR_MHPMCOUNTER24H] = { "mhpmcounter24h", any32, read_zero },
3577 [CSR_MHPMCOUNTER25H] = { "mhpmcounter25h", any32, read_zero },
3578 [CSR_MHPMCOUNTER26H] = { "mhpmcounter26h", any32, read_zero },
3579 [CSR_MHPMCOUNTER27H] = { "mhpmcounter27h", any32, read_zero },
3580 [CSR_MHPMCOUNTER28H] = { "mhpmcounter28h", any32, read_zero },
3581 [CSR_MHPMCOUNTER29H] = { "mhpmcounter29h", any32, read_zero },
3582 [CSR_MHPMCOUNTER30H] = { "mhpmcounter30h", any32, read_zero },
3583 [CSR_MHPMCOUNTER31H] = { "mhpmcounter31h", any32, read_zero },
c7b95171
MC
3584#endif /* !CONFIG_USER_ONLY */
3585};
This page took 0.682791 seconds and 4 git commands to generate.