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 /* Predicates */ 46 static int fs(CPURISCVState *env, int csrno) 47 { 48 #if !defined(CONFIG_USER_ONLY) 49 if (!env->debugger && !(env->mstatus & MSTATUS_FS)) { 50 return -1; 51 } 52 #endif 53 return 0; 54 } 55 56 static int ctr(CPURISCVState *env, int csrno) 57 { 58 #if !defined(CONFIG_USER_ONLY) 59 /* 60 * The counters are always enabled on newer priv specs, as the CSR has 61 * changed from controlling that the counters can be read to controlling 62 * that the counters increment. 63 */ 64 if (env->priv_ver > PRIV_VERSION_1_09_1) { 65 return 0; 66 } 67 68 uint32_t ctr_en = ~0u; 69 70 if (env->priv < PRV_M) { 71 ctr_en &= env->mcounteren; 72 } 73 if (env->priv < PRV_S) { 74 ctr_en &= env->scounteren; 75 } 76 if (!(ctr_en & (1u << (csrno & 31)))) { 77 return -1; 78 } 79 #endif 80 return 0; 81 } 82 83 #if !defined(CONFIG_USER_ONLY) 84 static int any(CPURISCVState *env, int csrno) 85 { 86 return 0; 87 } 88 89 static int smode(CPURISCVState *env, int csrno) 90 { 91 return -!riscv_has_ext(env, RVS); 92 } 93 94 static int pmp(CPURISCVState *env, int csrno) 95 { 96 return -!riscv_feature(env, RISCV_FEATURE_PMP); 97 } 98 #endif 99 100 /* User Floating-Point CSRs */ 101 static int read_fflags(CPURISCVState *env, int csrno, target_ulong *val) 102 { 103 #if !defined(CONFIG_USER_ONLY) 104 if (!env->debugger && !(env->mstatus & MSTATUS_FS)) { 105 return -1; 106 } 107 #endif 108 *val = riscv_cpu_get_fflags(env); 109 return 0; 110 } 111 112 static int write_fflags(CPURISCVState *env, int csrno, target_ulong val) 113 { 114 #if !defined(CONFIG_USER_ONLY) 115 if (!env->debugger && !(env->mstatus & MSTATUS_FS)) { 116 return -1; 117 } 118 env->mstatus |= MSTATUS_FS; 119 #endif 120 riscv_cpu_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT)); 121 return 0; 122 } 123 124 static int read_frm(CPURISCVState *env, int csrno, target_ulong *val) 125 { 126 #if !defined(CONFIG_USER_ONLY) 127 if (!env->debugger && !(env->mstatus & MSTATUS_FS)) { 128 return -1; 129 } 130 #endif 131 *val = env->frm; 132 return 0; 133 } 134 135 static int write_frm(CPURISCVState *env, int csrno, target_ulong val) 136 { 137 #if !defined(CONFIG_USER_ONLY) 138 if (!env->debugger && !(env->mstatus & MSTATUS_FS)) { 139 return -1; 140 } 141 env->mstatus |= MSTATUS_FS; 142 #endif 143 env->frm = val & (FSR_RD >> FSR_RD_SHIFT); 144 return 0; 145 } 146 147 static int read_fcsr(CPURISCVState *env, int csrno, target_ulong *val) 148 { 149 #if !defined(CONFIG_USER_ONLY) 150 if (!env->debugger && !(env->mstatus & MSTATUS_FS)) { 151 return -1; 152 } 153 #endif 154 *val = (riscv_cpu_get_fflags(env) << FSR_AEXC_SHIFT) 155 | (env->frm << FSR_RD_SHIFT); 156 return 0; 157 } 158 159 static int write_fcsr(CPURISCVState *env, int csrno, target_ulong val) 160 { 161 #if !defined(CONFIG_USER_ONLY) 162 if (!env->debugger && !(env->mstatus & MSTATUS_FS)) { 163 return -1; 164 } 165 env->mstatus |= MSTATUS_FS; 166 #endif 167 env->frm = (val & FSR_RD) >> FSR_RD_SHIFT; 168 riscv_cpu_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT); 169 return 0; 170 } 171 172 /* User Timers and Counters */ 173 static int read_instret(CPURISCVState *env, int csrno, target_ulong *val) 174 { 175 #if !defined(CONFIG_USER_ONLY) 176 if (use_icount) { 177 *val = cpu_get_icount(); 178 } else { 179 *val = cpu_get_host_ticks(); 180 } 181 #else 182 *val = cpu_get_host_ticks(); 183 #endif 184 return 0; 185 } 186 187 #if defined(TARGET_RISCV32) 188 static int read_instreth(CPURISCVState *env, int csrno, target_ulong *val) 189 { 190 #if !defined(CONFIG_USER_ONLY) 191 if (use_icount) { 192 *val = cpu_get_icount() >> 32; 193 } else { 194 *val = cpu_get_host_ticks() >> 32; 195 } 196 #else 197 *val = cpu_get_host_ticks() >> 32; 198 #endif 199 return 0; 200 } 201 #endif /* TARGET_RISCV32 */ 202 203 #if defined(CONFIG_USER_ONLY) 204 static int read_time(CPURISCVState *env, int csrno, target_ulong *val) 205 { 206 *val = cpu_get_host_ticks(); 207 return 0; 208 } 209 210 #if defined(TARGET_RISCV32) 211 static int read_timeh(CPURISCVState *env, int csrno, target_ulong *val) 212 { 213 *val = cpu_get_host_ticks() >> 32; 214 return 0; 215 } 216 #endif 217 218 #else /* CONFIG_USER_ONLY */ 219 220 /* Machine constants */ 221 222 #define M_MODE_INTERRUPTS (MIP_MSIP | MIP_MTIP | MIP_MEIP) 223 #define S_MODE_INTERRUPTS (MIP_SSIP | MIP_STIP | MIP_SEIP) 224 225 static const target_ulong delegable_ints = S_MODE_INTERRUPTS; 226 static const target_ulong all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS; 227 static const target_ulong delegable_excps = 228 (1ULL << (RISCV_EXCP_INST_ADDR_MIS)) | 229 (1ULL << (RISCV_EXCP_INST_ACCESS_FAULT)) | 230 (1ULL << (RISCV_EXCP_ILLEGAL_INST)) | 231 (1ULL << (RISCV_EXCP_BREAKPOINT)) | 232 (1ULL << (RISCV_EXCP_LOAD_ADDR_MIS)) | 233 (1ULL << (RISCV_EXCP_LOAD_ACCESS_FAULT)) | 234 (1ULL << (RISCV_EXCP_STORE_AMO_ADDR_MIS)) | 235 (1ULL << (RISCV_EXCP_STORE_AMO_ACCESS_FAULT)) | 236 (1ULL << (RISCV_EXCP_U_ECALL)) | 237 (1ULL << (RISCV_EXCP_S_ECALL)) | 238 (1ULL << (RISCV_EXCP_H_ECALL)) | 239 (1ULL << (RISCV_EXCP_M_ECALL)) | 240 (1ULL << (RISCV_EXCP_INST_PAGE_FAULT)) | 241 (1ULL << (RISCV_EXCP_LOAD_PAGE_FAULT)) | 242 (1ULL << (RISCV_EXCP_STORE_PAGE_FAULT)); 243 static const target_ulong sstatus_v1_9_mask = SSTATUS_SIE | SSTATUS_SPIE | 244 SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS | 245 SSTATUS_SUM | SSTATUS_SD; 246 static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE | 247 SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS | 248 SSTATUS_SUM | SSTATUS_MXR | SSTATUS_SD; 249 static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP; 250 251 #if defined(TARGET_RISCV32) 252 static const char valid_vm_1_09[16] = { 253 [VM_1_09_MBARE] = 1, 254 [VM_1_09_SV32] = 1, 255 }; 256 static const char valid_vm_1_10[16] = { 257 [VM_1_10_MBARE] = 1, 258 [VM_1_10_SV32] = 1 259 }; 260 #elif defined(TARGET_RISCV64) 261 static const char valid_vm_1_09[16] = { 262 [VM_1_09_MBARE] = 1, 263 [VM_1_09_SV39] = 1, 264 [VM_1_09_SV48] = 1, 265 }; 266 static const char valid_vm_1_10[16] = { 267 [VM_1_10_MBARE] = 1, 268 [VM_1_10_SV39] = 1, 269 [VM_1_10_SV48] = 1, 270 [VM_1_10_SV57] = 1 271 }; 272 #endif /* CONFIG_USER_ONLY */ 273 274 /* Machine Information Registers */ 275 static int read_zero(CPURISCVState *env, int csrno, target_ulong *val) 276 { 277 return *val = 0; 278 } 279 280 static int read_mhartid(CPURISCVState *env, int csrno, target_ulong *val) 281 { 282 *val = env->mhartid; 283 return 0; 284 } 285 286 /* Machine Trap Setup */ 287 static int read_mstatus(CPURISCVState *env, int csrno, target_ulong *val) 288 { 289 *val = env->mstatus; 290 return 0; 291 } 292 293 static int validate_vm(CPURISCVState *env, target_ulong vm) 294 { 295 return (env->priv_ver >= PRIV_VERSION_1_10_0) ? 296 valid_vm_1_10[vm & 0xf] : valid_vm_1_09[vm & 0xf]; 297 } 298 299 static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val) 300 { 301 target_ulong mstatus = env->mstatus; 302 target_ulong mask = 0; 303 304 /* flush tlb on mstatus fields that affect VM */ 305 if (env->priv_ver <= PRIV_VERSION_1_09_1) { 306 if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | 307 MSTATUS_MPRV | MSTATUS_SUM | MSTATUS_VM)) { 308 tlb_flush(env_cpu(env)); 309 } 310 mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE | 311 MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM | 312 MSTATUS_MPP | MSTATUS_MXR | 313 (validate_vm(env, get_field(val, MSTATUS_VM)) ? 314 MSTATUS_VM : 0); 315 } 316 if (env->priv_ver >= PRIV_VERSION_1_10_0) { 317 if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV | 318 MSTATUS_MPRV | MSTATUS_SUM)) { 319 tlb_flush(env_cpu(env)); 320 } 321 mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE | 322 MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM | 323 MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR | 324 MSTATUS_TW; 325 #if defined(TARGET_RISCV64) 326 /* 327 * RV32: MPV and MTL are not in mstatus. The current plan is to 328 * add them to mstatush. For now, we just don't support it. 329 */ 330 mask |= MSTATUS_MPP | MSTATUS_MPV; 331 #endif 332 } 333 334 mstatus = (mstatus & ~mask) | (val & mask); 335 336 int dirty = ((mstatus & MSTATUS_FS) == MSTATUS_FS) | 337 ((mstatus & MSTATUS_XS) == MSTATUS_XS); 338 mstatus = set_field(mstatus, MSTATUS_SD, dirty); 339 env->mstatus = mstatus; 340 341 return 0; 342 } 343 344 static int read_misa(CPURISCVState *env, int csrno, target_ulong *val) 345 { 346 *val = env->misa; 347 return 0; 348 } 349 350 static int write_misa(CPURISCVState *env, int csrno, target_ulong val) 351 { 352 if (!riscv_feature(env, RISCV_FEATURE_MISA)) { 353 /* drop write to misa */ 354 return 0; 355 } 356 357 /* 'I' or 'E' must be present */ 358 if (!(val & (RVI | RVE))) { 359 /* It is not, drop write to misa */ 360 return 0; 361 } 362 363 /* 'E' excludes all other extensions */ 364 if (val & RVE) { 365 /* when we support 'E' we can do "val = RVE;" however 366 * for now we just drop writes if 'E' is present. 367 */ 368 return 0; 369 } 370 371 /* Mask extensions that are not supported by this hart */ 372 val &= env->misa_mask; 373 374 /* Mask extensions that are not supported by QEMU */ 375 val &= (RVI | RVE | RVM | RVA | RVF | RVD | RVC | RVS | RVU); 376 377 /* 'D' depends on 'F', so clear 'D' if 'F' is not present */ 378 if ((val & RVD) && !(val & RVF)) { 379 val &= ~RVD; 380 } 381 382 /* Suppress 'C' if next instruction is not aligned 383 * TODO: this should check next_pc 384 */ 385 if ((val & RVC) && (GETPC() & ~3) != 0) { 386 val &= ~RVC; 387 } 388 389 /* misa.MXL writes are not supported by QEMU */ 390 val = (env->misa & MISA_MXL) | (val & ~MISA_MXL); 391 392 /* flush translation cache */ 393 if (val != env->misa) { 394 tb_flush(env_cpu(env)); 395 } 396 397 env->misa = val; 398 399 return 0; 400 } 401 402 static int read_medeleg(CPURISCVState *env, int csrno, target_ulong *val) 403 { 404 *val = env->medeleg; 405 return 0; 406 } 407 408 static int write_medeleg(CPURISCVState *env, int csrno, target_ulong val) 409 { 410 env->medeleg = (env->medeleg & ~delegable_excps) | (val & delegable_excps); 411 return 0; 412 } 413 414 static int read_mideleg(CPURISCVState *env, int csrno, target_ulong *val) 415 { 416 *val = env->mideleg; 417 return 0; 418 } 419 420 static int write_mideleg(CPURISCVState *env, int csrno, target_ulong val) 421 { 422 env->mideleg = (env->mideleg & ~delegable_ints) | (val & delegable_ints); 423 return 0; 424 } 425 426 static int read_mie(CPURISCVState *env, int csrno, target_ulong *val) 427 { 428 *val = env->mie; 429 return 0; 430 } 431 432 static int write_mie(CPURISCVState *env, int csrno, target_ulong val) 433 { 434 env->mie = (env->mie & ~all_ints) | (val & all_ints); 435 return 0; 436 } 437 438 static int read_mtvec(CPURISCVState *env, int csrno, target_ulong *val) 439 { 440 *val = env->mtvec; 441 return 0; 442 } 443 444 static int write_mtvec(CPURISCVState *env, int csrno, target_ulong val) 445 { 446 /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */ 447 if ((val & 3) < 2) { 448 env->mtvec = val; 449 } else { 450 qemu_log_mask(LOG_UNIMP, "CSR_MTVEC: reserved mode not supported\n"); 451 } 452 return 0; 453 } 454 455 static int read_mcounteren(CPURISCVState *env, int csrno, target_ulong *val) 456 { 457 if (env->priv_ver < PRIV_VERSION_1_10_0) { 458 return -1; 459 } 460 *val = env->mcounteren; 461 return 0; 462 } 463 464 static int write_mcounteren(CPURISCVState *env, int csrno, target_ulong val) 465 { 466 if (env->priv_ver < PRIV_VERSION_1_10_0) { 467 return -1; 468 } 469 env->mcounteren = val; 470 return 0; 471 } 472 473 /* This regiser is replaced with CSR_MCOUNTINHIBIT in 1.11.0 */ 474 static int read_mscounteren(CPURISCVState *env, int csrno, target_ulong *val) 475 { 476 if (env->priv_ver > PRIV_VERSION_1_09_1 477 && env->priv_ver < PRIV_VERSION_1_11_0) { 478 return -1; 479 } 480 *val = env->mcounteren; 481 return 0; 482 } 483 484 /* This regiser is replaced with CSR_MCOUNTINHIBIT in 1.11.0 */ 485 static int write_mscounteren(CPURISCVState *env, int csrno, target_ulong val) 486 { 487 if (env->priv_ver > PRIV_VERSION_1_09_1 488 && env->priv_ver < PRIV_VERSION_1_11_0) { 489 return -1; 490 } 491 env->mcounteren = val; 492 return 0; 493 } 494 495 static int read_mucounteren(CPURISCVState *env, int csrno, target_ulong *val) 496 { 497 if (env->priv_ver > PRIV_VERSION_1_09_1) { 498 return -1; 499 } 500 *val = env->scounteren; 501 return 0; 502 } 503 504 static int write_mucounteren(CPURISCVState *env, int csrno, target_ulong val) 505 { 506 if (env->priv_ver > PRIV_VERSION_1_09_1) { 507 return -1; 508 } 509 env->scounteren = val; 510 return 0; 511 } 512 513 /* Machine Trap Handling */ 514 static int read_mscratch(CPURISCVState *env, int csrno, target_ulong *val) 515 { 516 *val = env->mscratch; 517 return 0; 518 } 519 520 static int write_mscratch(CPURISCVState *env, int csrno, target_ulong val) 521 { 522 env->mscratch = val; 523 return 0; 524 } 525 526 static int read_mepc(CPURISCVState *env, int csrno, target_ulong *val) 527 { 528 *val = env->mepc; 529 return 0; 530 } 531 532 static int write_mepc(CPURISCVState *env, int csrno, target_ulong val) 533 { 534 env->mepc = val; 535 return 0; 536 } 537 538 static int read_mcause(CPURISCVState *env, int csrno, target_ulong *val) 539 { 540 *val = env->mcause; 541 return 0; 542 } 543 544 static int write_mcause(CPURISCVState *env, int csrno, target_ulong val) 545 { 546 env->mcause = val; 547 return 0; 548 } 549 550 static int read_mbadaddr(CPURISCVState *env, int csrno, target_ulong *val) 551 { 552 *val = env->mbadaddr; 553 return 0; 554 } 555 556 static int write_mbadaddr(CPURISCVState *env, int csrno, target_ulong val) 557 { 558 env->mbadaddr = val; 559 return 0; 560 } 561 562 static int rmw_mip(CPURISCVState *env, int csrno, target_ulong *ret_value, 563 target_ulong new_value, target_ulong write_mask) 564 { 565 RISCVCPU *cpu = env_archcpu(env); 566 /* Allow software control of delegable interrupts not claimed by hardware */ 567 target_ulong mask = write_mask & delegable_ints & ~env->miclaim; 568 uint32_t old_mip; 569 570 if (mask) { 571 old_mip = riscv_cpu_update_mip(cpu, mask, (new_value & mask)); 572 } else { 573 old_mip = atomic_read(&env->mip); 574 } 575 576 if (ret_value) { 577 *ret_value = old_mip; 578 } 579 580 return 0; 581 } 582 583 /* Supervisor Trap Setup */ 584 static int read_sstatus(CPURISCVState *env, int csrno, target_ulong *val) 585 { 586 target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ? 587 sstatus_v1_10_mask : sstatus_v1_9_mask); 588 *val = env->mstatus & mask; 589 return 0; 590 } 591 592 static int write_sstatus(CPURISCVState *env, int csrno, target_ulong val) 593 { 594 target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ? 595 sstatus_v1_10_mask : sstatus_v1_9_mask); 596 target_ulong newval = (env->mstatus & ~mask) | (val & mask); 597 return write_mstatus(env, CSR_MSTATUS, newval); 598 } 599 600 static int read_sie(CPURISCVState *env, int csrno, target_ulong *val) 601 { 602 *val = env->mie & env->mideleg; 603 return 0; 604 } 605 606 static int write_sie(CPURISCVState *env, int csrno, target_ulong val) 607 { 608 target_ulong newval = (env->mie & ~env->mideleg) | (val & env->mideleg); 609 return write_mie(env, CSR_MIE, newval); 610 } 611 612 static int read_stvec(CPURISCVState *env, int csrno, target_ulong *val) 613 { 614 *val = env->stvec; 615 return 0; 616 } 617 618 static int write_stvec(CPURISCVState *env, int csrno, target_ulong val) 619 { 620 /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */ 621 if ((val & 3) < 2) { 622 env->stvec = val; 623 } else { 624 qemu_log_mask(LOG_UNIMP, "CSR_STVEC: reserved mode not supported\n"); 625 } 626 return 0; 627 } 628 629 static int read_scounteren(CPURISCVState *env, int csrno, target_ulong *val) 630 { 631 if (env->priv_ver < PRIV_VERSION_1_10_0) { 632 return -1; 633 } 634 *val = env->scounteren; 635 return 0; 636 } 637 638 static int write_scounteren(CPURISCVState *env, int csrno, target_ulong val) 639 { 640 if (env->priv_ver < PRIV_VERSION_1_10_0) { 641 return -1; 642 } 643 env->scounteren = val; 644 return 0; 645 } 646 647 /* Supervisor Trap Handling */ 648 static int read_sscratch(CPURISCVState *env, int csrno, target_ulong *val) 649 { 650 *val = env->sscratch; 651 return 0; 652 } 653 654 static int write_sscratch(CPURISCVState *env, int csrno, target_ulong val) 655 { 656 env->sscratch = val; 657 return 0; 658 } 659 660 static int read_sepc(CPURISCVState *env, int csrno, target_ulong *val) 661 { 662 *val = env->sepc; 663 return 0; 664 } 665 666 static int write_sepc(CPURISCVState *env, int csrno, target_ulong val) 667 { 668 env->sepc = val; 669 return 0; 670 } 671 672 static int read_scause(CPURISCVState *env, int csrno, target_ulong *val) 673 { 674 *val = env->scause; 675 return 0; 676 } 677 678 static int write_scause(CPURISCVState *env, int csrno, target_ulong val) 679 { 680 env->scause = val; 681 return 0; 682 } 683 684 static int read_sbadaddr(CPURISCVState *env, int csrno, target_ulong *val) 685 { 686 *val = env->sbadaddr; 687 return 0; 688 } 689 690 static int write_sbadaddr(CPURISCVState *env, int csrno, target_ulong val) 691 { 692 env->sbadaddr = val; 693 return 0; 694 } 695 696 static int rmw_sip(CPURISCVState *env, int csrno, target_ulong *ret_value, 697 target_ulong new_value, target_ulong write_mask) 698 { 699 int ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value, 700 write_mask & env->mideleg & sip_writable_mask); 701 *ret_value &= env->mideleg; 702 return ret; 703 } 704 705 /* Supervisor Protection and Translation */ 706 static int read_satp(CPURISCVState *env, int csrno, target_ulong *val) 707 { 708 if (!riscv_feature(env, RISCV_FEATURE_MMU)) { 709 *val = 0; 710 } else if (env->priv_ver >= PRIV_VERSION_1_10_0) { 711 if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) { 712 return -1; 713 } else { 714 *val = env->satp; 715 } 716 } else { 717 *val = env->sptbr; 718 } 719 return 0; 720 } 721 722 static int write_satp(CPURISCVState *env, int csrno, target_ulong val) 723 { 724 if (!riscv_feature(env, RISCV_FEATURE_MMU)) { 725 return 0; 726 } 727 if (env->priv_ver <= PRIV_VERSION_1_09_1 && (val ^ env->sptbr)) { 728 tlb_flush(env_cpu(env)); 729 env->sptbr = val & (((target_ulong) 730 1 << (TARGET_PHYS_ADDR_SPACE_BITS - PGSHIFT)) - 1); 731 } 732 if (env->priv_ver >= PRIV_VERSION_1_10_0 && 733 validate_vm(env, get_field(val, SATP_MODE)) && 734 ((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN))) 735 { 736 if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) { 737 return -1; 738 } else { 739 if((val ^ env->satp) & SATP_ASID) { 740 tlb_flush(env_cpu(env)); 741 } 742 env->satp = val; 743 } 744 } 745 return 0; 746 } 747 748 /* Physical Memory Protection */ 749 static int read_pmpcfg(CPURISCVState *env, int csrno, target_ulong *val) 750 { 751 *val = pmpcfg_csr_read(env, csrno - CSR_PMPCFG0); 752 return 0; 753 } 754 755 static int write_pmpcfg(CPURISCVState *env, int csrno, target_ulong val) 756 { 757 pmpcfg_csr_write(env, csrno - CSR_PMPCFG0, val); 758 return 0; 759 } 760 761 static int read_pmpaddr(CPURISCVState *env, int csrno, target_ulong *val) 762 { 763 *val = pmpaddr_csr_read(env, csrno - CSR_PMPADDR0); 764 return 0; 765 } 766 767 static int write_pmpaddr(CPURISCVState *env, int csrno, target_ulong val) 768 { 769 pmpaddr_csr_write(env, csrno - CSR_PMPADDR0, val); 770 return 0; 771 } 772 773 #endif 774 775 /* 776 * riscv_csrrw - read and/or update control and status register 777 * 778 * csrr <-> riscv_csrrw(env, csrno, ret_value, 0, 0); 779 * csrrw <-> riscv_csrrw(env, csrno, ret_value, value, -1); 780 * csrrs <-> riscv_csrrw(env, csrno, ret_value, -1, value); 781 * csrrc <-> riscv_csrrw(env, csrno, ret_value, 0, value); 782 */ 783 784 int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value, 785 target_ulong new_value, target_ulong write_mask) 786 { 787 int ret; 788 target_ulong old_value; 789 790 /* check privileges and return -1 if check fails */ 791 #if !defined(CONFIG_USER_ONLY) 792 int csr_priv = get_field(csrno, 0x300); 793 int read_only = get_field(csrno, 0xC00) == 3; 794 if ((write_mask && read_only) || (env->priv < csr_priv)) { 795 return -1; 796 } 797 #endif 798 799 /* check predicate */ 800 if (!csr_ops[csrno].predicate || csr_ops[csrno].predicate(env, csrno) < 0) { 801 return -1; 802 } 803 804 /* execute combined read/write operation if it exists */ 805 if (csr_ops[csrno].op) { 806 return csr_ops[csrno].op(env, csrno, ret_value, new_value, write_mask); 807 } 808 809 /* if no accessor exists then return failure */ 810 if (!csr_ops[csrno].read) { 811 return -1; 812 } 813 814 /* read old value */ 815 ret = csr_ops[csrno].read(env, csrno, &old_value); 816 if (ret < 0) { 817 return ret; 818 } 819 820 /* write value if writable and write mask set, otherwise drop writes */ 821 if (write_mask) { 822 new_value = (old_value & ~write_mask) | (new_value & write_mask); 823 if (csr_ops[csrno].write) { 824 ret = csr_ops[csrno].write(env, csrno, new_value); 825 if (ret < 0) { 826 return ret; 827 } 828 } 829 } 830 831 /* return old value */ 832 if (ret_value) { 833 *ret_value = old_value; 834 } 835 836 return 0; 837 } 838 839 /* 840 * Debugger support. If not in user mode, set env->debugger before the 841 * riscv_csrrw call and clear it after the call. 842 */ 843 int riscv_csrrw_debug(CPURISCVState *env, int csrno, target_ulong *ret_value, 844 target_ulong new_value, target_ulong write_mask) 845 { 846 int ret; 847 #if !defined(CONFIG_USER_ONLY) 848 env->debugger = true; 849 #endif 850 ret = riscv_csrrw(env, csrno, ret_value, new_value, write_mask); 851 #if !defined(CONFIG_USER_ONLY) 852 env->debugger = false; 853 #endif 854 return ret; 855 } 856 857 /* Control and Status Register function table */ 858 static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { 859 /* User Floating-Point CSRs */ 860 [CSR_FFLAGS] = { fs, read_fflags, write_fflags }, 861 [CSR_FRM] = { fs, read_frm, write_frm }, 862 [CSR_FCSR] = { fs, read_fcsr, write_fcsr }, 863 864 /* User Timers and Counters */ 865 [CSR_CYCLE] = { ctr, read_instret }, 866 [CSR_INSTRET] = { ctr, read_instret }, 867 #if defined(TARGET_RISCV32) 868 [CSR_CYCLEH] = { ctr, read_instreth }, 869 [CSR_INSTRETH] = { ctr, read_instreth }, 870 #endif 871 872 /* User-level time CSRs are only available in linux-user 873 * In privileged mode, the monitor emulates these CSRs */ 874 #if defined(CONFIG_USER_ONLY) 875 [CSR_TIME] = { ctr, read_time }, 876 #if defined(TARGET_RISCV32) 877 [CSR_TIMEH] = { ctr, read_timeh }, 878 #endif 879 #endif 880 881 #if !defined(CONFIG_USER_ONLY) 882 /* Machine Timers and Counters */ 883 [CSR_MCYCLE] = { any, read_instret }, 884 [CSR_MINSTRET] = { any, read_instret }, 885 #if defined(TARGET_RISCV32) 886 [CSR_MCYCLEH] = { any, read_instreth }, 887 [CSR_MINSTRETH] = { any, read_instreth }, 888 #endif 889 890 /* Machine Information Registers */ 891 [CSR_MVENDORID] = { any, read_zero }, 892 [CSR_MARCHID] = { any, read_zero }, 893 [CSR_MIMPID] = { any, read_zero }, 894 [CSR_MHARTID] = { any, read_mhartid }, 895 896 /* Machine Trap Setup */ 897 [CSR_MSTATUS] = { any, read_mstatus, write_mstatus }, 898 [CSR_MISA] = { any, read_misa, write_misa }, 899 [CSR_MIDELEG] = { any, read_mideleg, write_mideleg }, 900 [CSR_MEDELEG] = { any, read_medeleg, write_medeleg }, 901 [CSR_MIE] = { any, read_mie, write_mie }, 902 [CSR_MTVEC] = { any, read_mtvec, write_mtvec }, 903 [CSR_MCOUNTEREN] = { any, read_mcounteren, write_mcounteren }, 904 905 /* Legacy Counter Setup (priv v1.9.1) */ 906 [CSR_MUCOUNTEREN] = { any, read_mucounteren, write_mucounteren }, 907 [CSR_MSCOUNTEREN] = { any, read_mscounteren, write_mscounteren }, 908 909 /* Machine Trap Handling */ 910 [CSR_MSCRATCH] = { any, read_mscratch, write_mscratch }, 911 [CSR_MEPC] = { any, read_mepc, write_mepc }, 912 [CSR_MCAUSE] = { any, read_mcause, write_mcause }, 913 [CSR_MBADADDR] = { any, read_mbadaddr, write_mbadaddr }, 914 [CSR_MIP] = { any, NULL, NULL, rmw_mip }, 915 916 /* Supervisor Trap Setup */ 917 [CSR_SSTATUS] = { smode, read_sstatus, write_sstatus }, 918 [CSR_SIE] = { smode, read_sie, write_sie }, 919 [CSR_STVEC] = { smode, read_stvec, write_stvec }, 920 [CSR_SCOUNTEREN] = { smode, read_scounteren, write_scounteren }, 921 922 /* Supervisor Trap Handling */ 923 [CSR_SSCRATCH] = { smode, read_sscratch, write_sscratch }, 924 [CSR_SEPC] = { smode, read_sepc, write_sepc }, 925 [CSR_SCAUSE] = { smode, read_scause, write_scause }, 926 [CSR_SBADADDR] = { smode, read_sbadaddr, write_sbadaddr }, 927 [CSR_SIP] = { smode, NULL, NULL, rmw_sip }, 928 929 /* Supervisor Protection and Translation */ 930 [CSR_SATP] = { smode, read_satp, write_satp }, 931 932 /* Physical Memory Protection */ 933 [CSR_PMPCFG0 ... CSR_PMPADDR9] = { pmp, read_pmpcfg, write_pmpcfg }, 934 [CSR_PMPADDR0 ... CSR_PMPADDR15] = { pmp, read_pmpaddr, write_pmpaddr }, 935 936 /* Performance Counters */ 937 [CSR_HPMCOUNTER3 ... CSR_HPMCOUNTER31] = { ctr, read_zero }, 938 [CSR_MHPMCOUNTER3 ... CSR_MHPMCOUNTER31] = { any, read_zero }, 939 [CSR_MHPMEVENT3 ... CSR_MHPMEVENT31] = { any, read_zero }, 940 #if defined(TARGET_RISCV32) 941 [CSR_HPMCOUNTER3H ... CSR_HPMCOUNTER31H] = { ctr, read_zero }, 942 [CSR_MHPMCOUNTER3H ... CSR_MHPMCOUNTER31H] = { any, read_zero }, 943 #endif 944 #endif /* !CONFIG_USER_ONLY */ 945 }; 946