aboutsummaryrefslogtreecommitdiff
path: root/modules/devices/arm
diff options
context:
space:
mode:
authorBurt P <pburt0@gmail.com>2017-05-23 13:45:14 -0500
committerLeandro A. F. Pereira <leandro@hardinfo.org>2017-06-02 12:50:14 -0700
commit8bbf82782fbb39f493d7d01dfa30f8add900c56e (patch)
treef27199da11b053198283d00dd8b4b96ea82978d9 /modules/devices/arm
parent947cfa55adc63bf4932f32d754a2d4125843ec9b (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.c183
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);
}