iPXE
cpuid.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <string.h>
27 #include <errno.h>
28 #include <ipxe/cpuid.h>
29 
30 /** @file
31  *
32  * x86 CPU feature detection
33  *
34  */
35 
36 /** Colour for debug messages */
37 #define colour 0x861d
38 
39 /**
40  * Check whether or not CPUID instruction is supported
41  *
42  * @ret rc Return status code
43  */
44 static int cpuid_instruction_supported ( void ) {
45  unsigned long original;
46  unsigned long inverted;
47 
48  /* Check for instruction existence via flag modifiability */
49  __asm__ ( "pushf\n\t"
50  "pushf\n\t"
51  "pop %0\n\t"
52  "mov %0,%1\n\t"
53  "xor %2,%1\n\t"
54  "push %1\n\t"
55  "popf\n\t"
56  "pushf\n\t"
57  "pop %1\n\t"
58  "popf\n\t"
59  : "=&r" ( original ), "=&r" ( inverted )
60  : "ir" ( CPUID_FLAG ) );
61  if ( ! ( ( original ^ inverted ) & CPUID_FLAG ) ) {
62  DBGC ( colour, "CPUID instruction is not supported\n" );
63  return -ENOTSUP;
64  }
65 
66  return 0;
67 }
68 
69 /**
70  * Check whether or not CPUID function is supported
71  *
72  * @v function CPUID function
73  * @ret rc Return status code
74  */
75 int cpuid_supported ( uint32_t function ) {
76  uint32_t max_function;
77  uint32_t discard_b;
79  uint32_t discard_d;
80  int rc;
81 
82  /* Check that CPUID instruction is available */
83  if ( ( rc = cpuid_instruction_supported() ) != 0 )
84  return rc;
85 
86  /* Find highest supported function number within this family */
87  cpuid ( ( function & ( CPUID_EXTENDED | CPUID_HYPERVISOR ) ), 0,
88  &max_function, &discard_b, &discard_c, &discard_d );
89 
90  /* Fail if maximum function number is meaningless (e.g. if we
91  * are attempting to call an extended function on a CPU which
92  * does not support them).
93  */
94  if ( ( max_function & CPUID_AMD_CHECK_MASK ) !=
95  ( function & CPUID_AMD_CHECK_MASK ) ) {
96  DBGC ( colour, "CPUID invalid maximum function %#08x\n",
97  max_function );
98  return -EINVAL;
99  }
100 
101  /* Fail if this function is not supported */
102  if ( function > max_function ) {
103  DBGC ( colour, "CPUID function %#08x not supported\n",
104  function );
105  return -ENOTTY;
106  }
107 
108  return 0;
109 }
110 
111 /**
112  * Get Intel-defined x86 CPU features
113  *
114  * @v features x86 CPU features to fill in
115  */
116 static void x86_intel_features ( struct x86_features *features ) {
117  uint32_t discard_a;
118  uint32_t discard_b;
119  int rc;
120 
121  /* Check that features are available via CPUID */
122  if ( ( rc = cpuid_supported ( CPUID_FEATURES ) ) != 0 ) {
123  DBGC ( features, "CPUID has no Intel-defined features\n" );
124  return;
125  }
126 
127  /* Get features */
128  cpuid ( CPUID_FEATURES, 0, &discard_a, &discard_b,
129  &features->intel.ecx, &features->intel.edx );
130  DBGC ( features, "CPUID Intel features: %%ecx=%08x, %%edx=%08x\n",
131  features->intel.ecx, features->intel.edx );
132 
133 }
134 
135 /**
136  * Get AMD-defined x86 CPU features
137  *
138  * @v features x86 CPU features to fill in
139  */
140 static void x86_amd_features ( struct x86_features *features ) {
141  uint32_t discard_a;
142  uint32_t discard_b;
143  int rc;
144 
145  /* Check that features are available via CPUID */
146  if ( ( rc = cpuid_supported ( CPUID_AMD_FEATURES ) ) != 0 ) {
147  DBGC ( features, "CPUID has no AMD-defined features\n" );
148  return;
149  }
150 
151  /* Get features */
152  cpuid ( CPUID_AMD_FEATURES, 0, &discard_a, &discard_b,
153  &features->amd.ecx, &features->amd.edx );
154  DBGC ( features, "CPUID AMD features: %%ecx=%08x, %%edx=%08x\n",
155  features->amd.ecx, features->amd.edx );
156 }
157 
158 /**
159  * Get x86 CPU features
160  *
161  * @v features x86 CPU features to fill in
162  */
164 
165  /* Clear all features */
166  memset ( features, 0, sizeof ( *features ) );
167 
168  /* Get Intel-defined features */
170 
171  /* Get AMD-defined features */
173 }
int cpuid_supported(uint32_t function)
Check whether or not CPUID function is supported.
Definition: cpuid.c:75
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
#define EINVAL
Invalid argument.
Definition: errno.h:428
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define CPUID_FEATURES
Get standard features.
Definition: cpuid.h:43
static void x86_amd_features(struct x86_features *features)
Get AMD-defined x86 CPU features.
Definition: cpuid.c:140
#define colour
Colour for debug messages.
Definition: cpuid.c:37
#define CPUID_HYPERVISOR
CPUID hypervisor function.
Definition: cpuid.h:37
Error codes.
#define CPUID_AMD_CHECK_MASK
Extended function existence check mask.
Definition: cpuid.h:64
#define DBGC(...)
Definition: compiler.h:505
void x86_features(struct x86_features *features)
Get x86 CPU features.
Definition: cpuid.c:163
x86 CPU features
Definition: cpuid.h:23
static void x86_intel_features(struct x86_features *features)
Get Intel-defined x86 CPU features.
Definition: cpuid.c:116
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
#define CPUID_FLAG
CPUID support flag.
Definition: cpuid.h:31
static int cpuid_instruction_supported(void)
Check whether or not CPUID instruction is supported.
Definition: cpuid.c:44
x86 CPU feature detection
uint32_t features
Supported features.
Definition: ena.h:16
unsigned int uint32_t
Definition: stdint.h:12
__asm__(".section \".rodata\", \"a\", " PROGBITS "\n\t" "\nprivate_key_data:\n\t" ".size private_key_data, ( . - private_key_data )\n\t" ".equ private_key_len, ( . - private_key_data )\n\t" ".previous\n\t")
#define ENOTTY
Inappropriate I/O control operation.
Definition: errno.h:594
#define CPUID_EXTENDED
CPUID extended function.
Definition: cpuid.h:34
long discard_c
Definition: bigint.h:32
#define CPUID_AMD_FEATURES
Get extended features.
Definition: cpuid.h:67
String functions.
void * memset(void *dest, int character, size_t len) __nonnull