This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
The following commit(s) were added to refs/heads/master by this push:
new edf44c881 mtetest: add thread to control mte test separately
edf44c881 is described below
commit edf44c881b6a390f8c2bcd62aac8adb176429558
Author: wangmingrong1 <[email protected]>
AuthorDate: Tue Jan 7 11:52:09 2025 +0800
mtetest: add thread to control mte test separately
After thread A holds the semaphore, it first accesses it safely. After
releasing it, thread B closes MTE for unsafe access. After accessing, it
switches back to thread A for unsafe access. At this time, an error should be
reported.
log:
Process 1 holding lock
Process 2 holding lock
Process 1 holding lock again
default_fatal_handler: (IFSC/DFSC) for Data/Instruction aborts: synchronous
tag check fault
arm64_exception_handler: CurrentEL: MODE_EL1
arm64_exception_handler: ESR_ELn: 0x96000011
arm64_exception_handler: FAR_ELn: 0xf00000040441700
arm64_exception_handler: ELR_ELn: 0x402ee5f4
print_ec_cause: DABT (current EL)
print_ec_cause: Data Abort taken without a change in Exception level
Signed-off-by: wangmingrong1 <[email protected]>
---
testing/mtetest/Kconfig | 8 +++
testing/mtetest/Makefile | 2 +-
testing/mtetest/mtetest.c | 122 ++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 126 insertions(+), 6 deletions(-)
diff --git a/testing/mtetest/Kconfig b/testing/mtetest/Kconfig
index e4574d581..d00f5ac4f 100644
--- a/testing/mtetest/Kconfig
+++ b/testing/mtetest/Kconfig
@@ -9,3 +9,11 @@ config TESTING_MTE
default n
---help---
Enable MTE instruction set test
+
+if TESTING_MTE
+
+config TESTING_MTE_PRIORITY
+ int "Task priority"
+ default 101
+
+endif
diff --git a/testing/mtetest/Makefile b/testing/mtetest/Makefile
index 9d9a3239f..73599309f 100644
--- a/testing/mtetest/Makefile
+++ b/testing/mtetest/Makefile
@@ -24,7 +24,7 @@ include $(APPDIR)/Make.defs
MAINSRC = mtetest.c
PROGNAME = mtetest
-PRIORITY = $(CONFIG_TESTING_KASAN_PRIORITY)
+PRIORITY = $(CONFIG_TESTING_MTE_PRIORITY)
STACKSIZE = $(CONFIG_DEFAULT_TASK_STACKSIZE)
include $(APPDIR)/Application.mk
diff --git a/testing/mtetest/mtetest.c b/testing/mtetest/mtetest.c
index 351c38b22..ac2f0bf1a 100644
--- a/testing/mtetest/mtetest.c
+++ b/testing/mtetest/mtetest.c
@@ -27,25 +27,42 @@
#include <nuttx/config.h>
#include <nuttx/compiler.h>
+#include <sys/wait.h>
+
+#include <spawn.h>
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
-#include <spawn.h>
#include <string.h>
-#include <sys/wait.h>
+#include <unistd.h>
+#include <pthread.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
+/* Must be a multiple of sixteen */
#define MTETEST_BUFFER_LEN 512
+#define SCTLR_TCF1_BIT (1ul << 40)
+
+/****************************************************************************
+ * Private Type
+ ****************************************************************************/
+
struct mte_test_s
{
FAR const char *name;
FAR void (*func)(void);
};
+struct args_s
+{
+ char *buffer;
+ size_t safe_len;
+ size_t len;
+ sem_t sem;
+};
+
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
@@ -55,6 +72,7 @@ static void mtetest2(void);
static void mtetest3(void);
static void mtetest4(void);
static void mtetest5(void);
+static void switch_mtetest(void);
/****************************************************************************
* Private Data
@@ -71,6 +89,7 @@ static const struct mte_test_s g_mtetest[] =
{ "mtetest3", mtetest3 },
{ "mtetest4", mtetest4 },
{ "mtetest5", mtetest5 },
+ { "Thread switch MTE test", switch_mtetest },
{ NULL, NULL }
};
@@ -95,7 +114,7 @@ static const struct mte_test_s g_mtetest[] =
* tagged.
****************************************************************************/
-static void __attribute__((noinline)) tagset(void *p, size_t size)
+static void tagset(const void *p, size_t size)
{
size_t i;
for (i = 0; i < size; i += 16)
@@ -123,7 +142,7 @@ static void __attribute__((noinline)) tagset(void *p,
size_t size)
* correct memory tagging and access.
****************************************************************************/
-static void __attribute__((noinline)) tagcheck(void *p, size_t size)
+static void tagcheck(const void *p, size_t size)
{
size_t i;
void *c;
@@ -135,6 +154,15 @@ static void __attribute__((noinline)) tagcheck(void *p,
size_t size)
}
}
+/* Disable the mte function */
+
+static void disable_mte(void)
+{
+ uint64_t val = read_sysreg(sctlr_el1);
+ val &= ~SCTLR_TCF1_BIT;
+ write_sysreg(val, sctlr_el1);
+}
+
/****************************************************************************
* Name: mtetest1
*
@@ -316,6 +344,90 @@ static void mtetest5(void)
assert(1 == *(p1 + 16));
}
+/* The first entry gets the semaphore for safe access,
+ * and the next switch back to unsafe access
+ */
+
+static void *process1(void *arg)
+{
+ struct args_s *args = (struct args_s *)arg;
+ int i;
+
+ while (1)
+ {
+ sem_wait(&args->sem);
+ printf("Process 1 holding lock\n");
+
+ for (i = 0; i < args->safe_len; i++)
+ {
+ args->buffer[i]++;
+ }
+
+ sem_post(&args->sem);
+ sleep(1);
+ printf("Process 1 holding lock again\n");
+ for (i = 0; i < args->len; i++)
+ {
+ args->buffer[i]++;
+ }
+
+ sem_post(&args->sem);
+ }
+
+ return NULL;
+}
+
+/* Disable unsafe access to MTE functions */
+
+static void *process2(void *arg)
+{
+ struct args_s *args = (struct args_s *)arg;
+ int i;
+
+ while (1)
+ {
+ sem_wait(&args->sem);
+
+ printf("Process 2 holding lock\n");
+ disable_mte();
+
+ for (i = 0; i < args->len; i++)
+ {
+ args->buffer[i]++;
+ }
+
+ sem_post(&args->sem);
+ sleep(1);
+ }
+
+ return NULL;
+}
+
+static void switch_mtetest(void)
+{
+ struct args_s args;
+ pthread_t t1;
+ pthread_t t2;
+
+ sem_init(&args.sem, 1, 1);
+
+ asm("irg %0,%1,%2" : "=r"(args.buffer) : "r"(g_buffer), "r"(1l));
+ assert(args.buffer != g_buffer);
+
+ args.safe_len = sizeof(g_buffer) / 2;
+ args.len = sizeof(g_buffer);
+
+ tagset(args.buffer, args.safe_len);
+
+ pthread_create(&t1, NULL, process1, &args);
+ pthread_create(&t2, NULL, process2, &args);
+
+ pthread_join(t1, NULL);
+ pthread_join(t2, NULL);
+
+ sem_destroy(&args.sem);
+}
+
static void spawn_test_process(const struct mte_test_s *test)
{
char *args[3];