diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h index c1db419af14..579a3ffcb31 100644 --- a/include/tcg/tcg.h +++ b/include/tcg/tcg.h @@ -689,7 +689,6 @@ extern uintptr_t tcg_splitwx_diff; extern TCGv_env cpu_env; #ifdef TARGET_CHERI extern TCGv ddc_interposition; -extern TCGv_i64 cpu_capreg_state; // 32 times 2 bits #endif #ifdef CONFIG_DEBUG_TCG extern TCGv _pc_is_current; diff --git a/target/cheri-common/cheri-lazy-capregs-types.h b/target/cheri-common/cheri-lazy-capregs-types.h index 81cccf06271..8c9dae1bd5e 100644 --- a/target/cheri-common/cheri-lazy-capregs-types.h +++ b/target/cheri-common/cheri-lazy-capregs-types.h @@ -83,6 +83,6 @@ typedef struct GPCapRegs { // We cache the decompressed capregs here (to avoid constantly decompressing // values such as $csp which are used frequently) cap_register_t decompressed[32]; - uint64_t capreg_state; // 32 times CapRegState compressed to one uint64_t + uint8_t capreg_state[32] QEMU_ALIGNED(64); /* 32 times CapRegState */ } GPCapRegs; #endif diff --git a/target/cheri-common/cheri-lazy-capregs.h b/target/cheri-common/cheri-lazy-capregs.h index 3f4eedfa815..7f154b81c9e 100644 --- a/target/cheri-common/cheri-lazy-capregs.h +++ b/target/cheri-common/cheri-lazy-capregs.h @@ -47,20 +47,11 @@ static inline GPCapRegs *cheri_get_gpcrs(CPUArchState *env); -static inline QEMU_ALWAYS_INLINE uint64_t -capreg_state_set_to_integer_mask(unsigned reg) -{ - return ~(((uint64_t)CREG_STATE_MASK) << (reg * 2)); -} - -static inline CapRegState get_capreg_state(const GPCapRegs *gpcrs, unsigned reg) +static inline QEMU_ALWAYS_INLINE CapRegState +get_capreg_state(const GPCapRegs *gpcrs, unsigned reg) { cheri_debug_assert(reg < 32); - /* - * Note: QEMU's extract64 has assertions enabled (even in release mode). - * Since this is a hot path, we re-implement it without assertions here. - */ - return (CapRegState)((gpcrs->capreg_state >> (reg * 2)) & CREG_STATE_MASK); + return (CapRegState)gpcrs->capreg_state[reg]; } static inline void sanity_check_capreg(GPCapRegs *gpcrs, unsigned regnum) @@ -106,7 +97,6 @@ static inline void sanity_check_capreg(GPCapRegs *gpcrs, unsigned regnum) #endif // CONFIG_DEBUG_TCG } -/* Marked as always_inline to avoid the |= if called with CREG_INTEGER. */ static inline QEMU_ALWAYS_INLINE void set_capreg_state(GPCapRegs *gpcrs, unsigned regnum, CapRegState new_state) { @@ -117,14 +107,7 @@ set_capreg_state(GPCapRegs *gpcrs, unsigned regnum, CapRegState new_state) } cheri_debug_assert(regnum < 32); - /* - * Note: QEMU's deposit64 has assertions enabled (even in release mode). - * Since this is a hot path, we re-implement it without assertions here. - */ - gpcrs->capreg_state &= capreg_state_set_to_integer_mask(regnum); - if (!__builtin_constant_p(new_state) || new_state != 0) { - gpcrs->capreg_state |= (((uint64_t)new_state) << (regnum * 2)); - } + gpcrs->capreg_state[regnum] = new_state; // Check that the compressed and decompressed caps are in sync sanity_check_capreg(gpcrs, regnum); } @@ -417,7 +400,9 @@ static inline void reset_capregs(CPUArchState *env) { // Reset all to NULL: GPCapRegs *gpcrs = cheri_get_gpcrs(env); - gpcrs->capreg_state = UINT64_MAX; // All decompressed values + for (size_t i = 0; i < ARRAY_SIZE(gpcrs->capreg_state); i++) { + gpcrs->capreg_state[i] = CREG_FULLY_DECOMPRESSED; + } for (size_t i = 0; i < ARRAY_SIZE(gpcrs->decompressed); i++) { const cap_register_t* newval = null_capability(&gpcrs->decompressed[i]); // Register should be fully decompressed @@ -432,7 +417,9 @@ static inline void set_max_perms_capregs(CPUArchState *env) { // Reset all to max perms (except NULL of course): GPCapRegs *gpcrs = cheri_get_gpcrs(env); - gpcrs->capreg_state = UINT64_MAX; // All decompressed values + for (size_t i = 0; i < ARRAY_SIZE(gpcrs->capreg_state); i++) { + gpcrs->capreg_state[i] = CREG_FULLY_DECOMPRESSED; + } null_capability(&gpcrs->decompressed[NULL_CAPREG_INDEX]); sanity_check_capreg(gpcrs, NULL_CAPREG_INDEX); for (size_t i = 0; i < ARRAY_SIZE(gpcrs->decompressed); i++) { diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 1cd8792f282..f58770c5781 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -225,8 +225,11 @@ static inline void gen_mark_gpr_as_integer(int reg_num_dst) { /* Currently, the integer flag is 0, so we can mask the 64-bit value holding * the capreg state appropriately to clear the bits for register N. */ - tcg_gen_andi_i64(cpu_capreg_state, cpu_capreg_state, - capreg_state_set_to_integer_mask(reg_num_dst)); + TCGv_i32 integer_state = tcg_const_i32(CREG_INTEGER); + tcg_gen_st8_i32( + integer_state, cpu_env, + offsetof(CPURISCVState, gpcapregs.capreg_state[reg_num_dst])); + tcg_temp_free_i32(integer_state); tcg_gen_movi_tl(_cpu_pesbt_do_not_access_directly[reg_num_dst], CAP_NULL_PESBT); /* TODO: maybe all ones is more efficient? We can just do an or and don't @@ -1085,9 +1088,6 @@ void riscv_translate_init(void) offsetof(CPURISCVState, gpcapregs.decompressed[i].cached_pesbt), cheri_gp_regnames[i]); } - cpu_capreg_state = tcg_global_mem_new_i64( - cpu_env, offsetof(CPURISCVState, gpcapregs.capreg_state), - "capreg_state"); #endif #ifdef CONFIG_RVFI_DII cpu_rvfi_available_fields = tcg_global_mem_new_i32( diff --git a/tcg/tcg.c b/tcg/tcg.c index acdd72e6d52..fe24485c970 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -168,7 +168,6 @@ TCGv _pc_is_current = 0; #endif #ifdef TARGET_CHERI TCGv ddc_interposition; -TCGv_i64 cpu_capreg_state; // 32 times 2 bits #endif #ifndef CONFIG_TCG_INTERPRETER