Path: blob/master/tools/testing/selftests/arm64/mte/check_prctl.c
26296 views
// SPDX-License-Identifier: GPL-2.01// Copyright (C) 2022 ARM Limited23#include <stdbool.h>4#include <stdio.h>5#include <string.h>67#include <sys/auxv.h>8#include <sys/prctl.h>910#include <asm/hwcap.h>1112#include "kselftest.h"1314#ifndef AT_HWCAP315#define AT_HWCAP3 2916#endif1718static int set_tagged_addr_ctrl(int val)19{20int ret;2122ret = prctl(PR_SET_TAGGED_ADDR_CTRL, val, 0, 0, 0);23if (ret < 0)24ksft_print_msg("PR_SET_TAGGED_ADDR_CTRL: failed %d %d (%s)\n",25ret, errno, strerror(errno));26return ret;27}2829static int get_tagged_addr_ctrl(void)30{31int ret;3233ret = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);34if (ret < 0)35ksft_print_msg("PR_GET_TAGGED_ADDR_CTRL failed: %d %d (%s)\n",36ret, errno, strerror(errno));37return ret;38}3940/*41* Read the current mode without having done any configuration, should42* run first.43*/44void check_basic_read(void)45{46int ret;4748ret = get_tagged_addr_ctrl();49if (ret < 0) {50ksft_test_result_fail("check_basic_read\n");51return;52}5354if (ret & PR_MTE_TCF_SYNC)55ksft_print_msg("SYNC enabled\n");56if (ret & PR_MTE_TCF_ASYNC)57ksft_print_msg("ASYNC enabled\n");5859/* Any configuration is valid */60ksft_test_result_pass("check_basic_read\n");61}6263/*64* Attempt to set a specified combination of modes.65*/66void set_mode_test(const char *name, int hwcap2, int hwcap3, int mask)67{68int ret;6970if ((getauxval(AT_HWCAP2) & hwcap2) != hwcap2) {71ksft_test_result_skip("%s\n", name);72return;73}7475if ((getauxval(AT_HWCAP3) & hwcap3) != hwcap3) {76ksft_test_result_skip("%s\n", name);77return;78}7980ret = set_tagged_addr_ctrl(mask);81if (ret < 0) {82ksft_test_result_fail("%s\n", name);83return;84}8586ret = get_tagged_addr_ctrl();87if (ret < 0) {88ksft_test_result_fail("%s\n", name);89return;90}9192if ((ret & (PR_MTE_TCF_MASK | PR_MTE_STORE_ONLY)) == mask) {93ksft_test_result_pass("%s\n", name);94} else {95ksft_print_msg("Got %x, expected %x\n",96(ret & (int)PR_MTE_TCF_MASK), mask);97ksft_test_result_fail("%s\n", name);98}99}100101struct mte_mode {102int mask;103int hwcap2;104int hwcap3;105const char *name;106} mte_modes[] = {107{ PR_MTE_TCF_NONE, 0, 0, "NONE" },108{ PR_MTE_TCF_SYNC, HWCAP2_MTE, 0, "SYNC" },109{ PR_MTE_TCF_ASYNC, HWCAP2_MTE, 0, "ASYNC" },110{ PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC, HWCAP2_MTE, 0, "SYNC+ASYNC" },111{ PR_MTE_TCF_SYNC | PR_MTE_STORE_ONLY, HWCAP2_MTE, HWCAP3_MTE_STORE_ONLY, "SYNC+STONLY" },112{ PR_MTE_TCF_ASYNC | PR_MTE_STORE_ONLY, HWCAP2_MTE, HWCAP3_MTE_STORE_ONLY, "ASYNC+STONLY" },113{ PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC | PR_MTE_STORE_ONLY, HWCAP2_MTE, HWCAP3_MTE_STORE_ONLY, "SYNC+ASYNC+STONLY" },114};115116int main(void)117{118int i;119120ksft_print_header();121ksft_set_plan(ARRAY_SIZE(mte_modes));122123check_basic_read();124for (i = 0; i < ARRAY_SIZE(mte_modes); i++)125set_mode_test(mte_modes[i].name, mte_modes[i].hwcap2, mte_modes[i].hwcap3,126mte_modes[i].mask);127128ksft_print_cnts();129130return 0;131}132133134