diff options
| author | Burt P <pburt0@gmail.com> | 2017-05-30 11:39:33 -0500 | 
|---|---|---|
| committer | Leandro A. F. Pereira <leandro@hardinfo.org> | 2017-06-02 12:50:14 -0700 | 
| commit | e00d167ea7968928f1130d52f1df62b4434e39cb (patch) | |
| tree | 2f802f4f1b36afb720bedb6f138668377b85f3d1 /modules | |
| parent | fc28c87f59861dafa5b1dea68f55cd93a13a278f (diff) | |
Decode ARM processor implementer and part numbers
Signed-off-by: Burt P <pburt0@gmail.com>
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/devices/arm/arm_data.c | 215 | ||||
| -rw-r--r-- | modules/devices/arm/arm_data.h | 38 | ||||
| -rw-r--r-- | modules/devices/arm/processor.c | 88 | 
3 files changed, 279 insertions, 62 deletions
| diff --git a/modules/devices/arm/arm_data.c b/modules/devices/arm/arm_data.c new file mode 100644 index 00000000..246cb643 --- /dev/null +++ b/modules/devices/arm/arm_data.c @@ -0,0 +1,215 @@ +/* + * rpiz - https://github.com/bp0/rpiz + * Copyright (C) 2017  Burt P. <pburt0@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "arm_data.h" + +/* sources: + *   https://unix.stackexchange.com/a/43563 + *   git:linux/arch/arm/kernel/setup.c + *   git:linux/arch/arm64/kernel/cpuinfo.c + */ +static struct { +    char *name, *meaning; +} tab_flag_meaning[] = { +    /* arm/hw_cap */ +    { "swp",	"SWP instruction (atomic read-modify-write)" }, +    { "half",	"Half-word loads and stores" }, +    { "thumb",	"Thumb (16-bit instruction set)" }, +    { "26bit",	"26-Bit Model (Processor status register folded into program counter)" }, +    { "fastmult",	"32x32->64-bit multiplication" }, +    { "fpa",	"Floating point accelerator" }, +    { "vfp",	"VFP (early SIMD vector floating point instructions)" }, +    { "edsp",	"DSP extensions (the 'e' variant of the ARM9 CPUs, and all others above)" }, +    { "java",	"Jazelle (Java bytecode accelerator)" }, +    { "iwmmxt",	"SIMD instructions similar to Intel MMX" }, +    { "crunch",	"MaverickCrunch coprocessor (if kernel support enabled)" }, +    { "thumbee",	"ThumbEE" }, +    { "neon",	"Advanced SIMD/NEON on AArch32" }, +    { "evtstrm",	"kernel event stream using generic architected timer" }, +    { "vfpv3",	"VFP version 3" }, +    { "vfpv3d16",	"VFP version 3 with 16 D-registers" }, +    { "vfpv4",	"VFP version 4 with fast context switching" }, +    { "vfpd32",	"VFP with 32 D-registers" }, +    { "tls",	"TLS register" }, +    { "idiva",	"SDIV and UDIV hardware division in ARM mode" }, +    { "idivt",	"SDIV and UDIV hardware division in Thumb mode" }, +    { "lpae",	"40-bit Large Physical Address Extension" }, +    /* arm/hw_cap2 */ +    { "pmull",	"64x64->128-bit F2m multiplication (arch>8)" }, +    { "aes",	"Crypto:AES (arch>8)" }, +    { "sha1",	"Crypto:SHA1 (arch>8)" }, +    { "sha2",	"Crypto:SHA2 (arch>8)" }, +    { "crc32",	"CRC32 checksum instructions (arch>8)" }, +    /* arm64/hw_cap */ +    { "fp",	"" }, +    { "asimd",	"Advanced SIMD/NEON on AArch64 (arch>8)" }, +    { "atomics",	"" }, +    { "fphp",	"" }, +    { "asimdhp",	"" }, +    { "cpuid",	"" }, +    { "asimdrdm",	"" }, +    { "jscvt",	"" }, +    { "fcma",	"" }, +    { "lrcpc",	"" }, + +    { NULL, NULL}, +}; + +static struct { +    int code; char *name; +} tab_arm_implementer[] = { +    { 0x41,	"ARM" }, +    { 0x44,	"Intel (formerly DEC) StrongARM" }, +    { 0x4e,	"nVidia" }, +    { 0x54,	"Texas Instruments" }, +    { 0x56,	"Marvell" }, +    { 0x69,	"Intel XScale" }, +    { 0, NULL}, +}; + +static struct { +    /* source: t = tested, d = official docs, f = web */ +    int code; char *part_desc; +} tab_arm_arm_part[] = { /* only valid for implementer 0x41 ARM */ +    /*d */ { 0x920,	"ARM920" }, +    /*d */ { 0x926,	"ARM926" }, +    /*d */ { 0x946,	"ARM946" }, +    /*d */ { 0x966,	"ARM966" }, +    /*d */ { 0xb02,	"ARM11 MPCore" }, +    /*d */ { 0xb36,	"ARM1136" }, +    /*d */ { 0xb56,	"ARM1156" }, +    /*dt*/ { 0xb76,	"ARM1176" }, +    /*dt*/ { 0xc05,	"Cortex-A5" }, +    /*d */ { 0xc07,	"Cortex-A7 MPCore" }, +    /*dt*/ { 0xc08,	"Cortex-A8" }, +    /*dt*/ { 0xc09,	"Cortex-A9" }, +    /*d */ { 0xc0e,	"Cortex-A17 MPCore" }, +    /*d */ { 0xc0f,	"Cortex-A15" }, +    /*d */ { 0xd01,	"Cortex-A32" }, +    /*dt*/ { 0xd03,	"Cortex-A53" }, +    /*d */ { 0xd04,	"Cortex-A35" }, +    /*d */ { 0xd07,	"Cortex-A57 MPCore" }, +    /*d */ { 0xd08,	"Cortex-A72" }, +    /*d */ { 0xd09,	"Cortex-A73" }, +           { 0, NULL}, +}; + +static char all_flags[1024] = ""; + +#define APPEND_FLAG(f) strcat(all_flags, f); strcat(all_flags, " "); +const char *arm_flag_list() { +    int i = 0, built = 0; +    built = strlen(all_flags); +    if (!built) { +        while(tab_flag_meaning[i].name != NULL) { +            APPEND_FLAG(tab_flag_meaning[i].name); +            i++; +        } +    } +    return all_flags; +} + +const char *arm_flag_meaning(const char *flag) { +    int i = 0; +    if (flag) +    while(tab_flag_meaning[i].name != NULL) { +        if (strcmp(tab_flag_meaning[i].name, flag) == 0) +            return tab_flag_meaning[i].meaning; +        i++; +    } +    return NULL; +} + +static int code_match(int c0, const char* code1) { +    int c1; +    if (code1 == NULL) return 0; +    c1 = strtol(code1, NULL, 0); +    return (c0 == c1) ? 1 : 0; +} + +const char *arm_implementer(const char *code) { +    int i = 0; +    if (code) +    while(tab_arm_implementer[i].code) { +        if (code_match(tab_arm_implementer[i].code, code)) +            return tab_arm_implementer[i].name; +        i++; +    } +    return NULL; +} + +const char *arm_part(const char *imp_code, const char *part_code) { +    int i = 0; +    if (imp_code && part_code) { +        if (code_match(0x41, imp_code)) { +            /* 0x41=ARM parts */ +            while(tab_arm_arm_part[i].code) { +                if (code_match(tab_arm_arm_part[i].code, part_code)) +                    return tab_arm_arm_part[i].part_desc; +                i++; +            } +        } +    } +    return NULL; +} + +char *arm_decoded_name(const char *imp, const char *part, const char *var, const char *rev, const char *arch, const char *model_name) { +    char *dnbuff; +    char *imp_name = NULL, *part_desc = NULL; +    int r = 0, p = 0; +    dnbuff = malloc(256); +    if (dnbuff) { +        memset(dnbuff, 0, 256); + +        if (imp && arch && part && rev) { +            /* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0395b/CIHCAGHH.html +             * variant and revision can be rendered r{variant}p{revision} */ +            r = strtol(var, NULL, 0); +            p = strtol(rev, NULL, 0); +            imp_name = (char*) arm_implementer(imp); +            part_desc = (char*) arm_part(imp, part); +            if (imp_name || part_desc) { +                sprintf(dnbuff, "%s %s r%dp%d (arch:%s)", +                        (imp_name) ? imp_name : imp, +                        (part_desc) ? part_desc : part, +                        r, p, arch); +            } else { +                /* fallback for now */ +                sprintf(dnbuff, "%s [imp:%s part:%s r%dp%d arch:%s]", +                        model_name, +                        (imp_name) ? imp_name : imp, +                        (part_desc) ? part_desc : part, +                        r, p, arch); +            } +        } else { +            /* prolly not ARM arch at all */ +            if (model_name) +                sprintf(dnbuff, "%s", model_name); +            else { +                free(dnbuff); +                return NULL; +            } +        } +    } +    return dnbuff; +} diff --git a/modules/devices/arm/arm_data.h b/modules/devices/arm/arm_data.h new file mode 100644 index 00000000..4d1d4cf9 --- /dev/null +++ b/modules/devices/arm/arm_data.h @@ -0,0 +1,38 @@ +/* + * rpiz - https://github.com/bp0/rpiz + * Copyright (C) 2017  Burt P. <pburt0@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. + * + */ + +#ifndef _ARMDATA_H_ +#define _ARMDATA_H_ + +/* table lookups */ +const char *arm_implementer(const char *code); +const char *arm_part(const char *imp_code, const char *part_code); + +/* cpu_implementer, cpu_part, cpu_variant, cpu_revision, cpu_architecture from /proc/cpuinfo + * model_name is returned as a fallback if not enough data is known */ +char *arm_decoded_name( +    const char *imp, const char *part, const char *var, const char *rev, +    const char *arch, const char *model_name); + +/* cpu flags from /proc/cpuinfo */ +const char *arm_flag_list(void);                  /* list of all known flags */ +const char *arm_flag_meaning(const char *flag);  /* lookup flag meaning */ + +#endif diff --git a/modules/devices/arm/processor.c b/modules/devices/arm/processor.c index ad29f09e..a18f6374 100644 --- a/modules/devices/arm/processor.c +++ b/modules/devices/arm/processor.c @@ -19,6 +19,9 @@  #include "hardinfo.h"  #include "devices.h" +#include "arm_data.h" +#include "arm_data.c" +  enum {      ARM_A32 = 0,      ARM_A64 = 1, @@ -31,68 +34,21 @@ static const gchar *arm_mode_str[] = {      "A32 on A64",  }; -/* sources: - *   https://unix.stackexchange.com/a/43563 - *   git:linux/arch/arm/kernel/setup.c - *   git:linux/arch/arm64/kernel/cpuinfo.c - */ -static struct { -    char *name, *meaning; -} flag_meaning[] = { -    /* arm/hw_cap */ -    { "swp",	"SWP instruction (atomic read-modify-write)" }, -    { "half",	"Half-word loads and stores" }, -    { "thumb",	"Thumb (16-bit instruction set)" }, -    { "26bit",	"26-Bit Model (Processor status register folded into program counter)" }, -    { "fastmult",	"32x32->64-bit multiplication" }, -    { "fpa",	"Floating point accelerator" }, -    { "vfp",	"VFP (early SIMD vector floating point instructions)" }, -    { "edsp",	"DSP extensions (the 'e' variant of the ARM9 CPUs, and all others above)" }, -    { "java",	"Jazelle (Java bytecode accelerator)" }, -    { "iwmmxt",	"SIMD instructions similar to Intel MMX" }, -    { "crunch",	"MaverickCrunch coprocessor (if kernel support enabled)" }, -    { "thumbee",	"ThumbEE" }, -    { "neon",	"Advanced SIMD/NEON on AArch32" }, -    { "evtstrm",	"kernel event stream using generic architected timer" }, -    { "vfpv3",	"VFP version 3" }, -    { "vfpv3d16",	"VFP version 3 with 16 D-registers" }, -    { "vfpv4",	"VFP version 4 with fast context switching" }, -    { "vfpd32",	"VFP with 32 D-registers" }, -    { "tls",	"TLS register" }, -    { "idiva",	"SDIV and UDIV hardware division in ARM mode" }, -    { "idivt",	"SDIV and UDIV hardware division in Thumb mode" }, -    { "lpae",	"40-bit Large Physical Address Extension" }, -    /* arm/hw_cap2 */ -    { "pmull",	"64x64->128-bit F2m multiplication (arch>8)" }, -    { "aes",	"Crypto:AES (arch>8)" }, -    { "sha1",	"Crypto:SHA1 (arch>8)" }, -    { "sha2",	"Crypto:SHA2 (arch>8)" }, -    { "crc32",	"CRC32 checksum instructions (arch>8)" }, -    /* arm64/hw_cap */ -    { "fp",	"" }, -    { "asimd",	"Advanced SIMD/NEON on AArch64 (arch>8)" }, -    { "atomics",	"" }, -    { "fphp",	"" }, -    { "asimdhp",	"" }, -    { "cpuid",	"" }, -    { "asimdrdm",	"" }, -    { "jscvt",	"" }, -    { "fcma",	"" }, -    { "lrcpc",	"" }, - -    { NULL, NULL}, -}; -  GHashTable *cpu_flags = NULL; /* FIXME: when is it freed? */  static void  populate_cpu_flags_list_internal()  {      int i; +    gchar **afl, *fm; +      cpu_flags = g_hash_table_new(g_str_hash, g_str_equal); -    for (i = 0; flag_meaning[i].name != NULL; i++) { -        g_hash_table_insert(cpu_flags, flag_meaning[i].name, -                            flag_meaning[i].meaning); +    afl = g_strsplit(arm_flag_list(), " ", 0); +    while(afl[i] != NULL) { +        fm = (char *)arm_flag_meaning(afl[i]); +        if (g_strcmp0(afl[i], "") != 0) +            g_hash_table_insert(cpu_flags, afl[i], (fm) ? fm : ""); +        i++;      }  } @@ -231,6 +187,11 @@ processor_scan(void)          UNKIFNULL(cpu_part);          UNKIFNULL(cpu_revision); +        processor->decoded_name = arm_decoded_name( +            processor->cpu_implementer, processor->cpu_part, +            processor->cpu_variant, processor->cpu_revision, +            processor->cpu_architecture, processor->model_name); +          /* freq */          processor->cpukhz_cur = get_cpu_int("cpufreq/scaling_cur_freq", processor->id);          processor->cpukhz_min = get_cpu_int("cpufreq/scaling_min_freq", processor->id); @@ -287,11 +248,13 @@ gchar *processor_get_capabilities_from_flags(gchar * strflags)  gchar *  processor_get_detailed_info(Processor *processor)  { -    gchar *tmp_flags, *ret; +    gchar *tmp_flags, *tmp_imp, *tmp_part, *ret;      tmp_flags = processor_get_capabilities_from_flags(processor->flags); - +    tmp_imp = (char*)arm_implementer(processor->cpu_implementer); +    tmp_part = (char *)arm_part(processor->cpu_implementer, processor->cpu_part);      ret = g_strdup_printf("[Processor]\n" -                           "Name=%s\n" +                           "Linux Name=%s\n" +                           "Decoded Name=%s\n"                             "Mode=%s\n"                     "BogoMips=%.2f\n"                     "Endianesss=" @@ -306,24 +269,25 @@ processor_get_detailed_info(Processor *processor)                         "Max=%d kHz\n"                         "Cur=%d kHz\n"                         "[ARM]\n" -                       "Implementer=%s\n" +                       "Implementer=[%s] %s\n" +                       "Part=[%s] %s\n"                         "Architecture=%s\n"                         "Variant=%s\n" -                       "Part=%s\n"                         "Revision=%s\n"                         "[Capabilities]\n"                         "%s"                         "%s",                     processor->model_name, +                   processor->decoded_name,                     arm_mode_str[processor->mode],                     processor->bogomips,                     processor->cpukhz_min,                     processor->cpukhz_max,                     processor->cpukhz_cur, -                   processor->cpu_implementer, +                   processor->cpu_implementer, (tmp_imp) ? tmp_imp : "", +                   processor->cpu_part, (tmp_part) ? tmp_part : "",                     processor->cpu_architecture,                     processor->cpu_variant, -                   processor->cpu_part,                     processor->cpu_revision,                     tmp_flags,                      ""); | 
