diff --git a/.gitmodules b/.gitmodules index 2a363f52..aefac6bd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "executer/user/lib/syscall_intercept"] path = executer/user/lib/syscall_intercept url = https://github.com/RIKEN-SysSoft/syscall_intercept.git +[submodule "executer/user/lib/uti"] + path = executer/user/lib/uti + url = https://github.com/RIKEN-SysSoft/uti.git diff --git a/docs/uti.rst b/docs/uti.rst index 607fd2c6..3d5cc75b 100644 --- a/docs/uti.rst +++ b/docs/uti.rst @@ -41,19 +41,6 @@ and then install it to your home directory of the login node: sed -i 's#/usr/#'"$HOME"'/'"$(uname -p)"'/usr/#' $HOME/$(uname -p)/usr/lib64/pkgconfig/capstone.pc -Install UTI for McKernel -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Install: - -.. code-block:: none - - git clone https://github.com/RIKEN-SysSoft/uti.git - mkdir build && cd build - ../uti/configure --prefix= --with-rm=mckernel - make && make install - - Install McKernel ~~~~~~~~~~~~~~~~~~~~ @@ -73,8 +60,8 @@ Run programs mcexec --enable-uti -Install UTI for Linux -~~~~~~~~~~~~~~~~~~~~~ +(Optional) Install UTI for Linux +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You can skip this step if you don't want to develop a run-time using UTI, or if it's already installed with, for example, Fujitsu Technical Computing Suite. @@ -100,3 +87,8 @@ Install by rpm rpmbuild -ba ./scripts/uti.spec rpm -Uvh uti---.rpm +(Optional) Install UTI for McKernel +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can skip this step if you don't want to develop a run-time using UTI. +Execute the commands above for installing UTI for Linux, with ``--with-rm=linux`` replaced with ``--with-rm=mckernel``. diff --git a/executer/user/lib/CMakeLists.txt b/executer/user/lib/CMakeLists.txt index e44fbe1b..de0ef430 100644 --- a/executer/user/lib/CMakeLists.txt +++ b/executer/user/lib/CMakeLists.txt @@ -9,8 +9,41 @@ if (ENABLE_UTI) set(SYSCALL_INTERCEPT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/syscall_intercept" CACHE STRINGS "relative path to syscalL_intercept source directory") endif() + + # syscall_intercept # change cmake options only in this directory SET(CMAKE_BUILD_TYPE Release CACHE STRING "release build" FORCE) SET(TREAT_WARNINGS_AS_ERRORS OFF CACHE BOOL "ignore warnings" FORCE) add_subdirectory(${SYSCALL_INTERCEPT_SOURCE_DIR} syscall_intercept) + + + # libuti + find_path(LIBCAP_INCLUDE_DIRS + capability.h + PATHS /usr/include/sys + NO_DEFAULT_PATH) + + find_library(LIBCAP_LIBRARIES + NAME cap + PATHS /usr/lib64 + NO_DEFAULT_PATH) + + if (NOT LIBCAP_INCLUDE_DIRS OR NOT LIBCAP_LIBRARIES) + message(FATAL_ERROR "error: couldn't find libcap") + endif() + + include(ExternalProject) + # Install libuti.so.* into /mck/ so that mcexec can + # redirect ld*.so's access to it. In this way, a.out created + # by Fujitsu MPI and linked to libuti.so in the standard path + # can use the McKernel version when invoked through mcexec. + ExternalProject_Add(libuti + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/uti + BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/uti + INSTALL_DIR ${prefix} + CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/uti/configure --prefix= --libdir=/lib64 --disable-static --with-rm=mckernel + BUILD_COMMAND ${MAKE} + BUILD_IN_SOURCE FALSE + INSTALL_COMMAND ${MAKE} install && bash -c "rm ${prefix}/include/uti.h ${prefix}/lib64/libuti.la && [[ -d ${prefix}/lib64/mck ]] || mkdir ${prefix}/lib64/mck && mv ${prefix}/lib64/libuti.* ${prefix}/lib64/mck" + ) endif() diff --git a/executer/user/lib/uti b/executer/user/lib/uti new file mode 160000 index 00000000..8c5a5568 --- /dev/null +++ b/executer/user/lib/uti @@ -0,0 +1 @@ +Subproject commit 8c5a556814efe1f57e5eb58b72318069dd7738b5 diff --git a/executer/user/mcexec.c b/executer/user/mcexec.c index b807d236..397e744f 100644 --- a/executer/user/mcexec.c +++ b/executer/user/mcexec.c @@ -3395,6 +3395,29 @@ overlay_path(int dirfd, const char *in, char *buf, int *resolvelinks) if (!strcmp(path, "/dev/xpmem")) return "/dev/null"; + + if (enable_uti && strstr(path, "libuti.so")) { + char libdir[PATH_MAX]; + char *basename; + + basename = strrchr(path, '/'); + if (basename == NULL) { + basename = (char *)path; + } else { + basename++; + } + if (find_libdir(libdir, sizeof(libdir)) < 0) { + fprintf(stderr, "error: failed to find library directory\n"); + return in; + } + n = snprintf(buf, PATH_MAX, "%s/mck/%s", + libdir, basename); + __dprintf("%s: %s replaced with %s\n", + __func__, path, buf); + goto checkexist; + } + + if (!strncmp(path, "/proc/self", 10) && (path[10] == '/' || path[10] == '\0')) { n = snprintf(buf, PATH_MAX, "/proc/mcos%d/%d%s", diff --git a/scripts/mckernel.spec.in b/scripts/mckernel.spec.in index 9b3651c5..714ae836 100644 --- a/scripts/mckernel.spec.in +++ b/scripts/mckernel.spec.in @@ -111,6 +111,9 @@ This package contains headers and libraries required for build apps using IHK/Mc %{_libdir}/libsyscall_intercept.so.0.1.0 %{_libdir}/libsyscall_intercept.so.0 %{_libdir}/libsyscall_intercept.so +%{_libdir}/mck/libuti.so.1.0.0 +%{_libdir}/mck/libuti.so.1 +%{_libdir}/mck/libuti.so %{_sysconfdir}/irqbalance_mck.in %{_mandir}/man1/mcreboot.1.gz %{_mandir}/man1/ihkconfig.1.gz diff --git a/test/uti/libuti/CMakeLists.txt b/test/uti/libuti/CMakeLists.txt new file mode 100644 index 00000000..8ac02ebb --- /dev/null +++ b/test/uti/libuti/CMakeLists.txt @@ -0,0 +1,102 @@ +cmake_minimum_required(VERSION 3.0) +cmake_policy(SET CMP0005 NEW) +project(uti_libuti C) + +execute_process(COMMAND bash -c "gawk '/CPU implementer/ { print \$4; exit; }' /proc/cpuinfo" + OUTPUT_VARIABLE CPU_IMPLEMENTER OUTPUT_STRIP_TRAILING_WHITESPACE) +execute_process(COMMAND bash -c "gawk '/CPU architecture/ { print \$3; exit; }' /proc/cpuinfo" + OUTPUT_VARIABLE CPU_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE) +execute_process(COMMAND bash -c "gawk '/CPU variant/ { print \$4; exit; }' /proc/cpuinfo" + OUTPUT_VARIABLE CPU_VARIANT OUTPUT_STRIP_TRAILING_WHITESPACE) +execute_process(COMMAND bash -c "gawk '/CPU part/ { print \$4; exit; }' /proc/cpuinfo" + OUTPUT_VARIABLE CPU_PART OUTPUT_STRIP_TRAILING_WHITESPACE) + +if(CPU_IMPLEMENTER STREQUAL "0x46" AND CPU_ARCH STREQUAL "8" AND + CPU_VARIANT STREQUAL "0x1" AND CPU_PART STREQUAL "0x001") + message("A64FX detected") + set(CPU_MODEL "a64fx") + add_definitions(-D__a64fx__) +endif() + +# Options: -DWITH_MCK= +add_definitions(-DWITH_MCK=${WITH_MCK}) + +# libuti install directory +execute_process(COMMAND bash -c "grep -E '^LIBUTI_DIR' $ENV{HOME}/.mck_test_config | cut -d= -f2" + OUTPUT_VARIABLE LIBUTI_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) +message("LIBUTI_DIR: ${LIBUTI_DIR}") + +execute_process(COMMAND bash -c "grep -E '^BOOTPARAM' $ENV{HOME}/.mck_test_config | cut -d= -f2" + OUTPUT_VARIABLE BOOTPARAM OUTPUT_STRIP_TRAILING_WHITESPACE) +message("BOOTPARAM: ${BOOTPARAM}") + +# for autotest +if(NOT DEFINED CMAKE_INSTALL_PREFIX_SCRIPTS) + set(CMAKE_INSTALL_PREFIX_SCRIPTS ${CMAKE_INSTALL_PREFIX}/scripts) +endif() + +# CPPFLAGS + +set(UNAME_R ${CMAKE_SYSTEM_VERSION} CACHE STRING "Kernel version to build against") +set(KERNEL_DIR "/lib/modules/${UNAME_R}/build" CACHE STRING "kernel build directory") +execute_process(COMMAND awk -F= "$1 == \"CONFIG_ARM64_64K_PAGES\" { print $2; exit; }" "${KERNEL_DIR}/.config" + OUTPUT_VARIABLE CONFIG_ARM64_64K_PAGES OUTPUT_STRIP_TRAILING_WHITESPACE) +if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") + if(CONFIG_ARM64_64K_PAGES STREQUAL "y") + set(PAGE_SIZE "65536") + else() + set(PAGE_SIZE "4096") + endif() +else() + set(PAGE_SIZE "4096") +endif() +message("PAGE_SIZE: ${PAGE_SIZE}") + +# CFLAGS +set(CFLAGS_WARNING "-Wall" "-Wextra" "-Wno-unused-parameter" "-Wno-sign-compare" "-Wno-unused-function" ${EXTRA_WARNINGS} CACHE STRING "Warning flags") +add_compile_options( + -O2 + -g + ${CFLAGS_WARNING} + ) + + +# -L, this must be done before adding dependants +link_directories("${LIBUTI_DIR}/lib") + +# -Wl,--rpath=, this must be done before adding dependants +# set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) +# set(CMAKE_INSTALL_RPATH "${WITH_MCK}/lib64/mck") + +# test driver scripts +foreach(target IN ITEMS + uti_pthread_create01 + ) + + # String replacement + configure_file(src/${target}.sh.in uti-${target} @ONLY) + + # Install scripts + install(PROGRAMS ${CMAKE_BINARY_DIR}/uti-${target} DESTINATION ${CMAKE_INSTALL_PREFIX_SCRIPTS}) +endforeach() + +# programs running on Linux +foreach(target IN ITEMS + uti_pthread_create01 + ) + + # Add C target + add_executable(${target} src/${target}.c) + + # -I + target_include_directories(${target} + PRIVATE ${LIBUTI_DIR}/include + ) + + # -l + target_link_libraries(${target} PRIVATE pthread uti) + + # Install + install(TARGETS ${target} DESTINATION bin) + +endforeach() diff --git a/test/uti/libuti/README b/test/uti/libuti/README new file mode 100644 index 00000000..d105f2db --- /dev/null +++ b/test/uti/libuti/README @@ -0,0 +1,21 @@ +What to test +============ + +uti_pthread_created of /lib64/mck/libuti.so is called regardless of RPATH or LD_LIBRARY_PATH. + +How to run +========== +cd .. +cwd=$(pwd) +&& rm -rf build && mkdir build && cd build +cmake -DCMAKE_INSTALL_PREFIX=$cwd/install -DWITH_MCK=$mcktest/work/mck ../libuti/ +$cwd/install/scripts/uti-uti_pthread_create01 + +You should prepare $HOME/.mck_test_config. The example: + +MCK_DIR=/home/m-takagi/project/os/install +BIN=/home/m-takagi/project/os/install/bin +SBIN=/home/m-takagi/project/os/install/sbin +BOOTPARAM="-c 12-59 -m 4G@0,4G@1,4G@2,4G@3 -r 12-35:0+36-59:1 -O" +LTP=/home/m-takagi/mcktest/ltp/install +LIBUTI_DIR=/home/m-takagi/libuti_linux diff --git a/test/uti/libuti/src/uti_pthread_create01.c b/test/uti/libuti/src/uti_pthread_create01.c new file mode 100644 index 00000000..b0ece005 --- /dev/null +++ b/test/uti/libuti/src/uti_pthread_create01.c @@ -0,0 +1,142 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +pthread_mutex_t mutex1; +pthread_cond_t cond1; +pthread_mutex_t mutex2; +pthread_cond_t cond2; +char *m; +int flag1, flag2; + +int sigst; +pthread_t thr; + +void +sigsegv(int s) +{ + if (sigst == 1) { + fprintf(stderr, "CT01007 munmap OK (SIGSEGV)\n"); + pthread_join(thr, NULL); + fprintf(stderr, "CT01008 exit(pthread_join) OK\n"); + fprintf(stderr, "CT01009 futex (pthread_mutex/pthread_cond) OK\n"); + fprintf(stderr, "CT01010 END\n"); + exit(0); + } + printf("BAD SIGSEGV\n"); + exit(1); +} + +void * +util_thread(void *arg) +{ + int rc; + + rc = syscall(732); + if (rc == -1) + fprintf(stderr, "CT01003 running on Linux OK\n"); + else { + fprintf(stderr, "CT01003 running on McKernel NG\n"); + exit(1); + } + errno = 0; + m = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + if (m != (void *)-1) { + fprintf(stderr, "CT01004 mmap OK\n"); + } + else { + fprintf(stderr, "CT01004 mmap NG errno=%d\n", errno); + exit(1); + } + strcpy(m, "mmap OK"); + pthread_mutex_lock(&mutex1); + flag1 = 1; + pthread_cond_signal(&cond1); + pthread_mutex_unlock(&mutex1); + + pthread_mutex_lock(&mutex2); + while (!flag2) { + pthread_cond_wait(&cond2, &mutex2); + } + flag2 = 0; + pthread_mutex_unlock(&mutex2); + rc = munmap(m, 4096); + if (rc == 0) { + fprintf(stderr, "CT01006 munmap OK\n"); + } + else { + fprintf(stderr, "CT01006 munmap NG errno=%d\n", errno); + exit(1); + } + + pthread_mutex_lock(&mutex1); + flag1 = 1; + pthread_cond_signal(&cond1); + pthread_mutex_unlock(&mutex1); + return NULL; +} + +int +main(int argc, char **argv) +{ + int rc; + uti_attr_t uti_attr; + + signal(SIGSEGV, sigsegv); + pthread_mutex_init(&mutex1, NULL); + pthread_cond_init(&cond1, NULL); + pthread_mutex_init(&mutex2, NULL); + pthread_cond_init(&cond2, NULL); + + fprintf(stderr, "CT01001 mmap/munmap/futex/exit START\n"); + + if ((rc = uti_attr_init(&uti_attr))) { + fprintf(stderr, "%s: error: uti_attr_init failed with %d\n", + __func__, rc); + exit(1); + } + + rc = uti_pthread_create(&thr, NULL, util_thread, NULL, &uti_attr); + if (rc) { + fprintf(stderr, "%s: uti_pthread_create failed with %d\n", + __func__, rc); + exit(1); + } + fprintf(stderr, "CT01002 uti_pthread_create OK\n"); + pthread_mutex_lock(&mutex1); + while (!flag1) { + pthread_cond_wait(&cond1, &mutex1); + } + flag1 = 0; + pthread_mutex_unlock(&mutex1); + + fprintf(stderr, "CT01005 %s\n", m); + pthread_mutex_lock(&mutex2); + flag2 = 1; + pthread_cond_signal(&cond2); + pthread_mutex_unlock(&mutex2); + + pthread_mutex_lock(&mutex1); + while (!flag1) { + pthread_cond_wait(&cond1, &mutex1); + } + flag1 = 0; + pthread_mutex_unlock(&mutex1); + + sigst = 1; + fprintf(stderr, "%s\n", m); + fprintf(stderr, "CT01007 munmap NG\n"); + pthread_join(thr, NULL); + fprintf(stderr, "CT01008 exit(pthread_join) OK\n"); + fprintf(stderr, "CT01009 futex (pthread_mutex/pthread_cond) OK\n"); + fprintf(stderr, "CT01010 END\n"); + exit(0); +} diff --git a/test/uti/libuti/src/uti_pthread_create01.sh.in b/test/uti/libuti/src/uti_pthread_create01.sh.in new file mode 100644 index 00000000..2c06be75 --- /dev/null +++ b/test/uti/libuti/src/uti_pthread_create01.sh.in @@ -0,0 +1,21 @@ +#!/usr/bin/bash + +# define WORKDIR +SCRIPT_PATH=$(readlink -m "${BASH_SOURCE[0]}") +SCRIPT_NAME="${SCRIPT_PATH##*/}" +TEST_NAME="${SCRIPT_NAME%.sh}" +AUTOTEST_HOME="${SCRIPT_PATH%/*/*/*}" +if [ -f ${AUTOTEST_HOME}/bin/config.sh ]; then + . ${AUTOTEST_HOME}/bin/config.sh +else + WORKDIR=$(pwd) +fi + +@WITH_MCK@/sbin/mcstop+release.sh +@WITH_MCK@/sbin/mcreboot.sh @BOOTPARAM@ + +@WITH_MCK@/bin/mcexec --enable-uti @CMAKE_INSTALL_PREFIX@/bin/uti_pthread_create01 || exit $? + +@WITH_MCK@/sbin/mcstop+release.sh + +exit 0