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