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 0000000..fbf58a9 Binary files /dev/null and b/include/.cpuinfo_ppc.h.swp differ 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