bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [RFC PATCH hurd] Add partial /proc/cpuinfo implementation


From: Luca
Subject: Re: [RFC PATCH hurd] Add partial /proc/cpuinfo implementation
Date: Wed, 8 Jan 2025 10:25:41 +0100

Hi,

Il 08/01/25 02:30, dnietoc@gmail.com ha scritto:
From: Diego Nieto Cid <dnietoc@gmail.com>

Hello,

This is a patch to introduce the cpuinfo file to the hierarchy
exposed by procfs.

I used as guidance the Wikipedia article on the CPUID instruction
and the GNU/Linux output to sort each line in the output.

There remains a lot of fields that I haven't covered yet and
SMP is not supported (in alignment with the output of /proc/stat).
But it seems to help in the porting of libgtop to GNU/Hurd, which I
started from a copy of Linux implementation.

Beside that, I probably need to cache the CPUID provided information
as I don't think it would change over time.

I think the information could be considered constant, at least gnumach should enable all supported features at startup.

I don't know if the cpuid performance impact is relevant compared to performing an rpc, but you can easily estimate it by measuring a few thousand reads, and then comparing with a version where you don't use cpuid but you return constant values.


The output below is what currently is implemented:

     demo@debian:~/dev/hurd/upstream/hurd/build-tree$ settrans -a test-proc 
procfs/procfs
     demo@debian:~/dev/hurd/upstream/hurd/build-tree$ cat ./test-proc/cpuinfo
     processor       : 0
     vendor_id       : AuthenticAMD
     cpu family      : 25
     model           : 80
     model name      : AMD Ryzen 9 5900HX with Radeon Graphics
     stepping        : 0
     flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca 
cmov pat pse36 clfsh mmx fxsr sse sse2 htt sse3 pclmulqdq ssse3 cx16 sse4_1 
sse4_2 movbe popcnt aes_ni rdrnd


So what else do you think should be included in our implementation
of cpuinfo?

Thanks,
Diego


-- >8 -- >8 -- >8 --

   * procfs/rootdir.c: (rootdir_gc_cpuinfo) new function
     (rootdir_entries): add entry for cpuinfo file
---
  procfs/rootdir.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++
  1 file changed, 127 insertions(+)

diff --git a/procfs/rootdir.c b/procfs/rootdir.c
index b8a8c4d1..966e2eee 100644
--- a/procfs/rootdir.c
+++ b/procfs/rootdir.c
@@ -38,6 +38,7 @@
  #include "procfs_dir.h"
  #include "main.h"
  #include <net/route.h>
+#include <cpuid.h>
#include "mach_debug_U.h"
  #include "pfinet_U.h"
@@ -696,6 +697,125 @@ out_fclose:
    fclose (m);
    return err;
  }
+
+static char * features_edx[] =
+  {
+    "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", "cx8", "apic",
+    NULL, "sep", "mtrr", "pge", "mca", "cmov", "pat", "pse36", "psn", "clfsh",
+    NULL, "ds", "acpi", "mmx", "fxsr", "sse", "sse2", "ss", "htt", "tm",
+   "ia64", "pbe"
+  };
+
+static char * features_ecx[] =
+  {
+    "sse3", "pclmulqdq", "dtes64", "monitor", "ds-cpl", "vmx", "smx", "est",
+    "tm3", "ssse3", "cnxt-id", "sdbg", "fma", "cx16", "xtpr", "pdcm",
+    NULL, "pcid", "dca", "sse4_1", "sse4_2", "x2apic", "movbe", "popcnt",
+   "tsc_deadline", "aes_ni", "xsave", "osxsave", "avx", "f16c", "rdrnd", 
"hypervisor"
+  };

Are these names reflecting the gcc header cpuid.h? It seems there is some difference with e.g. Linux naming (rdrnd vs rdrand), I'm not sure what would be the best reference.

+
+static error_t
+rootdir_gc_cpuinfo (void *hook, char **contents, ssize_t *contents_len)
+{
+# define VENDOR_ID_LEN 12
+# define MODEL_NAME_LEN 48
+  error_t err = 0;
+  int ret, index, stepping, model, family, extended_model, extended_family;
+  unsigned int eax, ebx, ecx, edx;
+  unsigned int feature_edx, feature_ecx;
+  char vendor[VENDOR_ID_LEN + 1] = { 0 };
+  char model_name[MODEL_NAME_LEN + 1] = { 0 };
+  FILE* m;
+
+  m = open_memstream(contents, (size_t *) contents_len);
+  if (m == NULL)
+    return errno;
+
+  ret = __get_cpuid(0, &eax, &ebx, &ecx, &edx);
+  if (ret != 1)
+    {
+      err = EIO;
+      goto out;
+    }
+
+  memcpy(vendor + 0 * sizeof(unsigned int), (char *) &ebx, sizeof(unsigned 
int));
+  memcpy(vendor + 1 * sizeof(unsigned int), (char *) &edx, sizeof(unsigned 
int));
+  memcpy(vendor + 2 * sizeof(unsigned int), (char *) &ecx, sizeof(unsigned 
int));
+
+  ret = __get_cpuid(1, &eax, &ebx, &ecx, &edx);
+   if (ret != 1)
+    {
+      err = EIO;
+      goto out;
+    }
+
+  feature_edx = edx;
+  feature_ecx = ecx;
+  stepping = eax & 0x0F;
+  model = (eax & 0xF0) >> 4;
+  family = (eax & 0xF00) >> 8;
+  extended_model = (eax & 0xF0000) >> 16;
+  extended_family = (eax &0xFF00000) >> 20;
+
+  if (family == 6 || family == 15)
+    model += (extended_model << 4);
+  if (family == 15)
+    family += extended_family;
+
+  __get_cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
+  if (eax >= 0x80000004)
+    {
+      __get_cpuid(0x80000002, &eax, &ebx, &ecx, &edx);
+      memcpy(model_name + 0 * sizeof(unsigned int), (char *) &eax, 
sizeof(unsigned int));
+      memcpy(model_name + 1 * sizeof(unsigned int), (char *) &ebx, 
sizeof(unsigned int));
+      memcpy(model_name + 2 * sizeof(unsigned int), (char *) &ecx, 
sizeof(unsigned int));
+      memcpy(model_name + 3 * sizeof(unsigned int), (char *) &edx, 
sizeof(unsigned int));
+
+      __get_cpuid(0x80000003, &eax, &ebx, &ecx, &edx);
+      memcpy(model_name + 4 * sizeof(unsigned int), (char *) &eax, 
sizeof(unsigned int));
+      memcpy(model_name + 5 * sizeof(unsigned int), (char *) &ebx, 
sizeof(unsigned int));
+      memcpy(model_name + 6 * sizeof(unsigned int), (char *) &ecx, 
sizeof(unsigned int));
+      memcpy(model_name + 7 * sizeof(unsigned int), (char *) &edx, 
sizeof(unsigned int));
+
+      __get_cpuid(0x80000004, &eax, &ebx, &ecx, &edx);
+      memcpy(model_name + 8 * sizeof(unsigned int), (char *) &eax, 
sizeof(unsigned int));
+      memcpy(model_name + 9 * sizeof(unsigned int), (char *) &ebx, 
sizeof(unsigned int));
+      memcpy(model_name + 10 * sizeof(unsigned int), (char *) &ecx, 
sizeof(unsigned int));
+      memcpy(model_name + 11 * sizeof(unsigned int), (char *) &edx, 
sizeof(unsigned int));
+    }
+
+  fprintf(m,
+    "processor       : 0\n"
+    "vendor_id       : %s\n"
+    "cpu family      : %d\n"
+    "model           : %d\n"
+    "model name      : %s\n"
+    "stepping        : %d\n",
+    vendor, family, model, model_name, stepping);
+
+  fprintf(m, "flags           :");
+  for (index = 0; index < 32; index++)
+    {
+      if (features_edx[index] == NULL)
+        continue;
+      if (feature_edx & (1 << index))
+        fprintf(m, " %s", features_edx[index]);
+    }
+  for (index = 0; index < 32; index++)
+    {
+      if (features_ecx[index] == NULL)
+        continue;
+      if (feature_ecx & (1 << index))
+        fprintf(m, " %s", features_ecx[index]);
+    }
+
+  fprintf(m, "\n\n");
+
+out:
+  fclose(m);
+  return err;
+}
  

maybe this can be already made arch-specific.


Luca



reply via email to

[Prev in Thread] Current Thread [Next in Thread]