1
0

check_prctl.c 3.1 KB

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