162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci#include <linux/compiler.h> 462306a36Sopenharmony_ci#include <linux/bits.h> 562306a36Sopenharmony_ci#include <string.h> 662306a36Sopenharmony_ci#include <cpuid.h> 762306a36Sopenharmony_ci#include <sched.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include "intel-pt-decoder/intel-pt-pkt-decoder.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "debug.h" 1262306a36Sopenharmony_ci#include "tests/tests.h" 1362306a36Sopenharmony_ci#include "arch-tests.h" 1462306a36Sopenharmony_ci#include "cpumap.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci/** 1762306a36Sopenharmony_ci * struct test_data - Test data. 1862306a36Sopenharmony_ci * @len: number of bytes to decode 1962306a36Sopenharmony_ci * @bytes: bytes to decode 2062306a36Sopenharmony_ci * @ctx: packet context to decode 2162306a36Sopenharmony_ci * @packet: expected packet 2262306a36Sopenharmony_ci * @new_ctx: expected new packet context 2362306a36Sopenharmony_ci * @ctx_unchanged: the packet context must not change 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_cistatic const struct test_data { 2662306a36Sopenharmony_ci int len; 2762306a36Sopenharmony_ci u8 bytes[INTEL_PT_PKT_MAX_SZ]; 2862306a36Sopenharmony_ci enum intel_pt_pkt_ctx ctx; 2962306a36Sopenharmony_ci struct intel_pt_pkt packet; 3062306a36Sopenharmony_ci enum intel_pt_pkt_ctx new_ctx; 3162306a36Sopenharmony_ci int ctx_unchanged; 3262306a36Sopenharmony_ci} data[] = { 3362306a36Sopenharmony_ci /* Padding Packet */ 3462306a36Sopenharmony_ci {1, {0}, 0, {INTEL_PT_PAD, 0, 0}, 0, 1 }, 3562306a36Sopenharmony_ci /* Short Taken/Not Taken Packet */ 3662306a36Sopenharmony_ci {1, {4}, 0, {INTEL_PT_TNT, 1, 0}, 0, 0 }, 3762306a36Sopenharmony_ci {1, {6}, 0, {INTEL_PT_TNT, 1, 0x20ULL << 58}, 0, 0 }, 3862306a36Sopenharmony_ci {1, {0x80}, 0, {INTEL_PT_TNT, 6, 0}, 0, 0 }, 3962306a36Sopenharmony_ci {1, {0xfe}, 0, {INTEL_PT_TNT, 6, 0x3fULL << 58}, 0, 0 }, 4062306a36Sopenharmony_ci /* Long Taken/Not Taken Packet */ 4162306a36Sopenharmony_ci {8, {0x02, 0xa3, 2}, 0, {INTEL_PT_TNT, 1, 0xa302ULL << 47}, 0, 0 }, 4262306a36Sopenharmony_ci {8, {0x02, 0xa3, 3}, 0, {INTEL_PT_TNT, 1, 0x1a302ULL << 47}, 0, 0 }, 4362306a36Sopenharmony_ci {8, {0x02, 0xa3, 0, 0, 0, 0, 0, 0x80}, 0, {INTEL_PT_TNT, 47, 0xa302ULL << 1}, 0, 0 }, 4462306a36Sopenharmony_ci {8, {0x02, 0xa3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0, {INTEL_PT_TNT, 47, 0xffffffffffffa302ULL << 1}, 0, 0 }, 4562306a36Sopenharmony_ci /* Target IP Packet */ 4662306a36Sopenharmony_ci {1, {0x0d}, 0, {INTEL_PT_TIP, 0, 0}, 0, 0 }, 4762306a36Sopenharmony_ci {3, {0x2d, 1, 2}, 0, {INTEL_PT_TIP, 1, 0x201}, 0, 0 }, 4862306a36Sopenharmony_ci {5, {0x4d, 1, 2, 3, 4}, 0, {INTEL_PT_TIP, 2, 0x4030201}, 0, 0 }, 4962306a36Sopenharmony_ci {7, {0x6d, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_TIP, 3, 0x60504030201}, 0, 0 }, 5062306a36Sopenharmony_ci {7, {0x8d, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_TIP, 4, 0x60504030201}, 0, 0 }, 5162306a36Sopenharmony_ci {9, {0xcd, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_TIP, 6, 0x807060504030201}, 0, 0 }, 5262306a36Sopenharmony_ci /* Packet Generation Enable */ 5362306a36Sopenharmony_ci {1, {0x11}, 0, {INTEL_PT_TIP_PGE, 0, 0}, 0, 0 }, 5462306a36Sopenharmony_ci {3, {0x31, 1, 2}, 0, {INTEL_PT_TIP_PGE, 1, 0x201}, 0, 0 }, 5562306a36Sopenharmony_ci {5, {0x51, 1, 2, 3, 4}, 0, {INTEL_PT_TIP_PGE, 2, 0x4030201}, 0, 0 }, 5662306a36Sopenharmony_ci {7, {0x71, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_TIP_PGE, 3, 0x60504030201}, 0, 0 }, 5762306a36Sopenharmony_ci {7, {0x91, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_TIP_PGE, 4, 0x60504030201}, 0, 0 }, 5862306a36Sopenharmony_ci {9, {0xd1, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_TIP_PGE, 6, 0x807060504030201}, 0, 0 }, 5962306a36Sopenharmony_ci /* Packet Generation Disable */ 6062306a36Sopenharmony_ci {1, {0x01}, 0, {INTEL_PT_TIP_PGD, 0, 0}, 0, 0 }, 6162306a36Sopenharmony_ci {3, {0x21, 1, 2}, 0, {INTEL_PT_TIP_PGD, 1, 0x201}, 0, 0 }, 6262306a36Sopenharmony_ci {5, {0x41, 1, 2, 3, 4}, 0, {INTEL_PT_TIP_PGD, 2, 0x4030201}, 0, 0 }, 6362306a36Sopenharmony_ci {7, {0x61, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_TIP_PGD, 3, 0x60504030201}, 0, 0 }, 6462306a36Sopenharmony_ci {7, {0x81, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_TIP_PGD, 4, 0x60504030201}, 0, 0 }, 6562306a36Sopenharmony_ci {9, {0xc1, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_TIP_PGD, 6, 0x807060504030201}, 0, 0 }, 6662306a36Sopenharmony_ci /* Flow Update Packet */ 6762306a36Sopenharmony_ci {1, {0x1d}, 0, {INTEL_PT_FUP, 0, 0}, 0, 0 }, 6862306a36Sopenharmony_ci {3, {0x3d, 1, 2}, 0, {INTEL_PT_FUP, 1, 0x201}, 0, 0 }, 6962306a36Sopenharmony_ci {5, {0x5d, 1, 2, 3, 4}, 0, {INTEL_PT_FUP, 2, 0x4030201}, 0, 0 }, 7062306a36Sopenharmony_ci {7, {0x7d, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_FUP, 3, 0x60504030201}, 0, 0 }, 7162306a36Sopenharmony_ci {7, {0x9d, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_FUP, 4, 0x60504030201}, 0, 0 }, 7262306a36Sopenharmony_ci {9, {0xdd, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_FUP, 6, 0x807060504030201}, 0, 0 }, 7362306a36Sopenharmony_ci /* Paging Information Packet */ 7462306a36Sopenharmony_ci {8, {0x02, 0x43, 2, 4, 6, 8, 10, 12}, 0, {INTEL_PT_PIP, 0, 0xC0A08060402}, 0, 0 }, 7562306a36Sopenharmony_ci {8, {0x02, 0x43, 3, 4, 6, 8, 10, 12}, 0, {INTEL_PT_PIP, 0, 0xC0A08060403}, 0, 0 }, 7662306a36Sopenharmony_ci /* Mode Exec Packet */ 7762306a36Sopenharmony_ci {2, {0x99, 0x00}, 0, {INTEL_PT_MODE_EXEC, 0, 16}, 0, 0 }, 7862306a36Sopenharmony_ci {2, {0x99, 0x01}, 0, {INTEL_PT_MODE_EXEC, 1, 64}, 0, 0 }, 7962306a36Sopenharmony_ci {2, {0x99, 0x02}, 0, {INTEL_PT_MODE_EXEC, 2, 32}, 0, 0 }, 8062306a36Sopenharmony_ci {2, {0x99, 0x04}, 0, {INTEL_PT_MODE_EXEC, 4, 16}, 0, 0 }, 8162306a36Sopenharmony_ci {2, {0x99, 0x05}, 0, {INTEL_PT_MODE_EXEC, 5, 64}, 0, 0 }, 8262306a36Sopenharmony_ci {2, {0x99, 0x06}, 0, {INTEL_PT_MODE_EXEC, 6, 32}, 0, 0 }, 8362306a36Sopenharmony_ci /* Mode TSX Packet */ 8462306a36Sopenharmony_ci {2, {0x99, 0x20}, 0, {INTEL_PT_MODE_TSX, 0, 0}, 0, 0 }, 8562306a36Sopenharmony_ci {2, {0x99, 0x21}, 0, {INTEL_PT_MODE_TSX, 0, 1}, 0, 0 }, 8662306a36Sopenharmony_ci {2, {0x99, 0x22}, 0, {INTEL_PT_MODE_TSX, 0, 2}, 0, 0 }, 8762306a36Sopenharmony_ci /* Trace Stop Packet */ 8862306a36Sopenharmony_ci {2, {0x02, 0x83}, 0, {INTEL_PT_TRACESTOP, 0, 0}, 0, 0 }, 8962306a36Sopenharmony_ci /* Core:Bus Ratio Packet */ 9062306a36Sopenharmony_ci {4, {0x02, 0x03, 0x12, 0}, 0, {INTEL_PT_CBR, 0, 0x12}, 0, 1 }, 9162306a36Sopenharmony_ci /* Timestamp Counter Packet */ 9262306a36Sopenharmony_ci {8, {0x19, 1, 2, 3, 4, 5, 6, 7}, 0, {INTEL_PT_TSC, 0, 0x7060504030201}, 0, 1 }, 9362306a36Sopenharmony_ci /* Mini Time Counter Packet */ 9462306a36Sopenharmony_ci {2, {0x59, 0x12}, 0, {INTEL_PT_MTC, 0, 0x12}, 0, 1 }, 9562306a36Sopenharmony_ci /* TSC / MTC Alignment Packet */ 9662306a36Sopenharmony_ci {7, {0x02, 0x73}, 0, {INTEL_PT_TMA, 0, 0}, 0, 1 }, 9762306a36Sopenharmony_ci {7, {0x02, 0x73, 1, 2}, 0, {INTEL_PT_TMA, 0, 0x201}, 0, 1 }, 9862306a36Sopenharmony_ci {7, {0x02, 0x73, 0, 0, 0, 0xff, 1}, 0, {INTEL_PT_TMA, 0x1ff, 0}, 0, 1 }, 9962306a36Sopenharmony_ci {7, {0x02, 0x73, 0x80, 0xc0, 0, 0xff, 1}, 0, {INTEL_PT_TMA, 0x1ff, 0xc080}, 0, 1 }, 10062306a36Sopenharmony_ci /* Cycle Count Packet */ 10162306a36Sopenharmony_ci {1, {0x03}, 0, {INTEL_PT_CYC, 0, 0}, 0, 1 }, 10262306a36Sopenharmony_ci {1, {0x0b}, 0, {INTEL_PT_CYC, 0, 1}, 0, 1 }, 10362306a36Sopenharmony_ci {1, {0xfb}, 0, {INTEL_PT_CYC, 0, 0x1f}, 0, 1 }, 10462306a36Sopenharmony_ci {2, {0x07, 2}, 0, {INTEL_PT_CYC, 0, 0x20}, 0, 1 }, 10562306a36Sopenharmony_ci {2, {0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0xfff}, 0, 1 }, 10662306a36Sopenharmony_ci {3, {0x07, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x1000}, 0, 1 }, 10762306a36Sopenharmony_ci {3, {0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0x7ffff}, 0, 1 }, 10862306a36Sopenharmony_ci {4, {0x07, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x80000}, 0, 1 }, 10962306a36Sopenharmony_ci {4, {0xff, 0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0x3ffffff}, 0, 1 }, 11062306a36Sopenharmony_ci {5, {0x07, 1, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x4000000}, 0, 1 }, 11162306a36Sopenharmony_ci {5, {0xff, 0xff, 0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0x1ffffffff}, 0, 1 }, 11262306a36Sopenharmony_ci {6, {0x07, 1, 1, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x200000000}, 0, 1 }, 11362306a36Sopenharmony_ci {6, {0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0xffffffffff}, 0, 1 }, 11462306a36Sopenharmony_ci {7, {0x07, 1, 1, 1, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x10000000000}, 0, 1 }, 11562306a36Sopenharmony_ci {7, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0x7fffffffffff}, 0, 1 }, 11662306a36Sopenharmony_ci {8, {0x07, 1, 1, 1, 1, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x800000000000}, 0, 1 }, 11762306a36Sopenharmony_ci {8, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0x3fffffffffffff}, 0, 1 }, 11862306a36Sopenharmony_ci {9, {0x07, 1, 1, 1, 1, 1, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x40000000000000}, 0, 1 }, 11962306a36Sopenharmony_ci {9, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0x1fffffffffffffff}, 0, 1 }, 12062306a36Sopenharmony_ci {10, {0x07, 1, 1, 1, 1, 1, 1, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x2000000000000000}, 0, 1 }, 12162306a36Sopenharmony_ci {10, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe}, 0, {INTEL_PT_CYC, 0, 0xffffffffffffffff}, 0, 1 }, 12262306a36Sopenharmony_ci /* Virtual-Machine Control Structure Packet */ 12362306a36Sopenharmony_ci {7, {0x02, 0xc8, 1, 2, 3, 4, 5}, 0, {INTEL_PT_VMCS, 5, 0x504030201}, 0, 0 }, 12462306a36Sopenharmony_ci /* Overflow Packet */ 12562306a36Sopenharmony_ci {2, {0x02, 0xf3}, 0, {INTEL_PT_OVF, 0, 0}, 0, 0 }, 12662306a36Sopenharmony_ci {2, {0x02, 0xf3}, INTEL_PT_BLK_4_CTX, {INTEL_PT_OVF, 0, 0}, 0, 0 }, 12762306a36Sopenharmony_ci {2, {0x02, 0xf3}, INTEL_PT_BLK_8_CTX, {INTEL_PT_OVF, 0, 0}, 0, 0 }, 12862306a36Sopenharmony_ci /* Packet Stream Boundary*/ 12962306a36Sopenharmony_ci {16, {0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82}, 0, {INTEL_PT_PSB, 0, 0}, 0, 0 }, 13062306a36Sopenharmony_ci {16, {0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82}, INTEL_PT_BLK_4_CTX, {INTEL_PT_PSB, 0, 0}, 0, 0 }, 13162306a36Sopenharmony_ci {16, {0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82}, INTEL_PT_BLK_8_CTX, {INTEL_PT_PSB, 0, 0}, 0, 0 }, 13262306a36Sopenharmony_ci /* PSB End Packet */ 13362306a36Sopenharmony_ci {2, {0x02, 0x23}, 0, {INTEL_PT_PSBEND, 0, 0}, 0, 0 }, 13462306a36Sopenharmony_ci /* Maintenance Packet */ 13562306a36Sopenharmony_ci {11, {0x02, 0xc3, 0x88, 1, 2, 3, 4, 5, 6, 7}, 0, {INTEL_PT_MNT, 0, 0x7060504030201}, 0, 1 }, 13662306a36Sopenharmony_ci /* Write Data to PT Packet */ 13762306a36Sopenharmony_ci {6, {0x02, 0x12, 1, 2, 3, 4}, 0, {INTEL_PT_PTWRITE, 0, 0x4030201}, 0, 0 }, 13862306a36Sopenharmony_ci {10, {0x02, 0x32, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_PTWRITE, 1, 0x807060504030201}, 0, 0 }, 13962306a36Sopenharmony_ci {6, {0x02, 0x92, 1, 2, 3, 4}, 0, {INTEL_PT_PTWRITE_IP, 0, 0x4030201}, 0, 0 }, 14062306a36Sopenharmony_ci {10, {0x02, 0xb2, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_PTWRITE_IP, 1, 0x807060504030201}, 0, 0 }, 14162306a36Sopenharmony_ci /* Execution Stop Packet */ 14262306a36Sopenharmony_ci {2, {0x02, 0x62}, 0, {INTEL_PT_EXSTOP, 0, 0}, 0, 1 }, 14362306a36Sopenharmony_ci {2, {0x02, 0xe2}, 0, {INTEL_PT_EXSTOP_IP, 0, 0}, 0, 1 }, 14462306a36Sopenharmony_ci /* Monitor Wait Packet */ 14562306a36Sopenharmony_ci {10, {0x02, 0xc2}, 0, {INTEL_PT_MWAIT, 0, 0}, 0, 0 }, 14662306a36Sopenharmony_ci {10, {0x02, 0xc2, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_MWAIT, 0, 0x807060504030201}, 0, 0 }, 14762306a36Sopenharmony_ci {10, {0x02, 0xc2, 0xff, 2, 3, 4, 7, 6, 7, 8}, 0, {INTEL_PT_MWAIT, 0, 0x8070607040302ff}, 0, 0 }, 14862306a36Sopenharmony_ci /* Power Entry Packet */ 14962306a36Sopenharmony_ci {4, {0x02, 0x22}, 0, {INTEL_PT_PWRE, 0, 0}, 0, 1 }, 15062306a36Sopenharmony_ci {4, {0x02, 0x22, 1, 2}, 0, {INTEL_PT_PWRE, 0, 0x0201}, 0, 1 }, 15162306a36Sopenharmony_ci {4, {0x02, 0x22, 0x80, 0x34}, 0, {INTEL_PT_PWRE, 0, 0x3480}, 0, 1 }, 15262306a36Sopenharmony_ci {4, {0x02, 0x22, 0x00, 0x56}, 0, {INTEL_PT_PWRE, 0, 0x5600}, 0, 1 }, 15362306a36Sopenharmony_ci /* Power Exit Packet */ 15462306a36Sopenharmony_ci {7, {0x02, 0xa2}, 0, {INTEL_PT_PWRX, 0, 0}, 0, 1 }, 15562306a36Sopenharmony_ci {7, {0x02, 0xa2, 1, 2, 3, 4, 5}, 0, {INTEL_PT_PWRX, 0, 0x504030201}, 0, 1 }, 15662306a36Sopenharmony_ci {7, {0x02, 0xa2, 0xff, 0xff, 0xff, 0xff, 0xff}, 0, {INTEL_PT_PWRX, 0, 0xffffffffff}, 0, 1 }, 15762306a36Sopenharmony_ci /* Block Begin Packet */ 15862306a36Sopenharmony_ci {3, {0x02, 0x63, 0x00}, 0, {INTEL_PT_BBP, 0, 0}, INTEL_PT_BLK_8_CTX, 0 }, 15962306a36Sopenharmony_ci {3, {0x02, 0x63, 0x80}, 0, {INTEL_PT_BBP, 1, 0}, INTEL_PT_BLK_4_CTX, 0 }, 16062306a36Sopenharmony_ci {3, {0x02, 0x63, 0x1f}, 0, {INTEL_PT_BBP, 0, 0x1f}, INTEL_PT_BLK_8_CTX, 0 }, 16162306a36Sopenharmony_ci {3, {0x02, 0x63, 0x9f}, 0, {INTEL_PT_BBP, 1, 0x1f}, INTEL_PT_BLK_4_CTX, 0 }, 16262306a36Sopenharmony_ci /* 4-byte Block Item Packet */ 16362306a36Sopenharmony_ci {5, {0x04}, INTEL_PT_BLK_4_CTX, {INTEL_PT_BIP, 0, 0}, INTEL_PT_BLK_4_CTX, 0 }, 16462306a36Sopenharmony_ci {5, {0xfc}, INTEL_PT_BLK_4_CTX, {INTEL_PT_BIP, 0x1f, 0}, INTEL_PT_BLK_4_CTX, 0 }, 16562306a36Sopenharmony_ci {5, {0x04, 1, 2, 3, 4}, INTEL_PT_BLK_4_CTX, {INTEL_PT_BIP, 0, 0x04030201}, INTEL_PT_BLK_4_CTX, 0 }, 16662306a36Sopenharmony_ci {5, {0xfc, 1, 2, 3, 4}, INTEL_PT_BLK_4_CTX, {INTEL_PT_BIP, 0x1f, 0x04030201}, INTEL_PT_BLK_4_CTX, 0 }, 16762306a36Sopenharmony_ci /* 8-byte Block Item Packet */ 16862306a36Sopenharmony_ci {9, {0x04}, INTEL_PT_BLK_8_CTX, {INTEL_PT_BIP, 0, 0}, INTEL_PT_BLK_8_CTX, 0 }, 16962306a36Sopenharmony_ci {9, {0xfc}, INTEL_PT_BLK_8_CTX, {INTEL_PT_BIP, 0x1f, 0}, INTEL_PT_BLK_8_CTX, 0 }, 17062306a36Sopenharmony_ci {9, {0x04, 1, 2, 3, 4, 5, 6, 7, 8}, INTEL_PT_BLK_8_CTX, {INTEL_PT_BIP, 0, 0x0807060504030201}, INTEL_PT_BLK_8_CTX, 0 }, 17162306a36Sopenharmony_ci {9, {0xfc, 1, 2, 3, 4, 5, 6, 7, 8}, INTEL_PT_BLK_8_CTX, {INTEL_PT_BIP, 0x1f, 0x0807060504030201}, INTEL_PT_BLK_8_CTX, 0 }, 17262306a36Sopenharmony_ci /* Block End Packet */ 17362306a36Sopenharmony_ci {2, {0x02, 0x33}, INTEL_PT_BLK_4_CTX, {INTEL_PT_BEP, 0, 0}, 0, 0 }, 17462306a36Sopenharmony_ci {2, {0x02, 0xb3}, INTEL_PT_BLK_4_CTX, {INTEL_PT_BEP_IP, 0, 0}, 0, 0 }, 17562306a36Sopenharmony_ci {2, {0x02, 0x33}, INTEL_PT_BLK_8_CTX, {INTEL_PT_BEP, 0, 0}, 0, 0 }, 17662306a36Sopenharmony_ci {2, {0x02, 0xb3}, INTEL_PT_BLK_8_CTX, {INTEL_PT_BEP_IP, 0, 0}, 0, 0 }, 17762306a36Sopenharmony_ci /* Control Flow Event Packet */ 17862306a36Sopenharmony_ci {4, {0x02, 0x13, 0x01, 0x03}, 0, {INTEL_PT_CFE, 1, 3}, 0, 0 }, 17962306a36Sopenharmony_ci {4, {0x02, 0x13, 0x81, 0x03}, 0, {INTEL_PT_CFE_IP, 1, 3}, 0, 0 }, 18062306a36Sopenharmony_ci {4, {0x02, 0x13, 0x1f, 0x00}, 0, {INTEL_PT_CFE, 0x1f, 0}, 0, 0 }, 18162306a36Sopenharmony_ci {4, {0x02, 0x13, 0x9f, 0xff}, 0, {INTEL_PT_CFE_IP, 0x1f, 0xff}, 0, 0 }, 18262306a36Sopenharmony_ci /* */ 18362306a36Sopenharmony_ci {11, {0x02, 0x53, 0x09, 1, 2, 3, 4, 5, 6, 7}, 0, {INTEL_PT_EVD, 0x09, 0x7060504030201}, 0, 0 }, 18462306a36Sopenharmony_ci {11, {0x02, 0x53, 0x3f, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_EVD, 0x3f, 0x8070605040302}, 0, 0 }, 18562306a36Sopenharmony_ci /* Terminator */ 18662306a36Sopenharmony_ci {0, {0}, 0, {0, 0, 0}, 0, 0 }, 18762306a36Sopenharmony_ci}; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cistatic int dump_packet(const struct intel_pt_pkt *packet, const u8 *bytes, int len) 19062306a36Sopenharmony_ci{ 19162306a36Sopenharmony_ci char desc[INTEL_PT_PKT_DESC_MAX]; 19262306a36Sopenharmony_ci int ret, i; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci for (i = 0; i < len; i++) 19562306a36Sopenharmony_ci pr_debug(" %02x", bytes[i]); 19662306a36Sopenharmony_ci for (; i < INTEL_PT_PKT_MAX_SZ; i++) 19762306a36Sopenharmony_ci pr_debug(" "); 19862306a36Sopenharmony_ci pr_debug(" "); 19962306a36Sopenharmony_ci ret = intel_pt_pkt_desc(packet, desc, INTEL_PT_PKT_DESC_MAX); 20062306a36Sopenharmony_ci if (ret < 0) { 20162306a36Sopenharmony_ci pr_debug("intel_pt_pkt_desc failed!\n"); 20262306a36Sopenharmony_ci return TEST_FAIL; 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci pr_debug("%s\n", desc); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci return TEST_OK; 20762306a36Sopenharmony_ci} 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_cistatic void decoding_failed(const struct test_data *d) 21062306a36Sopenharmony_ci{ 21162306a36Sopenharmony_ci pr_debug("Decoding failed!\n"); 21262306a36Sopenharmony_ci pr_debug("Decoding: "); 21362306a36Sopenharmony_ci dump_packet(&d->packet, d->bytes, d->len); 21462306a36Sopenharmony_ci} 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistatic int fail(const struct test_data *d, struct intel_pt_pkt *packet, int len, 21762306a36Sopenharmony_ci enum intel_pt_pkt_ctx new_ctx) 21862306a36Sopenharmony_ci{ 21962306a36Sopenharmony_ci decoding_failed(d); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci if (len != d->len) 22262306a36Sopenharmony_ci pr_debug("Expected length: %d Decoded length %d\n", 22362306a36Sopenharmony_ci d->len, len); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci if (packet->type != d->packet.type) 22662306a36Sopenharmony_ci pr_debug("Expected type: %d Decoded type %d\n", 22762306a36Sopenharmony_ci d->packet.type, packet->type); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci if (packet->count != d->packet.count) 23062306a36Sopenharmony_ci pr_debug("Expected count: %d Decoded count %d\n", 23162306a36Sopenharmony_ci d->packet.count, packet->count); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci if (packet->payload != d->packet.payload) 23462306a36Sopenharmony_ci pr_debug("Expected payload: 0x%llx Decoded payload 0x%llx\n", 23562306a36Sopenharmony_ci (unsigned long long)d->packet.payload, 23662306a36Sopenharmony_ci (unsigned long long)packet->payload); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci if (new_ctx != d->new_ctx) 23962306a36Sopenharmony_ci pr_debug("Expected packet context: %d Decoded packet context %d\n", 24062306a36Sopenharmony_ci d->new_ctx, new_ctx); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci return TEST_FAIL; 24362306a36Sopenharmony_ci} 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cistatic int test_ctx_unchanged(const struct test_data *d, struct intel_pt_pkt *packet, 24662306a36Sopenharmony_ci enum intel_pt_pkt_ctx ctx) 24762306a36Sopenharmony_ci{ 24862306a36Sopenharmony_ci enum intel_pt_pkt_ctx old_ctx = ctx; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci intel_pt_upd_pkt_ctx(packet, &ctx); 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci if (ctx != old_ctx) { 25362306a36Sopenharmony_ci decoding_failed(d); 25462306a36Sopenharmony_ci pr_debug("Packet context changed!\n"); 25562306a36Sopenharmony_ci return TEST_FAIL; 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci return TEST_OK; 25962306a36Sopenharmony_ci} 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistatic int test_one(const struct test_data *d) 26262306a36Sopenharmony_ci{ 26362306a36Sopenharmony_ci struct intel_pt_pkt packet; 26462306a36Sopenharmony_ci enum intel_pt_pkt_ctx ctx = d->ctx; 26562306a36Sopenharmony_ci int ret; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci memset(&packet, 0xff, sizeof(packet)); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci /* Decode a packet */ 27062306a36Sopenharmony_ci ret = intel_pt_get_packet(d->bytes, d->len, &packet, &ctx); 27162306a36Sopenharmony_ci if (ret < 0 || ret > INTEL_PT_PKT_MAX_SZ) { 27262306a36Sopenharmony_ci decoding_failed(d); 27362306a36Sopenharmony_ci pr_debug("intel_pt_get_packet returned %d\n", ret); 27462306a36Sopenharmony_ci return TEST_FAIL; 27562306a36Sopenharmony_ci } 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci /* Some packets must always leave the packet context unchanged */ 27862306a36Sopenharmony_ci if (d->ctx_unchanged) { 27962306a36Sopenharmony_ci int err; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci err = test_ctx_unchanged(d, &packet, INTEL_PT_NO_CTX); 28262306a36Sopenharmony_ci if (err) 28362306a36Sopenharmony_ci return err; 28462306a36Sopenharmony_ci err = test_ctx_unchanged(d, &packet, INTEL_PT_BLK_4_CTX); 28562306a36Sopenharmony_ci if (err) 28662306a36Sopenharmony_ci return err; 28762306a36Sopenharmony_ci err = test_ctx_unchanged(d, &packet, INTEL_PT_BLK_8_CTX); 28862306a36Sopenharmony_ci if (err) 28962306a36Sopenharmony_ci return err; 29062306a36Sopenharmony_ci } 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci /* Compare to the expected values */ 29362306a36Sopenharmony_ci if (ret != d->len || packet.type != d->packet.type || 29462306a36Sopenharmony_ci packet.count != d->packet.count || 29562306a36Sopenharmony_ci packet.payload != d->packet.payload || ctx != d->new_ctx) 29662306a36Sopenharmony_ci return fail(d, &packet, ret, ctx); 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci pr_debug("Decoded ok:"); 29962306a36Sopenharmony_ci ret = dump_packet(&d->packet, d->bytes, d->len); 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci return ret; 30262306a36Sopenharmony_ci} 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci/* 30562306a36Sopenharmony_ci * This test feeds byte sequences to the Intel PT packet decoder and checks the 30662306a36Sopenharmony_ci * results. Changes to the packet context are also checked. 30762306a36Sopenharmony_ci */ 30862306a36Sopenharmony_ciint test__intel_pt_pkt_decoder(struct test_suite *test __maybe_unused, int subtest __maybe_unused) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci const struct test_data *d = data; 31162306a36Sopenharmony_ci int ret; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci for (d = data; d->len; d++) { 31462306a36Sopenharmony_ci ret = test_one(d); 31562306a36Sopenharmony_ci if (ret) 31662306a36Sopenharmony_ci return ret; 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci return TEST_OK; 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistatic int setaffinity(int cpu) 32362306a36Sopenharmony_ci{ 32462306a36Sopenharmony_ci cpu_set_t cpu_set; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci CPU_ZERO(&cpu_set); 32762306a36Sopenharmony_ci CPU_SET(cpu, &cpu_set); 32862306a36Sopenharmony_ci if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set)) { 32962306a36Sopenharmony_ci pr_debug("sched_setaffinity() failed for CPU %d\n", cpu); 33062306a36Sopenharmony_ci return -1; 33162306a36Sopenharmony_ci } 33262306a36Sopenharmony_ci return 0; 33362306a36Sopenharmony_ci} 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci#define INTEL_PT_ADDR_FILT_CNT_MASK GENMASK(2, 0) 33662306a36Sopenharmony_ci#define INTEL_PT_SUBLEAF_CNT 2 33762306a36Sopenharmony_ci#define CPUID_REG_CNT 4 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_cistruct cpuid_result { 34062306a36Sopenharmony_ci union { 34162306a36Sopenharmony_ci struct { 34262306a36Sopenharmony_ci unsigned int eax; 34362306a36Sopenharmony_ci unsigned int ebx; 34462306a36Sopenharmony_ci unsigned int ecx; 34562306a36Sopenharmony_ci unsigned int edx; 34662306a36Sopenharmony_ci }; 34762306a36Sopenharmony_ci unsigned int reg[CPUID_REG_CNT]; 34862306a36Sopenharmony_ci }; 34962306a36Sopenharmony_ci}; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_cistruct pt_caps { 35262306a36Sopenharmony_ci struct cpuid_result subleaf[INTEL_PT_SUBLEAF_CNT]; 35362306a36Sopenharmony_ci}; 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_cistatic int get_pt_caps(int cpu, struct pt_caps *caps) 35662306a36Sopenharmony_ci{ 35762306a36Sopenharmony_ci struct cpuid_result r; 35862306a36Sopenharmony_ci int i; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci if (setaffinity(cpu)) 36162306a36Sopenharmony_ci return -1; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci memset(caps, 0, sizeof(*caps)); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci for (i = 0; i < INTEL_PT_SUBLEAF_CNT; i++) { 36662306a36Sopenharmony_ci __get_cpuid_count(20, i, &r.eax, &r.ebx, &r.ecx, &r.edx); 36762306a36Sopenharmony_ci pr_debug("CPU %d CPUID leaf 20 subleaf %d\n", cpu, i); 36862306a36Sopenharmony_ci pr_debug("eax = 0x%08x\n", r.eax); 36962306a36Sopenharmony_ci pr_debug("ebx = 0x%08x\n", r.ebx); 37062306a36Sopenharmony_ci pr_debug("ecx = 0x%08x\n", r.ecx); 37162306a36Sopenharmony_ci pr_debug("edx = 0x%08x\n", r.edx); 37262306a36Sopenharmony_ci caps->subleaf[i] = r; 37362306a36Sopenharmony_ci } 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci return 0; 37662306a36Sopenharmony_ci} 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_cistatic bool is_hydrid(void) 37962306a36Sopenharmony_ci{ 38062306a36Sopenharmony_ci unsigned int eax, ebx, ecx, edx = 0; 38162306a36Sopenharmony_ci bool result; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci __get_cpuid_count(7, 0, &eax, &ebx, &ecx, &edx); 38462306a36Sopenharmony_ci result = edx & BIT(15); 38562306a36Sopenharmony_ci pr_debug("Is %shybrid : CPUID leaf 7 subleaf 0 edx %#x (bit-15 indicates hybrid)\n", 38662306a36Sopenharmony_ci result ? "" : "not ", edx); 38762306a36Sopenharmony_ci return result; 38862306a36Sopenharmony_ci} 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_cistatic int compare_caps(int cpu, struct pt_caps *caps, struct pt_caps *caps0) 39162306a36Sopenharmony_ci{ 39262306a36Sopenharmony_ci struct pt_caps mask = { /* Mask of bits to check*/ 39362306a36Sopenharmony_ci .subleaf = { 39462306a36Sopenharmony_ci [0] = { 39562306a36Sopenharmony_ci .ebx = GENMASK(8, 0), 39662306a36Sopenharmony_ci .ecx = GENMASK(3, 0), 39762306a36Sopenharmony_ci }, 39862306a36Sopenharmony_ci [1] = { 39962306a36Sopenharmony_ci .eax = GENMASK(31, 16), 40062306a36Sopenharmony_ci .ebx = GENMASK(31, 0), 40162306a36Sopenharmony_ci } 40262306a36Sopenharmony_ci } 40362306a36Sopenharmony_ci }; 40462306a36Sopenharmony_ci unsigned int m, reg, reg0; 40562306a36Sopenharmony_ci int ret = 0; 40662306a36Sopenharmony_ci int i, j; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci for (i = 0; i < INTEL_PT_SUBLEAF_CNT; i++) { 40962306a36Sopenharmony_ci for (j = 0; j < CPUID_REG_CNT; j++) { 41062306a36Sopenharmony_ci m = mask.subleaf[i].reg[j]; 41162306a36Sopenharmony_ci reg = m & caps->subleaf[i].reg[j]; 41262306a36Sopenharmony_ci reg0 = m & caps0->subleaf[i].reg[j]; 41362306a36Sopenharmony_ci if ((reg & reg0) != reg0) { 41462306a36Sopenharmony_ci pr_debug("CPU %d subleaf %d reg %d FAIL %#x vs %#x\n", 41562306a36Sopenharmony_ci cpu, i, j, reg, reg0); 41662306a36Sopenharmony_ci ret = -1; 41762306a36Sopenharmony_ci } 41862306a36Sopenharmony_ci } 41962306a36Sopenharmony_ci } 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci m = INTEL_PT_ADDR_FILT_CNT_MASK; 42262306a36Sopenharmony_ci reg = m & caps->subleaf[1].eax; 42362306a36Sopenharmony_ci reg0 = m & caps0->subleaf[1].eax; 42462306a36Sopenharmony_ci if (reg < reg0) { 42562306a36Sopenharmony_ci pr_debug("CPU %d subleaf 1 reg 0 FAIL address filter count %#x vs %#x\n", 42662306a36Sopenharmony_ci cpu, reg, reg0); 42762306a36Sopenharmony_ci ret = -1; 42862306a36Sopenharmony_ci } 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci if (!ret) 43162306a36Sopenharmony_ci pr_debug("CPU %d OK\n", cpu); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci return ret; 43462306a36Sopenharmony_ci} 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ciint test__intel_pt_hybrid_compat(struct test_suite *test, int subtest) 43762306a36Sopenharmony_ci{ 43862306a36Sopenharmony_ci int max_cpu = cpu__max_cpu().cpu; 43962306a36Sopenharmony_ci struct pt_caps last_caps; 44062306a36Sopenharmony_ci struct pt_caps caps0; 44162306a36Sopenharmony_ci int ret = TEST_OK; 44262306a36Sopenharmony_ci int cpu; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci if (!is_hydrid()) { 44562306a36Sopenharmony_ci test->test_cases[subtest].skip_reason = "not hybrid"; 44662306a36Sopenharmony_ci return TEST_SKIP; 44762306a36Sopenharmony_ci } 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci if (get_pt_caps(0, &caps0)) 45062306a36Sopenharmony_ci return TEST_FAIL; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci for (cpu = 1, last_caps = caps0; cpu < max_cpu; cpu++) { 45362306a36Sopenharmony_ci struct pt_caps caps; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci if (get_pt_caps(cpu, &caps)) { 45662306a36Sopenharmony_ci pr_debug("CPU %d not found\n", cpu); 45762306a36Sopenharmony_ci continue; 45862306a36Sopenharmony_ci } 45962306a36Sopenharmony_ci if (!memcmp(&caps, &last_caps, sizeof(caps))) { 46062306a36Sopenharmony_ci pr_debug("CPU %d same caps as previous CPU\n", cpu); 46162306a36Sopenharmony_ci continue; 46262306a36Sopenharmony_ci } 46362306a36Sopenharmony_ci if (compare_caps(cpu, &caps, &caps0)) 46462306a36Sopenharmony_ci ret = TEST_FAIL; 46562306a36Sopenharmony_ci last_caps = caps; 46662306a36Sopenharmony_ci } 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci return ret; 46962306a36Sopenharmony_ci} 470