1
0
mirror of https://github.com/google/cpu_features.git synced 2025-04-27 23:22:31 +02:00

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>
This commit is contained in:
marquitos0119 2022-11-02 03:38:13 -05:00 committed by GitHub
parent bddcc3721c
commit 981fbe3914
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 457 additions and 1 deletions

27
.github/workflows/s390x_linux_cmake.yml vendored Normal file
View File

@ -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

View File

@ -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()

View File

@ -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)

View File

@ -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

108
include/cpuinfo_s390x.h Normal file
View File

@ -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_

View File

@ -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'))

View File

@ -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 ;;

120
src/impl_s390x_linux.c Normal file
View File

@ -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

View File

@ -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;
}

View File

@ -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()

View File

@ -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