From daf3ea9074180c310f35403a7c08ae09b2a7c838 Mon Sep 17 00:00:00 2001 From: Matheus Tavares Bernardino Date: Mon, 2 Sep 2024 16:41:44 -0300 Subject: [PATCH] [QTOOL-97486] honor framelimit on allocframe QEMU should throw an HEX_CAUSE_STACK_LIMIT exception (0x27) if allocframe would move sp beyond the framelimit. Also modernize test file and add more test cases for different scenarios (user/monitor mode, overflow/no-overflow). This was tested with and without idef-parser. Signed-off-by: Matheus Tavares Bernardino --- target/hexagon/genptr.c | 22 +++++++++++++-------- target/hexagon/genptr.h | 2 ++ target/hexagon/idef-parser/idef-parser.y | 4 ++++ target/hexagon/idef-parser/parser-helpers.c | 5 +++++ target/hexagon/idef-parser/parser-helpers.h | 2 ++ target/hexagon/op_helper.c | 2 +- target/hexagon/sys_macros.h | 15 +------------- 7 files changed, 29 insertions(+), 23 deletions(-) diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c index 7072569b4aea..b46fb6ae09f2 100644 --- a/target/hexagon/genptr.c +++ b/target/hexagon/genptr.c @@ -1027,27 +1027,33 @@ static void gen_load_frame(DisasContext *ctx, TCGv_i64 frame, TCGv EA) tcg_gen_qemu_ld_i64(frame, EA, ctx->mem_idx, MO_TEUQ | MO_ALIGN); } -#ifndef CONFIG_HEXAGON_IDEF_PARSER -/* Stack overflow check */ -static void gen_framecheck(TCGv EA, int framesize) + +void gen_framecheck(DisasContext *ctx, TCGv addr, TCGv ea) { - /* Not modelled in linux-user mode */ - /* Placeholder for system mode */ #ifndef CONFIG_USER_ONLY - /* FIXME - Implement framecheck */ + TCGLabel *ok = gen_new_label(); + tcg_gen_brcond_tl(TCG_COND_GEU, addr, hex_gpr[HEX_REG_FRAMELIMIT], ok); + gen_helper_raise_stack_overflow(tcg_env, tcg_constant_i32(ctx->insn->slot), ea); + gen_set_label(ok); #endif } +#ifndef CONFIG_HEXAGON_IDEF_PARSER static void gen_allocframe(DisasContext *ctx, TCGv r29, int framesize) { TCGv r30 = tcg_temp_new(); + TCGv new_r29 = tcg_temp_new(); TCGv_i64 frame; tcg_gen_addi_tl(r30, r29, -8); frame = gen_frame_scramble(); gen_store8(tcg_env, r30, frame, ctx->insn->slot); + tcg_gen_subi_tl(new_r29, r30, framesize); gen_log_reg_write(ctx, HEX_REG_FP, r30); - gen_framecheck(r30, framesize); - tcg_gen_subi_tl(r29, r30, framesize); + /* Not modelled in linux-user mode */ +#ifndef CONFIG_USER_ONLY + gen_framecheck(ctx, new_r29, hex_gpr[HEX_REG_PC]); +#endif + tcg_gen_mov_tl(r29, new_r29); } static void gen_deallocframe(DisasContext *ctx, TCGv_i64 r31_30, TCGv r30) diff --git a/target/hexagon/genptr.h b/target/hexagon/genptr.h index ad70efa4739f..771deb6ecb47 100644 --- a/target/hexagon/genptr.h +++ b/target/hexagon/genptr.h @@ -62,4 +62,6 @@ void probe_noshuf_load(TCGv va, int s, int mi); extern const target_ulong reg_immut_masks[TOTAL_PER_THREAD_REGS]; +void gen_framecheck(DisasContext *ctx, TCGv addr, TCGv ea); + #endif diff --git a/target/hexagon/idef-parser/idef-parser.y b/target/hexagon/idef-parser/idef-parser.y index f9a59995658c..a42c56a52aa3 100644 --- a/target/hexagon/idef-parser/idef-parser.y +++ b/target/hexagon/idef-parser/idef-parser.y @@ -406,6 +406,10 @@ control_statement : frame_check ; frame_check : FCHK '(' rvalue ',' rvalue ')' ';' + { + @1.last_column = @7.last_column; + gen_framecheck(c, &@1, &$3, &$5); + } ; cancel_statement : LOAD_CANCEL diff --git a/target/hexagon/idef-parser/parser-helpers.c b/target/hexagon/idef-parser/parser-helpers.c index 8e8cb831db3b..a4c784c9e064 100644 --- a/target/hexagon/idef-parser/parser-helpers.c +++ b/target/hexagon/idef-parser/parser-helpers.c @@ -2140,3 +2140,8 @@ void assert_signedness(Context *c, signedness != UNKNOWN_SIGNEDNESS, "Unspecified signedness"); } + +void gen_framecheck(Context *c, YYLTYPE *locp, HexValue *addr, HexValue *ea) +{ + OUT(c, locp, "gen_framecheck(ctx, ", addr, ", ", ea, ");\n"); +} diff --git a/target/hexagon/idef-parser/parser-helpers.h b/target/hexagon/idef-parser/parser-helpers.h index 7c5808716982..a41ff905173b 100644 --- a/target/hexagon/idef-parser/parser-helpers.h +++ b/target/hexagon/idef-parser/parser-helpers.h @@ -363,4 +363,6 @@ void assert_signedness(Context *c, YYLTYPE *locp, HexSignedness signedness); +void gen_framecheck(Context *c, YYLTYPE *locp, HexValue *addr, HexValue *ea); + #endif /* PARSER_HELPERS_h */ diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c index 60a4e17d1211..c6034b89ce93 100644 --- a/target/hexagon/op_helper.c +++ b/target/hexagon/op_helper.c @@ -1642,7 +1642,7 @@ void HELPER(raise_stack_overflow)(CPUHexagonState *env, uint32_t slot, { /* * Per section 7.3.1 of the V67 Programmer's Reference, - * stack limit exception isn't raised in monotor mode. + * stack limit exception isn't raised in monitor mode. */ if (sys_in_monitor_mode(env)) { return; diff --git a/target/hexagon/sys_macros.h b/target/hexagon/sys_macros.h index 2b2b13ac8bc6..1bc48923f338 100644 --- a/target/hexagon/sys_macros.h +++ b/target/hexagon/sys_macros.h @@ -106,20 +106,7 @@ #define fPOW2_ROUNDUP(VAL) (fPOW2_HELP_ROUNDUP((VAL) - 1) + 1) #ifdef QEMU_GENERATE -#ifdef FIXME -/* FIXME - Need to enable this check */ -#define fFRAMECHECK(ADDR, EA) \ - do { \ - TCGLabel *ok = gen_new_label(); \ - tcg_gen_brcond_tl(TCG_COND_GEU, ADDR, hex_gpr[HEX_REG_FRAMELIMIT], \ - ok); \ - gen_helper_raise_stack_overflow(tcg_env, \ - tcg_constant_i32(insn->slot), EA); \ - gen_set_label(ok); \ - } while (0) -#else -#define fFRAMECHECK(ADDR, EA) -#endif +#define fFRAMECHECK(ADDR, EA) gen_framecheck(ctx, ADDR, EA) #endif #define fTRAP(TRAPTYPE, IMM) \