[PATCH 2/2] selftests/powerpc: Add prefixed loads/stores to alignment_handler test
Alistair Popple
alistair at popple.id.au
Wed Jun 17 16:31:47 AEST 2020
Tested-by: Alistair Popple <alistair at popple.id.au>
On Wednesday, 20 May 2020 12:11:03 PM AEST Jordan Niethe wrote:
> Extend the alignment handler selftest to exercise prefixed load store
> instructions. Add tests for prefixed VSX, floating point and integer
> instructions.
>
> Skip prefix tests if ISA version does not support prefixed instructions.
>
> Signed-off-by: Jordan Niethe <jniethe5 at gmail.com>
> ---
> .../powerpc/alignment/alignment_handler.c | 93 ++++++++++++++++++-
> .../selftests/powerpc/include/instructions.h | 77 +++++++++++++++
> .../testing/selftests/powerpc/include/utils.h | 5 +
> 3 files changed, 172 insertions(+), 3 deletions(-)
>
> diff --git a/tools/testing/selftests/powerpc/alignment/alignment_handler.c b/tools/testing/selftests/powerpc/alignment/alignment_handler.c
> index eb6aba323f8b..e582e68b3b5b 100644
> --- a/tools/testing/selftests/powerpc/alignment/alignment_handler.c
> +++ b/tools/testing/selftests/powerpc/alignment/alignment_handler.c
> @@ -58,6 +58,7 @@
> #include <asm/cputable.h>
>
> #include "utils.h"
> +#include "instructions.h"
>
> int bufsize;
> int debug;
> @@ -96,6 +97,17 @@ void sighandler(int sig, siginfo_t *info, void *ctx)
> } \
> rc |= do_test(#name, test_##name)
>
> +#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)
> +
> #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)
> @@ -115,6 +127,17 @@ void sighandler(int sig, siginfo_t *info, void *ctx)
> #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)
>
> +#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)
>
> /* FIXME: Unimplemented tests: */
> // STORE_DFORM_TEST(stq) /* FIXME: need two registers for quad */
> @@ -361,6 +384,25 @@ int test_alignment_handler_vsx_300(void)
> return rc;
> }
>
> +int test_alignment_handler_vsx_prefix(void)
> +{
> + int rc = 0;
> +
> + SKIP_IF(!can_open_cifile());
> + SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_10));
> +
> + 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;
> +}
> +
> int test_alignment_handler_integer(void)
> {
> int rc = 0;
> @@ -432,6 +474,27 @@ int test_alignment_handler_integer_206(void)
> return rc;
> }
>
> +int test_alignment_handler_integer_prefix(void)
> +{
> + int rc = 0;
> +
> + SKIP_IF(!can_open_cifile());
> + SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_10));
> +
> + 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;
> +}
> +
> int test_alignment_handler_vmx(void)
> {
> int rc = 0;
> @@ -520,14 +583,32 @@ int test_alignment_handler_fp_206(void)
> return rc;
> }
>
> +
> +int test_alignment_handler_fp_prefix(void)
> +{
> + int rc = 0;
> +
> + SKIP_IF(!can_open_cifile());
> + SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_10));
> +
> + 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;
> +}
> +
> void usage(char *prog)
> {
> printf("Usage: %s [options] [path [offset]]\n", prog);
> printf(" -d Enable debug error output\n");
> printf("\n");
> - printf("This test requires a POWER8 or POWER9 CPU and either a ");
> - printf("usable framebuffer at /dev/fb0 or the path to usable ");
> - printf("cache-inhibited memory and optional offset to be provided\n");
> + 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");
> }
>
> int main(int argc, char *argv[])
> @@ -573,10 +654,14 @@ int main(int argc, char *argv[])
> "test_alignment_handler_vsx_207");
> rc |= test_harness(test_alignment_handler_vsx_300,
> "test_alignment_handler_vsx_300");
> + rc |= test_harness(test_alignment_handler_vsx_prefix,
> + "test_alignment_handler_vsx_prefix");
> rc |= test_harness(test_alignment_handler_integer,
> "test_alignment_handler_integer");
> rc |= test_harness(test_alignment_handler_integer_206,
> "test_alignment_handler_integer_206");
> + rc |= test_harness(test_alignment_handler_integer_prefix,
> + "test_alignment_handler_integer_prefix");
> rc |= test_harness(test_alignment_handler_vmx,
> "test_alignment_handler_vmx");
> rc |= test_harness(test_alignment_handler_fp,
> @@ -585,5 +670,7 @@ int main(int argc, char *argv[])
> "test_alignment_handler_fp_205");
> rc |= test_harness(test_alignment_handler_fp_206,
> "test_alignment_handler_fp_206");
> + rc |= test_harness(test_alignment_handler_fp_prefix,
> + "test_alignment_handler_fp_prefix");
> return rc;
> }
> diff --git a/tools/testing/selftests/powerpc/include/instructions.h b/tools/testing/selftests/powerpc/include/instructions.h
> index f36061eb6f0f..4efa6314bd96 100644
> --- a/tools/testing/selftests/powerpc/include/instructions.h
> +++ b/tools/testing/selftests/powerpc/include/instructions.h
> @@ -66,4 +66,81 @@ static inline int paste_last(void *i)
> #define PPC_INST_PASTE __PASTE(0, 0, 0, 0)
> #define PPC_INST_PASTE_LAST __PASTE(0, 0, 1, 1)
>
> +/* This defines the prefixed load/store instructions */
> +#ifdef __ASSEMBLY__
> +# define stringify_in_c(...) __VA_ARGS__
> +#else
> +# define __stringify_in_c(...) #__VA_ARGS__
> +# define stringify_in_c(...) __stringify_in_c(__VA_ARGS__) " "
> +#endif
> +
> +#define __PPC_RA(a) (((a) & 0x1f) << 16)
> +#define __PPC_RS(s) (((s) & 0x1f) << 21)
> +#define __PPC_RT(t) __PPC_RS(t)
> +#define __PPC_PREFIX_R(r) (((r) & 0x1) << 20)
> +
> +#define PPC_PREFIX_MLS 0x06000000
> +#define PPC_PREFIX_8LS 0x04000000
> +
> +#define PPC_INST_LBZ 0x88000000
> +#define PPC_INST_LHZ 0xa0000000
> +#define PPC_INST_LHA 0xa8000000
> +#define PPC_INST_LWZ 0x80000000
> +#define PPC_INST_STB 0x98000000
> +#define PPC_INST_STH 0xb0000000
> +#define PPC_INST_STW 0x90000000
> +#define PPC_INST_STD 0xf8000000
> +#define PPC_INST_LFS 0xc0000000
> +#define PPC_INST_LFD 0xc8000000
> +#define PPC_INST_STFS 0xd0000000
> +#define PPC_INST_STFD 0xd8000000
> +
> +#define PREFIX_MLS(instr, t, a, r, d) stringify_in_c(.balign 64, , 4;) \
> + stringify_in_c(.long PPC_PREFIX_MLS | \
> + __PPC_PREFIX_R(r) | \
> + (((d) >> 16) & 0x3ffff);) \
> + stringify_in_c(.long (instr) | \
> + __PPC_RT(t) | \
> + __PPC_RA(a) | \
> + ((d) & 0xffff);\n)
> +
> +#define PREFIX_8LS(instr, t, a, r, d) stringify_in_c(.balign 64, , 4;) \
> + stringify_in_c(.long PPC_PREFIX_8LS | \
> + __PPC_PREFIX_R(r) | \
> + (((d) >> 16) & 0x3ffff);) \
> + stringify_in_c(.long (instr) | \
> + __PPC_RT(t) | \
> + __PPC_RA(a) | \
> + ((d) & 0xffff);\n)
> +
> +/* Prefixed Integer Load/Store instructions */
> +#define PLBZ(t, a, r, d) PREFIX_MLS(PPC_INST_LBZ, t, a, r, d)
> +#define PLHZ(t, a, r, d) PREFIX_MLS(PPC_INST_LHZ, t, a, r, d)
> +#define PLHA(t, a, r, d) PREFIX_MLS(PPC_INST_LHA, t, a, r, d)
> +#define PLWZ(t, a, r, d) PREFIX_MLS(PPC_INST_LWZ, t, a, r, d)
> +#define PLWA(t, a, r, d) PREFIX_8LS(0xa4000000, t, a, r, d)
> +#define PLD(t, a, r, d) PREFIX_8LS(0xe4000000, t, a, r, d)
> +#define PLQ(t, a, r, d) PREFIX_8LS(0xe0000000, t, a, r, d)
> +#define PSTB(s, a, r, d) PREFIX_MLS(PPC_INST_STB, s, a, r, d)
> +#define PSTH(s, a, r, d) PREFIX_MLS(PPC_INST_STH, s, a, r, d)
> +#define PSTW(s, a, r, d) PREFIX_MLS(PPC_INST_STW, s, a, r, d)
> +#define PSTD(s, a, r, d) PREFIX_8LS(0xf4000000, s, a, r, d)
> +#define PSTQ(s, a, r, d) PREFIX_8LS(0xf0000000, s, a, r, d)
> +
> +/* Prefixed Floating-Point Load/Store Instructions */
> +#define PLFS(frt, a, r, d) PREFIX_MLS(PPC_INST_LFS, frt, a, r, d)
> +#define PLFD(frt, a, r, d) PREFIX_MLS(PPC_INST_LFD, frt, a, r, d)
> +#define PSTFS(frs, a, r, d) PREFIX_MLS(PPC_INST_STFS, frs, a, r, d)
> +#define PSTFD(frs, a, r, d) PREFIX_MLS(PPC_INST_STFD, frs, a, r, d)
> +
> +/* Prefixed VSX Load/Store Instructions */
> +#define PLXSD(vrt, a, r, d) PREFIX_8LS(0xa8000000, vrt, a, r, d)
> +#define PLXSSP(vrt, a, r, d) PREFIX_8LS(0xac000000, vrt, a, r, d)
> +#define PLXV0(s, a, r, d) PREFIX_8LS(0xc8000000, s, a, r, d)
> +#define PLXV1(s, a, r, d) PREFIX_8LS(0xcc000000, s, a, r, d)
> +#define PSTXSD(vrs, a, r, d) PREFIX_8LS(0xb8000000, vrs, a, r, d)
> +#define PSTXSSP(vrs, a, r, d) PREFIX_8LS(0xbc000000, vrs, a, r, d)
> +#define PSTXV0(s, a, r, d) PREFIX_8LS(0xd8000000, s, a, r, d)
> +#define PSTXV1(s, a, r, d) PREFIX_8LS(0xdc000000, s, a, r, d)
> +
> #endif /* _SELFTESTS_POWERPC_INSTRUCTIONS_H */
> diff --git a/tools/testing/selftests/powerpc/include/utils.h b/tools/testing/selftests/powerpc/include/utils.h
> index e089a0c30d9a..eb91cf3561f8 100644
> --- a/tools/testing/selftests/powerpc/include/utils.h
> +++ b/tools/testing/selftests/powerpc/include/utils.h
> @@ -101,6 +101,11 @@ do { \
> #define PPC_FEATURE2_ARCH_3_00 0x00800000
> #endif
>
> +/* POWER10 feature */
> +#ifndef PPC_FEATURE2_ARCH_3_10
> +#define PPC_FEATURE2_ARCH_3_10 0x00040000
> +#endif
> +
> #if defined(__powerpc64__)
> #define UCONTEXT_NIA(UC) (UC)->uc_mcontext.gp_regs[PT_NIP]
> #define UCONTEXT_MSR(UC) (UC)->uc_mcontext.gp_regs[PT_MSR]
>
More information about the Linuxppc-dev
mailing list