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
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <string.h>
28#include <errno.h>
29#include <ipxe/cpuid.h>
30
31/** @file
32 *
33 * x86 CPU feature detection
34 *
35 */
36
37/** Colour for debug messages */
38#define colour 0x861d
39
40/**
41 * Check whether or not CPUID instruction is supported
42 *
43 * @ret rc Return status code
44 */
45static int cpuid_instruction_supported ( void ) {
46 unsigned long original;
47 unsigned long inverted;
48
49 /* Check for instruction existence via flag modifiability */
50 __asm__ ( "pushf\n\t"
51 "pushf\n\t"
52 "pop %0\n\t"
53 "mov %0,%1\n\t"
54 "xor %2,%1\n\t"
55 "push %1\n\t"
56 "popf\n\t"
57 "pushf\n\t"
58 "pop %1\n\t"
59 "popf\n\t"
60 : "=&r" ( original ), "=&r" ( inverted )
61 : "ir" ( CPUID_FLAG ) );
62 if ( ! ( ( original ^ inverted ) & CPUID_FLAG ) ) {
63 DBGC ( colour, "CPUID instruction is not supported\n" );
64 return -ENOTSUP;
65 }
66
67 return 0;
68}
69
70/**
71 * Check whether or not CPUID function is supported
72 *
73 * @v function CPUID function
74 * @ret rc Return status code
75 */
77 uint32_t max_function;
78 uint32_t discard_b;
80 uint32_t discard_d;
81 int rc;
82
83 /* Check that CPUID instruction is available */
84 if ( ( rc = cpuid_instruction_supported() ) != 0 )
85 return rc;
86
87 /* Find highest supported function number within this family */
88 cpuid ( ( function & ( CPUID_EXTENDED | CPUID_HYPERVISOR ) ), 0,
89 &max_function, &discard_b, &discard_c, &discard_d );
90
91 /* Fail if maximum function number is meaningless (e.g. if we
92 * are attempting to call an extended function on a CPU which
93 * does not support them).
94 */
95 if ( ( max_function & CPUID_AMD_CHECK_MASK ) !=
97 DBGC ( colour, "CPUID invalid maximum function %#08x\n",
98 max_function );
99 return -EINVAL;
100 }
101
102 /* Fail if this function is not supported */
103 if ( function > max_function ) {
104 DBGC ( colour, "CPUID function %#08x not supported\n",
105 function );
106 return -ENOTTY;
107 }
108
109 return 0;
110}
111
112/**
113 * Get Intel-defined x86 CPU features
114 *
115 * @v features x86 CPU features to fill in
116 */
117static void x86_intel_features ( struct x86_features *features ) {
118 uint32_t discard_a;
119 uint32_t discard_b;
120 int rc;
121
122 /* Check that features are available via CPUID */
123 if ( ( rc = cpuid_supported ( CPUID_FEATURES ) ) != 0 ) {
124 DBGC ( features, "CPUID has no Intel-defined features\n" );
125 return;
126 }
127
128 /* Get features */
129 cpuid ( CPUID_FEATURES, 0, &discard_a, &discard_b,
130 &features->intel.ecx, &features->intel.edx );
131 DBGC ( features, "CPUID Intel features: %%ecx=%08x, %%edx=%08x\n",
132 features->intel.ecx, features->intel.edx );
133
134}
135
136/**
137 * Get AMD-defined x86 CPU features
138 *
139 * @v features x86 CPU features to fill in
140 */
141static void x86_amd_features ( struct x86_features *features ) {
142 uint32_t discard_a;
143 uint32_t discard_b;
144 int rc;
145
146 /* Check that features are available via CPUID */
147 if ( ( rc = cpuid_supported ( CPUID_AMD_FEATURES ) ) != 0 ) {
148 DBGC ( features, "CPUID has no AMD-defined features\n" );
149 return;
150 }
151
152 /* Get features */
153 cpuid ( CPUID_AMD_FEATURES, 0, &discard_a, &discard_b,
154 &features->amd.ecx, &features->amd.edx );
155 DBGC ( features, "CPUID AMD features: %%ecx=%08x, %%edx=%08x\n",
156 features->amd.ecx, features->amd.edx );
157}
158
159/**
160 * Get x86 CPU features
161 *
162 * @v features x86 CPU features to fill in
163 */
165
166 /* Clear all features */
167 memset ( features, 0, sizeof ( *features ) );
168
169 /* Get Intel-defined features */
171
172 /* Get AMD-defined features */
174}
#define colour
Colour for debug messages.
Definition acpi.c:42
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned int uint32_t
Definition stdint.h:12
long discard_c
Definition bigint.h:33
static void x86_intel_features(struct x86_features *features)
Get Intel-defined x86 CPU features.
Definition cpuid.c:117
void x86_features(struct x86_features *features)
Get x86 CPU features.
Definition cpuid.c:164
static int cpuid_instruction_supported(void)
Check whether or not CPUID instruction is supported.
Definition cpuid.c:45
static void x86_amd_features(struct x86_features *features)
Get AMD-defined x86 CPU features.
Definition cpuid.c:141
int cpuid_supported(uint32_t function)
Check whether or not CPUID function is supported.
Definition cpuid.c:76
x86 CPU feature detection
#define CPUID_HYPERVISOR
CPUID hypervisor function.
Definition cpuid.h:38
#define CPUID_FLAG
CPUID support flag.
Definition cpuid.h:32
#define CPUID_EXTENDED
CPUID extended function.
Definition cpuid.h:35
#define CPUID_AMD_CHECK_MASK
Extended function existence check mask.
Definition cpuid.h:65
#define CPUID_FEATURES
Get standard features.
Definition cpuid.h:44
#define CPUID_AMD_FEATURES
Get extended features.
Definition cpuid.h:68
uint8_t function
Function.
Definition edd.h:5
uint32_t features
Supported features.
Definition ena.h:5
Error codes.
#define DBGC(...)
Definition compiler.h:505
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define EINVAL
Invalid argument.
Definition errno.h:429
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:595
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
String functions.
void * memset(void *dest, int character, size_t len) __nonnull
__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")
x86 CPU features
Definition cpuid.h:24