diff mbox series

[v2,08/17] exec: Add support for TARGET_TAGGED_ADDRESSES

Message ID 20200605041733.415188-9-richard.henderson@linaro.org (mailing list archive)
State New, archived
Headers show
Series target-arm: Implement ARMv8.5-MemTag, user mode | expand

Commit Message

Richard Henderson June 5, 2020, 4:17 a.m. UTC
The AArch64 Linux ABI has always enabled TBI, but has historically
required that pointer tags be removed before a syscall.  This has
changed in the lead-up to ARMv8.5-MTE, in a way that affects the
ABI generically and not specifically to MTE.

This patch allows the target to indicate that (1) there are tags
and (2) whether or not they should be taken into account at the
syscall level.

Adjust g2h, guest_addr_valid, and guest_range_valid to ignore
pointer tags, similar to how TIF_TAGGED_ADDR alters __range_ok
in the arm64 kernel source.

The prctl syscall is not not yet updated, so this change by itself
has no visible effect.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/exec/cpu_ldst.h | 22 ++++++++++++++++++----
 target/arm/cpu-param.h  |  3 +++
 bsd-user/main.c         |  5 +++++
 linux-user/main.c       |  5 +++++
 4 files changed, 31 insertions(+), 4 deletions(-)

Comments

Peter Maydell June 25, 2020, 4:43 p.m. UTC | #1
On Fri, 5 Jun 2020 at 05:17, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> The AArch64 Linux ABI has always enabled TBI, but has historically
> required that pointer tags be removed before a syscall.  This has
> changed in the lead-up to ARMv8.5-MTE, in a way that affects the
> ABI generically and not specifically to MTE.
>
> This patch allows the target to indicate that (1) there are tags
> and (2) whether or not they should be taken into account at the
> syscall level.
>
> Adjust g2h, guest_addr_valid, and guest_range_valid to ignore
> pointer tags, similar to how TIF_TAGGED_ADDR alters __range_ok
> in the arm64 kernel source.
>
> The prctl syscall is not not yet updated, so this change by itself
> has no visible effect.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  include/exec/cpu_ldst.h | 22 ++++++++++++++++++----
>  target/arm/cpu-param.h  |  3 +++
>  bsd-user/main.c         |  5 +++++
>  linux-user/main.c       |  5 +++++
>  4 files changed, 31 insertions(+), 4 deletions(-)
>
> diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
> index 066cf33f70..d84847dc70 100644
> --- a/include/exec/cpu_ldst.h
> +++ b/include/exec/cpu_ldst.h
> @@ -69,17 +69,31 @@ typedef uint64_t abi_ptr;
>  #define TARGET_ABI_FMT_ptr "%"PRIx64
>  #endif
>
> +#ifdef TARGET_TAGGED_ADDRESSES
> +extern abi_ptr untagged_addr_mask;
> +static inline abi_ptr untagged_addr(abi_ptr x)
> +{
> +    return x & untagged_addr_mask;
> +}
> +#else
> +static inline abi_ptr untagged_addr(abi_ptr x) { return x; }
> +#endif
> +
>  /* All direct uses of g2h and h2g need to go away for usermode softmmu.  */
> -#define g2h(x) ((void *)((unsigned long)(abi_ptr)(x) + guest_base))
> +static inline void *g2h(abi_ptr x)
> +{
> +    return (void *)(uintptr_t)(untagged_addr(x) + guest_base);
> +}
>
>  static inline bool guest_addr_valid(abi_ptr x)
>  {
> -    return x <= GUEST_ADDR_MAX;
> +    return untagged_addr(x) <= GUEST_ADDR_MAX;
>  }
>
> -static inline int guest_range_valid(unsigned long start, unsigned long len)
> +static inline bool guest_range_valid(abi_ptr start, abi_ulong len)

More type changes...

>  {
> -    return len - 1 <= GUEST_ADDR_MAX && start <= GUEST_ADDR_MAX - len + 1;
> +    return len - 1 <= GUEST_ADDR_MAX &&
> +           untagged_addr(start) <= GUEST_ADDR_MAX - len + 1;
>  }
>
>  #define h2g_valid(x)  ((uintptr_t)(x) - guest_base <= GUEST_ADDR_MAX)

otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM
diff mbox series

Patch

diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
index 066cf33f70..d84847dc70 100644
--- a/include/exec/cpu_ldst.h
+++ b/include/exec/cpu_ldst.h
@@ -69,17 +69,31 @@  typedef uint64_t abi_ptr;
 #define TARGET_ABI_FMT_ptr "%"PRIx64
 #endif
 
+#ifdef TARGET_TAGGED_ADDRESSES
+extern abi_ptr untagged_addr_mask;
+static inline abi_ptr untagged_addr(abi_ptr x)
+{
+    return x & untagged_addr_mask;
+}
+#else
+static inline abi_ptr untagged_addr(abi_ptr x) { return x; }
+#endif
+
 /* All direct uses of g2h and h2g need to go away for usermode softmmu.  */
-#define g2h(x) ((void *)((unsigned long)(abi_ptr)(x) + guest_base))
+static inline void *g2h(abi_ptr x)
+{
+    return (void *)(uintptr_t)(untagged_addr(x) + guest_base);
+}
 
 static inline bool guest_addr_valid(abi_ptr x)
 {
-    return x <= GUEST_ADDR_MAX;
+    return untagged_addr(x) <= GUEST_ADDR_MAX;
 }
 
-static inline int guest_range_valid(unsigned long start, unsigned long len)
+static inline bool guest_range_valid(abi_ptr start, abi_ulong len)
 {
-    return len - 1 <= GUEST_ADDR_MAX && start <= GUEST_ADDR_MAX - len + 1;
+    return len - 1 <= GUEST_ADDR_MAX &&
+           untagged_addr(start) <= GUEST_ADDR_MAX - len + 1;
 }
 
 #define h2g_valid(x)  ((uintptr_t)(x) - guest_base <= GUEST_ADDR_MAX)
diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
index 6321385b46..f922aa0650 100644
--- a/target/arm/cpu-param.h
+++ b/target/arm/cpu-param.h
@@ -20,6 +20,9 @@ 
 
 #ifdef CONFIG_USER_ONLY
 #define TARGET_PAGE_BITS 12
+# ifdef TARGET_AARCH64
+#  define TARGET_TAGGED_ADDRESSES
+# endif
 #else
 /*
  * ARMv7 and later CPUs have 4K pages minimum, but ARMv5 and v6
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 0bfe46cff9..87c99fc6c2 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -45,6 +45,11 @@  unsigned long guest_base;
 bool have_guest_base;
 unsigned long reserved_va;
 
+#ifdef TARGET_TAGGED_ADDRESSES
+/* Default to no tagged addresses, i.e. all pointer bits valid.  */
+abi_ptr untagged_addr_mask = -1;
+#endif
+
 static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
 const char *qemu_uname_release;
 extern char **environ;
diff --git a/linux-user/main.c b/linux-user/main.c
index 3597e99bb1..8fcca3f5f1 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -103,6 +103,11 @@  static int last_log_mask;
 
 unsigned long reserved_va;
 
+#ifdef TARGET_TAGGED_ADDRESSES
+/* Default to no tagged addresses, i.e. all pointer bits valid.  */
+abi_ptr untagged_addr_mask = -1;
+#endif
+
 static void usage(int exitcode);
 
 static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;