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

selftests/powerpc: Update memcmp_64 selftest for VMX implementation

This patch reworked selftest memcmp_64 so that memcmp selftest can
cover more test cases.

It adds testcases for:
- memcmp over 4K bytes size.
- s1/s2 with different/random offset on 16 bytes boundary.
- enter/exit_vmx_ops pairness.

Signed-off-by: Simon Guo <wei.guo.simon@gmail.com>
[mpe: Add -maltivec to fix build on some toolchains]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

authored by

Simon Guo and committed by
Michael Ellerman
c827ac45 c2a4e54e

+142 -24
+2 -2
tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h
··· 36 36 li r3,0 37 37 blr 38 38 39 - FUNC_START(enter_vmx_copy) 39 + FUNC_START(enter_vmx_ops) 40 40 li r3,1 41 41 blr 42 42 43 - FUNC_START(exit_vmx_copy) 43 + FUNC_START(exit_vmx_ops) 44 44 blr 45 45 46 46 FUNC_START(memcpy_power7)
+1 -1
tools/testing/selftests/powerpc/stringloops/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 # The loops are all 64-bit code 3 - CFLAGS += -m64 3 + CFLAGS += -m64 -maltivec 4 4 CFLAGS += -I$(CURDIR) 5 5 6 6 TEST_GEN_PROGS := memcmp
+39
tools/testing/selftests/powerpc/stringloops/asm/ppc-opcode.h
··· 1 + /* 2 + * Copyright 2009 Freescale Semiconductor, Inc. 3 + * 4 + * This program is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU General Public License 6 + * as published by the Free Software Foundation; either version 7 + * 2 of the License, or (at your option) any later version. 8 + * 9 + * provides masks and opcode images for use by code generation, emulation 10 + * and for instructions that older assemblers might not know about 11 + */ 12 + #ifndef _ASM_POWERPC_PPC_OPCODE_H 13 + #define _ASM_POWERPC_PPC_OPCODE_H 14 + 15 + 16 + # define stringify_in_c(...) __VA_ARGS__ 17 + # define ASM_CONST(x) x 18 + 19 + 20 + #define PPC_INST_VCMPEQUD_RC 0x100000c7 21 + #define PPC_INST_VCMPEQUB_RC 0x10000006 22 + 23 + #define __PPC_RC21 (0x1 << 10) 24 + 25 + /* macros to insert fields into opcodes */ 26 + #define ___PPC_RA(a) (((a) & 0x1f) << 16) 27 + #define ___PPC_RB(b) (((b) & 0x1f) << 11) 28 + #define ___PPC_RS(s) (((s) & 0x1f) << 21) 29 + #define ___PPC_RT(t) ___PPC_RS(t) 30 + 31 + #define VCMPEQUD_RC(vrt, vra, vrb) stringify_in_c(.long PPC_INST_VCMPEQUD_RC | \ 32 + ___PPC_RT(vrt) | ___PPC_RA(vra) | \ 33 + ___PPC_RB(vrb) | __PPC_RC21) 34 + 35 + #define VCMPEQUB_RC(vrt, vra, vrb) stringify_in_c(.long PPC_INST_VCMPEQUB_RC | \ 36 + ___PPC_RT(vrt) | ___PPC_RA(vra) | \ 37 + ___PPC_RB(vrb) | __PPC_RC21) 38 + 39 + #endif /* _ASM_POWERPC_PPC_OPCODE_H */
+25
tools/testing/selftests/powerpc/stringloops/asm/ppc_asm.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _PPC_ASM_H 3 + #define __PPC_ASM_H 2 4 #include <ppc-asm.h> 3 5 4 6 #ifndef r1 ··· 8 6 #endif 9 7 10 8 #define _GLOBAL(A) FUNC_START(test_ ## A) 9 + #define _GLOBAL_TOC(A) FUNC_START(test_ ## A) 10 + 11 + #define CONFIG_ALTIVEC 12 + 13 + #define R14 r14 14 + #define R15 r15 15 + #define R16 r16 16 + #define R17 r17 17 + #define R18 r18 18 + #define R19 r19 19 + #define R20 r20 20 + #define R21 r21 21 + #define R22 r22 22 + #define R29 r29 23 + #define R30 r30 24 + #define R31 r31 25 + 26 + #define STACKFRAMESIZE 256 27 + #define STK_REG(i) (112 + ((i)-14)*8) 28 + 29 + #define BEGIN_FTR_SECTION 30 + #define END_FTR_SECTION_IFSET(val) 31 + #endif
+75 -21
tools/testing/selftests/powerpc/stringloops/memcmp.c
··· 2 2 #include <malloc.h> 3 3 #include <stdlib.h> 4 4 #include <string.h> 5 + #include <time.h> 5 6 #include "utils.h" 6 7 7 8 #define SIZE 256 8 9 #define ITERATIONS 10000 9 10 11 + #define LARGE_SIZE (5 * 1024) 12 + #define LARGE_ITERATIONS 1000 13 + #define LARGE_MAX_OFFSET 32 14 + #define LARGE_SIZE_START 4096 15 + 16 + #define MAX_OFFSET_DIFF_S1_S2 48 17 + 18 + int vmx_count; 19 + int enter_vmx_ops(void) 20 + { 21 + vmx_count++; 22 + return 1; 23 + } 24 + 25 + void exit_vmx_ops(void) 26 + { 27 + vmx_count--; 28 + } 10 29 int test_memcmp(const void *s1, const void *s2, size_t n); 11 30 12 31 /* test all offsets and lengths */ 13 - static void test_one(char *s1, char *s2) 32 + static void test_one(char *s1, char *s2, unsigned long max_offset, 33 + unsigned long size_start, unsigned long max_size) 14 34 { 15 35 unsigned long offset, size; 16 36 17 - for (offset = 0; offset < SIZE; offset++) { 18 - for (size = 0; size < (SIZE-offset); size++) { 37 + for (offset = 0; offset < max_offset; offset++) { 38 + for (size = size_start; size < (max_size - offset); size++) { 19 39 int x, y; 20 40 unsigned long i; 21 41 ··· 55 35 printf("\n"); 56 36 abort(); 57 37 } 38 + 39 + if (vmx_count != 0) { 40 + printf("vmx enter/exit not paired.(offset:%ld size:%ld s1:%p s2:%p vc:%d\n", 41 + offset, size, s1, s2, vmx_count); 42 + printf("\n"); 43 + abort(); 44 + } 58 45 } 59 46 } 60 47 } 61 48 62 - static int testcase(void) 49 + static int testcase(bool islarge) 63 50 { 64 51 char *s1; 65 52 char *s2; 66 53 unsigned long i; 67 54 68 - s1 = memalign(128, SIZE); 55 + unsigned long comp_size = (islarge ? LARGE_SIZE : SIZE); 56 + unsigned long alloc_size = comp_size + MAX_OFFSET_DIFF_S1_S2; 57 + int iterations = islarge ? LARGE_ITERATIONS : ITERATIONS; 58 + 59 + s1 = memalign(128, alloc_size); 69 60 if (!s1) { 70 61 perror("memalign"); 71 62 exit(1); 72 63 } 73 64 74 - s2 = memalign(128, SIZE); 65 + s2 = memalign(128, alloc_size); 75 66 if (!s2) { 76 67 perror("memalign"); 77 68 exit(1); 78 69 } 79 70 80 - srandom(1); 71 + srandom(time(0)); 81 72 82 - for (i = 0; i < ITERATIONS; i++) { 73 + for (i = 0; i < iterations; i++) { 83 74 unsigned long j; 84 75 unsigned long change; 76 + char *rand_s1 = s1; 77 + char *rand_s2 = s2; 85 78 86 - for (j = 0; j < SIZE; j++) 79 + for (j = 0; j < alloc_size; j++) 87 80 s1[j] = random(); 88 81 89 - memcpy(s2, s1, SIZE); 82 + rand_s1 += random() % MAX_OFFSET_DIFF_S1_S2; 83 + rand_s2 += random() % MAX_OFFSET_DIFF_S1_S2; 84 + memcpy(rand_s2, rand_s1, comp_size); 90 85 91 86 /* change one byte */ 92 - change = random() % SIZE; 93 - s2[change] = random() & 0xff; 87 + change = random() % comp_size; 88 + rand_s2[change] = random() & 0xff; 94 89 95 - test_one(s1, s2); 90 + if (islarge) 91 + test_one(rand_s1, rand_s2, LARGE_MAX_OFFSET, 92 + LARGE_SIZE_START, comp_size); 93 + else 94 + test_one(rand_s1, rand_s2, SIZE, 0, comp_size); 96 95 } 97 96 98 - srandom(1); 97 + srandom(time(0)); 99 98 100 - for (i = 0; i < ITERATIONS; i++) { 99 + for (i = 0; i < iterations; i++) { 101 100 unsigned long j; 102 101 unsigned long change; 102 + char *rand_s1 = s1; 103 + char *rand_s2 = s2; 103 104 104 - for (j = 0; j < SIZE; j++) 105 + for (j = 0; j < alloc_size; j++) 105 106 s1[j] = random(); 106 107 107 - memcpy(s2, s1, SIZE); 108 + rand_s1 += random() % MAX_OFFSET_DIFF_S1_S2; 109 + rand_s2 += random() % MAX_OFFSET_DIFF_S1_S2; 110 + memcpy(rand_s2, rand_s1, comp_size); 108 111 109 112 /* change multiple bytes, 1/8 of total */ 110 - for (j = 0; j < SIZE / 8; j++) { 111 - change = random() % SIZE; 113 + for (j = 0; j < comp_size / 8; j++) { 114 + change = random() % comp_size; 112 115 s2[change] = random() & 0xff; 113 116 } 114 117 115 - test_one(s1, s2); 118 + if (islarge) 119 + test_one(rand_s1, rand_s2, LARGE_MAX_OFFSET, 120 + LARGE_SIZE_START, comp_size); 121 + else 122 + test_one(rand_s1, rand_s2, SIZE, 0, comp_size); 116 123 } 117 124 118 125 return 0; 119 126 } 120 127 128 + static int testcases(void) 129 + { 130 + testcase(0); 131 + testcase(1); 132 + return 0; 133 + } 134 + 121 135 int main(void) 122 136 { 123 - return test_harness(testcase, "memcmp"); 137 + return test_harness(testcases, "memcmp"); 124 138 }