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