| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- // SPDX-License-Identifier: GPL-2.0
- // Copyright (C) 2022 ARM Limited
- #include <stdbool.h>
- #include <stdio.h>
- #include <string.h>
- #include <sys/auxv.h>
- #include <sys/prctl.h>
- #include <asm/hwcap.h>
- #include "kselftest.h"
- #ifndef AT_HWCAP3
- #define AT_HWCAP3 29
- #endif
- static int set_tagged_addr_ctrl(int val)
- {
- int ret;
- ret = prctl(PR_SET_TAGGED_ADDR_CTRL, val, 0, 0, 0);
- if (ret < 0)
- ksft_print_msg("PR_SET_TAGGED_ADDR_CTRL: failed %d %d (%s)\n",
- ret, errno, strerror(errno));
- return ret;
- }
- static int get_tagged_addr_ctrl(void)
- {
- int ret;
- ret = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
- if (ret < 0)
- ksft_print_msg("PR_GET_TAGGED_ADDR_CTRL failed: %d %d (%s)\n",
- ret, errno, strerror(errno));
- return ret;
- }
- /*
- * Read the current mode without having done any configuration, should
- * run first.
- */
- void check_basic_read(void)
- {
- int ret;
- ret = get_tagged_addr_ctrl();
- if (ret < 0) {
- ksft_test_result_fail("check_basic_read\n");
- return;
- }
- if (ret & PR_MTE_TCF_SYNC)
- ksft_print_msg("SYNC enabled\n");
- if (ret & PR_MTE_TCF_ASYNC)
- ksft_print_msg("ASYNC enabled\n");
- /* Any configuration is valid */
- ksft_test_result_pass("check_basic_read\n");
- }
- /*
- * Attempt to set a specified combination of modes.
- */
- void set_mode_test(const char *name, int hwcap2, int hwcap3, int mask)
- {
- int ret;
- if ((getauxval(AT_HWCAP2) & hwcap2) != hwcap2) {
- ksft_test_result_skip("%s\n", name);
- return;
- }
- if ((getauxval(AT_HWCAP3) & hwcap3) != hwcap3) {
- ksft_test_result_skip("%s\n", name);
- return;
- }
- ret = set_tagged_addr_ctrl(mask);
- if (ret < 0) {
- ksft_test_result_fail("%s\n", name);
- return;
- }
- ret = get_tagged_addr_ctrl();
- if (ret < 0) {
- ksft_test_result_fail("%s\n", name);
- return;
- }
- if ((ret & (PR_MTE_TCF_MASK | PR_MTE_STORE_ONLY)) == mask) {
- ksft_test_result_pass("%s\n", name);
- } else {
- ksft_print_msg("Got %x, expected %x\n",
- (ret & (int)PR_MTE_TCF_MASK), mask);
- ksft_test_result_fail("%s\n", name);
- }
- }
- struct mte_mode {
- int mask;
- int hwcap2;
- int hwcap3;
- const char *name;
- } mte_modes[] = {
- { PR_MTE_TCF_NONE, 0, 0, "NONE" },
- { PR_MTE_TCF_SYNC, HWCAP2_MTE, 0, "SYNC" },
- { PR_MTE_TCF_ASYNC, HWCAP2_MTE, 0, "ASYNC" },
- { PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC, HWCAP2_MTE, 0, "SYNC+ASYNC" },
- { PR_MTE_TCF_SYNC | PR_MTE_STORE_ONLY, HWCAP2_MTE, HWCAP3_MTE_STORE_ONLY, "SYNC+STONLY" },
- { PR_MTE_TCF_ASYNC | PR_MTE_STORE_ONLY, HWCAP2_MTE, HWCAP3_MTE_STORE_ONLY, "ASYNC+STONLY" },
- { PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC | PR_MTE_STORE_ONLY, HWCAP2_MTE, HWCAP3_MTE_STORE_ONLY, "SYNC+ASYNC+STONLY" },
- };
- int main(void)
- {
- int i;
- ksft_print_header();
- ksft_set_plan(ARRAY_SIZE(mte_modes));
- check_basic_read();
- for (i = 0; i < ARRAY_SIZE(mte_modes); i++)
- set_mode_test(mte_modes[i].name, mte_modes[i].hwcap2, mte_modes[i].hwcap3,
- mte_modes[i].mask);
- ksft_print_cnts();
- return 0;
- }
|