check_gcr_el1_cswitch.c (2657B)
1// SPDX-License-Identifier: GPL-2.0 2// Copyright (C) 2020 ARM Limited 3 4#define _GNU_SOURCE 5 6#include <errno.h> 7#include <pthread.h> 8#include <stdint.h> 9#include <stdio.h> 10#include <stdlib.h> 11#include <time.h> 12#include <unistd.h> 13#include <sys/auxv.h> 14#include <sys/mman.h> 15#include <sys/prctl.h> 16#include <sys/types.h> 17#include <sys/wait.h> 18 19#include "kselftest.h" 20#include "mte_common_util.h" 21 22#include "mte_def.h" 23 24#define NUM_ITERATIONS 1024 25#define MAX_THREADS 5 26#define THREAD_ITERATIONS 1000 27 28void *execute_thread(void *x) 29{ 30 pid_t pid = *((pid_t *)x); 31 pid_t tid = gettid(); 32 uint64_t prctl_tag_mask; 33 uint64_t prctl_set; 34 uint64_t prctl_get; 35 uint64_t prctl_tcf; 36 37 srand(time(NULL) ^ (pid << 16) ^ (tid << 16)); 38 39 prctl_tag_mask = rand() & 0xffff; 40 41 if (prctl_tag_mask % 2) 42 prctl_tcf = PR_MTE_TCF_SYNC; 43 else 44 prctl_tcf = PR_MTE_TCF_ASYNC; 45 46 prctl_set = PR_TAGGED_ADDR_ENABLE | prctl_tcf | (prctl_tag_mask << PR_MTE_TAG_SHIFT); 47 48 for (int j = 0; j < THREAD_ITERATIONS; j++) { 49 if (prctl(PR_SET_TAGGED_ADDR_CTRL, prctl_set, 0, 0, 0)) { 50 perror("prctl() failed"); 51 goto fail; 52 } 53 54 prctl_get = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0); 55 56 if (prctl_set != prctl_get) { 57 ksft_print_msg("Error: prctl_set: 0x%lx != prctl_get: 0x%lx\n", 58 prctl_set, prctl_get); 59 goto fail; 60 } 61 } 62 63 return (void *)KSFT_PASS; 64 65fail: 66 return (void *)KSFT_FAIL; 67} 68 69int execute_test(pid_t pid) 70{ 71 pthread_t thread_id[MAX_THREADS]; 72 int thread_data[MAX_THREADS]; 73 74 for (int i = 0; i < MAX_THREADS; i++) 75 pthread_create(&thread_id[i], NULL, 76 execute_thread, (void *)&pid); 77 78 for (int i = 0; i < MAX_THREADS; i++) 79 pthread_join(thread_id[i], (void *)&thread_data[i]); 80 81 for (int i = 0; i < MAX_THREADS; i++) 82 if (thread_data[i] == KSFT_FAIL) 83 return KSFT_FAIL; 84 85 return KSFT_PASS; 86} 87 88int mte_gcr_fork_test(void) 89{ 90 pid_t pid; 91 int results[NUM_ITERATIONS]; 92 pid_t cpid; 93 int res; 94 95 for (int i = 0; i < NUM_ITERATIONS; i++) { 96 pid = fork(); 97 98 if (pid < 0) 99 return KSFT_FAIL; 100 101 if (pid == 0) { 102 cpid = getpid(); 103 104 res = execute_test(cpid); 105 106 exit(res); 107 } 108 } 109 110 for (int i = 0; i < NUM_ITERATIONS; i++) { 111 wait(&res); 112 113 if (WIFEXITED(res)) 114 results[i] = WEXITSTATUS(res); 115 else 116 --i; 117 } 118 119 for (int i = 0; i < NUM_ITERATIONS; i++) 120 if (results[i] == KSFT_FAIL) 121 return KSFT_FAIL; 122 123 return KSFT_PASS; 124} 125 126int main(int argc, char *argv[]) 127{ 128 int err; 129 130 err = mte_default_setup(); 131 if (err) 132 return err; 133 134 ksft_set_plan(1); 135 136 evaluate_test(mte_gcr_fork_test(), 137 "Verify that GCR_EL1 is set correctly on context switch\n"); 138 139 mte_restore_setup(); 140 ksft_print_cnts(); 141 142 return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL; 143}