Unverified Commit 7f2b5ff1 authored by Michael Clark's avatar Michael Clark Committed by Palmer Dabbelt
Browse files

RISC-V: Implement mstatus.TSR/TW/TVM



This adds the necessary minimum to support S-mode
virtualization for priv ISA >= v1.10

Signed-off-by: default avatarMichael Clark <mjc@sifive.com>
Signed-off-by: default avatarAlistair Francis <alistair.francis@wdc.com>
Co-authored-by: default avatarMatthew Suozzo <msuozzo@google.com>
Co-authored-by: default avatarMichael Clark <mjc@sifive.com>
Signed-off-by: default avatarPalmer Dabbelt <palmer@sifive.com>
parent 533b8f88
Loading
Loading
Loading
Loading
+13 −4
Original line number Diff line number Diff line
@@ -305,7 +305,8 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
        }
        mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
            MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM |
            MSTATUS_MPP | MSTATUS_MXR;
            MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR |
            MSTATUS_TW;
    }

    /* silenty discard mstatus.mpp writes for unsupported modes */
@@ -642,7 +643,11 @@ static int read_satp(CPURISCVState *env, int csrno, target_ulong *val)
    if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
        *val = 0;
    } else if (env->priv_ver >= PRIV_VERSION_1_10_0) {
        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
            return -1;
        } else {
            *val = env->satp;
        }
    } else {
        *val = env->sptbr;
    }
@@ -663,9 +668,13 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val)
        validate_vm(env, get_field(val, SATP_MODE)) &&
        ((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN)))
    {
        if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
            return -1;
        } else {
            tlb_flush(CPU(riscv_env_get_cpu(env)));
            env->satp = val;
        }
    }
    return 0;
}

+21 −4
Original line number Diff line number Diff line
@@ -82,6 +82,11 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
        do_raise_exception_err(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
    }

    if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
        get_field(env->mstatus, MSTATUS_TSR)) {
        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
    }

    target_ulong mstatus = env->mstatus;
    target_ulong prev_priv = get_field(mstatus, MSTATUS_SPP);
    mstatus = set_field(mstatus,
@@ -125,16 +130,28 @@ void helper_wfi(CPURISCVState *env)
{
    CPUState *cs = CPU(riscv_env_get_cpu(env));

    if (env->priv == PRV_S &&
        env->priv_ver >= PRIV_VERSION_1_10_0 &&
        get_field(env->mstatus, MSTATUS_TW)) {
        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
    } else {
        cs->halted = 1;
        cs->exception_index = EXCP_HLT;
        cpu_loop_exit(cs);
    }
}

void helper_tlb_flush(CPURISCVState *env)
{
    RISCVCPU *cpu = riscv_env_get_cpu(env);
    CPUState *cs = CPU(cpu);
    if (env->priv == PRV_S &&
        env->priv_ver >= PRIV_VERSION_1_10_0 &&
        get_field(env->mstatus, MSTATUS_TVM)) {
        do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
    } else {
        tlb_flush(cs);
    }
}

#endif /* !CONFIG_USER_ONLY */