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_packet.h" 30 #include "pt_opcodes.h" 31 32 #include "intel-pt.h" 33 34 #include <limits.h> 35 36 37 static uint64_t pt_pkt_read_value(const uint8_t *pos, int size) 38 { 39 uint64_t val; 40 int idx; 41 42 for (val = 0, idx = 0; idx < size; ++idx) { 43 uint64_t byte = *pos++; 44 45 byte <<= (idx * 8); 46 val |= byte; 47 } 48 49 return val; 50 } 51 52 int pt_pkt_read_unknown(struct pt_packet *packet, const uint8_t *pos, 53 const struct pt_config *config) 54 { 55 int (*decode)(struct pt_packet_unknown *, const struct pt_config *, 56 const uint8_t *, void *); 57 int size; 58 59 if (!packet || !pos || !config) 60 return -pte_internal; 61 62 decode = config->decode.callback; 63 if (!decode) 64 return -pte_bad_opc; 65 66 /* Fill in some default values. */ 67 packet->payload.unknown.packet = pos; 68 packet->payload.unknown.priv = NULL; 69 70 /* We accept a size of zero to allow the callback to modify the 71 * trace buffer and resume normal decoding. 72 */ 73 size = (*decode)(&packet->payload.unknown, config, pos, 74 config->decode.context); 75 if (size < 0) 76 return size; 77 78 if (size > UCHAR_MAX) 79 return -pte_invalid; 80 81 packet->type = ppt_unknown; 82 packet->size = (uint8_t) size; 83 84 if (config->end < pos + size) 85 return -pte_eos; 86 87 return size; 88 } 89 90 int pt_pkt_read_psb(const uint8_t *pos, const struct pt_config *config) 91 { 92 int count; 93 94 if (!pos || !config) 95 return -pte_internal; 96 97 if (config->end < pos + ptps_psb) 98 return -pte_eos; 99 100 pos += pt_opcs_psb; 101 102 for (count = 0; count < pt_psb_repeat_count; ++count) { 103 if (*pos++ != pt_psb_hi) 104 return -pte_bad_packet; 105 if (*pos++ != pt_psb_lo) 106 return -pte_bad_packet; 107 } 108 109 return ptps_psb; 110 } 111 112 static int pt_pkt_ip_size(enum pt_ip_compression ipc) 113 { 114 switch (ipc) { 115 case pt_ipc_suppressed: 116 return 0; 117 118 case pt_ipc_update_16: 119 return 2; 120 121 case pt_ipc_update_32: 122 return 4; 123 124 case pt_ipc_update_48: 125 case pt_ipc_sext_48: 126 return 6; 127 128 case pt_ipc_full: 129 return 8; 130 } 131 132 return -pte_bad_packet; 133 } 134 135 int pt_pkt_read_ip(struct pt_packet_ip *packet, const uint8_t *pos, 136 const struct pt_config *config) 137 { 138 uint64_t ip; 139 uint8_t ipc; 140 int ipsize; 141 142 if (!packet || !pos || !config) 143 return -pte_internal; 144 145 ipc = (*pos++ >> pt_opm_ipc_shr) & pt_opm_ipc_shr_mask; 146 147 ip = 0ull; 148 ipsize = pt_pkt_ip_size((enum pt_ip_compression) ipc); 149 if (ipsize < 0) 150 return ipsize; 151 152 if (config->end < pos + ipsize) 153 return -pte_eos; 154 155 if (ipsize) 156 ip = pt_pkt_read_value(pos, ipsize); 157 158 packet->ipc = (enum pt_ip_compression) ipc; 159 packet->ip = ip; 160 161 return ipsize + 1; 162 } 163 164 static uint8_t pt_pkt_tnt_bit_size(uint64_t payload) 165 { 166 uint8_t size; 167 168 /* The payload bit-size is the bit-index of the payload's stop-bit, 169 * which itself is not part of the payload proper. 170 */ 171 for (size = 0; ; size += 1) { 172 payload >>= 1; 173 if (!payload) 174 break; 175 } 176 177 return size; 178 } 179 180 static int pt_pkt_read_tnt(struct pt_packet_tnt *packet, uint64_t payload) 181 { 182 uint8_t bit_size; 183 184 if (!packet) 185 return -pte_internal; 186 187 bit_size = pt_pkt_tnt_bit_size(payload); 188 if (!bit_size) 189 return -pte_bad_packet; 190 191 /* Remove the stop bit from the payload. */ 192 payload &= ~(1ull << bit_size); 193 194 packet->payload = payload; 195 packet->bit_size = bit_size; 196 197 return 0; 198 } 199 200 int pt_pkt_read_tnt_8(struct pt_packet_tnt *packet, const uint8_t *pos, 201 const struct pt_config *config) 202 { 203 int errcode; 204 205 (void) config; 206 207 if (!pos) 208 return -pte_internal; 209 210 errcode = pt_pkt_read_tnt(packet, pos[0] >> pt_opm_tnt_8_shr); 211 if (errcode < 0) 212 return errcode; 213 214 return ptps_tnt_8; 215 } 216 217 int pt_pkt_read_tnt_64(struct pt_packet_tnt *packet, const uint8_t *pos, 218 const struct pt_config *config) 219 { 220 uint64_t payload; 221 int errcode; 222 223 if (!pos || !config) 224 return -pte_internal; 225 226 if (config->end < pos + ptps_tnt_64) 227 return -pte_eos; 228 229 payload = pt_pkt_read_value(pos + pt_opcs_tnt_64, pt_pl_tnt_64_size); 230 231 errcode = pt_pkt_read_tnt(packet, payload); 232 if (errcode < 0) 233 return errcode; 234 235 return ptps_tnt_64; 236 } 237 238 int pt_pkt_read_pip(struct pt_packet_pip *packet, const uint8_t *pos, 239 const struct pt_config *config) 240 { 241 uint64_t payload; 242 243 if (!packet || !pos || !config) 244 return -pte_internal; 245 246 if (config->end < pos + ptps_pip) 247 return -pte_eos; 248 249 /* Read the payload. */ 250 payload = pt_pkt_read_value(pos + pt_opcs_pip, pt_pl_pip_size); 251 252 /* Extract the non-root information from the payload. */ 253 packet->nr = payload & pt_pl_pip_nr; 254 255 /* Create the cr3 value. */ 256 payload >>= pt_pl_pip_shr; 257 payload <<= pt_pl_pip_shl; 258 packet->cr3 = payload; 259 260 return ptps_pip; 261 } 262 263 static int pt_pkt_read_mode_exec(struct pt_packet_mode_exec *packet, 264 uint8_t mode) 265 { 266 if (!packet) 267 return -pte_internal; 268 269 packet->csl = (mode & pt_mob_exec_csl) != 0; 270 packet->csd = (mode & pt_mob_exec_csd) != 0; 271 272 return ptps_mode; 273 } 274 275 static int pt_pkt_read_mode_tsx(struct pt_packet_mode_tsx *packet, 276 uint8_t mode) 277 { 278 if (!packet) 279 return -pte_internal; 280 281 packet->intx = (mode & pt_mob_tsx_intx) != 0; 282 packet->abrt = (mode & pt_mob_tsx_abrt) != 0; 283 284 return ptps_mode; 285 } 286 287 int pt_pkt_read_mode(struct pt_packet_mode *packet, const uint8_t *pos, 288 const struct pt_config *config) 289 { 290 uint8_t payload, mode, leaf; 291 292 if (!packet || !pos || !config) 293 return -pte_internal; 294 295 if (config->end < pos + ptps_mode) 296 return -pte_eos; 297 298 payload = pos[pt_opcs_mode]; 299 leaf = payload & pt_mom_leaf; 300 mode = payload & pt_mom_bits; 301 302 packet->leaf = (enum pt_mode_leaf) leaf; 303 switch (leaf) { 304 default: 305 return -pte_bad_packet; 306 307 case pt_mol_exec: 308 return pt_pkt_read_mode_exec(&packet->bits.exec, mode); 309 310 case pt_mol_tsx: 311 return pt_pkt_read_mode_tsx(&packet->bits.tsx, mode); 312 } 313 } 314 315 int pt_pkt_read_tsc(struct pt_packet_tsc *packet, const uint8_t *pos, 316 const struct pt_config *config) 317 { 318 if (!packet || !pos || !config) 319 return -pte_internal; 320 321 if (config->end < pos + ptps_tsc) 322 return -pte_eos; 323 324 packet->tsc = pt_pkt_read_value(pos + pt_opcs_tsc, pt_pl_tsc_size); 325 326 return ptps_tsc; 327 } 328 329 int pt_pkt_read_cbr(struct pt_packet_cbr *packet, const uint8_t *pos, 330 const struct pt_config *config) 331 { 332 if (!packet || !pos || !config) 333 return -pte_internal; 334 335 if (config->end < pos + ptps_cbr) 336 return -pte_eos; 337 338 packet->ratio = pos[2]; 339 340 return ptps_cbr; 341 } 342 343 int pt_pkt_read_tma(struct pt_packet_tma *packet, const uint8_t *pos, 344 const struct pt_config *config) 345 { 346 uint16_t ctc, fc; 347 348 if (!packet || !pos || !config) 349 return -pte_internal; 350 351 if (config->end < pos + ptps_tma) 352 return -pte_eos; 353 354 ctc = pos[pt_pl_tma_ctc_0]; 355 ctc |= pos[pt_pl_tma_ctc_1] << 8; 356 357 fc = pos[pt_pl_tma_fc_0]; 358 fc |= pos[pt_pl_tma_fc_1] << 8; 359 360 if (fc & ~pt_pl_tma_fc_mask) 361 return -pte_bad_packet; 362 363 packet->ctc = ctc; 364 packet->fc = fc; 365 366 return ptps_tma; 367 } 368 369 int pt_pkt_read_mtc(struct pt_packet_mtc *packet, const uint8_t *pos, 370 const struct pt_config *config) 371 { 372 if (!packet || !pos || !config) 373 return -pte_internal; 374 375 if (config->end < pos + ptps_mtc) 376 return -pte_eos; 377 378 packet->ctc = pos[pt_opcs_mtc]; 379 380 return ptps_mtc; 381 } 382 383 int pt_pkt_read_cyc(struct pt_packet_cyc *packet, const uint8_t *pos, 384 const struct pt_config *config) 385 { 386 const uint8_t *begin, *end; 387 uint64_t value; 388 uint8_t cyc, ext, shl; 389 390 if (!packet || !pos || !config) 391 return -pte_internal; 392 393 begin = pos; 394 end = config->end; 395 396 /* The first byte contains the opcode and part of the payload. 397 * We already checked that this first byte is within bounds. 398 */ 399 cyc = *pos++; 400 401 ext = cyc & pt_opm_cyc_ext; 402 cyc >>= pt_opm_cyc_shr; 403 404 value = cyc; 405 shl = (8 - pt_opm_cyc_shr); 406 407 while (ext) { 408 uint64_t bits; 409 410 if (end <= pos) 411 return -pte_eos; 412 413 bits = *pos++; 414 ext = bits & pt_opm_cycx_ext; 415 416 bits >>= pt_opm_cycx_shr; 417 bits <<= shl; 418 419 shl += (8 - pt_opm_cycx_shr); 420 if (sizeof(value) * 8 < shl) 421 return -pte_bad_packet; 422 423 value |= bits; 424 } 425 426 packet->value = value; 427 428 return (int) (pos - begin); 429 } 430 431 int pt_pkt_read_vmcs(struct pt_packet_vmcs *packet, const uint8_t *pos, 432 const struct pt_config *config) 433 { 434 uint64_t payload; 435 436 if (!packet || !pos || !config) 437 return -pte_internal; 438 439 if (config->end < pos + ptps_vmcs) 440 return -pte_eos; 441 442 payload = pt_pkt_read_value(pos + pt_opcs_vmcs, pt_pl_vmcs_size); 443 444 packet->base = payload << pt_pl_vmcs_shl; 445 446 return ptps_vmcs; 447 } 448 449 int pt_pkt_read_mnt(struct pt_packet_mnt *packet, const uint8_t *pos, 450 const struct pt_config *config) 451 { 452 if (!packet || !pos || !config) 453 return -pte_internal; 454 455 if (config->end < pos + ptps_mnt) 456 return -pte_eos; 457 458 packet->payload = pt_pkt_read_value(pos + pt_opcs_mnt, pt_pl_mnt_size); 459 460 return ptps_mnt; 461 } 462 463 int pt_pkt_read_exstop(struct pt_packet_exstop *packet, const uint8_t *pos, 464 const struct pt_config *config) 465 { 466 if (!packet || !pos || !config) 467 return -pte_internal; 468 469 if (config->end < pos + ptps_exstop) 470 return -pte_eos; 471 472 packet->ip = pos[1] & pt_pl_exstop_ip_mask ? 1 : 0; 473 474 return ptps_exstop; 475 } 476 477 int pt_pkt_read_mwait(struct pt_packet_mwait *packet, const uint8_t *pos, 478 const struct pt_config *config) 479 { 480 if (!packet || !pos || !config) 481 return -pte_internal; 482 483 if (config->end < pos + ptps_mwait) 484 return -pte_eos; 485 486 packet->hints = (uint32_t) pt_pkt_read_value(pos + pt_opcs_mwait, 487 pt_pl_mwait_hints_size); 488 packet->ext = (uint32_t) pt_pkt_read_value(pos + pt_opcs_mwait + 489 pt_pl_mwait_hints_size, 490 pt_pl_mwait_ext_size); 491 return ptps_mwait; 492 } 493 494 int pt_pkt_read_pwre(struct pt_packet_pwre *packet, const uint8_t *pos, 495 const struct pt_config *config) 496 { 497 uint64_t payload; 498 499 if (!packet || !pos || !config) 500 return -pte_internal; 501 502 if (config->end < pos + ptps_pwre) 503 return -pte_eos; 504 505 payload = pt_pkt_read_value(pos + pt_opcs_pwre, pt_pl_pwre_size); 506 507 memset(packet, 0, sizeof(*packet)); 508 packet->state = (uint8_t) ((payload & pt_pl_pwre_state_mask) >> 509 pt_pl_pwre_state_shr); 510 packet->sub_state = (uint8_t) ((payload & pt_pl_pwre_sub_state_mask) >> 511 pt_pl_pwre_sub_state_shr); 512 if (payload & pt_pl_pwre_hw_mask) 513 packet->hw = 1; 514 515 return ptps_pwre; 516 } 517 518 int pt_pkt_read_pwrx(struct pt_packet_pwrx *packet, const uint8_t *pos, 519 const struct pt_config *config) 520 { 521 uint64_t payload; 522 523 if (!packet || !pos || !config) 524 return -pte_internal; 525 526 if (config->end < pos + ptps_pwrx) 527 return -pte_eos; 528 529 payload = pt_pkt_read_value(pos + pt_opcs_pwrx, pt_pl_pwrx_size); 530 531 memset(packet, 0, sizeof(*packet)); 532 packet->last = (uint8_t) ((payload & pt_pl_pwrx_last_mask) >> 533 pt_pl_pwrx_last_shr); 534 packet->deepest = (uint8_t) ((payload & pt_pl_pwrx_deepest_mask) >> 535 pt_pl_pwrx_deepest_shr); 536 if (payload & pt_pl_pwrx_wr_int) 537 packet->interrupt = 1; 538 if (payload & pt_pl_pwrx_wr_store) 539 packet->store = 1; 540 if (payload & pt_pl_pwrx_wr_hw) 541 packet->autonomous = 1; 542 543 return ptps_pwrx; 544 } 545 546 int pt_pkt_read_ptw(struct pt_packet_ptw *packet, const uint8_t *pos, 547 const struct pt_config *config) 548 { 549 uint8_t opc, plc; 550 int size; 551 552 if (!packet || !pos || !config) 553 return -pte_internal; 554 555 /* Skip the ext opcode. */ 556 pos++; 557 558 opc = *pos++; 559 plc = (opc >> pt_opm_ptw_pb_shr) & pt_opm_ptw_pb_shr_mask; 560 561 size = pt_ptw_size(plc); 562 if (size < 0) 563 return size; 564 565 if (config->end < pos + size) 566 return -pte_eos; 567 568 packet->payload = pt_pkt_read_value(pos, size); 569 packet->plc = plc; 570 packet->ip = opc & pt_opm_ptw_ip ? 1 : 0; 571 572 return pt_opcs_ptw + size; 573 } 574