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>
This commit is contained in:
parent
a7c81ce398
commit
98c45f51f7
7 changed files with 85 additions and 44 deletions
|
@ -12,6 +12,11 @@
|
||||||
#include <asm/asm-compat.h>
|
#include <asm/asm-compat.h>
|
||||||
#include <asm/feature-fixups.h>
|
#include <asm/feature-fixups.h>
|
||||||
|
|
||||||
|
#ifndef SELFTEST_CASE
|
||||||
|
/* 0 == most CPUs, 1 == POWER6, 2 == Cell */
|
||||||
|
#define SELFTEST_CASE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __BIG_ENDIAN__
|
#ifdef __BIG_ENDIAN__
|
||||||
#define sLd sld /* Shift towards low-numbered address. */
|
#define sLd sld /* Shift towards low-numbered address. */
|
||||||
#define sHd srd /* Shift towards high-numbered address. */
|
#define sHd srd /* Shift towards high-numbered address. */
|
||||||
|
@ -73,6 +78,7 @@ _GLOBAL(__copy_tofrom_user_base)
|
||||||
* At the time of writing the only CPU that has this combination of bits
|
* At the time of writing the only CPU that has this combination of bits
|
||||||
* set is Power6.
|
* set is Power6.
|
||||||
*/
|
*/
|
||||||
|
test_feature = (SELFTEST_CASE == 1)
|
||||||
BEGIN_FTR_SECTION
|
BEGIN_FTR_SECTION
|
||||||
nop
|
nop
|
||||||
FTR_SECTION_ELSE
|
FTR_SECTION_ELSE
|
||||||
|
@ -82,6 +88,7 @@ ALT_FTR_SECTION_END(CPU_FTR_UNALIGNED_LD_STD | CPU_FTR_CP_USE_DCBTZ, \
|
||||||
.Ldst_aligned:
|
.Ldst_aligned:
|
||||||
addi r3,r3,-16
|
addi r3,r3,-16
|
||||||
r3_offset = 16
|
r3_offset = 16
|
||||||
|
test_feature = (SELFTEST_CASE == 0)
|
||||||
BEGIN_FTR_SECTION
|
BEGIN_FTR_SECTION
|
||||||
andi. r0,r4,7
|
andi. r0,r4,7
|
||||||
bne .Lsrc_unaligned
|
bne .Lsrc_unaligned
|
||||||
|
|
|
@ -19,6 +19,11 @@
|
||||||
*/
|
*/
|
||||||
#include <asm/ppc_asm.h>
|
#include <asm/ppc_asm.h>
|
||||||
|
|
||||||
|
#ifndef SELFTEST_CASE
|
||||||
|
/* 0 == don't use VMX, 1 == use VMX */
|
||||||
|
#define SELFTEST_CASE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __BIG_ENDIAN__
|
#ifdef __BIG_ENDIAN__
|
||||||
#define LVS(VRT,RA,RB) lvsl VRT,RA,RB
|
#define LVS(VRT,RA,RB) lvsl VRT,RA,RB
|
||||||
#define VPERM(VRT,VRA,VRB,VRC) vperm VRT,VRA,VRB,VRC
|
#define VPERM(VRT,VRA,VRB,VRC) vperm VRT,VRA,VRB,VRC
|
||||||
|
@ -80,7 +85,6 @@
|
||||||
|
|
||||||
|
|
||||||
_GLOBAL(__copy_tofrom_user_power7)
|
_GLOBAL(__copy_tofrom_user_power7)
|
||||||
#ifdef CONFIG_ALTIVEC
|
|
||||||
cmpldi r5,16
|
cmpldi r5,16
|
||||||
cmpldi cr1,r5,3328
|
cmpldi cr1,r5,3328
|
||||||
|
|
||||||
|
@ -89,15 +93,12 @@ _GLOBAL(__copy_tofrom_user_power7)
|
||||||
std r5,-STACKFRAMESIZE+STK_REG(R29)(r1)
|
std r5,-STACKFRAMESIZE+STK_REG(R29)(r1)
|
||||||
|
|
||||||
blt .Lshort_copy
|
blt .Lshort_copy
|
||||||
bge cr1,.Lvmx_copy
|
|
||||||
#else
|
|
||||||
cmpldi r5,16
|
|
||||||
|
|
||||||
std r3,-STACKFRAMESIZE+STK_REG(R31)(r1)
|
#ifdef CONFIG_ALTIVEC
|
||||||
std r4,-STACKFRAMESIZE+STK_REG(R30)(r1)
|
test_feature = SELFTEST_CASE
|
||||||
std r5,-STACKFRAMESIZE+STK_REG(R29)(r1)
|
BEGIN_FTR_SECTION
|
||||||
|
bgt cr1,.Lvmx_copy
|
||||||
blt .Lshort_copy
|
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
.Lnonvmx_copy:
|
.Lnonvmx_copy:
|
||||||
|
@ -278,8 +279,8 @@ err1; stb r0,0(r3)
|
||||||
addi r1,r1,STACKFRAMESIZE
|
addi r1,r1,STACKFRAMESIZE
|
||||||
b .Lnonvmx_copy
|
b .Lnonvmx_copy
|
||||||
|
|
||||||
#ifdef CONFIG_ALTIVEC
|
|
||||||
.Lvmx_copy:
|
.Lvmx_copy:
|
||||||
|
#ifdef CONFIG_ALTIVEC
|
||||||
mflr r0
|
mflr r0
|
||||||
std r0,16(r1)
|
std r0,16(r1)
|
||||||
stdu r1,-STACKFRAMESIZE(r1)
|
stdu r1,-STACKFRAMESIZE(r1)
|
||||||
|
|
|
@ -12,6 +12,11 @@
|
||||||
#include <asm/asm-compat.h>
|
#include <asm/asm-compat.h>
|
||||||
#include <asm/feature-fixups.h>
|
#include <asm/feature-fixups.h>
|
||||||
|
|
||||||
|
#ifndef SELFTEST_CASE
|
||||||
|
/* For big-endian, 0 == most CPUs, 1 == POWER6, 2 == Cell */
|
||||||
|
#define SELFTEST_CASE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
.align 7
|
.align 7
|
||||||
_GLOBAL_TOC(memcpy)
|
_GLOBAL_TOC(memcpy)
|
||||||
BEGIN_FTR_SECTION
|
BEGIN_FTR_SECTION
|
||||||
|
@ -22,10 +27,8 @@ BEGIN_FTR_SECTION
|
||||||
#endif
|
#endif
|
||||||
FTR_SECTION_ELSE
|
FTR_SECTION_ELSE
|
||||||
#ifdef CONFIG_PPC_BOOK3S_64
|
#ifdef CONFIG_PPC_BOOK3S_64
|
||||||
#ifndef SELFTEST
|
|
||||||
b memcpy_power7
|
b memcpy_power7
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
ALT_FTR_SECTION_END_IFCLR(CPU_FTR_VMX_COPY)
|
ALT_FTR_SECTION_END_IFCLR(CPU_FTR_VMX_COPY)
|
||||||
#ifdef __LITTLE_ENDIAN__
|
#ifdef __LITTLE_ENDIAN__
|
||||||
/* dumb little-endian memcpy that will get replaced at runtime */
|
/* dumb little-endian memcpy that will get replaced at runtime */
|
||||||
|
@ -49,6 +52,7 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_VMX_COPY)
|
||||||
cleared.
|
cleared.
|
||||||
At the time of writing the only CPU that has this combination of bits
|
At the time of writing the only CPU that has this combination of bits
|
||||||
set is Power6. */
|
set is Power6. */
|
||||||
|
test_feature = (SELFTEST_CASE == 1)
|
||||||
BEGIN_FTR_SECTION
|
BEGIN_FTR_SECTION
|
||||||
nop
|
nop
|
||||||
FTR_SECTION_ELSE
|
FTR_SECTION_ELSE
|
||||||
|
@ -57,6 +61,7 @@ ALT_FTR_SECTION_END(CPU_FTR_UNALIGNED_LD_STD | CPU_FTR_CP_USE_DCBTZ, \
|
||||||
CPU_FTR_UNALIGNED_LD_STD)
|
CPU_FTR_UNALIGNED_LD_STD)
|
||||||
.Ldst_aligned:
|
.Ldst_aligned:
|
||||||
addi r3,r3,-16
|
addi r3,r3,-16
|
||||||
|
test_feature = (SELFTEST_CASE == 0)
|
||||||
BEGIN_FTR_SECTION
|
BEGIN_FTR_SECTION
|
||||||
andi. r0,r4,7
|
andi. r0,r4,7
|
||||||
bne .Lsrc_unaligned
|
bne .Lsrc_unaligned
|
||||||
|
|
|
@ -19,7 +19,10 @@
|
||||||
*/
|
*/
|
||||||
#include <asm/ppc_asm.h>
|
#include <asm/ppc_asm.h>
|
||||||
|
|
||||||
_GLOBAL(memcpy_power7)
|
#ifndef SELFTEST_CASE
|
||||||
|
/* 0 == don't use VMX, 1 == use VMX */
|
||||||
|
#define SELFTEST_CASE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __BIG_ENDIAN__
|
#ifdef __BIG_ENDIAN__
|
||||||
#define LVS(VRT,RA,RB) lvsl VRT,RA,RB
|
#define LVS(VRT,RA,RB) lvsl VRT,RA,RB
|
||||||
|
@ -29,20 +32,17 @@ _GLOBAL(memcpy_power7)
|
||||||
#define VPERM(VRT,VRA,VRB,VRC) vperm VRT,VRB,VRA,VRC
|
#define VPERM(VRT,VRA,VRB,VRC) vperm VRT,VRB,VRA,VRC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_ALTIVEC
|
_GLOBAL(memcpy_power7)
|
||||||
cmpldi r5,16
|
cmpldi r5,16
|
||||||
cmpldi cr1,r5,4096
|
cmpldi cr1,r5,4096
|
||||||
|
|
||||||
std r3,-STACKFRAMESIZE+STK_REG(R31)(r1)
|
std r3,-STACKFRAMESIZE+STK_REG(R31)(r1)
|
||||||
|
|
||||||
blt .Lshort_copy
|
blt .Lshort_copy
|
||||||
bgt cr1,.Lvmx_copy
|
|
||||||
#else
|
|
||||||
cmpldi r5,16
|
|
||||||
|
|
||||||
std r3,-STACKFRAMESIZE+STK_REG(R31)(r1)
|
#ifdef CONFIG_ALTIVEC
|
||||||
|
test_feature = SELFTEST_CASE
|
||||||
blt .Lshort_copy
|
BEGIN_FTR_SECTION
|
||||||
|
bgt cr1, .Lvmx_copy
|
||||||
|
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
.Lnonvmx_copy:
|
.Lnonvmx_copy:
|
||||||
|
@ -223,8 +223,8 @@ _GLOBAL(memcpy_power7)
|
||||||
addi r1,r1,STACKFRAMESIZE
|
addi r1,r1,STACKFRAMESIZE
|
||||||
b .Lnonvmx_copy
|
b .Lnonvmx_copy
|
||||||
|
|
||||||
#ifdef CONFIG_ALTIVEC
|
|
||||||
.Lvmx_copy:
|
.Lvmx_copy:
|
||||||
|
#ifdef CONFIG_ALTIVEC
|
||||||
mflr r0
|
mflr r0
|
||||||
std r4,-STACKFRAMESIZE+STK_REG(R30)(r1)
|
std r4,-STACKFRAMESIZE+STK_REG(R30)(r1)
|
||||||
std r5,-STACKFRAMESIZE+STK_REG(R29)(r1)
|
std r5,-STACKFRAMESIZE+STK_REG(R29)(r1)
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
copyuser_64
|
copyuser_64_t0
|
||||||
copyuser_power7
|
copyuser_64_t1
|
||||||
memcpy_64
|
copyuser_64_t2
|
||||||
memcpy_power7
|
copyuser_power7_t0
|
||||||
|
copyuser_power7_t1
|
||||||
|
memcpy_64_t0
|
||||||
|
memcpy_64_t1
|
||||||
|
memcpy_64_t2
|
||||||
|
memcpy_power7_t0
|
||||||
|
memcpy_power7_t1
|
||||||
|
|
|
@ -4,18 +4,41 @@ CFLAGS += -m64
|
||||||
CFLAGS += -I$(CURDIR)
|
CFLAGS += -I$(CURDIR)
|
||||||
CFLAGS += -D SELFTEST
|
CFLAGS += -D SELFTEST
|
||||||
CFLAGS += -maltivec
|
CFLAGS += -maltivec
|
||||||
|
CFLAGS += -mcpu=power4
|
||||||
|
|
||||||
# Use our CFLAGS for the implicit .S rule & set the asm machine type
|
# Use our CFLAGS for the implicit .S rule & set the asm machine type
|
||||||
ASFLAGS = $(CFLAGS) -Wa,-mpower4
|
ASFLAGS = $(CFLAGS) -Wa,-mpower4
|
||||||
|
|
||||||
TEST_GEN_PROGS := copyuser_64 copyuser_power7 memcpy_64 memcpy_power7
|
TEST_GEN_PROGS := copyuser_64_t0 copyuser_64_t1 copyuser_64_t2 \
|
||||||
|
copyuser_p7_t0 copyuser_p7_t1 \
|
||||||
|
memcpy_64_t0 memcpy_64_t1 memcpy_64_t2 \
|
||||||
|
memcpy_p7_t0 memcpy_p7_t1
|
||||||
|
|
||||||
EXTRA_SOURCES := validate.c ../harness.c
|
EXTRA_SOURCES := validate.c ../harness.c
|
||||||
|
|
||||||
include ../../lib.mk
|
include ../../lib.mk
|
||||||
|
|
||||||
$(OUTPUT)/copyuser_64: CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_base
|
$(OUTPUT)/copyuser_64_t%: copyuser_64.S $(EXTRA_SOURCES)
|
||||||
$(OUTPUT)/copyuser_power7: CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_power7
|
$(CC) $(CPPFLAGS) $(CFLAGS) \
|
||||||
$(OUTPUT)/memcpy_64: CPPFLAGS += -D COPY_LOOP=test_memcpy
|
-D COPY_LOOP=test___copy_tofrom_user_base \
|
||||||
$(OUTPUT)/memcpy_power7: CPPFLAGS += -D COPY_LOOP=test_memcpy_power7
|
-D SELFTEST_CASE=$(subst copyuser_64_t,,$(notdir $@)) \
|
||||||
|
-o $@ $^
|
||||||
|
|
||||||
$(TEST_GEN_PROGS): $(EXTRA_SOURCES)
|
$(OUTPUT)/copyuser_p7_t%: copyuser_power7.S $(EXTRA_SOURCES)
|
||||||
|
$(CC) $(CPPFLAGS) $(CFLAGS) \
|
||||||
|
-D COPY_LOOP=test___copy_tofrom_user_power7 \
|
||||||
|
-D SELFTEST_CASE=$(subst copyuser_p7_t,,$(notdir $@)) \
|
||||||
|
-o $@ $^
|
||||||
|
|
||||||
|
# Strictly speaking, we only need the memcpy_64 test cases for big-endian
|
||||||
|
$(OUTPUT)/memcpy_64_t%: memcpy_64.S $(EXTRA_SOURCES)
|
||||||
|
$(CC) $(CPPFLAGS) $(CFLAGS) \
|
||||||
|
-D COPY_LOOP=test_memcpy \
|
||||||
|
-D SELFTEST_CASE=$(subst memcpy_64_t,,$(notdir $@)) \
|
||||||
|
-o $@ $^
|
||||||
|
|
||||||
|
$(OUTPUT)/memcpy_p7_t%: memcpy_power7.S $(EXTRA_SOURCES)
|
||||||
|
$(CC) $(CPPFLAGS) $(CFLAGS) \
|
||||||
|
-D COPY_LOOP=test_memcpy_power7 \
|
||||||
|
-D SELFTEST_CASE=$(subst memcpy_p7_t,,$(notdir $@)) \
|
||||||
|
-o $@ $^
|
||||||
|
|
|
@ -43,17 +43,16 @@ FUNC_START(enter_vmx_ops)
|
||||||
FUNC_START(exit_vmx_ops)
|
FUNC_START(exit_vmx_ops)
|
||||||
blr
|
blr
|
||||||
|
|
||||||
FUNC_START(memcpy_power7)
|
|
||||||
blr
|
|
||||||
|
|
||||||
FUNC_START(__copy_tofrom_user_power7)
|
|
||||||
blr
|
|
||||||
|
|
||||||
FUNC_START(__copy_tofrom_user_base)
|
FUNC_START(__copy_tofrom_user_base)
|
||||||
blr
|
blr
|
||||||
|
|
||||||
#define BEGIN_FTR_SECTION
|
#define BEGIN_FTR_SECTION .if test_feature
|
||||||
#define FTR_SECTION_ELSE
|
#define FTR_SECTION_ELSE .else
|
||||||
#define ALT_FTR_SECTION_END_IFCLR(x)
|
#define ALT_FTR_SECTION_END_IFCLR(x) .endif
|
||||||
#define ALT_FTR_SECTION_END(x, y)
|
#define ALT_FTR_SECTION_END_IFSET(x) .endif
|
||||||
#define END_FTR_SECTION_IFCLR(x)
|
#define ALT_FTR_SECTION_END(x, y) .endif
|
||||||
|
#define END_FTR_SECTION_IFCLR(x) .endif
|
||||||
|
#define END_FTR_SECTION_IFSET(x) .endif
|
||||||
|
|
||||||
|
/* Default to taking the first of any alternative feature sections */
|
||||||
|
test_feature = 1
|
||||||
|
|
Loading…
Reference in a new issue