1 /* 2 * RISC-V Control and Status Registers. 3 * 4 * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu 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" 22 #include "cpu.h" 23 #include "qemu/main-loop.h" 24 #include "exec/exec-all.h" 25 26 /* CSR function table */ 27 static riscv_csr_operations csr_ops[]; 28 29 /* CSR function table constants */ 30 enum { 31 CSR_TABLE_SIZE = 0x1000 32 }; 33 34 /* CSR function table public API */ 35 void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops) 36 { 37 *ops = csr_ops[csrno & (CSR_TABLE_SIZE - 1)]; 38 } 39 40 void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops) 41 { 42 csr_ops[csrno & (CSR_TABLE_SIZE - 1)] = *ops; 43 } 44 45 /* User Floating-Point CSRs */ 46 static int read_fflags(CPURISCVState *env, int csrno, target_ulong *val) 47 { 48 #if !defined(CONFIG_USER_ONLY) 49 if (!(env->mstatus & MSTATUS_FS)) { 50 return -1; 51 } 52 #endif 53 *val = cpu_riscv_get_fflags(env); 54 return 0; 55 } 56 57 static int write_fflags(CPURISCVState *env, int csrno, target_ulong val) 58 { 59 #if !defined(CONFIG_USER_ONLY) 60 if (!(env->mstatus & MSTATUS_FS)) { 61 return -1; 62 } 63 env->mstatus |= MSTATUS_FS; 64 #endif 65 cpu_riscv_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT)); 66 return 0; 67 } 68 69 static int read_frm(CPURISCVState *env, int csrno, target_ulong *val) 70 { 71 #if !defined(CONFIG_USER_ONLY) 72 if (!(env->mstatus & MSTATUS_FS)) { 73 return -1; 74 } 75 #endif 76 *val = env->frm; 77 return 0; 78 } 79 80 static int write_frm(CPURISCVState *env, int csrno, target_ulong val) 81 { 82 #if !defined(CONFIG_USER_ONLY) 83 if (!(env->mstatus & MSTATUS_FS)) { 84 return -1; 85 } 86 env->mstatus |= MSTATUS_FS; 87 #endif 88 env->frm = val & (FSR_RD >> FSR_RD_SHIFT); 89 return 0; 90 } 91 92 static int read_fcsr(CPURISCVState *env, int csrno, target_ulong *val) 93 { 94 #if !defined(CONFIG_USER_ONLY) 95 if (!(env->mstatus & MSTATUS_FS)) { 96 return -1; 97 } 98 #endif 99 *val = (cpu_riscv_get_fflags(env) << FSR_AEXC_SHIFT) 100 | (env->frm << FSR_RD_SHIFT); 101 return 0; 102 } 103 104 static int write_fcsr(CPURISCVState *env, int csrno, target_ulong val) 105 { 106 #if !defined(CONFIG_USER_ONLY) 107 if (!(env->mstatus & MSTATUS_FS)) { 108 return -1; 109 } 110 env->mstatus |= MSTATUS_FS; 111 #endif 112 env->frm = (val & FSR_RD) >> FSR_RD_SHIFT; 113 cpu_riscv_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT); 114 return 0; 115 } 116 117 /* User Timers and Counters */ 118 static int counter_enabled(CPURISCVState *env, int csrno) 119 { 120 #ifndef CONFIG_USER_ONLY 121 target_ulong ctr_en = env->priv == PRV_U ? env->scounteren : 122 env->priv == PRV_S ? env->mcounteren : -1U; 123 #else 124 target_ulong ctr_en = -1; 125 #endif 126 return (ctr_en >> (csrno & 31)) & 1; 127 } 128 129 #if !defined(CONFIG_USER_ONLY) 130 static int read_zero_counter(CPURISCVState *env, int csrno, target_ulong *val) 131 { 132 if (!counter_enabled(env, csrno)) { 133 return -1; 134 } 135 *val = 0; 136 return 0; 137 } 138 #endif 139 140 static int read_instret(CPURISCVState *env, int csrno, target_ulong *val) 141 { 142 if (!counter_enabled(env, csrno)) { 143 return -1; 144 } 145 #if !defined(CONFIG_USER_ONLY) 146 if (use_icount) { 147 *val = cpu_get_icount(); 148 } else { 149 *val = cpu_get_host_ticks(); 150 } 151 #else 152 *val = cpu_get_host_ticks(); 153 #endif 154 return 0; 155 } 156 157 #if defined(TARGET_RISCV32) 158 static int read_instreth(CPURISCVState *env, int csrno, target_ulong *val) 159 { 160 if (!counter_enabled(env, csrno)) { 161 return -1; 162 } 163 #if !defined(CONFIG_USER_ONLY) 164 if (use_icount) { 165 *val = cpu_get_icount() >> 32; 166 } else { 167 *val = cpu_get_host_ticks() >> 32; 168 } 169 #else 170 *val = cpu_get_host_ticks() >> 32; 171 #endif 172 return 0; 173 } 174 #endif /* TARGET_RISCV32 */ 175 176 #if defined(CONFIG_USER_ONLY) 177 static int read_time(CPURISCVState *env, int csrno, target_ulong *val) 178 { 179 *val = cpu_get_host_ticks(); 180 return 0; 181 } 182 183 #if defined(TARGET_RISCV32) 184 static int read_timeh(CPURISCVState *env, int csrno, target_ulong *val) 185 { 186 *val = cpu_get_host_ticks() >> 32; 187 return 0; 188 } 189 #endif 190 191 #else /* CONFIG_USER_ONLY */ 192 193 /* Machine constants */ 194 195 #define M_MODE_INTERRUPTS (MIP_MSIP | MIP_MTIP | MIP_MEIP) 196 #define S_MODE_INTERRUPTS (MIP_SSIP | MIP_STIP | MIP_SEIP) 197 198 static const target_ulong delegable_ints = S_MODE_INTERRUPTS; 199 static const target_ulong all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS; 200 static const target_ulong delegable_excps = 201 (1ULL << (RISCV_EXCP_INST_ADDR_MIS)) | 202 (1ULL << (RISCV_EXCP_INST_ACCESS_FAULT)) | 203 (1ULL << (RISCV_EXCP_ILLEGAL_INST)) | 204 (1ULL << (RISCV_EXCP_BREAKPOINT)) | 205 (1ULL << (RISCV_EXCP_LOAD_ADDR_MIS)) | 206 (1ULL << (RISCV_EXCP_LOAD_ACCESS_FAULT)) | 207 (1ULL << (RISCV_EXCP_STORE_AMO_ADDR_MIS)) | 208 (1ULL << (RISCV_EXCP_STORE_AMO_ACCESS_FAULT)) | 209 (1ULL << (RISCV_EXCP_U_ECALL)) | 210 (1ULL << (RISCV_EXCP_S_ECALL)) | 211 (1ULL << (RISCV_EXCP_H_ECALL)) | 212 (1ULL << (RISCV_EXCP_M_ECALL)) | 213 (1ULL << (RISCV_EXCP_INST_PAGE_FAULT)) | 214 (1ULL << (RISCV_EXCP_LOAD_PAGE_FAULT)) | 215 (1ULL << (RISCV_EXCP_STORE_PAGE_FAULT)); 216 static const target_ulong sstatus_v1_9_mask = SSTATUS_SIE | SSTATUS_SPIE | 217 SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS | 218 SSTATUS_SUM | SSTATUS_SD; 219 static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE | 220 SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS | 221 SSTATUS_SUM | SSTATUS_MXR | SSTATUS_SD; 222 223 #if defined(TARGET_RISCV32) 224 static const char valid_vm_1_09[16] = { 225 [VM_1_09_MBARE] = 1, 226 [VM_1_09_SV32] = 1, 227 }; 228 static const char valid_vm_1_10[16] = { 229 [VM_1_10_MBARE] = 1, 230 [VM_1_10_SV32] = 1 231 }; 232 #elif defined(TARGET_RISCV64) 233 static const char valid_vm_1_09[16] = { 234 [VM_1_09_MBARE] = 1, 235 [VM_1_09_SV39] = 1, 236 [VM_1_09_SV48] = 1, 237 }; 238 static const char valid_vm_1_10[16] = { 239 [VM_1_10_MBARE] = 1, 240 [VM_1_10_SV39] = 1, 241 [VM_1_10_SV48] = 1, 242 [VM_1_10_SV57] = 1 243 }; 244 #endif /* CONFIG_USER_ONLY */ 245 246 /* Machine Information Registers */ 247 static int read_zero(CPURISCVState *env, int csrno, target_ulong *val) 248 { 249 return *val = 0; 250 } 251 252 static int read_mhartid(CPURISCVState *env, int csrno, target_ulong *val) 253 { 254 *val = env->mhartid; 255 return 0; 256 } 257 258 /* Machine Trap Setup */ 259 static int read_mstatus(CPURISCVState *env, int csrno, target_ulong *val) 260 { 261 *val = env->mstatus; 262 return 0; 263 } 264 265 static int validate_vm(CPURISCVState *env, target_ulong vm) 266 { 267 return (env->priv_ver >= PRIV_VERSION_1_10_0) ? 268 valid_vm_1_10[vm & 0xf] : valid_vm_1_09[vm & 0xf]; 269 } 270 271 static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val) 272 { 273 target_ulong mstatus = env->mstatus; 274 target_ulong mask = 0; 275 target_ulong mpp = get_field(val, MSTATUS_MPP); 276 277 /* flush tlb on mstatus fields that affect VM */ 278 if (env->priv_ver <= PRIV_VERSION_1_09_1) { 279 if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | 280 MSTATUS_MPRV | MSTATUS_SUM | MSTATUS_VM)) { 281 tlb_flush(CPU(riscv_env_get_cpu(env))); 282 } 283 mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE | 284 MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM | 285 MSTATUS_MPP | MSTATUS_MXR | 286 (validate_vm(env, get_field(val, MSTATUS_VM)) ? 287 MSTATUS_VM : 0); 288 } 289 if (env->priv_ver >= PRIV_VERSION_1_10_0) { 290 if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | 291 MSTATUS_MPRV | MSTATUS_SUM)) { 292 tlb_flush(CPU(riscv_env_get_cpu(env))); 293 } 294 mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE | 295 MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM | 296 MSTATUS_MPP | MSTATUS_MXR; 297 } 298 299 /* silenty discard mstatus.mpp writes for unsupported modes */ 300 if (mpp == PRV_H || 301 (!riscv_has_ext(env, RVS) && mpp == PRV_S) || 302 (!riscv_has_ext(env, RVU) && mpp == PRV_U)) { 303 mask &= ~MSTATUS_MPP; 304 } 305 306 mstatus = (mstatus & ~mask) | (val & mask); 307 308 /* Note: this is a workaround for an issue where mstatus.FS 309 does not report dirty after floating point operations 310 that modify floating point state. This workaround is 311 technically compliant with the RISC-V Privileged 312 specification as it is legal to return only off, or dirty. 313 at the expense of extra floating point save/restore. */ 314 315 /* FP is always dirty or off */ 316 if (mstatus & MSTATUS_FS) { 317 mstatus |= MSTATUS_FS; 318 } 319 320 int dirty = ((mstatus & MSTATUS_FS) == MSTATUS_FS) | 321 ((mstatus & MSTATUS_XS) == MSTATUS_XS); 322 mstatus = set_field(mstatus, MSTATUS_SD, dirty); 323 env->mstatus = mstatus; 324 325 return 0; 326 } 327 328 static int read_misa(CPURISCVState *env, int csrno, target_ulong *val) 329 { 330 *val = env->misa; 331 return 0; 332 } 333 334 static int read_medeleg(CPURISCVState *env, int csrno, target_ulong *val) 335 { 336 *val = env->medeleg; 337 return 0; 338 } 339 340 static int write_medeleg(CPURISCVState *env, int csrno, target_ulong val) 341 { 342 env->medeleg = (env->medeleg & ~delegable_excps) | (val & delegable_excps); 343 return 0; 344 } 345 346 static int read_mideleg(CPURISCVState *env, int csrno, target_ulong *val) 347 { 348 *val = env->mideleg; 349 return 0; 350 } 351 352 static int write_mideleg(CPURISCVState *env, int csrno, target_ulong val) 353 { 354 env->mideleg = (env->mideleg & ~delegable_ints) | (val & delegable_ints); 355 return 0; 356 } 357 358 static int read_mie(CPURISCVState *env, int csrno, target_ulong *val) 359 { 360 *val = env->mie; 361 return 0; 362 } 363 364 static int write_mie(CPURISCVState *env, int csrno, target_ulong val) 365 { 366 env->mie = (env->mie & ~all_ints) | (val & all_ints); 367 return 0; 368 } 369 370 static int read_mtvec(CPURISCVState *env, int csrno, target_ulong *val) 371 { 372 *val = env->mtvec; 373 return 0; 374 } 375 376 static int write_mtvec(CPURISCVState *env, int csrno, target_ulong val) 377 { 378 /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */ 379 if ((val & 3) == 0) { 380 env->mtvec = val >> 2 << 2; 381 } else { 382 qemu_log_mask(LOG_UNIMP, "CSR_MTVEC: vectored traps not supported"); 383 } 384 return 0; 385 } 386 387 static int read_mcounteren(CPURISCVState *env, int csrno, target_ulong *val) 388 { 389 if (env->priv_ver < PRIV_VERSION_1_10_0) { 390 return -1; 391 } 392 *val = env->mcounteren; 393 return 0; 394 } 395 396 static int write_mcounteren(CPURISCVState *env, int csrno, target_ulong val) 397 { 398 if (env->priv_ver < PRIV_VERSION_1_10_0) { 399 return -1; 400 } 401 env->mcounteren = val; 402 return 0; 403 } 404 405 static int read_mscounteren(CPURISCVState *env, int csrno, target_ulong *val) 406 { 407 if (env->priv_ver > PRIV_VERSION_1_09_1) { 408 return -1; 409 } 410 *val = env->mcounteren; 411 return 0; 412 } 413 414 static int write_mscounteren(CPURISCVState *env, int csrno, target_ulong val) 415 { 416 if (env->priv_ver > PRIV_VERSION_1_09_1) { 417 return -1; 418 } 419 env->mcounteren = val; 420 return 0; 421 } 422 423 static int read_mucounteren(CPURISCVState *env, int csrno, target_ulong *val) 424 { 425 if (env->priv_ver > PRIV_VERSION_1_09_1) { 426 return -1; 427 } 428 *val = env->scounteren; 429 return 0; 430 } 431 432 static int write_mucounteren(CPURISCVState *env, int csrno, target_ulong val) 433 { 434 if (env->priv_ver > PRIV_VERSION_1_09_1) { 435 return -1; 436 } 437 env->scounteren = val; 438 return 0; 439 } 440 441 /* Machine Trap Handling */ 442 static int read_mscratch(CPURISCVState *env, int csrno, target_ulong *val) 443 { 444 *val = env->mscratch; 445 return 0; 446 } 447 448 static int write_mscratch(CPURISCVState *env, int csrno, target_ulong val) 449 { 450 env->mscratch = val; 451 return 0; 452 } 453 454 static int read_mepc(CPURISCVState *env, int csrno, target_ulong *val) 455 { 456 *val = env->mepc; 457 return 0; 458 } 459 460 static int write_mepc(CPURISCVState *env, int csrno, target_ulong val) 461 { 462 env->mepc = val; 463 return 0; 464 } 465 466 static int read_mcause(CPURISCVState *env, int csrno, target_ulong *val) 467 { 468 *val = env->mcause; 469 return 0; 470 } 471 472 static int write_mcause(CPURISCVState *env, int csrno, target_ulong val) 473 { 474 env->mcause = val; 475 return 0; 476 } 477 478 static int read_mbadaddr(CPURISCVState *env, int csrno, target_ulong *val) 479 { 480 *val = env->mbadaddr; 481 return 0; 482 } 483 484 static int write_mbadaddr(CPURISCVState *env, int csrno, target_ulong val) 485 { 486 env->mbadaddr = val; 487 return 0; 488 } 489 490 static int read_mip(CPURISCVState *env, int csrno, target_ulong *val) 491 { 492 *val = atomic_read(&env->mip); 493 return 0; 494 } 495 496 static int write_mip(CPURISCVState *env, int csrno, target_ulong val) 497 { 498 RISCVCPU *cpu = riscv_env_get_cpu(env); 499 500 /* 501 * csrs, csrc on mip.SEIP is not decomposable into separate read and 502 * write steps, so a different implementation is needed 503 */ 504 505 qemu_mutex_lock_iothread(); 506 riscv_cpu_update_mip(cpu, MIP_SSIP | MIP_STIP, 507 (val & (MIP_SSIP | MIP_STIP))); 508 qemu_mutex_unlock_iothread(); 509 510 return 0; 511 } 512 513 /* Supervisor Trap Setup */ 514 static int read_sstatus(CPURISCVState *env, int csrno, target_ulong *val) 515 { 516 target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ? 517 sstatus_v1_10_mask : sstatus_v1_9_mask); 518 *val = env->mstatus & mask; 519 return 0; 520 } 521 522 static int write_sstatus(CPURISCVState *env, int csrno, target_ulong val) 523 { 524 target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ? 525 sstatus_v1_10_mask : sstatus_v1_9_mask); 526 target_ulong newval = (env->mstatus & ~mask) | (val & mask); 527 return write_mstatus(env, CSR_MSTATUS, newval); 528 } 529 530 static int read_sie(CPURISCVState *env, int csrno, target_ulong *val) 531 { 532 *val = env->mie & env->mideleg; 533 return 0; 534 } 535 536 static int write_sie(CPURISCVState *env, int csrno, target_ulong val) 537 { 538 target_ulong newval = (env->mie & ~env->mideleg) | (val & env->mideleg); 539 return write_mie(env, CSR_MIE, newval); 540 } 541 542 static int read_stvec(CPURISCVState *env, int csrno, target_ulong *val) 543 { 544 *val = env->stvec; 545 return 0; 546 } 547 548 static int write_stvec(CPURISCVState *env, int csrno, target_ulong val) 549 { 550 /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */ 551 if ((val & 3) == 0) { 552 env->stvec = val >> 2 << 2; 553 } else { 554 qemu_log_mask(LOG_UNIMP, "CSR_STVEC: vectored traps not supported"); 555 } 556 return 0; 557 } 558 559 static int read_scounteren(CPURISCVState *env, int csrno, target_ulong *val) 560 { 561 if (env->priv_ver < PRIV_VERSION_1_10_0) { 562 return -1; 563 } 564 *val = env->scounteren; 565 return 0; 566 } 567 568 static int write_scounteren(CPURISCVState *env, int csrno, target_ulong val) 569 { 570 if (env->priv_ver < PRIV_VERSION_1_10_0) { 571 return -1; 572 } 573 env->scounteren = val; 574 return 0; 575 } 576 577 /* Supervisor Trap Handling */ 578 static int read_sscratch(CPURISCVState *env, int csrno, target_ulong *val) 579 { 580 *val = env->sscratch; 581 return 0; 582 } 583 584 static int write_sscratch(CPURISCVState *env, int csrno, target_ulong val) 585 { 586 env->sscratch = val; 587 return 0; 588 } 589 590 static int read_sepc(CPURISCVState *env, int csrno, target_ulong *val) 591 { 592 *val = env->sepc; 593 return 0; 594 } 595 596 static int write_sepc(CPURISCVState *env, int csrno, target_ulong val) 597 { 598 env->sepc = val; 599 return 0; 600 } 601 602 static int read_scause(CPURISCVState *env, int csrno, target_ulong *val) 603 { 604 *val = env->scause; 605 return 0; 606 } 607 608 static int write_scause(CPURISCVState *env, int csrno, target_ulong val) 609 { 610 env->scause = val; 611 return 0; 612 } 613 614 static int read_sbadaddr(CPURISCVState *env, int csrno, target_ulong *val) 615 { 616 *val = env->sbadaddr; 617 return 0; 618 } 619 620 static int write_sbadaddr(CPURISCVState *env, int csrno, target_ulong val) 621 { 622 env->sbadaddr = val; 623 return 0; 624 } 625 626 static int read_sip(CPURISCVState *env, int csrno, target_ulong *val) 627 { 628 *val = atomic_read(&env->mip) & env->mideleg; 629 return 0; 630 } 631 632 static int write_sip(CPURISCVState *env, int csrno, target_ulong val) 633 { 634 target_ulong newval = (atomic_read(&env->mip) & ~env->mideleg) 635 | (val & env->mideleg); 636 return write_mip(env, CSR_MIP, newval); 637 } 638 639 /* Supervisor Protection and Translation */ 640 static int read_satp(CPURISCVState *env, int csrno, target_ulong *val) 641 { 642 if (!riscv_feature(env, RISCV_FEATURE_MMU)) { 643 *val = 0; 644 } else if (env->priv_ver >= PRIV_VERSION_1_10_0) { 645 *val = env->satp; 646 } else { 647 *val = env->sptbr; 648 } 649 return 0; 650 } 651 652 static int write_satp(CPURISCVState *env, int csrno, target_ulong val) 653 { 654 if (!riscv_feature(env, RISCV_FEATURE_MMU)) { 655 return 0; 656 } 657 if (env->priv_ver <= PRIV_VERSION_1_09_1 && (val ^ env->sptbr)) { 658 tlb_flush(CPU(riscv_env_get_cpu(env))); 659 env->sptbr = val & (((target_ulong) 660 1 << (TARGET_PHYS_ADDR_SPACE_BITS - PGSHIFT)) - 1); 661 } 662 if (env->priv_ver >= PRIV_VERSION_1_10_0 && 663 validate_vm(env, get_field(val, SATP_MODE)) && 664 ((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN))) 665 { 666 tlb_flush(CPU(riscv_env_get_cpu(env))); 667 env->satp = val; 668 } 669 return 0; 670 } 671 672 /* Physical Memory Protection */ 673 static int read_pmpcfg(CPURISCVState *env, int csrno, target_ulong *val) 674 { 675 *val = pmpcfg_csr_read(env, csrno - CSR_PMPCFG0); 676 return 0; 677 } 678 679 static int write_pmpcfg(CPURISCVState *env, int csrno, target_ulong val) 680 { 681 pmpcfg_csr_write(env, csrno - CSR_PMPCFG0, val); 682 return 0; 683 } 684 685 static int read_pmpaddr(CPURISCVState *env, int csrno, target_ulong *val) 686 { 687 *val = pmpaddr_csr_read(env, csrno - CSR_PMPADDR0); 688 return 0; 689 } 690 691 static int write_pmpaddr(CPURISCVState *env, int csrno, target_ulong val) 692 { 693 pmpaddr_csr_write(env, csrno - CSR_PMPADDR0, val); 694 return 0; 695 } 696 697 #endif 698 699 /* 700 * riscv_csrrw - read and/or update control and status register 701 * 702 * csrr <-> riscv_csrrw(env, csrno, ret_value, 0, 0); 703 * csrrw <-> riscv_csrrw(env, csrno, ret_value, value, -1); 704 * csrrs <-> riscv_csrrw(env, csrno, ret_value, -1, value); 705 * csrrc <-> riscv_csrrw(env, csrno, ret_value, 0, value); 706 */ 707 708 int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value, 709 target_ulong new_value, target_ulong write_mask) 710 { 711 int ret; 712 target_ulong old_value; 713 714 /* check privileges and return -1 if check fails */ 715 #if !defined(CONFIG_USER_ONLY) 716 int csr_priv = get_field(csrno, 0x300); 717 int read_only = get_field(csrno, 0xC00) == 3; 718 if ((write_mask && read_only) || (env->priv < csr_priv)) { 719 return -1; 720 } 721 #endif 722 723 /* execute combined read/write operation if it exists */ 724 if (csr_ops[csrno].op) { 725 return csr_ops[csrno].op(env, csrno, ret_value, new_value, write_mask); 726 } 727 728 /* if no accessor exists then return failure */ 729 if (!csr_ops[csrno].read) { 730 return -1; 731 } 732 733 /* read old value */ 734 ret = csr_ops[csrno].read(env, csrno, &old_value); 735 if (ret < 0) { 736 return ret; 737 } 738 739 /* write value if writable and write mask set, otherwise drop writes */ 740 if (write_mask) { 741 new_value = (old_value & ~write_mask) | (new_value & write_mask); 742 if (csr_ops[csrno].write) { 743 ret = csr_ops[csrno].write(env, csrno, new_value); 744 if (ret < 0) { 745 return ret; 746 } 747 } 748 } 749 750 /* return old value */ 751 if (ret_value) { 752 *ret_value = old_value; 753 } 754 755 return 0; 756 } 757 758 /* Control and Status Register function table */ 759 static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { 760 /* User Floating-Point CSRs */ 761 [CSR_FFLAGS] = { read_fflags, write_fflags }, 762 [CSR_FRM] = { read_frm, write_frm }, 763 [CSR_FCSR] = { read_fcsr, write_fcsr }, 764 765 /* User Timers and Counters */ 766 [CSR_CYCLE] = { read_instret }, 767 [CSR_INSTRET] = { read_instret }, 768 #if defined(TARGET_RISCV32) 769 [CSR_CYCLEH] = { read_instreth }, 770 [CSR_INSTRETH] = { read_instreth }, 771 #endif 772 773 /* User-level time CSRs are only available in linux-user 774 * In privileged mode, the monitor emulates these CSRs */ 775 #if defined(CONFIG_USER_ONLY) 776 [CSR_TIME] = { read_time }, 777 #if defined(TARGET_RISCV32) 778 [CSR_TIMEH] = { read_timeh }, 779 #endif 780 #endif 781 782 #if !defined(CONFIG_USER_ONLY) 783 /* Machine Timers and Counters */ 784 [CSR_MCYCLE] = { read_instret }, 785 [CSR_MINSTRET] = { read_instret }, 786 #if defined(TARGET_RISCV32) 787 [CSR_MCYCLEH] = { read_instreth }, 788 [CSR_MINSTRETH] = { read_instreth }, 789 #endif 790 791 /* Machine Information Registers */ 792 [CSR_MVENDORID] = { read_zero }, 793 [CSR_MARCHID] = { read_zero }, 794 [CSR_MIMPID] = { read_zero }, 795 [CSR_MHARTID] = { read_mhartid }, 796 797 /* Machine Trap Setup */ 798 [CSR_MSTATUS] = { read_mstatus, write_mstatus }, 799 [CSR_MISA] = { read_misa }, 800 [CSR_MIDELEG] = { read_mideleg, write_mideleg }, 801 [CSR_MEDELEG] = { read_medeleg, write_medeleg }, 802 [CSR_MIE] = { read_mie, write_mie }, 803 [CSR_MTVEC] = { read_mtvec, write_mtvec }, 804 [CSR_MCOUNTEREN] = { read_mcounteren, write_mcounteren }, 805 806 /* Legacy Counter Setup (priv v1.9.1) */ 807 [CSR_MUCOUNTEREN] = { read_mucounteren, write_mucounteren }, 808 [CSR_MSCOUNTEREN] = { read_mscounteren, write_mscounteren }, 809 810 /* Machine Trap Handling */ 811 [CSR_MSCRATCH] = { read_mscratch, write_mscratch }, 812 [CSR_MEPC] = { read_mepc, write_mepc }, 813 [CSR_MCAUSE] = { read_mcause, write_mcause }, 814 [CSR_MBADADDR] = { read_mbadaddr, write_mbadaddr }, 815 [CSR_MIP] = { read_mip, write_mip }, 816 817 /* Supervisor Trap Setup */ 818 [CSR_SSTATUS] = { read_sstatus, write_sstatus }, 819 [CSR_SIE] = { read_sie, write_sie }, 820 [CSR_STVEC] = { read_stvec, write_stvec }, 821 [CSR_SCOUNTEREN] = { read_scounteren, write_scounteren }, 822 823 /* Supervisor Trap Handling */ 824 [CSR_SSCRATCH] = { read_sscratch, write_sscratch }, 825 [CSR_SEPC] = { read_sepc, write_sepc }, 826 [CSR_SCAUSE] = { read_scause, write_scause }, 827 [CSR_SBADADDR] = { read_sbadaddr, write_sbadaddr }, 828 [CSR_SIP] = { read_sip, write_sip }, 829 830 /* Supervisor Protection and Translation */ 831 [CSR_SATP] = { read_satp, write_satp }, 832 833 /* Physical Memory Protection */ 834 [CSR_PMPCFG0 ... CSR_PMPADDR9] = { read_pmpcfg, write_pmpcfg }, 835 [CSR_PMPADDR0 ... CSR_PMPADDR15] = { read_pmpaddr, write_pmpaddr }, 836 837 /* Performance Counters */ 838 [CSR_HPMCOUNTER3 ... CSR_HPMCOUNTER31] = { read_zero_counter }, 839 [CSR_MHPMCOUNTER3 ... CSR_MHPMCOUNTER31] = { read_zero }, 840 [CSR_MHPMEVENT3 ... CSR_MHPMEVENT31] = { read_zero }, 841 #if defined(TARGET_RISCV32) 842 [CSR_HPMCOUNTER3H ... CSR_HPMCOUNTER31H] = { read_zero_counter }, 843 [CSR_MHPMCOUNTER3H ... CSR_MHPMCOUNTER31H] = { read_zero }, 844 #endif 845 #endif /* !CONFIG_USER_ONLY */ 846 }; 847