lkml.org 
[lkml]   [2020]   [Nov]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    Subject[PATCH v7 41/41] kselftest/arm64: Check GCR_EL1 after context switch
    From
    From: Vincenzo Frascino <vincenzo.frascino@arm.com>

    This test is specific to MTE and verifies that the GCR_EL1 register
    is context switched correctly.

    It spawn 1024 processes and each process spawns 5 threads. Each thread
    writes a random setting of GCR_EL1 through the prctl() system call and
    reads it back verifying that it is the same. If the values are not the
    same it reports a failure.

    Note: The test has been extended to verify that even SYNC and ASYNC mode
    setting is preserved correctly over context switching.

    Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
    Signed-off-by: Andrey Konovalov <andreyknvl@google.com>
    ---
    Change-Id: Ia917684a2b8e5f29e705ca5cbf360b010df6f61e
    ---
    tools/testing/selftests/arm64/mte/Makefile | 2 +-
    .../arm64/mte/check_gcr_el1_cswitch.c | 152 ++++++++++++++++++
    2 files changed, 153 insertions(+), 1 deletion(-)
    create mode 100644 tools/testing/selftests/arm64/mte/check_gcr_el1_cswitch.c

    diff --git a/tools/testing/selftests/arm64/mte/Makefile b/tools/testing/selftests/arm64/mte/Makefile
    index 2480226dfe57..0b3af552632a 100644
    --- a/tools/testing/selftests/arm64/mte/Makefile
    +++ b/tools/testing/selftests/arm64/mte/Makefile
    @@ -1,7 +1,7 @@
    # SPDX-License-Identifier: GPL-2.0
    # Copyright (C) 2020 ARM Limited

    -CFLAGS += -std=gnu99 -I.
    +CFLAGS += -std=gnu99 -I. -lpthread
    SRCS := $(filter-out mte_common_util.c,$(wildcard *.c))
    PROGS := $(patsubst %.c,%,$(SRCS))

    diff --git a/tools/testing/selftests/arm64/mte/check_gcr_el1_cswitch.c b/tools/testing/selftests/arm64/mte/check_gcr_el1_cswitch.c
    new file mode 100644
    index 000000000000..55e33d96794c
    --- /dev/null
    +++ b/tools/testing/selftests/arm64/mte/check_gcr_el1_cswitch.c
    @@ -0,0 +1,152 @@
    +// SPDX-License-Identifier: GPL-2.0
    +// Copyright (C) 2020 ARM Limited
    +
    +#define _GNU_SOURCE
    +
    +#include <errno.h>
    +#include <pthread.h>
    +#include <stdint.h>
    +#include <stdio.h>
    +#include <stdlib.h>
    +#include <time.h>
    +#include <unistd.h>
    +#include <sys/auxv.h>
    +#include <sys/mman.h>
    +#include <sys/prctl.h>
    +#include <sys/types.h>
    +#include <sys/wait.h>
    +
    +#include "kselftest.h"
    +#include "mte_common_util.h"
    +
    +#define PR_SET_TAGGED_ADDR_CTRL 55
    +#define PR_GET_TAGGED_ADDR_CTRL 56
    +# define PR_TAGGED_ADDR_ENABLE (1UL << 0)
    +# 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_TCF_MASK (3UL << PR_MTE_TCF_SHIFT)
    +# define PR_MTE_TAG_SHIFT 3
    +# define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
    +
    +#include "mte_def.h"
    +
    +#define NUM_ITERATIONS 1024
    +#define MAX_THREADS 5
    +#define THREAD_ITERATIONS 1000
    +
    +void *execute_thread(void *x)
    +{
    + pid_t pid = *((pid_t *)x);
    + pid_t tid = gettid();
    + uint64_t prctl_tag_mask;
    + uint64_t prctl_set;
    + uint64_t prctl_get;
    + uint64_t prctl_tcf;
    +
    + srand(time(NULL) ^ (pid << 16) ^ (tid << 16));
    +
    + prctl_tag_mask = rand() % 0xffff;
    +
    + if (prctl_tag_mask % 2)
    + prctl_tcf = PR_MTE_TCF_SYNC;
    + else
    + prctl_tcf = PR_MTE_TCF_ASYNC;
    +
    + prctl_set = PR_TAGGED_ADDR_ENABLE | prctl_tcf | (prctl_tag_mask << PR_MTE_TAG_SHIFT);
    +
    + for (int j = 0; j < THREAD_ITERATIONS; j++) {
    + if (prctl(PR_SET_TAGGED_ADDR_CTRL, prctl_set, 0, 0, 0)) {
    + perror("prctl() failed");
    + goto fail;
    + }
    +
    + prctl_get = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
    +
    + if (prctl_set != prctl_get) {
    + ksft_print_msg("Error: prctl_set: 0x%lx != prctl_get: 0x%lx\n",
    + prctl_set, prctl_get);
    + goto fail;
    + }
    + }
    +
    + return (void *)KSFT_PASS;
    +
    +fail:
    + return (void *)KSFT_FAIL;
    +}
    +
    +int execute_test(pid_t pid)
    +{
    + pthread_t thread_id[MAX_THREADS];
    + int thread_data[MAX_THREADS];
    +
    + for (int i = 0; i < MAX_THREADS; i++)
    + pthread_create(&thread_id[i], NULL,
    + execute_thread, (void *)&pid);
    +
    + for (int i = 0; i < MAX_THREADS; i++)
    + pthread_join(thread_id[i], (void *)&thread_data[i]);
    +
    + for (int i = 0; i < MAX_THREADS; i++)
    + if (thread_data[i] == KSFT_FAIL)
    + return KSFT_FAIL;
    +
    + return KSFT_PASS;
    +}
    +
    +int mte_gcr_fork_test()
    +{
    + pid_t pid[NUM_ITERATIONS];
    + int results[NUM_ITERATIONS];
    + pid_t cpid;
    + int res;
    +
    + for (int i = 0; i < NUM_ITERATIONS; i++) {
    + pid[i] = fork();
    +
    + if (pid[i] == 0) {
    + cpid = getpid();
    +
    + res = execute_test(cpid);
    +
    + exit(res);
    + }
    + }
    +
    + for (int i = 0; i < NUM_ITERATIONS; i++) {
    + wait(&res);
    +
    + if(WIFEXITED(res))
    + results[i] = WEXITSTATUS(res);
    + else
    + --i;
    + }
    +
    + for (int i = 0; i < NUM_ITERATIONS; i++)
    + if (results[i] == KSFT_FAIL)
    + return KSFT_FAIL;
    +
    + return KSFT_PASS;
    +}
    +
    +int main(int argc, char *argv[])
    +{
    + int err;
    +
    + err = mte_default_setup();
    + if (err)
    + return err;
    +
    + ksft_set_plan(1);
    +
    + evaluate_test(mte_gcr_fork_test(),
    + "Verify that GCR_EL1 is set correctly on context switch\n");
    +
    + mte_restore_setup();
    + ksft_print_cnts();
    +
    + return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL;
    +}
    +
    --
    2.29.1.341.ge80a0c044ae-goog
    \
     
     \ /
      Last update: 2020-11-02 17:06    [W:4.078 / U:0.340 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site