File Index
Files and directories
Sign in
FILE

check_prctl.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/arm64/mte/check_prctl.c C
  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#ifndef AT_HWCAP3
 16#define AT_HWCAP3 29
 17#endif
 18
 19static int set_tagged_addr_ctrl(int val)
 20{
 21	int ret;
 22
 23	ret = prctl(PR_SET_TAGGED_ADDR_CTRL, val, 0, 0, 0);
 24	if (ret < 0)
 25		ksft_print_msg("PR_SET_TAGGED_ADDR_CTRL: failed %d %d (%s)\n",
 26			       ret, errno, strerror(errno));
 27	return ret;
 28}
 29
 30static int get_tagged_addr_ctrl(void)
 31{
 32	int ret;
 33
 34	ret = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
 35	if (ret < 0)
 36		ksft_print_msg("PR_GET_TAGGED_ADDR_CTRL failed: %d %d (%s)\n",
 37			       ret, errno, strerror(errno));
 38	return ret;
 39}
 40
 41/*
 42 * Read the current mode without having done any configuration, should
 43 * run first.
 44 */
 45void check_basic_read(void)
 46{
 47	int ret;
 48
 49	ret = get_tagged_addr_ctrl();
 50	if (ret < 0) {
 51		ksft_test_result_fail("check_basic_read\n");
 52		return;
 53	}
 54
 55	if (ret & PR_MTE_TCF_SYNC)
 56		ksft_print_msg("SYNC enabled\n");
 57	if (ret & PR_MTE_TCF_ASYNC)
 58		ksft_print_msg("ASYNC enabled\n");
 59
 60	/* Any configuration is valid */
 61	ksft_test_result_pass("check_basic_read\n");
 62}
 63
 64/*
 65 * Attempt to set a specified combination of modes.
 66 */
 67void set_mode_test(const char *name, int hwcap2, int hwcap3, int mask)
 68{
 69	int ret;
 70
 71	if ((getauxval(AT_HWCAP2) & hwcap2) != hwcap2) {
 72		ksft_test_result_skip("%s\n", name);
 73		return;
 74	}
 75
 76	if ((getauxval(AT_HWCAP3) & hwcap3) != hwcap3) {
 77		ksft_test_result_skip("%s\n", name);
 78		return;
 79	}
 80
 81	ret = set_tagged_addr_ctrl(mask);
 82	if (ret < 0) {
 83		ksft_test_result_fail("%s\n", name);
 84		return;
 85	}
 86
 87	ret = get_tagged_addr_ctrl();
 88	if (ret < 0) {
 89		ksft_test_result_fail("%s\n", name);
 90		return;
 91	}
 92
 93	if ((ret & (PR_MTE_TCF_MASK | PR_MTE_STORE_ONLY)) == mask) {
 94		ksft_test_result_pass("%s\n", name);
 95	} else {
 96		ksft_print_msg("Got %x, expected %x\n",
 97			       (ret & (int)PR_MTE_TCF_MASK), mask);
 98		ksft_test_result_fail("%s\n", name);
 99	}
100}
101
102struct mte_mode {
103	int mask;
104	int hwcap2;
105	int hwcap3;
106	const char *name;
107} mte_modes[] = {
108	{ PR_MTE_TCF_NONE,                                        0,          0,                     "NONE"  },
109	{ PR_MTE_TCF_SYNC,                                        HWCAP2_MTE, 0,                     "SYNC"  },
110	{ PR_MTE_TCF_ASYNC,                                       HWCAP2_MTE, 0,                     "ASYNC" },
111	{ PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC,                     HWCAP2_MTE, 0,                     "SYNC+ASYNC"  },
112	{ PR_MTE_TCF_SYNC | PR_MTE_STORE_ONLY,                    HWCAP2_MTE, HWCAP3_MTE_STORE_ONLY, "SYNC+STONLY" },
113	{ PR_MTE_TCF_ASYNC | PR_MTE_STORE_ONLY,                   HWCAP2_MTE, HWCAP3_MTE_STORE_ONLY, "ASYNC+STONLY" },
114	{ PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC | PR_MTE_STORE_ONLY, HWCAP2_MTE, HWCAP3_MTE_STORE_ONLY, "SYNC+ASYNC+STONLY" },
115};
116
117int main(void)
118{
119	int i;
120
121	ksft_print_header();
122	ksft_set_plan(ARRAY_SIZE(mte_modes));
123
124	check_basic_read();
125	for (i = 0; i < ARRAY_SIZE(mte_modes); i++)
126		set_mode_test(mte_modes[i].name, mte_modes[i].hwcap2, mte_modes[i].hwcap3,
127			      mte_modes[i].mask);
128
129	ksft_print_cnts();
130
131	return 0;
132}
~/ Read-only file preview.