Signed-off-by: Yeqi Fu <fufuyqqq...@gmail.com> --- target/arm/helper.c | 47 ++++++++++++++++++++++++++++++++++ target/arm/helper.h | 6 +++++ target/arm/tcg/translate-a64.c | 22 ++++++++++++++++ target/arm/tcg/translate.c | 25 +++++++++++++++++- target/arm/tcg/translate.h | 19 ++++++++++++++ 5 files changed, 118 insertions(+), 1 deletion(-)
diff --git a/target/arm/helper.c b/target/arm/helper.c index 0b7fd2e7e6..03fbc3724b 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -25,6 +25,7 @@ #include "sysemu/tcg.h" #include "qapi/error.h" #include "qemu/guest-random.h" +#include "exec/cpu_ldst.h" #ifdef CONFIG_TCG #include "semihosting/common-semi.h" #endif @@ -12045,3 +12046,49 @@ void aarch64_sve_change_el(CPUARMState *env, int old_el, } } #endif + +#if defined(CONFIG_USER_ONLY) && defined(CONFIG_USER_NATIVE_CALL) + +#define NATIVE_FN_W_3W() \ + target_ulong arg0, arg1, arg2; \ + arg0 = env->regs[0]; \ + arg1 = env->regs[1]; \ + arg2 = env->regs[2]; + +void helper_native_memcpy(CPUARMState *env) +{ + CPUState *cs = env_cpu(env); + NATIVE_FN_W_3W(); + void *ret; + void *dest = g2h(cs, arg0); + void *src = g2h(cs, arg1); + size_t n = (size_t)arg2; + ret = memcpy(dest, src, n); + env->regs[0] = (target_ulong)h2g(ret); +} + +void helper_native_memcmp(CPUARMState *env) +{ + CPUState *cs = env_cpu(env); + NATIVE_FN_W_3W(); + int ret; + void *s1 = g2h(cs, arg0); + void *s2 = g2h(cs, arg1); + size_t n = (size_t)arg2; + ret = memcmp(s1, s2, n); + env->regs[0] = ret; +} + +void helper_native_memset(CPUARMState *env) +{ + CPUState *cs = env_cpu(env); + NATIVE_FN_W_3W(); + void *ret; + void *s = g2h(cs, arg0); + int c = (int)arg1; + size_t n = (size_t)arg2; + ret = memset(s, c, n); + env->regs[0] = (target_ulong)h2g(ret); +} + +#endif diff --git a/target/arm/helper.h b/target/arm/helper.h index 3335c2b10b..57144bf6fb 100644 --- a/target/arm/helper.h +++ b/target/arm/helper.h @@ -1038,6 +1038,12 @@ DEF_HELPER_FLAGS_5(gvec_uclamp_s, TCG_CALL_NO_RWG, DEF_HELPER_FLAGS_5(gvec_uclamp_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +#if defined(CONFIG_USER_ONLY) && defined(CONFIG_USER_NATIVE_CALL) +DEF_HELPER_1(native_memcpy, void, env) +DEF_HELPER_1(native_memcmp, void, env) +DEF_HELPER_1(native_memset, void, env) +#endif + #ifdef TARGET_AARCH64 #include "tcg/helper-a64.h" #include "tcg/helper-sve.h" diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c index 741a608739..04421af6c6 100644 --- a/target/arm/tcg/translate-a64.c +++ b/target/arm/tcg/translate-a64.c @@ -35,6 +35,7 @@ #include "cpregs.h" #include "translate-a64.h" #include "qemu/atomic128.h" +#include "native/native-func.h" static TCGv_i64 cpu_X[32]; static TCGv_i64 cpu_pc; @@ -2291,6 +2292,9 @@ static void disas_exc(DisasContext *s, uint32_t insn) if (s->fgt_svc) { gen_exception_insn_el(s, 0, EXCP_UDEF, syndrome, 2); break; + } else if (native_bypass() && imm16 == 0xff) { + s->native_call_status = true; + break; } gen_ss_advance(s); gen_exception_insn(s, 4, EXCP_SWI, syndrome); @@ -14203,6 +14207,24 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) s->fp_access_checked = false; s->sve_access_checked = false; + if (native_bypass() && s->native_call_status) { + switch (insn) { + case NATIVE_MEMCPY: + gen_helper_native_memcpy(cpu_env); + break; + case NATIVE_MEMCMP: + gen_helper_native_memcmp(cpu_env); + break; + case NATIVE_MEMSET: + gen_helper_native_memset(cpu_env); + break; + default: + unallocated_encoding(s); + } + s->native_call_status = false; + return; + } + if (s->pstate_il) { /* * Illegal execution state. This has priority over BTI diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c index 7468476724..83ce0f7437 100644 --- a/target/arm/tcg/translate.c +++ b/target/arm/tcg/translate.c @@ -34,7 +34,7 @@ #include "exec/helper-gen.h" #include "exec/log.h" #include "cpregs.h" - +#include "native/native-func.h" #define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T) #define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5) @@ -58,6 +58,10 @@ TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF; TCGv_i64 cpu_exclusive_addr; TCGv_i64 cpu_exclusive_val; +#if defined(CONFIG_USER_ONLY) && !defined(TARGET_AARCH64) \ + && defined(CONFIG_USER_NATIVE_CALL) +#endif + #include "exec/gen-icount.h" static const char * const regnames[] = @@ -8576,6 +8580,8 @@ static bool trans_SVC(DisasContext *s, arg_SVC *a) if (s->fgt_svc) { uint32_t syndrome = syn_aa32_svc(a->imm, s->thumb); gen_exception_insn_el(s, 0, EXCP_UDEF, syndrome, 2); + } else if (native_bypass() && a->imm == 0xff) { + s->native_call_status = true; } else { gen_update_pc(s, curr_insn_len(s)); s->svc_imm = a->imm; @@ -9372,6 +9378,23 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) insn = arm_ldl_code(env, &dc->base, pc, dc->sctlr_b); dc->insn = insn; dc->base.pc_next = pc + 4; + if (native_bypass() && dc->native_call_status) { + switch (insn) { + case NATIVE_MEMCPY: + gen_helper_native_memcpy(cpu_env); + break; + case NATIVE_MEMCMP: + gen_helper_native_memcmp(cpu_env); + break; + case NATIVE_MEMSET: + gen_helper_native_memset(cpu_env); + break; + default: + unallocated_encoding(dc); + } + dc->native_call_status = false; + return; + } disas_arm_insn(dc, insn); arm_post_translate_insn(dc); diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h index a9d1f4adc2..19c4f7af7f 100644 --- a/target/arm/tcg/translate.h +++ b/target/arm/tcg/translate.h @@ -149,6 +149,13 @@ typedef struct DisasContext { int c15_cpar; /* TCG op of the current insn_start. */ TCGOp *insn_start; + /* + * Indicate whether the next instruction is a native function call (true) + * or not (false). + */ +#if defined(CONFIG_USER_ONLY) && defined(CONFIG_USER_NATIVE_CALL) + bool native_call_status; +#endif } DisasContext; typedef struct DisasCompare { @@ -657,3 +664,15 @@ static inline void gen_restore_rmode(TCGv_i32 old, TCGv_ptr fpst) } #endif /* TARGET_ARM_TRANSLATE_H */ + +/* + * Check if the native bypass feature is enabled. + */ +static inline bool native_bypass(void) +{ +#if defined(CONFIG_USER_ONLY) && defined(CONFIG_USER_NATIVE_CALL) + return true; +#else + return false; +#endif +} -- 2.34.1