cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

test_emulate_step.c (37794B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Simple sanity tests for instruction emulation infrastructure.
      4 *
      5 * Copyright IBM Corp. 2016
      6 */
      7
      8#define pr_fmt(fmt) "emulate_step_test: " fmt
      9
     10#include <linux/ptrace.h>
     11#include <asm/cpu_has_feature.h>
     12#include <asm/sstep.h>
     13#include <asm/ppc-opcode.h>
     14#include <asm/code-patching.h>
     15#include <asm/inst.h>
     16
     17#define MAX_SUBTESTS	16
     18
     19#define IGNORE_GPR(n)	(0x1UL << (n))
     20#define IGNORE_XER	(0x1UL << 32)
     21#define IGNORE_CCR	(0x1UL << 33)
     22#define NEGATIVE_TEST	(0x1UL << 63)
     23
     24#define TEST_PLD(r, base, i, pr) \
     25	ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \
     26			PPC_INST_PLD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
     27
     28#define TEST_PLWZ(r, base, i, pr) \
     29	ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
     30			PPC_RAW_LWZ(r, base, i))
     31
     32#define TEST_PSTD(r, base, i, pr) \
     33	ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \
     34			PPC_INST_PSTD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
     35
     36#define TEST_PLFS(r, base, i, pr) \
     37	ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
     38			PPC_INST_LFS | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
     39
     40#define TEST_PSTFS(r, base, i, pr) \
     41	ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
     42			PPC_INST_STFS | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
     43
     44#define TEST_PLFD(r, base, i, pr) \
     45	ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
     46			PPC_INST_LFD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
     47
     48#define TEST_PSTFD(r, base, i, pr) \
     49	ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
     50			PPC_INST_STFD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
     51
     52#define TEST_PADDI(t, a, i, pr) \
     53	ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
     54			PPC_RAW_ADDI(t, a, i))
     55
     56#define TEST_SETB(t, bfa)       ppc_inst(PPC_INST_SETB | ___PPC_RT(t) | ___PPC_RA((bfa & 0x7) << 2))
     57
     58
     59static void __init init_pt_regs(struct pt_regs *regs)
     60{
     61	static unsigned long msr;
     62	static bool msr_cached;
     63
     64	memset(regs, 0, sizeof(struct pt_regs));
     65
     66	if (likely(msr_cached)) {
     67		regs->msr = msr;
     68		return;
     69	}
     70
     71	asm volatile("mfmsr %0" : "=r"(regs->msr));
     72
     73	regs->msr |= MSR_FP;
     74	regs->msr |= MSR_VEC;
     75	regs->msr |= MSR_VSX;
     76
     77	msr = regs->msr;
     78	msr_cached = true;
     79}
     80
     81static void __init show_result(char *mnemonic, char *result)
     82{
     83	pr_info("%-14s : %s\n", mnemonic, result);
     84}
     85
     86static void __init show_result_with_descr(char *mnemonic, char *descr,
     87					  char *result)
     88{
     89	pr_info("%-14s : %-50s %s\n", mnemonic, descr, result);
     90}
     91
     92static void __init test_ld(void)
     93{
     94	struct pt_regs regs;
     95	unsigned long a = 0x23;
     96	int stepped = -1;
     97
     98	init_pt_regs(&regs);
     99	regs.gpr[3] = (unsigned long) &a;
    100
    101	/* ld r5, 0(r3) */
    102	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LD(5, 3, 0)));
    103
    104	if (stepped == 1 && regs.gpr[5] == a)
    105		show_result("ld", "PASS");
    106	else
    107		show_result("ld", "FAIL");
    108}
    109
    110static void __init test_pld(void)
    111{
    112	struct pt_regs regs;
    113	unsigned long a = 0x23;
    114	int stepped = -1;
    115
    116	if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
    117		show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
    118		return;
    119	}
    120
    121	init_pt_regs(&regs);
    122	regs.gpr[3] = (unsigned long)&a;
    123
    124	/* pld r5, 0(r3), 0 */
    125	stepped = emulate_step(&regs, TEST_PLD(5, 3, 0, 0));
    126
    127	if (stepped == 1 && regs.gpr[5] == a)
    128		show_result("pld", "PASS");
    129	else
    130		show_result("pld", "FAIL");
    131}
    132
    133static void __init test_lwz(void)
    134{
    135	struct pt_regs regs;
    136	unsigned int a = 0x4545;
    137	int stepped = -1;
    138
    139	init_pt_regs(&regs);
    140	regs.gpr[3] = (unsigned long) &a;
    141
    142	/* lwz r5, 0(r3) */
    143	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LWZ(5, 3, 0)));
    144
    145	if (stepped == 1 && regs.gpr[5] == a)
    146		show_result("lwz", "PASS");
    147	else
    148		show_result("lwz", "FAIL");
    149}
    150
    151static void __init test_plwz(void)
    152{
    153	struct pt_regs regs;
    154	unsigned int a = 0x4545;
    155	int stepped = -1;
    156
    157	if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
    158		show_result("plwz", "SKIP (!CPU_FTR_ARCH_31)");
    159		return;
    160	}
    161
    162	init_pt_regs(&regs);
    163	regs.gpr[3] = (unsigned long)&a;
    164
    165	/* plwz r5, 0(r3), 0 */
    166
    167	stepped = emulate_step(&regs, TEST_PLWZ(5, 3, 0, 0));
    168
    169	if (stepped == 1 && regs.gpr[5] == a)
    170		show_result("plwz", "PASS");
    171	else
    172		show_result("plwz", "FAIL");
    173}
    174
    175static void __init test_lwzx(void)
    176{
    177	struct pt_regs regs;
    178	unsigned int a[3] = {0x0, 0x0, 0x1234};
    179	int stepped = -1;
    180
    181	init_pt_regs(&regs);
    182	regs.gpr[3] = (unsigned long) a;
    183	regs.gpr[4] = 8;
    184	regs.gpr[5] = 0x8765;
    185
    186	/* lwzx r5, r3, r4 */
    187	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LWZX(5, 3, 4)));
    188	if (stepped == 1 && regs.gpr[5] == a[2])
    189		show_result("lwzx", "PASS");
    190	else
    191		show_result("lwzx", "FAIL");
    192}
    193
    194static void __init test_std(void)
    195{
    196	struct pt_regs regs;
    197	unsigned long a = 0x1234;
    198	int stepped = -1;
    199
    200	init_pt_regs(&regs);
    201	regs.gpr[3] = (unsigned long) &a;
    202	regs.gpr[5] = 0x5678;
    203
    204	/* std r5, 0(r3) */
    205	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STD(5, 3, 0)));
    206	if (stepped == 1 && regs.gpr[5] == a)
    207		show_result("std", "PASS");
    208	else
    209		show_result("std", "FAIL");
    210}
    211
    212static void __init test_pstd(void)
    213{
    214	struct pt_regs regs;
    215	unsigned long a = 0x1234;
    216	int stepped = -1;
    217
    218	if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
    219		show_result("pstd", "SKIP (!CPU_FTR_ARCH_31)");
    220		return;
    221	}
    222
    223	init_pt_regs(&regs);
    224	regs.gpr[3] = (unsigned long)&a;
    225	regs.gpr[5] = 0x5678;
    226
    227	/* pstd r5, 0(r3), 0 */
    228	stepped = emulate_step(&regs, TEST_PSTD(5, 3, 0, 0));
    229	if (stepped == 1 || regs.gpr[5] == a)
    230		show_result("pstd", "PASS");
    231	else
    232		show_result("pstd", "FAIL");
    233}
    234
    235static void __init test_ldarx_stdcx(void)
    236{
    237	struct pt_regs regs;
    238	unsigned long a = 0x1234;
    239	int stepped = -1;
    240	unsigned long cr0_eq = 0x1 << 29; /* eq bit of CR0 */
    241
    242	init_pt_regs(&regs);
    243	asm volatile("mfcr %0" : "=r"(regs.ccr));
    244
    245
    246	/*** ldarx ***/
    247
    248	regs.gpr[3] = (unsigned long) &a;
    249	regs.gpr[4] = 0;
    250	regs.gpr[5] = 0x5678;
    251
    252	/* ldarx r5, r3, r4, 0 */
    253	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LDARX(5, 3, 4, 0)));
    254
    255	/*
    256	 * Don't touch 'a' here. Touching 'a' can do Load/store
    257	 * of 'a' which result in failure of subsequent stdcx.
    258	 * Instead, use hardcoded value for comparison.
    259	 */
    260	if (stepped <= 0 || regs.gpr[5] != 0x1234) {
    261		show_result("ldarx / stdcx.", "FAIL (ldarx)");
    262		return;
    263	}
    264
    265
    266	/*** stdcx. ***/
    267
    268	regs.gpr[5] = 0x9ABC;
    269
    270	/* stdcx. r5, r3, r4 */
    271	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STDCX(5, 3, 4)));
    272
    273	/*
    274	 * Two possible scenarios that indicates successful emulation
    275	 * of stdcx. :
    276	 *  1. Reservation is active and store is performed. In this
    277	 *     case cr0.eq bit will be set to 1.
    278	 *  2. Reservation is not active and store is not performed.
    279	 *     In this case cr0.eq bit will be set to 0.
    280	 */
    281	if (stepped == 1 && ((regs.gpr[5] == a && (regs.ccr & cr0_eq))
    282			|| (regs.gpr[5] != a && !(regs.ccr & cr0_eq))))
    283		show_result("ldarx / stdcx.", "PASS");
    284	else
    285		show_result("ldarx / stdcx.", "FAIL (stdcx.)");
    286}
    287
    288#ifdef CONFIG_PPC_FPU
    289static void __init test_lfsx_stfsx(void)
    290{
    291	struct pt_regs regs;
    292	union {
    293		float a;
    294		int b;
    295	} c;
    296	int cached_b;
    297	int stepped = -1;
    298
    299	init_pt_regs(&regs);
    300
    301
    302	/*** lfsx ***/
    303
    304	c.a = 123.45;
    305	cached_b = c.b;
    306
    307	regs.gpr[3] = (unsigned long) &c.a;
    308	regs.gpr[4] = 0;
    309
    310	/* lfsx frt10, r3, r4 */
    311	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LFSX(10, 3, 4)));
    312
    313	if (stepped == 1)
    314		show_result("lfsx", "PASS");
    315	else
    316		show_result("lfsx", "FAIL");
    317
    318
    319	/*** stfsx ***/
    320
    321	c.a = 678.91;
    322
    323	/* stfsx frs10, r3, r4 */
    324	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STFSX(10, 3, 4)));
    325
    326	if (stepped == 1 && c.b == cached_b)
    327		show_result("stfsx", "PASS");
    328	else
    329		show_result("stfsx", "FAIL");
    330}
    331
    332static void __init test_plfs_pstfs(void)
    333{
    334	struct pt_regs regs;
    335	union {
    336		float a;
    337		int b;
    338	} c;
    339	int cached_b;
    340	int stepped = -1;
    341
    342	if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
    343		show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
    344		return;
    345	}
    346
    347	init_pt_regs(&regs);
    348
    349
    350	/*** plfs ***/
    351
    352	c.a = 123.45;
    353	cached_b = c.b;
    354
    355	regs.gpr[3] = (unsigned long)&c.a;
    356
    357	/* plfs frt10, 0(r3), 0  */
    358	stepped = emulate_step(&regs, TEST_PLFS(10, 3, 0, 0));
    359
    360	if (stepped == 1)
    361		show_result("plfs", "PASS");
    362	else
    363		show_result("plfs", "FAIL");
    364
    365
    366	/*** pstfs ***/
    367
    368	c.a = 678.91;
    369
    370	/* pstfs frs10, 0(r3), 0 */
    371	stepped = emulate_step(&regs, TEST_PSTFS(10, 3, 0, 0));
    372
    373	if (stepped == 1 && c.b == cached_b)
    374		show_result("pstfs", "PASS");
    375	else
    376		show_result("pstfs", "FAIL");
    377}
    378
    379static void __init test_lfdx_stfdx(void)
    380{
    381	struct pt_regs regs;
    382	union {
    383		double a;
    384		long b;
    385	} c;
    386	long cached_b;
    387	int stepped = -1;
    388
    389	init_pt_regs(&regs);
    390
    391
    392	/*** lfdx ***/
    393
    394	c.a = 123456.78;
    395	cached_b = c.b;
    396
    397	regs.gpr[3] = (unsigned long) &c.a;
    398	regs.gpr[4] = 0;
    399
    400	/* lfdx frt10, r3, r4 */
    401	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LFDX(10, 3, 4)));
    402
    403	if (stepped == 1)
    404		show_result("lfdx", "PASS");
    405	else
    406		show_result("lfdx", "FAIL");
    407
    408
    409	/*** stfdx ***/
    410
    411	c.a = 987654.32;
    412
    413	/* stfdx frs10, r3, r4 */
    414	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STFDX(10, 3, 4)));
    415
    416	if (stepped == 1 && c.b == cached_b)
    417		show_result("stfdx", "PASS");
    418	else
    419		show_result("stfdx", "FAIL");
    420}
    421
    422static void __init test_plfd_pstfd(void)
    423{
    424	struct pt_regs regs;
    425	union {
    426		double a;
    427		long b;
    428	} c;
    429	long cached_b;
    430	int stepped = -1;
    431
    432	if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
    433		show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
    434		return;
    435	}
    436
    437	init_pt_regs(&regs);
    438
    439
    440	/*** plfd ***/
    441
    442	c.a = 123456.78;
    443	cached_b = c.b;
    444
    445	regs.gpr[3] = (unsigned long)&c.a;
    446
    447	/* plfd frt10, 0(r3), 0 */
    448	stepped = emulate_step(&regs, TEST_PLFD(10, 3, 0, 0));
    449
    450	if (stepped == 1)
    451		show_result("plfd", "PASS");
    452	else
    453		show_result("plfd", "FAIL");
    454
    455
    456	/*** pstfd ***/
    457
    458	c.a = 987654.32;
    459
    460	/* pstfd frs10, 0(r3), 0 */
    461	stepped = emulate_step(&regs, TEST_PSTFD(10, 3, 0, 0));
    462
    463	if (stepped == 1 && c.b == cached_b)
    464		show_result("pstfd", "PASS");
    465	else
    466		show_result("pstfd", "FAIL");
    467}
    468#else
    469static void __init test_lfsx_stfsx(void)
    470{
    471	show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)");
    472	show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)");
    473}
    474
    475static void __init test_plfs_pstfs(void)
    476{
    477	show_result("plfs", "SKIP (CONFIG_PPC_FPU is not set)");
    478	show_result("pstfs", "SKIP (CONFIG_PPC_FPU is not set)");
    479}
    480
    481static void __init test_lfdx_stfdx(void)
    482{
    483	show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)");
    484	show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)");
    485}
    486
    487static void __init test_plfd_pstfd(void)
    488{
    489	show_result("plfd", "SKIP (CONFIG_PPC_FPU is not set)");
    490	show_result("pstfd", "SKIP (CONFIG_PPC_FPU is not set)");
    491}
    492#endif /* CONFIG_PPC_FPU */
    493
    494#ifdef CONFIG_ALTIVEC
    495static void __init test_lvx_stvx(void)
    496{
    497	struct pt_regs regs;
    498	union {
    499		vector128 a;
    500		u32 b[4];
    501	} c;
    502	u32 cached_b[4];
    503	int stepped = -1;
    504
    505	init_pt_regs(&regs);
    506
    507
    508	/*** lvx ***/
    509
    510	cached_b[0] = c.b[0] = 923745;
    511	cached_b[1] = c.b[1] = 2139478;
    512	cached_b[2] = c.b[2] = 9012;
    513	cached_b[3] = c.b[3] = 982134;
    514
    515	regs.gpr[3] = (unsigned long) &c.a;
    516	regs.gpr[4] = 0;
    517
    518	/* lvx vrt10, r3, r4 */
    519	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LVX(10, 3, 4)));
    520
    521	if (stepped == 1)
    522		show_result("lvx", "PASS");
    523	else
    524		show_result("lvx", "FAIL");
    525
    526
    527	/*** stvx ***/
    528
    529	c.b[0] = 4987513;
    530	c.b[1] = 84313948;
    531	c.b[2] = 71;
    532	c.b[3] = 498532;
    533
    534	/* stvx vrs10, r3, r4 */
    535	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STVX(10, 3, 4)));
    536
    537	if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
    538	    cached_b[2] == c.b[2] && cached_b[3] == c.b[3])
    539		show_result("stvx", "PASS");
    540	else
    541		show_result("stvx", "FAIL");
    542}
    543#else
    544static void __init test_lvx_stvx(void)
    545{
    546	show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)");
    547	show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)");
    548}
    549#endif /* CONFIG_ALTIVEC */
    550
    551#ifdef CONFIG_VSX
    552static void __init test_lxvd2x_stxvd2x(void)
    553{
    554	struct pt_regs regs;
    555	union {
    556		vector128 a;
    557		u32 b[4];
    558	} c;
    559	u32 cached_b[4];
    560	int stepped = -1;
    561
    562	init_pt_regs(&regs);
    563
    564
    565	/*** lxvd2x ***/
    566
    567	cached_b[0] = c.b[0] = 18233;
    568	cached_b[1] = c.b[1] = 34863571;
    569	cached_b[2] = c.b[2] = 834;
    570	cached_b[3] = c.b[3] = 6138911;
    571
    572	regs.gpr[3] = (unsigned long) &c.a;
    573	regs.gpr[4] = 0;
    574
    575	/* lxvd2x vsr39, r3, r4 */
    576	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LXVD2X(39, R3, R4)));
    577
    578	if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
    579		show_result("lxvd2x", "PASS");
    580	} else {
    581		if (!cpu_has_feature(CPU_FTR_VSX))
    582			show_result("lxvd2x", "PASS (!CPU_FTR_VSX)");
    583		else
    584			show_result("lxvd2x", "FAIL");
    585	}
    586
    587
    588	/*** stxvd2x ***/
    589
    590	c.b[0] = 21379463;
    591	c.b[1] = 87;
    592	c.b[2] = 374234;
    593	c.b[3] = 4;
    594
    595	/* stxvd2x vsr39, r3, r4 */
    596	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STXVD2X(39, R3, R4)));
    597
    598	if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
    599	    cached_b[2] == c.b[2] && cached_b[3] == c.b[3] &&
    600	    cpu_has_feature(CPU_FTR_VSX)) {
    601		show_result("stxvd2x", "PASS");
    602	} else {
    603		if (!cpu_has_feature(CPU_FTR_VSX))
    604			show_result("stxvd2x", "PASS (!CPU_FTR_VSX)");
    605		else
    606			show_result("stxvd2x", "FAIL");
    607	}
    608}
    609#else
    610static void __init test_lxvd2x_stxvd2x(void)
    611{
    612	show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)");
    613	show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)");
    614}
    615#endif /* CONFIG_VSX */
    616
    617#ifdef CONFIG_VSX
    618static void __init test_lxvp_stxvp(void)
    619{
    620	struct pt_regs regs;
    621	union {
    622		vector128 a;
    623		u32 b[4];
    624	} c[2];
    625	u32 cached_b[8];
    626	int stepped = -1;
    627
    628	if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
    629		show_result("lxvp", "SKIP (!CPU_FTR_ARCH_31)");
    630		show_result("stxvp", "SKIP (!CPU_FTR_ARCH_31)");
    631		return;
    632	}
    633
    634	init_pt_regs(&regs);
    635
    636	/*** lxvp ***/
    637
    638	cached_b[0] = c[0].b[0] = 18233;
    639	cached_b[1] = c[0].b[1] = 34863571;
    640	cached_b[2] = c[0].b[2] = 834;
    641	cached_b[3] = c[0].b[3] = 6138911;
    642	cached_b[4] = c[1].b[0] = 1234;
    643	cached_b[5] = c[1].b[1] = 5678;
    644	cached_b[6] = c[1].b[2] = 91011;
    645	cached_b[7] = c[1].b[3] = 121314;
    646
    647	regs.gpr[4] = (unsigned long)&c[0].a;
    648
    649	/*
    650	 * lxvp XTp,DQ(RA)
    651	 * XTp = 32xTX + 2xTp
    652	 * let TX=1 Tp=1 RA=4 DQ=0
    653	 */
    654	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LXVP(34, 4, 0)));
    655
    656	if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
    657		show_result("lxvp", "PASS");
    658	} else {
    659		if (!cpu_has_feature(CPU_FTR_VSX))
    660			show_result("lxvp", "PASS (!CPU_FTR_VSX)");
    661		else
    662			show_result("lxvp", "FAIL");
    663	}
    664
    665	/*** stxvp ***/
    666
    667	c[0].b[0] = 21379463;
    668	c[0].b[1] = 87;
    669	c[0].b[2] = 374234;
    670	c[0].b[3] = 4;
    671	c[1].b[0] = 90;
    672	c[1].b[1] = 122;
    673	c[1].b[2] = 555;
    674	c[1].b[3] = 32144;
    675
    676	/*
    677	 * stxvp XSp,DQ(RA)
    678	 * XSp = 32xSX + 2xSp
    679	 * let SX=1 Sp=1 RA=4 DQ=0
    680	 */
    681	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STXVP(34, 4, 0)));
    682
    683	if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] &&
    684	    cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] &&
    685	    cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] &&
    686	    cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] &&
    687	    cpu_has_feature(CPU_FTR_VSX)) {
    688		show_result("stxvp", "PASS");
    689	} else {
    690		if (!cpu_has_feature(CPU_FTR_VSX))
    691			show_result("stxvp", "PASS (!CPU_FTR_VSX)");
    692		else
    693			show_result("stxvp", "FAIL");
    694	}
    695}
    696#else
    697static void __init test_lxvp_stxvp(void)
    698{
    699	show_result("lxvp", "SKIP (CONFIG_VSX is not set)");
    700	show_result("stxvp", "SKIP (CONFIG_VSX is not set)");
    701}
    702#endif /* CONFIG_VSX */
    703
    704#ifdef CONFIG_VSX
    705static void __init test_lxvpx_stxvpx(void)
    706{
    707	struct pt_regs regs;
    708	union {
    709		vector128 a;
    710		u32 b[4];
    711	} c[2];
    712	u32 cached_b[8];
    713	int stepped = -1;
    714
    715	if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
    716		show_result("lxvpx", "SKIP (!CPU_FTR_ARCH_31)");
    717		show_result("stxvpx", "SKIP (!CPU_FTR_ARCH_31)");
    718		return;
    719	}
    720
    721	init_pt_regs(&regs);
    722
    723	/*** lxvpx ***/
    724
    725	cached_b[0] = c[0].b[0] = 18233;
    726	cached_b[1] = c[0].b[1] = 34863571;
    727	cached_b[2] = c[0].b[2] = 834;
    728	cached_b[3] = c[0].b[3] = 6138911;
    729	cached_b[4] = c[1].b[0] = 1234;
    730	cached_b[5] = c[1].b[1] = 5678;
    731	cached_b[6] = c[1].b[2] = 91011;
    732	cached_b[7] = c[1].b[3] = 121314;
    733
    734	regs.gpr[3] = (unsigned long)&c[0].a;
    735	regs.gpr[4] = 0;
    736
    737	/*
    738	 * lxvpx XTp,RA,RB
    739	 * XTp = 32xTX + 2xTp
    740	 * let TX=1 Tp=1 RA=3 RB=4
    741	 */
    742	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LXVPX(34, 3, 4)));
    743
    744	if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
    745		show_result("lxvpx", "PASS");
    746	} else {
    747		if (!cpu_has_feature(CPU_FTR_VSX))
    748			show_result("lxvpx", "PASS (!CPU_FTR_VSX)");
    749		else
    750			show_result("lxvpx", "FAIL");
    751	}
    752
    753	/*** stxvpx ***/
    754
    755	c[0].b[0] = 21379463;
    756	c[0].b[1] = 87;
    757	c[0].b[2] = 374234;
    758	c[0].b[3] = 4;
    759	c[1].b[0] = 90;
    760	c[1].b[1] = 122;
    761	c[1].b[2] = 555;
    762	c[1].b[3] = 32144;
    763
    764	/*
    765	 * stxvpx XSp,RA,RB
    766	 * XSp = 32xSX + 2xSp
    767	 * let SX=1 Sp=1 RA=3 RB=4
    768	 */
    769	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STXVPX(34, 3, 4)));
    770
    771	if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] &&
    772	    cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] &&
    773	    cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] &&
    774	    cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] &&
    775	    cpu_has_feature(CPU_FTR_VSX)) {
    776		show_result("stxvpx", "PASS");
    777	} else {
    778		if (!cpu_has_feature(CPU_FTR_VSX))
    779			show_result("stxvpx", "PASS (!CPU_FTR_VSX)");
    780		else
    781			show_result("stxvpx", "FAIL");
    782	}
    783}
    784#else
    785static void __init test_lxvpx_stxvpx(void)
    786{
    787	show_result("lxvpx", "SKIP (CONFIG_VSX is not set)");
    788	show_result("stxvpx", "SKIP (CONFIG_VSX is not set)");
    789}
    790#endif /* CONFIG_VSX */
    791
    792#ifdef CONFIG_VSX
    793static void __init test_plxvp_pstxvp(void)
    794{
    795	ppc_inst_t instr;
    796	struct pt_regs regs;
    797	union {
    798		vector128 a;
    799		u32 b[4];
    800	} c[2];
    801	u32 cached_b[8];
    802	int stepped = -1;
    803
    804	if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
    805		show_result("plxvp", "SKIP (!CPU_FTR_ARCH_31)");
    806		show_result("pstxvp", "SKIP (!CPU_FTR_ARCH_31)");
    807		return;
    808	}
    809
    810	/*** plxvp ***/
    811
    812	cached_b[0] = c[0].b[0] = 18233;
    813	cached_b[1] = c[0].b[1] = 34863571;
    814	cached_b[2] = c[0].b[2] = 834;
    815	cached_b[3] = c[0].b[3] = 6138911;
    816	cached_b[4] = c[1].b[0] = 1234;
    817	cached_b[5] = c[1].b[1] = 5678;
    818	cached_b[6] = c[1].b[2] = 91011;
    819	cached_b[7] = c[1].b[3] = 121314;
    820
    821	init_pt_regs(&regs);
    822	regs.gpr[3] = (unsigned long)&c[0].a;
    823
    824	/*
    825	 * plxvp XTp,D(RA),R
    826	 * XTp = 32xTX + 2xTp
    827	 * let RA=3 R=0 D=d0||d1=0 R=0 Tp=1 TX=1
    828	 */
    829	instr = ppc_inst_prefix(PPC_RAW_PLXVP_P(34, 0, 3, 0), PPC_RAW_PLXVP_S(34, 0, 3, 0));
    830
    831	stepped = emulate_step(&regs, instr);
    832	if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
    833		show_result("plxvp", "PASS");
    834	} else {
    835		if (!cpu_has_feature(CPU_FTR_VSX))
    836			show_result("plxvp", "PASS (!CPU_FTR_VSX)");
    837		else
    838			show_result("plxvp", "FAIL");
    839	}
    840
    841	/*** pstxvp ***/
    842
    843	c[0].b[0] = 21379463;
    844	c[0].b[1] = 87;
    845	c[0].b[2] = 374234;
    846	c[0].b[3] = 4;
    847	c[1].b[0] = 90;
    848	c[1].b[1] = 122;
    849	c[1].b[2] = 555;
    850	c[1].b[3] = 32144;
    851
    852	/*
    853	 * pstxvp XSp,D(RA),R
    854	 * XSp = 32xSX + 2xSp
    855	 * let RA=3 D=d0||d1=0 R=0 Sp=1 SX=1
    856	 */
    857	instr = ppc_inst_prefix(PPC_RAW_PSTXVP_P(34, 0, 3, 0), PPC_RAW_PSTXVP_S(34, 0, 3, 0));
    858
    859	stepped = emulate_step(&regs, instr);
    860
    861	if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] &&
    862	    cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] &&
    863	    cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] &&
    864	    cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] &&
    865	    cpu_has_feature(CPU_FTR_VSX)) {
    866		show_result("pstxvp", "PASS");
    867	} else {
    868		if (!cpu_has_feature(CPU_FTR_VSX))
    869			show_result("pstxvp", "PASS (!CPU_FTR_VSX)");
    870		else
    871			show_result("pstxvp", "FAIL");
    872	}
    873}
    874#else
    875static void __init test_plxvp_pstxvp(void)
    876{
    877	show_result("plxvp", "SKIP (CONFIG_VSX is not set)");
    878	show_result("pstxvp", "SKIP (CONFIG_VSX is not set)");
    879}
    880#endif /* CONFIG_VSX */
    881
    882static void __init run_tests_load_store(void)
    883{
    884	test_ld();
    885	test_pld();
    886	test_lwz();
    887	test_plwz();
    888	test_lwzx();
    889	test_std();
    890	test_pstd();
    891	test_ldarx_stdcx();
    892	test_lfsx_stfsx();
    893	test_plfs_pstfs();
    894	test_lfdx_stfdx();
    895	test_plfd_pstfd();
    896	test_lvx_stvx();
    897	test_lxvd2x_stxvd2x();
    898	test_lxvp_stxvp();
    899	test_lxvpx_stxvpx();
    900	test_plxvp_pstxvp();
    901}
    902
    903struct compute_test {
    904	char *mnemonic;
    905	unsigned long cpu_feature;
    906	struct {
    907		char *descr;
    908		unsigned long flags;
    909		ppc_inst_t instr;
    910		struct pt_regs regs;
    911	} subtests[MAX_SUBTESTS + 1];
    912};
    913
    914/* Extreme values for si0||si1 (the MLS:D-form 34 bit immediate field) */
    915#define SI_MIN BIT(33)
    916#define SI_MAX (BIT(33) - 1)
    917#define SI_UMAX (BIT(34) - 1)
    918
    919static struct compute_test compute_tests[] = {
    920	{
    921		.mnemonic = "nop",
    922		.subtests = {
    923			{
    924				.descr = "R0 = LONG_MAX",
    925				.instr = ppc_inst(PPC_RAW_NOP()),
    926				.regs = {
    927					.gpr[0] = LONG_MAX,
    928				}
    929			}
    930		}
    931	},
    932	{
    933		.mnemonic = "setb",
    934		.cpu_feature = CPU_FTR_ARCH_300,
    935		.subtests = {
    936			{
    937				.descr = "BFA = 1, CR = GT",
    938				.instr = TEST_SETB(20, 1),
    939				.regs = {
    940					.ccr = 0x4000000,
    941				}
    942			},
    943			{
    944				.descr = "BFA = 4, CR = LT",
    945				.instr = TEST_SETB(20, 4),
    946				.regs = {
    947					.ccr = 0x8000,
    948				}
    949			},
    950			{
    951				.descr = "BFA = 5, CR = EQ",
    952				.instr = TEST_SETB(20, 5),
    953				.regs = {
    954					.ccr = 0x200,
    955				}
    956			}
    957		}
    958	},
    959	{
    960		.mnemonic = "add",
    961		.subtests = {
    962			{
    963				.descr = "RA = LONG_MIN, RB = LONG_MIN",
    964				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
    965				.regs = {
    966					.gpr[21] = LONG_MIN,
    967					.gpr[22] = LONG_MIN,
    968				}
    969			},
    970			{
    971				.descr = "RA = LONG_MIN, RB = LONG_MAX",
    972				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
    973				.regs = {
    974					.gpr[21] = LONG_MIN,
    975					.gpr[22] = LONG_MAX,
    976				}
    977			},
    978			{
    979				.descr = "RA = LONG_MAX, RB = LONG_MAX",
    980				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
    981				.regs = {
    982					.gpr[21] = LONG_MAX,
    983					.gpr[22] = LONG_MAX,
    984				}
    985			},
    986			{
    987				.descr = "RA = ULONG_MAX, RB = ULONG_MAX",
    988				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
    989				.regs = {
    990					.gpr[21] = ULONG_MAX,
    991					.gpr[22] = ULONG_MAX,
    992				}
    993			},
    994			{
    995				.descr = "RA = ULONG_MAX, RB = 0x1",
    996				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
    997				.regs = {
    998					.gpr[21] = ULONG_MAX,
    999					.gpr[22] = 0x1,
   1000				}
   1001			},
   1002			{
   1003				.descr = "RA = INT_MIN, RB = INT_MIN",
   1004				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
   1005				.regs = {
   1006					.gpr[21] = INT_MIN,
   1007					.gpr[22] = INT_MIN,
   1008				}
   1009			},
   1010			{
   1011				.descr = "RA = INT_MIN, RB = INT_MAX",
   1012				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
   1013				.regs = {
   1014					.gpr[21] = INT_MIN,
   1015					.gpr[22] = INT_MAX,
   1016				}
   1017			},
   1018			{
   1019				.descr = "RA = INT_MAX, RB = INT_MAX",
   1020				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
   1021				.regs = {
   1022					.gpr[21] = INT_MAX,
   1023					.gpr[22] = INT_MAX,
   1024				}
   1025			},
   1026			{
   1027				.descr = "RA = UINT_MAX, RB = UINT_MAX",
   1028				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
   1029				.regs = {
   1030					.gpr[21] = UINT_MAX,
   1031					.gpr[22] = UINT_MAX,
   1032				}
   1033			},
   1034			{
   1035				.descr = "RA = UINT_MAX, RB = 0x1",
   1036				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
   1037				.regs = {
   1038					.gpr[21] = UINT_MAX,
   1039					.gpr[22] = 0x1,
   1040				}
   1041			}
   1042		}
   1043	},
   1044	{
   1045		.mnemonic = "add.",
   1046		.subtests = {
   1047			{
   1048				.descr = "RA = LONG_MIN, RB = LONG_MIN",
   1049				.flags = IGNORE_CCR,
   1050				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
   1051				.regs = {
   1052					.gpr[21] = LONG_MIN,
   1053					.gpr[22] = LONG_MIN,
   1054				}
   1055			},
   1056			{
   1057				.descr = "RA = LONG_MIN, RB = LONG_MAX",
   1058				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
   1059				.regs = {
   1060					.gpr[21] = LONG_MIN,
   1061					.gpr[22] = LONG_MAX,
   1062				}
   1063			},
   1064			{
   1065				.descr = "RA = LONG_MAX, RB = LONG_MAX",
   1066				.flags = IGNORE_CCR,
   1067				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
   1068				.regs = {
   1069					.gpr[21] = LONG_MAX,
   1070					.gpr[22] = LONG_MAX,
   1071				}
   1072			},
   1073			{
   1074				.descr = "RA = ULONG_MAX, RB = ULONG_MAX",
   1075				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
   1076				.regs = {
   1077					.gpr[21] = ULONG_MAX,
   1078					.gpr[22] = ULONG_MAX,
   1079				}
   1080			},
   1081			{
   1082				.descr = "RA = ULONG_MAX, RB = 0x1",
   1083				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
   1084				.regs = {
   1085					.gpr[21] = ULONG_MAX,
   1086					.gpr[22] = 0x1,
   1087				}
   1088			},
   1089			{
   1090				.descr = "RA = INT_MIN, RB = INT_MIN",
   1091				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
   1092				.regs = {
   1093					.gpr[21] = INT_MIN,
   1094					.gpr[22] = INT_MIN,
   1095				}
   1096			},
   1097			{
   1098				.descr = "RA = INT_MIN, RB = INT_MAX",
   1099				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
   1100				.regs = {
   1101					.gpr[21] = INT_MIN,
   1102					.gpr[22] = INT_MAX,
   1103				}
   1104			},
   1105			{
   1106				.descr = "RA = INT_MAX, RB = INT_MAX",
   1107				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
   1108				.regs = {
   1109					.gpr[21] = INT_MAX,
   1110					.gpr[22] = INT_MAX,
   1111				}
   1112			},
   1113			{
   1114				.descr = "RA = UINT_MAX, RB = UINT_MAX",
   1115				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
   1116				.regs = {
   1117					.gpr[21] = UINT_MAX,
   1118					.gpr[22] = UINT_MAX,
   1119				}
   1120			},
   1121			{
   1122				.descr = "RA = UINT_MAX, RB = 0x1",
   1123				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
   1124				.regs = {
   1125					.gpr[21] = UINT_MAX,
   1126					.gpr[22] = 0x1,
   1127				}
   1128			}
   1129		}
   1130	},
   1131	{
   1132		.mnemonic = "addc",
   1133		.subtests = {
   1134			{
   1135				.descr = "RA = LONG_MIN, RB = LONG_MIN",
   1136				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
   1137				.regs = {
   1138					.gpr[21] = LONG_MIN,
   1139					.gpr[22] = LONG_MIN,
   1140				}
   1141			},
   1142			{
   1143				.descr = "RA = LONG_MIN, RB = LONG_MAX",
   1144				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
   1145				.regs = {
   1146					.gpr[21] = LONG_MIN,
   1147					.gpr[22] = LONG_MAX,
   1148				}
   1149			},
   1150			{
   1151				.descr = "RA = LONG_MAX, RB = LONG_MAX",
   1152				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
   1153				.regs = {
   1154					.gpr[21] = LONG_MAX,
   1155					.gpr[22] = LONG_MAX,
   1156				}
   1157			},
   1158			{
   1159				.descr = "RA = ULONG_MAX, RB = ULONG_MAX",
   1160				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
   1161				.regs = {
   1162					.gpr[21] = ULONG_MAX,
   1163					.gpr[22] = ULONG_MAX,
   1164				}
   1165			},
   1166			{
   1167				.descr = "RA = ULONG_MAX, RB = 0x1",
   1168				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
   1169				.regs = {
   1170					.gpr[21] = ULONG_MAX,
   1171					.gpr[22] = 0x1,
   1172				}
   1173			},
   1174			{
   1175				.descr = "RA = INT_MIN, RB = INT_MIN",
   1176				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
   1177				.regs = {
   1178					.gpr[21] = INT_MIN,
   1179					.gpr[22] = INT_MIN,
   1180				}
   1181			},
   1182			{
   1183				.descr = "RA = INT_MIN, RB = INT_MAX",
   1184				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
   1185				.regs = {
   1186					.gpr[21] = INT_MIN,
   1187					.gpr[22] = INT_MAX,
   1188				}
   1189			},
   1190			{
   1191				.descr = "RA = INT_MAX, RB = INT_MAX",
   1192				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
   1193				.regs = {
   1194					.gpr[21] = INT_MAX,
   1195					.gpr[22] = INT_MAX,
   1196				}
   1197			},
   1198			{
   1199				.descr = "RA = UINT_MAX, RB = UINT_MAX",
   1200				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
   1201				.regs = {
   1202					.gpr[21] = UINT_MAX,
   1203					.gpr[22] = UINT_MAX,
   1204				}
   1205			},
   1206			{
   1207				.descr = "RA = UINT_MAX, RB = 0x1",
   1208				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
   1209				.regs = {
   1210					.gpr[21] = UINT_MAX,
   1211					.gpr[22] = 0x1,
   1212				}
   1213			},
   1214			{
   1215				.descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
   1216				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
   1217				.regs = {
   1218					.gpr[21] = LONG_MIN | (uint)INT_MIN,
   1219					.gpr[22] = LONG_MIN | (uint)INT_MIN,
   1220				}
   1221			}
   1222		}
   1223	},
   1224	{
   1225		.mnemonic = "addc.",
   1226		.subtests = {
   1227			{
   1228				.descr = "RA = LONG_MIN, RB = LONG_MIN",
   1229				.flags = IGNORE_CCR,
   1230				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
   1231				.regs = {
   1232					.gpr[21] = LONG_MIN,
   1233					.gpr[22] = LONG_MIN,
   1234				}
   1235			},
   1236			{
   1237				.descr = "RA = LONG_MIN, RB = LONG_MAX",
   1238				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
   1239				.regs = {
   1240					.gpr[21] = LONG_MIN,
   1241					.gpr[22] = LONG_MAX,
   1242				}
   1243			},
   1244			{
   1245				.descr = "RA = LONG_MAX, RB = LONG_MAX",
   1246				.flags = IGNORE_CCR,
   1247				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
   1248				.regs = {
   1249					.gpr[21] = LONG_MAX,
   1250					.gpr[22] = LONG_MAX,
   1251				}
   1252			},
   1253			{
   1254				.descr = "RA = ULONG_MAX, RB = ULONG_MAX",
   1255				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
   1256				.regs = {
   1257					.gpr[21] = ULONG_MAX,
   1258					.gpr[22] = ULONG_MAX,
   1259				}
   1260			},
   1261			{
   1262				.descr = "RA = ULONG_MAX, RB = 0x1",
   1263				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
   1264				.regs = {
   1265					.gpr[21] = ULONG_MAX,
   1266					.gpr[22] = 0x1,
   1267				}
   1268			},
   1269			{
   1270				.descr = "RA = INT_MIN, RB = INT_MIN",
   1271				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
   1272				.regs = {
   1273					.gpr[21] = INT_MIN,
   1274					.gpr[22] = INT_MIN,
   1275				}
   1276			},
   1277			{
   1278				.descr = "RA = INT_MIN, RB = INT_MAX",
   1279				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
   1280				.regs = {
   1281					.gpr[21] = INT_MIN,
   1282					.gpr[22] = INT_MAX,
   1283				}
   1284			},
   1285			{
   1286				.descr = "RA = INT_MAX, RB = INT_MAX",
   1287				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
   1288				.regs = {
   1289					.gpr[21] = INT_MAX,
   1290					.gpr[22] = INT_MAX,
   1291				}
   1292			},
   1293			{
   1294				.descr = "RA = UINT_MAX, RB = UINT_MAX",
   1295				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
   1296				.regs = {
   1297					.gpr[21] = UINT_MAX,
   1298					.gpr[22] = UINT_MAX,
   1299				}
   1300			},
   1301			{
   1302				.descr = "RA = UINT_MAX, RB = 0x1",
   1303				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
   1304				.regs = {
   1305					.gpr[21] = UINT_MAX,
   1306					.gpr[22] = 0x1,
   1307				}
   1308			},
   1309			{
   1310				.descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
   1311				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
   1312				.regs = {
   1313					.gpr[21] = LONG_MIN | (uint)INT_MIN,
   1314					.gpr[22] = LONG_MIN | (uint)INT_MIN,
   1315				}
   1316			}
   1317		}
   1318	},
   1319	{
   1320		.mnemonic = "divde",
   1321		.subtests = {
   1322			{
   1323				.descr = "RA = LONG_MIN, RB = LONG_MIN",
   1324				.instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
   1325				.regs = {
   1326					.gpr[21] = LONG_MIN,
   1327					.gpr[22] = LONG_MIN,
   1328				}
   1329			},
   1330			{
   1331				.descr = "RA = 1L, RB = 0",
   1332				.instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
   1333				.flags = IGNORE_GPR(20),
   1334				.regs = {
   1335					.gpr[21] = 1L,
   1336					.gpr[22] = 0,
   1337				}
   1338			},
   1339			{
   1340				.descr = "RA = LONG_MIN, RB = LONG_MAX",
   1341				.instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
   1342				.regs = {
   1343					.gpr[21] = LONG_MIN,
   1344					.gpr[22] = LONG_MAX,
   1345				}
   1346			}
   1347		}
   1348	},
   1349	{
   1350		.mnemonic = "divde.",
   1351		.subtests = {
   1352			{
   1353				.descr = "RA = LONG_MIN, RB = LONG_MIN",
   1354				.instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
   1355				.regs = {
   1356					.gpr[21] = LONG_MIN,
   1357					.gpr[22] = LONG_MIN,
   1358				}
   1359			},
   1360			{
   1361				.descr = "RA = 1L, RB = 0",
   1362				.instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
   1363				.flags = IGNORE_GPR(20),
   1364				.regs = {
   1365					.gpr[21] = 1L,
   1366					.gpr[22] = 0,
   1367				}
   1368			},
   1369			{
   1370				.descr = "RA = LONG_MIN, RB = LONG_MAX",
   1371				.instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
   1372				.regs = {
   1373					.gpr[21] = LONG_MIN,
   1374					.gpr[22] = LONG_MAX,
   1375				}
   1376			}
   1377		}
   1378	},
   1379	{
   1380		.mnemonic = "divdeu",
   1381		.subtests = {
   1382			{
   1383				.descr = "RA = LONG_MIN, RB = LONG_MIN",
   1384				.instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
   1385				.flags = IGNORE_GPR(20),
   1386				.regs = {
   1387					.gpr[21] = LONG_MIN,
   1388					.gpr[22] = LONG_MIN,
   1389				}
   1390			},
   1391			{
   1392				.descr = "RA = 1L, RB = 0",
   1393				.instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
   1394				.flags = IGNORE_GPR(20),
   1395				.regs = {
   1396					.gpr[21] = 1L,
   1397					.gpr[22] = 0,
   1398				}
   1399			},
   1400			{
   1401				.descr = "RA = LONG_MIN, RB = LONG_MAX",
   1402				.instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
   1403				.regs = {
   1404					.gpr[21] = LONG_MIN,
   1405					.gpr[22] = LONG_MAX,
   1406				}
   1407			},
   1408			{
   1409				.descr = "RA = LONG_MAX - 1, RB = LONG_MAX",
   1410				.instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
   1411				.regs = {
   1412					.gpr[21] = LONG_MAX - 1,
   1413					.gpr[22] = LONG_MAX,
   1414				}
   1415			},
   1416			{
   1417				.descr = "RA = LONG_MIN + 1, RB = LONG_MIN",
   1418				.instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
   1419				.flags = IGNORE_GPR(20),
   1420				.regs = {
   1421					.gpr[21] = LONG_MIN + 1,
   1422					.gpr[22] = LONG_MIN,
   1423				}
   1424			}
   1425		}
   1426	},
   1427	{
   1428		.mnemonic = "divdeu.",
   1429		.subtests = {
   1430			{
   1431				.descr = "RA = LONG_MIN, RB = LONG_MIN",
   1432				.instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
   1433				.flags = IGNORE_GPR(20),
   1434				.regs = {
   1435					.gpr[21] = LONG_MIN,
   1436					.gpr[22] = LONG_MIN,
   1437				}
   1438			},
   1439			{
   1440				.descr = "RA = 1L, RB = 0",
   1441				.instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
   1442				.flags = IGNORE_GPR(20),
   1443				.regs = {
   1444					.gpr[21] = 1L,
   1445					.gpr[22] = 0,
   1446				}
   1447			},
   1448			{
   1449				.descr = "RA = LONG_MIN, RB = LONG_MAX",
   1450				.instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
   1451				.regs = {
   1452					.gpr[21] = LONG_MIN,
   1453					.gpr[22] = LONG_MAX,
   1454				}
   1455			},
   1456			{
   1457				.descr = "RA = LONG_MAX - 1, RB = LONG_MAX",
   1458				.instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
   1459				.regs = {
   1460					.gpr[21] = LONG_MAX - 1,
   1461					.gpr[22] = LONG_MAX,
   1462				}
   1463			},
   1464			{
   1465				.descr = "RA = LONG_MIN + 1, RB = LONG_MIN",
   1466				.instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
   1467				.flags = IGNORE_GPR(20),
   1468				.regs = {
   1469					.gpr[21] = LONG_MIN + 1,
   1470					.gpr[22] = LONG_MIN,
   1471				}
   1472			}
   1473		}
   1474	},
   1475	{
   1476		.mnemonic = "paddi",
   1477		.cpu_feature = CPU_FTR_ARCH_31,
   1478		.subtests = {
   1479			{
   1480				.descr = "RA = LONG_MIN, SI = SI_MIN, R = 0",
   1481				.instr = TEST_PADDI(21, 22, SI_MIN, 0),
   1482				.regs = {
   1483					.gpr[21] = 0,
   1484					.gpr[22] = LONG_MIN,
   1485				}
   1486			},
   1487			{
   1488				.descr = "RA = LONG_MIN, SI = SI_MAX, R = 0",
   1489				.instr = TEST_PADDI(21, 22, SI_MAX, 0),
   1490				.regs = {
   1491					.gpr[21] = 0,
   1492					.gpr[22] = LONG_MIN,
   1493				}
   1494			},
   1495			{
   1496				.descr = "RA = LONG_MAX, SI = SI_MAX, R = 0",
   1497				.instr = TEST_PADDI(21, 22, SI_MAX, 0),
   1498				.regs = {
   1499					.gpr[21] = 0,
   1500					.gpr[22] = LONG_MAX,
   1501				}
   1502			},
   1503			{
   1504				.descr = "RA = ULONG_MAX, SI = SI_UMAX, R = 0",
   1505				.instr = TEST_PADDI(21, 22, SI_UMAX, 0),
   1506				.regs = {
   1507					.gpr[21] = 0,
   1508					.gpr[22] = ULONG_MAX,
   1509				}
   1510			},
   1511			{
   1512				.descr = "RA = ULONG_MAX, SI = 0x1, R = 0",
   1513				.instr = TEST_PADDI(21, 22, 0x1, 0),
   1514				.regs = {
   1515					.gpr[21] = 0,
   1516					.gpr[22] = ULONG_MAX,
   1517				}
   1518			},
   1519			{
   1520				.descr = "RA = INT_MIN, SI = SI_MIN, R = 0",
   1521				.instr = TEST_PADDI(21, 22, SI_MIN, 0),
   1522				.regs = {
   1523					.gpr[21] = 0,
   1524					.gpr[22] = INT_MIN,
   1525				}
   1526			},
   1527			{
   1528				.descr = "RA = INT_MIN, SI = SI_MAX, R = 0",
   1529				.instr = TEST_PADDI(21, 22, SI_MAX, 0),
   1530				.regs = {
   1531					.gpr[21] = 0,
   1532					.gpr[22] = INT_MIN,
   1533				}
   1534			},
   1535			{
   1536				.descr = "RA = INT_MAX, SI = SI_MAX, R = 0",
   1537				.instr = TEST_PADDI(21, 22, SI_MAX, 0),
   1538				.regs = {
   1539					.gpr[21] = 0,
   1540					.gpr[22] = INT_MAX,
   1541				}
   1542			},
   1543			{
   1544				.descr = "RA = UINT_MAX, SI = 0x1, R = 0",
   1545				.instr = TEST_PADDI(21, 22, 0x1, 0),
   1546				.regs = {
   1547					.gpr[21] = 0,
   1548					.gpr[22] = UINT_MAX,
   1549				}
   1550			},
   1551			{
   1552				.descr = "RA = UINT_MAX, SI = SI_MAX, R = 0",
   1553				.instr = TEST_PADDI(21, 22, SI_MAX, 0),
   1554				.regs = {
   1555					.gpr[21] = 0,
   1556					.gpr[22] = UINT_MAX,
   1557				}
   1558			},
   1559			{
   1560				.descr = "RA is r0, SI = SI_MIN, R = 0",
   1561				.instr = TEST_PADDI(21, 0, SI_MIN, 0),
   1562				.regs = {
   1563					.gpr[21] = 0x0,
   1564				}
   1565			},
   1566			{
   1567				.descr = "RA = 0, SI = SI_MIN, R = 0",
   1568				.instr = TEST_PADDI(21, 22, SI_MIN, 0),
   1569				.regs = {
   1570					.gpr[21] = 0x0,
   1571					.gpr[22] = 0x0,
   1572				}
   1573			},
   1574			{
   1575				.descr = "RA is r0, SI = 0, R = 1",
   1576				.instr = TEST_PADDI(21, 0, 0, 1),
   1577				.regs = {
   1578					.gpr[21] = 0,
   1579				}
   1580			},
   1581			{
   1582				.descr = "RA is r0, SI = SI_MIN, R = 1",
   1583				.instr = TEST_PADDI(21, 0, SI_MIN, 1),
   1584				.regs = {
   1585					.gpr[21] = 0,
   1586				}
   1587			},
   1588			/* Invalid instruction form with R = 1 and RA != 0 */
   1589			{
   1590				.descr = "RA = R22(0), SI = 0, R = 1",
   1591				.instr = TEST_PADDI(21, 22, 0, 1),
   1592				.flags = NEGATIVE_TEST,
   1593				.regs = {
   1594					.gpr[21] = 0,
   1595					.gpr[22] = 0,
   1596				}
   1597			}
   1598		}
   1599	}
   1600};
   1601
   1602static int __init emulate_compute_instr(struct pt_regs *regs,
   1603					ppc_inst_t instr,
   1604					bool negative)
   1605{
   1606	int analysed;
   1607	struct instruction_op op;
   1608
   1609	if (!regs || !ppc_inst_val(instr))
   1610		return -EINVAL;
   1611
   1612	/* This is not a return frame regs */
   1613	regs->nip = patch_site_addr(&patch__exec_instr);
   1614
   1615	analysed = analyse_instr(&op, regs, instr);
   1616	if (analysed != 1 || GETTYPE(op.type) != COMPUTE) {
   1617		if (negative)
   1618			return -EFAULT;
   1619		pr_info("emulation failed, instruction = %s\n", ppc_inst_as_str(instr));
   1620		return -EFAULT;
   1621	}
   1622	if (analysed == 1 && negative)
   1623		pr_info("negative test failed, instruction = %s\n", ppc_inst_as_str(instr));
   1624	if (!negative)
   1625		emulate_update_regs(regs, &op);
   1626	return 0;
   1627}
   1628
   1629static int __init execute_compute_instr(struct pt_regs *regs,
   1630					ppc_inst_t instr)
   1631{
   1632	extern int exec_instr(struct pt_regs *regs);
   1633
   1634	if (!regs || !ppc_inst_val(instr))
   1635		return -EINVAL;
   1636
   1637	/* Patch the NOP with the actual instruction */
   1638	patch_instruction_site(&patch__exec_instr, instr);
   1639	if (exec_instr(regs)) {
   1640		pr_info("execution failed, instruction = %s\n", ppc_inst_as_str(instr));
   1641		return -EFAULT;
   1642	}
   1643
   1644	return 0;
   1645}
   1646
   1647#define gpr_mismatch(gprn, exp, got)	\
   1648	pr_info("GPR%u mismatch, exp = 0x%016lx, got = 0x%016lx\n",	\
   1649		gprn, exp, got)
   1650
   1651#define reg_mismatch(name, exp, got)	\
   1652	pr_info("%s mismatch, exp = 0x%016lx, got = 0x%016lx\n",	\
   1653		name, exp, got)
   1654
   1655static void __init run_tests_compute(void)
   1656{
   1657	unsigned long flags;
   1658	struct compute_test *test;
   1659	struct pt_regs *regs, exp, got;
   1660	unsigned int i, j, k;
   1661	ppc_inst_t instr;
   1662	bool ignore_gpr, ignore_xer, ignore_ccr, passed, rc, negative;
   1663
   1664	for (i = 0; i < ARRAY_SIZE(compute_tests); i++) {
   1665		test = &compute_tests[i];
   1666
   1667		if (test->cpu_feature && !early_cpu_has_feature(test->cpu_feature)) {
   1668			show_result(test->mnemonic, "SKIP (!CPU_FTR)");
   1669			continue;
   1670		}
   1671
   1672		for (j = 0; j < MAX_SUBTESTS && test->subtests[j].descr; j++) {
   1673			instr = test->subtests[j].instr;
   1674			flags = test->subtests[j].flags;
   1675			regs = &test->subtests[j].regs;
   1676			negative = flags & NEGATIVE_TEST;
   1677			ignore_xer = flags & IGNORE_XER;
   1678			ignore_ccr = flags & IGNORE_CCR;
   1679			passed = true;
   1680
   1681			memcpy(&exp, regs, sizeof(struct pt_regs));
   1682			memcpy(&got, regs, sizeof(struct pt_regs));
   1683
   1684			/*
   1685			 * Set a compatible MSR value explicitly to ensure
   1686			 * that XER and CR bits are updated appropriately
   1687			 */
   1688			exp.msr = MSR_KERNEL;
   1689			got.msr = MSR_KERNEL;
   1690
   1691			rc = emulate_compute_instr(&got, instr, negative) != 0;
   1692			if (negative) {
   1693				/* skip executing instruction */
   1694				passed = rc;
   1695				goto print;
   1696			} else if (rc || execute_compute_instr(&exp, instr)) {
   1697				passed = false;
   1698				goto print;
   1699			}
   1700
   1701			/* Verify GPR values */
   1702			for (k = 0; k < 32; k++) {
   1703				ignore_gpr = flags & IGNORE_GPR(k);
   1704				if (!ignore_gpr && exp.gpr[k] != got.gpr[k]) {
   1705					passed = false;
   1706					gpr_mismatch(k, exp.gpr[k], got.gpr[k]);
   1707				}
   1708			}
   1709
   1710			/* Verify LR value */
   1711			if (exp.link != got.link) {
   1712				passed = false;
   1713				reg_mismatch("LR", exp.link, got.link);
   1714			}
   1715
   1716			/* Verify XER value */
   1717			if (!ignore_xer && exp.xer != got.xer) {
   1718				passed = false;
   1719				reg_mismatch("XER", exp.xer, got.xer);
   1720			}
   1721
   1722			/* Verify CR value */
   1723			if (!ignore_ccr && exp.ccr != got.ccr) {
   1724				passed = false;
   1725				reg_mismatch("CR", exp.ccr, got.ccr);
   1726			}
   1727
   1728print:
   1729			show_result_with_descr(test->mnemonic,
   1730					       test->subtests[j].descr,
   1731					       passed ? "PASS" : "FAIL");
   1732		}
   1733	}
   1734}
   1735
   1736static int __init test_emulate_step(void)
   1737{
   1738	printk(KERN_INFO "Running instruction emulation self-tests ...\n");
   1739	run_tests_load_store();
   1740	run_tests_compute();
   1741
   1742	return 0;
   1743}
   1744late_initcall(test_emulate_step);