mirror of
https://github.com/apache/nuttx-apps.git
synced 2026-10-12 08:20:11 +00:00
mtetest: Add a series of tests for the mte instruction set
Added basic mte instructions, ldg, stg, irg, gmi instruction tests
➜ NX git:(master) ✗ qemu-system-aarch64 -cpu max -nographic \
-machine virt,virtualization=on,gic-version=3,mte=on \
-chardev stdio,id=con,mux=on, -serial chardev:con \
-mon chardev=con,mode=readline -kernel ./nuttx/nuttx
- Ready to Boot Primary CPU
- Boot from EL2
- Boot from EL1
- Boot to C runtime for OS Initialize
NuttShell (NSH)
nsh>
nsh>
nsh> mtetest
Spawning process for test: mtetest1
Running test: mtetest1
Test 'mtetest1' completed
Spawning process for test: mtetest2
Running test: mtetest2
Test 'mtetest2' completed
Spawning process for test: mtetest3
Running test: mtetest3
Test 'mtetest3' completed
Spawning process for test: mtetest4
Running test: mtetest4
Test 'mtetest4' completed
Spawning process for test: mtetest5
Running test: mtetest5
Test 'mtetest5' completed
All tests completed.
nsh>
Signed-off-by: wangmingrong1 <wangmingrong1@xiaomi.com>
This commit is contained in:
parent
0957d4b006
commit
5ab0115284
5 changed files with 456 additions and 0 deletions
23
testing/mtetest/CMakeLists.txt
Normal file
23
testing/mtetest/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# ##############################################################################
|
||||
# apps/testing/mtetest/CMakeLists.txt
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more contributor
|
||||
# license agreements. See the NOTICE file distributed with this work for
|
||||
# additional information regarding copyright ownership. The ASF licenses this
|
||||
# file to you under the Apache License, Version 2.0 (the "License"); you may not
|
||||
# use this file except in compliance with the License. You may obtain a copy of
|
||||
# the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
#
|
||||
# ##############################################################################
|
||||
|
||||
if(CONFIG_TESTING_MTE)
|
||||
nuttx_add_application(NAME mtetest COMPILE_FLAGS ${CFLAGS} SRCS mtetest.c)
|
||||
endif()
|
||||
11
testing/mtetest/Kconfig
Normal file
11
testing/mtetest/Kconfig
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
config TESTING_MTE
|
||||
tristate "MTE instruction set test"
|
||||
depends on ARM64_MTE
|
||||
default n
|
||||
---help---
|
||||
Enable MTE instruction set test
|
||||
23
testing/mtetest/Make.defs
Normal file
23
testing/mtetest/Make.defs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
############################################################################
|
||||
# apps/testing/mtetest/Make.defs
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
ifneq ($(CONFIG_TESTING_MTE),)
|
||||
CONFIGURED_APPS += $(APPDIR)/testing/mtetest
|
||||
endif
|
||||
28
testing/mtetest/Makefile
Normal file
28
testing/mtetest/Makefile
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
############################################################################
|
||||
# apps/testing/mtetest/Makefile
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
include $(APPDIR)/Make.defs
|
||||
|
||||
MAINSRC = mtetest.c
|
||||
PROGNAME = mtetest
|
||||
PRIORITY = $(CONFIG_TESTING_KASAN_PRIORITY)
|
||||
STACKSIZE = $(CONFIG_DEFAULT_TASK_STACKSIZE)
|
||||
|
||||
include $(APPDIR)/Application.mk
|
||||
371
testing/mtetest/mtetest.c
Normal file
371
testing/mtetest/mtetest.c
Normal file
|
|
@ -0,0 +1,371 @@
|
|||
/****************************************************************************
|
||||
* apps/testing/mtetest/mtetest.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/compiler.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <spawn.h>
|
||||
#include <string.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define MTETEST_BUFFER_LEN 512
|
||||
|
||||
struct mte_test_s
|
||||
{
|
||||
FAR const char *name;
|
||||
FAR void (*func)(void);
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static void mtetest1(void);
|
||||
static void mtetest2(void);
|
||||
static void mtetest3(void);
|
||||
static void mtetest4(void);
|
||||
static void mtetest5(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* The instruction requires a 16-byte aligned memory block. */
|
||||
|
||||
static aligned_data(16) char g_buffer[MTETEST_BUFFER_LEN];
|
||||
|
||||
static const struct mte_test_s g_mtetest[] =
|
||||
{
|
||||
{ "mtetest1", mtetest1 },
|
||||
{ "mtetest2", mtetest2 },
|
||||
{ "mtetest3", mtetest3 },
|
||||
{ "mtetest4", mtetest4 },
|
||||
{ "mtetest5", mtetest5 },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tagset
|
||||
*
|
||||
* Description:
|
||||
* Applies tags to a memory block starting from the pointer `p` for a
|
||||
* given size (`size`). The function iterates through the memory in
|
||||
* 16-byte chunks and uses the `stg` (store tag) instruction to assign
|
||||
* a tag to each address.
|
||||
*
|
||||
* - `p`: The starting pointer to the memory block.
|
||||
* - `size`: The size of the memory block (in bytes) to tag.
|
||||
*
|
||||
* The function uses inline assembly to store the tag at each memory
|
||||
* location in the specified region, ensuring that the entire block is
|
||||
* tagged.
|
||||
****************************************************************************/
|
||||
|
||||
static 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));
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tagcheck
|
||||
*
|
||||
* Description:
|
||||
* Verifies the consistency of tags in memory block starting from ptr `p`
|
||||
* for the given `size`. The function checks each 16-byte chunk using the
|
||||
* `ldg` (load tag) instruction to load the tag and compares it with the
|
||||
* original pointer `p` to ensure consistency.
|
||||
*
|
||||
* - `p`: The starting pointer to the memory block.
|
||||
* - `size`: The size of the memory block (in bytes) to check for
|
||||
* tag consistency.
|
||||
*
|
||||
* The function loads the tag for each chunk and ensures that the tag
|
||||
* matches the expected value. If the tag does not match, the function
|
||||
* triggers an assertion failure, providing a mechanism to validate
|
||||
* correct memory tagging and access.
|
||||
****************************************************************************/
|
||||
|
||||
static 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);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mtetest1
|
||||
*
|
||||
* Description:
|
||||
* 1. Initializes the pointer `p0` to point to `g_buffer`, which is assumed
|
||||
* to contain enough data.
|
||||
* 2. Uses the assembly instruction `irg` to create a tagged pointer `p1`
|
||||
* from `p0`. Asserts that `p1` is not equal to `p0`, confirming the
|
||||
* tagging operation worked.
|
||||
* 3. Uses the assembly instruction `subp` to calculate the difference
|
||||
* between `p0` and `p1`, storing it in `c`. Asserts that `c` is zero,
|
||||
* confirming that `p1` and `p0` are the same address.
|
||||
* 4. Uses `stg` to store the tag from `p1` at the address of `p1`.
|
||||
* 5. Uses `ldg` to load the tag from `p0` into `p2`. Asserts that `p1`
|
||||
* and `p2` are equal, confirming the tag stored at `p0` is correctly
|
||||
* retrieved into `p2`.
|
||||
****************************************************************************/
|
||||
|
||||
static void mtetest1(void)
|
||||
{
|
||||
long c;
|
||||
int *p0;
|
||||
int *p1;
|
||||
int *p2;
|
||||
|
||||
p0 = (int *)g_buffer;
|
||||
|
||||
asm("irg %0,%1,%2" : "=r"(p1) : "r"(p0), "r"(1l));
|
||||
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);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mtetest2
|
||||
*
|
||||
* Description:
|
||||
* 1. Initializes the pointer `p0` to point to `g_buffer`, which is assumed
|
||||
* to contain sufficient data.
|
||||
* 2. Uses the assembly instruction `irg` to create a tagged pointer `p1`
|
||||
* from `p0` using `excl`. The `gmi` instruction is used to modify `excl`,
|
||||
* and asserts that `excl` is different from 1, confirming the change.
|
||||
* 3. Creates a second tagged pointer `p2` using the modified `excl` and
|
||||
* asserts that `p1` and `p2` are different, validating that two distinct
|
||||
* tagged pointers are created.
|
||||
****************************************************************************/
|
||||
|
||||
static void mtetest2(void)
|
||||
{
|
||||
long excl = 1;
|
||||
int *p0;
|
||||
int *p1;
|
||||
int *p2;
|
||||
|
||||
p0 = (int *)g_buffer;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mtetest3
|
||||
*
|
||||
* Description:
|
||||
* 1. Initializes `p0` to point to `g_buffer`, which is assumed to contain
|
||||
* enough data.
|
||||
* 2. Uses the assembly instruction `irg` to create a tagged pointer `p1`
|
||||
* from `p0`. It then uses `gmi` to modify the `excl` value, ensuring it
|
||||
* is different from 1 (validated by an `assert`).
|
||||
* 3. Uses `irg` again to create a tagged pointer `p2` from `p0`. Asserts
|
||||
* that `p1` and `p2` are different, validating the creation of two
|
||||
* distinct tagged pointers.
|
||||
* 4. Stores the tag from the first pointer (`p1`) using the assembly
|
||||
* instruction `stg`.
|
||||
* 5. Stores the value at `p1` using the assembly instruction `str`, followed
|
||||
* by a `yield` to allow other tasks to execute.
|
||||
****************************************************************************/
|
||||
|
||||
static void mtetest3(void)
|
||||
{
|
||||
long excl = 1;
|
||||
int *p0;
|
||||
int *p1;
|
||||
int *p2;
|
||||
|
||||
p0 = (int *)g_buffer;
|
||||
|
||||
/* 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));
|
||||
asm("str %0, [%0]; yield" : : "r"(p1));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mtetest4
|
||||
*
|
||||
* Description:
|
||||
* 1. Initializes the pointer `p0` to point to `g_buffer`, which is assumed
|
||||
* to contain sufficient data.
|
||||
* 2. Uses the assembly instruction `irg` (likely a custom instruction) to
|
||||
* process `p0` and `excl`, storing the result in `p1`.
|
||||
* 3. Calls the `tagset` function with `p1` and `MTETEST_BUFFER_LEN` to set
|
||||
* tags for the buffer.
|
||||
* 4. Calls the `tagcheck` function with `p1` and `MTETEST_BUFFER_LEN` to
|
||||
* verify the tags for the buffer.
|
||||
****************************************************************************/
|
||||
|
||||
static void mtetest4(void)
|
||||
{
|
||||
long excl = 1;
|
||||
int *p0;
|
||||
int *p1;
|
||||
|
||||
p0 = (int *)g_buffer;
|
||||
|
||||
/* Tag the pointer. */
|
||||
|
||||
asm("irg %0,%1,%2" : "=r"(p1) : "r"(p0), "r"(excl));
|
||||
|
||||
tagset(p1, MTETEST_BUFFER_LEN);
|
||||
tagcheck(p1, MTETEST_BUFFER_LEN);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mtetest5
|
||||
*
|
||||
* Description:
|
||||
* 1. Initializes the pointer `p0` to point to `g_buffer`, which is assumed
|
||||
* to contain enough data.
|
||||
* 2. Uses the assembly instruction `irg` (possibly a custom instruction)
|
||||
* to process `p0` and `excl`, storing the result in `p1`.
|
||||
* 3. Uses the assembly instruction `stg` to store data at the address
|
||||
* `p0 + 16`.
|
||||
* 4. Uses standard C syntax to assign the value 1 to the address `p0 + 16`.
|
||||
* 5. Uses the assembly instruction `stg` to store data at the address
|
||||
* `p1 + 16`.
|
||||
* 6. Uses `assert` to verify that the value at `p1 + 16` is 1, ensuring
|
||||
* that the assignment was successful.
|
||||
****************************************************************************/
|
||||
|
||||
static void mtetest5(void)
|
||||
{
|
||||
long excl = 1;
|
||||
int *p0;
|
||||
int *p1;
|
||||
|
||||
p0 = (int *)g_buffer;
|
||||
|
||||
/* Tag the pointer. */
|
||||
|
||||
asm("irg %0,%1,%2" : "=r"(p1) : "r"(p0), "r"(excl));
|
||||
|
||||
/* Assign value 1 to the address p0 + 16 */
|
||||
|
||||
asm("stg %0, [%0]" : : "r"(p0 + 16));
|
||||
*(p0 + 16) = 1;
|
||||
|
||||
asm("stg %0, [%0]" : : "r"(p1 + 16));
|
||||
assert(1 == *(p1 + 16));
|
||||
}
|
||||
|
||||
static void spawn_test_process(const struct mte_test_s *test)
|
||||
{
|
||||
char *args[3];
|
||||
int status;
|
||||
pid_t pid;
|
||||
|
||||
args[0] = "mtetest";
|
||||
args[1] = (char *)test->name;
|
||||
args[2] = NULL;
|
||||
|
||||
if (posix_spawn(&pid, "mtetest", NULL, NULL, args, environ) != 0)
|
||||
{
|
||||
perror("posix_spawn");
|
||||
return;
|
||||
}
|
||||
|
||||
waitpid(pid, &status, 0);
|
||||
printf("Test '%s' completed\n", test->name);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
/* Loop through the tests and spawn a process for each one */
|
||||
|
||||
for (i = 0; g_mtetest[i].name != NULL; i++)
|
||||
{
|
||||
printf("Spawning process for test: %s\n", g_mtetest[i].name);
|
||||
spawn_test_process(&g_mtetest[i]);
|
||||
}
|
||||
|
||||
printf("All tests completed.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; g_mtetest[i].name != NULL; i++)
|
||||
{
|
||||
if (strcmp(argv[1], g_mtetest[i].name) == 0)
|
||||
{
|
||||
printf("Running test: %s\n", g_mtetest[i].name);
|
||||
g_mtetest[i].func();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue