Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/google/cpu_features.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormarquitos0119 <111894523+marquitos0119@users.noreply.github.com>2022-11-02 11:38:13 +0300
committerGitHub <noreply@github.com>2022-11-02 11:38:13 +0300
commit981fbe391454da866f1df57be72c4441b6396117 (patch)
treeccd7454f29a88b249e0188d718dffeb58e57bffb
parentbddcc3721c7ab1f88094617fb28572b771e77d6f (diff)
S390X Support (#274)
* support for s390x * added z15 T01, T02 model checking * removed z15 checking * removed empty strings * added s390x unit tests * added reference url for hwcaps * moved documentation to S390XFeatures struct, updated copyright date, removed unused include statement * changed num_processors to int * removed newlines from test inputs * scripts: Add bootlin s390x support * cmake(ci): Add s390x support * ci: Add s390x workflow Co-authored-by: Marcos <marcos.araque.fiallos@ibm.com> Co-authored-by: Corentin Le Molgat <corentinl@google.com>
-rw-r--r--.github/workflows/s390x_linux_cmake.yml27
-rw-r--r--CMakeLists.txt5
-rw-r--r--cmake/ci/Makefile4
-rw-r--r--include/cpu_features_macros.h4
-rw-r--r--include/cpuinfo_s390x.h108
-rw-r--r--include/internal/hwcaps.h28
-rwxr-xr-xscripts/run_integration.sh60
-rw-r--r--src/impl_s390x_linux.c120
-rw-r--r--src/utils/list_cpu_features.c13
-rw-r--r--test/CMakeLists.txt7
-rw-r--r--test/cpuinfo_s390x_test.cc82
11 files changed, 457 insertions, 1 deletions
diff --git a/.github/workflows/s390x_linux_cmake.yml b/.github/workflows/s390x_linux_cmake.yml
new file mode 100644
index 0000000..5be96a1
--- /dev/null
+++ b/.github/workflows/s390x_linux_cmake.yml
@@ -0,0 +1,27 @@
+name: s390x Linux CMake
+
+on:
+ push:
+ pull_request:
+ schedule:
+ # min hours day(month) month day(week)
+ - cron: '0 0 7,22 * *'
+
+jobs:
+ # Building using the github runner environement directly.
+ make:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ targets: [
+ [s390x],
+ ]
+ fail-fast: false
+ env:
+ TARGET: ${{ matrix.targets[0] }}
+ steps:
+ - uses: actions/checkout@v2
+ - name: Build
+ run: make --directory=cmake/ci ${TARGET}_build
+ - name: Test
+ run: make --directory=cmake/ci ${TARGET}_test
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 15d7aad..e2ffbe2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -49,6 +49,7 @@ set(PROCESSOR_IS_ARM FALSE)
set(PROCESSOR_IS_AARCH64 FALSE)
set(PROCESSOR_IS_X86 FALSE)
set(PROCESSOR_IS_POWER FALSE)
+set(PROCESSOR_IS_S390X FALSE)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips")
set(PROCESSOR_IS_MIPS TRUE)
@@ -60,6 +61,8 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64)|(AMD64|amd64)|(^i.86$)")
set(PROCESSOR_IS_X86 TRUE)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
set(PROCESSOR_IS_POWER TRUE)
+elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(s390x)")
+ set(PROCESSOR_IS_S390X TRUE)
endif()
macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME)
@@ -79,6 +82,8 @@ macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME)
list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/windows_utils.h)
elseif(PROCESSOR_IS_POWER)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_ppc.h)
+ elseif(PROCESSOR_IS_S390X)
+ list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_s390x.h)
else()
message(FATAL_ERROR "Unsupported architectures ${CMAKE_SYSTEM_PROCESSOR}")
endif()
diff --git a/cmake/ci/Makefile b/cmake/ci/Makefile
index dc19af8..b4ac3f1 100644
--- a/cmake/ci/Makefile
+++ b/cmake/ci/Makefile
@@ -50,6 +50,7 @@ help:
@echo -e "\t\t${BOLD}mips64${RESET} (codespace toolchain)"
@echo -e "\t\t${BOLD}mips32el${RESET} (codespace toolchain)"
@echo -e "\t\t${BOLD}mips64el${RESET} (codespace toolchain)"
+ @echo -e "\t\t${BOLD}s390x${RESET} (bootlin toolchain)"
@echo
@echo -e "\tWith ${BOLD}<toolchain_stage>${RESET}:"
@echo -e "\t\t${BOLD}env${RESET}"
@@ -145,7 +146,8 @@ $(clean_targets_amd64): clean_amd64_%:
TOOLCHAIN_TARGETS = \
arm-linux-gnueabihf armv8l-linux-gnueabihf arm-linux-gnueabi armeb-linux-gnueabihf armeb-linux-gnueabi \
aarch64-linux-gnu aarch64_be-linux-gnu \
- mips32 mips32el mips64 mips64el
+ mips32 mips32el mips64 mips64el \
+ s390x
TOOLCHAIN_STAGES = env devel build test
define toolchain-stage-target =
#$$(info STAGE: $1)
diff --git a/include/cpu_features_macros.h b/include/cpu_features_macros.h
index 09f8297..b759220 100644
--- a/include/cpu_features_macros.h
+++ b/include/cpu_features_macros.h
@@ -63,6 +63,10 @@
#define CPU_FEATURES_ARCH_PPC
#endif
+#if defined(__s390x__)
+#define CPU_FEATURES_ARCH_S390X
+#endif
+
#if defined(__riscv)
#define CPU_FEATURES_ARCH_RISCV
#endif
diff --git a/include/cpuinfo_s390x.h b/include/cpuinfo_s390x.h
new file mode 100644
index 0000000..48864de
--- /dev/null
+++ b/include/cpuinfo_s390x.h
@@ -0,0 +1,108 @@
+// Copyright 2022 IBM
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CPU_FEATURES_INCLUDE_CPUINFO_S390X_H_
+#define CPU_FEATURES_INCLUDE_CPUINFO_S390X_H_
+
+#include "cpu_features_cache_info.h"
+#include "cpu_features_macros.h"
+
+CPU_FEATURES_START_CPP_NAMESPACE
+
+typedef struct {
+ int esan3: 1; // instructions named N3, "backported" to esa-mode
+ int zarch: 1; // z/Architecture mode active
+ int stfle: 1; // store-facility-list-extended
+ int msa: 1; // message-security assist
+ int ldisp: 1; // long-displacement
+ int eimm: 1; // extended-immediate
+ int dfp: 1; // decimal floating point & perform floating point operation
+ int edat: 1; // huge page support
+ int etf3eh: 1; // extended-translation facility 3 enhancement
+ int highgprs: 1; // 64-bit register support for 31-bit processes
+ int te: 1; // transactional execution
+ int vx: 1; // vector extension facility
+ int vxd: 1; // vector-packed-decimal facility
+ int vxe: 1; // vector-enhancement facility 1
+ int gs: 1; // guarded-storage facility
+ int vxe2: 1; // vector-enhancements facility 2
+ int vxp: 1; // vector-packed-decimal-enhancement facility
+ int sort: 1; // enhanced-sort facility
+ int dflt: 1; // deflate-conversion facility
+ int vxp2: 1; // vector-packed-decimal-enhancement facility 2
+ int nnpa: 1; // neural network processing assist facility
+ int pcimio: 1; // PCI mio facility
+ int sie: 1; // virtualization support
+
+ // Make sure to update S390XFeaturesEnum below if you add a field here.
+} S390XFeatures;
+
+typedef struct {
+ S390XFeatures features;
+} S390XInfo;
+
+S390XInfo GetS390XInfo(void);
+
+typedef struct {
+ char platform[64]; // 0 terminated string
+} S390XPlatformTypeStrings;
+
+typedef struct {
+ int num_processors; // -1 if N/A
+ S390XPlatformTypeStrings type;
+} S390XPlatformStrings;
+
+S390XPlatformStrings GetS390XPlatformStrings(void);
+
+////////////////////////////////////////////////////////////////////////////////
+// Introspection functions
+
+typedef enum {
+ S390_ESAN3,
+ S390_ZARCH,
+ S390_STFLE,
+ S390_MSA,
+ S390_LDISP,
+ S390_EIMM,
+ S390_DFP,
+ S390_EDAT,
+ S390_ETF3EH,
+ S390_HIGHGPRS,
+ S390_TE,
+ S390_VX,
+ S390_VXD,
+ S390_VXE,
+ S390_GS,
+ S390_VXE2,
+ S390_VXP,
+ S390_SORT,
+ S390_DFLT,
+ S390_VXP2,
+ S390_NNPA,
+ S390_PCIMIO,
+ S390_SIE,
+ S390X_LAST_,
+} S390XFeaturesEnum;
+
+int GetS390XFeaturesEnumValue(const S390XFeatures* features, S390XFeaturesEnum value);
+
+const char* GetS390XFeaturesEnumName(S390XFeaturesEnum);
+
+CPU_FEATURES_END_CPP_NAMESPACE
+
+#if !defined(CPU_FEATURES_ARCH_S390X)
+#error "Including cpuinfo_s390x.h from a non-s390x target."
+#endif
+
+#endif // CPU_FEATURES_INCLUDE_CPUINFO_S390X_H_
diff --git a/include/internal/hwcaps.h b/include/internal/hwcaps.h
index f916b81..5030582 100644
--- a/include/internal/hwcaps.h
+++ b/include/internal/hwcaps.h
@@ -176,6 +176,34 @@ CPU_FEATURES_START_CPP_NAMESPACE
#define PPC_FEATURE2_HTM_NO_SUSPEND 0x00080000
#endif
+// https://elixir.bootlin.com/linux/v6.0-rc6/source/arch/s390/include/asm/elf.h
+#define HWCAP_S390_ESAN3 1
+#define HWCAP_S390_ZARCH 2
+#define HWCAP_S390_STFLE 4
+#define HWCAP_S390_MSA 8
+#define HWCAP_S390_LDISP 16
+#define HWCAP_S390_EIMM 32
+#define HWCAP_S390_DFP 64
+#define HWCAP_S390_HPAGE 128
+#define HWCAP_S390_ETF3EH 256
+#define HWCAP_S390_HIGH_GPRS 512
+#define HWCAP_S390_TE 1024
+#define HWCAP_S390_VX 2048
+#define HWCAP_S390_VXRS HWCAP_S390_VX
+#define HWCAP_S390_VXD 4096
+#define HWCAP_S390_VXRS_BCD HWCAP_S390_VXD
+#define HWCAP_S390_VXE 8192
+#define HWCAP_S390_VXRS_EXT HWCAP_S390_VXE
+#define HWCAP_S390_GS 16384
+#define HWCAP_S390_VXRS_EXT2 32768
+#define HWCAP_S390_VXRS_PDE 65536
+#define HWCAP_S390_SORT 131072
+#define HWCAP_S390_DFLT 262144
+#define HWCAP_S390_VXRS_PDE2 524288
+#define HWCAP_S390_NNPA 1048576
+#define HWCAP_S390_PCI_MIO 2097152
+#define HWCAP_S390_SIE 4194304
+
// https://elixir.bootlin.com/linux/latest/source/arch/riscv/include/uapi/asm/hwcap.h
#define RISCV_HWCAP_A (1UL << ('A' - 'A'))
#define RISCV_HWCAP_C (1UL << ('C' - 'A'))
diff --git a/scripts/run_integration.sh b/scripts/run_integration.sh
index 645cb6a..10a0968 100755
--- a/scripts/run_integration.sh
+++ b/scripts/run_integration.sh
@@ -140,6 +140,62 @@ QEMU_ARGS+=( -L "${SYSROOT_DIR}" )
QEMU_ARGS+=( -E LD_LIBRARY_PATH=/lib )
}
+function expand_bootlin_config() {
+ # ref: https://toolchains.bootlin.com/
+ local -r GCC_DIR=${ARCHIVE_DIR}/${GCC_RELATIVE_DIR}
+
+ case "${TARGET}" in
+ "s390x")
+ local -r POWER_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/s390x-z13/tarballs/s390x-z13--glibc--stable-2022.08-1.tar.bz2"
+ local -r GCC_PREFIX="s390x"
+ ;;
+ *)
+ >&2 echo 'unknown power platform'
+ exit 1 ;;
+ esac
+
+ local -r POWER_RELATIVE_DIR="${TARGET}"
+ unpack "${POWER_URL}" "${POWER_RELATIVE_DIR}"
+ local -r EXTRACT_DIR="${ARCHIVE_DIR}/$(basename ${POWER_URL%.tar.bz2})"
+
+ local -r POWER_DIR=${ARCHIVE_DIR}/${POWER_RELATIVE_DIR}
+ if [[ -d "${EXTRACT_DIR}" ]]; then
+ mv "${EXTRACT_DIR}" "${POWER_DIR}"
+ fi
+
+ local -r SYSROOT_DIR="${POWER_DIR}/${GCC_PREFIX}-buildroot-linux-gnu/sysroot"
+ #local -r STAGING_DIR=${SYSROOT_DIR}-stage
+
+ # Write a Toolchain file
+ # note: This is manadatory to use a file in order to have the CMake variable
+ # 'CMAKE_CROSSCOMPILING' set to TRUE.
+ # ref: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-linux
+ cat >"${TOOLCHAIN_FILE}" <<EOL
+set(CMAKE_SYSTEM_NAME Linux)
+set(CMAKE_SYSTEM_PROCESSOR ${GCC_PREFIX})
+
+set(CMAKE_SYSROOT ${SYSROOT_DIR})
+#set(CMAKE_STAGING_PREFIX ${STAGING_DIR})
+
+set(tools ${POWER_DIR})
+
+set(CMAKE_C_COMPILER \${tools}/bin/${GCC_PREFIX}-linux-gcc)
+set(CMAKE_C_FLAGS "${POWER_FLAGS}")
+set(CMAKE_CXX_COMPILER \${tools}/bin/${GCC_PREFIX}-linux-g++)
+set(CMAKE_CXX_FLAGS "${POWER_FLAGS} -L${SYSROOT_DIR}/lib")
+
+set(CMAKE_FIND_ROOT_PATH ${POWER_DIR})
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+EOL
+
+CMAKE_ADDITIONAL_ARGS+=( -DCMAKE_TOOLCHAIN_FILE="${TOOLCHAIN_FILE}" )
+QEMU_ARGS+=( -L "${SYSROOT_DIR}" )
+QEMU_ARGS+=( -E LD_PRELOAD="${SYSROOT_DIR}/usr/lib/libstdc++.so.6:${SYSROOT_DIR}/lib/libgcc_s.so.1" )
+}
+
function expand_codescape_config() {
# ref: https://codescape.mips.com/components/toolchain/2020.06-01/downloads.html
# ref: https://codescape.mips.com/components/toolchain/2019.02-04/downloads.html
@@ -269,6 +325,7 @@ DESCRIPTION
\t\tarmeb-linux-gnueabihf armeb-linux-gnueabi
\t\tmips32 mips32el
\t\tmips64 mips64el
+\t\ts390x (bootlin)
OPTIONS
\t-h --help: show this help text
@@ -339,6 +396,9 @@ function main() {
mips64el)
expand_codescape_config
declare -r QEMU_ARCH=mips64el ;;
+ s390x)
+ expand_bootlin_config
+ declare -r QEMU_ARCH=s390x ;;
*)
>&2 echo "Unknown TARGET '${TARGET}'..."
exit 1 ;;
diff --git a/src/impl_s390x_linux.c b/src/impl_s390x_linux.c
new file mode 100644
index 0000000..2b8b865
--- /dev/null
+++ b/src/impl_s390x_linux.c
@@ -0,0 +1,120 @@
+// Copyright 2022 IBM.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "cpu_features_macros.h"
+
+#ifdef CPU_FEATURES_ARCH_S390X
+#ifdef CPU_FEATURES_OS_LINUX
+
+#include "cpuinfo_s390x.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// Definitions for introspection.
+////////////////////////////////////////////////////////////////////////////////
+#define INTROSPECTION_TABLE \
+ LINE(S390_ESAN3, esan3, "esan3", HWCAP_S390_ESAN3, 0) \
+ LINE(S390_ZARCH, zarch, "zarch", HWCAP_S390_ZARCH, 0) \
+ LINE(S390_STFLE, stfle, "stfle", HWCAP_S390_STFLE, 0) \
+ LINE(S390_MSA, msa, "msa", HWCAP_S390_MSA, 0) \
+ LINE(S390_LDISP, ldisp, "ldisp", HWCAP_S390_LDISP, 0) \
+ LINE(S390_EIMM, eimm, "eimm", HWCAP_S390_EIMM, 0) \
+ LINE(S390_DFP, dfp, "dfp", HWCAP_S390_DFP, 0) \
+ LINE(S390_EDAT, edat, "edat", HWCAP_S390_HPAGE, 0) \
+ LINE(S390_ETF3EH, etf3eh, "etf3eh", HWCAP_S390_ETF3EH, 0) \
+ LINE(S390_HIGHGPRS, highgprs, "highgprs", HWCAP_S390_HIGH_GPRS, 0) \
+ LINE(S390_TE, te, "te", HWCAP_S390_TE, 0) \
+ LINE(S390_VX, vx, "vx", HWCAP_S390_VXRS, 0) \
+ LINE(S390_VXD, vxd, "vxd", HWCAP_S390_VXRS_BCD, 0) \
+ LINE(S390_VXE, vxe, "vxe", HWCAP_S390_VXRS_EXT, 0) \
+ LINE(S390_GS, gs, "gs", HWCAP_S390_GS, 0) \
+ LINE(S390_VXE2, vxe2, "vxe2", HWCAP_S390_VXRS_EXT2, 0) \
+ LINE(S390_VXP, vxp, "vxp", HWCAP_S390_VXRS_PDE, 0) \
+ LINE(S390_SORT, sort, "sort", HWCAP_S390_SORT, 0) \
+ LINE(S390_DFLT, dflt, "dflt", HWCAP_S390_DFLT, 0) \
+ LINE(S390_VXP2, vxp2, "vxp2", HWCAP_S390_VXRS_PDE2, 0) \
+ LINE(S390_NNPA, nnpa, "nnpa", HWCAP_S390_NNPA, 0) \
+ LINE(S390_PCIMIO, pcimio, "pcimio", HWCAP_S390_PCI_MIO, 0) \
+ LINE(S390_SIE, sie, "sie", HWCAP_S390_SIE, 0)
+#define INTROSPECTION_PREFIX S390X
+#define INTROSPECTION_ENUM_PREFIX S390X
+#include "define_introspection_and_hwcaps.inl"
+
+////////////////////////////////////////////////////////////////////////////////
+// Implementation.
+////////////////////////////////////////////////////////////////////////////////
+
+#include <stdbool.h>
+
+#include "internal/bit_utils.h"
+#include "internal/filesystem.h"
+#include "internal/hwcaps.h"
+#include "internal/stack_line_reader.h"
+#include "internal/string_view.h"
+
+static bool HandleS390XLine(const LineResult result,
+ S390XPlatformStrings* const strings) {
+ StringView line = result.line;
+ StringView key, value;
+ if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
+ if (CpuFeatures_StringView_IsEquals(key, str("# processors"))) {
+ strings->num_processors = CpuFeatures_StringView_ParsePositiveNumber(value);
+ }
+ }
+ return !result.eof;
+}
+
+static void FillProcCpuInfoData(S390XPlatformStrings* const strings) {
+ const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
+ if (fd >= 0) {
+ StackLineReader reader;
+ StackLineReader_Initialize(&reader, fd);
+ for (;;) {
+ if (!HandleS390XLine(StackLineReader_NextLine(&reader), strings)) {
+ break;
+ }
+ }
+ CpuFeatures_CloseFile(fd);
+ }
+}
+
+static const S390XInfo kEmptyS390XInfo;
+
+S390XInfo GetS390XInfo(void) {
+ S390XInfo info = kEmptyS390XInfo;
+ const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
+ for (size_t i = 0; i < S390X_LAST_; ++i) {
+ if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
+ kSetters[i](&info.features, true);
+ }
+ }
+ return info;
+}
+
+static const S390XPlatformStrings kEmptyS390XPlatformStrings;
+
+S390XPlatformStrings GetS390XPlatformStrings(void) {
+ S390XPlatformStrings strings = kEmptyS390XPlatformStrings;
+ const char* platform = CpuFeatures_GetPlatformPointer();
+
+ FillProcCpuInfoData(&strings);
+
+ if (platform != NULL)
+ CpuFeatures_StringView_CopyString(str(platform), strings.type.platform,
+ sizeof(strings.type.platform));
+
+ return strings;
+}
+
+#endif // CPU_FEATURES_OS_LINUX
+#endif // CPU_FEATURES_ARCH_S390X
diff --git a/src/utils/list_cpu_features.c b/src/utils/list_cpu_features.c
index 4d7fe14..b280f69 100644
--- a/src/utils/list_cpu_features.c
+++ b/src/utils/list_cpu_features.c
@@ -35,6 +35,8 @@
#include "cpuinfo_mips.h"
#elif defined(CPU_FEATURES_ARCH_PPC)
#include "cpuinfo_ppc.h"
+#elif defined(CPU_FEATURES_ARCH_S390X)
+#include "cpuinfo_s390x.h"
#endif
// Design principles
@@ -205,6 +207,9 @@ DEFINE_ADD_FLAGS(GetMipsFeaturesEnumValue, GetMipsFeaturesEnumName,
#elif defined(CPU_FEATURES_ARCH_PPC)
DEFINE_ADD_FLAGS(GetPPCFeaturesEnumValue, GetPPCFeaturesEnumName, PPCFeatures,
PPC_LAST_)
+#elif defined(CPU_FEATURES_ARCH_S390X)
+DEFINE_ADD_FLAGS(GetS390XFeaturesEnumValue, GetS390XFeaturesEnumName, S390XFeatures,
+ S390X_LAST_)
#endif
// Prints a json string with characters escaping.
@@ -408,6 +413,14 @@ static Node* CreateTree(void) {
AddMapEntry(root, "microarchitecture",
CreateString(strings.type.base_platform));
AddFlags(root, &info.features);
+#elif defined(CPU_FEATURES_ARCH_S390X)
+ const S390XInfo info = GetS390XInfo();
+ const S390XPlatformStrings strings = GetS390XPlatformStrings();
+ AddMapEntry(root, "arch", CreateString("s390x"));
+ AddMapEntry(root, "platform", CreateString("zSeries"));
+ AddMapEntry(root, "model", CreateString(strings.type.platform));
+ AddMapEntry(root, "# processors", CreateInt(strings.num_processors));
+ AddFlags(root, &info.features);
#endif
return root;
}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 8e8f72a..a87d18a 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -89,3 +89,10 @@ if(PROCESSOR_IS_POWER)
target_link_libraries(cpuinfo_ppc_test all_libraries)
add_test(NAME cpuinfo_ppc_test COMMAND cpuinfo_ppc_test)
endif()
+##------------------------------------------------------------------------------
+## cpuinfo_s390x_test
+if(PROCESSOR_IS_S390X)
+ add_executable(cpuinfo_s390x_test cpuinfo_s390x_test.cc ../src/impl_s390x_linux.c)
+ target_link_libraries(cpuinfo_s390x_test all_libraries)
+ add_test(NAME cpuinfo_s390x_test COMMAND cpuinfo_s390x_test)
+endif()
diff --git a/test/cpuinfo_s390x_test.cc b/test/cpuinfo_s390x_test.cc
new file mode 100644
index 0000000..800d3e9
--- /dev/null
+++ b/test/cpuinfo_s390x_test.cc
@@ -0,0 +1,82 @@
+// Copyright 2022 IBM.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "cpuinfo_s390x.h"
+#include "filesystem_for_testing.h"
+#include "gtest/gtest.h"
+#include "hwcaps_for_testing.h"
+
+namespace cpu_features {
+namespace {
+
+TEST(CpustringsS390XTest, S390XFeaturesEnum) {
+ const char *last_name = GetS390XFeaturesEnumName(S390X_LAST_);
+ EXPECT_STREQ(last_name, "unknown_feature");
+ for (int i = static_cast<int>(S390_ZARCH); i != static_cast<int>(S390X_LAST_); ++i) {
+ const auto feature = static_cast<S390XFeaturesEnum>(i);
+ const char *name = GetS390XFeaturesEnumName(feature);
+ ASSERT_FALSE(name == nullptr);
+ EXPECT_STRNE(name, "");
+ EXPECT_STRNE(name, last_name);
+ }
+}
+
+TEST(CpustringsS390XTest, FromHardwareCap) {
+ ResetHwcaps();
+ SetHardwareCapabilities(HWCAP_S390_ESAN3 | HWCAP_S390_HPAGE |
+ HWCAP_S390_NNPA | HWCAP_S390_SIE, 0);
+ GetEmptyFilesystem(); // disabling /proc/cpuinfo
+ const auto info = GetS390XInfo();
+ EXPECT_TRUE(info.features.esan3);
+ EXPECT_TRUE(info.features.edat);
+ EXPECT_TRUE(info.features.nnpa);
+ EXPECT_TRUE(info.features.sie);
+ EXPECT_FALSE(info.features.msa);
+ EXPECT_FALSE(info.features.stfle);
+ EXPECT_FALSE(info.features.vxp2);
+ EXPECT_FALSE(info.features.pcimio);
+}
+
+TEST(CpustringsS390XTest, z16) {
+ ResetHwcaps();
+ auto& fs = GetEmptyFilesystem();
+ fs.CreateFile("/proc/cpuinfo",
+ R"(vendor_id : IBM/S390
+# processors : 24
+bogomips per cpu: 26315.00
+max thread id : 1
+features : esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs te vx vxd vxe gs vxe2 vxp sort dflt vxp2 nnpa pcimio sie )");
+ SetPlatformPointer("z16");
+ const auto strings = GetS390XPlatformStrings();
+ EXPECT_EQ(strings.num_processors, 24);
+ ASSERT_STREQ(strings.type.platform, "z16");
+}
+
+TEST(CpustringsS390XTest, z15) {
+ ResetHwcaps();
+ auto& fs = GetEmptyFilesystem();
+ fs.CreateFile("/proc/cpuinfo",
+ R"(vendor_id : IBM/S390
+# processors : 2
+bogomips per cpu: 24038.00
+max thread id : 1
+features : esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs te vx vxd vxe gs vxe2 vxp sort dflt sie)");
+ SetPlatformPointer("z15");
+ const auto strings = GetS390XPlatformStrings();
+ EXPECT_EQ(strings.num_processors, 2);
+ ASSERT_STREQ(strings.type.platform, "z15");
+}
+
+} // namespace
+} // namespace cpu_features