From 981fbe391454da866f1df57be72c4441b6396117 Mon Sep 17 00:00:00 2001 From: marquitos0119 <111894523+marquitos0119@users.noreply.github.com> Date: Wed, 2 Nov 2022 03:38:13 -0500 Subject: [PATCH] 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 Co-authored-by: Corentin Le Molgat --- .github/workflows/s390x_linux_cmake.yml | 27 ++++++ CMakeLists.txt | 5 + cmake/ci/Makefile | 4 +- include/cpu_features_macros.h | 4 + include/cpuinfo_s390x.h | 108 +++++++++++++++++++++ include/internal/hwcaps.h | 28 ++++++ scripts/run_integration.sh | 60 ++++++++++++ src/impl_s390x_linux.c | 120 ++++++++++++++++++++++++ src/utils/list_cpu_features.c | 13 +++ test/CMakeLists.txt | 7 ++ test/cpuinfo_s390x_test.cc | 82 ++++++++++++++++ 11 files changed, 457 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/s390x_linux_cmake.yml create mode 100644 include/cpuinfo_s390x.h create mode 100644 src/impl_s390x_linux.c create mode 100644 test/cpuinfo_s390x_test.cc 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}${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}" <&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 + +#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(S390_ZARCH); i != static_cast(S390X_LAST_); ++i) { + const auto feature = static_cast(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