1 /* 2 * RISC-V Emulation Helpers for QEMU. 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 #include "exec/helper-proto.h" 26 27 #ifndef CONFIG_USER_ONLY 28 29 #if defined(TARGET_RISCV32) 30 static const char valid_vm_1_09[16] = { 31 [VM_1_09_MBARE] = 1, 32 [VM_1_09_SV32] = 1, 33 }; 34 static const char valid_vm_1_10[16] = { 35 [VM_1_10_MBARE] = 1, 36 [VM_1_10_SV32] = 1 37 }; 38 #elif defined(TARGET_RISCV64) 39 static const char valid_vm_1_09[16] = { 40 [VM_1_09_MBARE] = 1, 41 [VM_1_09_SV39] = 1, 42 [VM_1_09_SV48] = 1, 43 }; 44 static const char valid_vm_1_10[16] = { 45 [VM_1_10_MBARE] = 1, 46 [VM_1_10_SV39] = 1, 47 [VM_1_10_SV48] = 1, 48 [VM_1_10_SV57] = 1 49 }; 50 #endif 51 52 static int validate_vm(CPURISCVState *env, target_ulong vm) 53 { 54 return (env->priv_ver >= PRIV_VERSION_1_10_0) ? 55 valid_vm_1_10[vm & 0xf] : valid_vm_1_09[vm & 0xf]; 56 } 57 58 #endif 59 60 /* Exceptions processing helpers */ 61 void QEMU_NORETURN do_raise_exception_err(CPURISCVState *env, 62 uint32_t exception, uintptr_t pc) 63 { 64 CPUState *cs = CPU(riscv_env_get_cpu(env)); 65 qemu_log_mask(CPU_LOG_INT, "%s: %d\n", __func__, exception); 66 cs->exception_index = exception; 67 cpu_loop_exit_restore(cs, pc); 68 } 69 70 void helper_raise_exception(CPURISCVState *env, uint32_t exception) 71 { 72 do_raise_exception_err(env, exception, 0); 73 } 74 75 static void validate_mstatus_fs(CPURISCVState *env, uintptr_t ra) 76 { 77 #ifndef CONFIG_USER_ONLY 78 if (!(env->mstatus & MSTATUS_FS)) { 79 do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, ra); 80 } 81 #endif 82 } 83 84 /* 85 * Handle writes to CSRs and any resulting special behavior 86 * 87 * Adapted from Spike's processor_t::set_csr 88 */ 89 void csr_write_helper(CPURISCVState *env, target_ulong val_to_write, 90 target_ulong csrno) 91 { 92 #ifndef CONFIG_USER_ONLY 93 uint64_t delegable_ints = MIP_SSIP | MIP_STIP | MIP_SEIP | (1 << IRQ_X_COP); 94 uint64_t all_ints = delegable_ints | MIP_MSIP | MIP_MTIP; 95 #endif 96 97 switch (csrno) { 98 case CSR_FFLAGS: 99 validate_mstatus_fs(env, GETPC()); 100 cpu_riscv_set_fflags(env, val_to_write & (FSR_AEXC >> FSR_AEXC_SHIFT)); 101 break; 102 case CSR_FRM: 103 validate_mstatus_fs(env, GETPC()); 104 env->frm = val_to_write & (FSR_RD >> FSR_RD_SHIFT); 105 break; 106 case CSR_FCSR: 107 validate_mstatus_fs(env, GETPC()); 108 env->frm = (val_to_write & FSR_RD) >> FSR_RD_SHIFT; 109 cpu_riscv_set_fflags(env, (val_to_write & FSR_AEXC) >> FSR_AEXC_SHIFT); 110 break; 111 #ifndef CONFIG_USER_ONLY 112 case CSR_MSTATUS: { 113 target_ulong mstatus = env->mstatus; 114 target_ulong mask = 0; 115 target_ulong mpp = get_field(val_to_write, MSTATUS_MPP); 116 117 /* flush tlb on mstatus fields that affect VM */ 118 if (env->priv_ver <= PRIV_VERSION_1_09_1) { 119 if ((val_to_write ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | 120 MSTATUS_MPRV | MSTATUS_SUM | MSTATUS_VM)) { 121 helper_tlb_flush(env); 122 } 123 mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE | 124 MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM | 125 MSTATUS_MPP | MSTATUS_MXR | 126 (validate_vm(env, get_field(val_to_write, MSTATUS_VM)) ? 127 MSTATUS_VM : 0); 128 } 129 if (env->priv_ver >= PRIV_VERSION_1_10_0) { 130 if ((val_to_write ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | 131 MSTATUS_MPRV | MSTATUS_SUM)) { 132 helper_tlb_flush(env); 133 } 134 mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE | 135 MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM | 136 MSTATUS_MPP | MSTATUS_MXR; 137 } 138 139 /* silenty discard mstatus.mpp writes for unsupported modes */ 140 if (mpp == PRV_H || 141 (!riscv_has_ext(env, RVS) && mpp == PRV_S) || 142 (!riscv_has_ext(env, RVU) && mpp == PRV_U)) { 143 mask &= ~MSTATUS_MPP; 144 } 145 146 mstatus = (mstatus & ~mask) | (val_to_write & mask); 147 148 /* Note: this is a workaround for an issue where mstatus.FS 149 does not report dirty after floating point operations 150 that modify floating point state. This workaround is 151 technically compliant with the RISC-V Privileged 152 specification as it is legal to return only off, or dirty. 153 at the expense of extra floating point save/restore. */ 154 155 /* FP is always dirty or off */ 156 if (mstatus & MSTATUS_FS) { 157 mstatus |= MSTATUS_FS; 158 } 159 160 int dirty = ((mstatus & MSTATUS_FS) == MSTATUS_FS) | 161 ((mstatus & MSTATUS_XS) == MSTATUS_XS); 162 mstatus = set_field(mstatus, MSTATUS_SD, dirty); 163 env->mstatus = mstatus; 164 break; 165 } 166 case CSR_MIP: { 167 /* 168 * Since the writeable bits in MIP are not set asynchrously by the 169 * CLINT, no additional locking is needed for read-modifiy-write 170 * CSR operations 171 */ 172 qemu_mutex_lock_iothread(); 173 RISCVCPU *cpu = riscv_env_get_cpu(env); 174 riscv_set_local_interrupt(cpu, MIP_SSIP, 175 (val_to_write & MIP_SSIP) != 0); 176 riscv_set_local_interrupt(cpu, MIP_STIP, 177 (val_to_write & MIP_STIP) != 0); 178 /* 179 * csrs, csrc on mip.SEIP is not decomposable into separate read and 180 * write steps, so a different implementation is needed 181 */ 182 qemu_mutex_unlock_iothread(); 183 break; 184 } 185 case CSR_MIE: { 186 env->mie = (env->mie & ~all_ints) | 187 (val_to_write & all_ints); 188 break; 189 } 190 case CSR_MIDELEG: 191 env->mideleg = (env->mideleg & ~delegable_ints) 192 | (val_to_write & delegable_ints); 193 break; 194 case CSR_MEDELEG: { 195 target_ulong mask = 0; 196 mask |= 1ULL << (RISCV_EXCP_INST_ADDR_MIS); 197 mask |= 1ULL << (RISCV_EXCP_INST_ACCESS_FAULT); 198 mask |= 1ULL << (RISCV_EXCP_ILLEGAL_INST); 199 mask |= 1ULL << (RISCV_EXCP_BREAKPOINT); 200 mask |= 1ULL << (RISCV_EXCP_LOAD_ADDR_MIS); 201 mask |= 1ULL << (RISCV_EXCP_LOAD_ACCESS_FAULT); 202 mask |= 1ULL << (RISCV_EXCP_STORE_AMO_ADDR_MIS); 203 mask |= 1ULL << (RISCV_EXCP_STORE_AMO_ACCESS_FAULT); 204 mask |= 1ULL << (RISCV_EXCP_U_ECALL); 205 mask |= 1ULL << (RISCV_EXCP_S_ECALL); 206 mask |= 1ULL << (RISCV_EXCP_H_ECALL); 207 mask |= 1ULL << (RISCV_EXCP_M_ECALL); 208 mask |= 1ULL << (RISCV_EXCP_INST_PAGE_FAULT); 209 mask |= 1ULL << (RISCV_EXCP_LOAD_PAGE_FAULT); 210 mask |= 1ULL << (RISCV_EXCP_STORE_PAGE_FAULT); 211 env->medeleg = (env->medeleg & ~mask) 212 | (val_to_write & mask); 213 break; 214 } 215 case CSR_MINSTRET: 216 qemu_log_mask(LOG_UNIMP, "CSR_MINSTRET: write not implemented"); 217 goto do_illegal; 218 case CSR_MCYCLE: 219 qemu_log_mask(LOG_UNIMP, "CSR_MCYCLE: write not implemented"); 220 goto do_illegal; 221 case CSR_MINSTRETH: 222 qemu_log_mask(LOG_UNIMP, "CSR_MINSTRETH: write not implemented"); 223 goto do_illegal; 224 case CSR_MCYCLEH: 225 qemu_log_mask(LOG_UNIMP, "CSR_MCYCLEH: write not implemented"); 226 goto do_illegal; 227 case CSR_MUCOUNTEREN: 228 env->mucounteren = val_to_write; 229 break; 230 case CSR_MSCOUNTEREN: 231 env->mscounteren = val_to_write; 232 break; 233 case CSR_SSTATUS: { 234 target_ulong ms = env->mstatus; 235 target_ulong mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_UIE 236 | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS 237 | SSTATUS_SUM | SSTATUS_MXR | SSTATUS_SD; 238 ms = (ms & ~mask) | (val_to_write & mask); 239 csr_write_helper(env, ms, CSR_MSTATUS); 240 break; 241 } 242 case CSR_SIP: { 243 qemu_mutex_lock_iothread(); 244 target_ulong next_mip = (env->mip & ~env->mideleg) 245 | (val_to_write & env->mideleg); 246 qemu_mutex_unlock_iothread(); 247 csr_write_helper(env, next_mip, CSR_MIP); 248 break; 249 } 250 case CSR_SIE: { 251 target_ulong next_mie = (env->mie & ~env->mideleg) 252 | (val_to_write & env->mideleg); 253 csr_write_helper(env, next_mie, CSR_MIE); 254 break; 255 } 256 case CSR_SATP: /* CSR_SPTBR */ { 257 if (!riscv_feature(env, RISCV_FEATURE_MMU)) { 258 goto do_illegal; 259 } 260 if (env->priv_ver <= PRIV_VERSION_1_09_1 && (val_to_write ^ env->sptbr)) 261 { 262 helper_tlb_flush(env); 263 env->sptbr = val_to_write & (((target_ulong) 264 1 << (TARGET_PHYS_ADDR_SPACE_BITS - PGSHIFT)) - 1); 265 } 266 if (env->priv_ver >= PRIV_VERSION_1_10_0 && 267 validate_vm(env, get_field(val_to_write, SATP_MODE)) && 268 ((val_to_write ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN))) 269 { 270 helper_tlb_flush(env); 271 env->satp = val_to_write; 272 } 273 break; 274 } 275 case CSR_SEPC: 276 env->sepc = val_to_write; 277 break; 278 case CSR_STVEC: 279 if (val_to_write & 1) { 280 qemu_log_mask(LOG_UNIMP, "CSR_STVEC: vectored traps not supported"); 281 goto do_illegal; 282 } 283 env->stvec = val_to_write >> 2 << 2; 284 break; 285 case CSR_SCOUNTEREN: 286 env->scounteren = val_to_write; 287 break; 288 case CSR_SSCRATCH: 289 env->sscratch = val_to_write; 290 break; 291 case CSR_SCAUSE: 292 env->scause = val_to_write; 293 break; 294 case CSR_SBADADDR: 295 env->sbadaddr = val_to_write; 296 break; 297 case CSR_MEPC: 298 env->mepc = val_to_write; 299 break; 300 case CSR_MTVEC: 301 if (val_to_write & 1) { 302 qemu_log_mask(LOG_UNIMP, "CSR_MTVEC: vectored traps not supported"); 303 goto do_illegal; 304 } 305 env->mtvec = val_to_write >> 2 << 2; 306 break; 307 case CSR_MCOUNTEREN: 308 env->mcounteren = val_to_write; 309 break; 310 case CSR_MSCRATCH: 311 env->mscratch = val_to_write; 312 break; 313 case CSR_MCAUSE: 314 env->mcause = val_to_write; 315 break; 316 case CSR_MBADADDR: 317 env->mbadaddr = val_to_write; 318 break; 319 case CSR_MISA: { 320 qemu_log_mask(LOG_UNIMP, "CSR_MISA: misa writes not supported"); 321 goto do_illegal; 322 } 323 case CSR_PMPCFG0: 324 case CSR_PMPCFG1: 325 case CSR_PMPCFG2: 326 case CSR_PMPCFG3: 327 pmpcfg_csr_write(env, csrno - CSR_PMPCFG0, val_to_write); 328 break; 329 case CSR_PMPADDR0: 330 case CSR_PMPADDR1: 331 case CSR_PMPADDR2: 332 case CSR_PMPADDR3: 333 case CSR_PMPADDR4: 334 case CSR_PMPADDR5: 335 case CSR_PMPADDR6: 336 case CSR_PMPADDR7: 337 case CSR_PMPADDR8: 338 case CSR_PMPADDR9: 339 case CSR_PMPADDR10: 340 case CSR_PMPADDR11: 341 case CSR_PMPADDR12: 342 case CSR_PMPADDR13: 343 case CSR_PMPADDR14: 344 case CSR_PMPADDR15: 345 pmpaddr_csr_write(env, csrno - CSR_PMPADDR0, val_to_write); 346 break; 347 do_illegal: 348 #endif 349 default: 350 do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); 351 } 352 } 353 354 /* 355 * Handle reads to CSRs and any resulting special behavior 356 * 357 * Adapted from Spike's processor_t::get_csr 358 */ 359 target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno) 360 { 361 #ifndef CONFIG_USER_ONLY 362 target_ulong ctr_en = env->priv == PRV_U ? env->mucounteren : 363 env->priv == PRV_S ? env->mscounteren : -1U; 364 #else 365 target_ulong ctr_en = -1; 366 #endif 367 target_ulong ctr_ok = (ctr_en >> (csrno & 31)) & 1; 368 369 if (csrno >= CSR_HPMCOUNTER3 && csrno <= CSR_HPMCOUNTER31) { 370 if (ctr_ok) { 371 return 0; 372 } 373 } 374 #if defined(TARGET_RISCV32) 375 if (csrno >= CSR_HPMCOUNTER3H && csrno <= CSR_HPMCOUNTER31H) { 376 if (ctr_ok) { 377 return 0; 378 } 379 } 380 #endif 381 if (csrno >= CSR_MHPMCOUNTER3 && csrno <= CSR_MHPMCOUNTER31) { 382 return 0; 383 } 384 #if defined(TARGET_RISCV32) 385 if (csrno >= CSR_MHPMCOUNTER3 && csrno <= CSR_MHPMCOUNTER31) { 386 return 0; 387 } 388 #endif 389 if (csrno >= CSR_MHPMEVENT3 && csrno <= CSR_MHPMEVENT31) { 390 return 0; 391 } 392 393 switch (csrno) { 394 case CSR_FFLAGS: 395 validate_mstatus_fs(env, GETPC()); 396 return cpu_riscv_get_fflags(env); 397 case CSR_FRM: 398 validate_mstatus_fs(env, GETPC()); 399 return env->frm; 400 case CSR_FCSR: 401 validate_mstatus_fs(env, GETPC()); 402 return (cpu_riscv_get_fflags(env) << FSR_AEXC_SHIFT) 403 | (env->frm << FSR_RD_SHIFT); 404 /* rdtime/rdtimeh is trapped and emulated by bbl in system mode */ 405 #ifdef CONFIG_USER_ONLY 406 case CSR_TIME: 407 return cpu_get_host_ticks(); 408 #if defined(TARGET_RISCV32) 409 case CSR_TIMEH: 410 return cpu_get_host_ticks() >> 32; 411 #endif 412 #endif 413 case CSR_INSTRET: 414 case CSR_CYCLE: 415 if (ctr_ok) { 416 return cpu_get_host_ticks(); 417 } 418 break; 419 #if defined(TARGET_RISCV32) 420 case CSR_INSTRETH: 421 case CSR_CYCLEH: 422 if (ctr_ok) { 423 return cpu_get_host_ticks() >> 32; 424 } 425 break; 426 #endif 427 #ifndef CONFIG_USER_ONLY 428 case CSR_MINSTRET: 429 case CSR_MCYCLE: 430 return cpu_get_host_ticks(); 431 case CSR_MINSTRETH: 432 case CSR_MCYCLEH: 433 #if defined(TARGET_RISCV32) 434 return cpu_get_host_ticks() >> 32; 435 #endif 436 break; 437 case CSR_MUCOUNTEREN: 438 return env->mucounteren; 439 case CSR_MSCOUNTEREN: 440 return env->mscounteren; 441 case CSR_SSTATUS: { 442 target_ulong mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_UIE 443 | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS 444 | SSTATUS_SUM | SSTATUS_SD; 445 if (env->priv_ver >= PRIV_VERSION_1_10_0) { 446 mask |= SSTATUS_MXR; 447 } 448 return env->mstatus & mask; 449 } 450 case CSR_SIP: { 451 qemu_mutex_lock_iothread(); 452 target_ulong tmp = env->mip & env->mideleg; 453 qemu_mutex_unlock_iothread(); 454 return tmp; 455 } 456 case CSR_SIE: 457 return env->mie & env->mideleg; 458 case CSR_SEPC: 459 return env->sepc; 460 case CSR_SBADADDR: 461 return env->sbadaddr; 462 case CSR_STVEC: 463 return env->stvec; 464 case CSR_SCOUNTEREN: 465 return env->scounteren; 466 case CSR_SCAUSE: 467 return env->scause; 468 case CSR_SPTBR: 469 if (env->priv_ver >= PRIV_VERSION_1_10_0) { 470 return env->satp; 471 } else { 472 return env->sptbr; 473 } 474 case CSR_SSCRATCH: 475 return env->sscratch; 476 case CSR_MSTATUS: 477 return env->mstatus; 478 case CSR_MIP: { 479 qemu_mutex_lock_iothread(); 480 target_ulong tmp = env->mip; 481 qemu_mutex_unlock_iothread(); 482 return tmp; 483 } 484 case CSR_MIE: 485 return env->mie; 486 case CSR_MEPC: 487 return env->mepc; 488 case CSR_MSCRATCH: 489 return env->mscratch; 490 case CSR_MCAUSE: 491 return env->mcause; 492 case CSR_MBADADDR: 493 return env->mbadaddr; 494 case CSR_MISA: 495 return env->misa; 496 case CSR_MARCHID: 497 return 0; /* as spike does */ 498 case CSR_MIMPID: 499 return 0; /* as spike does */ 500 case CSR_MVENDORID: 501 return 0; /* as spike does */ 502 case CSR_MHARTID: 503 return env->mhartid; 504 case CSR_MTVEC: 505 return env->mtvec; 506 case CSR_MCOUNTEREN: 507 return env->mcounteren; 508 case CSR_MEDELEG: 509 return env->medeleg; 510 case CSR_MIDELEG: 511 return env->mideleg; 512 case CSR_PMPCFG0: 513 case CSR_PMPCFG1: 514 case CSR_PMPCFG2: 515 case CSR_PMPCFG3: 516 return pmpcfg_csr_read(env, csrno - CSR_PMPCFG0); 517 case CSR_PMPADDR0: 518 case CSR_PMPADDR1: 519 case CSR_PMPADDR2: 520 case CSR_PMPADDR3: 521 case CSR_PMPADDR4: 522 case CSR_PMPADDR5: 523 case CSR_PMPADDR6: 524 case CSR_PMPADDR7: 525 case CSR_PMPADDR8: 526 case CSR_PMPADDR9: 527 case CSR_PMPADDR10: 528 case CSR_PMPADDR11: 529 case CSR_PMPADDR12: 530 case CSR_PMPADDR13: 531 case CSR_PMPADDR14: 532 case CSR_PMPADDR15: 533 return pmpaddr_csr_read(env, csrno - CSR_PMPADDR0); 534 #endif 535 } 536 /* used by e.g. MTIME read */ 537 do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); 538 } 539 540 /* 541 * Check that CSR access is allowed. 542 * 543 * Adapted from Spike's decode.h:validate_csr 544 */ 545 static void validate_csr(CPURISCVState *env, uint64_t which, 546 uint64_t write, uintptr_t ra) 547 { 548 #ifndef CONFIG_USER_ONLY 549 unsigned csr_priv = get_field((which), 0x300); 550 unsigned csr_read_only = get_field((which), 0xC00) == 3; 551 if (((write) && csr_read_only) || (env->priv < csr_priv)) { 552 do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, ra); 553 } 554 #endif 555 } 556 557 target_ulong helper_csrrw(CPURISCVState *env, target_ulong src, 558 target_ulong csr) 559 { 560 validate_csr(env, csr, 1, GETPC()); 561 uint64_t csr_backup = csr_read_helper(env, csr); 562 csr_write_helper(env, src, csr); 563 return csr_backup; 564 } 565 566 target_ulong helper_csrrs(CPURISCVState *env, target_ulong src, 567 target_ulong csr, target_ulong rs1_pass) 568 { 569 validate_csr(env, csr, rs1_pass != 0, GETPC()); 570 uint64_t csr_backup = csr_read_helper(env, csr); 571 if (rs1_pass != 0) { 572 csr_write_helper(env, src | csr_backup, csr); 573 } 574 return csr_backup; 575 } 576 577 target_ulong helper_csrrc(CPURISCVState *env, target_ulong src, 578 target_ulong csr, target_ulong rs1_pass) 579 { 580 validate_csr(env, csr, rs1_pass != 0, GETPC()); 581 uint64_t csr_backup = csr_read_helper(env, csr); 582 if (rs1_pass != 0) { 583 csr_write_helper(env, (~src) & csr_backup, csr); 584 } 585 return csr_backup; 586 } 587 588 #ifndef CONFIG_USER_ONLY 589 590 /* iothread_mutex must be held */ 591 void riscv_set_local_interrupt(RISCVCPU *cpu, target_ulong mask, int value) 592 { 593 target_ulong old_mip = cpu->env.mip; 594 cpu->env.mip = (old_mip & ~mask) | (value ? mask : 0); 595 596 if (cpu->env.mip && !old_mip) { 597 cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); 598 } else if (!cpu->env.mip && old_mip) { 599 cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); 600 } 601 } 602 603 void riscv_set_mode(CPURISCVState *env, target_ulong newpriv) 604 { 605 if (newpriv > PRV_M) { 606 g_assert_not_reached(); 607 } 608 if (newpriv == PRV_H) { 609 newpriv = PRV_U; 610 } 611 /* tlb_flush is unnecessary as mode is contained in mmu_idx */ 612 env->priv = newpriv; 613 } 614 615 target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb) 616 { 617 if (!(env->priv >= PRV_S)) { 618 do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); 619 } 620 621 target_ulong retpc = env->sepc; 622 if (!riscv_has_ext(env, RVC) && (retpc & 0x3)) { 623 do_raise_exception_err(env, RISCV_EXCP_INST_ADDR_MIS, GETPC()); 624 } 625 626 target_ulong mstatus = env->mstatus; 627 target_ulong prev_priv = get_field(mstatus, MSTATUS_SPP); 628 mstatus = set_field(mstatus, 629 env->priv_ver >= PRIV_VERSION_1_10_0 ? 630 MSTATUS_SIE : MSTATUS_UIE << prev_priv, 631 get_field(mstatus, MSTATUS_SPIE)); 632 mstatus = set_field(mstatus, MSTATUS_SPIE, 0); 633 mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U); 634 riscv_set_mode(env, prev_priv); 635 csr_write_helper(env, mstatus, CSR_MSTATUS); 636 637 return retpc; 638 } 639 640 target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb) 641 { 642 if (!(env->priv >= PRV_M)) { 643 do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); 644 } 645 646 target_ulong retpc = env->mepc; 647 if (!riscv_has_ext(env, RVC) && (retpc & 0x3)) { 648 do_raise_exception_err(env, RISCV_EXCP_INST_ADDR_MIS, GETPC()); 649 } 650 651 target_ulong mstatus = env->mstatus; 652 target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP); 653 mstatus = set_field(mstatus, 654 env->priv_ver >= PRIV_VERSION_1_10_0 ? 655 MSTATUS_MIE : MSTATUS_UIE << prev_priv, 656 get_field(mstatus, MSTATUS_MPIE)); 657 mstatus = set_field(mstatus, MSTATUS_MPIE, 0); 658 mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U); 659 riscv_set_mode(env, prev_priv); 660 csr_write_helper(env, mstatus, CSR_MSTATUS); 661 662 return retpc; 663 } 664 665 666 void helper_wfi(CPURISCVState *env) 667 { 668 CPUState *cs = CPU(riscv_env_get_cpu(env)); 669 670 cs->halted = 1; 671 cs->exception_index = EXCP_HLT; 672 cpu_loop_exit(cs); 673 } 674 675 void helper_tlb_flush(CPURISCVState *env) 676 { 677 RISCVCPU *cpu = riscv_env_get_cpu(env); 678 CPUState *cs = CPU(cpu); 679 tlb_flush(cs); 680 } 681 682 #endif /* !CONFIG_USER_ONLY */ 683