From 3adafbfe666e7d8cf80fe8bb54201102ae5adfe0 Mon Sep 17 00:00:00 2001 From: Rashmica Gupta Date: Mon, 23 Apr 2018 10:46:47 +1000 Subject: [PATCH] powerpc: Added PowerPC implementation Signed-off-by: Rashmica Gupta --- CMakeLists.txt | 2 + include/.cpuinfo_ppc.h.swp | Bin 0 -> 16384 bytes include/cpu_features_macros.h | 4 + include/cpuinfo_ppc.h | 139 +++++++++++++ include/internal/hwcaps.h | 51 +++++ src/cpuinfo_ppc.c | 357 ++++++++++++++++++++++++++++++++++ src/utils/list_cpu_features.c | 13 ++ test/CMakeLists.txt | 5 + test/cpuinfo_ppc_test.cc | 116 +++++++++++ 9 files changed, 687 insertions(+) create mode 100644 include/.cpuinfo_ppc.h.swp create mode 100644 include/cpuinfo_ppc.h create mode 100644 src/cpuinfo_ppc.c create mode 100644 test/cpuinfo_ppc_test.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index f003768..640cf92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,7 @@ set(_HDRS include/cpuinfo_aarch64.h include/cpuinfo_arm.h include/cpuinfo_mips.h + include/cpuinfo_ppc.h include/cpuinfo_x86.h ) @@ -43,6 +44,7 @@ add_library(cpu_features src/cpuinfo_aarch64.c src/cpuinfo_arm.c src/cpuinfo_mips.c + src/cpuinfo_ppc.c src/cpuinfo_x86.c src/filesystem.c src/hwcaps.c diff --git a/include/.cpuinfo_ppc.h.swp b/include/.cpuinfo_ppc.h.swp new file mode 100644 index 0000000000000000000000000000000000000000..fbf58a9031fd0128f9328edd4b5deb5f5fc837bc GIT binary patch literal 16384 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 E0R?l0egFUf literal 0 HcmV?d00001 diff --git a/include/cpu_features_macros.h b/include/cpu_features_macros.h index d0e9a28..f8220e1 100644 --- a/include/cpu_features_macros.h +++ b/include/cpu_features_macros.h @@ -41,6 +41,10 @@ #define CPU_FEATURES_ARCH_MIPS #endif +#if defined(__powerpc__) +#define CPU_FEATURES_ARCH_PPC +#endif + //////////////////////////////////////////////////////////////////////////////// // Os //////////////////////////////////////////////////////////////////////////////// diff --git a/include/cpuinfo_ppc.h b/include/cpuinfo_ppc.h new file mode 100644 index 0000000..82de865 --- /dev/null +++ b/include/cpuinfo_ppc.h @@ -0,0 +1,139 @@ +// Copyright 2018 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_PPC_H_ +#define CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_ + +#include "cpu_features_macros.h" + +CPU_FEATURES_START_CPP_NAMESPACE + +typedef struct { + int ppc32 : 1; + int ppc64 : 1; + int ppc601 : 1; + int altivec : 1; + int fpu : 1; + int mmu : 1; + int mac_4xx : 1; + int unifiedcache : 1; + int spe : 1; + int efpsingle : 1; + int efpdouble : 1; + int no_tb : 1; + int power4 : 1; + int power5 : 1; + int power5plus : 1; + int cell : 1; + int booke : 1; + int smt : 1; + int icachesnoop : 1; + int arch205 : 1; + int pa6t : 1; + int dfp : 1; + int power6ext : 1; + int arch206 : 1; + int vsx : 1; + int pseries_perfmon_compat : 1; + int truele : 1; + int ppcle : 1; + int arch207 : 1; + int htm : 1; + int dscr : 1; + int ebb : 1; + int isel : 1; + int tar : 1; + int vcrypto : 1; + int htm_nosc : 1; + int arch300 : 1; + int ieee128 : 1; + int darn : 1; + int scv : 1; + int htm_no_suspend : 1; + + // Make sure to update PPCFeaturesEnum below if you add a field here. +} PPCFeatures; + +typedef struct { + PPCFeatures features; +} PPCInfo; + +// This function is guaranteed to be malloc, memset and memcpy free. +PPCInfo GetPPCInfo(void); + +typedef struct { + char platform[64]; // 0 terminated string + char model[64]; // 0 terminated string + char machine[64]; // 0 terminated string + char cpu[64]; // 0 terminated string +} PPCPlatformStrings; + +PPCPlatformStrings GetPPCPlatformStrings(void); + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +typedef enum { + PPC_32, /* 32 bit mode execution */ + PPC_64, /* 64 bit mode execution */ + PPC_601_INSTR, /* Old POWER ISA */ + PPC_HAS_ALTIVEC, /* SIMD Unit*/ + PPC_HAS_FPU, /* Floating Point Unit */ + PPC_HAS_MMU, /* Memory management unit */ + PPC_HAS_4xxMAC, + PPC_UNIFIED_CACHE, /* Unified instruction and data cache */ + PPC_HAS_SPE, /* Signal processing extention unit */ + PPC_HAS_EFP_SINGLE, /* SPE single precision fpu */ + PPC_HAS_EFP_DOUBLE, /* SPE double precision fpu */ + PPC_NO_TB, /* No timebase */ + PPC_POWER4, + PPC_POWER5, + PPC_POWER5_PLUS, + PPC_CELL, /* Cell broadband engine */ + PPC_BOOKE, /* Embedded ISA */ + PPC_SMT, /* Simultaneous multi-threading */ + PPC_ICACHE_SNOOP, + PPC_ARCH_2_05, /* ISA 2.05 - POWER6 */ + PPC_PA6T, /* PA Semi 6T core ISA */ + PPC_HAS_DFP, /* Decimal floating point unit */ + PPC_POWER6_EXT, + PPC_ARCH_2_06, /* ISA 2.06 - POWER7 */ + PPC_HAS_VSX, /* Vector-scalar extension */ + PPC_PSERIES_PERFMON_COMPAT, /* Set of backwards compatibile performance + monitoring events */ + PPC_TRUE_LE, + PPC_PPC_LE, + PPC_ARCH_2_07, /* ISA 2.07 - POWER8 */ + PPC_HTM, /* Hardware Transactional Memory */ + PPC_DSCR, /* Data stream control register */ + PPC_EBB, /* Event base branching */ + PPC_ISEL, /* Integer select instructions */ + PPC_TAR, /* Target address register */ + PPC_VEC_CRYPTO, /* Vector cryptography instructions */ + PPC_HTM_NOSC, /* Transactions aborted when syscall made*/ + PPC_ARCH_3_00, /* ISA 3.00 - POWER9 */ + PPC_HAS_IEEE128, /* VSX IEEE Binary Float 128-bit */ + PPC_DARN, /* Deliver a random number instruction */ + PPC_SCV, /* scv syscall */ + PPC_HTM_NO_SUSPEND, /* TM w/out suspended state */ + PPC_LAST_, +} PPCFeaturesEnum; + +int GetPPCFeaturesEnumValue(const PPCFeatures* features, PPCFeaturesEnum value); + +const char* GetPPCFeaturesEnumName(PPCFeaturesEnum); + +CPU_FEATURES_END_CPP_NAMESPACE + +#endif // CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_ diff --git a/include/internal/hwcaps.h b/include/internal/hwcaps.h index abbc718..f5f39d6 100644 --- a/include/internal/hwcaps.h +++ b/include/internal/hwcaps.h @@ -61,6 +61,57 @@ CPU_FEATURES_START_CPP_NAMESPACE #define MIPS_HWCAP_DSPR2 (1UL << 8) #define MIPS_HWCAP_MSA (1UL << 9) +// http://elixir.free-electrons.com/linux/latest/source/arch/powerpc/include/uapi/asm/cputable.h +#ifndef _UAPI__ASM_POWERPC_CPUTABLE_H +/* in AT_HWCAP */ +#define PPC_FEATURE_32 0x80000000 +#define PPC_FEATURE_64 0x40000000 +#define PPC_FEATURE_601_INSTR 0x20000000 +#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 +#define PPC_FEATURE_HAS_FPU 0x08000000 +#define PPC_FEATURE_HAS_MMU 0x04000000 +#define PPC_FEATURE_HAS_4xxMAC 0x02000000 +#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 +#define PPC_FEATURE_HAS_SPE 0x00800000 +#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000 +#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000 +#define PPC_FEATURE_NO_TB 0x00100000 +#define PPC_FEATURE_POWER4 0x00080000 +#define PPC_FEATURE_POWER5 0x00040000 +#define PPC_FEATURE_POWER5_PLUS 0x00020000 +#define PPC_FEATURE_CELL 0x00010000 +#define PPC_FEATURE_BOOKE 0x00008000 +#define PPC_FEATURE_SMT 0x00004000 +#define PPC_FEATURE_ICACHE_SNOOP 0x00002000 +#define PPC_FEATURE_ARCH_2_05 0x00001000 +#define PPC_FEATURE_PA6T 0x00000800 +#define PPC_FEATURE_HAS_DFP 0x00000400 +#define PPC_FEATURE_POWER6_EXT 0x00000200 +#define PPC_FEATURE_ARCH_2_06 0x00000100 +#define PPC_FEATURE_HAS_VSX 0x00000080 + +#define PPC_FEATURE_PSERIES_PERFMON_COMPAT 0x00000040 + +/* Reserved - do not use 0x00000004 */ +#define PPC_FEATURE_TRUE_LE 0x00000002 +#define PPC_FEATURE_PPC_LE 0x00000001 + +/* in AT_HWCAP2 */ +#define PPC_FEATURE2_ARCH_2_07 0x80000000 +#define PPC_FEATURE2_HTM 0x40000000 +#define PPC_FEATURE2_DSCR 0x20000000 +#define PPC_FEATURE2_EBB 0x10000000 +#define PPC_FEATURE2_ISEL 0x08000000 +#define PPC_FEATURE2_TAR 0x04000000 +#define PPC_FEATURE2_VEC_CRYPTO 0x02000000 +#define PPC_FEATURE2_HTM_NOSC 0x01000000 +#define PPC_FEATURE2_ARCH_3_00 0x00800000 +#define PPC_FEATURE2_HAS_IEEE128 0x00400000 +#define PPC_FEATURE2_DARN 0x00200000 +#define PPC_FEATURE2_SCV 0x00100000 +#define PPC_FEATURE2_HTM_NO_SUSPEND 0x00080000 +#endif + typedef struct { uint32_t hwcaps; uint32_t hwcaps2; diff --git a/src/cpuinfo_ppc.c b/src/cpuinfo_ppc.c new file mode 100644 index 0000000..9c2fd99 --- /dev/null +++ b/src/cpuinfo_ppc.c @@ -0,0 +1,357 @@ +// Copyright 2018 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 +#include + +#include "cpuinfo_ppc.h" +#include "internal/bit_utils.h" +#include "internal/filesystem.h" +#include "internal/linux_features_aggregator.h" +#include "internal/stack_line_reader.h" +#include "internal/string_view.h" + +DECLARE_SETTER(PPCFeatures, ppc32) +DECLARE_SETTER(PPCFeatures, ppc64) +DECLARE_SETTER(PPCFeatures, ppc601) +DECLARE_SETTER(PPCFeatures, altivec) +DECLARE_SETTER(PPCFeatures, fpu) +DECLARE_SETTER(PPCFeatures, mmu) +DECLARE_SETTER(PPCFeatures, mac_4xx) +DECLARE_SETTER(PPCFeatures, unifiedcache) +DECLARE_SETTER(PPCFeatures, spe) +DECLARE_SETTER(PPCFeatures, efpsingle) +DECLARE_SETTER(PPCFeatures, efpdouble) +DECLARE_SETTER(PPCFeatures, no_tb) +DECLARE_SETTER(PPCFeatures, power4) +DECLARE_SETTER(PPCFeatures, power5) +DECLARE_SETTER(PPCFeatures, power5plus) +DECLARE_SETTER(PPCFeatures, cell) +DECLARE_SETTER(PPCFeatures, booke) +DECLARE_SETTER(PPCFeatures, smt) +DECLARE_SETTER(PPCFeatures, icachesnoop) +DECLARE_SETTER(PPCFeatures, arch205) +DECLARE_SETTER(PPCFeatures, pa6t) +DECLARE_SETTER(PPCFeatures, dfp) +DECLARE_SETTER(PPCFeatures, power6ext) +DECLARE_SETTER(PPCFeatures, arch206) +DECLARE_SETTER(PPCFeatures, vsx) +DECLARE_SETTER(PPCFeatures, pseries_perfmon_compat) +DECLARE_SETTER(PPCFeatures, truele) +DECLARE_SETTER(PPCFeatures, ppcle) +DECLARE_SETTER(PPCFeatures, arch207) +DECLARE_SETTER(PPCFeatures, htm) +DECLARE_SETTER(PPCFeatures, dscr) +DECLARE_SETTER(PPCFeatures, ebb) +DECLARE_SETTER(PPCFeatures, isel) +DECLARE_SETTER(PPCFeatures, tar) +DECLARE_SETTER(PPCFeatures, vcrypto) +DECLARE_SETTER(PPCFeatures, htm_nosc) +DECLARE_SETTER(PPCFeatures, arch300) +DECLARE_SETTER(PPCFeatures, ieee128) +DECLARE_SETTER(PPCFeatures, darn) +DECLARE_SETTER(PPCFeatures, scv) +DECLARE_SETTER(PPCFeatures, htm_no_suspend) + +static const CapabilityConfig kConfigs[] = { + {{PPC_FEATURE_32, 0}, "ppc32", &set_ppc32}, + {{PPC_FEATURE_64, 0}, "ppc64", &set_ppc64}, + {{PPC_FEATURE_601_INSTR, 0}, "ppc601", &set_ppc601}, + {{PPC_FEATURE_HAS_ALTIVEC, 0}, "altivec", &set_altivec}, + {{PPC_FEATURE_HAS_FPU, 0}, "fpu", &set_fpu}, + {{PPC_FEATURE_HAS_MMU, 0}, "mmu", &set_mmu}, + {{PPC_FEATURE_HAS_4xxMAC, 0}, "4xxmac", &set_mac_4xx}, + {{PPC_FEATURE_UNIFIED_CACHE, 0}, "ucache", &set_unifiedcache}, + {{PPC_FEATURE_HAS_SPE, 0}, "spe", &set_spe}, + {{PPC_FEATURE_HAS_EFP_SINGLE, 0}, "efpsingle", &set_efpsingle}, + {{PPC_FEATURE_HAS_EFP_DOUBLE, 0}, "efpdouble", &set_efpdouble}, + {{PPC_FEATURE_NO_TB, 0}, "notb", &set_no_tb}, + {{PPC_FEATURE_POWER4, 0}, "power4", &set_power4}, + {{PPC_FEATURE_POWER5, 0}, "power5", &set_power5}, + {{PPC_FEATURE_POWER5_PLUS, 0}, "power5+", &set_power5plus}, + {{PPC_FEATURE_CELL, 0}, "cellbe", &set_cell}, + {{PPC_FEATURE_BOOKE, 0}, "booke", &set_booke}, + {{PPC_FEATURE_SMT, 0}, "smt", &set_smt}, + {{PPC_FEATURE_ICACHE_SNOOP, 0}, "ic_snoop", &set_icachesnoop}, + {{PPC_FEATURE_ARCH_2_05, 0}, "arch_2_05", &set_arch205}, + {{PPC_FEATURE_PA6T, 0}, "pa6t", &set_pa6t}, + {{PPC_FEATURE_HAS_DFP, 0}, "dfp", &set_dfp}, + {{PPC_FEATURE_POWER6_EXT, 0}, "power6x", &set_power6ext}, + {{PPC_FEATURE_ARCH_2_06, 0}, "arch_2_06", &set_arch206}, + {{PPC_FEATURE_HAS_VSX, 0}, "vsx", &set_vsx}, + {{PPC_FEATURE_PSERIES_PERFMON_COMPAT, 0}, + "archpmu", + &set_pseries_perfmon_compat}, + {{PPC_FEATURE_TRUE_LE, 0}, "true_le", &set_truele}, + {{PPC_FEATURE_PPC_LE, 0}, "ppcle", &set_ppcle}, + {{0, PPC_FEATURE2_ARCH_2_07}, "arch_2_07", &set_arch207}, + {{0, PPC_FEATURE2_HTM}, "htm", &set_htm}, + {{0, PPC_FEATURE2_DSCR}, "dscr", &set_dscr}, + {{0, PPC_FEATURE2_EBB}, "ebb", &set_ebb}, + {{0, PPC_FEATURE2_ISEL}, "isel", &set_isel}, + {{0, PPC_FEATURE2_TAR}, "tar", &set_tar}, + {{0, PPC_FEATURE2_VEC_CRYPTO}, "vcrypto", &set_vcrypto}, + {{0, PPC_FEATURE2_HTM_NOSC}, "htm-nosc", &set_htm_nosc}, + {{0, PPC_FEATURE2_ARCH_3_00}, "arch_3_00", &set_arch300}, + {{0, PPC_FEATURE2_HAS_IEEE128}, "ieee128", &set_ieee128}, + {{0, PPC_FEATURE2_DARN}, "darn", &set_darn}, + {{0, PPC_FEATURE2_SCV}, "scv", &set_scv}, + {{0, PPC_FEATURE2_HTM_NO_SUSPEND}, "htm-no-suspend", &set_htm_no_suspend}, +}; +static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig); + +static bool HandlePPCLine(const LineResult result, + PPCPlatformStrings* const strings) { + StringView line = result.line; + StringView key, value; + if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) { + if (CpuFeatures_StringView_HasWord(key, "platform")) { + CpuFeatures_StringView_CopyString(value, strings->platform, + sizeof(strings->platform)); + } else if (CpuFeatures_StringView_IsEquals(key, str("model"))) { + CpuFeatures_StringView_CopyString(value, strings->model, + sizeof(strings->platform)); + } else if (CpuFeatures_StringView_IsEquals(key, str("machine"))) { + CpuFeatures_StringView_CopyString(value, strings->machine, + sizeof(strings->platform)); + } else if (CpuFeatures_StringView_IsEquals(key, str("cpu"))) { + CpuFeatures_StringView_CopyString(value, strings->cpu, + sizeof(strings->platform)); + } + } + return !result.eof; +} + +static void FillProcCpuInfoData(PPCPlatformStrings* const strings) { + const int fd = CpuFeatures_OpenFile("/proc/cpuinfo"); + if (fd >= 0) { + StackLineReader reader; + StackLineReader_Initialize(&reader, fd); + for (;;) { + if (!HandlePPCLine(StackLineReader_NextLine(&reader), strings)) { + break; + } + } + CpuFeatures_CloseFile(fd); + } +} + +static const PPCInfo kEmptyPPCInfo; + +PPCInfo GetPPCInfo(void) { + /* + * On Power feature flags aren't currently in cpuinfo so we only look at + * the auxilary vector. + */ + PPCInfo info = kEmptyPPCInfo; + + CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs, + CpuFeatures_GetHardwareCapabilities(), + &info.features); + return info; +} + +static const PPCPlatformStrings kEmptyPPCPlatformStrings; + +PPCPlatformStrings GetPPCPlatformStrings(void) { + PPCPlatformStrings strings = kEmptyPPCPlatformStrings; + + FillProcCpuInfoData(&strings); + return strings; +} + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +int GetPPCFeaturesEnumValue(const PPCFeatures* features, + PPCFeaturesEnum value) { + switch (value) { + case PPC_32: + return features->ppc32; + case PPC_64: + return features->ppc64; + case PPC_601_INSTR: + return features->ppc601; + case PPC_HAS_ALTIVEC: + return features->altivec; + case PPC_HAS_FPU: + return features->fpu; + case PPC_HAS_MMU: + return features->mmu; + case PPC_HAS_4xxMAC: + return features->mac_4xx; + case PPC_UNIFIED_CACHE: + return features->unifiedcache; + case PPC_HAS_SPE: + return features->spe; + case PPC_HAS_EFP_SINGLE: + return features->efpsingle; + case PPC_HAS_EFP_DOUBLE: + return features->efpdouble; + case PPC_NO_TB: + return features->no_tb; + case PPC_POWER4: + return features->power4; + case PPC_POWER5: + return features->power5; + case PPC_POWER5_PLUS: + return features->power5plus; + case PPC_CELL: + return features->cell; + case PPC_BOOKE: + return features->booke; + case PPC_SMT: + return features->smt; + case PPC_ICACHE_SNOOP: + return features->icachesnoop; + case PPC_ARCH_2_05: + return features->arch205; + case PPC_PA6T: + return features->pa6t; + case PPC_HAS_DFP: + return features->dfp; + case PPC_POWER6_EXT: + return features->power6ext; + case PPC_ARCH_2_06: + return features->arch206; + case PPC_HAS_VSX: + return features->vsx; + case PPC_PSERIES_PERFMON_COMPAT: + return features->pseries_perfmon_compat; + case PPC_TRUE_LE: + return features->truele; + case PPC_PPC_LE: + return features->ppcle; + case PPC_ARCH_2_07: + return features->arch207; + case PPC_HTM: + return features->htm; + case PPC_DSCR: + return features->dscr; + case PPC_EBB: + return features->ebb; + case PPC_ISEL: + return features->isel; + case PPC_TAR: + return features->tar; + case PPC_VEC_CRYPTO: + return features->vcrypto; + case PPC_HTM_NOSC: + return features->htm_nosc; + case PPC_ARCH_3_00: + return features->arch300; + case PPC_HAS_IEEE128: + return features->ieee128; + case PPC_DARN: + return features->darn; + case PPC_SCV: + return features->scv; + case PPC_HTM_NO_SUSPEND: + return features->htm_no_suspend; + case PPC_LAST_: + break; + } + return false; +} + +/* Have used the same names as glibc */ +const char* GetPPCFeaturesEnumName(PPCFeaturesEnum value) { + switch (value) { + case PPC_32: + return "ppc32"; + case PPC_64: + return "ppc64"; + case PPC_601_INSTR: + return "ppc601"; + case PPC_HAS_ALTIVEC: + return "altivec"; + case PPC_HAS_FPU: + return "fpu"; + case PPC_HAS_MMU: + return "mmu"; + case PPC_HAS_4xxMAC: + return "4xxmac"; + case PPC_UNIFIED_CACHE: + return "ucache"; + case PPC_HAS_SPE: + return "spe"; + case PPC_HAS_EFP_SINGLE: + return "efpsingle"; + case PPC_HAS_EFP_DOUBLE: + return "efpdouble"; + case PPC_NO_TB: + return "notb"; + case PPC_POWER4: + return "power4"; + case PPC_POWER5: + return "power5"; + case PPC_POWER5_PLUS: + return "power5+"; + case PPC_CELL: + return "cellbe"; + case PPC_BOOKE: + return "booke"; + case PPC_SMT: + return "smt"; + case PPC_ICACHE_SNOOP: + return "ic_snoop"; + case PPC_ARCH_2_05: + return "arch_2_05"; + case PPC_PA6T: + return "pa6t"; + case PPC_HAS_DFP: + return "dfp"; + case PPC_POWER6_EXT: + return "power6x"; + case PPC_ARCH_2_06: + return "arch_2_06"; + case PPC_HAS_VSX: + return "vsx"; + case PPC_PSERIES_PERFMON_COMPAT: + return "archpmu"; + case PPC_TRUE_LE: + return "true_le"; + case PPC_PPC_LE: + return "ppcle"; + case PPC_ARCH_2_07: + return "arch_2_07"; + case PPC_HTM: + return "htm"; + case PPC_DSCR: + return "dscr"; + case PPC_EBB: + return "ebb"; + case PPC_ISEL: + return "isel"; + case PPC_TAR: + return "tar"; + case PPC_VEC_CRYPTO: + return "vcrypto"; + case PPC_HTM_NOSC: + return "htm-nosc"; + case PPC_ARCH_3_00: + return "arch_3_00"; + case PPC_HAS_IEEE128: + return "ieee128"; + case PPC_DARN: + return "darn"; + case PPC_SCV: + return "scv"; + case PPC_HTM_NO_SUSPEND: + return "htm-no-suspend"; + case PPC_LAST_: + break; + } + return "unknown_feature"; +} diff --git a/src/utils/list_cpu_features.c b/src/utils/list_cpu_features.c index 1bbe394..80ad0b9 100644 --- a/src/utils/list_cpu_features.c +++ b/src/utils/list_cpu_features.c @@ -20,6 +20,7 @@ #include "cpuinfo_aarch64.h" #include "cpuinfo_arm.h" #include "cpuinfo_mips.h" +#include "cpuinfo_ppc.h" #include "cpuinfo_x86.h" static void PrintEscapedAscii(const char* str) { @@ -150,6 +151,9 @@ DEFINE_PRINT_FLAGS(GetAarch64FeaturesEnumValue, GetAarch64FeaturesEnumName, #elif defined(CPU_FEATURES_ARCH_MIPS) DEFINE_PRINT_FLAGS(GetMipsFeaturesEnumValue, GetMipsFeaturesEnumName, MipsFeatures, MIPS_LAST_) +#elif defined(CPU_FEATURES_ARCH_PPC) +DEFINE_PRINT_FLAGS(GetPPCFeaturesEnumValue, GetPPCFeaturesEnumName, PPCFeatures, + PPC_LAST_) #endif static void PrintFeatures(const Printer printer) { @@ -186,6 +190,15 @@ static void PrintFeatures(const Printer printer) { const MipsInfo info = GetMipsInfo(); PrintS(printer, "arch", "mips"); PrintFlags(printer, &info.features); +#elif defined(CPU_FEATURES_ARCH_PPC) + const PPCInfo info = GetPPCInfo(); + const PPCPlatformStrings strings = GetPPCPlatformStrings(); + PrintS(printer, "arch", "ppc"); + PrintS(printer, "platform", strings.platform); + PrintS(printer, "model", strings.model); + PrintS(printer, "machine", strings.machine); + PrintS(printer, "cpu", strings.cpu); + PrintFlags(printer, &info.features); #endif } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9bfdcd6..794ef04 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -72,3 +72,8 @@ add_test(NAME cpuinfo_aarch64_test COMMAND cpuinfo_aarch64_test) add_executable(cpuinfo_mips_test cpuinfo_mips_test.cc ../src/cpuinfo_mips.c) target_link_libraries(cpuinfo_mips_test all_libraries) add_test(NAME cpuinfo_mips_test COMMAND cpuinfo_mips_test) +##------------------------------------------------------------------------------ +## cpuinfo_ppc_test +add_executable(cpuinfo_ppc_test cpuinfo_ppc_test.cc ../src/cpuinfo_ppc.c) +target_link_libraries(cpuinfo_ppc_test all_libraries) +add_test(NAME cpuinfo_ppc_test COMMAND cpuinfo_ppc_test) diff --git a/test/cpuinfo_ppc_test.cc b/test/cpuinfo_ppc_test.cc new file mode 100644 index 0000000..f6485c4 --- /dev/null +++ b/test/cpuinfo_ppc_test.cc @@ -0,0 +1,116 @@ +// Copyright 2018 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_ppc.h" +#include "filesystem_for_testing.h" +#include "hwcaps_for_testing.h" +#include "internal/string_view.h" + +#include "gtest/gtest.h" + +namespace cpu_features { +namespace { + +void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); } + +TEST(CpustringsPPCTest, FromHardwareCap) { + SetHardwareCapabilities(PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_VSX, + PPC_FEATURE2_ARCH_3_00); + GetEmptyFilesystem(); // disabling /proc/cpuinfo + const auto info = GetPPCInfo(); + EXPECT_TRUE(info.features.fpu); + EXPECT_FALSE(info.features.mmu); + EXPECT_TRUE(info.features.vsx); + EXPECT_TRUE(info.features.arch300); + EXPECT_FALSE(info.features.power4); + EXPECT_FALSE(info.features.altivec); + EXPECT_FALSE(info.features.vcrypto); + EXPECT_FALSE(info.features.htm); +} + +TEST(CpustringsPPCTest, Blade) { + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(processor : 14 +cpu : POWER7 (architected), altivec supported +clock : 3000.000000MHz +revision : 2.1 (pvr 003f 0201) + +processor : 15 +cpu : POWER7 (architected), altivec supported +clock : 3000.000000MHz +revision : 2.1 (pvr 003f 0201) + +timebase : 512000000 +platform : pSeries +model : IBM,8406-70Y +machine : CHRP IBM,8406-70Y)"); + const auto strings = GetPPCPlatformStrings(); + ASSERT_STREQ(strings.platform, "pSeries"); + ASSERT_STREQ(strings.model, "IBM,8406-70Y"); + ASSERT_STREQ(strings.machine, "CHRP IBM,8406-70Y"); + ASSERT_STREQ(strings.cpu, "POWER7 (architected), altivec supported"); +} + +TEST(CpustringsPPCTest, Firestone) { + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(processor : 126 +cpu : POWER8 (raw), altivec supported +clock : 2061.000000MHz +revision : 2.0 (pvr 004d 0200) + +processor : 127 +cpu : POWER8 (raw), altivec supported +clock : 2061.000000MHz +revision : 2.0 (pvr 004d 0200) + +timebase : 512000000 +platform : PowerNV +model : 8335-GTA +machine : PowerNV 8335-GTA +firmware : OPAL v3)"); + const auto strings = GetPPCPlatformStrings(); + ASSERT_STREQ(strings.platform, "PowerNV"); + ASSERT_STREQ(strings.model, "8335-GTA"); + ASSERT_STREQ(strings.machine, "PowerNV 8335-GTA"); + ASSERT_STREQ(strings.cpu, "POWER8 (raw), altivec supported"); +} + +TEST(CpustringsPPCTest, w8) { + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(processor : 143 +cpu : POWER9, altivec supported +clock : 2300.000000MHz +revision : 2.2 (pvr 004e 1202) + +timebase : 512000000 +platform : PowerNV +model : 0000000000000000 +machine : PowerNV 0000000000000000 +firmware : OPAL +MMU : Radix)"); + const auto strings = GetPPCPlatformStrings(); + ASSERT_STREQ(strings.platform, "PowerNV"); + ASSERT_STREQ(strings.model, "0000000000000000"); + ASSERT_STREQ(strings.machine, "PowerNV 0000000000000000"); + ASSERT_STREQ(strings.cpu, "POWER9, altivec supported"); +} + +} // namespace +} // namespace cpu_features