HPCToolkit
cpuid.c
Go to the documentation of this file.
1 // -*-Mode: C++;-*- // technically C99
2 
3 // * BeginRiceCopyright *****************************************************
4 //
5 // $HeadURL$
6 // $Id$
7 //
8 // --------------------------------------------------------------------------
9 // Part of HPCToolkit (hpctoolkit.org)
10 //
11 // Information about sources of support for research and development of
12 // HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
13 // --------------------------------------------------------------------------
14 //
15 // Copyright ((c)) 2002-2018, Rice University
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are
20 // met:
21 //
22 // * Redistributions of source code must retain the above copyright
23 // notice, this list of conditions and the following disclaimer.
24 //
25 // * Redistributions in binary form must reproduce the above copyright
26 // notice, this list of conditions and the following disclaimer in the
27 // documentation and/or other materials provided with the distribution.
28 //
29 // * Neither the name of Rice University (RICE) nor the names of its
30 // contributors may be used to endorse or promote products derived from
31 // this software without specific prior written permission.
32 //
33 // This software is provided by RICE and contributors "as is" and any
34 // express or implied warranties, including, but not limited to, the
35 // implied warranties of merchantability and fitness for a particular
36 // purpose are disclaimed. In no event shall RICE or contributors be
37 // liable for any direct, indirect, incidental, special, exemplary, or
38 // consequential damages (including, but not limited to, procurement of
39 // substitute goods or services; loss of use, data, or profits; or
40 // business interruption) however caused and on any theory of liability,
41 // whether in contract, strict liability, or tort (including negligence
42 // or otherwise) arising in any way out of the use of this software, even
43 // if advised of the possibility of such damage.
44 //
45 // ******************************************************* EndRiceCopyright *
46 
47 // Note:
48 // Some of the code is adapted from Linux Perf source code:
49 // https://github.com/torvalds/linux/blob/master/tools/perf/arch/x86/util/header.c
50 
51 #include <stdlib.h>
52 #include <stdio.h>
53 #include <string.h>
54 
55 #include <utilities/arch/cpuid.h>
56 
57 
58 static inline void
59 asm_cpuid(unsigned int op, unsigned int *a, unsigned int *b, unsigned int *c,
60  unsigned int *d)
61 {
62  // this assembly code is taken from Linux kernel
63  // the code is gpl, so I assume it's okay to put it here
64  __asm__ __volatile__ (".byte 0x53\n\tcpuid\n\t"
65  "movl %%ebx, %%esi\n\t.byte 0x5b"
66  : "=a" (*a),
67  "=S" (*b),
68  "=c" (*c),
69  "=d" (*d)
70  : "a" (op));
71 }
72 
73 /* return cpu type based on the cpu model */
74 /* see https://en.wikichip.org/wiki/intel/cpuid */
75 static cpu_type_t
77 {
78  cpu_type_t type = CPU_UNSUP;
79 
80  if (cpuid->family == 6) {
81  switch (cpuid->model) {
82 
83  case 26:
84  type = INTEL_NHM_EP;
85  break;
86  case 42:
87  type = INTEL_SNB;
88  break;
89  case 44:
90  type = INTEL_WSM_EP;
91  break;
92  case 45:
93  type = INTEL_SNB_EP;
94  break;
95  case 46:
96  type = INTEL_NHM_EX;
97  break;
98  case 47:
99  type = INTEL_WSM_EX;
100  break;
101  case 62:
102  type = INTEL_IVB_EX;
103  break;
104  case 63:
105  type = INTEL_HSX;
106  break;
107  case 79:
108  type = INTEL_BDX;
109  break;
110  case 85:
111  type = INTEL_SKX;
112  break;
113  case 87:
114  type = INTEL_KNL;
115  break;
116  case 0x7e:
117  type = INTEL_ICL;
118  break;
119 
120  }
121  }
122  return type;
123 }
124 
125 static cpu_type_t
127 {
128  cpu_type_t type = CPU_UNSUP;
129 
130  if (cpuid->family == 16) {
131  switch (cpuid->model) {
132  case 9:
133  type = AMD_MGN_CRS;
134  break;
135  }
136  }
137  return type;
138 }
139 
140 static cpu_type_t
141 __get_cpuid(struct cpuid_type_s *cpuid)
142 {
143  unsigned int a, b, c, d, lvl;
144 
145  asm_cpuid(0, &lvl, &b, &c, &d);
146 
147  strncpy(&cpuid->vendor[0], (char *)(&b), 4);
148  strncpy(&cpuid->vendor[4], (char *)(&d), 4);
149  strncpy(&cpuid->vendor[8], (char *)(&c), 4);
150 
151  cpuid->vendor[12] = '\0';
152 
153  if (lvl >= 1) {
154  asm_cpuid(1, &a, &b, &c, &d);
155 
156  cpuid->family = (a >> 8) & 0xf; /* bits 11 - 8 */
157  cpuid->model = (a >> 4) & 0xf; /* Bits 7 - 4 */
158  cpuid->step = a & 0xf;
159 
160  /* extended family */
161  if (cpuid->family == 0xf)
162  cpuid->family += (a >> 20) & 0xff;
163 
164  /* extended model */
165  if (cpuid->family >= 0x6)
166  cpuid->model += ((a >> 16) & 0xf) << 4;
167  }
168 
169  /* look for end marker to ensure the entire data fit */
170  if (strncmp(cpuid->vendor, VENDOR_INTEL, 12) == 0) {
171  // intel
172  return get_intel_cpu_type(cpuid);
173  } else if (strncmp(cpuid->vendor, VENDOR_AMD, 12) == 0) {
174  // amd
175  return get_amd_cpu_type(cpuid);
176  }
177  return CPU_UNSUP;
178 }
179 
180 
181 
184 {
185  struct cpuid_type_s cpuid;
186  memset(&cpuid, 0, sizeof(cpuid));
187 
188  cpu_type_t type = __get_cpuid(&cpuid);
189 #if UNIT_TEST_CPUID
190  printf("vendor:\t%s\nfamily:\t%d\nmodel:\t%d\nstep:\t%d\n", cpuid.vendor, cpuid.family, cpuid.model, cpuid.step);
191 #endif
192  return type;
193 }
194 
195 
196 #if UNIT_TEST_CPUID
197 
198 int main(void)
199 {
200  cpu_type_t type = get_cpuid();
201  printf("\ncpu type: %d\n", type);
202 }
203 #endif
char vendor[13]
Definition: cpuid.h:56
int model
Definition: cpuid.h:58
static cpu_type_t __get_cpuid(struct cpuid_type_s *cpuid)
Definition: cpuid.c:141
int family
Definition: cpuid.h:57
cpu_type_t
Definition: cpuid.h:62
cpu_type_t get_cpuid()
Definition: cpuid.c:52
static cpu_type_t get_intel_cpu_type(struct cpuid_type_s *cpuid)
Definition: cpuid.c:76
int main(int argc, char *argv[])
Definition: main.cpp:125
int step
Definition: cpuid.h:59
static void asm_cpuid(unsigned int op, unsigned int *a, unsigned int *b, unsigned int *c, unsigned int *d)
Definition: cpuid.c:59
#define VENDOR_INTEL
Definition: cpuid.h:52
static cpu_type_t get_amd_cpu_type(struct cpuid_type_s *cpuid)
Definition: cpuid.c:126
#define VENDOR_AMD
Definition: cpuid.h:53