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 int dirty = (mstatus & MSTATUS_FS) == MSTATUS_FS; 148 dirty |= (mstatus & MSTATUS_XS) == MSTATUS_XS; 149 mstatus = set_field(mstatus, MSTATUS_SD, dirty); 150 env->mstatus = mstatus; 151 break; 152 } 153 case CSR_MIP: { 154 /* 155 * Since the writeable bits in MIP are not set asynchrously by the 156 * CLINT, no additional locking is needed for read-modifiy-write 157 * CSR operations 158 */ 159 qemu_mutex_lock_iothread(); 160 RISCVCPU *cpu = riscv_env_get_cpu(env); 161 riscv_set_local_interrupt(cpu, MIP_SSIP, 162 (val_to_write & MIP_SSIP) != 0); 163 riscv_set_local_interrupt(cpu, MIP_STIP, 164 (val_to_write & MIP_STIP) != 0); 165 /* 166 * csrs, csrc on mip.SEIP is not decomposable into separate read and 167 * write steps, so a different implementation is needed 168 */ 169 qemu_mutex_unlock_iothread(); 170 break; 171 } 172 case CSR_MIE: { 173 env->mie = (env->mie & ~all_ints) | 174 (val_to_write & all_ints); 175 break; 176 } 177 case CSR_MIDELEG: 178 env->mideleg = (env->mideleg & ~delegable_ints) 179 | (val_to_write & delegable_ints); 180 break; 181 case CSR_MEDELEG: { 182 target_ulong mask = 0; 183 mask |= 1ULL << (RISCV_EXCP_INST_ADDR_MIS); 184 mask |= 1ULL << (RISCV_EXCP_INST_ACCESS_FAULT); 185 mask |= 1ULL << (RISCV_EXCP_ILLEGAL_INST); 186 mask |= 1ULL << (RISCV_EXCP_BREAKPOINT); 187 mask |= 1ULL << (RISCV_EXCP_LOAD_ADDR_MIS); 188 mask |= 1ULL << (RISCV_EXCP_LOAD_ACCESS_FAULT); 189 mask |= 1ULL << (RISCV_EXCP_STORE_AMO_ADDR_MIS); 190 mask |= 1ULL << (RISCV_EXCP_STORE_AMO_ACCESS_FAULT); 191 mask |= 1ULL << (RISCV_EXCP_U_ECALL); 192 mask |= 1ULL << (RISCV_EXCP_S_ECALL); 193 mask |= 1ULL << (RISCV_EXCP_H_ECALL); 194 mask |= 1ULL << (RISCV_EXCP_M_ECALL); 195 mask |= 1ULL << (RISCV_EXCP_INST_PAGE_FAULT); 196 mask |= 1ULL << (RISCV_EXCP_LOAD_PAGE_FAULT); 197 mask |= 1ULL << (RISCV_EXCP_STORE_PAGE_FAULT); 198 env->medeleg = (env->medeleg & ~mask) 199 | (val_to_write & mask); 200 break; 201 } 202 case CSR_MINSTRET: 203 qemu_log_mask(LOG_UNIMP, "CSR_MINSTRET: write not implemented"); 204 goto do_illegal; 205 case CSR_MCYCLE: 206 qemu_log_mask(LOG_UNIMP, "CSR_MCYCLE: write not implemented"); 207 goto do_illegal; 208 case CSR_MINSTRETH: 209 qemu_log_mask(LOG_UNIMP, "CSR_MINSTRETH: write not implemented"); 210 goto do_illegal; 211 case CSR_MCYCLEH: 212 qemu_log_mask(LOG_UNIMP, "CSR_MCYCLEH: write not implemented"); 213 goto do_illegal; 214 case CSR_MUCOUNTEREN: 215 env->mucounteren = val_to_write; 216 break; 217 case CSR_MSCOUNTEREN: 218 env->mscounteren = val_to_write; 219 break; 220 case CSR_SSTATUS: { 221 target_ulong ms = env->mstatus; 222 target_ulong mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_UIE 223 | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS 224 | SSTATUS_SUM | SSTATUS_MXR | SSTATUS_SD; 225 ms = (ms & ~mask) | (val_to_write & mask); 226 csr_write_helper(env, ms, CSR_MSTATUS); 227 break; 228 } 229 case CSR_SIP: { 230 qemu_mutex_lock_iothread(); 231 target_ulong next_mip = (env->mip & ~env->mideleg) 232 | (val_to_write & env->mideleg); 233 qemu_mutex_unlock_iothread(); 234 csr_write_helper(env, next_mip, CSR_MIP); 235 break; 236 } 237 case CSR_SIE: { 238 target_ulong next_mie = (env->mie & ~env->mideleg) 239 | (val_to_write & env->mideleg); 240 csr_write_helper(env, next_mie, CSR_MIE); 241 break; 242 } 243 case CSR_SATP: /* CSR_SPTBR */ { 244 if (!riscv_feature(env, RISCV_FEATURE_MMU)) { 245 goto do_illegal; 246 } 247 if (env->priv_ver <= PRIV_VERSION_1_09_1 && (val_to_write ^ env->sptbr)) 248 { 249 helper_tlb_flush(env); 250 env->sptbr = val_to_write & (((target_ulong) 251 1 << (TARGET_PHYS_ADDR_SPACE_BITS - PGSHIFT)) - 1); 252 } 253 if (env->priv_ver >= PRIV_VERSION_1_10_0 && 254 validate_vm(env, get_field(val_to_write, SATP_MODE)) && 255 ((val_to_write ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN))) 256 { 257 helper_tlb_flush(env); 258 env->satp = val_to_write; 259 } 260 break; 261 } 262 case CSR_SEPC: 263 env->sepc = val_to_write; 264 break; 265 case CSR_STVEC: 266 if (val_to_write & 1) { 267 qemu_log_mask(LOG_UNIMP, "CSR_STVEC: vectored traps not supported"); 268 goto do_illegal; 269 } 270 env->stvec = val_to_write >> 2 << 2; 271 break; 272 case CSR_SCOUNTEREN: 273 env->scounteren = val_to_write; 274 break; 275 case CSR_SSCRATCH: 276 env->sscratch = val_to_write; 277 break; 278 case CSR_SCAUSE: 279 env->scause = val_to_write; 280 break; 281 case CSR_SBADADDR: 282 env->sbadaddr = val_to_write; 283 break; 284 case CSR_MEPC: 285 env->mepc = val_to_write; 286 break; 287 case CSR_MTVEC: 288 if (val_to_write & 1) { 289 qemu_log_mask(LOG_UNIMP, "CSR_MTVEC: vectored traps not supported"); 290 goto do_illegal; 291 } 292 env->mtvec = val_to_write >> 2 << 2; 293 break; 294 case CSR_MCOUNTEREN: 295 env->mcounteren = val_to_write; 296 break; 297 case CSR_MSCRATCH: 298 env->mscratch = val_to_write; 299 break; 300 case CSR_MCAUSE: 301 env->mcause = val_to_write; 302 break; 303 case CSR_MBADADDR: 304 env->mbadaddr = val_to_write; 305 break; 306 case CSR_MISA: { 307 qemu_log_mask(LOG_UNIMP, "CSR_MISA: misa writes not supported"); 308 goto do_illegal; 309 } 310 case CSR_PMPCFG0: 311 case CSR_PMPCFG1: 312 case CSR_PMPCFG2: 313 case CSR_PMPCFG3: 314 pmpcfg_csr_write(env, csrno - CSR_PMPCFG0, val_to_write); 315 break; 316 case CSR_PMPADDR0: 317 case CSR_PMPADDR1: 318 case CSR_PMPADDR2: 319 case CSR_PMPADDR3: 320 case CSR_PMPADDR4: 321 case CSR_PMPADDR5: 322 case CSR_PMPADDR6: 323 case CSR_PMPADDR7: 324 case CSR_PMPADDR8: 325 case CSR_PMPADDR9: 326 case CSR_PMPADDR10: 327 case CSR_PMPADDR11: 328 case CSR_PMPADDR12: 329 case CSR_PMPADDR13: 330 case CSR_PMPADDR14: 331 case CSR_PMPADDR15: 332 pmpaddr_csr_write(env, csrno - CSR_PMPADDR0, val_to_write); 333 break; 334 do_illegal: 335 #endif 336 default: 337 do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); 338 } 339 } 340 341 /* 342 * Handle reads to CSRs and any resulting special behavior 343 * 344 * Adapted from Spike's processor_t::get_csr 345 */ 346 target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno) 347 { 348 #ifndef CONFIG_USER_ONLY 349 target_ulong ctr_en = env->priv == PRV_U ? env->mucounteren : 350 env->priv == PRV_S ? env->mscounteren : -1U; 351 #else 352 target_ulong ctr_en = -1; 353 #endif 354 target_ulong ctr_ok = (ctr_en >> (csrno & 31)) & 1; 355 356 if (csrno >= CSR_HPMCOUNTER3 && csrno <= CSR_HPMCOUNTER31) { 357 if (ctr_ok) { 358 return 0; 359 } 360 } 361 #if defined(TARGET_RISCV32) 362 if (csrno >= CSR_HPMCOUNTER3H && csrno <= CSR_HPMCOUNTER31H) { 363 if (ctr_ok) { 364 return 0; 365 } 366 } 367 #endif 368 if (csrno >= CSR_MHPMCOUNTER3 && csrno <= CSR_MHPMCOUNTER31) { 369 return 0; 370 } 371 #if defined(TARGET_RISCV32) 372 if (csrno >= CSR_MHPMCOUNTER3 && csrno <= CSR_MHPMCOUNTER31) { 373 return 0; 374 } 375 #endif 376 if (csrno >= CSR_MHPMEVENT3 && csrno <= CSR_MHPMEVENT31) { 377 return 0; 378 } 379 380 switch (csrno) { 381 case CSR_FFLAGS: 382 validate_mstatus_fs(env, GETPC()); 383 return cpu_riscv_get_fflags(env); 384 case CSR_FRM: 385 validate_mstatus_fs(env, GETPC()); 386 return env->frm; 387 case CSR_FCSR: 388 validate_mstatus_fs(env, GETPC()); 389 return (cpu_riscv_get_fflags(env) << FSR_AEXC_SHIFT) 390 | (env->frm << FSR_RD_SHIFT); 391 /* rdtime/rdtimeh is trapped and emulated by bbl in system mode */ 392 #ifdef CONFIG_USER_ONLY 393 case CSR_TIME: 394 return cpu_get_host_ticks(); 395 #if defined(TARGET_RISCV32) 396 case CSR_TIMEH: 397 return cpu_get_host_ticks() >> 32; 398 #endif 399 #endif 400 case CSR_INSTRET: 401 case CSR_CYCLE: 402 if (ctr_ok) { 403 return cpu_get_host_ticks(); 404 } 405 break; 406 #if defined(TARGET_RISCV32) 407 case CSR_INSTRETH: 408 case CSR_CYCLEH: 409 if (ctr_ok) { 410 return cpu_get_host_ticks() >> 32; 411 } 412 break; 413 #endif 414 #ifndef CONFIG_USER_ONLY 415 case CSR_MINSTRET: 416 case CSR_MCYCLE: 417 return cpu_get_host_ticks(); 418 case CSR_MINSTRETH: 419 case CSR_MCYCLEH: 420 #if defined(TARGET_RISCV32) 421 return cpu_get_host_ticks() >> 32; 422 #endif 423 break; 424 case CSR_MUCOUNTEREN: 425 return env->mucounteren; 426 case CSR_MSCOUNTEREN: 427 return env->mscounteren; 428 case CSR_SSTATUS: { 429 target_ulong mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_UIE 430 | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS 431 | SSTATUS_SUM | SSTATUS_SD; 432 if (env->priv_ver >= PRIV_VERSION_1_10_0) { 433 mask |= SSTATUS_MXR; 434 } 435 return env->mstatus & mask; 436 } 437 case CSR_SIP: { 438 qemu_mutex_lock_iothread(); 439 target_ulong tmp = env->mip & env->mideleg; 440 qemu_mutex_unlock_iothread(); 441 return tmp; 442 } 443 case CSR_SIE: 444 return env->mie & env->mideleg; 445 case CSR_SEPC: 446 return env->sepc; 447 case CSR_SBADADDR: 448 return env->sbadaddr; 449 case CSR_STVEC: 450 return env->stvec; 451 case CSR_SCOUNTEREN: 452 return env->scounteren; 453 case CSR_SCAUSE: 454 return env->scause; 455 case CSR_SPTBR: 456 if (env->priv_ver >= PRIV_VERSION_1_10_0) { 457 return env->satp; 458 } else { 459 return env->sptbr; 460 } 461 case CSR_SSCRATCH: 462 return env->sscratch; 463 case CSR_MSTATUS: 464 return env->mstatus; 465 case CSR_MIP: { 466 qemu_mutex_lock_iothread(); 467 target_ulong tmp = env->mip; 468 qemu_mutex_unlock_iothread(); 469 return tmp; 470 } 471 case CSR_MIE: 472 return env->mie; 473 case CSR_MEPC: 474 return env->mepc; 475 case CSR_MSCRATCH: 476 return env->mscratch; 477 case CSR_MCAUSE: 478 return env->mcause; 479 case CSR_MBADADDR: 480 return env->mbadaddr; 481 case CSR_MISA: 482 return env->misa; 483 case CSR_MARCHID: 484 return 0; /* as spike does */ 485 case CSR_MIMPID: 486 return 0; /* as spike does */ 487 case CSR_MVENDORID: 488 return 0; /* as spike does */ 489 case CSR_MHARTID: 490 return env->mhartid; 491 case CSR_MTVEC: 492 return env->mtvec; 493 case CSR_MCOUNTEREN: 494 return env->mcounteren; 495 case CSR_MEDELEG: 496 return env->medeleg; 497 case CSR_MIDELEG: 498 return env->mideleg; 499 case CSR_PMPCFG0: 500 case CSR_PMPCFG1: 501 case CSR_PMPCFG2: 502 case CSR_PMPCFG3: 503 return pmpcfg_csr_read(env, csrno - CSR_PMPCFG0); 504 case CSR_PMPADDR0: 505 case CSR_PMPADDR1: 506 case CSR_PMPADDR2: 507 case CSR_PMPADDR3: 508 case CSR_PMPADDR4: 509 case CSR_PMPADDR5: 510 case CSR_PMPADDR6: 511 case CSR_PMPADDR7: 512 case CSR_PMPADDR8: 513 case CSR_PMPADDR9: 514 case CSR_PMPADDR10: 515 case CSR_PMPADDR11: 516 case CSR_PMPADDR12: 517 case CSR_PMPADDR13: 518 case CSR_PMPADDR14: 519 case CSR_PMPADDR15: 520 return pmpaddr_csr_read(env, csrno - CSR_PMPADDR0); 521 #endif 522 } 523 /* used by e.g. MTIME read */ 524 do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); 525 } 526 527 /* 528 * Check that CSR access is allowed. 529 * 530 * Adapted from Spike's decode.h:validate_csr 531 */ 532 static void validate_csr(CPURISCVState *env, uint64_t which, 533 uint64_t write, uintptr_t ra) 534 { 535 #ifndef CONFIG_USER_ONLY 536 unsigned csr_priv = get_field((which), 0x300); 537 unsigned csr_read_only = get_field((which), 0xC00) == 3; 538 if (((write) && csr_read_only) || (env->priv < csr_priv)) { 539 do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, ra); 540 } 541 #endif 542 } 543 544 target_ulong helper_csrrw(CPURISCVState *env, target_ulong src, 545 target_ulong csr) 546 { 547 validate_csr(env, csr, 1, GETPC()); 548 uint64_t csr_backup = csr_read_helper(env, csr); 549 csr_write_helper(env, src, csr); 550 return csr_backup; 551 } 552 553 target_ulong helper_csrrs(CPURISCVState *env, target_ulong src, 554 target_ulong csr, target_ulong rs1_pass) 555 { 556 validate_csr(env, csr, rs1_pass != 0, GETPC()); 557 uint64_t csr_backup = csr_read_helper(env, csr); 558 if (rs1_pass != 0) { 559 csr_write_helper(env, src | csr_backup, csr); 560 } 561 return csr_backup; 562 } 563 564 target_ulong helper_csrrc(CPURISCVState *env, target_ulong src, 565 target_ulong csr, target_ulong rs1_pass) 566 { 567 validate_csr(env, csr, rs1_pass != 0, GETPC()); 568 uint64_t csr_backup = csr_read_helper(env, csr); 569 if (rs1_pass != 0) { 570 csr_write_helper(env, (~src) & csr_backup, csr); 571 } 572 return csr_backup; 573 } 574 575 #ifndef CONFIG_USER_ONLY 576 577 /* iothread_mutex must be held */ 578 void riscv_set_local_interrupt(RISCVCPU *cpu, target_ulong mask, int value) 579 { 580 target_ulong old_mip = cpu->env.mip; 581 cpu->env.mip = (old_mip & ~mask) | (value ? mask : 0); 582 583 if (cpu->env.mip && !old_mip) { 584 cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); 585 } else if (!cpu->env.mip && old_mip) { 586 cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); 587 } 588 } 589 590 void riscv_set_mode(CPURISCVState *env, target_ulong newpriv) 591 { 592 if (newpriv > PRV_M) { 593 g_assert_not_reached(); 594 } 595 if (newpriv == PRV_H) { 596 newpriv = PRV_U; 597 } 598 /* tlb_flush is unnecessary as mode is contained in mmu_idx */ 599 env->priv = newpriv; 600 } 601 602 target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb) 603 { 604 if (!(env->priv >= PRV_S)) { 605 do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); 606 } 607 608 target_ulong retpc = env->sepc; 609 if (!riscv_has_ext(env, RVC) && (retpc & 0x3)) { 610 do_raise_exception_err(env, RISCV_EXCP_INST_ADDR_MIS, GETPC()); 611 } 612 613 target_ulong mstatus = env->mstatus; 614 target_ulong prev_priv = get_field(mstatus, MSTATUS_SPP); 615 mstatus = set_field(mstatus, 616 env->priv_ver >= PRIV_VERSION_1_10_0 ? 617 MSTATUS_SIE : MSTATUS_UIE << prev_priv, 618 get_field(mstatus, MSTATUS_SPIE)); 619 mstatus = set_field(mstatus, MSTATUS_SPIE, 0); 620 mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U); 621 riscv_set_mode(env, prev_priv); 622 csr_write_helper(env, mstatus, CSR_MSTATUS); 623 624 return retpc; 625 } 626 627 target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb) 628 { 629 if (!(env->priv >= PRV_M)) { 630 do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); 631 } 632 633 target_ulong retpc = env->mepc; 634 if (!riscv_has_ext(env, RVC) && (retpc & 0x3)) { 635 do_raise_exception_err(env, RISCV_EXCP_INST_ADDR_MIS, GETPC()); 636 } 637 638 target_ulong mstatus = env->mstatus; 639 target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP); 640 mstatus = set_field(mstatus, 641 env->priv_ver >= PRIV_VERSION_1_10_0 ? 642 MSTATUS_MIE : MSTATUS_UIE << prev_priv, 643 get_field(mstatus, MSTATUS_MPIE)); 644 mstatus = set_field(mstatus, MSTATUS_MPIE, 0); 645 mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U); 646 riscv_set_mode(env, prev_priv); 647 csr_write_helper(env, mstatus, CSR_MSTATUS); 648 649 return retpc; 650 } 651 652 653 void helper_wfi(CPURISCVState *env) 654 { 655 CPUState *cs = CPU(riscv_env_get_cpu(env)); 656 657 cs->halted = 1; 658 cs->exception_index = EXCP_HLT; 659 cpu_loop_exit(cs); 660 } 661 662 void helper_tlb_flush(CPURISCVState *env) 663 { 664 RISCVCPU *cpu = riscv_env_get_cpu(env); 665 CPUState *cs = CPU(cpu); 666 tlb_flush(cs); 667 } 668 669 #endif /* !CONFIG_USER_ONLY */ 670