120 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (C) 2022 ARM Limited3 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 15static 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 26static 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, should39 * run first.40 */41void 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 */63void 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 93struct 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 104int 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