Hello,

For Intel with HyperThreading 8 I think -> 16 (virtual core).
Linux probably choose 8 to obtain better result.
This is not very clear for me.

http://www.richweb.com/cpu_info

I have apply your change.
With Qemu I obtain 1 processor (I keep the virtual number of core but it's easy to change, I can change it)

Alain



On 19/11/2011 23:18, Samuel Thibault wrote:
Hello,

Bouju Alain, le Sun 13 Nov 2011 12:44:04 +0100, a écrit :
/* gcc cpuinfo.c -o cpuinfo `pkg-config --cflags glib-2.0` -lm */
#include<glib.h>
Using glib for /proc is a bit out of question :)
16-bit and 32-bit types are available as uint16_t&  uint32_t in
stdint.h.

The coding style has to follow the GNU Coding Style, e.g. there must be
a space between the function name and the opening parenthesis. You
should probably use indent to fix everything automatically.

cpuid is only available on x86, so the code should be put in some x86/
directory, and ideally compiled only on x86.

No need to put __volatile__ in the cpuid macro, since we don't depend on
any effect of cpuid here.

A \n is missing between processors.

It detects too many processors on my machine: 16 instead of 8:

i 00000000 a 0000000d b 756e6547 c 6c65746e d 49656e69
i 00000001 a 000206a7 b 05100800 c 1fbae3ff d bfebfbff
i 00000002 a 76035a01 b 00f0b2ff c 00000000 d 00ca0000
i 00000003 a 00000000 b 00000000 c 00000000 d 00000000
i 00000004 a 00000000 b 00000000 c 00000000 d 00000000
i 00000005 a 00000040 b 00000040 c 00000003 d 00021120
i 00000006 a 00000077 b 00000002 c 00000009 d 00000000
i 00000007 a 00000000 b 00000000 c 00000000 d 00000000
i 00000008 a 00000000 b 00000000 c 00000000 d 00000000
i 00000009 a 00000000 b 00000000 c 00000000 d 00000000
i 0000000a a 07300403 b 00000000 c 00000000 d 00000603
i 0000000b a 00000000 b 00000000 c 000000e3 d 00000005
i 0000000c a 00000000 b 00000000 c 00000000 d 00000000
i 0000000d a 00000000 b 00000000 c 00000000 d 00000000
a 80000008 b 00000000 c 00000000 d 00000000
i 80000000 a 80000008 b 00000000 c 00000000 d 00000000
i 80000001 a 00000000 b 00000000 c 00000001 d 28100800
i 80000002 a 20202020 b 6e492020 c 286c6574 d 43202952
i 80000003 a 2865726f b 20294d54 c 322d3769 d 51303237
i 80000004 a 5043204d b 20402055 c 30322e32 d 007a4847
i 80000005 a 00000000 b 00000000 c 00000000 d 00000000
i 80000006 a 00000000 b 00000000 c 01006040 d 00000000
i 80000007 a 00000000 b 00000000 c 00000000 d 00000100
i 80000008 a 00003024 b 00000000 c 00000000 d 00000000
Intel
2093
processor       : 0
vendor_id       : GenuineIntel
model name      :       Intel(R) Core(TM) i7-2720QM CPU @ 2.20GHz
core id         : 0
cpuid-level     : 13

processor       : 1
vendor_id       : GenuineIntel
model name      :       Intel(R) Core(TM) i7-2720QM CPU @ 2.20GHz
core id         : 1
cpuid-level     : 13
processor       : 2
vendor_id       : GenuineIntel
model name      :       Intel(R) Core(TM) i7-2720QM CPU @ 2.20GHz
core id         : 2

etc. up to 15, while on Linux:

processor       : 0
physical id     : 0
siblings        : 8
core id         : 0
cpu cores       : 4
apicid          : 0

processor       : 1
physical id     : 0
siblings        : 8
core id         : 1
cpu cores       : 4
apicid          : 2

processor       : 2
physical id     : 0
siblings        : 8
core id         : 2
cpu cores       : 4
apicid          : 4

processor       : 3
physical id     : 0
siblings        : 8
core id         : 3
cpu cores       : 4
apicid          : 6

processor       : 4
physical id     : 0
siblings        : 8
core id         : 0
cpu cores       : 4
apicid          : 1

processor       : 5
physical id     : 0
siblings        : 8
core id         : 1
cpu cores       : 4
apicid          : 3

processor       : 6
physical id     : 0
siblings        : 8
core id         : 2
cpu cores       : 4
apicid          : 5

processor       : 7
physical id     : 0
siblings        : 8
core id         : 3
cpu cores       : 4
apicid          : 7

That being said, since GNU Mach only supports one processor, I'd rather
show only one processor in /proc/cpuinfo, because on Linux, cpuinfo
only shows the running processors, and thus some tools would infer from
/proc/cpuinfo that there are more than just 1 active processor.

Samuel

/* Hurd /proc filesystem, implementation of process directories.
   Copyright (C) 2010 Free Software Foundation, Inc.

   This file is part of the GNU Hurd.

   The GNU Hurd 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, or (at
   your option) any later version.

   The GNU Hurd 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., 675 Mass Ave, Cambridge, MA 02139, USA. */

#include "cpuinfo.h"

/* This module implements the cpuinfo directory */

/* Helper functions */
#define cpuid(func,ax,bx,cx,dx) __asm__ ("cpuid":       "=a" (ax), "=b" (bx), 
"=c" (cx), "=d" (dx) : "a" (func));



void
cpuinfo_string (char **result, int *result_length, CpuInfo cpuinfo)
{
  int len;
  char *result_processor;
  int i = 0;
  char *tmp_string;

  cpuinfo_processor_string (&result_processor, cpuinfo, 0);
  len = asprintf (result, "processor\t: %d\n%s\n", i, result_processor);

  for (i = 1; i < cpuinfo.cpu_cores; i++)
    {
      /* by processor */
      cpuinfo_processor_string (&result_processor, cpuinfo, i);
      tmp_string = *result;
      len =
        asprintf (result, "%sprocessor\t: %d\n%s\n", *result, i,
                  result_processor);
      free (tmp_string);
    }
  *result_length = len;
}

void
cpuinfo_processor_string (char **result, CpuInfo cpuinfo, int i)
{
  char *tmp_string;
  /* by processor */
  /* Vendor */
  asprintf (result, "vendor_id\t: %s\n", cpuinfo.vendor);
  /* Model Name */
  tmp_string = *result;
  asprintf (result, "%smodel name\t: %s\n", *result, cpuinfo.model_name);
  free (tmp_string);
  /* Core ID */
  tmp_string = *result;
  asprintf (result, "%score id\t\t: %d\n", *result, i);
  free (tmp_string);
  /* CPUID LEVEL */
  tmp_string = *result;
  asprintf (result, "%scpuid-level\t: %d\n", *result, cpuinfo.cpuid_level);
  free (tmp_string);
}

void
debug_cpu (void)
{
  uint32_t func;
  uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
  uint32_t size = 0;
  uint32_t i;

  /* MAX CPUID INSTRUCTION LEVELS */
  /* State */
  /* EAX 0 http://en.wikipedia.org/wiki/CPUID */
  func = 0;
  cpuid (func, eax, ebx, ecx, edx);
  size = eax & 0xffff;          /* The high-order word is non-zero on some 
Cyrix CPUs */
  for (i = 0; i <= size; i++)
    {
      cpuid (i, eax, ebx, ecx, edx);
      printf ("i %08x a %08x b %08x c %08x d %08x\n", i, eax, ebx, ecx, edx);
    }
  /* EAX 0x80000000 http://en.wikipedia.org/wiki/CPUID */
  func = 0x80000000;
  cpuid (func, eax, ebx, ecx, edx);
  printf ("a %08x b %08x c %08x d %08x\n", eax, ebx, ecx, edx);
  /* cpuid level */
  size = eax;                   /* The high-order word is non-zero on some 
Cyrix CPUs */

  for (i = 0x80000000; i <= size; i++)
    {
      cpuid (i, eax, ebx, ecx, edx);
      printf ("i %08x a %08x b %08x c %08x d %08x\n", i, eax, ebx, ecx, edx);
    }
  /* Brand */
  func = 0;
  cpuid (func, eax, ebx, ecx, edx);

  switch (ebx)
    {
    case 0x756e6547:            /* Intel */
      printf ("Intel\n");
      break;
    case 0x68747541:            /* AMD */
      printf ("AMD\n");
      break;
    case 0x69727943:            /* Cyrix */
      printf ("Cyrix \n");
      break;
    default:
      printf ("Unknown vendor\n");
      break;
    }


}


void
init_cpuinfo (CpuInfo * cpuinfo)
{
  uint32_t func;
  uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
  uint32_t tmp;
  uint32_t size = 0;
  uint32_t i;
  int j;
  char c;

  /* EAX 0 http://en.wikipedia.org/wiki/CPUID */
  func = 0;
  cpuid (func, eax, ebx, ecx, edx);
  size = eax & 0xffff;          /* The high-order word is non-zero on some 
Cyrix CPUs */
  cpuinfo->cpuid_level = size;

  /* EAX 0x00000004 http://en.wikipedia.org/wiki/CPUID */
  func = 1;
  cpuid (func, eax, ebx, ecx, edx);
  cpuinfo->cpu_cores = ebx >> 16 & 0xFF;

  /* Vendor */
  func = 0;
  cpuid (func, eax, ebx, ecx, edx);
  i = 0;
  /* ebx */
  tmp = ebx;
  for (j = 0; j < 4; j++)
    {
      c = tmp & 0xff;
      cpuinfo->vendor[i] = c;
      tmp = tmp >> 8;
      i++;
    }
  /* edx */
  tmp = edx;
  for (j = 0; j < 4; j++)
    {
      c = tmp & 0xff;
      cpuinfo->vendor[i] = c;
      tmp = tmp >> 8;
      i++;
    }
  /* ecx */
  tmp = ecx;
  for (j = 0; j < 4; j++)
    {
      c = tmp & 0xff;
      cpuinfo->vendor[i] = c;
      tmp = tmp >> 8;
      i++;
    }

  cpuinfo->vendor[i] = 0;

/* EAX 0x80000002 http://en.wikipedia.org/wiki/CPUID */
/* Model */
  i = 0;
  for (func = 0x80000002; func <= 0x80000004; func++)
    {
      cpuid (func, eax, ebx, ecx, edx);
      /* eax */
      tmp = eax;
      for (j = 0; j < 4; j++)
        {
          c = tmp & 0xff;
          cpuinfo->model_name[i] = c;
          tmp = tmp >> 8;
          i++;
        }

      /* ebx */
      tmp = ebx;
      for (j = 0; j < 4; j++)
        {
          c = tmp & 0xff;
          cpuinfo->model_name[i] = c;
          tmp = tmp >> 8;
          i++;
        }
      /* ecx */
      tmp = ecx;
      for (j = 0; j < 4; j++)
        {
          c = tmp & 0xff;
          cpuinfo->model_name[i] = c;
          tmp = tmp >> 8;
          i++;
        }
      /* edx */
      tmp = edx;
      for (j = 0; j < 4; j++)
        {
          c = tmp & 0xff;
          cpuinfo->model_name[i] = c;
          tmp = tmp >> 8;
          i++;
        }
    }
  cpuinfo->model_name[i] = 0;
}

/*
int
main (int argc, char *argv[])
{
  CpuInfo cpuinfo;
  char *result;
  int result_length;

  init_cpuinfo (&cpuinfo);
  cpuinfo_string (&result, &result_length, cpuinfo);
  printf ("%d\n%s\n", result_length, result);
  return 0;
}
*/
/* Hurd /proc filesystem, implementation of process directories.
   Copyright (C) 2010 Free Software Foundation, Inc.

   This file is part of the GNU Hurd.

   The GNU Hurd 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, or (at
   your option) any later version.

   The GNU Hurd 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., 675 Mass Ave, Cambridge, MA 02139, USA. */

#ifndef CPUINFO_H
#define CPUINFO_H
#include <stdio.h>
#include <math.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct cpuinfo
{
  short cpu_cores;
  char vendor[13];
  char model_name[49];
  short cpuid_level;
} CpuInfo;

/* init cpuinfo */
void init_cpuinfo (CpuInfo * cpuinfo);

/* cpuinfo string */
void cpuinfo_string (char **result, int *result_length, CpuInfo cpuinfo);

/* cpuinfo string for a core */
void cpuinfo_processor_string (char **result, CpuInfo cpuinfo, int i);


#endif
diff --git a/Makefile b/Makefile
index a397522..54fd741 100644
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,10 @@
 TARGET = procfs
-OBJS = procfs.o netfs.o procfs_dir.o \
+OBJS = procfs.o netfs.o procfs_dir.o x86/cpuinfo.o\
        process.o proclist.o rootdir.o dircat.o main.o
-LIBS = -lnetfs -lps
+LIBS = -lnetfs -lps -lfshelp
 
 CC = gcc
-CFLAGS = -Wall -g
+CFLAGS = -Wall -g 
 CPPFLAGS =
 LDFLAGS =
 
diff --git a/rootdir.c b/rootdir.c
index 1fa71b0..c1a8716 100644
--- a/rootdir.c
+++ b/rootdir.c
@@ -32,6 +32,7 @@
 #include "procfs.h"
 #include "procfs_dir.h"
 #include "main.h"
+#include "x86/cpuinfo.h"
 
 /* This implements a directory node with the static files in /proc.
    NB: the libps functions for host information return static storage;
@@ -397,6 +398,14 @@ rootdir_gc_fakeself (void *hook, char **contents, ssize_t 
*contents_len)
   return 0;
 }
 
+static error_t
+rootdir_gc_cpuinfo (void *hook, char **contents, ssize_t *contents_len)
+{
+  CpuInfo cpuinfo;
+  init_cpuinfo(&cpuinfo);
+  cpuinfo_string(contents,contents_len,cpuinfo);
+  return 0;
+}
 
 /* Glue logic and entries table */
 
@@ -480,6 +489,13 @@ static const struct procfs_dir_entry rootdir_entries[] = {
       .cleanup_contents = procfs_cleanup_contents_with_free,
     },
   },
+  {
+    .name = "cpuinfo",
+    .hook = & (struct procfs_node_ops) {
+      .get_contents = rootdir_gc_cpuinfo,
+      .cleanup_contents = procfs_cleanup_contents_with_free,
+    },
+  },
 #ifdef PROFILE
   /* In order to get a usable gmon.out file, we must apparently use exit(). */
   {

Reply via email to