1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (C) 2022 ARM Limited 3 4 #include <stdbool.h> 5 #include <stdio.h> 6 #include <string.h> 7 8 #include <sys/auxv.h> 9 #include <sys/prctl.h> 10 11 #include <asm/hwcap.h> 12 13 #include "kselftest.h" 14 15 static int set_tagged_addr_ctrl(int val) 16 { 17 int ret; 18 19 ret = prctl(PR_SET_TAGGED_ADDR_CTRL, val, 0, 0, 0); 20 if (ret < 0) 21 ksft_print_msg("PR_SET_TAGGED_ADDR_CTRL: failed %d %d (%s)\n", 22 ret, errno, strerror(errno)); 23 return ret; 24 } 25 26 static int get_tagged_addr_ctrl(void) 27 { 28 int ret; 29 30 ret = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0); 31 if (ret < 0) 32 ksft_print_msg("PR_GET_TAGGED_ADDR_CTRL failed: %d %d (%s)\n", 33 ret, errno, strerror(errno)); 34 return ret; 35 } 36 37 /* 38 * Read the current mode without having done any configuration, should 39 * run first. 40 */ 41 void check_basic_read(void) 42 { 43 int ret; 44 45 ret = get_tagged_addr_ctrl(); 46 if (ret < 0) { 47 ksft_test_result_fail("check_basic_read\n"); 48 return; 49 } 50 51 if (ret & PR_MTE_TCF_SYNC) 52 ksft_print_msg("SYNC enabled\n"); 53 if (ret & PR_MTE_TCF_ASYNC) 54 ksft_print_msg("ASYNC enabled\n"); 55 56 /* Any configuration is valid */ 57 ksft_test_result_pass("check_basic_read\n"); 58 } 59 60 /* 61 * Attempt to set a specified combination of modes. 62 */ 63 void set_mode_test(const char *name, int hwcap2, int mask) 64 { 65 int ret; 66 67 if ((getauxval(AT_HWCAP2) & hwcap2) != hwcap2) { 68 ksft_test_result_skip("%s\n", name); 69 return; 70 } 71 72 ret = set_tagged_addr_ctrl(mask); 73 if (ret < 0) { 74 ksft_test_result_fail("%s\n", name); 75 return; 76 } 77 78 ret = get_tagged_addr_ctrl(); 79 if (ret < 0) { 80 ksft_test_result_fail("%s\n", name); 81 return; 82 } 83 84 if ((ret & PR_MTE_TCF_MASK) == mask) { 85 ksft_test_result_pass("%s\n", name); 86 } else { 87 ksft_print_msg("Got %x, expected %x\n", 88 (ret & PR_MTE_TCF_MASK), mask); 89 ksft_test_result_fail("%s\n", name); 90 } 91 } 92 93 struct mte_mode { 94 int mask; 95 int hwcap2; 96 const char *name; 97 } mte_modes[] = { 98 { PR_MTE_TCF_NONE, 0, "NONE" }, 99 { PR_MTE_TCF_SYNC, HWCAP2_MTE, "SYNC" }, 100 { PR_MTE_TCF_ASYNC, HWCAP2_MTE, "ASYNC" }, 101 { PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC, HWCAP2_MTE, "SYNC+ASYNC" }, 102 }; 103 104 int main(void) 105 { 106 int i; 107 108 ksft_print_header(); 109 ksft_set_plan(5); 110 111 check_basic_read(); 112 for (i = 0; i < ARRAY_SIZE(mte_modes); i++) 113 set_mode_test(mte_modes[i].name, mte_modes[i].hwcap2, 114 mte_modes[i].mask); 115 116 ksft_print_cnts(); 117 118 return 0; 119 } 120