diff options
Diffstat (limited to '')
-rw-r--r-- | tools/testing/selftests/powerpc/include/basic_asm.h | 63 | ||||
-rw-r--r-- | tools/testing/selftests/powerpc/include/pkeys.h | 2 | ||||
-rw-r--r-- | tools/testing/selftests/powerpc/include/reg.h | 81 | ||||
-rw-r--r-- | tools/testing/selftests/powerpc/include/subunit.h | 16 | ||||
-rw-r--r-- | tools/testing/selftests/powerpc/include/utils.h | 80 |
5 files changed, 176 insertions, 66 deletions
diff --git a/tools/testing/selftests/powerpc/include/basic_asm.h b/tools/testing/selftests/powerpc/include/basic_asm.h index 886dc026fe7a..26cde8ea1f49 100644 --- a/tools/testing/selftests/powerpc/include/basic_asm.h +++ b/tools/testing/selftests/powerpc/include/basic_asm.h @@ -5,6 +5,16 @@ #include <ppc-asm.h> #include <asm/unistd.h> +#ifdef __powerpc64__ +#define PPC_LL ld +#define PPC_STL std +#define PPC_STLU stdu +#else +#define PPC_LL lwz +#define PPC_STL stw +#define PPC_STLU stwu +#endif + #define LOAD_REG_IMMEDIATE(reg, expr) \ lis reg, (expr)@highest; \ ori reg, reg, (expr)@higher; \ @@ -14,16 +24,20 @@ /* * Note: These macros assume that variables being stored on the stack are - * doublewords, while this is usually the case it may not always be the + * sizeof(long), while this is usually the case it may not always be the * case for each use case. */ +#ifdef __powerpc64__ + +// ABIv2 #if defined(_CALL_ELF) && _CALL_ELF == 2 #define STACK_FRAME_MIN_SIZE 32 #define STACK_FRAME_TOC_POS 24 #define __STACK_FRAME_PARAM(_param) (32 + ((_param)*8)) #define __STACK_FRAME_LOCAL(_num_params, _var_num) \ ((STACK_FRAME_PARAM(_num_params)) + ((_var_num)*8)) -#else + +#else // ABIv1 below #define STACK_FRAME_MIN_SIZE 112 #define STACK_FRAME_TOC_POS 40 #define __STACK_FRAME_PARAM(i) (48 + ((i)*8)) @@ -34,7 +48,24 @@ */ #define __STACK_FRAME_LOCAL(_num_params, _var_num) \ (112 + ((_var_num)*8)) -#endif + + +#endif // ABIv2 + +// Common 64-bit +#define STACK_FRAME_LR_POS 16 +#define STACK_FRAME_CR_POS 8 + +#else // 32-bit below + +#define STACK_FRAME_MIN_SIZE 16 +#define STACK_FRAME_LR_POS 4 + +#define __STACK_FRAME_PARAM(_param) (STACK_FRAME_MIN_SIZE + ((_param)*4)) +#define __STACK_FRAME_LOCAL(_num_params, _var_num) \ + ((STACK_FRAME_PARAM(_num_params)) + ((_var_num)*4)) + +#endif // __powerpc64__ /* Parameter x saved to the stack */ #define STACK_FRAME_PARAM(var) __STACK_FRAME_PARAM(var) @@ -42,8 +73,6 @@ /* Local variable x saved to the stack after x parameters */ #define STACK_FRAME_LOCAL(num_params, var) \ __STACK_FRAME_LOCAL(num_params, var) -#define STACK_FRAME_LR_POS 16 -#define STACK_FRAME_CR_POS 8 /* * It is very important to note here that _extra is the extra amount of @@ -56,19 +85,21 @@ * preprocessed incorrectly, hence r0. */ #define PUSH_BASIC_STACK(_extra) \ - mflr r0; \ - std r0, STACK_FRAME_LR_POS(%r1); \ - stdu %r1, -(_extra + STACK_FRAME_MIN_SIZE)(%r1); \ - mfcr r0; \ - stw r0, STACK_FRAME_CR_POS(%r1); \ - std %r2, STACK_FRAME_TOC_POS(%r1); + mflr r0; \ + PPC_STL r0, STACK_FRAME_LR_POS(%r1); \ + PPC_STLU %r1, -(((_extra + 15) & ~15) + STACK_FRAME_MIN_SIZE)(%r1); #define POP_BASIC_STACK(_extra) \ - ld %r2, STACK_FRAME_TOC_POS(%r1); \ - lwz r0, STACK_FRAME_CR_POS(%r1); \ - mtcr r0; \ - addi %r1, %r1, (_extra + STACK_FRAME_MIN_SIZE); \ - ld r0, STACK_FRAME_LR_POS(%r1); \ + addi %r1, %r1, (((_extra + 15) & ~15) + STACK_FRAME_MIN_SIZE); \ + PPC_LL r0, STACK_FRAME_LR_POS(%r1); \ mtlr r0; +.macro OP_REGS op, reg_width, start_reg, end_reg, base_reg, base_reg_offset=0, skip=0 + .set i, \start_reg + .rept (\end_reg - \start_reg + 1) + \op i, (\reg_width * (i - \skip) + \base_reg_offset)(\base_reg) + .set i, i + 1 + .endr +.endm + #endif /* _SELFTESTS_POWERPC_BASIC_ASM_H */ diff --git a/tools/testing/selftests/powerpc/include/pkeys.h b/tools/testing/selftests/powerpc/include/pkeys.h index 3312cb1b058d..51729d9a7111 100644 --- a/tools/testing/selftests/powerpc/include/pkeys.h +++ b/tools/testing/selftests/powerpc/include/pkeys.h @@ -24,7 +24,7 @@ #undef PKEY_DISABLE_EXECUTE #define PKEY_DISABLE_EXECUTE 0x4 -/* Older versions of libc do not not define this */ +/* Older versions of libc do not define this */ #ifndef SEGV_PKUERR #define SEGV_PKUERR 4 #endif diff --git a/tools/testing/selftests/powerpc/include/reg.h b/tools/testing/selftests/powerpc/include/reg.h index c0f2742a3a59..fad09c9d3387 100644 --- a/tools/testing/selftests/powerpc/include/reg.h +++ b/tools/testing/selftests/powerpc/include/reg.h @@ -19,6 +19,8 @@ #define mb() asm volatile("sync" : : : "memory"); #define barrier() asm volatile("" : : : "memory"); +#define SPRN_HDEXCR_RO 455 /* Userspace readonly view of SPRN_HDEXCR (471) */ + #define SPRN_MMCR2 769 #define SPRN_MMCRA 770 #define SPRN_MMCR0 779 @@ -47,11 +49,20 @@ #define SPRN_SDAR 781 #define SPRN_SIER 768 +#define SPRN_DEXCR_RO 812 /* Userspace readonly view of SPRN_DEXCR (828) */ + #define SPRN_TEXASR 0x82 /* Transaction Exception and Status Register */ #define SPRN_TFIAR 0x81 /* Transaction Failure Inst Addr */ #define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */ #define SPRN_TAR 0x32f /* Target Address Register */ +#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) +#define SPRN_PVR 0x11F + +#define PVR_CFG(pvr) (((pvr) >> 8) & 0xF) /* Configuration field */ +#define PVR_MAJ(pvr) (((pvr) >> 4) & 0xF) /* Major revision field */ +#define PVR_MIN(pvr) (((pvr) >> 0) & 0xF) /* Minor revision field */ + #define SPRN_DSCR_PRIV 0x11 /* Privilege State DSCR */ #define SPRN_DSCR 0x03 /* Data Stream Control Register */ #define SPRN_PPR 896 /* Program Priority Register */ @@ -84,6 +95,7 @@ #define TEXASR_ROT 0x0000000002000000 /* MSR register bits */ +#define MSR_HV (1ul << 60) /* Hypervisor state */ #define MSR_TS_S_LG 33 /* Trans Mem state: Suspended */ #define MSR_TS_T_LG 34 /* Trans Mem state: Active */ @@ -119,45 +131,44 @@ "li 30, %[" #_asm_symbol_name_immed "];" \ "li 31, %[" #_asm_symbol_name_immed "];" -#define ASM_LOAD_FPR_SINGLE_PRECISION(_asm_symbol_name_addr) \ - "lfs 0, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 1, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 2, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 3, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 4, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 5, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 6, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 7, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 8, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 9, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 10, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 11, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 12, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 13, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 14, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 15, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 16, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 17, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 18, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 19, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 20, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 21, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 22, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 23, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 24, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 25, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 26, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 27, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 28, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 29, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 30, 0(%[" #_asm_symbol_name_addr "]);" \ - "lfs 31, 0(%[" #_asm_symbol_name_addr "]);" +#define ASM_LOAD_FPR(_asm_symbol_name_addr) \ + "lfd 0, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 1, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 2, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 3, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 4, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 5, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 6, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 7, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 8, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 9, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 10, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 11, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 12, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 13, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 14, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 15, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 16, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 17, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 18, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 19, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 20, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 21, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 22, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 23, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 24, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 25, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 26, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 27, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 28, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 29, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 30, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfd 31, 0(%[" #_asm_symbol_name_addr "]);" #ifndef __ASSEMBLER__ void store_gpr(unsigned long *addr); void load_gpr(unsigned long *addr); -void load_fpr_single_precision(float *addr); -void store_fpr_single_precision(float *addr); +void store_fpr(double *addr); #endif /* end of __ASSEMBLER__ */ #endif /* _SELFTESTS_POWERPC_REG_H */ diff --git a/tools/testing/selftests/powerpc/include/subunit.h b/tools/testing/selftests/powerpc/include/subunit.h index 068d55fdf80f..b0bb774617c9 100644 --- a/tools/testing/selftests/powerpc/include/subunit.h +++ b/tools/testing/selftests/powerpc/include/subunit.h @@ -6,37 +6,37 @@ #ifndef _SELFTESTS_POWERPC_SUBUNIT_H #define _SELFTESTS_POWERPC_SUBUNIT_H -static inline void test_start(char *name) +static inline void test_start(const char *name) { printf("test: %s\n", name); } -static inline void test_failure_detail(char *name, char *detail) +static inline void test_failure_detail(const char *name, const char *detail) { printf("failure: %s [%s]\n", name, detail); } -static inline void test_failure(char *name) +static inline void test_failure(const char *name) { printf("failure: %s\n", name); } -static inline void test_error(char *name) +static inline void test_error(const char *name) { printf("error: %s\n", name); } -static inline void test_skip(char *name) +static inline void test_skip(const char *name) { printf("skip: %s\n", name); } -static inline void test_success(char *name) +static inline void test_success(const char *name) { printf("success: %s\n", name); } -static inline void test_finish(char *name, int status) +static inline void test_finish(const char *name, int status) { if (status) test_failure(name); @@ -44,7 +44,7 @@ static inline void test_finish(char *name, int status) test_success(name); } -static inline void test_set_git_version(char *value) +static inline void test_set_git_version(const char *value) { printf("tags: git_version:%s\n", value); } diff --git a/tools/testing/selftests/powerpc/include/utils.h b/tools/testing/selftests/powerpc/include/utils.h index 71d2924f5b8b..66d7b2368dd4 100644 --- a/tools/testing/selftests/powerpc/include/utils.h +++ b/tools/testing/selftests/powerpc/include/utils.h @@ -9,10 +9,18 @@ #define __cacheline_aligned __attribute__((aligned(128))) #include <stdint.h> +#include <stdio.h> #include <stdbool.h> +#include <sys/signal.h> #include <linux/auxvec.h> #include <linux/perf_event.h> +#include <asm/cputable.h> #include "reg.h" +#include <unistd.h> + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif /* Avoid headaches with PRI?64 - just use %ll? always */ typedef unsigned long long u64; @@ -24,26 +32,48 @@ typedef uint16_t u16; typedef uint8_t u8; void test_harness_set_timeout(uint64_t time); -int test_harness(int (test_function)(void), char *name); +int test_harness(int (test_function)(void), const char *name); int read_auxv(char *buf, ssize_t buf_size); void *find_auxv_entry(int type, char *auxv); void *get_auxv_entry(int type); -int pick_online_cpu(void); +#define BIND_CPU_ANY (-1) -int read_debugfs_file(char *debugfs_file, int *result); -int write_debugfs_file(char *debugfs_file, int result); +int pick_online_cpu(void); +int bind_to_cpu(int cpu); + +int parse_intmax(const char *buffer, size_t count, intmax_t *result, int base); +int parse_uintmax(const char *buffer, size_t count, uintmax_t *result, int base); +int parse_int(const char *buffer, size_t count, int *result, int base); +int parse_uint(const char *buffer, size_t count, unsigned int *result, int base); +int parse_long(const char *buffer, size_t count, long *result, int base); +int parse_ulong(const char *buffer, size_t count, unsigned long *result, int base); + +int read_file(const char *path, char *buf, size_t count, size_t *len); +int write_file(const char *path, const char *buf, size_t count); +int read_file_alloc(const char *path, char **buf, size_t *len); +int read_long(const char *path, long *result, int base); +int write_long(const char *path, long result, int base); +int read_ulong(const char *path, unsigned long *result, int base); +int write_ulong(const char *path, unsigned long result, int base); +int read_debugfs_file(const char *debugfs_file, char *buf, size_t count); +int write_debugfs_file(const char *debugfs_file, const char *buf, size_t count); +int read_debugfs_int(const char *debugfs_file, int *result); +int write_debugfs_int(const char *debugfs_file, int result); int read_sysfs_file(char *debugfs_file, char *result, size_t result_size); -void set_dscr(unsigned long val); int perf_event_open_counter(unsigned int type, unsigned long config, int group_fd); int perf_event_enable(int fd); int perf_event_disable(int fd); int perf_event_reset(int fd); +struct perf_event_read { + __u64 nr; + __u64 l1d_misses; +}; + #if !defined(__GLIBC_PREREQ) || !__GLIBC_PREREQ(2, 30) -#include <unistd.h> #include <sys/syscall.h> static inline pid_t gettid(void) @@ -69,9 +99,22 @@ static inline bool have_hwcap2(unsigned long ftr2) } #endif +static inline char *auxv_base_platform(void) +{ + return ((char *)get_auxv_entry(AT_BASE_PLATFORM)); +} + +static inline char *auxv_platform(void) +{ + return ((char *)get_auxv_entry(AT_PLATFORM)); +} + bool is_ppc64le(void); int using_hash_mmu(bool *using_hash); +struct sigaction push_signal_handler(int sig, void (*fn)(int, siginfo_t *, void *)); +struct sigaction pop_signal_handler(int sig, struct sigaction old_handler); + /* Yes, this is evil */ #define FAIL_IF(x) \ do { \ @@ -82,6 +125,16 @@ do { \ } \ } while (0) +#define FAIL_IF_MSG(x, msg) \ +do { \ + if ((x)) { \ + fprintf(stderr, \ + "[FAIL] Test FAILED on line %d: %s\n", \ + __LINE__, msg); \ + return 1; \ + } \ +} while (0) + #define FAIL_IF_EXIT(x) \ do { \ if ((x)) { \ @@ -91,6 +144,16 @@ do { \ } \ } while (0) +#define FAIL_IF_EXIT_MSG(x, msg) \ +do { \ + if ((x)) { \ + fprintf(stderr, \ + "[FAIL] Test FAILED on line %d: %s\n", \ + __LINE__, msg); \ + _exit(1); \ + } \ +} while (0) + /* The test harness uses this, yes it's gross */ #define MAGIC_SKIP_RETURN_VALUE 99 @@ -130,6 +193,11 @@ do { \ #define PPC_FEATURE2_ARCH_3_1 0x00040000 #endif +/* POWER10 features */ +#ifndef PPC_FEATURE2_MMA +#define PPC_FEATURE2_MMA 0x00020000 +#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] |