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