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/processor.c | |
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/processor.c')
-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); } |