Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/powerpc/64: Test all paths through copy routines

The hand-coded assembler 64-bit copy routines include feature sections
that select one code path or another depending on which CPU we are
executing on. The self-tests for these copy routines end up testing
just one path. This adds a mechanism for selecting any desired code
path at compile time, and makes 2 or 3 versions of each test, each
using a different code path, so as to cover all the possible paths.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
[mpe: Add -mcpu=power4 to CFLAGS for older compilers]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

authored by

Paul Mackerras and committed by
Michael Ellerman
98c45f51 a7c81ce3

+85 -44
+7
arch/powerpc/lib/copyuser_64.S
··· 12 12 #include <asm/asm-compat.h> 13 13 #include <asm/feature-fixups.h> 14 14 15 + #ifndef SELFTEST_CASE 16 + /* 0 == most CPUs, 1 == POWER6, 2 == Cell */ 17 + #define SELFTEST_CASE 0 18 + #endif 19 + 15 20 #ifdef __BIG_ENDIAN__ 16 21 #define sLd sld /* Shift towards low-numbered address. */ 17 22 #define sHd srd /* Shift towards high-numbered address. */ ··· 78 73 * At the time of writing the only CPU that has this combination of bits 79 74 * set is Power6. 80 75 */ 76 + test_feature = (SELFTEST_CASE == 1) 81 77 BEGIN_FTR_SECTION 82 78 nop 83 79 FTR_SECTION_ELSE ··· 88 82 .Ldst_aligned: 89 83 addi r3,r3,-16 90 84 r3_offset = 16 85 + test_feature = (SELFTEST_CASE == 0) 91 86 BEGIN_FTR_SECTION 92 87 andi. r0,r4,7 93 88 bne .Lsrc_unaligned
+11 -10
arch/powerpc/lib/copyuser_power7.S
··· 19 19 */ 20 20 #include <asm/ppc_asm.h> 21 21 22 + #ifndef SELFTEST_CASE 23 + /* 0 == don't use VMX, 1 == use VMX */ 24 + #define SELFTEST_CASE 0 25 + #endif 26 + 22 27 #ifdef __BIG_ENDIAN__ 23 28 #define LVS(VRT,RA,RB) lvsl VRT,RA,RB 24 29 #define VPERM(VRT,VRA,VRB,VRC) vperm VRT,VRA,VRB,VRC ··· 85 80 86 81 87 82 _GLOBAL(__copy_tofrom_user_power7) 88 - #ifdef CONFIG_ALTIVEC 89 83 cmpldi r5,16 90 84 cmpldi cr1,r5,3328 91 85 ··· 93 89 std r5,-STACKFRAMESIZE+STK_REG(R29)(r1) 94 90 95 91 blt .Lshort_copy 96 - bge cr1,.Lvmx_copy 97 - #else 98 - cmpldi r5,16 99 92 100 - std r3,-STACKFRAMESIZE+STK_REG(R31)(r1) 101 - std r4,-STACKFRAMESIZE+STK_REG(R30)(r1) 102 - std r5,-STACKFRAMESIZE+STK_REG(R29)(r1) 103 - 104 - blt .Lshort_copy 93 + #ifdef CONFIG_ALTIVEC 94 + test_feature = SELFTEST_CASE 95 + BEGIN_FTR_SECTION 96 + bgt cr1,.Lvmx_copy 97 + END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) 105 98 #endif 106 99 107 100 .Lnonvmx_copy: ··· 279 278 addi r1,r1,STACKFRAMESIZE 280 279 b .Lnonvmx_copy 281 280 282 - #ifdef CONFIG_ALTIVEC 283 281 .Lvmx_copy: 282 + #ifdef CONFIG_ALTIVEC 284 283 mflr r0 285 284 std r0,16(r1) 286 285 stdu r1,-STACKFRAMESIZE(r1)
+7 -2
arch/powerpc/lib/memcpy_64.S
··· 12 12 #include <asm/asm-compat.h> 13 13 #include <asm/feature-fixups.h> 14 14 15 + #ifndef SELFTEST_CASE 16 + /* For big-endian, 0 == most CPUs, 1 == POWER6, 2 == Cell */ 17 + #define SELFTEST_CASE 0 18 + #endif 19 + 15 20 .align 7 16 21 _GLOBAL_TOC(memcpy) 17 22 BEGIN_FTR_SECTION ··· 27 22 #endif 28 23 FTR_SECTION_ELSE 29 24 #ifdef CONFIG_PPC_BOOK3S_64 30 - #ifndef SELFTEST 31 25 b memcpy_power7 32 - #endif 33 26 #endif 34 27 ALT_FTR_SECTION_END_IFCLR(CPU_FTR_VMX_COPY) 35 28 #ifdef __LITTLE_ENDIAN__ ··· 52 49 cleared. 53 50 At the time of writing the only CPU that has this combination of bits 54 51 set is Power6. */ 52 + test_feature = (SELFTEST_CASE == 1) 55 53 BEGIN_FTR_SECTION 56 54 nop 57 55 FTR_SECTION_ELSE ··· 61 57 CPU_FTR_UNALIGNED_LD_STD) 62 58 .Ldst_aligned: 63 59 addi r3,r3,-16 60 + test_feature = (SELFTEST_CASE == 0) 64 61 BEGIN_FTR_SECTION 65 62 andi. r0,r4,7 66 63 bne .Lsrc_unaligned
+11 -11
arch/powerpc/lib/memcpy_power7.S
··· 19 19 */ 20 20 #include <asm/ppc_asm.h> 21 21 22 - _GLOBAL(memcpy_power7) 22 + #ifndef SELFTEST_CASE 23 + /* 0 == don't use VMX, 1 == use VMX */ 24 + #define SELFTEST_CASE 0 25 + #endif 23 26 24 27 #ifdef __BIG_ENDIAN__ 25 28 #define LVS(VRT,RA,RB) lvsl VRT,RA,RB ··· 32 29 #define VPERM(VRT,VRA,VRB,VRC) vperm VRT,VRB,VRA,VRC 33 30 #endif 34 31 35 - #ifdef CONFIG_ALTIVEC 32 + _GLOBAL(memcpy_power7) 36 33 cmpldi r5,16 37 34 cmpldi cr1,r5,4096 38 - 39 35 std r3,-STACKFRAMESIZE+STK_REG(R31)(r1) 40 - 41 36 blt .Lshort_copy 42 - bgt cr1,.Lvmx_copy 43 - #else 44 - cmpldi r5,16 45 37 46 - std r3,-STACKFRAMESIZE+STK_REG(R31)(r1) 47 - 48 - blt .Lshort_copy 38 + #ifdef CONFIG_ALTIVEC 39 + test_feature = SELFTEST_CASE 40 + BEGIN_FTR_SECTION 41 + bgt cr1, .Lvmx_copy 42 + END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) 49 43 #endif 50 44 51 45 .Lnonvmx_copy: ··· 223 223 addi r1,r1,STACKFRAMESIZE 224 224 b .Lnonvmx_copy 225 225 226 - #ifdef CONFIG_ALTIVEC 227 226 .Lvmx_copy: 227 + #ifdef CONFIG_ALTIVEC 228 228 mflr r0 229 229 std r4,-STACKFRAMESIZE+STK_REG(R30)(r1) 230 230 std r5,-STACKFRAMESIZE+STK_REG(R29)(r1)
+10 -4
tools/testing/selftests/powerpc/copyloops/.gitignore
··· 1 - copyuser_64 2 - copyuser_power7 3 - memcpy_64 4 - memcpy_power7 1 + copyuser_64_t0 2 + copyuser_64_t1 3 + copyuser_64_t2 4 + copyuser_power7_t0 5 + copyuser_power7_t1 6 + memcpy_64_t0 7 + memcpy_64_t1 8 + memcpy_64_t2 9 + memcpy_power7_t0 10 + memcpy_power7_t1
+29 -6
tools/testing/selftests/powerpc/copyloops/Makefile
··· 4 4 CFLAGS += -I$(CURDIR) 5 5 CFLAGS += -D SELFTEST 6 6 CFLAGS += -maltivec 7 + CFLAGS += -mcpu=power4 7 8 8 9 # Use our CFLAGS for the implicit .S rule & set the asm machine type 9 10 ASFLAGS = $(CFLAGS) -Wa,-mpower4 10 11 11 - TEST_GEN_PROGS := copyuser_64 copyuser_power7 memcpy_64 memcpy_power7 12 + TEST_GEN_PROGS := copyuser_64_t0 copyuser_64_t1 copyuser_64_t2 \ 13 + copyuser_p7_t0 copyuser_p7_t1 \ 14 + memcpy_64_t0 memcpy_64_t1 memcpy_64_t2 \ 15 + memcpy_p7_t0 memcpy_p7_t1 16 + 12 17 EXTRA_SOURCES := validate.c ../harness.c 13 18 14 19 include ../../lib.mk 15 20 16 - $(OUTPUT)/copyuser_64: CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_base 17 - $(OUTPUT)/copyuser_power7: CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_power7 18 - $(OUTPUT)/memcpy_64: CPPFLAGS += -D COPY_LOOP=test_memcpy 19 - $(OUTPUT)/memcpy_power7: CPPFLAGS += -D COPY_LOOP=test_memcpy_power7 21 + $(OUTPUT)/copyuser_64_t%: copyuser_64.S $(EXTRA_SOURCES) 22 + $(CC) $(CPPFLAGS) $(CFLAGS) \ 23 + -D COPY_LOOP=test___copy_tofrom_user_base \ 24 + -D SELFTEST_CASE=$(subst copyuser_64_t,,$(notdir $@)) \ 25 + -o $@ $^ 20 26 21 - $(TEST_GEN_PROGS): $(EXTRA_SOURCES) 27 + $(OUTPUT)/copyuser_p7_t%: copyuser_power7.S $(EXTRA_SOURCES) 28 + $(CC) $(CPPFLAGS) $(CFLAGS) \ 29 + -D COPY_LOOP=test___copy_tofrom_user_power7 \ 30 + -D SELFTEST_CASE=$(subst copyuser_p7_t,,$(notdir $@)) \ 31 + -o $@ $^ 32 + 33 + # Strictly speaking, we only need the memcpy_64 test cases for big-endian 34 + $(OUTPUT)/memcpy_64_t%: memcpy_64.S $(EXTRA_SOURCES) 35 + $(CC) $(CPPFLAGS) $(CFLAGS) \ 36 + -D COPY_LOOP=test_memcpy \ 37 + -D SELFTEST_CASE=$(subst memcpy_64_t,,$(notdir $@)) \ 38 + -o $@ $^ 39 + 40 + $(OUTPUT)/memcpy_p7_t%: memcpy_power7.S $(EXTRA_SOURCES) 41 + $(CC) $(CPPFLAGS) $(CFLAGS) \ 42 + -D COPY_LOOP=test_memcpy_power7 \ 43 + -D SELFTEST_CASE=$(subst memcpy_p7_t,,$(notdir $@)) \ 44 + -o $@ $^
+10 -11
tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h
··· 43 43 FUNC_START(exit_vmx_ops) 44 44 blr 45 45 46 - FUNC_START(memcpy_power7) 47 - blr 48 - 49 - FUNC_START(__copy_tofrom_user_power7) 50 - blr 51 - 52 46 FUNC_START(__copy_tofrom_user_base) 53 47 blr 54 48 55 - #define BEGIN_FTR_SECTION 56 - #define FTR_SECTION_ELSE 57 - #define ALT_FTR_SECTION_END_IFCLR(x) 58 - #define ALT_FTR_SECTION_END(x, y) 59 - #define END_FTR_SECTION_IFCLR(x) 49 + #define BEGIN_FTR_SECTION .if test_feature 50 + #define FTR_SECTION_ELSE .else 51 + #define ALT_FTR_SECTION_END_IFCLR(x) .endif 52 + #define ALT_FTR_SECTION_END_IFSET(x) .endif 53 + #define ALT_FTR_SECTION_END(x, y) .endif 54 + #define END_FTR_SECTION_IFCLR(x) .endif 55 + #define END_FTR_SECTION_IFSET(x) .endif 56 + 57 + /* Default to taking the first of any alternative feature sections */ 58 + test_feature = 1