diff options
| author | Burt P <pburt0@gmail.com> | 2017-05-23 13:45:14 -0500 | 
|---|---|---|
| committer | Leandro A. F. Pereira <leandro@hardinfo.org> | 2017-06-02 12:50:14 -0700 | 
| commit | 8bbf82782fbb39f493d7d01dfa30f8add900c56e (patch) | |
| tree | f27199da11b053198283d00dd8b4b96ea82978d9 /modules/devices/arm | |
| parent | 947cfa55adc63bf4932f32d754a2d4125843ec9b (diff) | |
ARM processor information improvements
* Multiple processors/cores reported
* CPU min/max/cur frequency information reported
* Flag definitions
Tested only on Raspberry Pi models 1 and 3.
Signed-off-by: Burt P <pburt0@gmail.com>
Diffstat (limited to 'modules/devices/arm')
| -rw-r--r-- | modules/devices/arm/processor.c | 183 | 
1 files changed, 169 insertions, 14 deletions
| diff --git a/modules/devices/arm/processor.c b/modules/devices/arm/processor.c index 8d09ea8d..587bb507 100644 --- a/modules/devices/arm/processor.c +++ b/modules/devices/arm/processor.c @@ -19,22 +19,101 @@  #include "hardinfo.h"  #include "devices.h" +/* source: https://unix.stackexchange.com/a/43563 */ +static struct { +    char *name, *meaning; +} flag_meaning[] = { +    { "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" }, +    { "asimd",	"Advanced SIMD/NEON on AArch64" }, +    { "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" }, +    { "pmull{2}",	"64x64->128-bit F2m multiplication" }, +    { NULL, NULL}, +}; + +GHashTable *cpu_flags = NULL; /* FIXME: when is it freed? */ + +static void +populate_cpu_flags_list_internal() +{ +    int i; +    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); +    } +} + +static gint get_cpu_int(const gchar* file, gint cpuid) { +    gchar *tmp0 = NULL; +    gchar *tmp1 = NULL; +    gint ret = 0; + +    tmp0 = g_strdup_printf("/sys/devices/system/cpu/cpu%d/%s", cpuid, file); +    g_file_get_contents(tmp0, &tmp1, NULL, NULL); +    ret = atol(tmp1); + +    g_free(tmp0); +    g_free(tmp1); +    return ret; +} +  GSList *  processor_scan(void)  { +    GSList *procs = NULL;      Processor *processor; +    gint processor_number = 0;      FILE *cpuinfo;      gchar buffer[128]; +    gchar *tmpfreq_str = NULL;      cpuinfo = fopen("/proc/cpuinfo", "r");      if (!cpuinfo)      return NULL; -    processor = g_new0(Processor, 1);      while (fgets(buffer, 128, cpuinfo)) {          gchar **tmp = g_strsplit(buffer, ":", 2); -        if (tmp[0] && tmp[1]) { +        if (g_str_has_prefix(tmp[0], "processor")) { +            if (processor) { +                procs = g_slist_append(procs, processor); +            } + +            processor = g_new0(Processor, 1); +            //get_int("processor", processor->id); +            processor->id = processor_number; +            processor_number++; + +            /* 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); +            processor->cpukhz_max = get_cpu_int("cpufreq/scaling_max_freq", processor->id); +            if (processor->cpukhz_max) +                processor->cpu_mhz = processor->cpukhz_max / 1000; +            else +                processor->cpu_mhz = 0.0f; +        } + +        if (processor && tmp[0] && tmp[1]) {              tmp[0] = g_strstrip(tmp[0]);              tmp[1] = g_strstrip(tmp[1]); @@ -43,27 +122,55 @@ processor_scan(void)                  get_str("model name", processor->model_name);              get_str("Features", processor->flags);              get_float("BogoMIPS", processor->bogomips); - -            get_str("Hardware", processor->has_fpu);          }          g_strfreev(tmp);      } -    processor->cpu_mhz = 0.0f; +    if (processor) +        procs = g_slist_append(procs, processor);      fclose(cpuinfo); -    return g_slist_append(NULL, processor); +    return procs; +} + +gchar *processor_get_capabilities_from_flags(gchar * strflags) +{ +    gchar **flags, **old; +    gchar *tmp = NULL; +    gint j = 0; + +    if (!cpu_flags) +        populate_cpu_flags_list_internal(); + +    flags = g_strsplit(strflags, " ", 0); +    old = flags; + +    while (flags[j]) { +        gchar *meaning = g_hash_table_lookup(cpu_flags, flags[j]); + +        if (meaning) { +            tmp = h_strdup_cprintf("%s=%s\n", tmp, flags[j], meaning); +        } else { +            tmp = h_strdup_cprintf("%s=\n", tmp, flags[j]); +        } +        j++; +    } +    if (tmp == NULL || g_strcmp0(tmp, "") == 0) +        tmp = g_strdup_printf("%s=%s\n", "empty", _("Empty List")); + +    g_strfreev(old); +    return tmp;  }  gchar * -processor_get_info(GSList *processors) +processor_get_detailed_info(Processor *processor)  { -        Processor *processor = (Processor *)processors->data; -         -    return g_strdup_printf("[Processor]\n" +    gchar *tmp_flags, *ret; +    tmp_flags = processor_get_capabilities_from_flags(processor->flags); + +    ret = g_strdup_printf("[Processor]\n"                             "Name=%s\n" -                           "Features=%s\n"                     "BogoMips=%.2f\n"                     "Endianesss="  #if G_BYTE_ORDER == G_LITTLE_ENDIAN @@ -72,9 +179,57 @@ processor_get_info(GSList *processors)                         "Big Endian"  #endif                         "\n" -                   "Hardware=%s\n", +                       "[Freq]\n" +                       "Min=%d kHz\n" +                       "Max=%d kHz\n" +                       "Cur=%d kHz\n" +                       "[Capabilities]\n" +                       "%s" +                       "%s",                     processor->model_name, -                   processor->flags,                     processor->bogomips, -                   processor->has_fpu); +                   processor->cpukhz_min, +                   processor->cpukhz_max, +                   processor->cpukhz_cur, +                   tmp_flags, +                    ""); +    g_free(tmp_flags); +    return ret; +} + +gchar *processor_get_info(GSList * processors) +{ +    Processor *processor; + +    if (g_slist_length(processors) > 1) { +    gchar *ret, *tmp, *hashkey; +    GSList *l; + +    tmp = g_strdup(""); + +    for (l = processors; l; l = l->next) { +        processor = (Processor *) l->data; + +        tmp = g_strdup_printf(_("%s$CPU%d$%s=%.2fMHz\n"), +                  tmp, processor->id, +                  processor->model_name, +                  processor->cpu_mhz); + +        hashkey = g_strdup_printf("CPU%d", processor->id); +        moreinfo_add_with_prefix("DEV", hashkey, +                processor_get_detailed_info(processor)); +           g_free(hashkey); +    } + +    ret = g_strdup_printf("[$ShellParam$]\n" +                  "ViewType=1\n" +                  "[Processors]\n" +                  "%s", tmp); +    g_free(tmp); + +    return ret; +    } + +    processor = (Processor *) processors->data; +    return processor_get_detailed_info(processor);  } | 
