1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <string.h>
#include "hardware.h"
#define PLL_FEAT_AVAIL(x,y) (((x) & (y)) == (y))
#define PLL_SYS_CPU_DIR_PATH "/sys/devices/system/cpu/"
//#ifdef _MSC_VER
//#define inline __inline
//#endif
static __inline void cpuid(unsigned int op, int count,
unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx)
{
#ifdef WIN32
__int32 regs[4];
__cpuid((int*)regs, (int)op);
*eax = regs[0];
*ebx = regs[1];
*ecx = regs[2];
*edx = regs[3];
#else
*eax = op;
*ecx = count;
asm volatile("cpuid"
: "=a" (*eax),
"=b" (*ebx),
"=c" (*ecx),
"=d" (*edx)
: "0" (*eax), "2" (*ecx)
: "memory");
#endif
}
void show_hardware_info(pllHardwareInfo * hw)
{
printf ("MMX.........: %d\n"
"SSE.........: %d\n"
"SSE2........: %d\n"
"SSE3........: %d\n"
"SSSE3.......: %d\n"
"FMA.........: %d\n"
"SSE4.1......: %d\n"
"SSE4.2......: %d\n"
"AVX.........: %d\n"
"AVX2........: %d\n"
"SSE4A.......: %d\n"
"FMA4........: %d\n\n"
"Core(s).....: %d\n"
"CPU Sockets.: %d\n",
hw->has_mmx, hw->has_sse, hw->has_sse2, hw->has_sse3, hw->has_ssse3,
hw->has_fma, hw->has_sse41, hw->has_sse42, hw->has_avx, hw->has_avx2,
hw->has_sse4a, hw->has_fma4, hw->cores, hw->cpu_sockets);
}
static int pll_probe_cpu (pllHardwareInfo * hw)
{
struct stat cpustat;
char cpu[30];
char cpupath[100];
int i, id, max_physical_id = -1;
char * physical_id_path = "/topology/physical_package_id";
FILE * fd;
/* check whether the sys cpu dir exists */
if (stat(PLL_SYS_CPU_DIR_PATH, &cpustat)) return (0);
/* and also check whether it is a dir */
if (!S_ISDIR(cpustat.st_mode)) return (0);
/* detect number of processors */
for (i = 0; ; ++i)
{
sprintf(cpu, "cpu%d", i);
strcpy (cpupath, PLL_SYS_CPU_DIR_PATH);
strcat (cpupath, cpu);
if (stat(cpupath, &cpustat)) break;
strcat (cpupath, physical_id_path);
if (!stat(cpupath, &cpustat))
{
fd = fopen (cpupath,"r");
fscanf (fd, "%d", &id);
/* printf ("Detected processor %d belonging to package %d\n", i, id); */
if (id > max_physical_id) max_physical_id = id;
fclose (fd);
}
}
hw->cores = i;
hw->cpu_sockets = max_physical_id + 1;
return (1);
}
static void pll_probe_hardware (pllHardwareInfo * hw)
{
unsigned int a, b, c, d;
c = 0;
cpuid(0,0,&a,&b,&c,&d);
*((unsigned int *)(hw->vendor) ) = b;
*((unsigned int *)(hw->vendor + 4)) = d;
*((unsigned int *)(hw->vendor + 8)) = c;
hw->vendor[12] = 0;
printf ("%s\n", hw->vendor);
cpuid(1,0,&a,&b,&c,&d);
hw->has_mmx = PLL_FEAT_AVAIL(d,PLL_HAS_MMX);
hw->has_sse = PLL_FEAT_AVAIL(d,PLL_HAS_SSE);
hw->has_sse2 = PLL_FEAT_AVAIL(d,PLL_HAS_SSE2);
hw->has_sse3 = PLL_FEAT_AVAIL(c,PLL_HAS_SSE3);
hw->has_ssse3 = PLL_FEAT_AVAIL(c,PLL_HAS_SSSE3);
hw->has_fma = PLL_FEAT_AVAIL(c,PLL_HAS_FMA);
hw->has_sse41 = PLL_FEAT_AVAIL(c,PLL_HAS_SSE41);
hw->has_sse42 = PLL_FEAT_AVAIL(c,PLL_HAS_SSE42);
hw->has_avx = PLL_FEAT_AVAIL(c,PLL_HAS_AVX);
cpuid(7,0,&a,&b,&c,&d);
hw->has_avx2 = PLL_FEAT_AVAIL(b,PLL_HAS_AVX2);
/* TODO: note, here we have to check whether leaf 0x80000001 exists */
cpuid(0x80000001,0,&a,&b,&c,&d);
hw->has_sse4a = PLL_FEAT_AVAIL(c,PLL_HAS_SSE4A);
hw->has_fma4 = PLL_FEAT_AVAIL(c,PLL_HAS_FMA4);
}
int pllGetHardwareInfo (pllHardwareInfo * hw)
{
pll_probe_hardware (hw);
pll_probe_cpu (hw);
/* TODO: finish failure checks in probe_hardware and probe_cpu */
return (1);
}
/* TODO: Remove after testing */
/*
int main (int argc, char * argv[])
{
pllHardwareInfo hw;
pll_probe_hardware(&hw);
pll_probe_cpu(&hw);
show_hardware_info(&hw);
return (EXIT_SUCCESS);
}
*/
|