~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/arch/x86/tests/insn-x86.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 #include <linux/types.h>
  3 #include <string.h>
  4 
  5 #include "debug.h"
  6 #include "tests/tests.h"
  7 #include "arch-tests.h"
  8 #include "../../../../arch/x86/include/asm/insn.h"
  9 
 10 #include "intel-pt-decoder/intel-pt-insn-decoder.h"
 11 
 12 struct test_data {
 13         u8 data[MAX_INSN_SIZE];
 14         int expected_length;
 15         int expected_rel;
 16         const char *expected_op_str;
 17         const char *expected_branch_str;
 18         const char *asm_rep;
 19 };
 20 
 21 const struct test_data test_data_32[] = {
 22 #include "insn-x86-dat-32.c"
 23         {{0x0f, 0x01, 0xee}, 3, 0, NULL, NULL, "0f 01 ee             \trdpkru"},
 24         {{0x0f, 0x01, 0xef}, 3, 0, NULL, NULL, "0f 01 ef             \twrpkru"},
 25         {{0}, 0, 0, NULL, NULL, NULL},
 26 };
 27 
 28 const struct test_data test_data_64[] = {
 29 #include "insn-x86-dat-64.c"
 30         {{0x0f, 0x01, 0xee}, 3, 0, NULL, NULL, "0f 01 ee             \trdpkru"},
 31         {{0x0f, 0x01, 0xef}, 3, 0, NULL, NULL, "0f 01 ef             \twrpkru"},
 32         {{0xf2, 0x0f, 0x01, 0xca}, 4, 0, "erets", "indirect", "f2 0f 01 ca  \terets"},
 33         {{0xf3, 0x0f, 0x01, 0xca}, 4, 0, "eretu", "indirect", "f3 0f 01 ca  \teretu"},
 34         {{0}, 0, 0, NULL, NULL, NULL},
 35 };
 36 
 37 static int get_op(const char *op_str)
 38 {
 39         struct val_data {
 40                 const char *name;
 41                 int val;
 42         } vals[] = {
 43                 {"other",   INTEL_PT_OP_OTHER},
 44                 {"call",    INTEL_PT_OP_CALL},
 45                 {"ret",     INTEL_PT_OP_RET},
 46                 {"jcc",     INTEL_PT_OP_JCC},
 47                 {"jmp",     INTEL_PT_OP_JMP},
 48                 {"loop",    INTEL_PT_OP_LOOP},
 49                 {"iret",    INTEL_PT_OP_IRET},
 50                 {"int",     INTEL_PT_OP_INT},
 51                 {"syscall", INTEL_PT_OP_SYSCALL},
 52                 {"sysret",  INTEL_PT_OP_SYSRET},
 53                 {"vmentry",  INTEL_PT_OP_VMENTRY},
 54                 {"erets",   INTEL_PT_OP_ERETS},
 55                 {"eretu",   INTEL_PT_OP_ERETU},
 56                 {NULL, 0},
 57         };
 58         struct val_data *val;
 59 
 60         if (!op_str || !strlen(op_str))
 61                 return 0;
 62 
 63         for (val = vals; val->name; val++) {
 64                 if (!strcmp(val->name, op_str))
 65                         return val->val;
 66         }
 67 
 68         pr_debug("Failed to get op\n");
 69 
 70         return -1;
 71 }
 72 
 73 static int get_branch(const char *branch_str)
 74 {
 75         struct val_data {
 76                 const char *name;
 77                 int val;
 78         } vals[] = {
 79                 {"no_branch",     INTEL_PT_BR_NO_BRANCH},
 80                 {"indirect",      INTEL_PT_BR_INDIRECT},
 81                 {"conditional",   INTEL_PT_BR_CONDITIONAL},
 82                 {"unconditional", INTEL_PT_BR_UNCONDITIONAL},
 83                 {NULL, 0},
 84         };
 85         struct val_data *val;
 86 
 87         if (!branch_str || !strlen(branch_str))
 88                 return 0;
 89 
 90         for (val = vals; val->name; val++) {
 91                 if (!strcmp(val->name, branch_str))
 92                         return val->val;
 93         }
 94 
 95         pr_debug("Failed to get branch\n");
 96 
 97         return -1;
 98 }
 99 
100 static int test_data_item(const struct test_data *dat, int x86_64)
101 {
102         struct intel_pt_insn intel_pt_insn;
103         int op, branch, ret;
104         struct insn insn;
105 
106         ret = insn_decode(&insn, dat->data, MAX_INSN_SIZE,
107                           x86_64 ? INSN_MODE_64 : INSN_MODE_32);
108         if (ret < 0) {
109                 pr_debug("Failed to decode: %s\n", dat->asm_rep);
110                 return -1;
111         }
112 
113         if (insn.length != dat->expected_length) {
114                 pr_debug("Failed to decode length (%d vs expected %d): %s\n",
115                          insn.length, dat->expected_length, dat->asm_rep);
116                 return -1;
117         }
118 
119         op = get_op(dat->expected_op_str);
120         branch = get_branch(dat->expected_branch_str);
121 
122         if (intel_pt_get_insn(dat->data, MAX_INSN_SIZE, x86_64, &intel_pt_insn)) {
123                 pr_debug("Intel PT failed to decode: %s\n", dat->asm_rep);
124                 return -1;
125         }
126 
127         if ((int)intel_pt_insn.op != op) {
128                 pr_debug("Failed to decode 'op' value (%d vs expected %d): %s\n",
129                          intel_pt_insn.op, op, dat->asm_rep);
130                 return -1;
131         }
132 
133         if ((int)intel_pt_insn.branch != branch) {
134                 pr_debug("Failed to decode 'branch' value (%d vs expected %d): %s\n",
135                          intel_pt_insn.branch, branch, dat->asm_rep);
136                 return -1;
137         }
138 
139         if (intel_pt_insn.rel != dat->expected_rel) {
140                 pr_debug("Failed to decode 'rel' value (%#x vs expected %#x): %s\n",
141                          intel_pt_insn.rel, dat->expected_rel, dat->asm_rep);
142                 return -1;
143         }
144 
145         pr_debug("Decoded ok: %s\n", dat->asm_rep);
146 
147         return 0;
148 }
149 
150 static int test_data_set(const struct test_data *dat_set, int x86_64)
151 {
152         const struct test_data *dat;
153         int ret = 0;
154 
155         for (dat = dat_set; dat->expected_length; dat++) {
156                 if (test_data_item(dat, x86_64))
157                         ret = -1;
158         }
159 
160         return ret;
161 }
162 
163 /**
164  * test__insn_x86 - test x86 instruction decoder - new instructions.
165  *
166  * This function implements a test that decodes a selection of instructions and
167  * checks the results.  The Intel PT function that further categorizes
168  * instructions (i.e. intel_pt_get_insn()) is also checked.
169  *
170  * The instructions are originally in insn-x86-dat-src.c which has been
171  * processed by scripts gen-insn-x86-dat.sh and gen-insn-x86-dat.awk to produce
172  * insn-x86-dat-32.c and insn-x86-dat-64.c which are included into this program.
173  * i.e. to add new instructions to the test, edit insn-x86-dat-src.c, run the
174  * gen-insn-x86-dat.sh script, make perf, and then run the test.
175  *
176  * If the test passes %0 is returned, otherwise %-1 is returned.  Use the
177  * verbose (-v) option to see all the instructions and whether or not they
178  * decoded successfully.
179  */
180 int test__insn_x86(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
181 {
182         int ret = 0;
183 
184         if (test_data_set(test_data_32, 0))
185                 ret = -1;
186 
187         if (test_data_set(test_data_64, 1))
188                 ret = -1;
189 
190         return ret;
191 }
192 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php