qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode
@ 2021-01-15 22:46 Richard Henderson
  2021-01-15 22:46 ` [PATCH v3 01/21] tcg: Introduce target-specific page data for user-only Richard Henderson
                   ` (21 more replies)
  0 siblings, 22 replies; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

The kernel abi was finally merged into 5.10.

Changes for v3:
  * Split out type changes to separate patches.
  * Add doc comments; tweak alloc so that the !PAGE_VALID case is clear.
  * Do not overlap PAGE_TARGET_2 with PAGE_RESERVED.
  * Use syndrome.h, arm_deliver_fault.


r~


v1: https://patchew.org/QEMU/20191015163254.12041-1-richard.henderson@linaro.org/
v2: https://patchew.org/QEMU/20200605041733.415188-1-richard.henderson@linaro.org/

Richard Henderson (21):
  tcg: Introduce target-specific page data for user-only
  linux-user: Introduce PAGE_ANON
  exec: Use uintptr_t for guest_base
  exec: Use uintptr_t in cpu_ldst.h
  exec: Improve types for guest_addr_valid
  linux-user: Check for overflow in access_ok
  linux-user: Tidy VERIFY_READ/VERIFY_WRITE
  bsd-user: Tidy VERIFY_READ/VERIFY_WRITE
  linux-user: Do not use guest_addr_valid for h2g_valid
  linux-user: Fix guest_addr_valid vs reserved_va
  exec: Add support for TARGET_TAGGED_ADDRESSES
  linux-user/aarch64: Implement PR_TAGGED_ADDR_ENABLE
  linux-user/aarch64: Implement PR_MTE_TCF and PR_MTE_TAG
  linux-user/aarch64: Implement PROT_MTE
  target/arm: Split out syndrome.h from internals.h
  linux-user/aarch64: Pass syndrome to EXC_*_ABORT
  linux-user/aarch64: Signal SEGV_MTESERR for sync tag check fault
  linux-user/aarch64: Signal SEGV_MTEAERR for async tag check error
  target/arm: Add allocation tag storage for user mode
  target/arm: Enable MTE for user-only
  tests/tcg/aarch64: Add mte smoke tests

 bsd-user/qemu.h                     |   9 +-
 include/exec/cpu-all.h              |  47 ++++-
 include/exec/cpu_ldst.h             |  42 +++--
 linux-user/aarch64/target_signal.h  |   3 +
 linux-user/aarch64/target_syscall.h |  13 ++
 linux-user/qemu.h                   |  19 +-
 linux-user/syscall_defs.h           |   1 +
 target/arm/cpu-param.h              |   3 +
 target/arm/cpu.h                    |  24 +++
 target/arm/internals.h              | 245 +------------------------
 target/arm/syndrome.h               | 273 ++++++++++++++++++++++++++++
 tests/tcg/aarch64/mte.h             |  53 ++++++
 accel/tcg/translate-all.c           |  28 +++
 bsd-user/main.c                     |   2 +-
 linux-user/aarch64/cpu_loop.c       |  61 +++++--
 linux-user/main.c                   |   2 +-
 linux-user/mmap.c                   |  29 ++-
 linux-user/syscall.c                |  73 +++++++-
 target/arm/cpu.c                    |  19 ++
 target/arm/mte_helper.c             |  39 +++-
 target/arm/tlb_helper.c             |  15 +-
 tests/tcg/aarch64/mte-1.c           |  25 +++
 tests/tcg/aarch64/mte-2.c           |  42 +++++
 tests/tcg/aarch64/mte-3.c           |  47 +++++
 tests/tcg/aarch64/mte-4.c           |  42 +++++
 tests/tcg/aarch64/Makefile.target   |   6 +
 tests/tcg/configure.sh              |   4 +
 27 files changed, 856 insertions(+), 310 deletions(-)
 create mode 100644 target/arm/syndrome.h
 create mode 100644 tests/tcg/aarch64/mte.h
 create mode 100644 tests/tcg/aarch64/mte-1.c
 create mode 100644 tests/tcg/aarch64/mte-2.c
 create mode 100644 tests/tcg/aarch64/mte-3.c
 create mode 100644 tests/tcg/aarch64/mte-4.c

-- 
2.25.1



^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v3 01/21] tcg: Introduce target-specific page data for user-only
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-19 16:53   ` Peter Maydell
  2021-01-15 22:46 ` [PATCH v3 02/21] linux-user: Introduce PAGE_ANON Richard Henderson
                   ` (20 subsequent siblings)
  21 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

This data can be allocated by page_alloc_target_data() and
released by page_set_flags(start, end, prot | PAGE_RESET).

This data will be used to hold tag memory for AArch64 MTE.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v3: Add doc comments; tweak alloc so that the !PAGE_VALID case is clear.
---
 include/exec/cpu-all.h    | 42 +++++++++++++++++++++++++++++++++------
 accel/tcg/translate-all.c | 28 ++++++++++++++++++++++++++
 linux-user/mmap.c         |  4 +++-
 linux-user/syscall.c      |  4 ++--
 4 files changed, 69 insertions(+), 9 deletions(-)

diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 4b5408c341..99a09ee137 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -264,15 +264,21 @@ extern intptr_t qemu_host_page_mask;
 #define PAGE_EXEC      0x0004
 #define PAGE_BITS      (PAGE_READ | PAGE_WRITE | PAGE_EXEC)
 #define PAGE_VALID     0x0008
-/* original state of the write flag (used when tracking self-modifying
-   code */
+/*
+ * Original state of the write flag (used when tracking self-modifying code)
+ */
 #define PAGE_WRITE_ORG 0x0010
-/* Invalidate the TLB entry immediately, helpful for s390x
- * Low-Address-Protection. Used with PAGE_WRITE in tlb_set_page_with_attrs() */
-#define PAGE_WRITE_INV 0x0040
+/*
+ * Invalidate the TLB entry immediately, helpful for s390x
+ * Low-Address-Protection. Used with PAGE_WRITE in tlb_set_page_with_attrs()
+ */
+#define PAGE_WRITE_INV 0x0020
+/* For use with page_set_flags: page is being replaced; target_data cleared. */
+#define PAGE_RESET     0x0040
+
 #if defined(CONFIG_BSD) && defined(CONFIG_USER_ONLY)
 /* FIXME: Code that sets/uses this is broken and needs to go away.  */
-#define PAGE_RESERVED  0x0020
+#define PAGE_RESERVED  0x0100
 #endif
 /* Target-specific bits that will be used via page_get_flags().  */
 #define PAGE_TARGET_1  0x0080
@@ -287,6 +293,30 @@ int walk_memory_regions(void *, walk_memory_regions_fn);
 int page_get_flags(target_ulong address);
 void page_set_flags(target_ulong start, target_ulong end, int flags);
 int page_check_range(target_ulong start, target_ulong len, int flags);
+
+/**
+ * page_alloc_target_data(address, size)
+ * @address: guest virtual address
+ * @size: size of data to allocate
+ *
+ * Allocate @size bytes of out-of-band data to associate with the
+ * guest page at @address.  If the page is not mapped, NULL will
+ * be returned.  If there is existing data associated with @address,
+ * no new memory will be allocated.
+ *
+ * The memory will be freed when the guest page is deallocated,
+ * e.g. with the munmap system call.
+ */
+void *page_alloc_target_data(target_ulong address, size_t size);
+
+/**
+ * page_get_target_data(address)
+ * @address: guest virtual address
+ *
+ * Return any out-of-bound memory assocated with the guest page
+ * at @address, as per page_alloc_target_data.
+ */
+void *page_get_target_data(target_ulong address);
 #endif
 
 CPUArchState *cpu_copy(CPUArchState *env);
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index e9de6ff9dd..7bcb6663f1 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -113,6 +113,7 @@ typedef struct PageDesc {
     unsigned int code_write_count;
 #else
     unsigned long flags;
+    void *target_data;
 #endif
 #ifndef CONFIG_USER_ONLY
     QemuSpin lock;
@@ -2740,6 +2741,7 @@ int page_get_flags(target_ulong address)
 void page_set_flags(target_ulong start, target_ulong end, int flags)
 {
     target_ulong addr, len;
+    bool reset_target_data;
 
     /* This function should never be called with addresses outside the
        guest address space.  If this assert fires, it probably indicates
@@ -2754,6 +2756,8 @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
     if (flags & PAGE_WRITE) {
         flags |= PAGE_WRITE_ORG;
     }
+    reset_target_data = !(flags & PAGE_VALID) || (flags & PAGE_RESET);
+    flags &= ~PAGE_RESET;
 
     for (addr = start, len = end - start;
          len != 0;
@@ -2767,10 +2771,34 @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
             p->first_tb) {
             tb_invalidate_phys_page(addr, 0);
         }
+        if (reset_target_data && p->target_data) {
+            g_free(p->target_data);
+            p->target_data = NULL;
+        }
         p->flags = flags;
     }
 }
 
+void *page_get_target_data(target_ulong address)
+{
+    PageDesc *p = page_find(address >> TARGET_PAGE_BITS);
+    return p ? p->target_data : NULL;
+}
+
+void *page_alloc_target_data(target_ulong address, size_t size)
+{
+    PageDesc *p = page_find(address >> TARGET_PAGE_BITS);
+    void *ret = NULL;
+
+    if (p->flags & PAGE_VALID) {
+        ret = p->target_data;
+        if (!ret) {
+            p->target_data = ret = g_malloc0(size);
+        }
+    }
+    return ret;
+}
+
 int page_check_range(target_ulong start, target_ulong len, int flags)
 {
     PageDesc *p;
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 810653c503..c693505b60 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -599,6 +599,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
         }
     }
  the_end1:
+    page_flags |= PAGE_RESET;
     page_set_flags(start, start + len, page_flags);
  the_end:
     trace_target_mmap_complete(start);
@@ -792,7 +793,8 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
         new_addr = h2g(host_addr);
         prot = page_get_flags(old_addr);
         page_set_flags(old_addr, old_addr + old_size, 0);
-        page_set_flags(new_addr, new_addr + new_size, prot | PAGE_VALID);
+        page_set_flags(new_addr, new_addr + new_size,
+                       prot | PAGE_VALID | PAGE_RESET);
     }
     tb_invalidate_phys_range(new_addr, new_addr + new_size);
     mmap_unlock();
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index d182890ff0..bec2ab7769 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4625,8 +4625,8 @@ static inline abi_ulong do_shmat(CPUArchState *cpu_env,
     raddr=h2g((unsigned long)host_raddr);
 
     page_set_flags(raddr, raddr + shm_info.shm_segsz,
-                   PAGE_VALID | PAGE_READ |
-                   ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));
+                   PAGE_VALID | PAGE_RESET | PAGE_READ |
+                   (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
 
     for (i = 0; i < N_SHM_REGIONS; i++) {
         if (!shm_regions[i].in_use) {
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 02/21] linux-user: Introduce PAGE_ANON
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
  2021-01-15 22:46 ` [PATCH v3 01/21] tcg: Introduce target-specific page data for user-only Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-15 22:46 ` [PATCH v3 03/21] exec: Use uintptr_t for guest_base Richard Henderson
                   ` (19 subsequent siblings)
  21 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

Record whether the backing page is anonymous, or if it has file
backing.  This will allow us to get close to the Linux AArch64
ABI for MTE, which allows tag memory only on ram-backed VMAs.

The real ABI allows tag memory on files, when those files are
on ram-backed filesystems, such as tmpfs.  We will not be able
to implement that in QEMU linux-user.

Thankfully, anonymous memory for malloc arenas is the primary
consumer of this feature, so this restricted version should
still be of use.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/exec/cpu-all.h | 2 ++
 linux-user/mmap.c      | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 99a09ee137..c23c77589b 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -275,6 +275,8 @@ extern intptr_t qemu_host_page_mask;
 #define PAGE_WRITE_INV 0x0020
 /* For use with page_set_flags: page is being replaced; target_data cleared. */
 #define PAGE_RESET     0x0040
+/* For linux-user, indicates that the page is MAP_ANON. */
+#define PAGE_ANON      0x0080
 
 #if defined(CONFIG_BSD) && defined(CONFIG_USER_ONLY)
 /* FIXME: Code that sets/uses this is broken and needs to go away.  */
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index c693505b60..7fb4c628e1 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -599,6 +599,9 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
         }
     }
  the_end1:
+    if (flags & MAP_ANONYMOUS) {
+        page_flags |= PAGE_ANON;
+    }
     page_flags |= PAGE_RESET;
     page_set_flags(start, start + len, page_flags);
  the_end:
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 03/21] exec: Use uintptr_t for guest_base
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
  2021-01-15 22:46 ` [PATCH v3 01/21] tcg: Introduce target-specific page data for user-only Richard Henderson
  2021-01-15 22:46 ` [PATCH v3 02/21] linux-user: Introduce PAGE_ANON Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-19 16:56   ` Peter Maydell
  2021-01-15 22:46 ` [PATCH v3 04/21] exec: Use uintptr_t in cpu_ldst.h Richard Henderson
                   ` (18 subsequent siblings)
  21 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

This is more descriptive than 'unsigned long'.
No functional change, since these match on all linux+bsd hosts.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/exec/cpu-all.h | 2 +-
 bsd-user/main.c        | 2 +-
 linux-user/main.c      | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index c23c77589b..c52180e8e6 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -158,7 +158,7 @@ static inline void tswap64s(uint64_t *s)
 /* On some host systems the guest address space is reserved on the host.
  * This allows the guest address space to be offset to a convenient location.
  */
-extern unsigned long guest_base;
+extern uintptr_t guest_base;
 extern bool have_guest_base;
 extern unsigned long reserved_va;
 
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 65163e1396..5c8e6a4acd 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -41,7 +41,7 @@
 
 int singlestep;
 unsigned long mmap_min_addr;
-unsigned long guest_base;
+uintptr_t guest_base;
 bool have_guest_base;
 unsigned long reserved_va;
 
diff --git a/linux-user/main.c b/linux-user/main.c
index bb4e55e8fc..2600245300 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -58,7 +58,7 @@ static const char *cpu_model;
 static const char *cpu_type;
 static const char *seed_optarg;
 unsigned long mmap_min_addr;
-unsigned long guest_base;
+uintptr_t guest_base;
 bool have_guest_base;
 
 /*
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 04/21] exec: Use uintptr_t in cpu_ldst.h
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
                   ` (2 preceding siblings ...)
  2021-01-15 22:46 ` [PATCH v3 03/21] exec: Use uintptr_t for guest_base Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-19 16:56   ` Peter Maydell
  2021-01-15 22:46 ` [PATCH v3 05/21] exec: Improve types for guest_addr_valid Richard Henderson
                   ` (17 subsequent siblings)
  21 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

This is more descriptive than 'unsigned long'.
No functional change, since these match on all linux+bsd hosts.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/exec/cpu_ldst.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
index ef54cb7e1f..3f9063aade 100644
--- a/include/exec/cpu_ldst.h
+++ b/include/exec/cpu_ldst.h
@@ -70,14 +70,14 @@ typedef uint64_t abi_ptr;
 #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))
+#define g2h(x) ((void *)((uintptr_t)(abi_ptr)(x) + guest_base))
 
 #if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
 #define guest_addr_valid(x) (1)
 #else
 #define guest_addr_valid(x) ((x) <= GUEST_ADDR_MAX)
 #endif
-#define h2g_valid(x) guest_addr_valid((unsigned long)(x) - guest_base)
+#define h2g_valid(x) guest_addr_valid((uintptr_t)(x) - guest_base)
 
 static inline int guest_range_valid(unsigned long start, unsigned long len)
 {
@@ -85,7 +85,7 @@ static inline int guest_range_valid(unsigned long start, unsigned long len)
 }
 
 #define h2g_nocheck(x) ({ \
-    unsigned long __ret = (unsigned long)(x) - guest_base; \
+    uintptr_t __ret = (uintptr_t)(x) - guest_base; \
     (abi_ptr)__ret; \
 })
 
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 05/21] exec: Improve types for guest_addr_valid
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
                   ` (3 preceding siblings ...)
  2021-01-15 22:46 ` [PATCH v3 04/21] exec: Use uintptr_t in cpu_ldst.h Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-19 16:57   ` Peter Maydell
  2021-01-15 22:46 ` [PATCH v3 06/21] linux-user: Check for overflow in access_ok Richard Henderson
                   ` (16 subsequent siblings)
  21 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

Return bool not int; pass abi_ulong not 'unsigned long'.
All callers use abi_ulong already, so the change in type
has no effect.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/exec/cpu_ldst.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
index 3f9063aade..5e8878ee9b 100644
--- a/include/exec/cpu_ldst.h
+++ b/include/exec/cpu_ldst.h
@@ -79,7 +79,7 @@ typedef uint64_t abi_ptr;
 #endif
 #define h2g_valid(x) guest_addr_valid((uintptr_t)(x) - guest_base)
 
-static inline int guest_range_valid(unsigned long start, unsigned long len)
+static inline bool guest_range_valid(abi_ulong start, abi_ulong len)
 {
     return len - 1 <= GUEST_ADDR_MAX && start <= GUEST_ADDR_MAX - len + 1;
 }
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 06/21] linux-user: Check for overflow in access_ok
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
                   ` (4 preceding siblings ...)
  2021-01-15 22:46 ` [PATCH v3 05/21] exec: Improve types for guest_addr_valid Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-15 22:46 ` [PATCH v3 07/21] linux-user: Tidy VERIFY_READ/VERIFY_WRITE Richard Henderson
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

Verify that addr + size - 1 does not wrap around.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/qemu.h | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 534753ca12..a0f670832e 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -489,12 +489,19 @@ extern unsigned long guest_stack_size;
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1 /* implies read access */
 
-static inline int access_ok(int type, abi_ulong addr, abi_ulong size)
+static inline bool access_ok(int type, abi_ulong addr, abi_ulong size)
 {
-    return guest_addr_valid(addr) &&
-           (size == 0 || guest_addr_valid(addr + size - 1)) &&
-           page_check_range((target_ulong)addr, size,
-                            (type == VERIFY_READ) ? PAGE_READ : (PAGE_READ | PAGE_WRITE)) == 0;
+    if (!guest_addr_valid(addr)) {
+        return false;
+    }
+    if (size != 0 &&
+        (addr + size - 1 < addr ||
+         !guest_addr_valid(addr + size - 1))) {
+        return false;
+    }
+    return page_check_range((target_ulong)addr, size,
+                            (type == VERIFY_READ) ? PAGE_READ :
+                            (PAGE_READ | PAGE_WRITE)) == 0;
 }
 
 /* NOTE __get_user and __put_user use host pointers and don't check access.
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 07/21] linux-user: Tidy VERIFY_READ/VERIFY_WRITE
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
                   ` (5 preceding siblings ...)
  2021-01-15 22:46 ` [PATCH v3 06/21] linux-user: Check for overflow in access_ok Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-15 22:46 ` [PATCH v3 08/21] bsd-user: " Richard Henderson
                   ` (14 subsequent siblings)
  21 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

These constants are only ever used with access_ok, and friends.
Rather than translating them to PAGE_* bits, let them equal
the PAGE_* bits to begin.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/qemu.h | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index a0f670832e..329a6de669 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -486,8 +486,8 @@ extern unsigned long guest_stack_size;
 
 /* user access */
 
-#define VERIFY_READ 0
-#define VERIFY_WRITE 1 /* implies read access */
+#define VERIFY_READ  PAGE_READ
+#define VERIFY_WRITE (PAGE_READ | PAGE_WRITE)
 
 static inline bool access_ok(int type, abi_ulong addr, abi_ulong size)
 {
@@ -499,9 +499,7 @@ static inline bool access_ok(int type, abi_ulong addr, abi_ulong size)
          !guest_addr_valid(addr + size - 1))) {
         return false;
     }
-    return page_check_range((target_ulong)addr, size,
-                            (type == VERIFY_READ) ? PAGE_READ :
-                            (PAGE_READ | PAGE_WRITE)) == 0;
+    return page_check_range((target_ulong)addr, size, type) == 0;
 }
 
 /* NOTE __get_user and __put_user use host pointers and don't check access.
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 08/21] bsd-user: Tidy VERIFY_READ/VERIFY_WRITE
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
                   ` (6 preceding siblings ...)
  2021-01-15 22:46 ` [PATCH v3 07/21] linux-user: Tidy VERIFY_READ/VERIFY_WRITE Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-16 16:28   ` Warner Losh
  2021-01-15 22:46 ` [PATCH v3 09/21] linux-user: Do not use guest_addr_valid for h2g_valid Richard Henderson
                   ` (13 subsequent siblings)
  21 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

These constants are only ever used with access_ok, and friends.
Rather than translating them to PAGE_* bits, let them equal
the PAGE_* bits to begin.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 bsd-user/qemu.h | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index f8bb1e5459..4076adabd0 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -218,13 +218,12 @@ extern unsigned long x86_stack_size;
 
 /* user access */
 
-#define VERIFY_READ 0
-#define VERIFY_WRITE 1 /* implies read access */
+#define VERIFY_READ  PAGE_READ
+#define VERIFY_WRITE (PAGE_READ | PAGE_WRITE)
 
-static inline int access_ok(int type, abi_ulong addr, abi_ulong size)
+static inline bool access_ok(int type, abi_ulong addr, abi_ulong size)
 {
-    return page_check_range((target_ulong)addr, size,
-                            (type == VERIFY_READ) ? PAGE_READ : (PAGE_READ | PAGE_WRITE)) == 0;
+    return page_check_range((target_ulong)addr, size, type) == 0;
 }
 
 /* NOTE __get_user and __put_user use host pointers and don't check access. */
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 09/21] linux-user: Do not use guest_addr_valid for h2g_valid
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
                   ` (7 preceding siblings ...)
  2021-01-15 22:46 ` [PATCH v3 08/21] bsd-user: " Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-19 16:59   ` Peter Maydell
  2021-01-15 22:46 ` [PATCH v3 10/21] linux-user: Fix guest_addr_valid vs reserved_va Richard Henderson
                   ` (12 subsequent siblings)
  21 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

This is the only use of guest_addr_valid that does not begin
with a guest address, but a host address being transformed to
a guest address.

We will shortly adjust guest_addr_valid to handle guest memory
tags, and the host address should not be subjected to that.

Move h2g_valid adjacent to the other h2g macros.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v3: Ditch type changes; retain true for HLB <= GAM (pmm).
---
 include/exec/cpu_ldst.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
index 5e8878ee9b..4e6ef3d542 100644
--- a/include/exec/cpu_ldst.h
+++ b/include/exec/cpu_ldst.h
@@ -77,13 +77,16 @@ typedef uint64_t abi_ptr;
 #else
 #define guest_addr_valid(x) ((x) <= GUEST_ADDR_MAX)
 #endif
-#define h2g_valid(x) guest_addr_valid((uintptr_t)(x) - guest_base)
 
 static inline bool guest_range_valid(abi_ulong start, abi_ulong len)
 {
     return len - 1 <= GUEST_ADDR_MAX && start <= GUEST_ADDR_MAX - len + 1;
 }
 
+#define h2g_valid(x) \
+    (HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS || \
+     (uintptr_t)(x) - guest_base <= GUEST_ADDR_MAX)
+
 #define h2g_nocheck(x) ({ \
     uintptr_t __ret = (uintptr_t)(x) - guest_base; \
     (abi_ptr)__ret; \
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 10/21] linux-user: Fix guest_addr_valid vs reserved_va
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
                   ` (8 preceding siblings ...)
  2021-01-15 22:46 ` [PATCH v3 09/21] linux-user: Do not use guest_addr_valid for h2g_valid Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-19 17:03   ` Peter Maydell
  2021-01-15 22:46 ` [PATCH v3 11/21] exec: Add support for TARGET_TAGGED_ADDRESSES Richard Henderson
                   ` (11 subsequent siblings)
  21 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

We must always use GUEST_ADDR_MAX, because even 32-bit hosts can
use -R <reserved_va> to restrict the memory address of the guest.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/exec/cpu_ldst.h | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
index 4e6ef3d542..e62f4fba00 100644
--- a/include/exec/cpu_ldst.h
+++ b/include/exec/cpu_ldst.h
@@ -72,11 +72,10 @@ typedef uint64_t abi_ptr;
 /* All direct uses of g2h and h2g need to go away for usermode softmmu.  */
 #define g2h(x) ((void *)((uintptr_t)(abi_ptr)(x) + guest_base))
 
-#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
-#define guest_addr_valid(x) (1)
-#else
-#define guest_addr_valid(x) ((x) <= GUEST_ADDR_MAX)
-#endif
+static inline bool guest_addr_valid(abi_ulong x)
+{
+    return x <= GUEST_ADDR_MAX;
+}
 
 static inline bool guest_range_valid(abi_ulong start, abi_ulong len)
 {
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 11/21] exec: Add support for TARGET_TAGGED_ADDRESSES
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
                   ` (9 preceding siblings ...)
  2021-01-15 22:46 ` [PATCH v3 10/21] linux-user: Fix guest_addr_valid vs reserved_va Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-22 14:13   ` Peter Maydell
  2021-01-15 22:46 ` [PATCH v3 12/21] linux-user/aarch64: Implement PR_TAGGED_ADDR_ENABLE Richard Henderson
                   ` (10 subsequent siblings)
  21 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

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 | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
index e62f4fba00..1df9b93e59 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
 
+static inline abi_ptr untagged_addr(abi_ptr x)
+{
+#ifdef TARGET_TAGGED_ADDRESSES
+    if (current_cpu) {
+        return cpu_untagged_addr(current_cpu, x);
+    }
+#endif
+    return x;
+}
+
 /* All direct uses of g2h and h2g need to go away for usermode softmmu.  */
-#define g2h(x) ((void *)((uintptr_t)(abi_ptr)(x) + guest_base))
+static inline void *g2h(abi_ulong x)
+{
+    return (void *)((uintptr_t)untagged_addr(x) + guest_base);
+}
 
 static inline bool guest_addr_valid(abi_ulong x)
 {
-    return x <= GUEST_ADDR_MAX;
+    return untagged_addr(x) <= GUEST_ADDR_MAX;
 }
 
 static inline bool guest_range_valid(abi_ulong 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) \
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 12/21] linux-user/aarch64: Implement PR_TAGGED_ADDR_ENABLE
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
                   ` (10 preceding siblings ...)
  2021-01-15 22:46 ` [PATCH v3 11/21] exec: Add support for TARGET_TAGGED_ADDRESSES Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-22 11:36   ` Peter Maydell
  2021-01-22 11:53   ` Peter Maydell
  2021-01-15 22:46 ` [PATCH v3 13/21] linux-user/aarch64: Implement PR_MTE_TCF and PR_MTE_TAG Richard Henderson
                   ` (9 subsequent siblings)
  21 siblings, 2 replies; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

This is the prctl bit that controls whether syscalls accept tagged
addresses.  See Documentation/arm64/tagged-address-abi.rst in the
linux kernel.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/aarch64/target_syscall.h |  4 ++++
 target/arm/cpu-param.h              |  3 +++
 target/arm/cpu.h                    | 23 +++++++++++++++++++++++
 linux-user/syscall.c                | 25 +++++++++++++++++++++++++
 target/arm/cpu.c                    |  3 +++
 5 files changed, 58 insertions(+)

diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h
index 3194e6b009..820601dfcc 100644
--- a/linux-user/aarch64/target_syscall.h
+++ b/linux-user/aarch64/target_syscall.h
@@ -30,4 +30,8 @@ struct target_pt_regs {
 # define TARGET_PR_PAC_APDBKEY   (1 << 3)
 # define TARGET_PR_PAC_APGAKEY   (1 << 4)
 
+#define TARGET_PR_SET_TAGGED_ADDR_CTRL 55
+#define TARGET_PR_GET_TAGGED_ADDR_CTRL 56
+# define TARGET_PR_TAGGED_ADDR_ENABLE  (1UL << 0)
+
 #endif /* AARCH64_TARGET_SYSCALL_H */
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/target/arm/cpu.h b/target/arm/cpu.h
index f3bca73d98..6ddfd9ebe6 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -712,6 +712,10 @@ typedef struct CPUARMState {
     const struct arm_boot_info *boot_info;
     /* Store GICv3CPUState to access from this struct */
     void *gicv3state;
+
+#ifdef TARGET_TAGGED_ADDRESSES
+    target_ulong untagged_addr_mask;
+#endif
 } CPUARMState;
 
 static inline void set_feature(CPUARMState *env, int feature)
@@ -3556,6 +3560,25 @@ static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x)
  */
 #define PAGE_BTI  PAGE_TARGET_1
 
+#ifdef TARGET_TAGGED_ADDRESSES
+/**
+ * cpu_untagged_addr:
+ * @cs: CPU context
+ * @x: tagged address
+ *
+ * Remove any address tag from @x.  This is explicitly related to the
+ * linux syscall TIF_TAGGED_ADDR setting, not TBI in general.
+ *
+ * There should be a better place to put this, but we need this in
+ * include/exec/cpu_ldst.h, and not some place linux-user specific.
+ */
+static inline target_ulong cpu_untagged_addr(CPUState *cs, target_ulong x)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    return x & cpu->env.untagged_addr_mask;
+}
+#endif
+
 /*
  * Naming convention for isar_feature functions:
  * Functions which test 32-bit ID registers should have _aa32_ in
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index bec2ab7769..ebb4e2898c 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -10948,6 +10948,31 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
                 }
             }
             return -TARGET_EINVAL;
+        case TARGET_PR_SET_TAGGED_ADDR_CTRL:
+            {
+                abi_ulong valid_mask = TARGET_PR_TAGGED_ADDR_ENABLE;
+                CPUARMState *env = cpu_env;
+
+                if ((arg2 & ~valid_mask) || arg3 || arg4 || arg5) {
+                    return -TARGET_EINVAL;
+                }
+                env->untagged_addr_mask = (arg2 & TARGET_PR_TAGGED_ADDR_ENABLE
+                                           ? MAKE_64BIT_MASK(0, 56) : -1);
+                return 0;
+            }
+        case TARGET_PR_GET_TAGGED_ADDR_CTRL:
+            {
+                abi_long ret = 0;
+                CPUARMState *env = cpu_env;
+
+                if (arg2 || arg3 || arg4 || arg5) {
+                    return -TARGET_EINVAL;
+                }
+                if (env->untagged_addr_mask != -1) {
+                    ret |= TARGET_PR_TAGGED_ADDR_ENABLE;
+                }
+                return ret;
+            }
 #endif /* AARCH64 */
         case PR_GET_SECCOMP:
         case PR_SET_SECCOMP:
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 8387e94b94..abc0affd00 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -208,6 +208,9 @@ static void arm_cpu_reset(DeviceState *dev)
          * Do not modify this without other changes.
          */
         env->cp15.tcr_el[1].raw_tcr = (3ULL << 37);
+# ifdef TARGET_TAGGED_ADDRESSES
+        env->untagged_addr_mask = -1;
+# endif
 #else
         /* Reset into the highest available EL */
         if (arm_feature(env, ARM_FEATURE_EL3)) {
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 13/21] linux-user/aarch64: Implement PR_MTE_TCF and PR_MTE_TAG
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
                   ` (11 preceding siblings ...)
  2021-01-15 22:46 ` [PATCH v3 12/21] linux-user/aarch64: Implement PR_TAGGED_ADDR_ENABLE Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-22 11:48   ` Peter Maydell
  2021-01-15 22:46 ` [PATCH v3 14/21] linux-user/aarch64: Implement PROT_MTE Richard Henderson
                   ` (8 subsequent siblings)
  21 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

These prctl fields are required for the function of MTE.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/aarch64/target_syscall.h |  9 ++++++
 linux-user/syscall.c                | 44 +++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+)

diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h
index 820601dfcc..76f6c3391d 100644
--- a/linux-user/aarch64/target_syscall.h
+++ b/linux-user/aarch64/target_syscall.h
@@ -33,5 +33,14 @@ struct target_pt_regs {
 #define TARGET_PR_SET_TAGGED_ADDR_CTRL 55
 #define TARGET_PR_GET_TAGGED_ADDR_CTRL 56
 # define TARGET_PR_TAGGED_ADDR_ENABLE  (1UL << 0)
+/* MTE tag check fault modes */
+# define TARGET_PR_MTE_TCF_SHIFT       1
+# define TARGET_PR_MTE_TCF_NONE        (0UL << TARGET_PR_MTE_TCF_SHIFT)
+# define TARGET_PR_MTE_TCF_SYNC        (1UL << TARGET_PR_MTE_TCF_SHIFT)
+# define TARGET_PR_MTE_TCF_ASYNC       (2UL << TARGET_PR_MTE_TCF_SHIFT)
+# define TARGET_PR_MTE_TCF_MASK        (3UL << TARGET_PR_MTE_TCF_SHIFT)
+/* MTE tag inclusion mask */
+# define TARGET_PR_MTE_TAG_SHIFT       3
+# define TARGET_PR_MTE_TAG_MASK        (0xffffUL << TARGET_PR_MTE_TAG_SHIFT)
 
 #endif /* AARCH64_TARGET_SYSCALL_H */
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index ebb4e2898c..0316497636 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -10952,10 +10952,46 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
             {
                 abi_ulong valid_mask = TARGET_PR_TAGGED_ADDR_ENABLE;
                 CPUARMState *env = cpu_env;
+                ARMCPU *cpu = env_archcpu(env);
+
+                if (cpu_isar_feature(aa64_mte, cpu)) {
+                    valid_mask |= TARGET_PR_MTE_TCF_MASK;
+                    valid_mask |= TARGET_PR_MTE_TAG_MASK;
+                }
 
                 if ((arg2 & ~valid_mask) || arg3 || arg4 || arg5) {
                     return -TARGET_EINVAL;
                 }
+
+                if (cpu_isar_feature(aa64_mte, cpu)) {
+                    switch (arg2 & TARGET_PR_MTE_TCF_MASK) {
+                    case TARGET_PR_MTE_TCF_NONE:
+                    case TARGET_PR_MTE_TCF_SYNC:
+                    case TARGET_PR_MTE_TCF_ASYNC:
+                        break;
+                    default:
+                        return -EINVAL;
+                    }
+
+                    /*
+                     * Write PR_MTE_TCF to SCTLR_EL1[TCF0].
+                     * Note that the syscall values are consistent with hw.
+                     */
+                    env->cp15.sctlr_el[1] =
+                        deposit64(env->cp15.sctlr_el[1], 38, 2,
+                                  arg2 >> TARGET_PR_MTE_TCF_SHIFT);
+
+                    /*
+                     * Write PR_MTE_TAG to GCR_EL1[Exclude].
+                     * Note that the syscall uses an include mask,
+                     * and hardware uses an exclude mask -- invert.
+                     */
+                    env->cp15.gcr_el1 =
+                        deposit64(env->cp15.gcr_el1, 0, 16,
+                                  ~arg2 >> TARGET_PR_MTE_TAG_SHIFT);
+                    arm_rebuild_hflags(env);
+                }
+
                 env->untagged_addr_mask = (arg2 & TARGET_PR_TAGGED_ADDR_ENABLE
                                            ? MAKE_64BIT_MASK(0, 56) : -1);
                 return 0;
@@ -10964,6 +11000,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
             {
                 abi_long ret = 0;
                 CPUARMState *env = cpu_env;
+                ARMCPU *cpu = env_archcpu(env);
 
                 if (arg2 || arg3 || arg4 || arg5) {
                     return -TARGET_EINVAL;
@@ -10971,6 +11008,13 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
                 if (env->untagged_addr_mask != -1) {
                     ret |= TARGET_PR_TAGGED_ADDR_ENABLE;
                 }
+                if (cpu_isar_feature(aa64_mte, cpu)) {
+                    /* See above. */
+                    ret |= (extract64(env->cp15.sctlr_el[1], 38, 2)
+                            << TARGET_PR_MTE_TCF_SHIFT);
+                    ret = deposit64(ret, TARGET_PR_MTE_TAG_SHIFT, 16,
+                                    ~env->cp15.gcr_el1);
+                }
                 return ret;
             }
 #endif /* AARCH64 */
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 14/21] linux-user/aarch64: Implement PROT_MTE
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
                   ` (12 preceding siblings ...)
  2021-01-15 22:46 ` [PATCH v3 13/21] linux-user/aarch64: Implement PR_MTE_TCF and PR_MTE_TAG Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-15 22:46 ` [PATCH v3 15/21] target/arm: Split out syndrome.h from internals.h Richard Henderson
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

Remember the PROT_MTE bit as PAGE_MTE/PAGE_TARGET_2.
Otherwise this does not yet have effect.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v3: Do not overlap PAGE_TARGET_2 with PAGE_RESERVED.
---
 include/exec/cpu-all.h    |  1 +
 linux-user/syscall_defs.h |  1 +
 target/arm/cpu.h          |  1 +
 linux-user/mmap.c         | 22 ++++++++++++++--------
 4 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index c52180e8e6..b2a72f70ec 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -284,6 +284,7 @@ extern intptr_t qemu_host_page_mask;
 #endif
 /* Target-specific bits that will be used via page_get_flags().  */
 #define PAGE_TARGET_1  0x0080
+#define PAGE_TARGET_2  0x0200
 
 #if defined(CONFIG_USER_ONLY)
 void page_dump(FILE *f);
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index a00bfc2647..0d6bb1ff8b 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -1311,6 +1311,7 @@ struct target_winsize {
 
 #ifdef TARGET_AARCH64
 #define TARGET_PROT_BTI         0x10
+#define TARGET_PROT_MTE         0x20
 #endif
 
 /* Common */
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 6ddfd9ebe6..e14c9a6277 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3559,6 +3559,7 @@ static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x)
  * AArch64 usage of the PAGE_TARGET_* bits for linux-user.
  */
 #define PAGE_BTI  PAGE_TARGET_1
+#define PAGE_MTE  PAGE_TARGET_2
 
 #ifdef TARGET_TAGGED_ADDRESSES
 /**
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 7fb4c628e1..34bd114f97 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -84,18 +84,24 @@ static int validate_prot_to_pageflags(int *host_prot, int prot)
                | (prot & PROT_EXEC ? PROT_READ : 0);
 
 #ifdef TARGET_AARCH64
-    /*
-     * The PROT_BTI bit is only accepted if the cpu supports the feature.
-     * Since this is the unusual case, don't bother checking unless
-     * the bit has been requested.  If set and valid, record the bit
-     * within QEMU's page_flags.
-     */
-    if (prot & TARGET_PROT_BTI) {
+    {
         ARMCPU *cpu = ARM_CPU(thread_cpu);
-        if (cpu_isar_feature(aa64_bti, cpu)) {
+
+        /*
+         * The PROT_BTI bit is only accepted if the cpu supports the feature.
+         * Since this is the unusual case, don't bother checking unless
+         * the bit has been requested.  If set and valid, record the bit
+         * within QEMU's page_flags.
+         */
+        if ((prot & TARGET_PROT_BTI) && cpu_isar_feature(aa64_bti, cpu)) {
             valid |= TARGET_PROT_BTI;
             page_flags |= PAGE_BTI;
         }
+        /* Similarly for the PROT_MTE bit. */
+        if ((prot & TARGET_PROT_MTE) && cpu_isar_feature(aa64_mte, cpu)) {
+            valid |= TARGET_PROT_MTE;
+            page_flags |= PAGE_MTE;
+        }
     }
 #endif
 
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 15/21] target/arm: Split out syndrome.h from internals.h
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
                   ` (13 preceding siblings ...)
  2021-01-15 22:46 ` [PATCH v3 14/21] linux-user/aarch64: Implement PROT_MTE Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-19 17:07   ` Peter Maydell
  2021-01-15 22:46 ` [PATCH v3 16/21] linux-user/aarch64: Pass syndrome to EXC_*_ABORT Richard Henderson
                   ` (6 subsequent siblings)
  21 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

Move everything related to syndromes to a new file,
which can be shared with linux-user.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/internals.h | 245 +-----------------------------------
 target/arm/syndrome.h  | 273 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 274 insertions(+), 244 deletions(-)
 create mode 100644 target/arm/syndrome.h

diff --git a/target/arm/internals.h b/target/arm/internals.h
index 5460678756..1e60c0e0e8 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -26,6 +26,7 @@
 #define TARGET_ARM_INTERNALS_H
 
 #include "hw/registerfields.h"
+#include "syndrome.h"
 
 /* register banks for CPU modes */
 #define BANK_USRSYS 0
@@ -256,250 +257,6 @@ static inline bool extended_addresses_enabled(CPUARMState *env)
            (arm_feature(env, ARM_FEATURE_LPAE) && (tcr->raw_tcr & TTBCR_EAE));
 }
 
-/* Valid Syndrome Register EC field values */
-enum arm_exception_class {
-    EC_UNCATEGORIZED          = 0x00,
-    EC_WFX_TRAP               = 0x01,
-    EC_CP15RTTRAP             = 0x03,
-    EC_CP15RRTTRAP            = 0x04,
-    EC_CP14RTTRAP             = 0x05,
-    EC_CP14DTTRAP             = 0x06,
-    EC_ADVSIMDFPACCESSTRAP    = 0x07,
-    EC_FPIDTRAP               = 0x08,
-    EC_PACTRAP                = 0x09,
-    EC_CP14RRTTRAP            = 0x0c,
-    EC_BTITRAP                = 0x0d,
-    EC_ILLEGALSTATE           = 0x0e,
-    EC_AA32_SVC               = 0x11,
-    EC_AA32_HVC               = 0x12,
-    EC_AA32_SMC               = 0x13,
-    EC_AA64_SVC               = 0x15,
-    EC_AA64_HVC               = 0x16,
-    EC_AA64_SMC               = 0x17,
-    EC_SYSTEMREGISTERTRAP     = 0x18,
-    EC_SVEACCESSTRAP          = 0x19,
-    EC_INSNABORT              = 0x20,
-    EC_INSNABORT_SAME_EL      = 0x21,
-    EC_PCALIGNMENT            = 0x22,
-    EC_DATAABORT              = 0x24,
-    EC_DATAABORT_SAME_EL      = 0x25,
-    EC_SPALIGNMENT            = 0x26,
-    EC_AA32_FPTRAP            = 0x28,
-    EC_AA64_FPTRAP            = 0x2c,
-    EC_SERROR                 = 0x2f,
-    EC_BREAKPOINT             = 0x30,
-    EC_BREAKPOINT_SAME_EL     = 0x31,
-    EC_SOFTWARESTEP           = 0x32,
-    EC_SOFTWARESTEP_SAME_EL   = 0x33,
-    EC_WATCHPOINT             = 0x34,
-    EC_WATCHPOINT_SAME_EL     = 0x35,
-    EC_AA32_BKPT              = 0x38,
-    EC_VECTORCATCH            = 0x3a,
-    EC_AA64_BKPT              = 0x3c,
-};
-
-#define ARM_EL_EC_SHIFT 26
-#define ARM_EL_IL_SHIFT 25
-#define ARM_EL_ISV_SHIFT 24
-#define ARM_EL_IL (1 << ARM_EL_IL_SHIFT)
-#define ARM_EL_ISV (1 << ARM_EL_ISV_SHIFT)
-
-static inline uint32_t syn_get_ec(uint32_t syn)
-{
-    return syn >> ARM_EL_EC_SHIFT;
-}
-
-/* Utility functions for constructing various kinds of syndrome value.
- * Note that in general we follow the AArch64 syndrome values; in a
- * few cases the value in HSR for exceptions taken to AArch32 Hyp
- * mode differs slightly, and we fix this up when populating HSR in
- * arm_cpu_do_interrupt_aarch32_hyp().
- * The exception is FP/SIMD access traps -- these report extra information
- * when taking an exception to AArch32. For those we include the extra coproc
- * and TA fields, and mask them out when taking the exception to AArch64.
- */
-static inline uint32_t syn_uncategorized(void)
-{
-    return (EC_UNCATEGORIZED << ARM_EL_EC_SHIFT) | ARM_EL_IL;
-}
-
-static inline uint32_t syn_aa64_svc(uint32_t imm16)
-{
-    return (EC_AA64_SVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
-}
-
-static inline uint32_t syn_aa64_hvc(uint32_t imm16)
-{
-    return (EC_AA64_HVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
-}
-
-static inline uint32_t syn_aa64_smc(uint32_t imm16)
-{
-    return (EC_AA64_SMC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
-}
-
-static inline uint32_t syn_aa32_svc(uint32_t imm16, bool is_16bit)
-{
-    return (EC_AA32_SVC << ARM_EL_EC_SHIFT) | (imm16 & 0xffff)
-        | (is_16bit ? 0 : ARM_EL_IL);
-}
-
-static inline uint32_t syn_aa32_hvc(uint32_t imm16)
-{
-    return (EC_AA32_HVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
-}
-
-static inline uint32_t syn_aa32_smc(void)
-{
-    return (EC_AA32_SMC << ARM_EL_EC_SHIFT) | ARM_EL_IL;
-}
-
-static inline uint32_t syn_aa64_bkpt(uint32_t imm16)
-{
-    return (EC_AA64_BKPT << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
-}
-
-static inline uint32_t syn_aa32_bkpt(uint32_t imm16, bool is_16bit)
-{
-    return (EC_AA32_BKPT << ARM_EL_EC_SHIFT) | (imm16 & 0xffff)
-        | (is_16bit ? 0 : ARM_EL_IL);
-}
-
-static inline uint32_t syn_aa64_sysregtrap(int op0, int op1, int op2,
-                                           int crn, int crm, int rt,
-                                           int isread)
-{
-    return (EC_SYSTEMREGISTERTRAP << ARM_EL_EC_SHIFT) | ARM_EL_IL
-        | (op0 << 20) | (op2 << 17) | (op1 << 14) | (crn << 10) | (rt << 5)
-        | (crm << 1) | isread;
-}
-
-static inline uint32_t syn_cp14_rt_trap(int cv, int cond, int opc1, int opc2,
-                                        int crn, int crm, int rt, int isread,
-                                        bool is_16bit)
-{
-    return (EC_CP14RTTRAP << ARM_EL_EC_SHIFT)
-        | (is_16bit ? 0 : ARM_EL_IL)
-        | (cv << 24) | (cond << 20) | (opc2 << 17) | (opc1 << 14)
-        | (crn << 10) | (rt << 5) | (crm << 1) | isread;
-}
-
-static inline uint32_t syn_cp15_rt_trap(int cv, int cond, int opc1, int opc2,
-                                        int crn, int crm, int rt, int isread,
-                                        bool is_16bit)
-{
-    return (EC_CP15RTTRAP << ARM_EL_EC_SHIFT)
-        | (is_16bit ? 0 : ARM_EL_IL)
-        | (cv << 24) | (cond << 20) | (opc2 << 17) | (opc1 << 14)
-        | (crn << 10) | (rt << 5) | (crm << 1) | isread;
-}
-
-static inline uint32_t syn_cp14_rrt_trap(int cv, int cond, int opc1, int crm,
-                                         int rt, int rt2, int isread,
-                                         bool is_16bit)
-{
-    return (EC_CP14RRTTRAP << ARM_EL_EC_SHIFT)
-        | (is_16bit ? 0 : ARM_EL_IL)
-        | (cv << 24) | (cond << 20) | (opc1 << 16)
-        | (rt2 << 10) | (rt << 5) | (crm << 1) | isread;
-}
-
-static inline uint32_t syn_cp15_rrt_trap(int cv, int cond, int opc1, int crm,
-                                         int rt, int rt2, int isread,
-                                         bool is_16bit)
-{
-    return (EC_CP15RRTTRAP << ARM_EL_EC_SHIFT)
-        | (is_16bit ? 0 : ARM_EL_IL)
-        | (cv << 24) | (cond << 20) | (opc1 << 16)
-        | (rt2 << 10) | (rt << 5) | (crm << 1) | isread;
-}
-
-static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_16bit)
-{
-    /* AArch32 FP trap or any AArch64 FP/SIMD trap: TA == 0 coproc == 0xa */
-    return (EC_ADVSIMDFPACCESSTRAP << ARM_EL_EC_SHIFT)
-        | (is_16bit ? 0 : ARM_EL_IL)
-        | (cv << 24) | (cond << 20) | 0xa;
-}
-
-static inline uint32_t syn_simd_access_trap(int cv, int cond, bool is_16bit)
-{
-    /* AArch32 SIMD trap: TA == 1 coproc == 0 */
-    return (EC_ADVSIMDFPACCESSTRAP << ARM_EL_EC_SHIFT)
-        | (is_16bit ? 0 : ARM_EL_IL)
-        | (cv << 24) | (cond << 20) | (1 << 5);
-}
-
-static inline uint32_t syn_sve_access_trap(void)
-{
-    return EC_SVEACCESSTRAP << ARM_EL_EC_SHIFT;
-}
-
-static inline uint32_t syn_pactrap(void)
-{
-    return EC_PACTRAP << ARM_EL_EC_SHIFT;
-}
-
-static inline uint32_t syn_btitrap(int btype)
-{
-    return (EC_BTITRAP << ARM_EL_EC_SHIFT) | btype;
-}
-
-static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc)
-{
-    return (EC_INSNABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
-        | ARM_EL_IL | (ea << 9) | (s1ptw << 7) | fsc;
-}
-
-static inline uint32_t syn_data_abort_no_iss(int same_el, int fnv,
-                                             int ea, int cm, int s1ptw,
-                                             int wnr, int fsc)
-{
-    return (EC_DATAABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
-           | ARM_EL_IL
-           | (fnv << 10) | (ea << 9) | (cm << 8) | (s1ptw << 7)
-           | (wnr << 6) | fsc;
-}
-
-static inline uint32_t syn_data_abort_with_iss(int same_el,
-                                               int sas, int sse, int srt,
-                                               int sf, int ar,
-                                               int ea, int cm, int s1ptw,
-                                               int wnr, int fsc,
-                                               bool is_16bit)
-{
-    return (EC_DATAABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
-           | (is_16bit ? 0 : ARM_EL_IL)
-           | ARM_EL_ISV | (sas << 22) | (sse << 21) | (srt << 16)
-           | (sf << 15) | (ar << 14)
-           | (ea << 9) | (cm << 8) | (s1ptw << 7) | (wnr << 6) | fsc;
-}
-
-static inline uint32_t syn_swstep(int same_el, int isv, int ex)
-{
-    return (EC_SOFTWARESTEP << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
-        | ARM_EL_IL | (isv << 24) | (ex << 6) | 0x22;
-}
-
-static inline uint32_t syn_watchpoint(int same_el, int cm, int wnr)
-{
-    return (EC_WATCHPOINT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
-        | ARM_EL_IL | (cm << 8) | (wnr << 6) | 0x22;
-}
-
-static inline uint32_t syn_breakpoint(int same_el)
-{
-    return (EC_BREAKPOINT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
-        | ARM_EL_IL | 0x22;
-}
-
-static inline uint32_t syn_wfx(int cv, int cond, int ti, bool is_16bit)
-{
-    return (EC_WFX_TRAP << ARM_EL_EC_SHIFT) |
-           (is_16bit ? 0 : (1 << ARM_EL_IL_SHIFT)) |
-           (cv << 24) | (cond << 20) | ti;
-}
-
 /* Update a QEMU watchpoint based on the information the guest has set in the
  * DBGWCR<n>_EL1 and DBGWVR<n>_EL1 registers.
  */
diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
new file mode 100644
index 0000000000..39a31260f2
--- /dev/null
+++ b/target/arm/syndrome.h
@@ -0,0 +1,273 @@
+/*
+ * QEMU ARM CPU -- syndrome functions and types
+ *
+ * Copyright (c) 2014 Linaro Ltd
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
+ *
+ * This header defines functions, types, etc which need to be shared
+ * between different source files within target/arm/ but which are
+ * private to it and not required by the rest of QEMU.
+ */
+
+#ifndef TARGET_ARM_SYNDROME_H
+#define TARGET_ARM_SYNDROME_H
+
+/* Valid Syndrome Register EC field values */
+enum arm_exception_class {
+    EC_UNCATEGORIZED          = 0x00,
+    EC_WFX_TRAP               = 0x01,
+    EC_CP15RTTRAP             = 0x03,
+    EC_CP15RRTTRAP            = 0x04,
+    EC_CP14RTTRAP             = 0x05,
+    EC_CP14DTTRAP             = 0x06,
+    EC_ADVSIMDFPACCESSTRAP    = 0x07,
+    EC_FPIDTRAP               = 0x08,
+    EC_PACTRAP                = 0x09,
+    EC_CP14RRTTRAP            = 0x0c,
+    EC_BTITRAP                = 0x0d,
+    EC_ILLEGALSTATE           = 0x0e,
+    EC_AA32_SVC               = 0x11,
+    EC_AA32_HVC               = 0x12,
+    EC_AA32_SMC               = 0x13,
+    EC_AA64_SVC               = 0x15,
+    EC_AA64_HVC               = 0x16,
+    EC_AA64_SMC               = 0x17,
+    EC_SYSTEMREGISTERTRAP     = 0x18,
+    EC_SVEACCESSTRAP          = 0x19,
+    EC_INSNABORT              = 0x20,
+    EC_INSNABORT_SAME_EL      = 0x21,
+    EC_PCALIGNMENT            = 0x22,
+    EC_DATAABORT              = 0x24,
+    EC_DATAABORT_SAME_EL      = 0x25,
+    EC_SPALIGNMENT            = 0x26,
+    EC_AA32_FPTRAP            = 0x28,
+    EC_AA64_FPTRAP            = 0x2c,
+    EC_SERROR                 = 0x2f,
+    EC_BREAKPOINT             = 0x30,
+    EC_BREAKPOINT_SAME_EL     = 0x31,
+    EC_SOFTWARESTEP           = 0x32,
+    EC_SOFTWARESTEP_SAME_EL   = 0x33,
+    EC_WATCHPOINT             = 0x34,
+    EC_WATCHPOINT_SAME_EL     = 0x35,
+    EC_AA32_BKPT              = 0x38,
+    EC_VECTORCATCH            = 0x3a,
+    EC_AA64_BKPT              = 0x3c,
+};
+
+#define ARM_EL_EC_SHIFT 26
+#define ARM_EL_IL_SHIFT 25
+#define ARM_EL_ISV_SHIFT 24
+#define ARM_EL_IL (1 << ARM_EL_IL_SHIFT)
+#define ARM_EL_ISV (1 << ARM_EL_ISV_SHIFT)
+
+static inline uint32_t syn_get_ec(uint32_t syn)
+{
+    return syn >> ARM_EL_EC_SHIFT;
+}
+
+/*
+ * Utility functions for constructing various kinds of syndrome value.
+ * Note that in general we follow the AArch64 syndrome values; in a
+ * few cases the value in HSR for exceptions taken to AArch32 Hyp
+ * mode differs slightly, and we fix this up when populating HSR in
+ * arm_cpu_do_interrupt_aarch32_hyp().
+ * The exception is FP/SIMD access traps -- these report extra information
+ * when taking an exception to AArch32. For those we include the extra coproc
+ * and TA fields, and mask them out when taking the exception to AArch64.
+ */
+static inline uint32_t syn_uncategorized(void)
+{
+    return (EC_UNCATEGORIZED << ARM_EL_EC_SHIFT) | ARM_EL_IL;
+}
+
+static inline uint32_t syn_aa64_svc(uint32_t imm16)
+{
+    return (EC_AA64_SVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
+}
+
+static inline uint32_t syn_aa64_hvc(uint32_t imm16)
+{
+    return (EC_AA64_HVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
+}
+
+static inline uint32_t syn_aa64_smc(uint32_t imm16)
+{
+    return (EC_AA64_SMC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
+}
+
+static inline uint32_t syn_aa32_svc(uint32_t imm16, bool is_16bit)
+{
+    return (EC_AA32_SVC << ARM_EL_EC_SHIFT) | (imm16 & 0xffff)
+        | (is_16bit ? 0 : ARM_EL_IL);
+}
+
+static inline uint32_t syn_aa32_hvc(uint32_t imm16)
+{
+    return (EC_AA32_HVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
+}
+
+static inline uint32_t syn_aa32_smc(void)
+{
+    return (EC_AA32_SMC << ARM_EL_EC_SHIFT) | ARM_EL_IL;
+}
+
+static inline uint32_t syn_aa64_bkpt(uint32_t imm16)
+{
+    return (EC_AA64_BKPT << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
+}
+
+static inline uint32_t syn_aa32_bkpt(uint32_t imm16, bool is_16bit)
+{
+    return (EC_AA32_BKPT << ARM_EL_EC_SHIFT) | (imm16 & 0xffff)
+        | (is_16bit ? 0 : ARM_EL_IL);
+}
+
+static inline uint32_t syn_aa64_sysregtrap(int op0, int op1, int op2,
+                                           int crn, int crm, int rt,
+                                           int isread)
+{
+    return (EC_SYSTEMREGISTERTRAP << ARM_EL_EC_SHIFT) | ARM_EL_IL
+        | (op0 << 20) | (op2 << 17) | (op1 << 14) | (crn << 10) | (rt << 5)
+        | (crm << 1) | isread;
+}
+
+static inline uint32_t syn_cp14_rt_trap(int cv, int cond, int opc1, int opc2,
+                                        int crn, int crm, int rt, int isread,
+                                        bool is_16bit)
+{
+    return (EC_CP14RTTRAP << ARM_EL_EC_SHIFT)
+        | (is_16bit ? 0 : ARM_EL_IL)
+        | (cv << 24) | (cond << 20) | (opc2 << 17) | (opc1 << 14)
+        | (crn << 10) | (rt << 5) | (crm << 1) | isread;
+}
+
+static inline uint32_t syn_cp15_rt_trap(int cv, int cond, int opc1, int opc2,
+                                        int crn, int crm, int rt, int isread,
+                                        bool is_16bit)
+{
+    return (EC_CP15RTTRAP << ARM_EL_EC_SHIFT)
+        | (is_16bit ? 0 : ARM_EL_IL)
+        | (cv << 24) | (cond << 20) | (opc2 << 17) | (opc1 << 14)
+        | (crn << 10) | (rt << 5) | (crm << 1) | isread;
+}
+
+static inline uint32_t syn_cp14_rrt_trap(int cv, int cond, int opc1, int crm,
+                                         int rt, int rt2, int isread,
+                                         bool is_16bit)
+{
+    return (EC_CP14RRTTRAP << ARM_EL_EC_SHIFT)
+        | (is_16bit ? 0 : ARM_EL_IL)
+        | (cv << 24) | (cond << 20) | (opc1 << 16)
+        | (rt2 << 10) | (rt << 5) | (crm << 1) | isread;
+}
+
+static inline uint32_t syn_cp15_rrt_trap(int cv, int cond, int opc1, int crm,
+                                         int rt, int rt2, int isread,
+                                         bool is_16bit)
+{
+    return (EC_CP15RRTTRAP << ARM_EL_EC_SHIFT)
+        | (is_16bit ? 0 : ARM_EL_IL)
+        | (cv << 24) | (cond << 20) | (opc1 << 16)
+        | (rt2 << 10) | (rt << 5) | (crm << 1) | isread;
+}
+
+static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_16bit)
+{
+    /* AArch32 FP trap or any AArch64 FP/SIMD trap: TA == 0 coproc == 0xa */
+    return (EC_ADVSIMDFPACCESSTRAP << ARM_EL_EC_SHIFT)
+        | (is_16bit ? 0 : ARM_EL_IL)
+        | (cv << 24) | (cond << 20) | 0xa;
+}
+
+static inline uint32_t syn_simd_access_trap(int cv, int cond, bool is_16bit)
+{
+    /* AArch32 SIMD trap: TA == 1 coproc == 0 */
+    return (EC_ADVSIMDFPACCESSTRAP << ARM_EL_EC_SHIFT)
+        | (is_16bit ? 0 : ARM_EL_IL)
+        | (cv << 24) | (cond << 20) | (1 << 5);
+}
+
+static inline uint32_t syn_sve_access_trap(void)
+{
+    return EC_SVEACCESSTRAP << ARM_EL_EC_SHIFT;
+}
+
+static inline uint32_t syn_pactrap(void)
+{
+    return EC_PACTRAP << ARM_EL_EC_SHIFT;
+}
+
+static inline uint32_t syn_btitrap(int btype)
+{
+    return (EC_BTITRAP << ARM_EL_EC_SHIFT) | btype;
+}
+
+static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc)
+{
+    return (EC_INSNABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
+        | ARM_EL_IL | (ea << 9) | (s1ptw << 7) | fsc;
+}
+
+static inline uint32_t syn_data_abort_no_iss(int same_el, int fnv,
+                                             int ea, int cm, int s1ptw,
+                                             int wnr, int fsc)
+{
+    return (EC_DATAABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
+           | ARM_EL_IL
+           | (fnv << 10) | (ea << 9) | (cm << 8) | (s1ptw << 7)
+           | (wnr << 6) | fsc;
+}
+
+static inline uint32_t syn_data_abort_with_iss(int same_el,
+                                               int sas, int sse, int srt,
+                                               int sf, int ar,
+                                               int ea, int cm, int s1ptw,
+                                               int wnr, int fsc,
+                                               bool is_16bit)
+{
+    return (EC_DATAABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
+           | (is_16bit ? 0 : ARM_EL_IL)
+           | ARM_EL_ISV | (sas << 22) | (sse << 21) | (srt << 16)
+           | (sf << 15) | (ar << 14)
+           | (ea << 9) | (cm << 8) | (s1ptw << 7) | (wnr << 6) | fsc;
+}
+
+static inline uint32_t syn_swstep(int same_el, int isv, int ex)
+{
+    return (EC_SOFTWARESTEP << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
+        | ARM_EL_IL | (isv << 24) | (ex << 6) | 0x22;
+}
+
+static inline uint32_t syn_watchpoint(int same_el, int cm, int wnr)
+{
+    return (EC_WATCHPOINT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
+        | ARM_EL_IL | (cm << 8) | (wnr << 6) | 0x22;
+}
+
+static inline uint32_t syn_breakpoint(int same_el)
+{
+    return (EC_BREAKPOINT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
+        | ARM_EL_IL | 0x22;
+}
+
+static inline uint32_t syn_wfx(int cv, int cond, int ti, bool is_16bit)
+{
+    return (EC_WFX_TRAP << ARM_EL_EC_SHIFT) |
+           (is_16bit ? 0 : (1 << ARM_EL_IL_SHIFT)) |
+           (cv << 24) | (cond << 20) | ti;
+}
+
+#endif /* TARGET_ARM_SYNDROME_H */
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 16/21] linux-user/aarch64: Pass syndrome to EXC_*_ABORT
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
                   ` (14 preceding siblings ...)
  2021-01-15 22:46 ` [PATCH v3 15/21] target/arm: Split out syndrome.h from internals.h Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-19 17:12   ` Peter Maydell
  2021-01-15 22:46 ` [PATCH v3 17/21] linux-user/aarch64: Signal SEGV_MTESERR for sync tag check fault Richard Henderson
                   ` (5 subsequent siblings)
  21 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

A proper syndrome is required to fill in the proper si_code.
Use page_get_flags to determine permission vs translation for user-only.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v3: Use syndrome.h, arm_deliver_fault.
---
 linux-user/aarch64/cpu_loop.c | 24 +++++++++++++++++++++---
 target/arm/tlb_helper.c       | 15 +++++++++------
 2 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
index bbe9fefca8..7811440c68 100644
--- a/linux-user/aarch64/cpu_loop.c
+++ b/linux-user/aarch64/cpu_loop.c
@@ -22,6 +22,7 @@
 #include "qemu.h"
 #include "cpu_loop-common.h"
 #include "qemu/guest-random.h"
+#include "target/arm/syndrome.h"
 
 #define get_user_code_u32(x, gaddr, env)                \
     ({ abi_long __r = get_user_u32((x), (gaddr));       \
@@ -75,7 +76,7 @@
 void cpu_loop(CPUARMState *env)
 {
     CPUState *cs = env_cpu(env);
-    int trapnr;
+    int trapnr, ec, fsc;
     abi_long ret;
     target_siginfo_t info;
 
@@ -116,9 +117,26 @@ void cpu_loop(CPUARMState *env)
         case EXCP_DATA_ABORT:
             info.si_signo = TARGET_SIGSEGV;
             info.si_errno = 0;
-            /* XXX: check env->error_code */
-            info.si_code = TARGET_SEGV_MAPERR;
             info._sifields._sigfault._addr = env->exception.vaddress;
+
+            /* We should only arrive here with EC in {DATAABORT, INSNABORT}. */
+            ec = syn_get_ec(env->exception.syndrome);
+            assert(ec == EC_DATAABORT || ec == EC_INSNABORT);
+
+            /* Both EC have the same format for FSC, or close enough. */
+            fsc = extract32(env->exception.syndrome, 0, 6);
+            switch (fsc) {
+            case 0x04 ... 0x07: /* Translation fault, level {0-3} */
+                info.si_code = TARGET_SEGV_MAPERR;
+                break;
+            case 0x09 ... 0x0b: /* Access flag fault, level {1-3} */
+            case 0x0d ... 0x0f: /* Permission fault, level {1-3} */
+                info.si_code = TARGET_SEGV_ACCERR;
+                break;
+            default:
+                g_assert_not_reached();
+            }
+
             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
             break;
         case EXCP_DEBUG:
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
index b35dc8a011..31015749fd 100644
--- a/target/arm/tlb_helper.c
+++ b/target/arm/tlb_helper.c
@@ -151,21 +151,24 @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
                       bool probe, uintptr_t retaddr)
 {
     ARMCPU *cpu = ARM_CPU(cs);
+    ARMMMUFaultInfo fi = {};
 
 #ifdef CONFIG_USER_ONLY
-    cpu->env.exception.vaddress = address;
-    if (access_type == MMU_INST_FETCH) {
-        cs->exception_index = EXCP_PREFETCH_ABORT;
+    int flags = page_get_flags(useronly_clean_ptr(address));
+    if (flags & PAGE_VALID) {
+        fi.type = ARMFault_Permission;
     } else {
-        cs->exception_index = EXCP_DATA_ABORT;
+        fi.type = ARMFault_Translation;
     }
-    cpu_loop_exit_restore(cs, retaddr);
+
+    /* now we have a real cpu fault */
+    cpu_restore_state(cs, retaddr, true);
+    arm_deliver_fault(cpu, address, access_type, mmu_idx, &fi);
 #else
     hwaddr phys_addr;
     target_ulong page_size;
     int prot, ret;
     MemTxAttrs attrs = {};
-    ARMMMUFaultInfo fi = {};
     ARMCacheAttrs cacheattrs = {};
 
     /*
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 17/21] linux-user/aarch64: Signal SEGV_MTESERR for sync tag check fault
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
                   ` (15 preceding siblings ...)
  2021-01-15 22:46 ` [PATCH v3 16/21] linux-user/aarch64: Pass syndrome to EXC_*_ABORT Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-22 12:03   ` Peter Maydell
  2021-01-15 22:46 ` [PATCH v3 18/21] linux-user/aarch64: Signal SEGV_MTEAERR for async tag check error Richard Henderson
                   ` (4 subsequent siblings)
  21 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/aarch64/target_signal.h | 2 ++
 linux-user/aarch64/cpu_loop.c      | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/linux-user/aarch64/target_signal.h b/linux-user/aarch64/target_signal.h
index ddd73169f0..777fb667fe 100644
--- a/linux-user/aarch64/target_signal.h
+++ b/linux-user/aarch64/target_signal.h
@@ -21,5 +21,7 @@ typedef struct target_sigaltstack {
 
 #include "../generic/signal.h"
 
+#define TARGET_SEGV_MTESERR  9  /* Synchronous ARM MTE exception */
+
 #define TARGET_ARCH_HAS_SETUP_FRAME
 #endif /* AARCH64_TARGET_SIGNAL_H */
diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
index 7811440c68..6867f0db2b 100644
--- a/linux-user/aarch64/cpu_loop.c
+++ b/linux-user/aarch64/cpu_loop.c
@@ -133,6 +133,9 @@ void cpu_loop(CPUARMState *env)
             case 0x0d ... 0x0f: /* Permission fault, level {1-3} */
                 info.si_code = TARGET_SEGV_ACCERR;
                 break;
+            case 0x11: /* Synchronous Tag Check Fault */
+                info.si_code = TARGET_SEGV_MTESERR;
+                break;
             default:
                 g_assert_not_reached();
             }
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 18/21] linux-user/aarch64: Signal SEGV_MTEAERR for async tag check error
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
                   ` (16 preceding siblings ...)
  2021-01-15 22:46 ` [PATCH v3 17/21] linux-user/aarch64: Signal SEGV_MTESERR for sync tag check fault Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-22 13:59   ` Peter Maydell
  2021-01-15 22:46 ` [PATCH v3 19/21] target/arm: Add allocation tag storage for user mode Richard Henderson
                   ` (3 subsequent siblings)
  21 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/aarch64/target_signal.h |  1 +
 linux-user/aarch64/cpu_loop.c      | 34 +++++++++++++++++++++---------
 target/arm/mte_helper.c            | 10 +++++++++
 3 files changed, 35 insertions(+), 10 deletions(-)

diff --git a/linux-user/aarch64/target_signal.h b/linux-user/aarch64/target_signal.h
index 777fb667fe..18013e1b23 100644
--- a/linux-user/aarch64/target_signal.h
+++ b/linux-user/aarch64/target_signal.h
@@ -21,6 +21,7 @@ typedef struct target_sigaltstack {
 
 #include "../generic/signal.h"
 
+#define TARGET_SEGV_MTEAERR  8  /* Asynchronous ARM MTE error */
 #define TARGET_SEGV_MTESERR  9  /* Synchronous ARM MTE exception */
 
 #define TARGET_ARCH_HAS_SETUP_FRAME
diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
index 6867f0db2b..6160a401bd 100644
--- a/linux-user/aarch64/cpu_loop.c
+++ b/linux-user/aarch64/cpu_loop.c
@@ -72,6 +72,21 @@
         put_user_u16(__x, (gaddr));                     \
     })
 
+static bool check_mte_async_fault(CPUARMState *env, target_siginfo_t *info)
+{
+    if (likely(env->cp15.tfsr_el[0] == 0)) {
+        return false;
+    }
+
+    env->cp15.tfsr_el[0] = 0;
+    info->si_signo = TARGET_SIGSEGV;
+    info->si_errno = 0;
+    info->_sifields._sigfault._addr = 0;
+    info->si_code = TARGET_SEGV_MTEAERR;
+    queue_signal(env, info->si_signo, QEMU_SI_FAULT, info);
+    return true;
+}
+
 /* AArch64 main loop */
 void cpu_loop(CPUARMState *env)
 {
@@ -88,15 +103,13 @@ void cpu_loop(CPUARMState *env)
 
         switch (trapnr) {
         case EXCP_SWI:
-            ret = do_syscall(env,
-                             env->xregs[8],
-                             env->xregs[0],
-                             env->xregs[1],
-                             env->xregs[2],
-                             env->xregs[3],
-                             env->xregs[4],
-                             env->xregs[5],
-                             0, 0);
+            if (check_mte_async_fault(env, &info)) {
+                ret = -TARGET_ERESTARTSYS;
+            } else {
+                ret = do_syscall(env, env->xregs[8], env->xregs[0],
+                                 env->xregs[1], env->xregs[2], env->xregs[3],
+                                 env->xregs[4], env->xregs[5], 0, 0);
+            }
             if (ret == -TARGET_ERESTARTSYS) {
                 env->pc -= 4;
             } else if (ret != -TARGET_QEMU_ESIGRETURN) {
@@ -104,7 +117,8 @@ void cpu_loop(CPUARMState *env)
             }
             break;
         case EXCP_INTERRUPT:
-            /* just indicate that signals should be handled asap */
+            /* Just indicate that signals should be handled asap. */
+            check_mte_async_fault(env, &info);
             break;
         case EXCP_UDEF:
             info.si_signo = TARGET_SIGILL;
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
index 153bd1e9df..d55f8d1e1e 100644
--- a/target/arm/mte_helper.c
+++ b/target/arm/mte_helper.c
@@ -565,6 +565,16 @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
             select = 0;
         }
         env->cp15.tfsr_el[el] |= 1 << select;
+#ifdef CONFIG_USER_ONLY
+        /*
+         * Stand in for a timer irq, setting _TIF_MTE_ASYNC_FAULT,
+         * which then sends a SIGSEGV when the thread is next scheduled.
+         * This cpu will return to the main loop at the end of the TB,
+         * which is rather sooner than "normal".  But the alternative
+         * is waiting until the next syscall.
+         */
+        qemu_cpu_kick(env_cpu(env));
+#endif
         break;
 
     default:
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 19/21] target/arm: Add allocation tag storage for user mode
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
                   ` (17 preceding siblings ...)
  2021-01-15 22:46 ` [PATCH v3 18/21] linux-user/aarch64: Signal SEGV_MTEAERR for async tag check error Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-22 14:05   ` Peter Maydell
  2021-01-15 22:46 ` [PATCH v3 20/21] target/arm: Enable MTE for user-only Richard Henderson
                   ` (2 subsequent siblings)
  21 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

Use the now-saved PAGE_ANON and PAGE_MTE bits,
and the per-page saved data.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/mte_helper.c | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
index d55f8d1e1e..1c569336ea 100644
--- a/target/arm/mte_helper.c
+++ b/target/arm/mte_helper.c
@@ -78,8 +78,33 @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
                                    int tag_size, uintptr_t ra)
 {
 #ifdef CONFIG_USER_ONLY
-    /* Tag storage not implemented.  */
-    return NULL;
+    uint64_t clean_ptr = useronly_clean_ptr(ptr);
+    int flags = page_get_flags(clean_ptr);
+    uint8_t *tags;
+    uintptr_t index;
+
+    if (!(flags & (ptr_access == MMU_DATA_STORE ? PAGE_WRITE : PAGE_READ))) {
+        /* SIGSEGV */
+        arm_cpu_tlb_fill(env_cpu(env), ptr, ptr_size, ptr_access,
+                         ptr_mmu_idx, false, ra);
+        g_assert_not_reached();
+    }
+
+    /* Require both MAP_ANON and PROT_MTE for the page. */
+    if (!(flags & PAGE_ANON) || !(flags & PAGE_MTE)) {
+        return NULL;
+    }
+
+    tags = page_get_target_data(clean_ptr);
+    if (tags == NULL) {
+        size_t alloc_size = TARGET_PAGE_SIZE >> (LOG2_TAG_GRANULE + 1);
+        tags = page_alloc_target_data(clean_ptr, alloc_size);
+        assert(tags != NULL);
+    }
+
+    index = extract32(ptr, LOG2_TAG_GRANULE + 1,
+                      TARGET_PAGE_BITS - LOG2_TAG_GRANULE - 1);
+    return tags + index;
 #else
     uintptr_t index;
     CPUIOTLBEntry *iotlbentry;
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 20/21] target/arm: Enable MTE for user-only
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
                   ` (18 preceding siblings ...)
  2021-01-15 22:46 ` [PATCH v3 19/21] target/arm: Add allocation tag storage for user mode Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-22 14:02   ` Peter Maydell
  2021-01-15 22:46 ` [PATCH v3 21/21] tests/tcg/aarch64: Add mte smoke tests Richard Henderson
  2021-01-15 23:15 ` [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode no-reply
  21 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index abc0affd00..5e613a747a 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -208,6 +208,22 @@ static void arm_cpu_reset(DeviceState *dev)
          * Do not modify this without other changes.
          */
         env->cp15.tcr_el[1].raw_tcr = (3ULL << 37);
+
+        /* Enable MTE */
+        if (cpu_isar_feature(aa64_mte, cpu)) {
+            /* Enable tag access, but leave TCF0 as No Effect (0). */
+            env->cp15.sctlr_el[1] |= SCTLR_ATA0;
+            /*
+             * Exclude all tags, so that tag 0 is always used.
+             * This corresponds to Linux current->thread.gcr_incl = 0.
+             *
+             * Set RRND, so that helper_irg() will generate a seed later.
+             * Here in cpu_reset(), the crypto subsystem has not yet been
+             * initialized.
+             */
+            env->cp15.gcr_el1 = 0x1ffff;
+        }
+
 # ifdef TARGET_TAGGED_ADDRESSES
         env->untagged_addr_mask = -1;
 # endif
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 21/21] tests/tcg/aarch64: Add mte smoke tests
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
                   ` (19 preceding siblings ...)
  2021-01-15 22:46 ` [PATCH v3 20/21] target/arm: Enable MTE for user-only Richard Henderson
@ 2021-01-15 22:46 ` Richard Henderson
  2021-01-22 14:04   ` Peter Maydell
  2021-01-15 23:15 ` [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode no-reply
  21 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2021-01-15 22:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-arm

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tests/tcg/aarch64/mte.h           | 53 +++++++++++++++++++++++++++++++
 tests/tcg/aarch64/mte-1.c         | 25 +++++++++++++++
 tests/tcg/aarch64/mte-2.c         | 42 ++++++++++++++++++++++++
 tests/tcg/aarch64/mte-3.c         | 47 +++++++++++++++++++++++++++
 tests/tcg/aarch64/mte-4.c         | 42 ++++++++++++++++++++++++
 tests/tcg/aarch64/Makefile.target |  6 ++++
 tests/tcg/configure.sh            |  4 +++
 7 files changed, 219 insertions(+)
 create mode 100644 tests/tcg/aarch64/mte.h
 create mode 100644 tests/tcg/aarch64/mte-1.c
 create mode 100644 tests/tcg/aarch64/mte-2.c
 create mode 100644 tests/tcg/aarch64/mte-3.c
 create mode 100644 tests/tcg/aarch64/mte-4.c

diff --git a/tests/tcg/aarch64/mte.h b/tests/tcg/aarch64/mte.h
new file mode 100644
index 0000000000..038d33ab6c
--- /dev/null
+++ b/tests/tcg/aarch64/mte.h
@@ -0,0 +1,53 @@
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/prctl.h>
+
+#ifndef PR_SET_TAGGED_ADDR_CTRL
+# define PR_SET_TAGGED_ADDR_CTRL  55
+#endif
+#ifndef PR_TAGGED_ADDR_ENABLE
+# define PR_TAGGED_ADDR_ENABLE    (1UL << 0)
+#endif
+#ifndef PR_MTE_TCF_SHIFT
+# define PR_MTE_TCF_SHIFT         1
+# define PR_MTE_TCF_NONE          (0UL << PR_MTE_TCF_SHIFT)
+# define PR_MTE_TCF_SYNC          (1UL << PR_MTE_TCF_SHIFT)
+# define PR_MTE_TCF_ASYNC         (2UL << PR_MTE_TCF_SHIFT)
+# define PR_MTE_TAG_SHIFT         3
+#endif
+
+#ifndef PROT_MTE
+# define PROT_MTE 0x20
+#endif
+
+#ifndef SEGV_MTEAERR
+# define SEGV_MTEAERR    8
+# define SEGV_MTESERR    9
+#endif
+
+static void enable_mte(int tcf)
+{
+    int r = prctl(PR_SET_TAGGED_ADDR_CTRL,
+                  PR_TAGGED_ADDR_ENABLE | tcf | (0xfffe << PR_MTE_TAG_SHIFT),
+                  0, 0, 0);
+    if (r < 0) {
+        perror("PR_SET_TAGGED_ADDR_CTRL");
+        exit(2);
+    }
+}
+
+static void *alloc_mte_mem(size_t size)
+{
+    void *p = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_MTE,
+                   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+    if (p == MAP_FAILED) {
+        perror("mmap PROT_MTE");
+        exit(2);
+    }
+    return p;
+}
diff --git a/tests/tcg/aarch64/mte-1.c b/tests/tcg/aarch64/mte-1.c
new file mode 100644
index 0000000000..02bc978482
--- /dev/null
+++ b/tests/tcg/aarch64/mte-1.c
@@ -0,0 +1,25 @@
+/*
+ * Memory tagging, basic pass cases.
+ */
+
+#include "mte.h"
+
+int main(int ac, char **av)
+{
+    int *p0, *p1, *p2;
+    long c;
+
+    enable_mte(PR_MTE_TCF_NONE);
+    p0 = alloc_mte_mem(sizeof(*p0));
+
+    asm("irg %0,%1,%2" : "=r"(p1) : "r"(p0), "r"(1));
+    assert(p1 != p0);
+    asm("subp %0,%1,%2" : "=r"(c) : "r"(p0), "r"(p1));
+    assert(c == 0);
+
+    asm("stg %0, [%0]" : : "r"(p1));
+    asm("ldg %0, [%1]" : "=r"(p2) : "r"(p0), "0"(p0));
+    assert(p1 == p2);
+
+    return 0;
+}
diff --git a/tests/tcg/aarch64/mte-2.c b/tests/tcg/aarch64/mte-2.c
new file mode 100644
index 0000000000..a05f5183cb
--- /dev/null
+++ b/tests/tcg/aarch64/mte-2.c
@@ -0,0 +1,42 @@
+/*
+ * Memory tagging, basic fail cases.
+ */
+
+#include "mte.h"
+
+void pass(int sig, siginfo_t *info, void *uc)
+{
+    assert(info->si_code == SEGV_MTESERR);
+    exit(0);
+}
+
+int main(int ac, char **av)
+{
+    struct sigaction sa;
+    int *p0, *p1, *p2;
+    long excl = 1;
+
+    enable_mte(PR_MTE_TCF_SYNC);
+    p0 = alloc_mte_mem(sizeof(*p0));
+
+    /* Create two differently tagged pointers.  */
+    asm("irg %0,%1,%2" : "=r"(p1) : "r"(p0), "r"(excl));
+    asm("gmi %0,%1,%0" : "+r"(excl) : "r" (p1));
+    assert(excl != 1);
+    asm("irg %0,%1,%2" : "=r"(p2) : "r"(p0), "r"(excl));
+    assert(p1 != p2);
+
+    /* Store the tag from the first pointer.  */
+    asm("stg %0, [%0]" : : "r"(p1));
+
+    *p1 = 0;
+
+    memset(&sa, 0, sizeof(sa));
+    sa.sa_sigaction = pass;
+    sa.sa_flags = SA_SIGINFO;
+    sigaction(SIGSEGV, &sa, NULL);
+
+    *p2 = 0;
+
+    abort();
+}
diff --git a/tests/tcg/aarch64/mte-3.c b/tests/tcg/aarch64/mte-3.c
new file mode 100644
index 0000000000..0d08b477cc
--- /dev/null
+++ b/tests/tcg/aarch64/mte-3.c
@@ -0,0 +1,47 @@
+/*
+ * Memory tagging, basic fail cases.
+ */
+
+#include "mte.h"
+
+void pass(int sig, siginfo_t *info, void *uc)
+{
+    assert(info->si_code == SEGV_MTEAERR);
+    exit(0);
+}
+
+int main(int ac, char **av)
+{
+    struct sigaction sa;
+    int *p0, *p1, *p2;
+    long excl = 1;
+
+    enable_mte(PR_MTE_TCF_ASYNC);
+    p0 = alloc_mte_mem(sizeof(*p0));
+
+    /* Create two differently tagged pointers.  */
+    asm("irg %0,%1,%2" : "=r"(p1) : "r"(p0), "r"(excl));
+    asm("gmi %0,%1,%0" : "+r"(excl) : "r" (p1));
+    assert(excl != 1);
+    asm("irg %0,%1,%2" : "=r"(p2) : "r"(p0), "r"(excl));
+    assert(p1 != p2);
+
+    /* Store the tag from the first pointer.  */
+    asm("stg %0, [%0]" : : "r"(p1));
+
+    *p1 = 0;
+
+    memset(&sa, 0, sizeof(sa));
+    sa.sa_sigaction = pass;
+    sa.sa_flags = SA_SIGINFO;
+    sigaction(SIGSEGV, &sa, NULL);
+
+    /*
+     * Signal for async error will happen eventually.
+     * For a real kernel this should be after the next IRQ (e.g. timer).
+     * For qemu linux-user, we kick the cpu and exit at the next TB.
+     * In either case, loop until this happens (or killed by timeout).
+     */
+    *p2 = 0;
+    while (1);
+}
diff --git a/tests/tcg/aarch64/mte-4.c b/tests/tcg/aarch64/mte-4.c
new file mode 100644
index 0000000000..52aa6fae65
--- /dev/null
+++ b/tests/tcg/aarch64/mte-4.c
@@ -0,0 +1,42 @@
+/*
+ * Memory tagging, basic fail cases.
+ */
+
+#include "mte.h"
+
+void __attribute__((noinline)) tagset(void *p, size_t size)
+{
+    size_t i;
+    for (i = 0; i < size; i += 16) {
+        asm("stg %0, [%0]" : : "r"(p + i));
+    }
+}
+
+void __attribute__((noinline)) tagcheck(void *p, size_t size)
+{
+    size_t i;
+    void *c;
+
+    for (i = 0; i < size; i += 16) {
+        asm("ldg %0, [%1]" : "=r"(c) : "r"(p + i), "0"(p));
+        assert(c == p);
+    }
+}
+
+int main(int ac, char **av)
+{
+    size_t size = getpagesize() * 4;
+    long excl = 1;
+    int *p0, *p1;
+
+    enable_mte(PR_MTE_TCF_ASYNC);
+    p0 = alloc_mte_mem(size);
+
+    /* Tag the pointer. */
+    asm("irg %0,%1,%2" : "=r"(p1) : "r"(p0), "r"(excl));
+
+    tagset(p1, size);
+    tagcheck(p1, size);
+
+    return 0;
+}
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
index d7d33e293c..bf53ad0087 100644
--- a/tests/tcg/aarch64/Makefile.target
+++ b/tests/tcg/aarch64/Makefile.target
@@ -35,6 +35,12 @@ endif
 # bti-2 tests PROT_BTI, so no special compiler support required.
 AARCH64_TESTS += bti-2
 
+# MTE Tests
+ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_ARMV8_MTE),)
+AARCH64_TESTS += mte-1 mte-2 mte-3 mte-4
+mte-%: CFLAGS += -march=armv8.5-a+memtag
+endif
+
 # Semihosting smoke test for linux-user
 AARCH64_TESTS += semihosting
 run-semihosting: semihosting
diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
index e1b70e25f2..ba8ac9a93e 100755
--- a/tests/tcg/configure.sh
+++ b/tests/tcg/configure.sh
@@ -244,6 +244,10 @@ for target in $target_list; do
                -mbranch-protection=standard -o $TMPE $TMPC; then
                 echo "CROSS_CC_HAS_ARMV8_BTI=y" >> $config_target_mak
             fi
+            if do_compiler "$target_compiler" $target_compiler_cflags \
+               -march=armv8.5-a+memtag -o $TMPE $TMPC; then
+                echo "CROSS_CC_HAS_ARMV8_MTE=y" >> $config_target_mak
+            fi
         ;;
     esac
 
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode
  2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
                   ` (20 preceding siblings ...)
  2021-01-15 22:46 ` [PATCH v3 21/21] tests/tcg/aarch64: Add mte smoke tests Richard Henderson
@ 2021-01-15 23:15 ` no-reply
  21 siblings, 0 replies; 46+ messages in thread
From: no-reply @ 2021-01-15 23:15 UTC (permalink / raw)
  To: richard.henderson; +Cc: peter.maydell, qemu-arm, qemu-devel

Patchew URL: https://patchew.org/QEMU/20210115224645.1196742-1-richard.henderson@linaro.org/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20210115224645.1196742-1-richard.henderson@linaro.org
Subject: [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 - [tag update]      patchew/20201104092900.21214-1-green.wan@sifive.com -> patchew/20201104092900.21214-1-green.wan@sifive.com
 - [tag update]      patchew/20210110185109.29841-1-space.monkey.delivers@gmail.com -> patchew/20210110185109.29841-1-space.monkey.delivers@gmail.com
 * [new tag]         patchew/20210115224645.1196742-1-richard.henderson@linaro.org -> patchew/20210115224645.1196742-1-richard.henderson@linaro.org
Switched to a new branch 'test'
b51c62b tests/tcg/aarch64: Add mte smoke tests
2bb6651 target/arm: Enable MTE for user-only
581006b target/arm: Add allocation tag storage for user mode
3995c13 linux-user/aarch64: Signal SEGV_MTEAERR for async tag check error
3b2735a linux-user/aarch64: Signal SEGV_MTESERR for sync tag check fault
87773dc linux-user/aarch64: Pass syndrome to EXC_*_ABORT
c77b9e7 target/arm: Split out syndrome.h from internals.h
03409db linux-user/aarch64: Implement PROT_MTE
a349186 linux-user/aarch64: Implement PR_MTE_TCF and PR_MTE_TAG
1bf3014 linux-user/aarch64: Implement PR_TAGGED_ADDR_ENABLE
dda6aba exec: Add support for TARGET_TAGGED_ADDRESSES
37ecbdb linux-user: Fix guest_addr_valid vs reserved_va
b45e037 linux-user: Do not use guest_addr_valid for h2g_valid
cabbb07 bsd-user: Tidy VERIFY_READ/VERIFY_WRITE
9528890 linux-user: Tidy VERIFY_READ/VERIFY_WRITE
074f1b6 linux-user: Check for overflow in access_ok
a57aaa3 exec: Improve types for guest_addr_valid
acb28c7 exec: Use uintptr_t in cpu_ldst.h
6b630ff exec: Use uintptr_t for guest_base
6b7daa3 linux-user: Introduce PAGE_ANON
b7dc05d tcg: Introduce target-specific page data for user-only

=== OUTPUT BEGIN ===
1/21 Checking commit b7dc05ddcc5b (tcg: Introduce target-specific page data for user-only)
2/21 Checking commit 6b7daa34298c (linux-user: Introduce PAGE_ANON)
3/21 Checking commit 6b630ffe4c66 (exec: Use uintptr_t for guest_base)
4/21 Checking commit acb28c7cb60b (exec: Use uintptr_t in cpu_ldst.h)
5/21 Checking commit a57aaa3359f2 (exec: Improve types for guest_addr_valid)
6/21 Checking commit 074f1b6a03d3 (linux-user: Check for overflow in access_ok)
7/21 Checking commit 952889066ba0 (linux-user: Tidy VERIFY_READ/VERIFY_WRITE)
8/21 Checking commit cabbb07508f6 (bsd-user: Tidy VERIFY_READ/VERIFY_WRITE)
9/21 Checking commit b45e037c08d2 (linux-user: Do not use guest_addr_valid for h2g_valid)
10/21 Checking commit 37ecbdbf6a08 (linux-user: Fix guest_addr_valid vs reserved_va)
11/21 Checking commit dda6aba68cc2 (exec: Add support for TARGET_TAGGED_ADDRESSES)
12/21 Checking commit 1bf30143d18d (linux-user/aarch64: Implement PR_TAGGED_ADDR_ENABLE)
13/21 Checking commit a349186d27f0 (linux-user/aarch64: Implement PR_MTE_TCF and PR_MTE_TAG)
14/21 Checking commit 03409db2e4ec (linux-user/aarch64: Implement PROT_MTE)
15/21 Checking commit c77b9e72eb32 (target/arm: Split out syndrome.h from internals.h)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#277: 
new file mode 100644

total: 0 errors, 1 warnings, 530 lines checked

Patch 15/21 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
16/21 Checking commit 87773dca7e38 (linux-user/aarch64: Pass syndrome to EXC_*_ABORT)
17/21 Checking commit 3b2735ac2c32 (linux-user/aarch64: Signal SEGV_MTESERR for sync tag check fault)
18/21 Checking commit 3995c13283cb (linux-user/aarch64: Signal SEGV_MTEAERR for async tag check error)
19/21 Checking commit 581006bf041a (target/arm: Add allocation tag storage for user mode)
20/21 Checking commit 2bb6651fbcf7 (target/arm: Enable MTE for user-only)
21/21 Checking commit b51c62bbd980 (tests/tcg/aarch64: Add mte smoke tests)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#28: 
new file mode 100644

ERROR: trailing statements should be on next line
#157: FILE: tests/tcg/aarch64/mte-3.c:46:
+    while (1);

ERROR: braces {} are necessary for all arms of this statement
#157: FILE: tests/tcg/aarch64/mte-3.c:46:
+    while (1);
[...]

ERROR: use qemu_real_host_page_size instead of getpagesize()
#192: FILE: tests/tcg/aarch64/mte-4.c:28:
+    size_t size = getpagesize() * 4;

total: 3 errors, 1 warnings, 231 lines checked

Patch 21/21 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20210115224645.1196742-1-richard.henderson@linaro.org/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 08/21] bsd-user: Tidy VERIFY_READ/VERIFY_WRITE
  2021-01-15 22:46 ` [PATCH v3 08/21] bsd-user: " Richard Henderson
@ 2021-01-16 16:28   ` Warner Losh
  0 siblings, 0 replies; 46+ messages in thread
From: Warner Losh @ 2021-01-16 16:28 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Peter Maydell, qemu-arm, QEMU Developers

[-- Attachment #1: Type: text/plain, Size: 1391 bytes --]

On Fri, Jan 15, 2021 at 3:56 PM Richard Henderson <
richard.henderson@linaro.org> wrote:

> These constants are only ever used with access_ok, and friends.
> Rather than translating them to PAGE_* bits, let them equal
> the PAGE_* bits to begin.
>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>

This looks OK to me.

Reviewed-by: Warner Losh <imp@bsdimp.com>


> ---
>  bsd-user/qemu.h | 9 ++++-----
>  1 file changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
> index f8bb1e5459..4076adabd0 100644
> --- a/bsd-user/qemu.h
> +++ b/bsd-user/qemu.h
> @@ -218,13 +218,12 @@ extern unsigned long x86_stack_size;
>
>  /* user access */
>
> -#define VERIFY_READ 0
> -#define VERIFY_WRITE 1 /* implies read access */
> +#define VERIFY_READ  PAGE_READ
> +#define VERIFY_WRITE (PAGE_READ | PAGE_WRITE)
>
> -static inline int access_ok(int type, abi_ulong addr, abi_ulong size)
> +static inline bool access_ok(int type, abi_ulong addr, abi_ulong size)
>  {
> -    return page_check_range((target_ulong)addr, size,
> -                            (type == VERIFY_READ) ? PAGE_READ :
> (PAGE_READ | PAGE_WRITE)) == 0;
> +    return page_check_range((target_ulong)addr, size, type) == 0;
>  }
>
>  /* NOTE __get_user and __put_user use host pointers and don't check
> access. */
> --
>

[-- Attachment #2: Type: text/html, Size: 2252 bytes --]

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 01/21] tcg: Introduce target-specific page data for user-only
  2021-01-15 22:46 ` [PATCH v3 01/21] tcg: Introduce target-specific page data for user-only Richard Henderson
@ 2021-01-19 16:53   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2021-01-19 16:53 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, QEMU Developers

On Fri, 15 Jan 2021 at 22:46, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> This data can be allocated by page_alloc_target_data() and
> released by page_set_flags(start, end, prot | PAGE_RESET).
>
> This data will be used to hold tag memory for AArch64 MTE.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> v3: Add doc comments; tweak alloc so that the !PAGE_VALID case is clear.

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

thanks
-- PMM


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 03/21] exec: Use uintptr_t for guest_base
  2021-01-15 22:46 ` [PATCH v3 03/21] exec: Use uintptr_t for guest_base Richard Henderson
@ 2021-01-19 16:56   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2021-01-19 16:56 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, QEMU Developers

On Fri, 15 Jan 2021 at 22:46, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> This is more descriptive than 'unsigned long'.
> No functional change, since these match on all linux+bsd hosts.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

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

thanks
-- PMM


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 04/21] exec: Use uintptr_t in cpu_ldst.h
  2021-01-15 22:46 ` [PATCH v3 04/21] exec: Use uintptr_t in cpu_ldst.h Richard Henderson
@ 2021-01-19 16:56   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2021-01-19 16:56 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, QEMU Developers

On Fri, 15 Jan 2021 at 22:46, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> This is more descriptive than 'unsigned long'.
> No functional change, since these match on all linux+bsd hosts.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

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

thanks
-- PMM


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 05/21] exec: Improve types for guest_addr_valid
  2021-01-15 22:46 ` [PATCH v3 05/21] exec: Improve types for guest_addr_valid Richard Henderson
@ 2021-01-19 16:57   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2021-01-19 16:57 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, QEMU Developers

On Fri, 15 Jan 2021 at 22:46, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Return bool not int; pass abi_ulong not 'unsigned long'.
> All callers use abi_ulong already, so the change in type
> has no effect.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  include/exec/cpu_ldst.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
> index 3f9063aade..5e8878ee9b 100644
> --- a/include/exec/cpu_ldst.h
> +++ b/include/exec/cpu_ldst.h
> @@ -79,7 +79,7 @@ typedef uint64_t abi_ptr;
>  #endif
>  #define h2g_valid(x) guest_addr_valid((uintptr_t)(x) - guest_base)
>
> -static inline int guest_range_valid(unsigned long start, unsigned long len)
> +static inline bool guest_range_valid(abi_ulong start, abi_ulong len)
>  {
>      return len - 1 <= GUEST_ADDR_MAX && start <= GUEST_ADDR_MAX - len + 1;
>  }
> --

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

thanks
-- PMM


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 09/21] linux-user: Do not use guest_addr_valid for h2g_valid
  2021-01-15 22:46 ` [PATCH v3 09/21] linux-user: Do not use guest_addr_valid for h2g_valid Richard Henderson
@ 2021-01-19 16:59   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2021-01-19 16:59 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, QEMU Developers

On Fri, 15 Jan 2021 at 22:47, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> This is the only use of guest_addr_valid that does not begin
> with a guest address, but a host address being transformed to
> a guest address.
>
> We will shortly adjust guest_addr_valid to handle guest memory
> tags, and the host address should not be subjected to that.
>
> Move h2g_valid adjacent to the other h2g macros.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> v3: Ditch type changes; retain true for HLB <= GAM (pmm).

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

thanks
-- PMM


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 10/21] linux-user: Fix guest_addr_valid vs reserved_va
  2021-01-15 22:46 ` [PATCH v3 10/21] linux-user: Fix guest_addr_valid vs reserved_va Richard Henderson
@ 2021-01-19 17:03   ` Peter Maydell
  2021-01-19 17:41     ` Richard Henderson
  0 siblings, 1 reply; 46+ messages in thread
From: Peter Maydell @ 2021-01-19 17:03 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, QEMU Developers

On Fri, 15 Jan 2021 at 22:47, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> We must always use GUEST_ADDR_MAX, because even 32-bit hosts can
> use -R <reserved_va> to restrict the memory address of the guest.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  include/exec/cpu_ldst.h | 9 ++++-----
>  1 file changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
> index 4e6ef3d542..e62f4fba00 100644
> --- a/include/exec/cpu_ldst.h
> +++ b/include/exec/cpu_ldst.h
> @@ -72,11 +72,10 @@ typedef uint64_t abi_ptr;
>  /* All direct uses of g2h and h2g need to go away for usermode softmmu.  */
>  #define g2h(x) ((void *)((uintptr_t)(abi_ptr)(x) + guest_base))
>
> -#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
> -#define guest_addr_valid(x) (1)
> -#else
> -#define guest_addr_valid(x) ((x) <= GUEST_ADDR_MAX)
> -#endif
> +static inline bool guest_addr_valid(abi_ulong x)
> +{
> +    return x <= GUEST_ADDR_MAX;
> +}

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

Looking back at patch 9 -- if we always check against
GUEST_ADDR_MAX here, should we also do that for h2g_valid(),
or are the two uses different ?
(The v2->v3 changes list for patch 9 suggests we may have
had this discussion previously, but I forget the details...)

thanks
-- PMM


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 15/21] target/arm: Split out syndrome.h from internals.h
  2021-01-15 22:46 ` [PATCH v3 15/21] target/arm: Split out syndrome.h from internals.h Richard Henderson
@ 2021-01-19 17:07   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2021-01-19 17:07 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, QEMU Developers

On Fri, 15 Jan 2021 at 22:47, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Move everything related to syndromes to a new file,
> which can be shared with linux-user.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/internals.h | 245 +-----------------------------------
>  target/arm/syndrome.h  | 273 +++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 274 insertions(+), 244 deletions(-)
>  create mode 100644 target/arm/syndrome.h

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

thanks
-- PMM


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 16/21] linux-user/aarch64: Pass syndrome to EXC_*_ABORT
  2021-01-15 22:46 ` [PATCH v3 16/21] linux-user/aarch64: Pass syndrome to EXC_*_ABORT Richard Henderson
@ 2021-01-19 17:12   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2021-01-19 17:12 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, QEMU Developers

On Fri, 15 Jan 2021 at 22:47, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> A proper syndrome is required to fill in the proper si_code.
> Use page_get_flags to determine permission vs translation for user-only.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> v3: Use syndrome.h, arm_deliver_fault.

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

thanks
-- PMM


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 10/21] linux-user: Fix guest_addr_valid vs reserved_va
  2021-01-19 17:03   ` Peter Maydell
@ 2021-01-19 17:41     ` Richard Henderson
  0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-01-19 17:41 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-arm, QEMU Developers

On 1/19/21 7:03 AM, Peter Maydell wrote:
> On Fri, 15 Jan 2021 at 22:47, Richard Henderson
> <richard.henderson@linaro.org> wrote:
>>
>> We must always use GUEST_ADDR_MAX, because even 32-bit hosts can
>> use -R <reserved_va> to restrict the memory address of the guest.
>>
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>  include/exec/cpu_ldst.h | 9 ++++-----
>>  1 file changed, 4 insertions(+), 5 deletions(-)
>>
>> diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
>> index 4e6ef3d542..e62f4fba00 100644
>> --- a/include/exec/cpu_ldst.h
>> +++ b/include/exec/cpu_ldst.h
>> @@ -72,11 +72,10 @@ typedef uint64_t abi_ptr;
>>  /* All direct uses of g2h and h2g need to go away for usermode softmmu.  */
>>  #define g2h(x) ((void *)((uintptr_t)(abi_ptr)(x) + guest_base))
>>
>> -#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
>> -#define guest_addr_valid(x) (1)
>> -#else
>> -#define guest_addr_valid(x) ((x) <= GUEST_ADDR_MAX)
>> -#endif
>> +static inline bool guest_addr_valid(abi_ulong x)
>> +{
>> +    return x <= GUEST_ADDR_MAX;
>> +}
> 
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> 
> Looking back at patch 9 -- if we always check against
> GUEST_ADDR_MAX here, should we also do that for h2g_valid(),
> or are the two uses different ?
> (The v2->v3 changes list for patch 9 suggests we may have
> had this discussion previously, but I forget the details...)

I had thought we should always check GUEST_ADDR_MAX.

If something is outside G_A_M, then it doesn't fit
into the reserved_va that either (1) the user requested
via the command-line or (2) for which the guest has
constraints (e.g. TARGET_VIRT_ADDR_SPACE_BITS for sh4
or mips, requiring 31-bit addresses).


r~


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 12/21] linux-user/aarch64: Implement PR_TAGGED_ADDR_ENABLE
  2021-01-15 22:46 ` [PATCH v3 12/21] linux-user/aarch64: Implement PR_TAGGED_ADDR_ENABLE Richard Henderson
@ 2021-01-22 11:36   ` Peter Maydell
  2021-01-22 11:53   ` Peter Maydell
  1 sibling, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2021-01-22 11:36 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, QEMU Developers

On Fri, 15 Jan 2021 at 22:47, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> This is the prctl bit that controls whether syscalls accept tagged
> addresses.  See Documentation/arm64/tagged-address-abi.rst in the
> linux kernel.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  linux-user/aarch64/target_syscall.h |  4 ++++
>  target/arm/cpu-param.h              |  3 +++
>  target/arm/cpu.h                    | 23 +++++++++++++++++++++++
>  linux-user/syscall.c                | 25 +++++++++++++++++++++++++
>  target/arm/cpu.c                    |  3 +++
>  5 files changed, 58 insertions(+)
>
> diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h
> index 3194e6b009..820601dfcc 100644
> --- a/linux-user/aarch64/target_syscall.h
> +++ b/linux-user/aarch64/target_syscall.h
> @@ -30,4 +30,8 @@ struct target_pt_regs {
>  # define TARGET_PR_PAC_APDBKEY   (1 << 3)
>  # define TARGET_PR_PAC_APGAKEY   (1 << 4)
>
> +#define TARGET_PR_SET_TAGGED_ADDR_CTRL 55
> +#define TARGET_PR_GET_TAGGED_ADDR_CTRL 56
> +# define TARGET_PR_TAGGED_ADDR_ENABLE  (1UL << 0)

Stray extra space.

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

thanks
-- PMM


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 13/21] linux-user/aarch64: Implement PR_MTE_TCF and PR_MTE_TAG
  2021-01-15 22:46 ` [PATCH v3 13/21] linux-user/aarch64: Implement PR_MTE_TCF and PR_MTE_TAG Richard Henderson
@ 2021-01-22 11:48   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2021-01-22 11:48 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, QEMU Developers

On Fri, 15 Jan 2021 at 22:47, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> These prctl fields are required for the function of MTE.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  linux-user/aarch64/target_syscall.h |  9 ++++++
>  linux-user/syscall.c                | 44 +++++++++++++++++++++++++++++
>  2 files changed, 53 insertions(+)
>
> diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h
> index 820601dfcc..76f6c3391d 100644
> --- a/linux-user/aarch64/target_syscall.h
> +++ b/linux-user/aarch64/target_syscall.h
> @@ -33,5 +33,14 @@ struct target_pt_regs {
>  #define TARGET_PR_SET_TAGGED_ADDR_CTRL 55
>  #define TARGET_PR_GET_TAGGED_ADDR_CTRL 56
>  # define TARGET_PR_TAGGED_ADDR_ENABLE  (1UL << 0)
> +/* MTE tag check fault modes */
> +# define TARGET_PR_MTE_TCF_SHIFT       1
> +# define TARGET_PR_MTE_TCF_NONE        (0UL << TARGET_PR_MTE_TCF_SHIFT)
> +# define TARGET_PR_MTE_TCF_SYNC        (1UL << TARGET_PR_MTE_TCF_SHIFT)
> +# define TARGET_PR_MTE_TCF_ASYNC       (2UL << TARGET_PR_MTE_TCF_SHIFT)
> +# define TARGET_PR_MTE_TCF_MASK        (3UL << TARGET_PR_MTE_TCF_SHIFT)
> +/* MTE tag inclusion mask */
> +# define TARGET_PR_MTE_TAG_SHIFT       3
> +# define TARGET_PR_MTE_TAG_MASK        (0xffffUL << TARGET_PR_MTE_TAG_SHIFT)

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

thanks
-- PMM


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 12/21] linux-user/aarch64: Implement PR_TAGGED_ADDR_ENABLE
  2021-01-15 22:46 ` [PATCH v3 12/21] linux-user/aarch64: Implement PR_TAGGED_ADDR_ENABLE Richard Henderson
  2021-01-22 11:36   ` Peter Maydell
@ 2021-01-22 11:53   ` Peter Maydell
  2021-01-22 12:02     ` Peter Maydell
  1 sibling, 1 reply; 46+ messages in thread
From: Peter Maydell @ 2021-01-22 11:53 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, QEMU Developers

On Fri, 15 Jan 2021 at 22:47, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> This is the prctl bit that controls whether syscalls accept tagged
> addresses.  See Documentation/arm64/tagged-address-abi.rst in the
> linux kernel.

> +#ifdef TARGET_TAGGED_ADDRESSES
> +/**
> + * cpu_untagged_addr:
> + * @cs: CPU context
> + * @x: tagged address
> + *
> + * Remove any address tag from @x.  This is explicitly related to the
> + * linux syscall TIF_TAGGED_ADDR setting, not TBI in general.
> + *
> + * There should be a better place to put this, but we need this in
> + * include/exec/cpu_ldst.h, and not some place linux-user specific.
> + */
> +static inline target_ulong cpu_untagged_addr(CPUState *cs, target_ulong x)
> +{
> +    ARMCPU *cpu = ARM_CPU(cs);
> +    return x & cpu->env.untagged_addr_mask;
> +}
> +#endif

Forgot to mention: this only does the right thing on addresses
in the lower half of the address space. I guess that's mostly
OK for our purposes? It probably means that if a guest program
deliberately dereferences a bad address in the top half of the
address space we'll report the wrong (ie different to what a real
kernel reports) address value to it in the SEGV signal handler.

The kernel's "untagged_addr()" implementation:
https://elixir.bootlin.com/linux/latest/source/arch/arm64/include/asm/memory.h#L203
slightly confusingly does "untag the addr if it's in the userspace
half, leave the tag bits alone if in the kernel half".

thanks
-- PMM


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 12/21] linux-user/aarch64: Implement PR_TAGGED_ADDR_ENABLE
  2021-01-22 11:53   ` Peter Maydell
@ 2021-01-22 12:02     ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2021-01-22 12:02 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, QEMU Developers

On Fri, 22 Jan 2021 at 11:53, Peter Maydell <peter.maydell@linaro.org> wrote:
> The kernel's "untagged_addr()" implementation:
> https://elixir.bootlin.com/linux/latest/source/arch/arm64/include/asm/memory.h#L203
> slightly confusingly does "untag the addr if it's in the userspace
> half, leave the tag bits alone if in the kernel half".

...and a kernel person has just explained to me the rationale:
TBI is always enabled for userspace and never for the kernel,
so "always clear tag bits for a userspace address, never clear
them for a kernel address" is the right behaviour. I think we
should have the same logic.

-- PMM


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 17/21] linux-user/aarch64: Signal SEGV_MTESERR for sync tag check fault
  2021-01-15 22:46 ` [PATCH v3 17/21] linux-user/aarch64: Signal SEGV_MTESERR for sync tag check fault Richard Henderson
@ 2021-01-22 12:03   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2021-01-22 12:03 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, QEMU Developers

On Fri, 15 Jan 2021 at 22:47, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  linux-user/aarch64/target_signal.h | 2 ++
>  linux-user/aarch64/cpu_loop.c      | 3 +++
>  2 files changed, 5 insertions(+)
>
> diff --git a/linux-user/aarch64/target_signal.h b/linux-user/aarch64/target_signal.h
> index ddd73169f0..777fb667fe 100644
> --- a/linux-user/aarch64/target_signal.h
> +++ b/linux-user/aarch64/target_signal.h
> @@ -21,5 +21,7 @@ typedef struct target_sigaltstack {
>
>  #include "../generic/signal.h"
>
> +#define TARGET_SEGV_MTESERR  9  /* Synchronous ARM MTE exception */
> +
>  #define TARGET_ARCH_HAS_SETUP_FRAME
>  #endif /* AARCH64_TARGET_SIGNAL_H */
> diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
> index 7811440c68..6867f0db2b 100644
> --- a/linux-user/aarch64/cpu_loop.c
> +++ b/linux-user/aarch64/cpu_loop.c
> @@ -133,6 +133,9 @@ void cpu_loop(CPUARMState *env)
>              case 0x0d ... 0x0f: /* Permission fault, level {1-3} */
>                  info.si_code = TARGET_SEGV_ACCERR;
>                  break;
> +            case 0x11: /* Synchronous Tag Check Fault */
> +                info.si_code = TARGET_SEGV_MTESERR;
> +                break;
>              default:
>                  g_assert_not_reached();
>              }
> --
> 2.25.1

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

thanks
-- PMM


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 18/21] linux-user/aarch64: Signal SEGV_MTEAERR for async tag check error
  2021-01-15 22:46 ` [PATCH v3 18/21] linux-user/aarch64: Signal SEGV_MTEAERR for async tag check error Richard Henderson
@ 2021-01-22 13:59   ` Peter Maydell
  2021-01-28  8:49     ` Richard Henderson
  0 siblings, 1 reply; 46+ messages in thread
From: Peter Maydell @ 2021-01-22 13:59 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, QEMU Developers

On Fri, 15 Jan 2021 at 22:47, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

So when does the real kernel report async MTE exceptions to userspace?
The commit message would be a good place to briefly describe the
kernel's strategy and where QEMU differs from it (if anywhere)...

> ---
>  linux-user/aarch64/target_signal.h |  1 +
>  linux-user/aarch64/cpu_loop.c      | 34 +++++++++++++++++++++---------
>  target/arm/mte_helper.c            | 10 +++++++++
>  3 files changed, 35 insertions(+), 10 deletions(-)
>
> diff --git a/linux-user/aarch64/target_signal.h b/linux-user/aarch64/target_signal.h
> index 777fb667fe..18013e1b23 100644
> --- a/linux-user/aarch64/target_signal.h
> +++ b/linux-user/aarch64/target_signal.h
> @@ -21,6 +21,7 @@ typedef struct target_sigaltstack {
>
>  #include "../generic/signal.h"
>
> +#define TARGET_SEGV_MTEAERR  8  /* Asynchronous ARM MTE error */
>  #define TARGET_SEGV_MTESERR  9  /* Synchronous ARM MTE exception */
>
>  #define TARGET_ARCH_HAS_SETUP_FRAME
> diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
> index 6867f0db2b..6160a401bd 100644
> --- a/linux-user/aarch64/cpu_loop.c
> +++ b/linux-user/aarch64/cpu_loop.c
> @@ -72,6 +72,21 @@
>          put_user_u16(__x, (gaddr));                     \
>      })
>
> +static bool check_mte_async_fault(CPUARMState *env, target_siginfo_t *info)
> +{
> +    if (likely(env->cp15.tfsr_el[0] == 0)) {
> +        return false;
> +    }
> +
> +    env->cp15.tfsr_el[0] = 0;
> +    info->si_signo = TARGET_SIGSEGV;
> +    info->si_errno = 0;
> +    info->_sifields._sigfault._addr = 0;
> +    info->si_code = TARGET_SEGV_MTEAERR;
> +    queue_signal(env, info->si_signo, QEMU_SI_FAULT, info);
> +    return true;
> +}
> +
>  /* AArch64 main loop */
>  void cpu_loop(CPUARMState *env)
>  {
> @@ -88,15 +103,13 @@ void cpu_loop(CPUARMState *env)
>
>          switch (trapnr) {
>          case EXCP_SWI:
> -            ret = do_syscall(env,
> -                             env->xregs[8],
> -                             env->xregs[0],
> -                             env->xregs[1],
> -                             env->xregs[2],
> -                             env->xregs[3],
> -                             env->xregs[4],
> -                             env->xregs[5],
> -                             0, 0);
> +            if (check_mte_async_fault(env, &info)) {
> +                ret = -TARGET_ERESTARTSYS;
> +            } else {
> +                ret = do_syscall(env, env->xregs[8], env->xregs[0],
> +                                 env->xregs[1], env->xregs[2], env->xregs[3],
> +                                 env->xregs[4], env->xregs[5], 0, 0);
> +            }
>              if (ret == -TARGET_ERESTARTSYS) {
>                  env->pc -= 4;
>              } else if (ret != -TARGET_QEMU_ESIGRETURN) {
> @@ -104,7 +117,8 @@ void cpu_loop(CPUARMState *env)
>              }
>              break;
>          case EXCP_INTERRUPT:
> -            /* just indicate that signals should be handled asap */
> +            /* Just indicate that signals should be handled asap. */
> +            check_mte_async_fault(env, &info);
>              break;
>          case EXCP_UDEF:
>              info.si_signo = TARGET_SIGILL;

So this doesn't guarantee to check the async-fault status on
every exit from cpu_exec(), which means we might miss things.
For instance I think this slightly contrived example would not
ever take the SEGV:
    STR x0, [x1]   # with a bad tag
    YIELD
l:  B l

because the STR and YIELD go into the same TB, the YIELD causes us
to leave the TB with EXCP_YIELD, we don't check for an async fault
in that code path, and then we'll go into the infinite loop and
have nothing to prompt us to come out and look at the async fault flags.

Does it work if we just always queue the SEGV on exit from cpu_exec()
and let the signal handling machinery prioritize if we also pend
some other signal because this was an EXCP_UDEF or whatever?
It would be neater if we could keep the fault-check outside the
switch (trapnr) somehow.

> diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
> index 153bd1e9df..d55f8d1e1e 100644
> --- a/target/arm/mte_helper.c
> +++ b/target/arm/mte_helper.c
> @@ -565,6 +565,16 @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
>              select = 0;
>          }
>          env->cp15.tfsr_el[el] |= 1 << select;
> +#ifdef CONFIG_USER_ONLY
> +        /*
> +         * Stand in for a timer irq, setting _TIF_MTE_ASYNC_FAULT,
> +         * which then sends a SIGSEGV when the thread is next scheduled.
> +         * This cpu will return to the main loop at the end of the TB,
> +         * which is rather sooner than "normal".  But the alternative
> +         * is waiting until the next syscall.
> +         */
> +        qemu_cpu_kick(env_cpu(env));
> +#endif
>          break;

This does the right thing, but qemu_cpu_kick() is one of those
functions that's in a category of "not used much at all in the
codebase" and which always make me wonder if there's a reason.
(In particular there's exactly one use in the whole of target/
right now.) I suppose the case of "helper function wants to cause
us to leave the TB loop but not to abort the current insn" is
an unusual one...

thanks
-- PMM


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 20/21] target/arm: Enable MTE for user-only
  2021-01-15 22:46 ` [PATCH v3 20/21] target/arm: Enable MTE for user-only Richard Henderson
@ 2021-01-22 14:02   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2021-01-22 14:02 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, QEMU Developers

On Fri, 15 Jan 2021 at 22:47, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/cpu.c | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
>
> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
> index abc0affd00..5e613a747a 100644
> --- a/target/arm/cpu.c
> +++ b/target/arm/cpu.c
> @@ -208,6 +208,22 @@ static void arm_cpu_reset(DeviceState *dev)
>           * Do not modify this without other changes.
>           */
>          env->cp15.tcr_el[1].raw_tcr = (3ULL << 37);
> +
> +        /* Enable MTE */
> +        if (cpu_isar_feature(aa64_mte, cpu)) {
> +            /* Enable tag access, but leave TCF0 as No Effect (0). */
> +            env->cp15.sctlr_el[1] |= SCTLR_ATA0;
> +            /*
> +             * Exclude all tags, so that tag 0 is always used.
> +             * This corresponds to Linux current->thread.gcr_incl = 0.
> +             *
> +             * Set RRND, so that helper_irg() will generate a seed later.
> +             * Here in cpu_reset(), the crypto subsystem has not yet been
> +             * initialized.
> +             */
> +            env->cp15.gcr_el1 = 0x1ffff;
> +        }
> +
>  # ifdef TARGET_TAGGED_ADDRESSES
>          env->untagged_addr_mask = -1;
>  # endif
> --

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

thanks
-- PMM


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 21/21] tests/tcg/aarch64: Add mte smoke tests
  2021-01-15 22:46 ` [PATCH v3 21/21] tests/tcg/aarch64: Add mte smoke tests Richard Henderson
@ 2021-01-22 14:04   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2021-01-22 14:04 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, QEMU Developers

On Fri, 15 Jan 2021 at 22:47, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  tests/tcg/aarch64/mte.h           | 53 +++++++++++++++++++++++++++++++
>  tests/tcg/aarch64/mte-1.c         | 25 +++++++++++++++
>  tests/tcg/aarch64/mte-2.c         | 42 ++++++++++++++++++++++++
>  tests/tcg/aarch64/mte-3.c         | 47 +++++++++++++++++++++++++++
>  tests/tcg/aarch64/mte-4.c         | 42 ++++++++++++++++++++++++
>  tests/tcg/aarch64/Makefile.target |  6 ++++
>  tests/tcg/configure.sh            |  4 +++
>  7 files changed, 219 insertions(+)
>  create mode 100644 tests/tcg/aarch64/mte.h
>  create mode 100644 tests/tcg/aarch64/mte-1.c
>  create mode 100644 tests/tcg/aarch64/mte-2.c
>  create mode 100644 tests/tcg/aarch64/mte-3.c
>  create mode 100644 tests/tcg/aarch64/mte-4.c
>
> diff --git a/tests/tcg/aarch64/mte.h b/tests/tcg/aarch64/mte.h
> new file mode 100644
> index 0000000000..038d33ab6c
> --- /dev/null
> +++ b/tests/tcg/aarch64/mte.h
> @@ -0,0 +1,53 @@
> +#include <assert.h>
> +#include <string.h>
> +#include <stdlib.h>
> +#include <stdio.h>

All new files need the usual copyright-and-license header comment,
please.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 19/21] target/arm: Add allocation tag storage for user mode
  2021-01-15 22:46 ` [PATCH v3 19/21] target/arm: Add allocation tag storage for user mode Richard Henderson
@ 2021-01-22 14:05   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2021-01-22 14:05 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, QEMU Developers

On Fri, 15 Jan 2021 at 22:47, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Use the now-saved PAGE_ANON and PAGE_MTE bits,
> and the per-page saved data.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---

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

thanks
-- PMM


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 11/21] exec: Add support for TARGET_TAGGED_ADDRESSES
  2021-01-15 22:46 ` [PATCH v3 11/21] exec: Add support for TARGET_TAGGED_ADDRESSES Richard Henderson
@ 2021-01-22 14:13   ` Peter Maydell
  2021-01-26 17:10     ` Richard Henderson
  0 siblings, 1 reply; 46+ messages in thread
From: Peter Maydell @ 2021-01-22 14:13 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, QEMU Developers

On Fri, 15 Jan 2021 at 22:47, 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 | 20 +++++++++++++++++---
>  1 file changed, 17 insertions(+), 3 deletions(-)
>
> diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
> index e62f4fba00..1df9b93e59 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
>
> +static inline abi_ptr untagged_addr(abi_ptr x)
> +{
> +#ifdef TARGET_TAGGED_ADDRESSES
> +    if (current_cpu) {
> +        return cpu_untagged_addr(current_cpu, x);
> +    }
> +#endif
> +    return x;
> +}

The current_cpu global is a nasty hack and I don't like seeing
new usages of it. In particular, it's very difficult to
analyse in what places this will get called when current_cpu is
NULL and whether it's always OK to not clean the tag in that
situation.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 11/21] exec: Add support for TARGET_TAGGED_ADDRESSES
  2021-01-22 14:13   ` Peter Maydell
@ 2021-01-26 17:10     ` Richard Henderson
  0 siblings, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2021-01-26 17:10 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-arm, QEMU Developers

On 1/22/21 4:13 AM, Peter Maydell wrote:
> On Fri, 15 Jan 2021 at 22:47, 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 | 20 +++++++++++++++++---
>>  1 file changed, 17 insertions(+), 3 deletions(-)
>>
>> diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
>> index e62f4fba00..1df9b93e59 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
>>
>> +static inline abi_ptr untagged_addr(abi_ptr x)
>> +{
>> +#ifdef TARGET_TAGGED_ADDRESSES
>> +    if (current_cpu) {
>> +        return cpu_untagged_addr(current_cpu, x);
>> +    }
>> +#endif
>> +    return x;
>> +}
> 
> The current_cpu global is a nasty hack and I don't like seeing
> new usages of it. In particular, it's very difficult to
> analyse in what places this will get called when current_cpu is
> NULL and whether it's always OK to not clean the tag in that
> situation.

Well, that'll be a really lot of changes to add cpu/env as an argument to
get_user et al.

Let's see how easily coccinelle can fix em all up for me...


r~


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 18/21] linux-user/aarch64: Signal SEGV_MTEAERR for async tag check error
  2021-01-22 13:59   ` Peter Maydell
@ 2021-01-28  8:49     ` Richard Henderson
  2021-01-28 10:44       ` Peter Maydell
  0 siblings, 1 reply; 46+ messages in thread
From: Richard Henderson @ 2021-01-28  8:49 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-arm, QEMU Developers

On 1/22/21 3:59 AM, Peter Maydell wrote:
> On Fri, 15 Jan 2021 at 22:47, Richard Henderson
> <richard.henderson@linaro.org> wrote:
>>
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> 
> So when does the real kernel report async MTE exceptions to userspace?
> The commit message would be a good place to briefly describe the
> kernel's strategy and where QEMU differs from it (if anywhere)...

I can add that, sure.

>>          case EXCP_INTERRUPT:
>> -            /* just indicate that signals should be handled asap */
>> +            /* Just indicate that signals should be handled asap. */
>> +            check_mte_async_fault(env, &info);
>>              break;
>>          case EXCP_UDEF:
>>              info.si_signo = TARGET_SIGILL;
> 
> So this doesn't guarantee to check the async-fault status on
> every exit from cpu_exec(), which means we might miss things.
> For instance I think this slightly contrived example would not
> ever take the SEGV:
>     STR x0, [x1]   # with a bad tag
>     YIELD
> l:  B l
> 
> because the STR and YIELD go into the same TB, the YIELD causes us
> to leave the TB with EXCP_YIELD, we don't check for an async fault
> in that code path, and then we'll go into the infinite loop and
> have nothing to prompt us to come out and look at the async fault flags.

I'll add that test case to the smoke test.

> Does it work if we just always queue the SEGV on exit from cpu_exec()
> and let the signal handling machinery prioritize if we also pend
> some other signal because this was an EXCP_UDEF or whatever?
> It would be neater if we could keep the fault-check outside the
> switch (trapnr) somehow.

I would think so.  I'll try that.

>> +#ifdef CONFIG_USER_ONLY
>> +        /*
>> +         * Stand in for a timer irq, setting _TIF_MTE_ASYNC_FAULT,
>> +         * which then sends a SIGSEGV when the thread is next scheduled.
>> +         * This cpu will return to the main loop at the end of the TB,
>> +         * which is rather sooner than "normal".  But the alternative
>> +         * is waiting until the next syscall.
>> +         */
>> +        qemu_cpu_kick(env_cpu(env));
>> +#endif
>>          break;
> 
> This does the right thing, but qemu_cpu_kick() is one of those
> functions that's in a category of "not used much at all in the
> codebase" and which always make me wonder if there's a reason.
> (In particular there's exactly one use in the whole of target/
> right now.) I suppose the case of "helper function wants to cause
> us to leave the TB loop but not to abort the current insn" is
> an unusual one...

Exactly.

Usually something in target/ calls (via mmio or whatnot) something in hw/ which
raises an interrupt, which does the kick.


r~


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 18/21] linux-user/aarch64: Signal SEGV_MTEAERR for async tag check error
  2021-01-28  8:49     ` Richard Henderson
@ 2021-01-28 10:44       ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2021-01-28 10:44 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, QEMU Developers

On Thu, 28 Jan 2021 at 08:49, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 1/22/21 3:59 AM, Peter Maydell wrote:
> > Does it work if we just always queue the SEGV on exit from cpu_exec()
> > and let the signal handling machinery prioritize if we also pend
> > some other signal because this was an EXCP_UDEF or whatever?
> > It would be neater if we could keep the fault-check outside the
> > switch (trapnr) somehow.
>
> I would think so.  I'll try that.

In particular it seems worth testing whether 'singlestep in gdbstub
over an insn that takes an async MTE fault' has reasonable user-facing
behaviour.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 46+ messages in thread

end of thread, other threads:[~2021-01-28 10:45 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-15 22:46 [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode Richard Henderson
2021-01-15 22:46 ` [PATCH v3 01/21] tcg: Introduce target-specific page data for user-only Richard Henderson
2021-01-19 16:53   ` Peter Maydell
2021-01-15 22:46 ` [PATCH v3 02/21] linux-user: Introduce PAGE_ANON Richard Henderson
2021-01-15 22:46 ` [PATCH v3 03/21] exec: Use uintptr_t for guest_base Richard Henderson
2021-01-19 16:56   ` Peter Maydell
2021-01-15 22:46 ` [PATCH v3 04/21] exec: Use uintptr_t in cpu_ldst.h Richard Henderson
2021-01-19 16:56   ` Peter Maydell
2021-01-15 22:46 ` [PATCH v3 05/21] exec: Improve types for guest_addr_valid Richard Henderson
2021-01-19 16:57   ` Peter Maydell
2021-01-15 22:46 ` [PATCH v3 06/21] linux-user: Check for overflow in access_ok Richard Henderson
2021-01-15 22:46 ` [PATCH v3 07/21] linux-user: Tidy VERIFY_READ/VERIFY_WRITE Richard Henderson
2021-01-15 22:46 ` [PATCH v3 08/21] bsd-user: " Richard Henderson
2021-01-16 16:28   ` Warner Losh
2021-01-15 22:46 ` [PATCH v3 09/21] linux-user: Do not use guest_addr_valid for h2g_valid Richard Henderson
2021-01-19 16:59   ` Peter Maydell
2021-01-15 22:46 ` [PATCH v3 10/21] linux-user: Fix guest_addr_valid vs reserved_va Richard Henderson
2021-01-19 17:03   ` Peter Maydell
2021-01-19 17:41     ` Richard Henderson
2021-01-15 22:46 ` [PATCH v3 11/21] exec: Add support for TARGET_TAGGED_ADDRESSES Richard Henderson
2021-01-22 14:13   ` Peter Maydell
2021-01-26 17:10     ` Richard Henderson
2021-01-15 22:46 ` [PATCH v3 12/21] linux-user/aarch64: Implement PR_TAGGED_ADDR_ENABLE Richard Henderson
2021-01-22 11:36   ` Peter Maydell
2021-01-22 11:53   ` Peter Maydell
2021-01-22 12:02     ` Peter Maydell
2021-01-15 22:46 ` [PATCH v3 13/21] linux-user/aarch64: Implement PR_MTE_TCF and PR_MTE_TAG Richard Henderson
2021-01-22 11:48   ` Peter Maydell
2021-01-15 22:46 ` [PATCH v3 14/21] linux-user/aarch64: Implement PROT_MTE Richard Henderson
2021-01-15 22:46 ` [PATCH v3 15/21] target/arm: Split out syndrome.h from internals.h Richard Henderson
2021-01-19 17:07   ` Peter Maydell
2021-01-15 22:46 ` [PATCH v3 16/21] linux-user/aarch64: Pass syndrome to EXC_*_ABORT Richard Henderson
2021-01-19 17:12   ` Peter Maydell
2021-01-15 22:46 ` [PATCH v3 17/21] linux-user/aarch64: Signal SEGV_MTESERR for sync tag check fault Richard Henderson
2021-01-22 12:03   ` Peter Maydell
2021-01-15 22:46 ` [PATCH v3 18/21] linux-user/aarch64: Signal SEGV_MTEAERR for async tag check error Richard Henderson
2021-01-22 13:59   ` Peter Maydell
2021-01-28  8:49     ` Richard Henderson
2021-01-28 10:44       ` Peter Maydell
2021-01-15 22:46 ` [PATCH v3 19/21] target/arm: Add allocation tag storage for user mode Richard Henderson
2021-01-22 14:05   ` Peter Maydell
2021-01-15 22:46 ` [PATCH v3 20/21] target/arm: Enable MTE for user-only Richard Henderson
2021-01-22 14:02   ` Peter Maydell
2021-01-15 22:46 ` [PATCH v3 21/21] tests/tcg/aarch64: Add mte smoke tests Richard Henderson
2021-01-22 14:04   ` Peter Maydell
2021-01-15 23:15 ` [PATCH v3 00/21] target-arm: Implement ARMv8.5-MemTag, user mode no-reply

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).