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_last_ip.h" 30 31 #include "intel-pt.h" 32 33 34 void pt_last_ip_init(struct pt_last_ip *last_ip) 35 { 36 if (!last_ip) 37 return; 38 39 last_ip->ip = 0ull; 40 last_ip->have_ip = 0; 41 last_ip->suppressed = 0; 42 } 43 44 int pt_last_ip_query(uint64_t *ip, const struct pt_last_ip *last_ip) 45 { 46 if (!last_ip) 47 return -pte_internal; 48 49 if (!last_ip->have_ip) { 50 if (ip) 51 *ip = 0ull; 52 return -pte_noip; 53 } 54 55 if (last_ip->suppressed) { 56 if (ip) 57 *ip = 0ull; 58 return -pte_ip_suppressed; 59 } 60 61 if (ip) 62 *ip = last_ip->ip; 63 64 return 0; 65 } 66 67 /* Sign-extend a uint64_t value. */ 68 static uint64_t sext(uint64_t val, uint8_t sign) 69 { 70 uint64_t signbit, mask; 71 72 signbit = 1ull << (sign - 1); 73 mask = ~0ull << sign; 74 75 return val & signbit ? val | mask : val & ~mask; 76 } 77 78 int pt_last_ip_update_ip(struct pt_last_ip *last_ip, 79 const struct pt_packet_ip *packet, 80 const struct pt_config *config) 81 { 82 (void) config; 83 84 if (!last_ip || !packet) 85 return -pte_internal; 86 87 switch (packet->ipc) { 88 case pt_ipc_suppressed: 89 last_ip->suppressed = 1; 90 return 0; 91 92 case pt_ipc_sext_48: 93 last_ip->ip = sext(packet->ip, 48); 94 last_ip->have_ip = 1; 95 last_ip->suppressed = 0; 96 return 0; 97 98 case pt_ipc_update_16: 99 last_ip->ip = (last_ip->ip & ~0xffffull) 100 | (packet->ip & 0xffffull); 101 last_ip->have_ip = 1; 102 last_ip->suppressed = 0; 103 return 0; 104 105 case pt_ipc_update_32: 106 last_ip->ip = (last_ip->ip & ~0xffffffffull) 107 | (packet->ip & 0xffffffffull); 108 last_ip->have_ip = 1; 109 last_ip->suppressed = 0; 110 return 0; 111 112 case pt_ipc_update_48: 113 last_ip->ip = (last_ip->ip & ~0xffffffffffffull) 114 | (packet->ip & 0xffffffffffffull); 115 last_ip->have_ip = 1; 116 last_ip->suppressed = 0; 117 return 0; 118 119 case pt_ipc_full: 120 last_ip->ip = packet->ip; 121 last_ip->have_ip = 1; 122 last_ip->suppressed = 0; 123 return 0; 124 } 125 126 return -pte_bad_packet; 127 } 128