[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 16/30] target/arm: Implement MTE tag-checking functions for FEAT_M
From: |
Peter Maydell |
Subject: |
[PULL 16/30] target/arm: Implement MTE tag-checking functions for FEAT_MOPS |
Date: |
Thu, 21 Sep 2023 18:37:06 +0100 |
The FEAT_MOPS instructions need a couple of helper routines that
check for MTE tag failures:
* mte_mops_probe() checks whether there is going to be a tag
error in the next up-to-a-page worth of data
* mte_check_fail() is an existing function to record the fact
of a tag failure, which we need to make global so we can
call it from helper-a64.c
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20230912140434.1333369-7-peter.maydell@linaro.org
---
target/arm/internals.h | 28 +++++++++++++++++++
target/arm/tcg/mte_helper.c | 54 +++++++++++++++++++++++++++++++++++--
2 files changed, 80 insertions(+), 2 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 5f5393b25c4..a70a7fd50f6 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1272,6 +1272,34 @@ FIELD(MTEDESC, SIZEM1, 12, SIMD_DATA_BITS - 12) /* size
- 1 */
bool mte_probe(CPUARMState *env, uint32_t desc, uint64_t ptr);
uint64_t mte_check(CPUARMState *env, uint32_t desc, uint64_t ptr, uintptr_t
ra);
+/**
+ * mte_mops_probe: Check where the next MTE failure is for a FEAT_MOPS
operation
+ * @env: CPU env
+ * @ptr: start address of memory region (dirty pointer)
+ * @size: length of region (guaranteed not to cross a page boundary)
+ * @desc: MTEDESC descriptor word (0 means no MTE checks)
+ * Returns: the size of the region that can be copied without hitting
+ * an MTE tag failure
+ *
+ * Note that we assume that the caller has already checked the TBI
+ * and TCMA bits with mte_checks_needed() and an MTE check is definitely
+ * required.
+ */
+uint64_t mte_mops_probe(CPUARMState *env, uint64_t ptr, uint64_t size,
+ uint32_t desc);
+
+/**
+ * mte_check_fail: Record an MTE tag check failure
+ * @env: CPU env
+ * @desc: MTEDESC descriptor word
+ * @dirty_ptr: Failing dirty address
+ * @ra: TCG retaddr
+ *
+ * This may never return (if the MTE tag checks are configured to fault).
+ */
+void mte_check_fail(CPUARMState *env, uint32_t desc,
+ uint64_t dirty_ptr, uintptr_t ra);
+
static inline int allocation_tag_from_addr(uint64_t ptr)
{
return extract64(ptr, 56, 4);
diff --git a/target/arm/tcg/mte_helper.c b/target/arm/tcg/mte_helper.c
index 303bcc7fd84..1cb61cea7af 100644
--- a/target/arm/tcg/mte_helper.c
+++ b/target/arm/tcg/mte_helper.c
@@ -617,8 +617,8 @@ static void mte_async_check_fail(CPUARMState *env, uint64_t
dirty_ptr,
}
/* Record a tag check failure. */
-static void mte_check_fail(CPUARMState *env, uint32_t desc,
- uint64_t dirty_ptr, uintptr_t ra)
+void mte_check_fail(CPUARMState *env, uint32_t desc,
+ uint64_t dirty_ptr, uintptr_t ra)
{
int mmu_idx = FIELD_EX32(desc, MTEDESC, MIDX);
ARMMMUIdx arm_mmu_idx = core_to_aa64_mmu_idx(mmu_idx);
@@ -991,3 +991,53 @@ uint64_t HELPER(mte_check_zva)(CPUARMState *env, uint32_t
desc, uint64_t ptr)
done:
return useronly_clean_ptr(ptr);
}
+
+uint64_t mte_mops_probe(CPUARMState *env, uint64_t ptr, uint64_t size,
+ uint32_t desc)
+{
+ int mmu_idx, tag_count;
+ uint64_t ptr_tag, tag_first, tag_last;
+ void *mem;
+ bool w = FIELD_EX32(desc, MTEDESC, WRITE);
+ uint32_t n;
+
+ mmu_idx = FIELD_EX32(desc, MTEDESC, MIDX);
+ /* True probe; this will never fault */
+ mem = allocation_tag_mem_probe(env, mmu_idx, ptr,
+ w ? MMU_DATA_STORE : MMU_DATA_LOAD,
+ size, MMU_DATA_LOAD, true, 0);
+ if (!mem) {
+ return size;
+ }
+
+ /*
+ * TODO: checkN() is not designed for checks of the size we expect
+ * for FEAT_MOPS operations, so we should implement this differently.
+ * Maybe we should do something like
+ * if (region start and size are aligned nicely) {
+ * do direct loads of 64 tag bits at a time;
+ * } else {
+ * call checkN()
+ * }
+ */
+ /* Round the bounds to the tag granule, and compute the number of tags. */
+ ptr_tag = allocation_tag_from_addr(ptr);
+ tag_first = QEMU_ALIGN_DOWN(ptr, TAG_GRANULE);
+ tag_last = QEMU_ALIGN_DOWN(ptr + size - 1, TAG_GRANULE);
+ tag_count = ((tag_last - tag_first) / TAG_GRANULE) + 1;
+ n = checkN(mem, ptr & TAG_GRANULE, ptr_tag, tag_count);
+ if (likely(n == tag_count)) {
+ return size;
+ }
+
+ /*
+ * Failure; for the first granule, it's at @ptr. Otherwise
+ * it's at the first byte of the nth granule. Calculate how
+ * many bytes we can access without hitting that failure.
+ */
+ if (n == 0) {
+ return 0;
+ } else {
+ return n * TAG_GRANULE - (ptr - tag_first);
+ }
+}
--
2.34.1
- [PULL 04/30] linux-user/elfload.c: Correct SME feature names reported in cpuinfo, (continued)
- [PULL 04/30] linux-user/elfload.c: Correct SME feature names reported in cpuinfo, Peter Maydell, 2023/09/21
- [PULL 03/30] hw/arm/boot: Set SCR_EL3.FGTEn when booting kernel, Peter Maydell, 2023/09/21
- [PULL 08/30] target/arm: Update user-mode ID reg mask values, Peter Maydell, 2023/09/21
- [PULL 10/30] target/arm: Remove unused allocation_tag_mem() argument, Peter Maydell, 2023/09/21
- [PULL 12/30] target/arm: Implement FEAT_MOPS enable bits, Peter Maydell, 2023/09/21
- [PULL 14/30] target/arm: Define syndrome function for MOPS exceptions, Peter Maydell, 2023/09/21
- [PULL 17/30] target/arm: Implement the SET* instructions, Peter Maydell, 2023/09/21
- [PULL 05/30] linux-user/elfload.c: Add missing arm and arm64 hwcap values, Peter Maydell, 2023/09/21
- [PULL 19/30] target/arm: Implement the SETG* instructions, Peter Maydell, 2023/09/21
- [PULL 20/30] target/arm: Implement MTE tag-checking functions for FEAT_MOPS copies, Peter Maydell, 2023/09/21
- [PULL 16/30] target/arm: Implement MTE tag-checking functions for FEAT_MOPS,
Peter Maydell <=
- [PULL 13/30] target/arm: Pass unpriv bool to get_a64_user_mem_index(), Peter Maydell, 2023/09/21
- [PULL 06/30] linux-user/elfload.c: Report previously missing arm32 hwcaps, Peter Maydell, 2023/09/21
- [PULL 23/30] audio/jackaudio: Avoid dynamic stack allocation in qjack_client_init, Peter Maydell, 2023/09/21
- [PULL 21/30] target/arm: Implement the CPY* instructions, Peter Maydell, 2023/09/21
- [PULL 18/30] target/arm: Define new TB flag for ATA0, Peter Maydell, 2023/09/21
- [PULL 28/30] elf2dmp: introduce merging of physical memory runs, Peter Maydell, 2023/09/21
- [PULL 15/30] target/arm: New function allocation_tag_mem_probe(), Peter Maydell, 2023/09/21
- [PULL 29/30] elf2dmp: use Linux mmap with MAP_NORESERVE when possible, Peter Maydell, 2023/09/21
- [PULL 24/30] audio/jackaudio: Avoid dynamic stack allocation in qjack_process(), Peter Maydell, 2023/09/21
- [PULL 30/30] elf2dmp: rework PDB_STREAM_INDEXES::segments obtaining, Peter Maydell, 2023/09/21