162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Test the powerpc alignment handler on POWER8/POWER9 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2017 IBM Corporation (Michael Neuling, Andrew Donnellan) 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* 962306a36Sopenharmony_ci * This selftest exercises the powerpc alignment fault handler. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * We create two sets of source and destination buffers, one in regular memory, 1262306a36Sopenharmony_ci * the other cache-inhibited (by default we use /dev/fb0 for this, but an 1362306a36Sopenharmony_ci * alterative path for cache-inhibited memory may be provided, e.g. memtrace). 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * We initialise the source buffers, then use whichever set of load/store 1662306a36Sopenharmony_ci * instructions is under test to copy bytes from the source buffers to the 1762306a36Sopenharmony_ci * destination buffers. For the regular buffers, these instructions will 1862306a36Sopenharmony_ci * execute normally. For the cache-inhibited buffers, these instructions 1962306a36Sopenharmony_ci * will trap and cause an alignment fault, and the alignment fault handler 2062306a36Sopenharmony_ci * will emulate the particular instruction under test. We then compare the 2162306a36Sopenharmony_ci * destination buffers to ensure that the native and emulated cases give the 2262306a36Sopenharmony_ci * same result. 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * TODO: 2562306a36Sopenharmony_ci * - Any FIXMEs below 2662306a36Sopenharmony_ci * - Test VSX regs < 32 and > 32 2762306a36Sopenharmony_ci * - Test all loads and stores 2862306a36Sopenharmony_ci * - Check update forms do update register 2962306a36Sopenharmony_ci * - Test alignment faults over page boundary 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * Some old binutils may not support all the instructions. 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#include <sys/mman.h> 3662306a36Sopenharmony_ci#include <sys/types.h> 3762306a36Sopenharmony_ci#include <sys/stat.h> 3862306a36Sopenharmony_ci#include <fcntl.h> 3962306a36Sopenharmony_ci#include <unistd.h> 4062306a36Sopenharmony_ci#include <stdbool.h> 4162306a36Sopenharmony_ci#include <stdio.h> 4262306a36Sopenharmony_ci#include <stdlib.h> 4362306a36Sopenharmony_ci#include <string.h> 4462306a36Sopenharmony_ci#include <assert.h> 4562306a36Sopenharmony_ci#include <getopt.h> 4662306a36Sopenharmony_ci#include <setjmp.h> 4762306a36Sopenharmony_ci#include <signal.h> 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#include "utils.h" 5062306a36Sopenharmony_ci#include "instructions.h" 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ciint bufsize; 5362306a36Sopenharmony_ciint debug; 5462306a36Sopenharmony_ciint testing; 5562306a36Sopenharmony_civolatile int gotsig; 5662306a36Sopenharmony_cibool prefixes_enabled; 5762306a36Sopenharmony_cichar *cipath = "/dev/fb0"; 5862306a36Sopenharmony_cilong cioffset; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_civoid sighandler(int sig, siginfo_t *info, void *ctx) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci ucontext_t *ucp = ctx; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci if (!testing) { 6562306a36Sopenharmony_ci signal(sig, SIG_DFL); 6662306a36Sopenharmony_ci kill(0, sig); 6762306a36Sopenharmony_ci } 6862306a36Sopenharmony_ci gotsig = sig; 6962306a36Sopenharmony_ci#ifdef __powerpc64__ 7062306a36Sopenharmony_ci if (prefixes_enabled) { 7162306a36Sopenharmony_ci u32 inst = *(u32 *)ucp->uc_mcontext.gp_regs[PT_NIP]; 7262306a36Sopenharmony_ci ucp->uc_mcontext.gp_regs[PT_NIP] += ((inst >> 26 == 1) ? 8 : 4); 7362306a36Sopenharmony_ci } else { 7462306a36Sopenharmony_ci ucp->uc_mcontext.gp_regs[PT_NIP] += 4; 7562306a36Sopenharmony_ci } 7662306a36Sopenharmony_ci#else 7762306a36Sopenharmony_ci ucp->uc_mcontext.uc_regs->gregs[PT_NIP] += 4; 7862306a36Sopenharmony_ci#endif 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci#define XFORM(reg, n) " " #reg " ,%"#n",%2 ;" 8262306a36Sopenharmony_ci#define DFORM(reg, n) " " #reg " ,0(%"#n") ;" 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci#define TEST(name, ld_op, st_op, form, ld_reg, st_reg) \ 8562306a36Sopenharmony_ci void test_##name(char *s, char *d) \ 8662306a36Sopenharmony_ci { \ 8762306a36Sopenharmony_ci asm volatile( \ 8862306a36Sopenharmony_ci #ld_op form(ld_reg, 0) \ 8962306a36Sopenharmony_ci #st_op form(st_reg, 1) \ 9062306a36Sopenharmony_ci :: "r"(s), "r"(d), "r"(0) \ 9162306a36Sopenharmony_ci : "memory", "vs0", "vs32", "r31"); \ 9262306a36Sopenharmony_ci } \ 9362306a36Sopenharmony_ci rc |= do_test(#name, test_##name) 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci#define TESTP(name, ld_op, st_op, ld_reg, st_reg) \ 9662306a36Sopenharmony_ci void test_##name(char *s, char *d) \ 9762306a36Sopenharmony_ci { \ 9862306a36Sopenharmony_ci asm volatile( \ 9962306a36Sopenharmony_ci ld_op(ld_reg, %0, 0, 0) \ 10062306a36Sopenharmony_ci st_op(st_reg, %1, 0, 0) \ 10162306a36Sopenharmony_ci :: "r"(s), "r"(d), "r"(0) \ 10262306a36Sopenharmony_ci : "memory", "vs0", "vs32", "r31"); \ 10362306a36Sopenharmony_ci } \ 10462306a36Sopenharmony_ci rc |= do_test(#name, test_##name) 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci#define LOAD_VSX_XFORM_TEST(op) TEST(op, op, stxvd2x, XFORM, 32, 32) 10762306a36Sopenharmony_ci#define STORE_VSX_XFORM_TEST(op) TEST(op, lxvd2x, op, XFORM, 32, 32) 10862306a36Sopenharmony_ci#define LOAD_VSX_DFORM_TEST(op) TEST(op, op, stxv, DFORM, 32, 32) 10962306a36Sopenharmony_ci#define STORE_VSX_DFORM_TEST(op) TEST(op, lxv, op, DFORM, 32, 32) 11062306a36Sopenharmony_ci#define LOAD_VMX_XFORM_TEST(op) TEST(op, op, stxvd2x, XFORM, 0, 32) 11162306a36Sopenharmony_ci#define STORE_VMX_XFORM_TEST(op) TEST(op, lxvd2x, op, XFORM, 32, 0) 11262306a36Sopenharmony_ci#define LOAD_VMX_DFORM_TEST(op) TEST(op, op, stxv, DFORM, 0, 32) 11362306a36Sopenharmony_ci#define STORE_VMX_DFORM_TEST(op) TEST(op, lxv, op, DFORM, 32, 0) 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci#define LOAD_XFORM_TEST(op) TEST(op, op, stdx, XFORM, 31, 31) 11662306a36Sopenharmony_ci#define STORE_XFORM_TEST(op) TEST(op, ldx, op, XFORM, 31, 31) 11762306a36Sopenharmony_ci#define LOAD_DFORM_TEST(op) TEST(op, op, std, DFORM, 31, 31) 11862306a36Sopenharmony_ci#define STORE_DFORM_TEST(op) TEST(op, ld, op, DFORM, 31, 31) 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci#define LOAD_FLOAT_DFORM_TEST(op) TEST(op, op, stfd, DFORM, 0, 0) 12162306a36Sopenharmony_ci#define STORE_FLOAT_DFORM_TEST(op) TEST(op, lfd, op, DFORM, 0, 0) 12262306a36Sopenharmony_ci#define LOAD_FLOAT_XFORM_TEST(op) TEST(op, op, stfdx, XFORM, 0, 0) 12362306a36Sopenharmony_ci#define STORE_FLOAT_XFORM_TEST(op) TEST(op, lfdx, op, XFORM, 0, 0) 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci#define LOAD_MLS_PREFIX_TEST(op) TESTP(op, op, PSTD, 31, 31) 12662306a36Sopenharmony_ci#define STORE_MLS_PREFIX_TEST(op) TESTP(op, PLD, op, 31, 31) 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci#define LOAD_8LS_PREFIX_TEST(op) TESTP(op, op, PSTD, 31, 31) 12962306a36Sopenharmony_ci#define STORE_8LS_PREFIX_TEST(op) TESTP(op, PLD, op, 31, 31) 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci#define LOAD_FLOAT_MLS_PREFIX_TEST(op) TESTP(op, op, PSTFD, 0, 0) 13262306a36Sopenharmony_ci#define STORE_FLOAT_MLS_PREFIX_TEST(op) TESTP(op, PLFD, op, 0, 0) 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci#define LOAD_VSX_8LS_PREFIX_TEST(op, tail) TESTP(op, op, PSTXV ## tail, 0, 32) 13562306a36Sopenharmony_ci#define STORE_VSX_8LS_PREFIX_TEST(op, tail) TESTP(op, PLXV ## tail, op, 32, 0) 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci/* FIXME: Unimplemented tests: */ 13862306a36Sopenharmony_ci// STORE_DFORM_TEST(stq) /* FIXME: need two registers for quad */ 13962306a36Sopenharmony_ci// STORE_DFORM_TEST(stswi) /* FIXME: string instruction */ 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci// STORE_XFORM_TEST(stwat) /* AMO can't emulate or run on CI */ 14262306a36Sopenharmony_ci// STORE_XFORM_TEST(stdat) /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */ 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci/* preload byte by byte */ 14662306a36Sopenharmony_civoid preload_data(void *dst, int offset, int width) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci char *c = dst; 14962306a36Sopenharmony_ci int i; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci c += offset; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci for (i = 0 ; i < width ; i++) 15462306a36Sopenharmony_ci c[i] = i; 15562306a36Sopenharmony_ci} 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ciint test_memcpy(void *dst, void *src, int size, int offset, 15862306a36Sopenharmony_ci void (*test_func)(char *, char *)) 15962306a36Sopenharmony_ci{ 16062306a36Sopenharmony_ci char *s, *d; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci s = src; 16362306a36Sopenharmony_ci s += offset; 16462306a36Sopenharmony_ci d = dst; 16562306a36Sopenharmony_ci d += offset; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci assert(size == 16); 16862306a36Sopenharmony_ci gotsig = 0; 16962306a36Sopenharmony_ci testing = 1; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci test_func(s, d); /* run the actual test */ 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci testing = 0; 17462306a36Sopenharmony_ci if (gotsig) { 17562306a36Sopenharmony_ci if (debug) 17662306a36Sopenharmony_ci printf(" Got signal %i\n", gotsig); 17762306a36Sopenharmony_ci return 1; 17862306a36Sopenharmony_ci } 17962306a36Sopenharmony_ci return 0; 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_civoid dumpdata(char *s1, char *s2, int n, char *test_name) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci int i; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci printf(" %s: unexpected result:\n", test_name); 18762306a36Sopenharmony_ci printf(" mem:"); 18862306a36Sopenharmony_ci for (i = 0; i < n; i++) 18962306a36Sopenharmony_ci printf(" %02x", s1[i]); 19062306a36Sopenharmony_ci printf("\n"); 19162306a36Sopenharmony_ci printf(" ci: "); 19262306a36Sopenharmony_ci for (i = 0; i < n; i++) 19362306a36Sopenharmony_ci printf(" %02x", s2[i]); 19462306a36Sopenharmony_ci printf("\n"); 19562306a36Sopenharmony_ci} 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ciint test_memcmp(void *s1, void *s2, int n, int offset, char *test_name) 19862306a36Sopenharmony_ci{ 19962306a36Sopenharmony_ci char *s1c, *s2c; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci s1c = s1; 20262306a36Sopenharmony_ci s1c += offset; 20362306a36Sopenharmony_ci s2c = s2; 20462306a36Sopenharmony_ci s2c += offset; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci if (memcmp(s1c, s2c, n)) { 20762306a36Sopenharmony_ci if (debug) { 20862306a36Sopenharmony_ci printf("\n Compare failed. Offset:%i length:%i\n", 20962306a36Sopenharmony_ci offset, n); 21062306a36Sopenharmony_ci dumpdata(s1c, s2c, n, test_name); 21162306a36Sopenharmony_ci } 21262306a36Sopenharmony_ci return 1; 21362306a36Sopenharmony_ci } 21462306a36Sopenharmony_ci return 0; 21562306a36Sopenharmony_ci} 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci/* 21862306a36Sopenharmony_ci * Do two memcpy tests using the same instructions. One cachable 21962306a36Sopenharmony_ci * memory and the other doesn't. 22062306a36Sopenharmony_ci */ 22162306a36Sopenharmony_ciint do_test(char *test_name, void (*test_func)(char *, char *)) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci int offset, width, fd, rc, r; 22462306a36Sopenharmony_ci void *mem0, *mem1, *ci0, *ci1; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci printf("\tDoing %s:\t", test_name); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci fd = open(cipath, O_RDWR); 22962306a36Sopenharmony_ci if (fd < 0) { 23062306a36Sopenharmony_ci printf("\n"); 23162306a36Sopenharmony_ci perror("Can't open ci file now?"); 23262306a36Sopenharmony_ci return 1; 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci ci0 = mmap(NULL, bufsize, PROT_WRITE | PROT_READ, MAP_SHARED, 23662306a36Sopenharmony_ci fd, cioffset); 23762306a36Sopenharmony_ci ci1 = mmap(NULL, bufsize, PROT_WRITE | PROT_READ, MAP_SHARED, 23862306a36Sopenharmony_ci fd, cioffset + bufsize); 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci if ((ci0 == MAP_FAILED) || (ci1 == MAP_FAILED)) { 24162306a36Sopenharmony_ci printf("\n"); 24262306a36Sopenharmony_ci perror("mmap failed"); 24362306a36Sopenharmony_ci SKIP_IF(1); 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci rc = posix_memalign(&mem0, bufsize, bufsize); 24762306a36Sopenharmony_ci if (rc) { 24862306a36Sopenharmony_ci printf("\n"); 24962306a36Sopenharmony_ci return rc; 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci rc = posix_memalign(&mem1, bufsize, bufsize); 25362306a36Sopenharmony_ci if (rc) { 25462306a36Sopenharmony_ci printf("\n"); 25562306a36Sopenharmony_ci free(mem0); 25662306a36Sopenharmony_ci return rc; 25762306a36Sopenharmony_ci } 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci rc = 0; 26062306a36Sopenharmony_ci /* 26162306a36Sopenharmony_ci * offset = 0 is aligned but tests the workaround for the P9N 26262306a36Sopenharmony_ci * DD2.1 vector CI load issue (see 5080332c2c89 "powerpc/64s: 26362306a36Sopenharmony_ci * Add workaround for P9 vector CI load issue") 26462306a36Sopenharmony_ci */ 26562306a36Sopenharmony_ci for (offset = 0; offset < 16; offset++) { 26662306a36Sopenharmony_ci width = 16; /* vsx == 16 bytes */ 26762306a36Sopenharmony_ci r = 0; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci /* load pattern into memory byte by byte */ 27062306a36Sopenharmony_ci preload_data(ci0, offset, width); 27162306a36Sopenharmony_ci preload_data(mem0, offset, width); // FIXME: remove?? 27262306a36Sopenharmony_ci memcpy(ci0, mem0, bufsize); 27362306a36Sopenharmony_ci memcpy(ci1, mem1, bufsize); /* initialise output to the same */ 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci /* sanity check */ 27662306a36Sopenharmony_ci test_memcmp(mem0, ci0, width, offset, test_name); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci r |= test_memcpy(ci1, ci0, width, offset, test_func); 27962306a36Sopenharmony_ci r |= test_memcpy(mem1, mem0, width, offset, test_func); 28062306a36Sopenharmony_ci if (r && !debug) { 28162306a36Sopenharmony_ci printf("FAILED: Got signal"); 28262306a36Sopenharmony_ci rc = 1; 28362306a36Sopenharmony_ci break; 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci r |= test_memcmp(mem1, ci1, width, offset, test_name); 28762306a36Sopenharmony_ci if (r && !debug) { 28862306a36Sopenharmony_ci printf("FAILED: Wrong Data"); 28962306a36Sopenharmony_ci rc = 1; 29062306a36Sopenharmony_ci break; 29162306a36Sopenharmony_ci } 29262306a36Sopenharmony_ci } 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci if (rc == 0) 29562306a36Sopenharmony_ci printf("PASSED"); 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci printf("\n"); 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci munmap(ci0, bufsize); 30062306a36Sopenharmony_ci munmap(ci1, bufsize); 30162306a36Sopenharmony_ci free(mem0); 30262306a36Sopenharmony_ci free(mem1); 30362306a36Sopenharmony_ci close(fd); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci return rc; 30662306a36Sopenharmony_ci} 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_cistatic bool can_open_cifile(void) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci int fd; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci fd = open(cipath, O_RDWR); 31362306a36Sopenharmony_ci if (fd < 0) 31462306a36Sopenharmony_ci return false; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci close(fd); 31762306a36Sopenharmony_ci return true; 31862306a36Sopenharmony_ci} 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ciint test_alignment_handler_vsx_206(void) 32162306a36Sopenharmony_ci{ 32262306a36Sopenharmony_ci int rc = 0; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci SKIP_IF(!can_open_cifile()); 32562306a36Sopenharmony_ci SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06)); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci printf("VSX: 2.06B\n"); 32862306a36Sopenharmony_ci LOAD_VSX_XFORM_TEST(lxvd2x); 32962306a36Sopenharmony_ci LOAD_VSX_XFORM_TEST(lxvw4x); 33062306a36Sopenharmony_ci LOAD_VSX_XFORM_TEST(lxsdx); 33162306a36Sopenharmony_ci LOAD_VSX_XFORM_TEST(lxvdsx); 33262306a36Sopenharmony_ci STORE_VSX_XFORM_TEST(stxvd2x); 33362306a36Sopenharmony_ci STORE_VSX_XFORM_TEST(stxvw4x); 33462306a36Sopenharmony_ci STORE_VSX_XFORM_TEST(stxsdx); 33562306a36Sopenharmony_ci return rc; 33662306a36Sopenharmony_ci} 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ciint test_alignment_handler_vsx_207(void) 33962306a36Sopenharmony_ci{ 34062306a36Sopenharmony_ci int rc = 0; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci SKIP_IF(!can_open_cifile()); 34362306a36Sopenharmony_ci SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_2_07)); 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci printf("VSX: 2.07B\n"); 34662306a36Sopenharmony_ci LOAD_VSX_XFORM_TEST(lxsspx); 34762306a36Sopenharmony_ci LOAD_VSX_XFORM_TEST(lxsiwax); 34862306a36Sopenharmony_ci LOAD_VSX_XFORM_TEST(lxsiwzx); 34962306a36Sopenharmony_ci STORE_VSX_XFORM_TEST(stxsspx); 35062306a36Sopenharmony_ci STORE_VSX_XFORM_TEST(stxsiwx); 35162306a36Sopenharmony_ci return rc; 35262306a36Sopenharmony_ci} 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ciint test_alignment_handler_vsx_300(void) 35562306a36Sopenharmony_ci{ 35662306a36Sopenharmony_ci int rc = 0; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci SKIP_IF(!can_open_cifile()); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00)); 36162306a36Sopenharmony_ci printf("VSX: 3.00B\n"); 36262306a36Sopenharmony_ci LOAD_VMX_DFORM_TEST(lxsd); 36362306a36Sopenharmony_ci LOAD_VSX_XFORM_TEST(lxsibzx); 36462306a36Sopenharmony_ci LOAD_VSX_XFORM_TEST(lxsihzx); 36562306a36Sopenharmony_ci LOAD_VMX_DFORM_TEST(lxssp); 36662306a36Sopenharmony_ci LOAD_VSX_DFORM_TEST(lxv); 36762306a36Sopenharmony_ci LOAD_VSX_XFORM_TEST(lxvb16x); 36862306a36Sopenharmony_ci LOAD_VSX_XFORM_TEST(lxvh8x); 36962306a36Sopenharmony_ci LOAD_VSX_XFORM_TEST(lxvx); 37062306a36Sopenharmony_ci LOAD_VSX_XFORM_TEST(lxvwsx); 37162306a36Sopenharmony_ci LOAD_VSX_XFORM_TEST(lxvl); 37262306a36Sopenharmony_ci LOAD_VSX_XFORM_TEST(lxvll); 37362306a36Sopenharmony_ci STORE_VMX_DFORM_TEST(stxsd); 37462306a36Sopenharmony_ci STORE_VSX_XFORM_TEST(stxsibx); 37562306a36Sopenharmony_ci STORE_VSX_XFORM_TEST(stxsihx); 37662306a36Sopenharmony_ci STORE_VMX_DFORM_TEST(stxssp); 37762306a36Sopenharmony_ci STORE_VSX_DFORM_TEST(stxv); 37862306a36Sopenharmony_ci STORE_VSX_XFORM_TEST(stxvb16x); 37962306a36Sopenharmony_ci STORE_VSX_XFORM_TEST(stxvh8x); 38062306a36Sopenharmony_ci STORE_VSX_XFORM_TEST(stxvx); 38162306a36Sopenharmony_ci STORE_VSX_XFORM_TEST(stxvl); 38262306a36Sopenharmony_ci STORE_VSX_XFORM_TEST(stxvll); 38362306a36Sopenharmony_ci return rc; 38462306a36Sopenharmony_ci} 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ciint test_alignment_handler_vsx_prefix(void) 38762306a36Sopenharmony_ci{ 38862306a36Sopenharmony_ci int rc = 0; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci SKIP_IF(!can_open_cifile()); 39162306a36Sopenharmony_ci SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1)); 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci printf("VSX: PREFIX\n"); 39462306a36Sopenharmony_ci LOAD_VSX_8LS_PREFIX_TEST(PLXSD, 0); 39562306a36Sopenharmony_ci LOAD_VSX_8LS_PREFIX_TEST(PLXSSP, 0); 39662306a36Sopenharmony_ci LOAD_VSX_8LS_PREFIX_TEST(PLXV0, 0); 39762306a36Sopenharmony_ci LOAD_VSX_8LS_PREFIX_TEST(PLXV1, 1); 39862306a36Sopenharmony_ci STORE_VSX_8LS_PREFIX_TEST(PSTXSD, 0); 39962306a36Sopenharmony_ci STORE_VSX_8LS_PREFIX_TEST(PSTXSSP, 0); 40062306a36Sopenharmony_ci STORE_VSX_8LS_PREFIX_TEST(PSTXV0, 0); 40162306a36Sopenharmony_ci STORE_VSX_8LS_PREFIX_TEST(PSTXV1, 1); 40262306a36Sopenharmony_ci return rc; 40362306a36Sopenharmony_ci} 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ciint test_alignment_handler_integer(void) 40662306a36Sopenharmony_ci{ 40762306a36Sopenharmony_ci int rc = 0; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci SKIP_IF(!can_open_cifile()); 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci printf("Integer\n"); 41262306a36Sopenharmony_ci LOAD_DFORM_TEST(lbz); 41362306a36Sopenharmony_ci LOAD_DFORM_TEST(lbzu); 41462306a36Sopenharmony_ci LOAD_XFORM_TEST(lbzx); 41562306a36Sopenharmony_ci LOAD_XFORM_TEST(lbzux); 41662306a36Sopenharmony_ci LOAD_DFORM_TEST(lhz); 41762306a36Sopenharmony_ci LOAD_DFORM_TEST(lhzu); 41862306a36Sopenharmony_ci LOAD_XFORM_TEST(lhzx); 41962306a36Sopenharmony_ci LOAD_XFORM_TEST(lhzux); 42062306a36Sopenharmony_ci LOAD_DFORM_TEST(lha); 42162306a36Sopenharmony_ci LOAD_DFORM_TEST(lhau); 42262306a36Sopenharmony_ci LOAD_XFORM_TEST(lhax); 42362306a36Sopenharmony_ci LOAD_XFORM_TEST(lhaux); 42462306a36Sopenharmony_ci LOAD_XFORM_TEST(lhbrx); 42562306a36Sopenharmony_ci LOAD_DFORM_TEST(lwz); 42662306a36Sopenharmony_ci LOAD_DFORM_TEST(lwzu); 42762306a36Sopenharmony_ci LOAD_XFORM_TEST(lwzx); 42862306a36Sopenharmony_ci LOAD_XFORM_TEST(lwzux); 42962306a36Sopenharmony_ci LOAD_DFORM_TEST(lwa); 43062306a36Sopenharmony_ci LOAD_XFORM_TEST(lwax); 43162306a36Sopenharmony_ci LOAD_XFORM_TEST(lwaux); 43262306a36Sopenharmony_ci LOAD_XFORM_TEST(lwbrx); 43362306a36Sopenharmony_ci LOAD_DFORM_TEST(ld); 43462306a36Sopenharmony_ci LOAD_DFORM_TEST(ldu); 43562306a36Sopenharmony_ci LOAD_XFORM_TEST(ldx); 43662306a36Sopenharmony_ci LOAD_XFORM_TEST(ldux); 43762306a36Sopenharmony_ci STORE_DFORM_TEST(stb); 43862306a36Sopenharmony_ci STORE_XFORM_TEST(stbx); 43962306a36Sopenharmony_ci STORE_DFORM_TEST(stbu); 44062306a36Sopenharmony_ci STORE_XFORM_TEST(stbux); 44162306a36Sopenharmony_ci STORE_DFORM_TEST(sth); 44262306a36Sopenharmony_ci STORE_XFORM_TEST(sthx); 44362306a36Sopenharmony_ci STORE_DFORM_TEST(sthu); 44462306a36Sopenharmony_ci STORE_XFORM_TEST(sthux); 44562306a36Sopenharmony_ci STORE_XFORM_TEST(sthbrx); 44662306a36Sopenharmony_ci STORE_DFORM_TEST(stw); 44762306a36Sopenharmony_ci STORE_XFORM_TEST(stwx); 44862306a36Sopenharmony_ci STORE_DFORM_TEST(stwu); 44962306a36Sopenharmony_ci STORE_XFORM_TEST(stwux); 45062306a36Sopenharmony_ci STORE_XFORM_TEST(stwbrx); 45162306a36Sopenharmony_ci STORE_DFORM_TEST(std); 45262306a36Sopenharmony_ci STORE_XFORM_TEST(stdx); 45362306a36Sopenharmony_ci STORE_DFORM_TEST(stdu); 45462306a36Sopenharmony_ci STORE_XFORM_TEST(stdux); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci#ifdef __BIG_ENDIAN__ 45762306a36Sopenharmony_ci LOAD_DFORM_TEST(lmw); 45862306a36Sopenharmony_ci STORE_DFORM_TEST(stmw); 45962306a36Sopenharmony_ci#endif 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci return rc; 46262306a36Sopenharmony_ci} 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ciint test_alignment_handler_integer_206(void) 46562306a36Sopenharmony_ci{ 46662306a36Sopenharmony_ci int rc = 0; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci SKIP_IF(!can_open_cifile()); 46962306a36Sopenharmony_ci SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06)); 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci printf("Integer: 2.06\n"); 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci LOAD_XFORM_TEST(ldbrx); 47462306a36Sopenharmony_ci STORE_XFORM_TEST(stdbrx); 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci return rc; 47762306a36Sopenharmony_ci} 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ciint test_alignment_handler_integer_prefix(void) 48062306a36Sopenharmony_ci{ 48162306a36Sopenharmony_ci int rc = 0; 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci SKIP_IF(!can_open_cifile()); 48462306a36Sopenharmony_ci SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1)); 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci printf("Integer: PREFIX\n"); 48762306a36Sopenharmony_ci LOAD_MLS_PREFIX_TEST(PLBZ); 48862306a36Sopenharmony_ci LOAD_MLS_PREFIX_TEST(PLHZ); 48962306a36Sopenharmony_ci LOAD_MLS_PREFIX_TEST(PLHA); 49062306a36Sopenharmony_ci LOAD_MLS_PREFIX_TEST(PLWZ); 49162306a36Sopenharmony_ci LOAD_8LS_PREFIX_TEST(PLWA); 49262306a36Sopenharmony_ci LOAD_8LS_PREFIX_TEST(PLD); 49362306a36Sopenharmony_ci STORE_MLS_PREFIX_TEST(PSTB); 49462306a36Sopenharmony_ci STORE_MLS_PREFIX_TEST(PSTH); 49562306a36Sopenharmony_ci STORE_MLS_PREFIX_TEST(PSTW); 49662306a36Sopenharmony_ci STORE_8LS_PREFIX_TEST(PSTD); 49762306a36Sopenharmony_ci return rc; 49862306a36Sopenharmony_ci} 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ciint test_alignment_handler_vmx(void) 50162306a36Sopenharmony_ci{ 50262306a36Sopenharmony_ci int rc = 0; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci SKIP_IF(!can_open_cifile()); 50562306a36Sopenharmony_ci SKIP_IF(!have_hwcap(PPC_FEATURE_HAS_ALTIVEC)); 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci printf("VMX\n"); 50862306a36Sopenharmony_ci LOAD_VMX_XFORM_TEST(lvx); 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci /* 51162306a36Sopenharmony_ci * FIXME: These loads only load part of the register, so our 51262306a36Sopenharmony_ci * testing method doesn't work. Also they don't take alignment 51362306a36Sopenharmony_ci * faults, so it's kinda pointless anyway 51462306a36Sopenharmony_ci * 51562306a36Sopenharmony_ci LOAD_VMX_XFORM_TEST(lvebx) 51662306a36Sopenharmony_ci LOAD_VMX_XFORM_TEST(lvehx) 51762306a36Sopenharmony_ci LOAD_VMX_XFORM_TEST(lvewx) 51862306a36Sopenharmony_ci LOAD_VMX_XFORM_TEST(lvxl) 51962306a36Sopenharmony_ci */ 52062306a36Sopenharmony_ci STORE_VMX_XFORM_TEST(stvx); 52162306a36Sopenharmony_ci STORE_VMX_XFORM_TEST(stvebx); 52262306a36Sopenharmony_ci STORE_VMX_XFORM_TEST(stvehx); 52362306a36Sopenharmony_ci STORE_VMX_XFORM_TEST(stvewx); 52462306a36Sopenharmony_ci STORE_VMX_XFORM_TEST(stvxl); 52562306a36Sopenharmony_ci return rc; 52662306a36Sopenharmony_ci} 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ciint test_alignment_handler_fp(void) 52962306a36Sopenharmony_ci{ 53062306a36Sopenharmony_ci int rc = 0; 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci SKIP_IF(!can_open_cifile()); 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci printf("Floating point\n"); 53562306a36Sopenharmony_ci LOAD_FLOAT_DFORM_TEST(lfd); 53662306a36Sopenharmony_ci LOAD_FLOAT_XFORM_TEST(lfdx); 53762306a36Sopenharmony_ci LOAD_FLOAT_DFORM_TEST(lfdu); 53862306a36Sopenharmony_ci LOAD_FLOAT_XFORM_TEST(lfdux); 53962306a36Sopenharmony_ci LOAD_FLOAT_DFORM_TEST(lfs); 54062306a36Sopenharmony_ci LOAD_FLOAT_XFORM_TEST(lfsx); 54162306a36Sopenharmony_ci LOAD_FLOAT_DFORM_TEST(lfsu); 54262306a36Sopenharmony_ci LOAD_FLOAT_XFORM_TEST(lfsux); 54362306a36Sopenharmony_ci STORE_FLOAT_DFORM_TEST(stfd); 54462306a36Sopenharmony_ci STORE_FLOAT_XFORM_TEST(stfdx); 54562306a36Sopenharmony_ci STORE_FLOAT_DFORM_TEST(stfdu); 54662306a36Sopenharmony_ci STORE_FLOAT_XFORM_TEST(stfdux); 54762306a36Sopenharmony_ci STORE_FLOAT_DFORM_TEST(stfs); 54862306a36Sopenharmony_ci STORE_FLOAT_XFORM_TEST(stfsx); 54962306a36Sopenharmony_ci STORE_FLOAT_DFORM_TEST(stfsu); 55062306a36Sopenharmony_ci STORE_FLOAT_XFORM_TEST(stfsux); 55162306a36Sopenharmony_ci STORE_FLOAT_XFORM_TEST(stfiwx); 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci return rc; 55462306a36Sopenharmony_ci} 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ciint test_alignment_handler_fp_205(void) 55762306a36Sopenharmony_ci{ 55862306a36Sopenharmony_ci int rc = 0; 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci SKIP_IF(!can_open_cifile()); 56162306a36Sopenharmony_ci SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_05)); 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci printf("Floating point: 2.05\n"); 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci LOAD_FLOAT_DFORM_TEST(lfdp); 56662306a36Sopenharmony_ci LOAD_FLOAT_XFORM_TEST(lfdpx); 56762306a36Sopenharmony_ci LOAD_FLOAT_XFORM_TEST(lfiwax); 56862306a36Sopenharmony_ci STORE_FLOAT_DFORM_TEST(stfdp); 56962306a36Sopenharmony_ci STORE_FLOAT_XFORM_TEST(stfdpx); 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci return rc; 57262306a36Sopenharmony_ci} 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ciint test_alignment_handler_fp_206(void) 57562306a36Sopenharmony_ci{ 57662306a36Sopenharmony_ci int rc = 0; 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci SKIP_IF(!can_open_cifile()); 57962306a36Sopenharmony_ci SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06)); 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci printf("Floating point: 2.06\n"); 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci LOAD_FLOAT_XFORM_TEST(lfiwzx); 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci return rc; 58662306a36Sopenharmony_ci} 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ciint test_alignment_handler_fp_prefix(void) 59062306a36Sopenharmony_ci{ 59162306a36Sopenharmony_ci int rc = 0; 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci SKIP_IF(!can_open_cifile()); 59462306a36Sopenharmony_ci SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1)); 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci printf("Floating point: PREFIX\n"); 59762306a36Sopenharmony_ci LOAD_FLOAT_DFORM_TEST(lfs); 59862306a36Sopenharmony_ci LOAD_FLOAT_MLS_PREFIX_TEST(PLFS); 59962306a36Sopenharmony_ci LOAD_FLOAT_MLS_PREFIX_TEST(PLFD); 60062306a36Sopenharmony_ci STORE_FLOAT_MLS_PREFIX_TEST(PSTFS); 60162306a36Sopenharmony_ci STORE_FLOAT_MLS_PREFIX_TEST(PSTFD); 60262306a36Sopenharmony_ci return rc; 60362306a36Sopenharmony_ci} 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_civoid usage(char *prog) 60662306a36Sopenharmony_ci{ 60762306a36Sopenharmony_ci printf("Usage: %s [options] [path [offset]]\n", prog); 60862306a36Sopenharmony_ci printf(" -d Enable debug error output\n"); 60962306a36Sopenharmony_ci printf("\n"); 61062306a36Sopenharmony_ci printf("This test requires a POWER8, POWER9 or POWER10 CPU "); 61162306a36Sopenharmony_ci printf("and either a usable framebuffer at /dev/fb0 or "); 61262306a36Sopenharmony_ci printf("the path to usable cache inhibited memory and optional "); 61362306a36Sopenharmony_ci printf("offset to be provided\n"); 61462306a36Sopenharmony_ci} 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ciint main(int argc, char *argv[]) 61762306a36Sopenharmony_ci{ 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci struct sigaction sa; 62062306a36Sopenharmony_ci int rc = 0; 62162306a36Sopenharmony_ci int option = 0; 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci while ((option = getopt(argc, argv, "d")) != -1) { 62462306a36Sopenharmony_ci switch (option) { 62562306a36Sopenharmony_ci case 'd': 62662306a36Sopenharmony_ci debug++; 62762306a36Sopenharmony_ci break; 62862306a36Sopenharmony_ci default: 62962306a36Sopenharmony_ci usage(argv[0]); 63062306a36Sopenharmony_ci exit(1); 63162306a36Sopenharmony_ci } 63262306a36Sopenharmony_ci } 63362306a36Sopenharmony_ci argc -= optind; 63462306a36Sopenharmony_ci argv += optind; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci if (argc > 0) 63762306a36Sopenharmony_ci cipath = argv[0]; 63862306a36Sopenharmony_ci if (argc > 1) 63962306a36Sopenharmony_ci cioffset = strtol(argv[1], 0, 0x10); 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci bufsize = getpagesize(); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci sa.sa_sigaction = sighandler; 64462306a36Sopenharmony_ci sigemptyset(&sa.sa_mask); 64562306a36Sopenharmony_ci sa.sa_flags = SA_SIGINFO; 64662306a36Sopenharmony_ci if (sigaction(SIGSEGV, &sa, NULL) == -1 64762306a36Sopenharmony_ci || sigaction(SIGBUS, &sa, NULL) == -1 64862306a36Sopenharmony_ci || sigaction(SIGILL, &sa, NULL) == -1) { 64962306a36Sopenharmony_ci perror("sigaction"); 65062306a36Sopenharmony_ci exit(1); 65162306a36Sopenharmony_ci } 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci prefixes_enabled = have_hwcap2(PPC_FEATURE2_ARCH_3_1); 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci rc |= test_harness(test_alignment_handler_vsx_206, 65662306a36Sopenharmony_ci "test_alignment_handler_vsx_206"); 65762306a36Sopenharmony_ci rc |= test_harness(test_alignment_handler_vsx_207, 65862306a36Sopenharmony_ci "test_alignment_handler_vsx_207"); 65962306a36Sopenharmony_ci rc |= test_harness(test_alignment_handler_vsx_300, 66062306a36Sopenharmony_ci "test_alignment_handler_vsx_300"); 66162306a36Sopenharmony_ci rc |= test_harness(test_alignment_handler_vsx_prefix, 66262306a36Sopenharmony_ci "test_alignment_handler_vsx_prefix"); 66362306a36Sopenharmony_ci rc |= test_harness(test_alignment_handler_integer, 66462306a36Sopenharmony_ci "test_alignment_handler_integer"); 66562306a36Sopenharmony_ci rc |= test_harness(test_alignment_handler_integer_206, 66662306a36Sopenharmony_ci "test_alignment_handler_integer_206"); 66762306a36Sopenharmony_ci rc |= test_harness(test_alignment_handler_integer_prefix, 66862306a36Sopenharmony_ci "test_alignment_handler_integer_prefix"); 66962306a36Sopenharmony_ci rc |= test_harness(test_alignment_handler_vmx, 67062306a36Sopenharmony_ci "test_alignment_handler_vmx"); 67162306a36Sopenharmony_ci rc |= test_harness(test_alignment_handler_fp, 67262306a36Sopenharmony_ci "test_alignment_handler_fp"); 67362306a36Sopenharmony_ci rc |= test_harness(test_alignment_handler_fp_205, 67462306a36Sopenharmony_ci "test_alignment_handler_fp_205"); 67562306a36Sopenharmony_ci rc |= test_harness(test_alignment_handler_fp_206, 67662306a36Sopenharmony_ci "test_alignment_handler_fp_206"); 67762306a36Sopenharmony_ci rc |= test_harness(test_alignment_handler_fp_prefix, 67862306a36Sopenharmony_ci "test_alignment_handler_fp_prefix"); 67962306a36Sopenharmony_ci return rc; 68062306a36Sopenharmony_ci} 681