2019-05-27 08:55:01 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2017-10-16 16:04:02 +11:00
/*
* Test the powerpc alignment handler on POWER8 / POWER9
*
* Copyright ( C ) 2017 IBM Corporation ( Michael Neuling , Andrew Donnellan )
*/
/*
* This selftest exercises the powerpc alignment fault handler .
*
* We create two sets of source and destination buffers , one in regular memory ,
2020-05-20 12:11:02 +10:00
* the other cache - inhibited ( by default we use / dev / fb0 for this , but an
2021-02-25 14:21:07 +11:00
* alterative path for cache - inhibited memory may be provided , e . g . memtrace ) .
2017-10-16 16:04:02 +11:00
*
* We initialise the source buffers , then use whichever set of load / store
* instructions is under test to copy bytes from the source buffers to the
* destination buffers . For the regular buffers , these instructions will
* execute normally . For the cache - inhibited buffers , these instructions
* will trap and cause an alignment fault , and the alignment fault handler
* will emulate the particular instruction under test . We then compare the
* destination buffers to ensure that the native and emulated cases give the
* same result .
*
* TODO :
* - Any FIXMEs below
* - Test VSX regs < 32 and > 32
* - Test all loads and stores
* - Check update forms do update register
* - Test alignment faults over page boundary
*
* Some old binutils may not support all the instructions .
*/
# include <sys/mman.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <unistd.h>
2018-07-31 22:08:41 +10:00
# include <stdbool.h>
2017-10-16 16:04:02 +11:00
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <assert.h>
# include <getopt.h>
# include <setjmp.h>
# include <signal.h>
# include "utils.h"
2020-05-20 12:11:03 +10:00
# include "instructions.h"
2017-10-16 16:04:02 +11:00
int bufsize ;
int debug ;
int testing ;
volatile int gotsig ;
2020-08-24 23:12:31 +10:00
bool prefixes_enabled ;
2020-05-20 12:11:02 +10:00
char * cipath = " /dev/fb0 " ;
long cioffset ;
2017-10-16 16:04:02 +11:00
void sighandler ( int sig , siginfo_t * info , void * ctx )
{
2018-02-13 12:02:55 +05:30
ucontext_t * ucp = ctx ;
2017-10-16 16:04:02 +11:00
if ( ! testing ) {
signal ( sig , SIG_DFL ) ;
kill ( 0 , sig ) ;
}
gotsig = sig ;
# ifdef __powerpc64__
2020-08-24 23:12:31 +10:00
if ( prefixes_enabled ) {
u32 inst = * ( u32 * ) ucp - > uc_mcontext . gp_regs [ PT_NIP ] ;
ucp - > uc_mcontext . gp_regs [ PT_NIP ] + = ( ( inst > > 26 = = 1 ) ? 8 : 4 ) ;
} else {
ucp - > uc_mcontext . gp_regs [ PT_NIP ] + = 4 ;
}
2017-10-16 16:04:02 +11:00
# else
ucp - > uc_mcontext . uc_regs - > gregs [ PT_NIP ] + = 4 ;
# endif
}
# define XFORM(reg, n) " " #reg " ,%"#n",%2 ;"
# define DFORM(reg, n) " " #reg " ,0(%"#n") ;"
# define TEST(name, ld_op, st_op, form, ld_reg, st_reg) \
void test_ # # name ( char * s , char * d ) \
{ \
asm volatile ( \
# ld_op form(ld_reg, 0) \
# st_op form(st_reg, 1) \
: : " r " ( s ) , " r " ( d ) , " r " ( 0 ) \
: " memory " , " vs0 " , " vs32 " , " r31 " ) ; \
} \
rc | = do_test ( # name , test_ # # name )
2020-05-20 12:11:03 +10:00
# define TESTP(name, ld_op, st_op, ld_reg, st_reg) \
void test_ # # name ( char * s , char * d ) \
{ \
asm volatile ( \
ld_op ( ld_reg , % 0 , 0 , 0 ) \
st_op ( st_reg , % 1 , 0 , 0 ) \
: : " r " ( s ) , " r " ( d ) , " r " ( 0 ) \
: " memory " , " vs0 " , " vs32 " , " r31 " ) ; \
} \
rc | = do_test ( # name , test_ # # name )
2017-10-16 16:04:02 +11:00
# define LOAD_VSX_XFORM_TEST(op) TEST(op, op, stxvd2x, XFORM, 32, 32)
# define STORE_VSX_XFORM_TEST(op) TEST(op, lxvd2x, op, XFORM, 32, 32)
# define LOAD_VSX_DFORM_TEST(op) TEST(op, op, stxv, DFORM, 32, 32)
# define STORE_VSX_DFORM_TEST(op) TEST(op, lxv, op, DFORM, 32, 32)
# define LOAD_VMX_XFORM_TEST(op) TEST(op, op, stxvd2x, XFORM, 0, 32)
# define STORE_VMX_XFORM_TEST(op) TEST(op, lxvd2x, op, XFORM, 32, 0)
# define LOAD_VMX_DFORM_TEST(op) TEST(op, op, stxv, DFORM, 0, 32)
# define STORE_VMX_DFORM_TEST(op) TEST(op, lxv, op, DFORM, 32, 0)
# define LOAD_XFORM_TEST(op) TEST(op, op, stdx, XFORM, 31, 31)
# define STORE_XFORM_TEST(op) TEST(op, ldx, op, XFORM, 31, 31)
# define LOAD_DFORM_TEST(op) TEST(op, op, std, DFORM, 31, 31)
# define STORE_DFORM_TEST(op) TEST(op, ld, op, DFORM, 31, 31)
# define LOAD_FLOAT_DFORM_TEST(op) TEST(op, op, stfd, DFORM, 0, 0)
# define STORE_FLOAT_DFORM_TEST(op) TEST(op, lfd, op, DFORM, 0, 0)
# define LOAD_FLOAT_XFORM_TEST(op) TEST(op, op, stfdx, XFORM, 0, 0)
# define STORE_FLOAT_XFORM_TEST(op) TEST(op, lfdx, op, XFORM, 0, 0)
2020-05-20 12:11:03 +10:00
# define LOAD_MLS_PREFIX_TEST(op) TESTP(op, op, PSTD, 31, 31)
# define STORE_MLS_PREFIX_TEST(op) TESTP(op, PLD, op, 31, 31)
# define LOAD_8LS_PREFIX_TEST(op) TESTP(op, op, PSTD, 31, 31)
# define STORE_8LS_PREFIX_TEST(op) TESTP(op, PLD, op, 31, 31)
# define LOAD_FLOAT_MLS_PREFIX_TEST(op) TESTP(op, op, PSTFD, 0, 0)
# define STORE_FLOAT_MLS_PREFIX_TEST(op) TESTP(op, PLFD, op, 0, 0)
# define LOAD_VSX_8LS_PREFIX_TEST(op, tail) TESTP(op, op, PSTXV ## tail, 0, 32)
# define STORE_VSX_8LS_PREFIX_TEST(op, tail) TESTP(op, PLXV ## tail, op, 32, 0)
2017-10-16 16:04:02 +11:00
/* FIXME: Unimplemented tests: */
// STORE_DFORM_TEST(stq) /* FIXME: need two registers for quad */
// STORE_DFORM_TEST(stswi) /* FIXME: string instruction */
// STORE_XFORM_TEST(stwat) /* AMO can't emulate or run on CI */
// STORE_XFORM_TEST(stdat) /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
/* preload byte by byte */
void preload_data ( void * dst , int offset , int width )
{
char * c = dst ;
int i ;
c + = offset ;
for ( i = 0 ; i < width ; i + + )
c [ i ] = i ;
}
int test_memcpy ( void * dst , void * src , int size , int offset ,
void ( * test_func ) ( char * , char * ) )
{
char * s , * d ;
s = src ;
s + = offset ;
d = dst ;
d + = offset ;
assert ( size = = 16 ) ;
gotsig = 0 ;
testing = 1 ;
test_func ( s , d ) ; /* run the actual test */
testing = 0 ;
if ( gotsig ) {
if ( debug )
printf ( " Got signal %i \n " , gotsig ) ;
return 1 ;
}
return 0 ;
}
void dumpdata ( char * s1 , char * s2 , int n , char * test_name )
{
int i ;
printf ( " %s: unexpected result: \n " , test_name ) ;
printf ( " mem: " ) ;
for ( i = 0 ; i < n ; i + + )
printf ( " %02x " , s1 [ i ] ) ;
printf ( " \n " ) ;
printf ( " ci: " ) ;
for ( i = 0 ; i < n ; i + + )
printf ( " %02x " , s2 [ i ] ) ;
printf ( " \n " ) ;
}
int test_memcmp ( void * s1 , void * s2 , int n , int offset , char * test_name )
{
char * s1c , * s2c ;
s1c = s1 ;
s1c + = offset ;
s2c = s2 ;
s2c + = offset ;
if ( memcmp ( s1c , s2c , n ) ) {
if ( debug ) {
printf ( " \n Compare failed. Offset:%i length:%i \n " ,
offset , n ) ;
dumpdata ( s1c , s2c , n , test_name ) ;
}
return 1 ;
}
return 0 ;
}
/*
* Do two memcpy tests using the same instructions . One cachable
* memory and the other doesn ' t .
*/
int do_test ( char * test_name , void ( * test_func ) ( char * , char * ) )
{
2018-07-31 22:08:41 +10:00
int offset , width , fd , rc , r ;
2017-10-16 16:04:02 +11:00
void * mem0 , * mem1 , * ci0 , * ci1 ;
printf ( " \t Doing %s: \t " , test_name ) ;
2020-05-20 12:11:02 +10:00
fd = open ( cipath , O_RDWR ) ;
2017-10-16 16:04:02 +11:00
if ( fd < 0 ) {
printf ( " \n " ) ;
2020-05-20 12:11:02 +10:00
perror ( " Can't open ci file now? " ) ;
2018-07-31 22:08:41 +10:00
return 1 ;
2017-10-16 16:04:02 +11:00
}
2020-05-20 12:11:02 +10:00
ci0 = mmap ( NULL , bufsize , PROT_WRITE | PROT_READ , MAP_SHARED ,
fd , cioffset ) ;
ci1 = mmap ( NULL , bufsize , PROT_WRITE | PROT_READ , MAP_SHARED ,
fd , cioffset + bufsize ) ;
2017-10-16 16:04:02 +11:00
if ( ( ci0 = = MAP_FAILED ) | | ( ci1 = = MAP_FAILED ) ) {
printf ( " \n " ) ;
perror ( " mmap failed " ) ;
SKIP_IF ( 1 ) ;
}
rc = posix_memalign ( & mem0 , bufsize , bufsize ) ;
if ( rc ) {
printf ( " \n " ) ;
return rc ;
}
rc = posix_memalign ( & mem1 , bufsize , bufsize ) ;
if ( rc ) {
printf ( " \n " ) ;
free ( mem0 ) ;
return rc ;
}
2018-07-31 22:08:41 +10:00
rc = 0 ;
2020-10-13 15:37:41 +11:00
/*
* offset = 0 is aligned but tests the workaround for the P9N
* DD2 .1 vector CI load issue ( see 5080332 c2c89 " powerpc/64s:
* Add workaround for P9 vector CI load issue " )
*/
for ( offset = 0 ; offset < 16 ; offset + + ) {
2017-10-16 16:04:02 +11:00
width = 16 ; /* vsx == 16 bytes */
r = 0 ;
/* load pattern into memory byte by byte */
preload_data ( ci0 , offset , width ) ;
preload_data ( mem0 , offset , width ) ; // FIXME: remove??
memcpy ( ci0 , mem0 , bufsize ) ;
memcpy ( ci1 , mem1 , bufsize ) ; /* initialise output to the same */
/* sanity check */
test_memcmp ( mem0 , ci0 , width , offset , test_name ) ;
r | = test_memcpy ( ci1 , ci0 , width , offset , test_func ) ;
r | = test_memcpy ( mem1 , mem0 , width , offset , test_func ) ;
if ( r & & ! debug ) {
printf ( " FAILED: Got signal " ) ;
2018-07-31 22:08:41 +10:00
rc = 1 ;
2017-10-16 16:04:02 +11:00
break ;
}
r | = test_memcmp ( mem1 , ci1 , width , offset , test_name ) ;
if ( r & & ! debug ) {
printf ( " FAILED: Wrong Data " ) ;
2018-07-31 22:08:41 +10:00
rc = 1 ;
2017-10-16 16:04:02 +11:00
break ;
}
}
2018-07-31 22:08:41 +10:00
if ( rc = = 0 )
2017-10-16 16:04:02 +11:00
printf ( " PASSED " ) ;
2018-07-31 22:08:41 +10:00
2017-10-16 16:04:02 +11:00
printf ( " \n " ) ;
munmap ( ci0 , bufsize ) ;
munmap ( ci1 , bufsize ) ;
free ( mem0 ) ;
free ( mem1 ) ;
2018-07-31 22:08:41 +10:00
close ( fd ) ;
2017-10-16 16:04:02 +11:00
return rc ;
}
2020-05-20 12:11:02 +10:00
static bool can_open_cifile ( void )
2018-07-31 22:08:41 +10:00
{
int fd ;
2020-05-20 12:11:02 +10:00
fd = open ( cipath , O_RDWR ) ;
2018-07-31 22:08:41 +10:00
if ( fd < 0 )
return false ;
close ( fd ) ;
return true ;
}
2017-10-16 16:04:02 +11:00
int test_alignment_handler_vsx_206 ( void )
{
int rc = 0 ;
2020-05-20 12:11:02 +10:00
SKIP_IF ( ! can_open_cifile ( ) ) ;
2018-07-31 22:08:42 +10:00
SKIP_IF ( ! have_hwcap ( PPC_FEATURE_ARCH_2_06 ) ) ;
2018-07-31 22:08:41 +10:00
2017-10-16 16:04:02 +11:00
printf ( " VSX: 2.06B \n " ) ;
LOAD_VSX_XFORM_TEST ( lxvd2x ) ;
LOAD_VSX_XFORM_TEST ( lxvw4x ) ;
LOAD_VSX_XFORM_TEST ( lxsdx ) ;
LOAD_VSX_XFORM_TEST ( lxvdsx ) ;
STORE_VSX_XFORM_TEST ( stxvd2x ) ;
STORE_VSX_XFORM_TEST ( stxvw4x ) ;
STORE_VSX_XFORM_TEST ( stxsdx ) ;
return rc ;
}
int test_alignment_handler_vsx_207 ( void )
{
int rc = 0 ;
2020-05-20 12:11:02 +10:00
SKIP_IF ( ! can_open_cifile ( ) ) ;
2018-07-31 22:08:42 +10:00
SKIP_IF ( ! have_hwcap2 ( PPC_FEATURE2_ARCH_2_07 ) ) ;
2018-07-31 22:08:41 +10:00
2017-10-16 16:04:02 +11:00
printf ( " VSX: 2.07B \n " ) ;
LOAD_VSX_XFORM_TEST ( lxsspx ) ;
LOAD_VSX_XFORM_TEST ( lxsiwax ) ;
LOAD_VSX_XFORM_TEST ( lxsiwzx ) ;
STORE_VSX_XFORM_TEST ( stxsspx ) ;
STORE_VSX_XFORM_TEST ( stxsiwx ) ;
return rc ;
}
int test_alignment_handler_vsx_300 ( void )
{
int rc = 0 ;
2020-05-20 12:11:02 +10:00
SKIP_IF ( ! can_open_cifile ( ) ) ;
2018-07-31 22:08:41 +10:00
2017-10-16 16:04:02 +11:00
SKIP_IF ( ! have_hwcap2 ( PPC_FEATURE2_ARCH_3_00 ) ) ;
printf ( " VSX: 3.00B \n " ) ;
LOAD_VMX_DFORM_TEST ( lxsd ) ;
LOAD_VSX_XFORM_TEST ( lxsibzx ) ;
LOAD_VSX_XFORM_TEST ( lxsihzx ) ;
LOAD_VMX_DFORM_TEST ( lxssp ) ;
LOAD_VSX_DFORM_TEST ( lxv ) ;
LOAD_VSX_XFORM_TEST ( lxvb16x ) ;
LOAD_VSX_XFORM_TEST ( lxvh8x ) ;
LOAD_VSX_XFORM_TEST ( lxvx ) ;
LOAD_VSX_XFORM_TEST ( lxvwsx ) ;
LOAD_VSX_XFORM_TEST ( lxvl ) ;
LOAD_VSX_XFORM_TEST ( lxvll ) ;
STORE_VMX_DFORM_TEST ( stxsd ) ;
STORE_VSX_XFORM_TEST ( stxsibx ) ;
STORE_VSX_XFORM_TEST ( stxsihx ) ;
STORE_VMX_DFORM_TEST ( stxssp ) ;
STORE_VSX_DFORM_TEST ( stxv ) ;
STORE_VSX_XFORM_TEST ( stxvb16x ) ;
STORE_VSX_XFORM_TEST ( stxvh8x ) ;
STORE_VSX_XFORM_TEST ( stxvx ) ;
STORE_VSX_XFORM_TEST ( stxvl ) ;
STORE_VSX_XFORM_TEST ( stxvll ) ;
return rc ;
}
2020-05-20 12:11:03 +10:00
int test_alignment_handler_vsx_prefix ( void )
{
int rc = 0 ;
SKIP_IF ( ! can_open_cifile ( ) ) ;
SKIP_IF ( ! have_hwcap2 ( PPC_FEATURE2_ARCH_3_1 ) ) ;
printf ( " VSX: PREFIX \n " ) ;
LOAD_VSX_8LS_PREFIX_TEST ( PLXSD , 0 ) ;
LOAD_VSX_8LS_PREFIX_TEST ( PLXSSP , 0 ) ;
LOAD_VSX_8LS_PREFIX_TEST ( PLXV0 , 0 ) ;
LOAD_VSX_8LS_PREFIX_TEST ( PLXV1 , 1 ) ;
STORE_VSX_8LS_PREFIX_TEST ( PSTXSD , 0 ) ;
STORE_VSX_8LS_PREFIX_TEST ( PSTXSSP , 0 ) ;
STORE_VSX_8LS_PREFIX_TEST ( PSTXV0 , 0 ) ;
STORE_VSX_8LS_PREFIX_TEST ( PSTXV1 , 1 ) ;
return rc ;
}
2017-10-16 16:04:02 +11:00
int test_alignment_handler_integer ( void )
{
int rc = 0 ;
2020-05-20 12:11:02 +10:00
SKIP_IF ( ! can_open_cifile ( ) ) ;
2018-07-31 22:08:41 +10:00
2017-10-16 16:04:02 +11:00
printf ( " Integer \n " ) ;
LOAD_DFORM_TEST ( lbz ) ;
LOAD_DFORM_TEST ( lbzu ) ;
LOAD_XFORM_TEST ( lbzx ) ;
LOAD_XFORM_TEST ( lbzux ) ;
LOAD_DFORM_TEST ( lhz ) ;
LOAD_DFORM_TEST ( lhzu ) ;
LOAD_XFORM_TEST ( lhzx ) ;
LOAD_XFORM_TEST ( lhzux ) ;
LOAD_DFORM_TEST ( lha ) ;
LOAD_DFORM_TEST ( lhau ) ;
LOAD_XFORM_TEST ( lhax ) ;
LOAD_XFORM_TEST ( lhaux ) ;
LOAD_XFORM_TEST ( lhbrx ) ;
LOAD_DFORM_TEST ( lwz ) ;
LOAD_DFORM_TEST ( lwzu ) ;
LOAD_XFORM_TEST ( lwzx ) ;
LOAD_XFORM_TEST ( lwzux ) ;
LOAD_DFORM_TEST ( lwa ) ;
LOAD_XFORM_TEST ( lwax ) ;
LOAD_XFORM_TEST ( lwaux ) ;
LOAD_XFORM_TEST ( lwbrx ) ;
LOAD_DFORM_TEST ( ld ) ;
LOAD_DFORM_TEST ( ldu ) ;
LOAD_XFORM_TEST ( ldx ) ;
LOAD_XFORM_TEST ( ldux ) ;
STORE_DFORM_TEST ( stb ) ;
STORE_XFORM_TEST ( stbx ) ;
STORE_DFORM_TEST ( stbu ) ;
STORE_XFORM_TEST ( stbux ) ;
STORE_DFORM_TEST ( sth ) ;
STORE_XFORM_TEST ( sthx ) ;
STORE_DFORM_TEST ( sthu ) ;
STORE_XFORM_TEST ( sthux ) ;
STORE_XFORM_TEST ( sthbrx ) ;
STORE_DFORM_TEST ( stw ) ;
STORE_XFORM_TEST ( stwx ) ;
STORE_DFORM_TEST ( stwu ) ;
STORE_XFORM_TEST ( stwux ) ;
STORE_XFORM_TEST ( stwbrx ) ;
STORE_DFORM_TEST ( std ) ;
STORE_XFORM_TEST ( stdx ) ;
STORE_DFORM_TEST ( stdu ) ;
STORE_XFORM_TEST ( stdux ) ;
2021-01-19 15:18:00 +11:00
# ifdef __BIG_ENDIAN__
LOAD_DFORM_TEST ( lmw ) ;
2017-10-16 16:04:02 +11:00
STORE_DFORM_TEST ( stmw ) ;
2021-01-19 15:18:00 +11:00
# endif
2018-07-31 22:08:42 +10:00
return rc ;
}
int test_alignment_handler_integer_206 ( void )
{
int rc = 0 ;
2020-05-20 12:11:02 +10:00
SKIP_IF ( ! can_open_cifile ( ) ) ;
2018-07-31 22:08:42 +10:00
SKIP_IF ( ! have_hwcap ( PPC_FEATURE_ARCH_2_06 ) ) ;
printf ( " Integer: 2.06 \n " ) ;
LOAD_XFORM_TEST ( ldbrx ) ;
STORE_XFORM_TEST ( stdbrx ) ;
2017-10-16 16:04:02 +11:00
return rc ;
}
2020-05-20 12:11:03 +10:00
int test_alignment_handler_integer_prefix ( void )
{
int rc = 0 ;
SKIP_IF ( ! can_open_cifile ( ) ) ;
SKIP_IF ( ! have_hwcap2 ( PPC_FEATURE2_ARCH_3_1 ) ) ;
printf ( " Integer: PREFIX \n " ) ;
LOAD_MLS_PREFIX_TEST ( PLBZ ) ;
LOAD_MLS_PREFIX_TEST ( PLHZ ) ;
LOAD_MLS_PREFIX_TEST ( PLHA ) ;
LOAD_MLS_PREFIX_TEST ( PLWZ ) ;
LOAD_8LS_PREFIX_TEST ( PLWA ) ;
LOAD_8LS_PREFIX_TEST ( PLD ) ;
STORE_MLS_PREFIX_TEST ( PSTB ) ;
STORE_MLS_PREFIX_TEST ( PSTH ) ;
STORE_MLS_PREFIX_TEST ( PSTW ) ;
STORE_8LS_PREFIX_TEST ( PSTD ) ;
return rc ;
}
2017-10-16 16:04:02 +11:00
int test_alignment_handler_vmx ( void )
{
int rc = 0 ;
2020-05-20 12:11:02 +10:00
SKIP_IF ( ! can_open_cifile ( ) ) ;
2018-07-31 22:08:42 +10:00
SKIP_IF ( ! have_hwcap ( PPC_FEATURE_HAS_ALTIVEC ) ) ;
2018-07-31 22:08:41 +10:00
2017-10-16 16:04:02 +11:00
printf ( " VMX \n " ) ;
LOAD_VMX_XFORM_TEST ( lvx ) ;
/*
* FIXME : These loads only load part of the register , so our
* testing method doesn ' t work . Also they don ' t take alignment
* faults , so it ' s kinda pointless anyway
*
LOAD_VMX_XFORM_TEST ( lvebx )
LOAD_VMX_XFORM_TEST ( lvehx )
LOAD_VMX_XFORM_TEST ( lvewx )
LOAD_VMX_XFORM_TEST ( lvxl )
*/
STORE_VMX_XFORM_TEST ( stvx ) ;
STORE_VMX_XFORM_TEST ( stvebx ) ;
STORE_VMX_XFORM_TEST ( stvehx ) ;
STORE_VMX_XFORM_TEST ( stvewx ) ;
STORE_VMX_XFORM_TEST ( stvxl ) ;
return rc ;
}
int test_alignment_handler_fp ( void )
{
int rc = 0 ;
2020-05-20 12:11:02 +10:00
SKIP_IF ( ! can_open_cifile ( ) ) ;
2018-07-31 22:08:41 +10:00
2017-10-16 16:04:02 +11:00
printf ( " Floating point \n " ) ;
LOAD_FLOAT_DFORM_TEST ( lfd ) ;
LOAD_FLOAT_XFORM_TEST ( lfdx ) ;
LOAD_FLOAT_DFORM_TEST ( lfdu ) ;
LOAD_FLOAT_XFORM_TEST ( lfdux ) ;
LOAD_FLOAT_DFORM_TEST ( lfs ) ;
LOAD_FLOAT_XFORM_TEST ( lfsx ) ;
LOAD_FLOAT_DFORM_TEST ( lfsu ) ;
LOAD_FLOAT_XFORM_TEST ( lfsux ) ;
STORE_FLOAT_DFORM_TEST ( stfd ) ;
STORE_FLOAT_XFORM_TEST ( stfdx ) ;
STORE_FLOAT_DFORM_TEST ( stfdu ) ;
STORE_FLOAT_XFORM_TEST ( stfdux ) ;
STORE_FLOAT_DFORM_TEST ( stfs ) ;
STORE_FLOAT_XFORM_TEST ( stfsx ) ;
STORE_FLOAT_DFORM_TEST ( stfsu ) ;
STORE_FLOAT_XFORM_TEST ( stfsux ) ;
STORE_FLOAT_XFORM_TEST ( stfiwx ) ;
return rc ;
}
2018-07-31 22:08:42 +10:00
int test_alignment_handler_fp_205 ( void )
{
int rc = 0 ;
2020-05-20 12:11:02 +10:00
SKIP_IF ( ! can_open_cifile ( ) ) ;
2018-07-31 22:08:42 +10:00
SKIP_IF ( ! have_hwcap ( PPC_FEATURE_ARCH_2_05 ) ) ;
printf ( " Floating point: 2.05 \n " ) ;
LOAD_FLOAT_DFORM_TEST ( lfdp ) ;
LOAD_FLOAT_XFORM_TEST ( lfdpx ) ;
LOAD_FLOAT_XFORM_TEST ( lfiwax ) ;
STORE_FLOAT_DFORM_TEST ( stfdp ) ;
STORE_FLOAT_XFORM_TEST ( stfdpx ) ;
return rc ;
}
int test_alignment_handler_fp_206 ( void )
{
int rc = 0 ;
2020-05-20 12:11:02 +10:00
SKIP_IF ( ! can_open_cifile ( ) ) ;
2018-07-31 22:08:42 +10:00
SKIP_IF ( ! have_hwcap ( PPC_FEATURE_ARCH_2_06 ) ) ;
printf ( " Floating point: 2.06 \n " ) ;
LOAD_FLOAT_XFORM_TEST ( lfiwzx ) ;
return rc ;
}
2020-05-20 12:11:03 +10:00
int test_alignment_handler_fp_prefix ( void )
{
int rc = 0 ;
SKIP_IF ( ! can_open_cifile ( ) ) ;
SKIP_IF ( ! have_hwcap2 ( PPC_FEATURE2_ARCH_3_1 ) ) ;
printf ( " Floating point: PREFIX \n " ) ;
LOAD_FLOAT_DFORM_TEST ( lfs ) ;
LOAD_FLOAT_MLS_PREFIX_TEST ( PLFS ) ;
LOAD_FLOAT_MLS_PREFIX_TEST ( PLFD ) ;
STORE_FLOAT_MLS_PREFIX_TEST ( PSTFS ) ;
STORE_FLOAT_MLS_PREFIX_TEST ( PSTFD ) ;
return rc ;
}
2017-10-16 16:04:02 +11:00
void usage ( char * prog )
{
2020-05-20 12:11:02 +10:00
printf ( " Usage: %s [options] [path [offset]] \n " , prog ) ;
2017-10-16 16:04:02 +11:00
printf ( " -d Enable debug error output \n " ) ;
printf ( " \n " ) ;
2020-05-20 12:11:03 +10:00
printf ( " This test requires a POWER8, POWER9 or POWER10 CPU " ) ;
printf ( " and either a usable framebuffer at /dev/fb0 or " ) ;
printf ( " the path to usable cache inhibited memory and optional " ) ;
printf ( " offset to be provided \n " ) ;
2017-10-16 16:04:02 +11:00
}
int main ( int argc , char * argv [ ] )
{
struct sigaction sa ;
int rc = 0 ;
int option = 0 ;
while ( ( option = getopt ( argc , argv , " d " ) ) ! = - 1 ) {
switch ( option ) {
case ' d ' :
debug + + ;
break ;
default :
usage ( argv [ 0 ] ) ;
exit ( 1 ) ;
}
}
2020-05-20 12:11:02 +10:00
argc - = optind ;
argv + = optind ;
if ( argc > 0 )
cipath = argv [ 0 ] ;
if ( argc > 1 )
cioffset = strtol ( argv [ 1 ] , 0 , 0x10 ) ;
2017-10-16 16:04:02 +11:00
bufsize = getpagesize ( ) ;
sa . sa_sigaction = sighandler ;
sigemptyset ( & sa . sa_mask ) ;
sa . sa_flags = SA_SIGINFO ;
if ( sigaction ( SIGSEGV , & sa , NULL ) = = - 1
| | sigaction ( SIGBUS , & sa , NULL ) = = - 1
| | sigaction ( SIGILL , & sa , NULL ) = = - 1 ) {
perror ( " sigaction " ) ;
exit ( 1 ) ;
}
2020-08-24 23:12:31 +10:00
prefixes_enabled = have_hwcap2 ( PPC_FEATURE2_ARCH_3_1 ) ;
2017-10-16 16:04:02 +11:00
rc | = test_harness ( test_alignment_handler_vsx_206 ,
" test_alignment_handler_vsx_206 " ) ;
rc | = test_harness ( test_alignment_handler_vsx_207 ,
" test_alignment_handler_vsx_207 " ) ;
rc | = test_harness ( test_alignment_handler_vsx_300 ,
" test_alignment_handler_vsx_300 " ) ;
2020-05-20 12:11:03 +10:00
rc | = test_harness ( test_alignment_handler_vsx_prefix ,
" test_alignment_handler_vsx_prefix " ) ;
2017-10-16 16:04:02 +11:00
rc | = test_harness ( test_alignment_handler_integer ,
" test_alignment_handler_integer " ) ;
2018-07-31 22:08:42 +10:00
rc | = test_harness ( test_alignment_handler_integer_206 ,
" test_alignment_handler_integer_206 " ) ;
2020-05-20 12:11:03 +10:00
rc | = test_harness ( test_alignment_handler_integer_prefix ,
" test_alignment_handler_integer_prefix " ) ;
2017-10-16 16:04:02 +11:00
rc | = test_harness ( test_alignment_handler_vmx ,
" test_alignment_handler_vmx " ) ;
rc | = test_harness ( test_alignment_handler_fp ,
" test_alignment_handler_fp " ) ;
2018-07-31 22:08:42 +10:00
rc | = test_harness ( test_alignment_handler_fp_205 ,
" test_alignment_handler_fp_205 " ) ;
rc | = test_harness ( test_alignment_handler_fp_206 ,
" test_alignment_handler_fp_206 " ) ;
2020-05-20 12:11:03 +10:00
rc | = test_harness ( test_alignment_handler_fp_prefix ,
" test_alignment_handler_fp_prefix " ) ;
2017-10-16 16:04:02 +11:00
return rc ;
}