14ceae137SRavi Bangoria /* 284022ac1SSandipan Das * Simple sanity tests for instruction emulation infrastructure. 34ceae137SRavi Bangoria * 44ceae137SRavi Bangoria * Copyright IBM Corp. 2016 54ceae137SRavi Bangoria * 64ceae137SRavi Bangoria * This program is free software; you can redistribute it and/or modify 74ceae137SRavi Bangoria * it under the terms of the GNU General Public License as published by 84ceae137SRavi Bangoria * the Free Software Foundation; either version 2 of the License, or 94ceae137SRavi Bangoria * (at your option) any later version. 104ceae137SRavi Bangoria */ 114ceae137SRavi Bangoria 124ceae137SRavi Bangoria #define pr_fmt(fmt) "emulate_step_test: " fmt 134ceae137SRavi Bangoria 144ceae137SRavi Bangoria #include <linux/ptrace.h> 154ceae137SRavi Bangoria #include <asm/sstep.h> 164ceae137SRavi Bangoria #include <asm/ppc-opcode.h> 1784022ac1SSandipan Das #include <asm/code-patching.h> 184ceae137SRavi Bangoria 194ceae137SRavi Bangoria #define IMM_L(i) ((uintptr_t)(i) & 0xffff) 204ceae137SRavi Bangoria 214ceae137SRavi Bangoria /* 224ceae137SRavi Bangoria * Defined with TEST_ prefix so it does not conflict with other 234ceae137SRavi Bangoria * definitions. 244ceae137SRavi Bangoria */ 254ceae137SRavi Bangoria #define TEST_LD(r, base, i) (PPC_INST_LD | ___PPC_RT(r) | \ 264ceae137SRavi Bangoria ___PPC_RA(base) | IMM_L(i)) 274ceae137SRavi Bangoria #define TEST_LWZ(r, base, i) (PPC_INST_LWZ | ___PPC_RT(r) | \ 284ceae137SRavi Bangoria ___PPC_RA(base) | IMM_L(i)) 294ceae137SRavi Bangoria #define TEST_LWZX(t, a, b) (PPC_INST_LWZX | ___PPC_RT(t) | \ 304ceae137SRavi Bangoria ___PPC_RA(a) | ___PPC_RB(b)) 314ceae137SRavi Bangoria #define TEST_STD(r, base, i) (PPC_INST_STD | ___PPC_RS(r) | \ 324ceae137SRavi Bangoria ___PPC_RA(base) | ((i) & 0xfffc)) 334ceae137SRavi Bangoria #define TEST_LDARX(t, a, b, eh) (PPC_INST_LDARX | ___PPC_RT(t) | \ 344ceae137SRavi Bangoria ___PPC_RA(a) | ___PPC_RB(b) | \ 354ceae137SRavi Bangoria __PPC_EH(eh)) 364ceae137SRavi Bangoria #define TEST_STDCX(s, a, b) (PPC_INST_STDCX | ___PPC_RS(s) | \ 374ceae137SRavi Bangoria ___PPC_RA(a) | ___PPC_RB(b)) 384ceae137SRavi Bangoria #define TEST_LFSX(t, a, b) (PPC_INST_LFSX | ___PPC_RT(t) | \ 394ceae137SRavi Bangoria ___PPC_RA(a) | ___PPC_RB(b)) 404ceae137SRavi Bangoria #define TEST_STFSX(s, a, b) (PPC_INST_STFSX | ___PPC_RS(s) | \ 414ceae137SRavi Bangoria ___PPC_RA(a) | ___PPC_RB(b)) 424ceae137SRavi Bangoria #define TEST_LFDX(t, a, b) (PPC_INST_LFDX | ___PPC_RT(t) | \ 434ceae137SRavi Bangoria ___PPC_RA(a) | ___PPC_RB(b)) 444ceae137SRavi Bangoria #define TEST_STFDX(s, a, b) (PPC_INST_STFDX | ___PPC_RS(s) | \ 454ceae137SRavi Bangoria ___PPC_RA(a) | ___PPC_RB(b)) 464ceae137SRavi Bangoria #define TEST_LVX(t, a, b) (PPC_INST_LVX | ___PPC_RT(t) | \ 474ceae137SRavi Bangoria ___PPC_RA(a) | ___PPC_RB(b)) 484ceae137SRavi Bangoria #define TEST_STVX(s, a, b) (PPC_INST_STVX | ___PPC_RS(s) | \ 494ceae137SRavi Bangoria ___PPC_RA(a) | ___PPC_RB(b)) 504ceae137SRavi Bangoria #define TEST_LXVD2X(s, a, b) (PPC_INST_LXVD2X | VSX_XX1((s), R##a, R##b)) 514ceae137SRavi Bangoria #define TEST_STXVD2X(s, a, b) (PPC_INST_STXVD2X | VSX_XX1((s), R##a, R##b)) 52*44dea178SSandipan Das #define TEST_ADD(t, a, b) (PPC_INST_ADD | ___PPC_RT(t) | \ 53*44dea178SSandipan Das ___PPC_RA(a) | ___PPC_RB(b)) 54*44dea178SSandipan Das #define TEST_ADD_DOT(t, a, b) (PPC_INST_ADD | ___PPC_RT(t) | \ 55*44dea178SSandipan Das ___PPC_RA(a) | ___PPC_RB(b) | 0x1) 564ceae137SRavi Bangoria 5784022ac1SSandipan Das #define MAX_SUBTESTS 16 5884022ac1SSandipan Das 5984022ac1SSandipan Das #define IGNORE_GPR(n) (0x1UL << (n)) 6084022ac1SSandipan Das #define IGNORE_XER (0x1UL << 32) 6184022ac1SSandipan Das #define IGNORE_CCR (0x1UL << 33) 624ceae137SRavi Bangoria 634ceae137SRavi Bangoria static void __init init_pt_regs(struct pt_regs *regs) 644ceae137SRavi Bangoria { 654ceae137SRavi Bangoria static unsigned long msr; 664ceae137SRavi Bangoria static bool msr_cached; 674ceae137SRavi Bangoria 684ceae137SRavi Bangoria memset(regs, 0, sizeof(struct pt_regs)); 694ceae137SRavi Bangoria 704ceae137SRavi Bangoria if (likely(msr_cached)) { 714ceae137SRavi Bangoria regs->msr = msr; 724ceae137SRavi Bangoria return; 734ceae137SRavi Bangoria } 744ceae137SRavi Bangoria 754ceae137SRavi Bangoria asm volatile("mfmsr %0" : "=r"(regs->msr)); 764ceae137SRavi Bangoria 774ceae137SRavi Bangoria regs->msr |= MSR_FP; 784ceae137SRavi Bangoria regs->msr |= MSR_VEC; 794ceae137SRavi Bangoria regs->msr |= MSR_VSX; 804ceae137SRavi Bangoria 814ceae137SRavi Bangoria msr = regs->msr; 824ceae137SRavi Bangoria msr_cached = true; 834ceae137SRavi Bangoria } 844ceae137SRavi Bangoria 8584022ac1SSandipan Das static void __init show_result(char *mnemonic, char *result) 864ceae137SRavi Bangoria { 8784022ac1SSandipan Das pr_info("%-14s : %s\n", mnemonic, result); 8884022ac1SSandipan Das } 8984022ac1SSandipan Das 9084022ac1SSandipan Das static void __init show_result_with_descr(char *mnemonic, char *descr, 9184022ac1SSandipan Das char *result) 9284022ac1SSandipan Das { 9384022ac1SSandipan Das pr_info("%-14s : %-50s %s\n", mnemonic, descr, result); 944ceae137SRavi Bangoria } 954ceae137SRavi Bangoria 964ceae137SRavi Bangoria static void __init test_ld(void) 974ceae137SRavi Bangoria { 984ceae137SRavi Bangoria struct pt_regs regs; 994ceae137SRavi Bangoria unsigned long a = 0x23; 1004ceae137SRavi Bangoria int stepped = -1; 1014ceae137SRavi Bangoria 1024ceae137SRavi Bangoria init_pt_regs(®s); 1034ceae137SRavi Bangoria regs.gpr[3] = (unsigned long) &a; 1044ceae137SRavi Bangoria 1054ceae137SRavi Bangoria /* ld r5, 0(r3) */ 1064ceae137SRavi Bangoria stepped = emulate_step(®s, TEST_LD(5, 3, 0)); 1074ceae137SRavi Bangoria 1084ceae137SRavi Bangoria if (stepped == 1 && regs.gpr[5] == a) 1094ceae137SRavi Bangoria show_result("ld", "PASS"); 1104ceae137SRavi Bangoria else 1114ceae137SRavi Bangoria show_result("ld", "FAIL"); 1124ceae137SRavi Bangoria } 1134ceae137SRavi Bangoria 1144ceae137SRavi Bangoria static void __init test_lwz(void) 1154ceae137SRavi Bangoria { 1164ceae137SRavi Bangoria struct pt_regs regs; 1174ceae137SRavi Bangoria unsigned int a = 0x4545; 1184ceae137SRavi Bangoria int stepped = -1; 1194ceae137SRavi Bangoria 1204ceae137SRavi Bangoria init_pt_regs(®s); 1214ceae137SRavi Bangoria regs.gpr[3] = (unsigned long) &a; 1224ceae137SRavi Bangoria 1234ceae137SRavi Bangoria /* lwz r5, 0(r3) */ 1244ceae137SRavi Bangoria stepped = emulate_step(®s, TEST_LWZ(5, 3, 0)); 1254ceae137SRavi Bangoria 1264ceae137SRavi Bangoria if (stepped == 1 && regs.gpr[5] == a) 1274ceae137SRavi Bangoria show_result("lwz", "PASS"); 1284ceae137SRavi Bangoria else 1294ceae137SRavi Bangoria show_result("lwz", "FAIL"); 1304ceae137SRavi Bangoria } 1314ceae137SRavi Bangoria 1324ceae137SRavi Bangoria static void __init test_lwzx(void) 1334ceae137SRavi Bangoria { 1344ceae137SRavi Bangoria struct pt_regs regs; 1354ceae137SRavi Bangoria unsigned int a[3] = {0x0, 0x0, 0x1234}; 1364ceae137SRavi Bangoria int stepped = -1; 1374ceae137SRavi Bangoria 1384ceae137SRavi Bangoria init_pt_regs(®s); 1394ceae137SRavi Bangoria regs.gpr[3] = (unsigned long) a; 1404ceae137SRavi Bangoria regs.gpr[4] = 8; 1414ceae137SRavi Bangoria regs.gpr[5] = 0x8765; 1424ceae137SRavi Bangoria 1434ceae137SRavi Bangoria /* lwzx r5, r3, r4 */ 1444ceae137SRavi Bangoria stepped = emulate_step(®s, TEST_LWZX(5, 3, 4)); 1454ceae137SRavi Bangoria if (stepped == 1 && regs.gpr[5] == a[2]) 1464ceae137SRavi Bangoria show_result("lwzx", "PASS"); 1474ceae137SRavi Bangoria else 1484ceae137SRavi Bangoria show_result("lwzx", "FAIL"); 1494ceae137SRavi Bangoria } 1504ceae137SRavi Bangoria 1514ceae137SRavi Bangoria static void __init test_std(void) 1524ceae137SRavi Bangoria { 1534ceae137SRavi Bangoria struct pt_regs regs; 1544ceae137SRavi Bangoria unsigned long a = 0x1234; 1554ceae137SRavi Bangoria int stepped = -1; 1564ceae137SRavi Bangoria 1574ceae137SRavi Bangoria init_pt_regs(®s); 1584ceae137SRavi Bangoria regs.gpr[3] = (unsigned long) &a; 1594ceae137SRavi Bangoria regs.gpr[5] = 0x5678; 1604ceae137SRavi Bangoria 1614ceae137SRavi Bangoria /* std r5, 0(r3) */ 1624ceae137SRavi Bangoria stepped = emulate_step(®s, TEST_STD(5, 3, 0)); 1634ceae137SRavi Bangoria if (stepped == 1 || regs.gpr[5] == a) 1644ceae137SRavi Bangoria show_result("std", "PASS"); 1654ceae137SRavi Bangoria else 1664ceae137SRavi Bangoria show_result("std", "FAIL"); 1674ceae137SRavi Bangoria } 1684ceae137SRavi Bangoria 1694ceae137SRavi Bangoria static void __init test_ldarx_stdcx(void) 1704ceae137SRavi Bangoria { 1714ceae137SRavi Bangoria struct pt_regs regs; 1724ceae137SRavi Bangoria unsigned long a = 0x1234; 1734ceae137SRavi Bangoria int stepped = -1; 1744ceae137SRavi Bangoria unsigned long cr0_eq = 0x1 << 29; /* eq bit of CR0 */ 1754ceae137SRavi Bangoria 1764ceae137SRavi Bangoria init_pt_regs(®s); 1774ceae137SRavi Bangoria asm volatile("mfcr %0" : "=r"(regs.ccr)); 1784ceae137SRavi Bangoria 1794ceae137SRavi Bangoria 1804ceae137SRavi Bangoria /*** ldarx ***/ 1814ceae137SRavi Bangoria 1824ceae137SRavi Bangoria regs.gpr[3] = (unsigned long) &a; 1834ceae137SRavi Bangoria regs.gpr[4] = 0; 1844ceae137SRavi Bangoria regs.gpr[5] = 0x5678; 1854ceae137SRavi Bangoria 1864ceae137SRavi Bangoria /* ldarx r5, r3, r4, 0 */ 1874ceae137SRavi Bangoria stepped = emulate_step(®s, TEST_LDARX(5, 3, 4, 0)); 1884ceae137SRavi Bangoria 1894ceae137SRavi Bangoria /* 1904ceae137SRavi Bangoria * Don't touch 'a' here. Touching 'a' can do Load/store 1914ceae137SRavi Bangoria * of 'a' which result in failure of subsequent stdcx. 1924ceae137SRavi Bangoria * Instead, use hardcoded value for comparison. 1934ceae137SRavi Bangoria */ 1944ceae137SRavi Bangoria if (stepped <= 0 || regs.gpr[5] != 0x1234) { 1954ceae137SRavi Bangoria show_result("ldarx / stdcx.", "FAIL (ldarx)"); 1964ceae137SRavi Bangoria return; 1974ceae137SRavi Bangoria } 1984ceae137SRavi Bangoria 1994ceae137SRavi Bangoria 2004ceae137SRavi Bangoria /*** stdcx. ***/ 2014ceae137SRavi Bangoria 2024ceae137SRavi Bangoria regs.gpr[5] = 0x9ABC; 2034ceae137SRavi Bangoria 2044ceae137SRavi Bangoria /* stdcx. r5, r3, r4 */ 2054ceae137SRavi Bangoria stepped = emulate_step(®s, TEST_STDCX(5, 3, 4)); 2064ceae137SRavi Bangoria 2074ceae137SRavi Bangoria /* 2084ceae137SRavi Bangoria * Two possible scenarios that indicates successful emulation 2094ceae137SRavi Bangoria * of stdcx. : 2104ceae137SRavi Bangoria * 1. Reservation is active and store is performed. In this 2114ceae137SRavi Bangoria * case cr0.eq bit will be set to 1. 2124ceae137SRavi Bangoria * 2. Reservation is not active and store is not performed. 2134ceae137SRavi Bangoria * In this case cr0.eq bit will be set to 0. 2144ceae137SRavi Bangoria */ 2154ceae137SRavi Bangoria if (stepped == 1 && ((regs.gpr[5] == a && (regs.ccr & cr0_eq)) 2164ceae137SRavi Bangoria || (regs.gpr[5] != a && !(regs.ccr & cr0_eq)))) 2174ceae137SRavi Bangoria show_result("ldarx / stdcx.", "PASS"); 2184ceae137SRavi Bangoria else 2194ceae137SRavi Bangoria show_result("ldarx / stdcx.", "FAIL (stdcx.)"); 2204ceae137SRavi Bangoria } 2214ceae137SRavi Bangoria 2224ceae137SRavi Bangoria #ifdef CONFIG_PPC_FPU 2234ceae137SRavi Bangoria static void __init test_lfsx_stfsx(void) 2244ceae137SRavi Bangoria { 2254ceae137SRavi Bangoria struct pt_regs regs; 2264ceae137SRavi Bangoria union { 2274ceae137SRavi Bangoria float a; 2284ceae137SRavi Bangoria int b; 2294ceae137SRavi Bangoria } c; 2304ceae137SRavi Bangoria int cached_b; 2314ceae137SRavi Bangoria int stepped = -1; 2324ceae137SRavi Bangoria 2334ceae137SRavi Bangoria init_pt_regs(®s); 2344ceae137SRavi Bangoria 2354ceae137SRavi Bangoria 2364ceae137SRavi Bangoria /*** lfsx ***/ 2374ceae137SRavi Bangoria 2384ceae137SRavi Bangoria c.a = 123.45; 2394ceae137SRavi Bangoria cached_b = c.b; 2404ceae137SRavi Bangoria 2414ceae137SRavi Bangoria regs.gpr[3] = (unsigned long) &c.a; 2424ceae137SRavi Bangoria regs.gpr[4] = 0; 2434ceae137SRavi Bangoria 2444ceae137SRavi Bangoria /* lfsx frt10, r3, r4 */ 2454ceae137SRavi Bangoria stepped = emulate_step(®s, TEST_LFSX(10, 3, 4)); 2464ceae137SRavi Bangoria 2474ceae137SRavi Bangoria if (stepped == 1) 2484ceae137SRavi Bangoria show_result("lfsx", "PASS"); 2494ceae137SRavi Bangoria else 2504ceae137SRavi Bangoria show_result("lfsx", "FAIL"); 2514ceae137SRavi Bangoria 2524ceae137SRavi Bangoria 2534ceae137SRavi Bangoria /*** stfsx ***/ 2544ceae137SRavi Bangoria 2554ceae137SRavi Bangoria c.a = 678.91; 2564ceae137SRavi Bangoria 2574ceae137SRavi Bangoria /* stfsx frs10, r3, r4 */ 2584ceae137SRavi Bangoria stepped = emulate_step(®s, TEST_STFSX(10, 3, 4)); 2594ceae137SRavi Bangoria 2604ceae137SRavi Bangoria if (stepped == 1 && c.b == cached_b) 2614ceae137SRavi Bangoria show_result("stfsx", "PASS"); 2624ceae137SRavi Bangoria else 2634ceae137SRavi Bangoria show_result("stfsx", "FAIL"); 2644ceae137SRavi Bangoria } 2654ceae137SRavi Bangoria 2664ceae137SRavi Bangoria static void __init test_lfdx_stfdx(void) 2674ceae137SRavi Bangoria { 2684ceae137SRavi Bangoria struct pt_regs regs; 2694ceae137SRavi Bangoria union { 2704ceae137SRavi Bangoria double a; 2714ceae137SRavi Bangoria long b; 2724ceae137SRavi Bangoria } c; 2734ceae137SRavi Bangoria long cached_b; 2744ceae137SRavi Bangoria int stepped = -1; 2754ceae137SRavi Bangoria 2764ceae137SRavi Bangoria init_pt_regs(®s); 2774ceae137SRavi Bangoria 2784ceae137SRavi Bangoria 2794ceae137SRavi Bangoria /*** lfdx ***/ 2804ceae137SRavi Bangoria 2814ceae137SRavi Bangoria c.a = 123456.78; 2824ceae137SRavi Bangoria cached_b = c.b; 2834ceae137SRavi Bangoria 2844ceae137SRavi Bangoria regs.gpr[3] = (unsigned long) &c.a; 2854ceae137SRavi Bangoria regs.gpr[4] = 0; 2864ceae137SRavi Bangoria 2874ceae137SRavi Bangoria /* lfdx frt10, r3, r4 */ 2884ceae137SRavi Bangoria stepped = emulate_step(®s, TEST_LFDX(10, 3, 4)); 2894ceae137SRavi Bangoria 2904ceae137SRavi Bangoria if (stepped == 1) 2914ceae137SRavi Bangoria show_result("lfdx", "PASS"); 2924ceae137SRavi Bangoria else 2934ceae137SRavi Bangoria show_result("lfdx", "FAIL"); 2944ceae137SRavi Bangoria 2954ceae137SRavi Bangoria 2964ceae137SRavi Bangoria /*** stfdx ***/ 2974ceae137SRavi Bangoria 2984ceae137SRavi Bangoria c.a = 987654.32; 2994ceae137SRavi Bangoria 3004ceae137SRavi Bangoria /* stfdx frs10, r3, r4 */ 3014ceae137SRavi Bangoria stepped = emulate_step(®s, TEST_STFDX(10, 3, 4)); 3024ceae137SRavi Bangoria 3034ceae137SRavi Bangoria if (stepped == 1 && c.b == cached_b) 3044ceae137SRavi Bangoria show_result("stfdx", "PASS"); 3054ceae137SRavi Bangoria else 3064ceae137SRavi Bangoria show_result("stfdx", "FAIL"); 3074ceae137SRavi Bangoria } 3084ceae137SRavi Bangoria #else 3094ceae137SRavi Bangoria static void __init test_lfsx_stfsx(void) 3104ceae137SRavi Bangoria { 3114ceae137SRavi Bangoria show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)"); 3124ceae137SRavi Bangoria show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)"); 3134ceae137SRavi Bangoria } 3144ceae137SRavi Bangoria 3154ceae137SRavi Bangoria static void __init test_lfdx_stfdx(void) 3164ceae137SRavi Bangoria { 3174ceae137SRavi Bangoria show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)"); 3184ceae137SRavi Bangoria show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)"); 3194ceae137SRavi Bangoria } 3204ceae137SRavi Bangoria #endif /* CONFIG_PPC_FPU */ 3214ceae137SRavi Bangoria 3224ceae137SRavi Bangoria #ifdef CONFIG_ALTIVEC 3234ceae137SRavi Bangoria static void __init test_lvx_stvx(void) 3244ceae137SRavi Bangoria { 3254ceae137SRavi Bangoria struct pt_regs regs; 3264ceae137SRavi Bangoria union { 3274ceae137SRavi Bangoria vector128 a; 3284ceae137SRavi Bangoria u32 b[4]; 3294ceae137SRavi Bangoria } c; 3304ceae137SRavi Bangoria u32 cached_b[4]; 3314ceae137SRavi Bangoria int stepped = -1; 3324ceae137SRavi Bangoria 3334ceae137SRavi Bangoria init_pt_regs(®s); 3344ceae137SRavi Bangoria 3354ceae137SRavi Bangoria 3364ceae137SRavi Bangoria /*** lvx ***/ 3374ceae137SRavi Bangoria 3384ceae137SRavi Bangoria cached_b[0] = c.b[0] = 923745; 3394ceae137SRavi Bangoria cached_b[1] = c.b[1] = 2139478; 3404ceae137SRavi Bangoria cached_b[2] = c.b[2] = 9012; 3414ceae137SRavi Bangoria cached_b[3] = c.b[3] = 982134; 3424ceae137SRavi Bangoria 3434ceae137SRavi Bangoria regs.gpr[3] = (unsigned long) &c.a; 3444ceae137SRavi Bangoria regs.gpr[4] = 0; 3454ceae137SRavi Bangoria 3464ceae137SRavi Bangoria /* lvx vrt10, r3, r4 */ 3474ceae137SRavi Bangoria stepped = emulate_step(®s, TEST_LVX(10, 3, 4)); 3484ceae137SRavi Bangoria 3494ceae137SRavi Bangoria if (stepped == 1) 3504ceae137SRavi Bangoria show_result("lvx", "PASS"); 3514ceae137SRavi Bangoria else 3524ceae137SRavi Bangoria show_result("lvx", "FAIL"); 3534ceae137SRavi Bangoria 3544ceae137SRavi Bangoria 3554ceae137SRavi Bangoria /*** stvx ***/ 3564ceae137SRavi Bangoria 3574ceae137SRavi Bangoria c.b[0] = 4987513; 3584ceae137SRavi Bangoria c.b[1] = 84313948; 3594ceae137SRavi Bangoria c.b[2] = 71; 3604ceae137SRavi Bangoria c.b[3] = 498532; 3614ceae137SRavi Bangoria 3624ceae137SRavi Bangoria /* stvx vrs10, r3, r4 */ 3634ceae137SRavi Bangoria stepped = emulate_step(®s, TEST_STVX(10, 3, 4)); 3644ceae137SRavi Bangoria 3654ceae137SRavi Bangoria if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] && 3664ceae137SRavi Bangoria cached_b[2] == c.b[2] && cached_b[3] == c.b[3]) 3674ceae137SRavi Bangoria show_result("stvx", "PASS"); 3684ceae137SRavi Bangoria else 3694ceae137SRavi Bangoria show_result("stvx", "FAIL"); 3704ceae137SRavi Bangoria } 3714ceae137SRavi Bangoria #else 3724ceae137SRavi Bangoria static void __init test_lvx_stvx(void) 3734ceae137SRavi Bangoria { 3744ceae137SRavi Bangoria show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)"); 3754ceae137SRavi Bangoria show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)"); 3764ceae137SRavi Bangoria } 3774ceae137SRavi Bangoria #endif /* CONFIG_ALTIVEC */ 3784ceae137SRavi Bangoria 3794ceae137SRavi Bangoria #ifdef CONFIG_VSX 3804ceae137SRavi Bangoria static void __init test_lxvd2x_stxvd2x(void) 3814ceae137SRavi Bangoria { 3824ceae137SRavi Bangoria struct pt_regs regs; 3834ceae137SRavi Bangoria union { 3844ceae137SRavi Bangoria vector128 a; 3854ceae137SRavi Bangoria u32 b[4]; 3864ceae137SRavi Bangoria } c; 3874ceae137SRavi Bangoria u32 cached_b[4]; 3884ceae137SRavi Bangoria int stepped = -1; 3894ceae137SRavi Bangoria 3904ceae137SRavi Bangoria init_pt_regs(®s); 3914ceae137SRavi Bangoria 3924ceae137SRavi Bangoria 3934ceae137SRavi Bangoria /*** lxvd2x ***/ 3944ceae137SRavi Bangoria 3954ceae137SRavi Bangoria cached_b[0] = c.b[0] = 18233; 3964ceae137SRavi Bangoria cached_b[1] = c.b[1] = 34863571; 3974ceae137SRavi Bangoria cached_b[2] = c.b[2] = 834; 3984ceae137SRavi Bangoria cached_b[3] = c.b[3] = 6138911; 3994ceae137SRavi Bangoria 4004ceae137SRavi Bangoria regs.gpr[3] = (unsigned long) &c.a; 4014ceae137SRavi Bangoria regs.gpr[4] = 0; 4024ceae137SRavi Bangoria 4034ceae137SRavi Bangoria /* lxvd2x vsr39, r3, r4 */ 4044ceae137SRavi Bangoria stepped = emulate_step(®s, TEST_LXVD2X(39, 3, 4)); 4054ceae137SRavi Bangoria 4065a61640eSRavi Bangoria if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) { 4074ceae137SRavi Bangoria show_result("lxvd2x", "PASS"); 4085a61640eSRavi Bangoria } else { 4095a61640eSRavi Bangoria if (!cpu_has_feature(CPU_FTR_VSX)) 4105a61640eSRavi Bangoria show_result("lxvd2x", "PASS (!CPU_FTR_VSX)"); 4114ceae137SRavi Bangoria else 4124ceae137SRavi Bangoria show_result("lxvd2x", "FAIL"); 4135a61640eSRavi Bangoria } 4144ceae137SRavi Bangoria 4154ceae137SRavi Bangoria 4164ceae137SRavi Bangoria /*** stxvd2x ***/ 4174ceae137SRavi Bangoria 4184ceae137SRavi Bangoria c.b[0] = 21379463; 4194ceae137SRavi Bangoria c.b[1] = 87; 4204ceae137SRavi Bangoria c.b[2] = 374234; 4214ceae137SRavi Bangoria c.b[3] = 4; 4224ceae137SRavi Bangoria 4234ceae137SRavi Bangoria /* stxvd2x vsr39, r3, r4 */ 4244ceae137SRavi Bangoria stepped = emulate_step(®s, TEST_STXVD2X(39, 3, 4)); 4254ceae137SRavi Bangoria 4264ceae137SRavi Bangoria if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] && 4275a61640eSRavi Bangoria cached_b[2] == c.b[2] && cached_b[3] == c.b[3] && 4285a61640eSRavi Bangoria cpu_has_feature(CPU_FTR_VSX)) { 4294ceae137SRavi Bangoria show_result("stxvd2x", "PASS"); 4305a61640eSRavi Bangoria } else { 4315a61640eSRavi Bangoria if (!cpu_has_feature(CPU_FTR_VSX)) 4325a61640eSRavi Bangoria show_result("stxvd2x", "PASS (!CPU_FTR_VSX)"); 4334ceae137SRavi Bangoria else 4344ceae137SRavi Bangoria show_result("stxvd2x", "FAIL"); 4354ceae137SRavi Bangoria } 4365a61640eSRavi Bangoria } 4374ceae137SRavi Bangoria #else 4384ceae137SRavi Bangoria static void __init test_lxvd2x_stxvd2x(void) 4394ceae137SRavi Bangoria { 4404ceae137SRavi Bangoria show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)"); 4414ceae137SRavi Bangoria show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)"); 4424ceae137SRavi Bangoria } 4434ceae137SRavi Bangoria #endif /* CONFIG_VSX */ 4444ceae137SRavi Bangoria 44584022ac1SSandipan Das static void __init run_tests_load_store(void) 4464ceae137SRavi Bangoria { 4474ceae137SRavi Bangoria test_ld(); 4484ceae137SRavi Bangoria test_lwz(); 4494ceae137SRavi Bangoria test_lwzx(); 4504ceae137SRavi Bangoria test_std(); 4514ceae137SRavi Bangoria test_ldarx_stdcx(); 4524ceae137SRavi Bangoria test_lfsx_stfsx(); 4534ceae137SRavi Bangoria test_lfdx_stfdx(); 4544ceae137SRavi Bangoria test_lvx_stvx(); 4554ceae137SRavi Bangoria test_lxvd2x_stxvd2x(); 45684022ac1SSandipan Das } 45784022ac1SSandipan Das 45884022ac1SSandipan Das struct compute_test { 45984022ac1SSandipan Das char *mnemonic; 46084022ac1SSandipan Das struct { 46184022ac1SSandipan Das char *descr; 46284022ac1SSandipan Das unsigned long flags; 46384022ac1SSandipan Das unsigned int instr; 46484022ac1SSandipan Das struct pt_regs regs; 46584022ac1SSandipan Das } subtests[MAX_SUBTESTS + 1]; 46684022ac1SSandipan Das }; 46784022ac1SSandipan Das 46884022ac1SSandipan Das static struct compute_test compute_tests[] = { 46984022ac1SSandipan Das { 47084022ac1SSandipan Das .mnemonic = "nop", 47184022ac1SSandipan Das .subtests = { 47284022ac1SSandipan Das { 47384022ac1SSandipan Das .descr = "R0 = LONG_MAX", 47484022ac1SSandipan Das .instr = PPC_INST_NOP, 47584022ac1SSandipan Das .regs = { 47684022ac1SSandipan Das .gpr[0] = LONG_MAX, 47784022ac1SSandipan Das } 47884022ac1SSandipan Das } 47984022ac1SSandipan Das } 480*44dea178SSandipan Das }, 481*44dea178SSandipan Das { 482*44dea178SSandipan Das .mnemonic = "add", 483*44dea178SSandipan Das .subtests = { 484*44dea178SSandipan Das { 485*44dea178SSandipan Das .descr = "RA = LONG_MIN, RB = LONG_MIN", 486*44dea178SSandipan Das .instr = TEST_ADD(20, 21, 22), 487*44dea178SSandipan Das .regs = { 488*44dea178SSandipan Das .gpr[21] = LONG_MIN, 489*44dea178SSandipan Das .gpr[22] = LONG_MIN, 490*44dea178SSandipan Das } 491*44dea178SSandipan Das }, 492*44dea178SSandipan Das { 493*44dea178SSandipan Das .descr = "RA = LONG_MIN, RB = LONG_MAX", 494*44dea178SSandipan Das .instr = TEST_ADD(20, 21, 22), 495*44dea178SSandipan Das .regs = { 496*44dea178SSandipan Das .gpr[21] = LONG_MIN, 497*44dea178SSandipan Das .gpr[22] = LONG_MAX, 498*44dea178SSandipan Das } 499*44dea178SSandipan Das }, 500*44dea178SSandipan Das { 501*44dea178SSandipan Das .descr = "RA = LONG_MAX, RB = LONG_MAX", 502*44dea178SSandipan Das .instr = TEST_ADD(20, 21, 22), 503*44dea178SSandipan Das .regs = { 504*44dea178SSandipan Das .gpr[21] = LONG_MAX, 505*44dea178SSandipan Das .gpr[22] = LONG_MAX, 506*44dea178SSandipan Das } 507*44dea178SSandipan Das }, 508*44dea178SSandipan Das { 509*44dea178SSandipan Das .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 510*44dea178SSandipan Das .instr = TEST_ADD(20, 21, 22), 511*44dea178SSandipan Das .regs = { 512*44dea178SSandipan Das .gpr[21] = ULONG_MAX, 513*44dea178SSandipan Das .gpr[22] = ULONG_MAX, 514*44dea178SSandipan Das } 515*44dea178SSandipan Das }, 516*44dea178SSandipan Das { 517*44dea178SSandipan Das .descr = "RA = ULONG_MAX, RB = 0x1", 518*44dea178SSandipan Das .instr = TEST_ADD(20, 21, 22), 519*44dea178SSandipan Das .regs = { 520*44dea178SSandipan Das .gpr[21] = ULONG_MAX, 521*44dea178SSandipan Das .gpr[22] = 0x1, 522*44dea178SSandipan Das } 523*44dea178SSandipan Das }, 524*44dea178SSandipan Das { 525*44dea178SSandipan Das .descr = "RA = INT_MIN, RB = INT_MIN", 526*44dea178SSandipan Das .instr = TEST_ADD(20, 21, 22), 527*44dea178SSandipan Das .regs = { 528*44dea178SSandipan Das .gpr[21] = INT_MIN, 529*44dea178SSandipan Das .gpr[22] = INT_MIN, 530*44dea178SSandipan Das } 531*44dea178SSandipan Das }, 532*44dea178SSandipan Das { 533*44dea178SSandipan Das .descr = "RA = INT_MIN, RB = INT_MAX", 534*44dea178SSandipan Das .instr = TEST_ADD(20, 21, 22), 535*44dea178SSandipan Das .regs = { 536*44dea178SSandipan Das .gpr[21] = INT_MIN, 537*44dea178SSandipan Das .gpr[22] = INT_MAX, 538*44dea178SSandipan Das } 539*44dea178SSandipan Das }, 540*44dea178SSandipan Das { 541*44dea178SSandipan Das .descr = "RA = INT_MAX, RB = INT_MAX", 542*44dea178SSandipan Das .instr = TEST_ADD(20, 21, 22), 543*44dea178SSandipan Das .regs = { 544*44dea178SSandipan Das .gpr[21] = INT_MAX, 545*44dea178SSandipan Das .gpr[22] = INT_MAX, 546*44dea178SSandipan Das } 547*44dea178SSandipan Das }, 548*44dea178SSandipan Das { 549*44dea178SSandipan Das .descr = "RA = UINT_MAX, RB = UINT_MAX", 550*44dea178SSandipan Das .instr = TEST_ADD(20, 21, 22), 551*44dea178SSandipan Das .regs = { 552*44dea178SSandipan Das .gpr[21] = UINT_MAX, 553*44dea178SSandipan Das .gpr[22] = UINT_MAX, 554*44dea178SSandipan Das } 555*44dea178SSandipan Das }, 556*44dea178SSandipan Das { 557*44dea178SSandipan Das .descr = "RA = UINT_MAX, RB = 0x1", 558*44dea178SSandipan Das .instr = TEST_ADD(20, 21, 22), 559*44dea178SSandipan Das .regs = { 560*44dea178SSandipan Das .gpr[21] = UINT_MAX, 561*44dea178SSandipan Das .gpr[22] = 0x1, 562*44dea178SSandipan Das } 563*44dea178SSandipan Das } 564*44dea178SSandipan Das } 565*44dea178SSandipan Das }, 566*44dea178SSandipan Das { 567*44dea178SSandipan Das .mnemonic = "add.", 568*44dea178SSandipan Das .subtests = { 569*44dea178SSandipan Das { 570*44dea178SSandipan Das .descr = "RA = LONG_MIN, RB = LONG_MIN", 571*44dea178SSandipan Das .flags = IGNORE_CCR, 572*44dea178SSandipan Das .instr = TEST_ADD_DOT(20, 21, 22), 573*44dea178SSandipan Das .regs = { 574*44dea178SSandipan Das .gpr[21] = LONG_MIN, 575*44dea178SSandipan Das .gpr[22] = LONG_MIN, 576*44dea178SSandipan Das } 577*44dea178SSandipan Das }, 578*44dea178SSandipan Das { 579*44dea178SSandipan Das .descr = "RA = LONG_MIN, RB = LONG_MAX", 580*44dea178SSandipan Das .instr = TEST_ADD_DOT(20, 21, 22), 581*44dea178SSandipan Das .regs = { 582*44dea178SSandipan Das .gpr[21] = LONG_MIN, 583*44dea178SSandipan Das .gpr[22] = LONG_MAX, 584*44dea178SSandipan Das } 585*44dea178SSandipan Das }, 586*44dea178SSandipan Das { 587*44dea178SSandipan Das .descr = "RA = LONG_MAX, RB = LONG_MAX", 588*44dea178SSandipan Das .flags = IGNORE_CCR, 589*44dea178SSandipan Das .instr = TEST_ADD_DOT(20, 21, 22), 590*44dea178SSandipan Das .regs = { 591*44dea178SSandipan Das .gpr[21] = LONG_MAX, 592*44dea178SSandipan Das .gpr[22] = LONG_MAX, 593*44dea178SSandipan Das } 594*44dea178SSandipan Das }, 595*44dea178SSandipan Das { 596*44dea178SSandipan Das .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 597*44dea178SSandipan Das .instr = TEST_ADD_DOT(20, 21, 22), 598*44dea178SSandipan Das .regs = { 599*44dea178SSandipan Das .gpr[21] = ULONG_MAX, 600*44dea178SSandipan Das .gpr[22] = ULONG_MAX, 601*44dea178SSandipan Das } 602*44dea178SSandipan Das }, 603*44dea178SSandipan Das { 604*44dea178SSandipan Das .descr = "RA = ULONG_MAX, RB = 0x1", 605*44dea178SSandipan Das .instr = TEST_ADD_DOT(20, 21, 22), 606*44dea178SSandipan Das .regs = { 607*44dea178SSandipan Das .gpr[21] = ULONG_MAX, 608*44dea178SSandipan Das .gpr[22] = 0x1, 609*44dea178SSandipan Das } 610*44dea178SSandipan Das }, 611*44dea178SSandipan Das { 612*44dea178SSandipan Das .descr = "RA = INT_MIN, RB = INT_MIN", 613*44dea178SSandipan Das .instr = TEST_ADD_DOT(20, 21, 22), 614*44dea178SSandipan Das .regs = { 615*44dea178SSandipan Das .gpr[21] = INT_MIN, 616*44dea178SSandipan Das .gpr[22] = INT_MIN, 617*44dea178SSandipan Das } 618*44dea178SSandipan Das }, 619*44dea178SSandipan Das { 620*44dea178SSandipan Das .descr = "RA = INT_MIN, RB = INT_MAX", 621*44dea178SSandipan Das .instr = TEST_ADD_DOT(20, 21, 22), 622*44dea178SSandipan Das .regs = { 623*44dea178SSandipan Das .gpr[21] = INT_MIN, 624*44dea178SSandipan Das .gpr[22] = INT_MAX, 625*44dea178SSandipan Das } 626*44dea178SSandipan Das }, 627*44dea178SSandipan Das { 628*44dea178SSandipan Das .descr = "RA = INT_MAX, RB = INT_MAX", 629*44dea178SSandipan Das .instr = TEST_ADD_DOT(20, 21, 22), 630*44dea178SSandipan Das .regs = { 631*44dea178SSandipan Das .gpr[21] = INT_MAX, 632*44dea178SSandipan Das .gpr[22] = INT_MAX, 633*44dea178SSandipan Das } 634*44dea178SSandipan Das }, 635*44dea178SSandipan Das { 636*44dea178SSandipan Das .descr = "RA = UINT_MAX, RB = UINT_MAX", 637*44dea178SSandipan Das .instr = TEST_ADD_DOT(20, 21, 22), 638*44dea178SSandipan Das .regs = { 639*44dea178SSandipan Das .gpr[21] = UINT_MAX, 640*44dea178SSandipan Das .gpr[22] = UINT_MAX, 641*44dea178SSandipan Das } 642*44dea178SSandipan Das }, 643*44dea178SSandipan Das { 644*44dea178SSandipan Das .descr = "RA = UINT_MAX, RB = 0x1", 645*44dea178SSandipan Das .instr = TEST_ADD_DOT(20, 21, 22), 646*44dea178SSandipan Das .regs = { 647*44dea178SSandipan Das .gpr[21] = UINT_MAX, 648*44dea178SSandipan Das .gpr[22] = 0x1, 649*44dea178SSandipan Das } 650*44dea178SSandipan Das } 651*44dea178SSandipan Das } 65284022ac1SSandipan Das } 65384022ac1SSandipan Das }; 65484022ac1SSandipan Das 65584022ac1SSandipan Das static int __init emulate_compute_instr(struct pt_regs *regs, 65684022ac1SSandipan Das unsigned int instr) 65784022ac1SSandipan Das { 65884022ac1SSandipan Das struct instruction_op op; 65984022ac1SSandipan Das 66084022ac1SSandipan Das if (!regs || !instr) 66184022ac1SSandipan Das return -EINVAL; 66284022ac1SSandipan Das 66384022ac1SSandipan Das if (analyse_instr(&op, regs, instr) != 1 || 66484022ac1SSandipan Das GETTYPE(op.type) != COMPUTE) { 66584022ac1SSandipan Das pr_info("emulation failed, instruction = 0x%08x\n", instr); 66684022ac1SSandipan Das return -EFAULT; 66784022ac1SSandipan Das } 66884022ac1SSandipan Das 66984022ac1SSandipan Das emulate_update_regs(regs, &op); 67084022ac1SSandipan Das return 0; 67184022ac1SSandipan Das } 67284022ac1SSandipan Das 67384022ac1SSandipan Das static int __init execute_compute_instr(struct pt_regs *regs, 67484022ac1SSandipan Das unsigned int instr) 67584022ac1SSandipan Das { 67684022ac1SSandipan Das extern int exec_instr(struct pt_regs *regs); 67784022ac1SSandipan Das extern s32 patch__exec_instr; 67884022ac1SSandipan Das 67984022ac1SSandipan Das if (!regs || !instr) 68084022ac1SSandipan Das return -EINVAL; 68184022ac1SSandipan Das 68284022ac1SSandipan Das /* Patch the NOP with the actual instruction */ 68384022ac1SSandipan Das patch_instruction_site(&patch__exec_instr, instr); 68484022ac1SSandipan Das if (exec_instr(regs)) { 68584022ac1SSandipan Das pr_info("execution failed, instruction = 0x%08x\n", instr); 68684022ac1SSandipan Das return -EFAULT; 68784022ac1SSandipan Das } 68884022ac1SSandipan Das 68984022ac1SSandipan Das return 0; 69084022ac1SSandipan Das } 69184022ac1SSandipan Das 69284022ac1SSandipan Das #define gpr_mismatch(gprn, exp, got) \ 69384022ac1SSandipan Das pr_info("GPR%u mismatch, exp = 0x%016lx, got = 0x%016lx\n", \ 69484022ac1SSandipan Das gprn, exp, got) 69584022ac1SSandipan Das 69684022ac1SSandipan Das #define reg_mismatch(name, exp, got) \ 69784022ac1SSandipan Das pr_info("%s mismatch, exp = 0x%016lx, got = 0x%016lx\n", \ 69884022ac1SSandipan Das name, exp, got) 69984022ac1SSandipan Das 70084022ac1SSandipan Das static void __init run_tests_compute(void) 70184022ac1SSandipan Das { 70284022ac1SSandipan Das unsigned long flags; 70384022ac1SSandipan Das struct compute_test *test; 70484022ac1SSandipan Das struct pt_regs *regs, exp, got; 70584022ac1SSandipan Das unsigned int i, j, k, instr; 70684022ac1SSandipan Das bool ignore_gpr, ignore_xer, ignore_ccr, passed; 70784022ac1SSandipan Das 70884022ac1SSandipan Das for (i = 0; i < ARRAY_SIZE(compute_tests); i++) { 70984022ac1SSandipan Das test = &compute_tests[i]; 71084022ac1SSandipan Das 71184022ac1SSandipan Das for (j = 0; j < MAX_SUBTESTS && test->subtests[j].descr; j++) { 71284022ac1SSandipan Das instr = test->subtests[j].instr; 71384022ac1SSandipan Das flags = test->subtests[j].flags; 71484022ac1SSandipan Das regs = &test->subtests[j].regs; 71584022ac1SSandipan Das ignore_xer = flags & IGNORE_XER; 71684022ac1SSandipan Das ignore_ccr = flags & IGNORE_CCR; 71784022ac1SSandipan Das passed = true; 71884022ac1SSandipan Das 71984022ac1SSandipan Das memcpy(&exp, regs, sizeof(struct pt_regs)); 72084022ac1SSandipan Das memcpy(&got, regs, sizeof(struct pt_regs)); 72184022ac1SSandipan Das 72284022ac1SSandipan Das /* 72384022ac1SSandipan Das * Set a compatible MSR value explicitly to ensure 72484022ac1SSandipan Das * that XER and CR bits are updated appropriately 72584022ac1SSandipan Das */ 72684022ac1SSandipan Das exp.msr = MSR_KERNEL; 72784022ac1SSandipan Das got.msr = MSR_KERNEL; 72884022ac1SSandipan Das 72984022ac1SSandipan Das if (emulate_compute_instr(&got, instr) || 73084022ac1SSandipan Das execute_compute_instr(&exp, instr)) { 73184022ac1SSandipan Das passed = false; 73284022ac1SSandipan Das goto print; 73384022ac1SSandipan Das } 73484022ac1SSandipan Das 73584022ac1SSandipan Das /* Verify GPR values */ 73684022ac1SSandipan Das for (k = 0; k < 32; k++) { 73784022ac1SSandipan Das ignore_gpr = flags & IGNORE_GPR(k); 73884022ac1SSandipan Das if (!ignore_gpr && exp.gpr[k] != got.gpr[k]) { 73984022ac1SSandipan Das passed = false; 74084022ac1SSandipan Das gpr_mismatch(k, exp.gpr[k], got.gpr[k]); 74184022ac1SSandipan Das } 74284022ac1SSandipan Das } 74384022ac1SSandipan Das 74484022ac1SSandipan Das /* Verify LR value */ 74584022ac1SSandipan Das if (exp.link != got.link) { 74684022ac1SSandipan Das passed = false; 74784022ac1SSandipan Das reg_mismatch("LR", exp.link, got.link); 74884022ac1SSandipan Das } 74984022ac1SSandipan Das 75084022ac1SSandipan Das /* Verify XER value */ 75184022ac1SSandipan Das if (!ignore_xer && exp.xer != got.xer) { 75284022ac1SSandipan Das passed = false; 75384022ac1SSandipan Das reg_mismatch("XER", exp.xer, got.xer); 75484022ac1SSandipan Das } 75584022ac1SSandipan Das 75684022ac1SSandipan Das /* Verify CR value */ 75784022ac1SSandipan Das if (!ignore_ccr && exp.ccr != got.ccr) { 75884022ac1SSandipan Das passed = false; 75984022ac1SSandipan Das reg_mismatch("CR", exp.ccr, got.ccr); 76084022ac1SSandipan Das } 76184022ac1SSandipan Das 76284022ac1SSandipan Das print: 76384022ac1SSandipan Das show_result_with_descr(test->mnemonic, 76484022ac1SSandipan Das test->subtests[j].descr, 76584022ac1SSandipan Das passed ? "PASS" : "FAIL"); 76684022ac1SSandipan Das } 76784022ac1SSandipan Das } 76884022ac1SSandipan Das } 76984022ac1SSandipan Das 77084022ac1SSandipan Das static int __init test_emulate_step(void) 77184022ac1SSandipan Das { 77284022ac1SSandipan Das printk(KERN_INFO "Running instruction emulation self-tests ...\n"); 77384022ac1SSandipan Das run_tests_load_store(); 77484022ac1SSandipan Das run_tests_compute(); 7754ceae137SRavi Bangoria 7764ceae137SRavi Bangoria return 0; 7774ceae137SRavi Bangoria } 7784ceae137SRavi Bangoria late_initcall(test_emulate_step); 779