1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2008 4f08c3bdfSopenharmony_ci * Copyright (c) Paul Mackerras, IBM Corp., 2008 5f08c3bdfSopenharmony_ci * Copyright (c) 2018-2023 Linux Test Project 6f08c3bdfSopenharmony_ci */ 7f08c3bdfSopenharmony_ci 8f08c3bdfSopenharmony_ci/* 9f08c3bdfSopenharmony_ci * Test little-endian mode switch system call. Requires a 64-bit 10f08c3bdfSopenharmony_ci * processor that supports little-endian mode,such as POWER6. 11f08c3bdfSopenharmony_ci */ 12f08c3bdfSopenharmony_ci 13f08c3bdfSopenharmony_ci#include <errno.h> 14f08c3bdfSopenharmony_ci#include <stdio.h> 15f08c3bdfSopenharmony_ci#include <stdlib.h> 16f08c3bdfSopenharmony_ci#include <unistd.h> 17f08c3bdfSopenharmony_ci#include <elf.h> 18f08c3bdfSopenharmony_ci#include <sys/types.h> 19f08c3bdfSopenharmony_ci#include <sys/wait.h> 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_ci#include "tst_test.h" 22f08c3bdfSopenharmony_ci 23f08c3bdfSopenharmony_ci#if defined(__powerpc64__) || defined(__powerpc__) 24f08c3bdfSopenharmony_ci 25f08c3bdfSopenharmony_ci# ifndef PPC_FEATURE_TRUE_LE 26f08c3bdfSopenharmony_ci# define PPC_FEATURE_TRUE_LE 0x00000002 27f08c3bdfSopenharmony_ci# endif 28f08c3bdfSopenharmony_ci 29f08c3bdfSopenharmony_ci# ifdef HAVE_GETAUXVAL 30f08c3bdfSopenharmony_ci# include <sys/auxv.h> 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_ci/* 33f08c3bdfSopenharmony_ci * Make minimal call to 0x1ebe. If we get ENOSYS then syscall is not 34f08c3bdfSopenharmony_ci * available, likely because of: 35f08c3bdfSopenharmony_ci * commit 727f13616c45 ("powerpc: Disable the fast-endian switch syscall by default") 36f08c3bdfSopenharmony_ci * If we get any other outcome, including crashes with various signals, 37f08c3bdfSopenharmony_ci * then we assume syscall is available and carry on with the test. 38f08c3bdfSopenharmony_ci */ 39f08c3bdfSopenharmony_civoid check_le_switch_supported(void) 40f08c3bdfSopenharmony_ci{ 41f08c3bdfSopenharmony_ci int status; 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_ci if (SAFE_FORK() == 0) { 44f08c3bdfSopenharmony_ci syscall(0x1ebe); 45f08c3bdfSopenharmony_ci exit(errno); 46f08c3bdfSopenharmony_ci } 47f08c3bdfSopenharmony_ci 48f08c3bdfSopenharmony_ci if (!(getauxval(AT_HWCAP) & PPC_FEATURE_TRUE_LE)) 49f08c3bdfSopenharmony_ci tst_brk(TCONF, "Processor does not support little-endian mode"); 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_ci SAFE_WAIT(&status); 52f08c3bdfSopenharmony_ci if (WIFSIGNALED(status)) { 53f08c3bdfSopenharmony_ci int sig = WTERMSIG(status); 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_ci tst_res(TINFO, "check exited with sig %d", sig); 56f08c3bdfSopenharmony_ci } else if (WIFEXITED(status)) { 57f08c3bdfSopenharmony_ci int rc = WEXITSTATUS(status); 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_ci tst_res(TINFO, "check exited with %d", rc); 60f08c3bdfSopenharmony_ci if (rc == ENOSYS) 61f08c3bdfSopenharmony_ci tst_brk(TCONF, "fast endian switch (0x1ebe) N/A"); 62f08c3bdfSopenharmony_ci } 63f08c3bdfSopenharmony_ci} 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_civoid test_le_switch(void) 66f08c3bdfSopenharmony_ci{ 67f08c3bdfSopenharmony_ci int status; 68f08c3bdfSopenharmony_ci 69f08c3bdfSopenharmony_ci if (SAFE_FORK() == 0) { 70f08c3bdfSopenharmony_ci register int r0 asm("r0") = 0x1ebe; 71f08c3bdfSopenharmony_ci 72f08c3bdfSopenharmony_ci asm volatile ("sc; .long 0x02000044" 73f08c3bdfSopenharmony_ci : "=&r" (r0) 74f08c3bdfSopenharmony_ci : "0"(r0) 75f08c3bdfSopenharmony_ci : "cr0", "r9", "r10", "r11", "r12"); 76f08c3bdfSopenharmony_ci exit(0); 77f08c3bdfSopenharmony_ci } 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_ci SAFE_WAIT(&status); 80f08c3bdfSopenharmony_ci if (WIFSIGNALED(status)) { 81f08c3bdfSopenharmony_ci int sig = WTERMSIG(status); 82f08c3bdfSopenharmony_ci 83f08c3bdfSopenharmony_ci tst_res(TFAIL, "test exited with sig %d", sig); 84f08c3bdfSopenharmony_ci } else if (WIFEXITED(status)) { 85f08c3bdfSopenharmony_ci int rc = WEXITSTATUS(status); 86f08c3bdfSopenharmony_ci 87f08c3bdfSopenharmony_ci if (rc != 0) 88f08c3bdfSopenharmony_ci tst_res(TFAIL, "test exited with %d", rc); 89f08c3bdfSopenharmony_ci else 90f08c3bdfSopenharmony_ci tst_res(TPASS, "endian_switch() syscall tests passed"); 91f08c3bdfSopenharmony_ci } 92f08c3bdfSopenharmony_ci} 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_cistatic void endian_test(void) 95f08c3bdfSopenharmony_ci{ 96f08c3bdfSopenharmony_ci check_le_switch_supported(); 97f08c3bdfSopenharmony_ci test_le_switch(); 98f08c3bdfSopenharmony_ci} 99f08c3bdfSopenharmony_ci 100f08c3bdfSopenharmony_cistatic struct tst_test test = { 101f08c3bdfSopenharmony_ci .test_all = endian_test, 102f08c3bdfSopenharmony_ci .forks_child = 1, 103f08c3bdfSopenharmony_ci}; 104f08c3bdfSopenharmony_ci 105f08c3bdfSopenharmony_ci# else 106f08c3bdfSopenharmony_ciTST_TEST_TCONF("Toolchain does not have <sys/auxv.h>"); 107f08c3bdfSopenharmony_ci# endif /* HAVE_GETAUXVAL */ 108f08c3bdfSopenharmony_ci 109f08c3bdfSopenharmony_ci#else /* defined (__powerpc64__) || (__powerpc__) */ 110f08c3bdfSopenharmony_ciTST_TEST_TCONF("This system does not support running of switch() syscall"); 111f08c3bdfSopenharmony_ci#endif 112