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 && !riscv_cpu_fp_enabled(env)) {
  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 && !riscv_cpu_fp_enabled(env)) {
 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 && !riscv_cpu_fp_enabled(env)) {
 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 && !riscv_cpu_fp_enabled(env)) {
 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 && !riscv_cpu_fp_enabled(env)) {
 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 && !riscv_cpu_fp_enabled(env)) {
 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 && !riscv_cpu_fp_enabled(env)) {
 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    int dirty;
 311
 312    /* flush tlb on mstatus fields that affect VM */
 313    if (env->priv_ver <= PRIV_VERSION_1_09_1) {
 314        if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP |
 315                MSTATUS_MPRV | MSTATUS_SUM | MSTATUS_VM)) {
 316            tlb_flush(env_cpu(env));
 317        }
 318        mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
 319            MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM |
 320            MSTATUS_MPP | MSTATUS_MXR |
 321            (validate_vm(env, get_field(val, MSTATUS_VM)) ?
 322                MSTATUS_VM : 0);
 323    }
 324    if (env->priv_ver >= PRIV_VERSION_1_10_0) {
 325        if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV |
 326                MSTATUS_MPRV | MSTATUS_SUM)) {
 327            tlb_flush(env_cpu(env));
 328        }
 329        mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
 330            MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM |
 331            MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR |
 332            MSTATUS_TW;
 333#if defined(TARGET_RISCV64)
 334            /*
 335             * RV32: MPV and MTL are not in mstatus. The current plan is to
 336             * add them to mstatush. For now, we just don't support it.
 337             */
 338            mask |= MSTATUS_MTL | MSTATUS_MPV;
 339#endif
 340    }
 341
 342    mstatus = (mstatus & ~mask) | (val & mask);
 343
 344    dirty = (riscv_cpu_fp_enabled(env) &&
 345             ((mstatus & MSTATUS_FS) == MSTATUS_FS)) |
 346            ((mstatus & MSTATUS_XS) == MSTATUS_XS);
 347    mstatus = set_field(mstatus, MSTATUS_SD, dirty);
 348    env->mstatus = mstatus;
 349
 350    return 0;
 351}
 352
 353static int read_misa(CPURISCVState *env, int csrno, target_ulong *val)
 354{
 355    *val = env->misa;
 356    return 0;
 357}
 358
 359static int write_misa(CPURISCVState *env, int csrno, target_ulong val)
 360{
 361    if (!riscv_feature(env, RISCV_FEATURE_MISA)) {
 362        /* drop write to misa */
 363        return 0;
 364    }
 365
 366    /* 'I' or 'E' must be present */
 367    if (!(val & (RVI | RVE))) {
 368        /* It is not, drop write to misa */
 369        return 0;
 370    }
 371
 372    /* 'E' excludes all other extensions */
 373    if (val & RVE) {
 374        /* when we support 'E' we can do "val = RVE;" however
 375         * for now we just drop writes if 'E' is present.
 376         */
 377        return 0;
 378    }
 379
 380    /* Mask extensions that are not supported by this hart */
 381    val &= env->misa_mask;
 382
 383    /* Mask extensions that are not supported by QEMU */
 384    val &= (RVI | RVE | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
 385
 386    /* 'D' depends on 'F', so clear 'D' if 'F' is not present */
 387    if ((val & RVD) && !(val & RVF)) {
 388        val &= ~RVD;
 389    }
 390
 391    /* Suppress 'C' if next instruction is not aligned
 392     * TODO: this should check next_pc
 393     */
 394    if ((val & RVC) && (GETPC() & ~3) != 0) {
 395        val &= ~RVC;
 396    }
 397
 398    /* misa.MXL writes are not supported by QEMU */
 399    val = (env->misa & MISA_MXL) | (val & ~MISA_MXL);
 400
 401    /* flush translation cache */
 402    if (val != env->misa) {
 403        tb_flush(env_cpu(env));
 404    }
 405
 406    env->misa = val;
 407
 408    return 0;
 409}
 410
 411static int read_medeleg(CPURISCVState *env, int csrno, target_ulong *val)
 412{
 413    *val = env->medeleg;
 414    return 0;
 415}
 416
 417static int write_medeleg(CPURISCVState *env, int csrno, target_ulong val)
 418{
 419    env->medeleg = (env->medeleg & ~delegable_excps) | (val & delegable_excps);
 420    return 0;
 421}
 422
 423static int read_mideleg(CPURISCVState *env, int csrno, target_ulong *val)
 424{
 425    *val = env->mideleg;
 426    return 0;
 427}
 428
 429static int write_mideleg(CPURISCVState *env, int csrno, target_ulong val)
 430{
 431    env->mideleg = (env->mideleg & ~delegable_ints) | (val & delegable_ints);
 432    return 0;
 433}
 434
 435static int read_mie(CPURISCVState *env, int csrno, target_ulong *val)
 436{
 437    *val = env->mie;
 438    return 0;
 439}
 440
 441static int write_mie(CPURISCVState *env, int csrno, target_ulong val)
 442{
 443    env->mie = (env->mie & ~all_ints) | (val & all_ints);
 444    return 0;
 445}
 446
 447static int read_mtvec(CPURISCVState *env, int csrno, target_ulong *val)
 448{
 449    *val = env->mtvec;
 450    return 0;
 451}
 452
 453static int write_mtvec(CPURISCVState *env, int csrno, target_ulong val)
 454{
 455    /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */
 456    if ((val & 3) < 2) {
 457        env->mtvec = val;
 458    } else {
 459        qemu_log_mask(LOG_UNIMP, "CSR_MTVEC: reserved mode not supported\n");
 460    }
 461    return 0;
 462}
 463
 464static int read_mcounteren(CPURISCVState *env, int csrno, target_ulong *val)
 465{
 466    if (env->priv_ver < PRIV_VERSION_1_10_0) {
 467        return -1;
 468    }
 469    *val = env->mcounteren;
 470    return 0;
 471}
 472
 473static int write_mcounteren(CPURISCVState *env, int csrno, target_ulong val)
 474{
 475    if (env->priv_ver < PRIV_VERSION_1_10_0) {
 476        return -1;
 477    }
 478    env->mcounteren = val;
 479    return 0;
 480}
 481
 482/* This regiser is replaced with CSR_MCOUNTINHIBIT in 1.11.0 */
 483static int read_mscounteren(CPURISCVState *env, int csrno, target_ulong *val)
 484{
 485    if (env->priv_ver > PRIV_VERSION_1_09_1
 486        && env->priv_ver < PRIV_VERSION_1_11_0) {
 487        return -1;
 488    }
 489    *val = env->mcounteren;
 490    return 0;
 491}
 492
 493/* This regiser is replaced with CSR_MCOUNTINHIBIT in 1.11.0 */
 494static int write_mscounteren(CPURISCVState *env, int csrno, target_ulong val)
 495{
 496    if (env->priv_ver > PRIV_VERSION_1_09_1
 497        && env->priv_ver < PRIV_VERSION_1_11_0) {
 498        return -1;
 499    }
 500    env->mcounteren = val;
 501    return 0;
 502}
 503
 504static int read_mucounteren(CPURISCVState *env, int csrno, target_ulong *val)
 505{
 506    if (env->priv_ver > PRIV_VERSION_1_09_1) {
 507        return -1;
 508    }
 509    *val = env->scounteren;
 510    return 0;
 511}
 512
 513static int write_mucounteren(CPURISCVState *env, int csrno, target_ulong val)
 514{
 515    if (env->priv_ver > PRIV_VERSION_1_09_1) {
 516        return -1;
 517    }
 518    env->scounteren = val;
 519    return 0;
 520}
 521
 522/* Machine Trap Handling */
 523static int read_mscratch(CPURISCVState *env, int csrno, target_ulong *val)
 524{
 525    *val = env->mscratch;
 526    return 0;
 527}
 528
 529static int write_mscratch(CPURISCVState *env, int csrno, target_ulong val)
 530{
 531    env->mscratch = val;
 532    return 0;
 533}
 534
 535static int read_mepc(CPURISCVState *env, int csrno, target_ulong *val)
 536{
 537    *val = env->mepc;
 538    return 0;
 539}
 540
 541static int write_mepc(CPURISCVState *env, int csrno, target_ulong val)
 542{
 543    env->mepc = val;
 544    return 0;
 545}
 546
 547static int read_mcause(CPURISCVState *env, int csrno, target_ulong *val)
 548{
 549    *val = env->mcause;
 550    return 0;
 551}
 552
 553static int write_mcause(CPURISCVState *env, int csrno, target_ulong val)
 554{
 555    env->mcause = val;
 556    return 0;
 557}
 558
 559static int read_mbadaddr(CPURISCVState *env, int csrno, target_ulong *val)
 560{
 561    *val = env->mbadaddr;
 562    return 0;
 563}
 564
 565static int write_mbadaddr(CPURISCVState *env, int csrno, target_ulong val)
 566{
 567    env->mbadaddr = val;
 568    return 0;
 569}
 570
 571static int rmw_mip(CPURISCVState *env, int csrno, target_ulong *ret_value,
 572                   target_ulong new_value, target_ulong write_mask)
 573{
 574    RISCVCPU *cpu = env_archcpu(env);
 575    /* Allow software control of delegable interrupts not claimed by hardware */
 576    target_ulong mask = write_mask & delegable_ints & ~env->miclaim;
 577    uint32_t old_mip;
 578
 579    if (mask) {
 580        old_mip = riscv_cpu_update_mip(cpu, mask, (new_value & mask));
 581    } else {
 582        old_mip = env->mip;
 583    }
 584
 585    if (ret_value) {
 586        *ret_value = old_mip;
 587    }
 588
 589    return 0;
 590}
 591
 592/* Supervisor Trap Setup */
 593static int read_sstatus(CPURISCVState *env, int csrno, target_ulong *val)
 594{
 595    target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
 596                         sstatus_v1_10_mask : sstatus_v1_9_mask);
 597    *val = env->mstatus & mask;
 598    return 0;
 599}
 600
 601static int write_sstatus(CPURISCVState *env, int csrno, target_ulong val)
 602{
 603    target_ulong mask = ((env->priv_ver >= PRIV_VERSION_1_10_0) ?
 604                         sstatus_v1_10_mask : sstatus_v1_9_mask);
 605    target_ulong newval = (env->mstatus & ~mask) | (val & mask);
 606    return write_mstatus(env, CSR_MSTATUS, newval);
 607}
 608
 609static int read_sie(CPURISCVState *env, int csrno, target_ulong *val)
 610{
 611    *val = env->mie & env->mideleg;
 612    return 0;
 613}
 614
 615static int write_sie(CPURISCVState *env, int csrno, target_ulong val)
 616{
 617    target_ulong newval = (env->mie & ~env->mideleg) | (val & env->mideleg);
 618    return write_mie(env, CSR_MIE, newval);
 619}
 620
 621static int read_stvec(CPURISCVState *env, int csrno, target_ulong *val)
 622{
 623    *val = env->stvec;
 624    return 0;
 625}
 626
 627static int write_stvec(CPURISCVState *env, int csrno, target_ulong val)
 628{
 629    /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */
 630    if ((val & 3) < 2) {
 631        env->stvec = val;
 632    } else {
 633        qemu_log_mask(LOG_UNIMP, "CSR_STVEC: reserved mode not supported\n");
 634    }
 635    return 0;
 636}
 637
 638static int read_scounteren(CPURISCVState *env, int csrno, target_ulong *val)
 639{
 640    if (env->priv_ver < PRIV_VERSION_1_10_0) {
 641        return -1;
 642    }
 643    *val = env->scounteren;
 644    return 0;
 645}
 646
 647static int write_scounteren(CPURISCVState *env, int csrno, target_ulong val)
 648{
 649    if (env->priv_ver < PRIV_VERSION_1_10_0) {
 650        return -1;
 651    }
 652    env->scounteren = val;
 653    return 0;
 654}
 655
 656/* Supervisor Trap Handling */
 657static int read_sscratch(CPURISCVState *env, int csrno, target_ulong *val)
 658{
 659    *val = env->sscratch;
 660    return 0;
 661}
 662
 663static int write_sscratch(CPURISCVState *env, int csrno, target_ulong val)
 664{
 665    env->sscratch = val;
 666    return 0;
 667}
 668
 669static int read_sepc(CPURISCVState *env, int csrno, target_ulong *val)
 670{
 671    *val = env->sepc;
 672    return 0;
 673}
 674
 675static int write_sepc(CPURISCVState *env, int csrno, target_ulong val)
 676{
 677    env->sepc = val;
 678    return 0;
 679}
 680
 681static int read_scause(CPURISCVState *env, int csrno, target_ulong *val)
 682{
 683    *val = env->scause;
 684    return 0;
 685}
 686
 687static int write_scause(CPURISCVState *env, int csrno, target_ulong val)
 688{
 689    env->scause = val;
 690    return 0;
 691}
 692
 693static int read_sbadaddr(CPURISCVState *env, int csrno, target_ulong *val)
 694{
 695    *val = env->sbadaddr;
 696    return 0;
 697}
 698
 699static int write_sbadaddr(CPURISCVState *env, int csrno, target_ulong val)
 700{
 701    env->sbadaddr = val;
 702    return 0;
 703}
 704
 705static int rmw_sip(CPURISCVState *env, int csrno, target_ulong *ret_value,
 706                   target_ulong new_value, target_ulong write_mask)
 707{
 708    int ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value,
 709                      write_mask & env->mideleg & sip_writable_mask);
 710    *ret_value &= env->mideleg;
 711    return ret;
 712}
 713
 714/* Supervisor Protection and Translation */
 715static int read_satp(CPURISCVState *env, int csrno, target_ulong *val)
 716{
 717    if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
 718        *val = 0;
 719    } else if (env->priv_ver >= PRIV_VERSION_1_10_0) {
 720        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
 721            return -1;
 722        } else {
 723            *val = env->satp;
 724        }
 725    } else {
 726        *val = env->sptbr;
 727    }
 728    return 0;
 729}
 730
 731static int write_satp(CPURISCVState *env, int csrno, target_ulong val)
 732{
 733    if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
 734        return 0;
 735    }
 736    if (env->priv_ver <= PRIV_VERSION_1_09_1 && (val ^ env->sptbr)) {
 737        tlb_flush(env_cpu(env));
 738        env->sptbr = val & (((target_ulong)
 739            1 << (TARGET_PHYS_ADDR_SPACE_BITS - PGSHIFT)) - 1);
 740    }
 741    if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
 742        validate_vm(env, get_field(val, SATP_MODE)) &&
 743        ((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN)))
 744    {
 745        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
 746            return -1;
 747        } else {
 748            if((val ^ env->satp) & SATP_ASID) {
 749                tlb_flush(env_cpu(env));
 750            }
 751            env->satp = val;
 752        }
 753    }
 754    return 0;
 755}
 756
 757/* Physical Memory Protection */
 758static int read_pmpcfg(CPURISCVState *env, int csrno, target_ulong *val)
 759{
 760    *val = pmpcfg_csr_read(env, csrno - CSR_PMPCFG0);
 761    return 0;
 762}
 763
 764static int write_pmpcfg(CPURISCVState *env, int csrno, target_ulong val)
 765{
 766    pmpcfg_csr_write(env, csrno - CSR_PMPCFG0, val);
 767    return 0;
 768}
 769
 770static int read_pmpaddr(CPURISCVState *env, int csrno, target_ulong *val)
 771{
 772    *val = pmpaddr_csr_read(env, csrno - CSR_PMPADDR0);
 773    return 0;
 774}
 775
 776static int write_pmpaddr(CPURISCVState *env, int csrno, target_ulong val)
 777{
 778    pmpaddr_csr_write(env, csrno - CSR_PMPADDR0, val);
 779    return 0;
 780}
 781
 782#endif
 783
 784/*
 785 * riscv_csrrw - read and/or update control and status register
 786 *
 787 * csrr   <->  riscv_csrrw(env, csrno, ret_value, 0, 0);
 788 * csrrw  <->  riscv_csrrw(env, csrno, ret_value, value, -1);
 789 * csrrs  <->  riscv_csrrw(env, csrno, ret_value, -1, value);
 790 * csrrc  <->  riscv_csrrw(env, csrno, ret_value, 0, value);
 791 */
 792
 793int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value,
 794                target_ulong new_value, target_ulong write_mask)
 795{
 796    int ret;
 797    target_ulong old_value;
 798    RISCVCPU *cpu = env_archcpu(env);
 799
 800    /* check privileges and return -1 if check fails */
 801#if !defined(CONFIG_USER_ONLY)
 802    int csr_priv = get_field(csrno, 0x300);
 803    int read_only = get_field(csrno, 0xC00) == 3;
 804    if ((!env->debugger) && (env->priv < csr_priv)) {
 805        return -1;
 806    }
 807    if (write_mask && read_only) {
 808        return -1;
 809    }
 810#endif
 811
 812    /* ensure the CSR extension is enabled. */
 813    if (!cpu->cfg.ext_icsr) {
 814        return -1;
 815    }
 816
 817    /* check predicate */
 818    if (!csr_ops[csrno].predicate || csr_ops[csrno].predicate(env, csrno) < 0) {
 819        return -1;
 820    }
 821
 822    /* execute combined read/write operation if it exists */
 823    if (csr_ops[csrno].op) {
 824        return csr_ops[csrno].op(env, csrno, ret_value, new_value, write_mask);
 825    }
 826
 827    /* if no accessor exists then return failure */
 828    if (!csr_ops[csrno].read) {
 829        return -1;
 830    }
 831
 832    /* read old value */
 833    ret = csr_ops[csrno].read(env, csrno, &old_value);
 834    if (ret < 0) {
 835        return ret;
 836    }
 837
 838    /* write value if writable and write mask set, otherwise drop writes */
 839    if (write_mask) {
 840        new_value = (old_value & ~write_mask) | (new_value & write_mask);
 841        if (csr_ops[csrno].write) {
 842            ret = csr_ops[csrno].write(env, csrno, new_value);
 843            if (ret < 0) {
 844                return ret;
 845            }
 846        }
 847    }
 848
 849    /* return old value */
 850    if (ret_value) {
 851        *ret_value = old_value;
 852    }
 853
 854    return 0;
 855}
 856
 857/*
 858 * Debugger support.  If not in user mode, set env->debugger before the
 859 * riscv_csrrw call and clear it after the call.
 860 */
 861int riscv_csrrw_debug(CPURISCVState *env, int csrno, target_ulong *ret_value,
 862                target_ulong new_value, target_ulong write_mask)
 863{
 864    int ret;
 865#if !defined(CONFIG_USER_ONLY)
 866    env->debugger = true;
 867#endif
 868    ret = riscv_csrrw(env, csrno, ret_value, new_value, write_mask);
 869#if !defined(CONFIG_USER_ONLY)
 870    env->debugger = false;
 871#endif
 872    return ret;
 873}
 874
 875/* Control and Status Register function table */
 876static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 877    /* User Floating-Point CSRs */
 878    [CSR_FFLAGS] =              { fs,   read_fflags,      write_fflags      },
 879    [CSR_FRM] =                 { fs,   read_frm,         write_frm         },
 880    [CSR_FCSR] =                { fs,   read_fcsr,        write_fcsr        },
 881
 882    /* User Timers and Counters */
 883    [CSR_CYCLE] =               { ctr,  read_instret                        },
 884    [CSR_INSTRET] =             { ctr,  read_instret                        },
 885#if defined(TARGET_RISCV32)
 886    [CSR_CYCLEH] =              { ctr,  read_instreth                       },
 887    [CSR_INSTRETH] =            { ctr,  read_instreth                       },
 888#endif
 889
 890    /* User-level time CSRs are only available in linux-user
 891     * In privileged mode, the monitor emulates these CSRs */
 892#if defined(CONFIG_USER_ONLY)
 893    [CSR_TIME] =                { ctr,  read_time                           },
 894#if defined(TARGET_RISCV32)
 895    [CSR_TIMEH] =               { ctr,  read_timeh                          },
 896#endif
 897#endif
 898
 899#if !defined(CONFIG_USER_ONLY)
 900    /* Machine Timers and Counters */
 901    [CSR_MCYCLE] =              { any,  read_instret                        },
 902    [CSR_MINSTRET] =            { any,  read_instret                        },
 903#if defined(TARGET_RISCV32)
 904    [CSR_MCYCLEH] =             { any,  read_instreth                       },
 905    [CSR_MINSTRETH] =           { any,  read_instreth                       },
 906#endif
 907
 908    /* Machine Information Registers */
 909    [CSR_MVENDORID] =           { any,  read_zero                           },
 910    [CSR_MARCHID] =             { any,  read_zero                           },
 911    [CSR_MIMPID] =              { any,  read_zero                           },
 912    [CSR_MHARTID] =             { any,  read_mhartid                        },
 913
 914    /* Machine Trap Setup */
 915    [CSR_MSTATUS] =             { any,  read_mstatus,     write_mstatus     },
 916    [CSR_MISA] =                { any,  read_misa,        write_misa        },
 917    [CSR_MIDELEG] =             { any,  read_mideleg,     write_mideleg     },
 918    [CSR_MEDELEG] =             { any,  read_medeleg,     write_medeleg     },
 919    [CSR_MIE] =                 { any,  read_mie,         write_mie         },
 920    [CSR_MTVEC] =               { any,  read_mtvec,       write_mtvec       },
 921    [CSR_MCOUNTEREN] =          { any,  read_mcounteren,  write_mcounteren  },
 922
 923    /* Legacy Counter Setup (priv v1.9.1) */
 924    [CSR_MUCOUNTEREN] =         { any,  read_mucounteren, write_mucounteren },
 925    [CSR_MSCOUNTEREN] =         { any,  read_mscounteren, write_mscounteren },
 926
 927    /* Machine Trap Handling */
 928    [CSR_MSCRATCH] =            { any,  read_mscratch,    write_mscratch    },
 929    [CSR_MEPC] =                { any,  read_mepc,        write_mepc        },
 930    [CSR_MCAUSE] =              { any,  read_mcause,      write_mcause      },
 931    [CSR_MBADADDR] =            { any,  read_mbadaddr,    write_mbadaddr    },
 932    [CSR_MIP] =                 { any,  NULL,     NULL,     rmw_mip         },
 933
 934    /* Supervisor Trap Setup */
 935    [CSR_SSTATUS] =             { smode, read_sstatus,     write_sstatus     },
 936    [CSR_SIE] =                 { smode, read_sie,         write_sie         },
 937    [CSR_STVEC] =               { smode, read_stvec,       write_stvec       },
 938    [CSR_SCOUNTEREN] =          { smode, read_scounteren,  write_scounteren  },
 939
 940    /* Supervisor Trap Handling */
 941    [CSR_SSCRATCH] =            { smode, read_sscratch,    write_sscratch    },
 942    [CSR_SEPC] =                { smode, read_sepc,        write_sepc        },
 943    [CSR_SCAUSE] =              { smode, read_scause,      write_scause      },
 944    [CSR_SBADADDR] =            { smode, read_sbadaddr,    write_sbadaddr    },
 945    [CSR_SIP] =                 { smode, NULL,     NULL,     rmw_sip         },
 946
 947    /* Supervisor Protection and Translation */
 948    [CSR_SATP] =                { smode, read_satp,        write_satp        },
 949
 950    /* Physical Memory Protection */
 951    [CSR_PMPCFG0  ... CSR_PMPADDR9] =  { pmp,   read_pmpcfg,  write_pmpcfg   },
 952    [CSR_PMPADDR0 ... CSR_PMPADDR15] = { pmp,   read_pmpaddr, write_pmpaddr  },
 953
 954    /* Performance Counters */
 955    [CSR_HPMCOUNTER3   ... CSR_HPMCOUNTER31] =    { ctr,  read_zero          },
 956    [CSR_MHPMCOUNTER3  ... CSR_MHPMCOUNTER31] =   { any,  read_zero          },
 957    [CSR_MHPMEVENT3    ... CSR_MHPMEVENT31] =     { any,  read_zero          },
 958#if defined(TARGET_RISCV32)
 959    [CSR_HPMCOUNTER3H  ... CSR_HPMCOUNTER31H] =   { ctr,  read_zero          },
 960    [CSR_MHPMCOUNTER3H ... CSR_MHPMCOUNTER31H] =  { any,  read_zero          },
 961#endif
 962#endif /* !CONFIG_USER_ONLY */
 963};
 964