1 /* 2 * Copyright (c) 2013-2019, Intel Corporation 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * * Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright notice, 10 * this list of conditions and the following disclaimer in the documentation 11 * and/or other materials provided with the distribution. 12 * * Neither the name of Intel Corporation nor the names of its contributors 13 * may be used to endorse or promote products derived from this software 14 * without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "pt_decoder_function.h" 30 #include "pt_packet_decoder.h" 31 #include "pt_query_decoder.h" 32 #include "pt_opcodes.h" 33 34 #include "intel-pt.h" 35 36 37 const struct pt_decoder_function pt_decode_unknown = { 38 /* .packet = */ pt_pkt_decode_unknown, 39 /* .decode = */ pt_qry_decode_unknown, 40 /* .header = */ pt_qry_decode_unknown, 41 /* .flags = */ pdff_unknown 42 }; 43 44 const struct pt_decoder_function pt_decode_pad = { 45 /* .packet = */ pt_pkt_decode_pad, 46 /* .decode = */ pt_qry_decode_pad, 47 /* .header = */ pt_qry_decode_pad, 48 /* .flags = */ pdff_pad 49 }; 50 51 const struct pt_decoder_function pt_decode_psb = { 52 /* .packet = */ pt_pkt_decode_psb, 53 /* .decode = */ pt_qry_decode_psb, 54 /* .header = */ NULL, 55 /* .flags = */ 0 56 }; 57 58 const struct pt_decoder_function pt_decode_tip = { 59 /* .packet = */ pt_pkt_decode_tip, 60 /* .decode = */ pt_qry_decode_tip, 61 /* .header = */ NULL, 62 /* .flags = */ pdff_tip 63 }; 64 65 const struct pt_decoder_function pt_decode_tnt_8 = { 66 /* .packet = */ pt_pkt_decode_tnt_8, 67 /* .decode = */ pt_qry_decode_tnt_8, 68 /* .header = */ NULL, 69 /* .flags = */ pdff_tnt 70 }; 71 72 const struct pt_decoder_function pt_decode_tnt_64 = { 73 /* .packet = */ pt_pkt_decode_tnt_64, 74 /* .decode = */ pt_qry_decode_tnt_64, 75 /* .header = */ NULL, 76 /* .flags = */ pdff_tnt 77 }; 78 79 const struct pt_decoder_function pt_decode_tip_pge = { 80 /* .packet = */ pt_pkt_decode_tip_pge, 81 /* .decode = */ pt_qry_decode_tip_pge, 82 /* .header = */ NULL, 83 /* .flags = */ pdff_event 84 }; 85 86 const struct pt_decoder_function pt_decode_tip_pgd = { 87 /* .packet = */ pt_pkt_decode_tip_pgd, 88 /* .decode = */ pt_qry_decode_tip_pgd, 89 /* .header = */ NULL, 90 /* .flags = */ pdff_event 91 }; 92 93 const struct pt_decoder_function pt_decode_fup = { 94 /* .packet = */ pt_pkt_decode_fup, 95 /* .decode = */ pt_qry_decode_fup, 96 /* .header = */ pt_qry_header_fup, 97 /* .flags = */ pdff_fup 98 }; 99 100 const struct pt_decoder_function pt_decode_pip = { 101 /* .packet = */ pt_pkt_decode_pip, 102 /* .decode = */ pt_qry_decode_pip, 103 /* .header = */ pt_qry_header_pip, 104 /* .flags = */ pdff_event 105 }; 106 107 const struct pt_decoder_function pt_decode_ovf = { 108 /* .packet = */ pt_pkt_decode_ovf, 109 /* .decode = */ pt_qry_decode_ovf, 110 /* .header = */ NULL, 111 /* .flags = */ pdff_psbend | pdff_event 112 }; 113 114 const struct pt_decoder_function pt_decode_mode = { 115 /* .packet = */ pt_pkt_decode_mode, 116 /* .decode = */ pt_qry_decode_mode, 117 /* .header = */ pt_qry_header_mode, 118 /* .flags = */ pdff_event 119 }; 120 121 const struct pt_decoder_function pt_decode_psbend = { 122 /* .packet = */ pt_pkt_decode_psbend, 123 /* .decode = */ pt_qry_decode_psbend, 124 /* .header = */ NULL, 125 /* .flags = */ pdff_psbend 126 }; 127 128 const struct pt_decoder_function pt_decode_tsc = { 129 /* .packet = */ pt_pkt_decode_tsc, 130 /* .decode = */ pt_qry_decode_tsc, 131 /* .header = */ pt_qry_header_tsc, 132 /* .flags = */ pdff_timing 133 }; 134 135 const struct pt_decoder_function pt_decode_cbr = { 136 /* .packet = */ pt_pkt_decode_cbr, 137 /* .decode = */ pt_qry_decode_cbr, 138 /* .header = */ pt_qry_header_cbr, 139 /* .flags = */ pdff_timing | pdff_event 140 }; 141 142 const struct pt_decoder_function pt_decode_tma = { 143 /* .packet = */ pt_pkt_decode_tma, 144 /* .decode = */ pt_qry_decode_tma, 145 /* .header = */ pt_qry_decode_tma, 146 /* .flags = */ pdff_timing 147 }; 148 149 const struct pt_decoder_function pt_decode_mtc = { 150 /* .packet = */ pt_pkt_decode_mtc, 151 /* .decode = */ pt_qry_decode_mtc, 152 /* .header = */ pt_qry_decode_mtc, 153 /* .flags = */ pdff_timing 154 }; 155 156 const struct pt_decoder_function pt_decode_cyc = { 157 /* .packet = */ pt_pkt_decode_cyc, 158 /* .decode = */ pt_qry_decode_cyc, 159 /* .header = */ pt_qry_decode_cyc, 160 /* .flags = */ pdff_timing 161 }; 162 163 const struct pt_decoder_function pt_decode_stop = { 164 /* .packet = */ pt_pkt_decode_stop, 165 /* .decode = */ pt_qry_decode_stop, 166 /* .header = */ NULL, 167 /* .flags = */ pdff_event 168 }; 169 170 const struct pt_decoder_function pt_decode_vmcs = { 171 /* .packet = */ pt_pkt_decode_vmcs, 172 /* .decode = */ pt_qry_decode_vmcs, 173 /* .header = */ pt_qry_header_vmcs, 174 /* .flags = */ pdff_event 175 }; 176 177 const struct pt_decoder_function pt_decode_mnt = { 178 /* .packet = */ pt_pkt_decode_mnt, 179 /* .decode = */ pt_qry_decode_mnt, 180 /* .header = */ pt_qry_header_mnt, 181 /* .flags = */ pdff_event 182 }; 183 184 const struct pt_decoder_function pt_decode_exstop = { 185 /* .packet = */ pt_pkt_decode_exstop, 186 /* .decode = */ pt_qry_decode_exstop, 187 /* .header = */ NULL, 188 /* .flags = */ pdff_event 189 }; 190 191 const struct pt_decoder_function pt_decode_mwait = { 192 /* .packet = */ pt_pkt_decode_mwait, 193 /* .decode = */ pt_qry_decode_mwait, 194 /* .header = */ NULL, 195 /* .flags = */ pdff_event 196 }; 197 198 const struct pt_decoder_function pt_decode_pwre = { 199 /* .packet = */ pt_pkt_decode_pwre, 200 /* .decode = */ pt_qry_decode_pwre, 201 /* .header = */ NULL, 202 /* .flags = */ pdff_event 203 }; 204 205 const struct pt_decoder_function pt_decode_pwrx = { 206 /* .packet = */ pt_pkt_decode_pwrx, 207 /* .decode = */ pt_qry_decode_pwrx, 208 /* .header = */ NULL, 209 /* .flags = */ pdff_event 210 }; 211 212 const struct pt_decoder_function pt_decode_ptw = { 213 /* .packet = */ pt_pkt_decode_ptw, 214 /* .decode = */ pt_qry_decode_ptw, 215 /* .header = */ NULL, 216 /* .flags = */ pdff_event 217 }; 218 219 220 int pt_df_fetch(const struct pt_decoder_function **dfun, const uint8_t *pos, 221 const struct pt_config *config) 222 { 223 const uint8_t *begin, *end; 224 uint8_t opc, ext, ext2; 225 226 if (!dfun || !config) 227 return -pte_internal; 228 229 /* Clear the decode function in case of errors. */ 230 *dfun = NULL; 231 232 begin = config->begin; 233 end = config->end; 234 235 if (!pos || (pos < begin) || (end < pos)) 236 return -pte_nosync; 237 238 if (pos == end) 239 return -pte_eos; 240 241 opc = *pos++; 242 switch (opc) { 243 default: 244 /* Check opcodes that require masking. */ 245 if ((opc & pt_opm_tnt_8) == pt_opc_tnt_8) { 246 *dfun = &pt_decode_tnt_8; 247 return 0; 248 } 249 250 if ((opc & pt_opm_cyc) == pt_opc_cyc) { 251 *dfun = &pt_decode_cyc; 252 return 0; 253 } 254 255 if ((opc & pt_opm_tip) == pt_opc_tip) { 256 *dfun = &pt_decode_tip; 257 return 0; 258 } 259 260 if ((opc & pt_opm_fup) == pt_opc_fup) { 261 *dfun = &pt_decode_fup; 262 return 0; 263 } 264 265 if ((opc & pt_opm_tip) == pt_opc_tip_pge) { 266 *dfun = &pt_decode_tip_pge; 267 return 0; 268 } 269 270 if ((opc & pt_opm_tip) == pt_opc_tip_pgd) { 271 *dfun = &pt_decode_tip_pgd; 272 return 0; 273 } 274 275 *dfun = &pt_decode_unknown; 276 return 0; 277 278 case pt_opc_pad: 279 *dfun = &pt_decode_pad; 280 return 0; 281 282 case pt_opc_mode: 283 *dfun = &pt_decode_mode; 284 return 0; 285 286 case pt_opc_tsc: 287 *dfun = &pt_decode_tsc; 288 return 0; 289 290 case pt_opc_mtc: 291 *dfun = &pt_decode_mtc; 292 return 0; 293 294 case pt_opc_ext: 295 if (pos == end) 296 return -pte_eos; 297 298 ext = *pos++; 299 switch (ext) { 300 default: 301 /* Check opcodes that require masking. */ 302 if ((ext & pt_opm_ptw) == pt_ext_ptw) { 303 *dfun = &pt_decode_ptw; 304 return 0; 305 } 306 307 *dfun = &pt_decode_unknown; 308 return 0; 309 310 case pt_ext_psb: 311 *dfun = &pt_decode_psb; 312 return 0; 313 314 case pt_ext_ovf: 315 *dfun = &pt_decode_ovf; 316 return 0; 317 318 case pt_ext_tnt_64: 319 *dfun = &pt_decode_tnt_64; 320 return 0; 321 322 case pt_ext_psbend: 323 *dfun = &pt_decode_psbend; 324 return 0; 325 326 case pt_ext_cbr: 327 *dfun = &pt_decode_cbr; 328 return 0; 329 330 case pt_ext_pip: 331 *dfun = &pt_decode_pip; 332 return 0; 333 334 case pt_ext_tma: 335 *dfun = &pt_decode_tma; 336 return 0; 337 338 case pt_ext_stop: 339 *dfun = &pt_decode_stop; 340 return 0; 341 342 case pt_ext_vmcs: 343 *dfun = &pt_decode_vmcs; 344 return 0; 345 346 case pt_ext_exstop: 347 case pt_ext_exstop_ip: 348 *dfun = &pt_decode_exstop; 349 return 0; 350 351 case pt_ext_mwait: 352 *dfun = &pt_decode_mwait; 353 return 0; 354 355 case pt_ext_pwre: 356 *dfun = &pt_decode_pwre; 357 return 0; 358 359 case pt_ext_pwrx: 360 *dfun = &pt_decode_pwrx; 361 return 0; 362 363 case pt_ext_ext2: 364 if (pos == end) 365 return -pte_eos; 366 367 ext2 = *pos++; 368 switch (ext2) { 369 default: 370 *dfun = &pt_decode_unknown; 371 return 0; 372 373 case pt_ext2_mnt: 374 *dfun = &pt_decode_mnt; 375 return 0; 376 } 377 } 378 } 379 } 380