Octeon exposes CvmCount through RDHWR register 31. Add the Octeon-only decode path, enable the corresponding HWREna bit for linux-user, and use an unsigned mask when checking HWREna so bit 31 is handled safely.
For user-mode emulation, return host ticks as a monotonic counter source suitable for existing Octeon userspace code. In system mode, fall back to the existing CP0 Count value. Signed-off-by: James Hilliard <[email protected]> --- target/mips/cpu.c | 2 +- target/mips/helper.h | 1 + target/mips/tcg/op_helper.c | 13 ++++++++++++- target/mips/tcg/translate.c | 11 +++++++++++ 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/target/mips/cpu.c b/target/mips/cpu.c index a2b9f6634f..606a1d838b 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -321,7 +321,7 @@ static void mips_cpu_reset_hold(Object *obj, ResetType type) */ env->CP0_HWREna |= 0x0000000F; if (env->insn_flags & INSN_OCTEON) { - env->CP0_HWREna |= 0x40000000u; + env->CP0_HWREna |= 0xc0000000u; } if (env->CP0_Config1 & (1 << CP0C1_FP)) { env->CP0_Status |= (1 << CP0St_CU1); diff --git a/target/mips/helper.h b/target/mips/helper.h index 410a9b8090..d7a0feb673 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -203,6 +203,7 @@ DEF_HELPER_1(rdhwr_ccres, tl, env) DEF_HELPER_1(rdhwr_performance, tl, env) DEF_HELPER_1(rdhwr_xnp, tl, env) DEF_HELPER_1(rdhwr_chord, tl, env) +DEF_HELPER_1(rdhwr_cvmcount, tl, env) DEF_HELPER_2(pmon, void, env, int) DEF_HELPER_1(wait, void, env) diff --git a/target/mips/tcg/op_helper.c b/target/mips/tcg/op_helper.c index 67854f08df..55ac877506 100644 --- a/target/mips/tcg/op_helper.c +++ b/target/mips/tcg/op_helper.c @@ -25,6 +25,7 @@ #include "exec/memop.h" #include "fpu_helper.h" #include "qemu/crc32c.h" +#include "qemu/timer.h" #include <zlib.h> static inline target_ulong bitswap(target_ulong v) @@ -366,7 +367,7 @@ target_ulong helper_yield(CPUMIPSState *env, target_ulong arg) static inline void check_hwrena(CPUMIPSState *env, int reg, uintptr_t pc) { - if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << reg))) { + if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1u << reg))) { return; } do_raise_exception(env, EXCP_RI, pc); @@ -418,6 +419,16 @@ target_ulong helper_rdhwr_chord(CPUMIPSState *env) return env->octeon_crypto.chord; } +target_ulong helper_rdhwr_cvmcount(CPUMIPSState *env) +{ + check_hwrena(env, 31, GETPC()); +#ifdef CONFIG_USER_ONLY + return cpu_get_host_ticks(); +#else + return (uint32_t)cpu_mips_get_count(env); +#endif +} + void helper_pmon(CPUMIPSState *env, int function) { function /= 2; diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index 3e39f3460a..7627a4ffb4 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -10931,6 +10931,17 @@ void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel) gen_helper_rdhwr_chord(t0, tcg_env); gen_store_gpr(t0, rt); break; + case 31: + if (!(ctx->insn_flags & INSN_OCTEON)) { + gen_reserved_instruction(ctx); + break; + } + translator_io_start(&ctx->base); + gen_helper_rdhwr_cvmcount(t0, tcg_env); + gen_store_gpr(t0, rt); + gen_save_pc(ctx->base.pc_next + 4); + ctx->base.is_jmp = DISAS_EXIT; + break; default: /* Invalid */ MIPS_INVAL("rdhwr"); gen_reserved_instruction(ctx); -- 2.54.0
