From: "Alex Bennée" <alex.bennee@linaro.org>
To: Yeqi Fu <fufuyqqqqqq@gmail.com>
Cc: richard.henderson@linaro.org, qemu-devel@nongnu.org,
Paolo Bonzini <pbonzini@redhat.com>
Subject: Re: [RFC v4 06/11] tcg: Add tcg opcodes and helpers for native library calls
Date: Wed, 09 Aug 2023 17:41:57 +0100 [thread overview]
Message-ID: <87cyzw40e8.fsf@linaro.org> (raw)
In-Reply-To: <20230808141739.3110740-7-fufuyqqqqqq@gmail.com>
Yeqi Fu <fufuyqqqqqq@gmail.com> writes:
> This commit implements tcg opcodes and helpers for extracting and
> invoke native functions.
>
> Signed-off-by: Yeqi Fu <fufuyqqqqqq@gmail.com>
> ---
> accel/tcg/tcg-runtime.h | 22 ++++++
> include/tcg/tcg-op-common.h | 11 +++
> include/tcg/tcg.h | 9 +++
> tcg/tcg-op.c | 140 ++++++++++++++++++++++++++++++++++++
> 4 files changed, 182 insertions(+)
>
> diff --git a/accel/tcg/tcg-runtime.h b/accel/tcg/tcg-runtime.h
> index 39e68007f9..bda78b4489 100644
> --- a/accel/tcg/tcg-runtime.h
> +++ b/accel/tcg/tcg-runtime.h
> @@ -37,6 +37,28 @@ DEF_HELPER_FLAGS_1(exit_atomic, TCG_CALL_NO_WG, noreturn, env)
> */
> #define helper_memset memset
> DEF_HELPER_FLAGS_3(memset, TCG_CALL_NO_RWG, ptr, ptr, int, ptr)
> +
> +#define helper_memcpy memcpy
> +DEF_HELPER_FLAGS_3(memcpy, TCG_CALL_NO_RWG, ptr, ptr, ptr, ptr)
> +
> +#define helper_strncpy strncpy
> +DEF_HELPER_FLAGS_3(strncpy, TCG_CALL_NO_RWG, ptr, ptr, ptr, ptr)
> +
> +#define helper_memcmp memcmp
> +DEF_HELPER_FLAGS_3(memcmp, TCG_CALL_NO_RWG, int, ptr, ptr, ptr)
> +
> +#define helper_strncmp strncmp
> +DEF_HELPER_FLAGS_3(strncmp, TCG_CALL_NO_RWG, int, ptr, ptr, ptr)
> +
> +#define helper_strcpy strcpy
> +DEF_HELPER_FLAGS_2(strcpy, TCG_CALL_NO_RWG, ptr, ptr, ptr)
> +
> +#define helper_strcat strcat
> +DEF_HELPER_FLAGS_2(strcat, TCG_CALL_NO_RWG, ptr, ptr, ptr)
> +
> +#define helper_strcmp strcmp
> +DEF_HELPER_FLAGS_2(strcmp, TCG_CALL_NO_RWG, int, ptr, ptr)
> +
> #endif /* IN_HELPER_PROTO */
>
> DEF_HELPER_FLAGS_3(ld_i128, TCG_CALL_NO_WG, i128, env, i64, i32)
> diff --git a/include/tcg/tcg-op-common.h b/include/tcg/tcg-op-common.h
> index be382bbf77..2e712f1573 100644
> --- a/include/tcg/tcg-op-common.h
> +++ b/include/tcg/tcg-op-common.h
> @@ -903,6 +903,12 @@ void tcg_gen_ld_vec(TCGv_vec r, TCGv_ptr base, TCGArg offset);
> void tcg_gen_st_vec(TCGv_vec r, TCGv_ptr base, TCGArg offset);
> void tcg_gen_stl_vec(TCGv_vec r, TCGv_ptr base, TCGArg offset, TCGType t);
>
> +/* Host <-> guest conversions */
> +void tcg_gen_g2h_i32(TCGv_ptr ret, TCGv_i32 arg);
> +void tcg_gen_g2h_i64(TCGv_ptr ret, TCGv_i64 arg);
> +void tcg_gen_h2g_i32(TCGv_i32 ret, TCGv_ptr arg);
> +void tcg_gen_h2g_i64(TCGv_i64 ret, TCGv_ptr arg);
> +
> /* Host pointer ops */
>
> #if UINTPTR_MAX == UINT32_MAX
> @@ -938,6 +944,11 @@ static inline void tcg_gen_addi_ptr(TCGv_ptr r, TCGv_ptr a, intptr_t b)
> glue(tcg_gen_addi_,PTR)((NAT)r, (NAT)a, b);
> }
>
> +static inline void tcg_gen_subi_ptr(TCGv_ptr r, TCGv_ptr a, intptr_t b)
> +{
> + glue(tcg_gen_subi_, PTR)((NAT)r, (NAT)a, b);
> +}
> +
> static inline void tcg_gen_mov_ptr(TCGv_ptr d, TCGv_ptr s)
> {
> glue(tcg_gen_mov_,PTR)((NAT)d, (NAT)s);
> diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
> index 0875971719..7c7fafb1cd 100644
> --- a/include/tcg/tcg.h
> +++ b/include/tcg/tcg.h
> @@ -35,6 +35,9 @@
> #include "tcg-target.h"
> #include "tcg/tcg-cond.h"
> #include "tcg/debug-assert.h"
> +#ifdef CONFIG_USER_ONLY
> +#include "exec/user/guest-base.h"
> +#endif
>
> /* XXX: make safe guess about sizes */
> #define MAX_OP_PER_INSTR 266
> @@ -1148,4 +1151,10 @@ static inline const TCGOpcode *tcg_swap_vecop_list(const TCGOpcode *n)
>
> bool tcg_can_emit_vecop_list(const TCGOpcode *, TCGType, unsigned);
>
> +/* native call */
> +void gen_native_call_i32(const char *fun_name, TCGv_i32 ret,
> + TCGv_i32 arg1, TCGv_i32 arg2, TCGv_i32 arg3);
> +void gen_native_call_i64(const char *fun_name, TCGv_i64 ret,
> + TCGv_i64 arg1, TCGv_i64 arg2, TCGv_i64 arg3);
> +
> #endif /* TCG_H */
> diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
> index 7aadb37756..83e3a5682c 100644
> --- a/tcg/tcg-op.c
> +++ b/tcg/tcg-op.c
> @@ -2852,3 +2852,143 @@ void tcg_gen_lookup_and_goto_ptr(void)
> tcg_gen_op1i(INDEX_op_goto_ptr, tcgv_ptr_arg(ptr));
> tcg_temp_free_ptr(ptr);
> }
> +
> +#ifdef CONFIG_USER_ONLY
> +void tcg_gen_g2h_i32(TCGv_ptr ret, TCGv_i32 arg)
> +{
> + TCGv_ptr temp = tcg_temp_new_ptr();
> + tcg_gen_ext_i32_ptr(temp, arg);
> + tcg_gen_addi_ptr(ret, temp, guest_base);
> + tcg_temp_free_ptr(temp);
> +}
> +
> +void tcg_gen_g2h_i64(TCGv_ptr ret, TCGv_i64 arg)
> +{
> + TCGv_ptr temp = tcg_temp_new_ptr();
> + tcg_gen_trunc_i64_ptr(temp, arg); /* Not sure */
> + tcg_gen_addi_ptr(ret, temp, guest_base);
> + tcg_temp_free_ptr(temp);
> +}
> +
> +void tcg_gen_h2g_i32(TCGv_i32 ret, TCGv_ptr arg)
> +{
> + TCGv_ptr temp = tcg_temp_new_ptr();
> + tcg_gen_subi_ptr(temp, arg, guest_base);
> + tcg_gen_trunc_ptr_i32(ret, temp);
> + tcg_temp_free_ptr(temp);
> +}
> +
> +void tcg_gen_h2g_i64(TCGv_i64 ret, TCGv_ptr arg)
> +{
> + TCGv_ptr temp = tcg_temp_new_ptr();
> + tcg_gen_subi_ptr(temp, arg, guest_base);
> + tcg_gen_extu_ptr_i64(ret, temp);
> + tcg_temp_free_ptr(temp);
> +}
> +
> +#else
> +void tcg_gen_g2h_i32(TCGv_ptr ret, TCGv_i32 arg)
> +{
It would be worth adding g_assert_not_reached() to these stubs so any
accidental call gets flagged straight away.
> +}
> +void tcg_gen_g2h_i64(TCGv_ptr ret, TCGv_i64 arg)
> +{
> +}
> +void tcg_gen_h2g_i32(TCGv_i32 ret, TCGv_ptr arg)
> +{
> +}
> +void tcg_gen_h2g_i64(TCGv_i64 ret, TCGv_ptr arg)
> +{
> +}
> +#endif
> +
> +/* p: iptr ; i: i32 ; a: ptr(address) */
> +void gen_native_call_i32(const char *fun_name, TCGv_i32 ret,
> + TCGv_i32 arg1, TCGv_i32 arg2, TCGv_i32 arg3)
> +{
> + TCGv_ptr arg1_ptr = tcg_temp_new_ptr();
> + TCGv_ptr arg2_ptr = tcg_temp_new_ptr();
> + TCGv_ptr arg3_ptr = tcg_temp_new_ptr();
> + TCGv_ptr ret_ptr = tcg_temp_new_ptr();
> + tcg_gen_g2h_i32(arg1_ptr, arg1);
> + if (strcmp(fun_name, "memset") == 0) {/* a aip */
> + tcg_gen_ext_i32_ptr(arg3_ptr, arg3);
> + gen_helper_memset(ret_ptr, arg1_ptr, arg2, arg3_ptr);
> + goto ret_ptr;
> + }
> + tcg_gen_g2h_i32(arg2_ptr, arg2);
> + if (strcmp(fun_name, "strcpy") == 0) { /* a aa */
> + gen_helper_strcpy(ret_ptr, arg1_ptr, arg2_ptr);
> + goto ret_ptr;
> + } else if (strcmp(fun_name, "strcat") == 0) { /* a aa */
> + gen_helper_strcat(ret_ptr, arg1_ptr, arg2_ptr);
> + goto ret_ptr;
> + } else if (strcmp(fun_name, "strcmp") == 0) { /* i aa */
> + gen_helper_strcmp(ret, arg1_ptr, arg2_ptr);
> + }
> + tcg_gen_ext_i32_ptr(arg3_ptr, arg3);
> + if (strcmp(fun_name, "memcpy") == 0) { /* a aap */
> + gen_helper_memcpy(ret_ptr, arg1_ptr, arg2_ptr, arg3_ptr);
> + goto ret_ptr;
> + } else if (strcmp(fun_name, "strncpy") == 0) { /* a aap */
> + gen_helper_strncpy(ret_ptr, arg1_ptr, arg2_ptr, arg3_ptr);
> + goto ret_ptr;
> + } else if (strcmp(fun_name, "memcmp") == 0) { /* i aap */
> + gen_helper_memcmp(ret, arg1_ptr, arg2_ptr, arg3_ptr);
> + } else if (strcmp(fun_name, "strncmp") == 0) { /* i aap */
> + gen_helper_strncmp(ret, arg1_ptr, arg2_ptr, arg3_ptr);
> + }
> + return;
> +ret_ptr:
> + tcg_gen_h2g_i32(ret, ret_ptr);
> + return;
This is a bit of a messy function considering that most of it is data
driven. I think we could have a table with something like:
{
{ .func = "memset", .helper = gen_helper_memset,
.g2h_arg1 = true },
...
}
and then remove the duplication between the two gen_native_calls as
simply having different signatures for their g2h and h2h conversions. If
we ever get to embedding the signatures in the library that would make
things simpler to replace as well I think.
> +}
> +
> +void gen_native_call_i64(const char *fun_name, TCGv_i64 ret,
> + TCGv_i64 arg1, TCGv_i64 arg2, TCGv_i64 arg3)
> +{
> + TCGv_ptr arg1_ptr = tcg_temp_new_ptr();
> + TCGv_ptr arg2_ptr = tcg_temp_new_ptr();
> + TCGv_ptr arg3_ptr = tcg_temp_new_ptr();
> + TCGv_ptr ret_ptr = tcg_temp_new_ptr();
> + TCGv_i32 arg2_i32, ret_i32 = tcg_temp_new_i32();
> + tcg_gen_g2h_i64(arg1_ptr, arg1);
> + if (strcmp(fun_name, "memset") == 0) { /* a aip */
> + arg2_i32 = tcg_temp_new_i32();
> + tcg_gen_extrl_i64_i32(arg2_i32, arg2);
> + tcg_gen_trunc_i64_ptr(arg3_ptr, arg3);
> + gen_helper_memset(ret_ptr, arg1_ptr, arg2_i32, arg3_ptr);
> + goto ret_ptr;
> + }
> + tcg_gen_g2h_i64(arg2_ptr, arg2);
> + if (strcmp(fun_name, "strcpy") == 0) { /* a aa */
> + gen_helper_strcpy(ret_ptr, arg1_ptr, arg2_ptr);
> + goto ret_ptr;
> + } else if (strcmp(fun_name, "strcat") == 0) { /* a aa */
> + gen_helper_strcat(ret_ptr, arg1_ptr, arg2_ptr);
> + goto ret_ptr;
> + } else if (strcmp(fun_name, "strcmp") == 0) { /* i aa */
> + gen_helper_strcmp(ret_i32, arg1_ptr, arg2_ptr);
> + goto ret_i32;
> + }
> + tcg_gen_trunc_i64_ptr(arg3_ptr, arg3);
> + if (strcmp(fun_name, "memcpy") == 0) { /* a aap */
> + gen_helper_memcpy(ret_ptr, arg1_ptr, arg2_ptr, arg3_ptr);
> + goto ret_ptr;
> + } else if (strcmp(fun_name, "strncpy") == 0) { /* a aap */
> + gen_helper_strncpy(ret_ptr, arg1_ptr, arg2_ptr, arg3_ptr);
> + goto ret_ptr;
> + } else if (strcmp(fun_name, "memcmp") == 0) { /* i aap */
> + gen_helper_memcmp(ret_i32, arg1_ptr, arg2_ptr, arg3_ptr);
> + goto ret_i32;
> + } else if (strcmp(fun_name, "strncmp") == 0) { /* i aap */
> + gen_helper_strncmp(ret_i32, arg1_ptr, arg2_ptr, arg3_ptr);
> + goto ret_i32;
> + }
> + return;
> +ret_ptr:
> + tcg_gen_h2g_i64(ret, ret_ptr);
> + return;
> +ret_i32:
> + tcg_gen_extu_i32_i64(ret, ret_i32);
> + return;
> +}
--
Alex Bennée
Virtualisation Tech Lead @ Linaro
next prev parent reply other threads:[~2023-08-09 17:00 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-08 14:17 [RFC v4 00/11] Native Library Calls Yeqi Fu
2023-08-08 14:17 ` [RFC v4 01/11] build: Implement logic for sharing cross-building config files Yeqi Fu
2023-08-09 12:24 ` Manos Pitsidianakis
2023-08-09 14:42 ` Alex Bennée
2023-08-09 15:23 ` Alex Bennée
2023-08-10 8:41 ` Alex Bennée
2023-08-08 14:17 ` [RFC v4 02/11] build: Implement libnative library and the build machinery for libnative Yeqi Fu
2023-08-09 15:18 ` Alex Bennée
2023-08-09 16:10 ` Richard Henderson
2023-08-08 14:17 ` [RFC v4 03/11] linux-user: Implement envlist_appendenv and add tests for envlist Yeqi Fu
2023-08-09 15:27 ` Alex Bennée
2023-08-09 15:44 ` Richard Henderson
2023-08-09 16:06 ` Richard Henderson
2023-08-08 14:17 ` [RFC v4 04/11] linux-user: Implement native-bypass option support Yeqi Fu
2023-08-09 15:42 ` Richard Henderson
2023-08-09 15:47 ` Alex Bennée
2023-08-08 14:17 ` [RFC v4 05/11] linux-user/elfload: Add support for parsing symbols of native libraries Yeqi Fu
2023-08-09 16:14 ` Richard Henderson
2023-08-09 17:04 ` Alex Bennée
2023-08-08 14:17 ` [RFC v4 06/11] tcg: Add tcg opcodes and helpers for native library calls Yeqi Fu
2023-08-09 16:41 ` Alex Bennée [this message]
2023-08-08 14:17 ` [RFC v4 07/11] target/i386: Add support " Yeqi Fu
2023-08-09 16:44 ` Richard Henderson
2023-08-08 14:17 ` [RFC v4 08/11] target/mips: " Yeqi Fu
2023-08-08 14:17 ` [RFC v4 09/11] target/arm: " Yeqi Fu
2023-08-08 14:17 ` [RFC v4 10/11] tests/tcg/multiarch: Add nativecall.c test Yeqi Fu
2023-08-09 8:42 ` Alex Bennée
2023-08-09 17:01 ` Alex Bennée
2023-08-09 17:12 ` Alex Bennée
2023-08-08 14:17 ` [RFC v4 11/11] docs/user: Add doc for native library calls Yeqi Fu
2023-08-09 12:51 ` Manos Pitsidianakis
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87cyzw40e8.fsf@linaro.org \
--to=alex.bennee@linaro.org \
--cc=fufuyqqqqqq@gmail.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).