Browse Source

[cmdline] Add "cpuid" command

Allow x86 CPU feature flags (such as support for 64-bit mode) to be
checked using the "cpuid" command.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
591541af66

+ 0
- 73
src/arch/i386/core/cpu.c View File

@@ -1,73 +0,0 @@
1
-#include <stdint.h>
2
-#include <string.h>
3
-#include <cpu.h>
4
-
5
-/** @file
6
- *
7
- * CPU identification
8
- *
9
- */
10
-
11
-/**
12
- * Test to see if CPU flag is changeable
13
- *
14
- * @v flag		Flag to test
15
- * @ret can_change	Flag is changeable
16
- */
17
-static inline int flag_is_changeable ( unsigned int flag ) {
18
-	uint32_t f1, f2;
19
-
20
-	__asm__ ( "pushfl\n\t"
21
-		  "pushfl\n\t"
22
-		  "popl %0\n\t"
23
-		  "movl %0,%1\n\t"
24
-		  "xorl %2,%0\n\t"
25
-		  "pushl %0\n\t"
26
-		  "popfl\n\t"
27
-		  "pushfl\n\t"
28
-		  "popl %0\n\t"
29
-		  "popfl\n\t"
30
-		  : "=&r" ( f1 ), "=&r" ( f2 )
31
-		  : "ir" ( flag ) );
32
-
33
-	return ( ( ( f1 ^ f2 ) & flag ) != 0 );
34
-}
35
-
36
-/**
37
- * Get CPU information
38
- *
39
- * @v cpu		CPU information structure to fill in
40
- */
41
-void get_cpuinfo ( struct cpuinfo_x86 *cpu ) {
42
-	unsigned int cpuid_level;
43
-	unsigned int cpuid_extlevel;
44
-	unsigned int discard_1, discard_2, discard_3;
45
-
46
-	memset ( cpu, 0, sizeof ( *cpu ) );
47
-
48
-	/* Check for CPUID instruction */
49
-	if ( ! flag_is_changeable ( X86_EFLAGS_ID ) ) {
50
-		DBG ( "CPUID not supported\n" );
51
-		return;
52
-	}
53
-
54
-	/* Get features, if present */
55
-	cpuid ( 0x00000000, &cpuid_level, &discard_1,
56
-		&discard_2, &discard_3 );
57
-	if ( cpuid_level >= 0x00000001 ) {
58
-		cpuid ( 0x00000001, &discard_1, &discard_2,
59
-			&discard_3, &cpu->features );
60
-	} else {
61
-		DBG ( "CPUID cannot return capabilities\n" );
62
-	}
63
-
64
-	/* Get 64-bit features, if present */
65
-	cpuid ( 0x80000000, &cpuid_extlevel, &discard_1,
66
-		&discard_2, &discard_3 );
67
-	if ( ( cpuid_extlevel & 0xffff0000 ) == 0x80000000 ) {
68
-		if ( cpuid_extlevel >= 0x80000001 ) {
69
-			cpuid ( 0x80000001, &discard_1, &discard_2,
70
-				&discard_3, &cpu->amd_features );
71
-		}
72
-	}
73
-}

+ 0
- 86
src/arch/i386/include/bits/cpu.h View File

@@ -1,86 +0,0 @@
1
-#ifndef I386_BITS_CPU_H
2
-#define I386_BITS_CPU_H
3
-
4
-/* Intel-defined CPU features, CPUID level 0x00000001, word 0 */
5
-#define X86_FEATURE_FPU		0 /* Onboard FPU */
6
-#define X86_FEATURE_VME		1 /* Virtual Mode Extensions */
7
-#define X86_FEATURE_DE		2 /* Debugging Extensions */
8
-#define X86_FEATURE_PSE 	3 /* Page Size Extensions */
9
-#define X86_FEATURE_TSC		4 /* Time Stamp Counter */
10
-#define X86_FEATURE_MSR		5 /* Model-Specific Registers, RDMSR, WRMSR */
11
-#define X86_FEATURE_PAE		6 /* Physical Address Extensions */
12
-#define X86_FEATURE_MCE		7 /* Machine Check Architecture */
13
-#define X86_FEATURE_CX8		8 /* CMPXCHG8 instruction */
14
-#define X86_FEATURE_APIC	9 /* Onboard APIC */
15
-#define X86_FEATURE_SEP		11 /* SYSENTER/SYSEXIT */
16
-#define X86_FEATURE_MTRR	12 /* Memory Type Range Registers */
17
-#define X86_FEATURE_PGE		13 /* Page Global Enable */
18
-#define X86_FEATURE_MCA		14 /* Machine Check Architecture */
19
-#define X86_FEATURE_CMOV	15 /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */
20
-#define X86_FEATURE_PAT		16 /* Page Attribute Table */
21
-#define X86_FEATURE_PSE36	17 /* 36-bit PSEs */
22
-#define X86_FEATURE_PN		18 /* Processor serial number */
23
-#define X86_FEATURE_CLFLSH	19 /* Supports the CLFLUSH instruction */
24
-#define X86_FEATURE_DTES	21 /* Debug Trace Store */
25
-#define X86_FEATURE_ACPI	22 /* ACPI via MSR */
26
-#define X86_FEATURE_MMX		23 /* Multimedia Extensions */
27
-#define X86_FEATURE_FXSR	24 /* FXSAVE and FXRSTOR instructions (fast save and restore */
28
-				          /* of FPU context), and CR4.OSFXSR available */
29
-#define X86_FEATURE_XMM		25 /* Streaming SIMD Extensions */
30
-#define X86_FEATURE_XMM2	26 /* Streaming SIMD Extensions-2 */
31
-#define X86_FEATURE_SELFSNOOP	27 /* CPU self snoop */
32
-#define X86_FEATURE_HT		28 /* Hyper-Threading */
33
-#define X86_FEATURE_ACC		29 /* Automatic clock control */
34
-#define X86_FEATURE_IA64	30 /* IA-64 processor */
35
-
36
-/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */
37
-/* Don't duplicate feature flags which are redundant with Intel! */
38
-#define X86_FEATURE_SYSCALL	11 /* SYSCALL/SYSRET */
39
-#define X86_FEATURE_MMXEXT	22 /* AMD MMX extensions */
40
-#define X86_FEATURE_LM		29 /* Long Mode (x86-64) */
41
-#define X86_FEATURE_3DNOWEXT	30 /* AMD 3DNow! extensions */
42
-#define X86_FEATURE_3DNOW	31 /* 3DNow! */
43
-
44
-/** x86 CPU information */
45
-struct cpuinfo_x86 {
46
-	/** CPU features */
47
-	unsigned int features;
48
-	/** 64-bit CPU features */
49
-	unsigned int amd_features;
50
-};
51
-
52
-/*
53
- * EFLAGS bits
54
- */
55
-#define X86_EFLAGS_CF	0x00000001 /* Carry Flag */
56
-#define X86_EFLAGS_PF	0x00000004 /* Parity Flag */
57
-#define X86_EFLAGS_AF	0x00000010 /* Auxillary carry Flag */
58
-#define X86_EFLAGS_ZF	0x00000040 /* Zero Flag */
59
-#define X86_EFLAGS_SF	0x00000080 /* Sign Flag */
60
-#define X86_EFLAGS_TF	0x00000100 /* Trap Flag */
61
-#define X86_EFLAGS_IF	0x00000200 /* Interrupt Flag */
62
-#define X86_EFLAGS_DF	0x00000400 /* Direction Flag */
63
-#define X86_EFLAGS_OF	0x00000800 /* Overflow Flag */
64
-#define X86_EFLAGS_IOPL	0x00003000 /* IOPL mask */
65
-#define X86_EFLAGS_NT	0x00004000 /* Nested Task */
66
-#define X86_EFLAGS_RF	0x00010000 /* Resume Flag */
67
-#define X86_EFLAGS_VM	0x00020000 /* Virtual Mode */
68
-#define X86_EFLAGS_AC	0x00040000 /* Alignment Check */
69
-#define X86_EFLAGS_VIF	0x00080000 /* Virtual Interrupt Flag */
70
-#define X86_EFLAGS_VIP	0x00100000 /* Virtual Interrupt Pending */
71
-#define X86_EFLAGS_ID	0x00200000 /* CPUID detection flag */
72
-
73
-/*
74
- * Generic CPUID function
75
- */
76
-static inline __attribute__ (( always_inline )) void
77
-cpuid ( int op, unsigned int *eax, unsigned int *ebx,
78
-	unsigned int *ecx, unsigned int *edx ) {
79
-	__asm__ ( "cpuid" :
80
-		  "=a" ( *eax ), "=b" ( *ebx ), "=c" ( *ecx ), "=d" ( *edx )
81
-		: "0" ( op ) );
82
-}
83
-
84
-extern void get_cpuinfo ( struct cpuinfo_x86 *cpu );
85
-
86
-#endif /* I386_BITS_CPU_H */

+ 1
- 0
src/arch/x86/Makefile View File

@@ -7,6 +7,7 @@ INCDIRS		+= arch/x86/include
7 7
 SRCDIRS		+= arch/x86/core
8 8
 SRCDIRS		+= arch/x86/interface/efi
9 9
 SRCDIRS		+= arch/x86/prefix
10
+SRCDIRS		+= arch/x86/hci/commands
10 11
 
11 12
 # breaks building some of the linux-related objects
12 13
 CFLAGS		+= -Ulinux

+ 154
- 0
src/arch/x86/core/cpuid.c View File

@@ -0,0 +1,154 @@
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., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+FILE_LICENCE ( GPL2_OR_LATER );
20
+
21
+#include <string.h>
22
+#include <ipxe/cpuid.h>
23
+
24
+/** @file
25
+ *
26
+ * x86 CPU feature detection
27
+ *
28
+ */
29
+
30
+/**
31
+ * Check whether or not CPUID instruction is supported
32
+ *
33
+ * @ret is_supported	CPUID instruction is supported
34
+ */
35
+static int cpuid_is_supported ( void ) {
36
+	unsigned long original;
37
+	unsigned long inverted;
38
+
39
+	__asm__ ( "pushf\n\t"
40
+		  "pushf\n\t"
41
+		  "pop %0\n\t"
42
+		  "mov %0,%1\n\t"
43
+		  "xor %2,%1\n\t"
44
+		  "push %1\n\t"
45
+		  "popf\n\t"
46
+		  "pushf\n\t"
47
+		  "pop %1\n\t"
48
+		  "popf\n\t"
49
+		  : "=&r" ( original ), "=&r" ( inverted )
50
+		  : "ir" ( CPUID_FLAG ) );
51
+	return ( ( original ^ inverted ) & CPUID_FLAG );
52
+}
53
+
54
+/**
55
+ * Issue CPUID instruction
56
+ *
57
+ * @v operation		CPUID operation
58
+ * @v eax		Output via %eax
59
+ * @v ebx		Output via %ebx
60
+ * @v ecx		Output via %ecx
61
+ * @v edx		Output via %edx
62
+ */
63
+static inline __attribute__ (( always_inline )) void
64
+cpuid ( uint32_t operation, uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
65
+	uint32_t *edx ) {
66
+
67
+	__asm__ ( "cpuid"
68
+		  : "=a" ( *eax ), "=b" ( *ebx ), "=c" ( *ecx ), "=d" ( *edx )
69
+		  : "0" ( operation ) );
70
+}
71
+
72
+/**
73
+ * Get Intel-defined x86 CPU features
74
+ *
75
+ * @v features		x86 CPU features to fill in
76
+ */
77
+static void x86_intel_features ( struct x86_features *features ) {
78
+	uint32_t max_level;
79
+	uint32_t discard_a;
80
+	uint32_t discard_b;
81
+	uint32_t discard_c;
82
+	uint32_t discard_d;
83
+
84
+	/* Check that features are available via CPUID */
85
+	cpuid ( CPUID_VENDOR_ID, &max_level, &discard_b, &discard_c,
86
+		&discard_d );
87
+	if ( max_level < CPUID_FEATURES ) {
88
+		DBGC ( features, "CPUID has no Intel-defined features (max "
89
+		       "level %08x)\n", max_level );
90
+		return;
91
+	}
92
+
93
+	/* Get features */
94
+	cpuid ( CPUID_FEATURES, &discard_a, &discard_b,
95
+		&features->intel.ecx, &features->intel.edx );
96
+	DBGC ( features, "CPUID Intel features: %%ecx=%08x, %%edx=%08x\n",
97
+	       features->intel.ecx, features->intel.edx );
98
+
99
+}
100
+
101
+/**
102
+ * Get AMD-defined x86 CPU features
103
+ *
104
+ * @v features		x86 CPU features to fill in
105
+ */
106
+static void x86_amd_features ( struct x86_features *features ) {
107
+	uint32_t max_level;
108
+	uint32_t discard_a;
109
+	uint32_t discard_b;
110
+	uint32_t discard_c;
111
+	uint32_t discard_d;
112
+
113
+	/* Check that features are available via CPUID */
114
+	cpuid ( CPUID_AMD_MAX_FN, &max_level, &discard_b, &discard_c,
115
+		&discard_d );
116
+	if ( ( max_level & CPUID_AMD_CHECK_MASK ) != CPUID_AMD_CHECK ) {
117
+		DBGC ( features, "CPUID has no extended functions\n" );
118
+		return;
119
+	}
120
+	if ( max_level < CPUID_AMD_FEATURES ) {
121
+		DBGC ( features, "CPUID has no AMD-defined features (max "
122
+		       "level %08x)\n", max_level );
123
+		return;
124
+	}
125
+
126
+	/* Get features */
127
+	cpuid ( CPUID_AMD_FEATURES, &discard_a, &discard_b,
128
+		&features->amd.ecx, &features->amd.edx );
129
+	DBGC ( features, "CPUID AMD features: %%ecx=%08x, %%edx=%08x\n",
130
+	       features->amd.ecx, features->amd.edx );
131
+}
132
+
133
+/**
134
+ * Get x86 CPU features
135
+ *
136
+ * @v features		x86 CPU features to fill in
137
+ */
138
+void x86_features ( struct x86_features *features ) {
139
+
140
+	/* Clear all features */
141
+	memset ( features, 0, sizeof ( *features ) );
142
+
143
+	/* Check that CPUID instruction is available */
144
+	if ( ! cpuid_is_supported() ) {
145
+		DBGC ( features, "CPUID instruction is not supported\n" );
146
+		return;
147
+	}
148
+
149
+	/* Get Intel-defined features */
150
+	x86_intel_features ( features );
151
+
152
+	/* Get AMD-defined features */
153
+	x86_amd_features ( features );
154
+}

+ 94
- 0
src/arch/x86/hci/commands/cpuid_cmd.c View File

@@ -0,0 +1,94 @@
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., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+FILE_LICENCE ( GPL2_OR_LATER );
20
+
21
+#include <stdint.h>
22
+#include <stdio.h>
23
+#include <errno.h>
24
+#include <getopt.h>
25
+#include <ipxe/cpuid.h>
26
+#include <ipxe/command.h>
27
+#include <ipxe/parseopt.h>
28
+
29
+/** @file
30
+ *
31
+ * x86 CPU feature detection command
32
+ *
33
+ */
34
+
35
+/** "cpuid" options */
36
+struct cpuid_options {
37
+	/** Check AMD-defined features (%eax=0x80000001) */
38
+	int amd;
39
+	/** Check features defined via %ecx */
40
+	int ecx;
41
+};
42
+
43
+/** "cpuid" option list */
44
+static struct option_descriptor cpuid_opts[] = {
45
+	OPTION_DESC ( "amd", 'a', no_argument,
46
+		      struct cpuid_options, amd, parse_flag ),
47
+	OPTION_DESC ( "ecx", 'c', no_argument,
48
+		      struct cpuid_options, ecx, parse_flag ),
49
+};
50
+
51
+/** "cpuid" command descriptor */
52
+static struct command_descriptor cpuid_cmd =
53
+	COMMAND_DESC ( struct cpuid_options, cpuid_opts, 1, 1,
54
+		       "[--amd] [--ecx] <bit>" );
55
+
56
+/**
57
+ * The "cpuid" command
58
+ *
59
+ * @v argc		Argument count
60
+ * @v argv		Argument list
61
+ * @ret rc		Return status code
62
+ */
63
+static int cpuid_exec ( int argc, char **argv ) {
64
+	struct cpuid_options opts;
65
+	struct x86_features features;
66
+	struct x86_feature_registers *feature_regs;
67
+	uint32_t feature_reg;
68
+	unsigned int bit;
69
+	int rc;
70
+
71
+	/* Parse options */
72
+	if ( ( rc = parse_options ( argc, argv, &cpuid_cmd, &opts ) ) != 0 )
73
+		return rc;
74
+
75
+	/* Parse bit number */
76
+	if ( ( rc = parse_integer ( argv[optind], &bit ) ) != 0 )
77
+		return rc;
78
+
79
+	/* Get CPU features */
80
+	x86_features ( &features );
81
+
82
+	/* Extract relevant feature register */
83
+	feature_regs = ( opts.amd ? &features.amd : &features.intel );
84
+	feature_reg = ( opts.ecx ? feature_regs->ecx : feature_regs->edx );
85
+
86
+	/* Check presence of specified feature */
87
+	return ( ( feature_reg & ( 1 << bit ) ) ? 0 : -ENOENT );
88
+}
89
+
90
+/** x86 CPU feature detection command */
91
+struct command cpuid_command __command = {
92
+	.name = "cpuid",
93
+	.exec = cpuid_exec,
94
+};

+ 4
- 2
src/arch/x86/include/bits/errfile.h View File

@@ -38,8 +38,10 @@ FILE_LICENCE ( GPL2_OR_LATER );
38 38
 #define ERRFILE_undionly	 ( ERRFILE_ARCH | ERRFILE_NET | 0x00030000 )
39 39
 #define ERRFILE_undirom		 ( ERRFILE_ARCH | ERRFILE_NET | 0x00040000 )
40 40
 
41
-#define ERRFILE_timer_rdtsc    ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00000000 )
42
-#define ERRFILE_timer_bios     ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00010000 )
41
+#define ERRFILE_timer_rdtsc   ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00000000 )
42
+#define ERRFILE_timer_bios    ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00010000 )
43
+
44
+#define ERRFILE_cpuid_cmd      ( ERRFILE_ARCH | ERRFILE_OTHER | 0x00000000 )
43 45
 
44 46
 /** @} */
45 47
 

+ 53
- 0
src/arch/x86/include/ipxe/cpuid.h View File

@@ -0,0 +1,53 @@
1
+#ifndef _IPXE_CPUID_H
2
+#define _IPXE_CPUID_H
3
+
4
+/** @file
5
+ *
6
+ * x86 CPU feature detection
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER );
11
+
12
+#include <stdint.h>
13
+
14
+/** An x86 CPU feature register set */
15
+struct x86_feature_registers {
16
+	/** Features returned via %ecx */
17
+	uint32_t ecx;
18
+	/** Features returned via %edx */
19
+	uint32_t edx;
20
+};
21
+
22
+/** x86 CPU features */
23
+struct x86_features {
24
+	/** Intel-defined features (%eax=0x00000001) */
25
+	struct x86_feature_registers intel;
26
+	/** AMD-defined features (%eax=0x80000001) */
27
+	struct x86_feature_registers amd;
28
+};
29
+
30
+/** CPUID support flag */
31
+#define CPUID_FLAG 0x00200000UL
32
+
33
+/** Get vendor ID and largest standard function */
34
+#define CPUID_VENDOR_ID 0x00000000UL
35
+
36
+/** Get standard features */
37
+#define CPUID_FEATURES 0x00000001UL
38
+
39
+/** Get largest extended function */
40
+#define CPUID_AMD_MAX_FN 0x80000000UL
41
+
42
+/** Extended function existence check */
43
+#define CPUID_AMD_CHECK 0x80000000UL
44
+
45
+/** Extended function existence check mask */
46
+#define CPUID_AMD_CHECK_MASK 0xffff0000UL
47
+
48
+/** Get extended features */
49
+#define CPUID_AMD_FEATURES 0x80000001UL
50
+
51
+extern void x86_features ( struct x86_features *features );
52
+
53
+#endif /* _IPXE_CPUID_H */

+ 3
- 0
src/config/config.c View File

@@ -238,6 +238,9 @@ REQUIRE_OBJECT ( vlan_cmd );
238 238
 #ifdef REBOOT_CMD
239 239
 REQUIRE_OBJECT ( reboot_cmd );
240 240
 #endif
241
+#ifdef CPUID_CMD
242
+REQUIRE_OBJECT ( cpuid_cmd );
243
+#endif
241 244
 
242 245
 /*
243 246
  * Drag in miscellaneous objects

+ 1
- 0
src/config/defaults/pcbios.h View File

@@ -36,5 +36,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
36 36
 #define	SANBOOT_PROTO_FCP	/* Fibre Channel protocol */
37 37
 
38 38
 #define	REBOOT_CMD		/* Reboot command */
39
+#define	CPUID_CMD		/* x86 CPU feature detection command */
39 40
 
40 41
 #endif /* CONFIG_DEFAULTS_PCBIOS_H */

Loading…
Cancel
Save