+++ /dev/null
-#include <stdint.h>
-#include <string.h>
-#include <cpu.h>
-
-/** @file
- *
- * CPU identification
- *
- */
-
-/**
- * Test to see if CPU flag is changeable
- *
- * @v flag Flag to test
- * @ret can_change Flag is changeable
- */
-static inline int flag_is_changeable ( unsigned int flag ) {
- uint32_t f1, f2;
-
- __asm__ ( "pushfl\n\t"
- "pushfl\n\t"
- "popl %0\n\t"
- "movl %0,%1\n\t"
- "xorl %2,%0\n\t"
- "pushl %0\n\t"
- "popfl\n\t"
- "pushfl\n\t"
- "popl %0\n\t"
- "popfl\n\t"
- : "=&r" ( f1 ), "=&r" ( f2 )
- : "ir" ( flag ) );
-
- return ( ( ( f1 ^ f2 ) & flag ) != 0 );
-}
-
-/**
- * Get CPU information
- *
- * @v cpu CPU information structure to fill in
- */
-void get_cpuinfo ( struct cpuinfo_x86 *cpu ) {
- unsigned int cpuid_level;
- unsigned int cpuid_extlevel;
- unsigned int discard_1, discard_2, discard_3;
-
- memset ( cpu, 0, sizeof ( *cpu ) );
-
- /* Check for CPUID instruction */
- if ( ! flag_is_changeable ( X86_EFLAGS_ID ) ) {
- DBG ( "CPUID not supported\n" );
- return;
- }
-
- /* Get features, if present */
- cpuid ( 0x00000000, &cpuid_level, &discard_1,
- &discard_2, &discard_3 );
- if ( cpuid_level >= 0x00000001 ) {
- cpuid ( 0x00000001, &discard_1, &discard_2,
- &discard_3, &cpu->features );
- } else {
- DBG ( "CPUID cannot return capabilities\n" );
- }
-
- /* Get 64-bit features, if present */
- cpuid ( 0x80000000, &cpuid_extlevel, &discard_1,
- &discard_2, &discard_3 );
- if ( ( cpuid_extlevel & 0xffff0000 ) == 0x80000000 ) {
- if ( cpuid_extlevel >= 0x80000001 ) {
- cpuid ( 0x80000001, &discard_1, &discard_2,
- &discard_3, &cpu->amd_features );
- }
- }
-}
+++ /dev/null
-#ifndef I386_BITS_CPU_H
-#define I386_BITS_CPU_H
-
-/* Intel-defined CPU features, CPUID level 0x00000001, word 0 */
-#define X86_FEATURE_FPU 0 /* Onboard FPU */
-#define X86_FEATURE_VME 1 /* Virtual Mode Extensions */
-#define X86_FEATURE_DE 2 /* Debugging Extensions */
-#define X86_FEATURE_PSE 3 /* Page Size Extensions */
-#define X86_FEATURE_TSC 4 /* Time Stamp Counter */
-#define X86_FEATURE_MSR 5 /* Model-Specific Registers, RDMSR, WRMSR */
-#define X86_FEATURE_PAE 6 /* Physical Address Extensions */
-#define X86_FEATURE_MCE 7 /* Machine Check Architecture */
-#define X86_FEATURE_CX8 8 /* CMPXCHG8 instruction */
-#define X86_FEATURE_APIC 9 /* Onboard APIC */
-#define X86_FEATURE_SEP 11 /* SYSENTER/SYSEXIT */
-#define X86_FEATURE_MTRR 12 /* Memory Type Range Registers */
-#define X86_FEATURE_PGE 13 /* Page Global Enable */
-#define X86_FEATURE_MCA 14 /* Machine Check Architecture */
-#define X86_FEATURE_CMOV 15 /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */
-#define X86_FEATURE_PAT 16 /* Page Attribute Table */
-#define X86_FEATURE_PSE36 17 /* 36-bit PSEs */
-#define X86_FEATURE_PN 18 /* Processor serial number */
-#define X86_FEATURE_CLFLSH 19 /* Supports the CLFLUSH instruction */
-#define X86_FEATURE_DTES 21 /* Debug Trace Store */
-#define X86_FEATURE_ACPI 22 /* ACPI via MSR */
-#define X86_FEATURE_MMX 23 /* Multimedia Extensions */
-#define X86_FEATURE_FXSR 24 /* FXSAVE and FXRSTOR instructions (fast save and restore */
- /* of FPU context), and CR4.OSFXSR available */
-#define X86_FEATURE_XMM 25 /* Streaming SIMD Extensions */
-#define X86_FEATURE_XMM2 26 /* Streaming SIMD Extensions-2 */
-#define X86_FEATURE_SELFSNOOP 27 /* CPU self snoop */
-#define X86_FEATURE_HT 28 /* Hyper-Threading */
-#define X86_FEATURE_ACC 29 /* Automatic clock control */
-#define X86_FEATURE_IA64 30 /* IA-64 processor */
-
-/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */
-/* Don't duplicate feature flags which are redundant with Intel! */
-#define X86_FEATURE_SYSCALL 11 /* SYSCALL/SYSRET */
-#define X86_FEATURE_MMXEXT 22 /* AMD MMX extensions */
-#define X86_FEATURE_LM 29 /* Long Mode (x86-64) */
-#define X86_FEATURE_3DNOWEXT 30 /* AMD 3DNow! extensions */
-#define X86_FEATURE_3DNOW 31 /* 3DNow! */
-
-/** x86 CPU information */
-struct cpuinfo_x86 {
- /** CPU features */
- unsigned int features;
- /** 64-bit CPU features */
- unsigned int amd_features;
-};
-
-/*
- * EFLAGS bits
- */
-#define X86_EFLAGS_CF 0x00000001 /* Carry Flag */
-#define X86_EFLAGS_PF 0x00000004 /* Parity Flag */
-#define X86_EFLAGS_AF 0x00000010 /* Auxillary carry Flag */
-#define X86_EFLAGS_ZF 0x00000040 /* Zero Flag */
-#define X86_EFLAGS_SF 0x00000080 /* Sign Flag */
-#define X86_EFLAGS_TF 0x00000100 /* Trap Flag */
-#define X86_EFLAGS_IF 0x00000200 /* Interrupt Flag */
-#define X86_EFLAGS_DF 0x00000400 /* Direction Flag */
-#define X86_EFLAGS_OF 0x00000800 /* Overflow Flag */
-#define X86_EFLAGS_IOPL 0x00003000 /* IOPL mask */
-#define X86_EFLAGS_NT 0x00004000 /* Nested Task */
-#define X86_EFLAGS_RF 0x00010000 /* Resume Flag */
-#define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */
-#define X86_EFLAGS_AC 0x00040000 /* Alignment Check */
-#define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */
-#define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */
-#define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */
-
-/*
- * Generic CPUID function
- */
-static inline __attribute__ (( always_inline )) void
-cpuid ( int op, unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx ) {
- __asm__ ( "cpuid" :
- "=a" ( *eax ), "=b" ( *ebx ), "=c" ( *ecx ), "=d" ( *edx )
- : "0" ( op ) );
-}
-
-extern void get_cpuinfo ( struct cpuinfo_x86 *cpu );
-
-#endif /* I386_BITS_CPU_H */
SRCDIRS += arch/x86/core
SRCDIRS += arch/x86/interface/efi
SRCDIRS += arch/x86/prefix
+SRCDIRS += arch/x86/hci/commands
# breaks building some of the linux-related objects
CFLAGS += -Ulinux
--- /dev/null
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <ipxe/cpuid.h>
+
+/** @file
+ *
+ * x86 CPU feature detection
+ *
+ */
+
+/**
+ * Check whether or not CPUID instruction is supported
+ *
+ * @ret is_supported CPUID instruction is supported
+ */
+static int cpuid_is_supported ( void ) {
+ unsigned long original;
+ unsigned long inverted;
+
+ __asm__ ( "pushf\n\t"
+ "pushf\n\t"
+ "pop %0\n\t"
+ "mov %0,%1\n\t"
+ "xor %2,%1\n\t"
+ "push %1\n\t"
+ "popf\n\t"
+ "pushf\n\t"
+ "pop %1\n\t"
+ "popf\n\t"
+ : "=&r" ( original ), "=&r" ( inverted )
+ : "ir" ( CPUID_FLAG ) );
+ return ( ( original ^ inverted ) & CPUID_FLAG );
+}
+
+/**
+ * Issue CPUID instruction
+ *
+ * @v operation CPUID operation
+ * @v eax Output via %eax
+ * @v ebx Output via %ebx
+ * @v ecx Output via %ecx
+ * @v edx Output via %edx
+ */
+static inline __attribute__ (( always_inline )) void
+cpuid ( uint32_t operation, uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
+ uint32_t *edx ) {
+
+ __asm__ ( "cpuid"
+ : "=a" ( *eax ), "=b" ( *ebx ), "=c" ( *ecx ), "=d" ( *edx )
+ : "0" ( operation ) );
+}
+
+/**
+ * Get Intel-defined x86 CPU features
+ *
+ * @v features x86 CPU features to fill in
+ */
+static void x86_intel_features ( struct x86_features *features ) {
+ uint32_t max_level;
+ uint32_t discard_a;
+ uint32_t discard_b;
+ uint32_t discard_c;
+ uint32_t discard_d;
+
+ /* Check that features are available via CPUID */
+ cpuid ( CPUID_VENDOR_ID, &max_level, &discard_b, &discard_c,
+ &discard_d );
+ if ( max_level < CPUID_FEATURES ) {
+ DBGC ( features, "CPUID has no Intel-defined features (max "
+ "level %08x)\n", max_level );
+ return;
+ }
+
+ /* Get features */
+ cpuid ( CPUID_FEATURES, &discard_a, &discard_b,
+ &features->intel.ecx, &features->intel.edx );
+ DBGC ( features, "CPUID Intel features: %%ecx=%08x, %%edx=%08x\n",
+ features->intel.ecx, features->intel.edx );
+
+}
+
+/**
+ * Get AMD-defined x86 CPU features
+ *
+ * @v features x86 CPU features to fill in
+ */
+static void x86_amd_features ( struct x86_features *features ) {
+ uint32_t max_level;
+ uint32_t discard_a;
+ uint32_t discard_b;
+ uint32_t discard_c;
+ uint32_t discard_d;
+
+ /* Check that features are available via CPUID */
+ cpuid ( CPUID_AMD_MAX_FN, &max_level, &discard_b, &discard_c,
+ &discard_d );
+ if ( ( max_level & CPUID_AMD_CHECK_MASK ) != CPUID_AMD_CHECK ) {
+ DBGC ( features, "CPUID has no extended functions\n" );
+ return;
+ }
+ if ( max_level < CPUID_AMD_FEATURES ) {
+ DBGC ( features, "CPUID has no AMD-defined features (max "
+ "level %08x)\n", max_level );
+ return;
+ }
+
+ /* Get features */
+ cpuid ( CPUID_AMD_FEATURES, &discard_a, &discard_b,
+ &features->amd.ecx, &features->amd.edx );
+ DBGC ( features, "CPUID AMD features: %%ecx=%08x, %%edx=%08x\n",
+ features->amd.ecx, features->amd.edx );
+}
+
+/**
+ * Get x86 CPU features
+ *
+ * @v features x86 CPU features to fill in
+ */
+void x86_features ( struct x86_features *features ) {
+
+ /* Clear all features */
+ memset ( features, 0, sizeof ( *features ) );
+
+ /* Check that CPUID instruction is available */
+ if ( ! cpuid_is_supported() ) {
+ DBGC ( features, "CPUID instruction is not supported\n" );
+ return;
+ }
+
+ /* Get Intel-defined features */
+ x86_intel_features ( features );
+
+ /* Get AMD-defined features */
+ x86_amd_features ( features );
+}
--- /dev/null
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stdio.h>
+#include <errno.h>
+#include <getopt.h>
+#include <ipxe/cpuid.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+
+/** @file
+ *
+ * x86 CPU feature detection command
+ *
+ */
+
+/** "cpuid" options */
+struct cpuid_options {
+ /** Check AMD-defined features (%eax=0x80000001) */
+ int amd;
+ /** Check features defined via %ecx */
+ int ecx;
+};
+
+/** "cpuid" option list */
+static struct option_descriptor cpuid_opts[] = {
+ OPTION_DESC ( "amd", 'a', no_argument,
+ struct cpuid_options, amd, parse_flag ),
+ OPTION_DESC ( "ecx", 'c', no_argument,
+ struct cpuid_options, ecx, parse_flag ),
+};
+
+/** "cpuid" command descriptor */
+static struct command_descriptor cpuid_cmd =
+ COMMAND_DESC ( struct cpuid_options, cpuid_opts, 1, 1,
+ "[--amd] [--ecx] <bit>" );
+
+/**
+ * The "cpuid" command
+ *
+ * @v argc Argument count
+ * @v argv Argument list
+ * @ret rc Return status code
+ */
+static int cpuid_exec ( int argc, char **argv ) {
+ struct cpuid_options opts;
+ struct x86_features features;
+ struct x86_feature_registers *feature_regs;
+ uint32_t feature_reg;
+ unsigned int bit;
+ int rc;
+
+ /* Parse options */
+ if ( ( rc = parse_options ( argc, argv, &cpuid_cmd, &opts ) ) != 0 )
+ return rc;
+
+ /* Parse bit number */
+ if ( ( rc = parse_integer ( argv[optind], &bit ) ) != 0 )
+ return rc;
+
+ /* Get CPU features */
+ x86_features ( &features );
+
+ /* Extract relevant feature register */
+ feature_regs = ( opts.amd ? &features.amd : &features.intel );
+ feature_reg = ( opts.ecx ? feature_regs->ecx : feature_regs->edx );
+
+ /* Check presence of specified feature */
+ return ( ( feature_reg & ( 1 << bit ) ) ? 0 : -ENOENT );
+}
+
+/** x86 CPU feature detection command */
+struct command cpuid_command __command = {
+ .name = "cpuid",
+ .exec = cpuid_exec,
+};
#define ERRFILE_undionly ( ERRFILE_ARCH | ERRFILE_NET | 0x00030000 )
#define ERRFILE_undirom ( ERRFILE_ARCH | ERRFILE_NET | 0x00040000 )
-#define ERRFILE_timer_rdtsc ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00000000 )
-#define ERRFILE_timer_bios ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00010000 )
+#define ERRFILE_timer_rdtsc ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00000000 )
+#define ERRFILE_timer_bios ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00010000 )
+
+#define ERRFILE_cpuid_cmd ( ERRFILE_ARCH | ERRFILE_OTHER | 0x00000000 )
/** @} */
--- /dev/null
+#ifndef _IPXE_CPUID_H
+#define _IPXE_CPUID_H
+
+/** @file
+ *
+ * x86 CPU feature detection
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+
+/** An x86 CPU feature register set */
+struct x86_feature_registers {
+ /** Features returned via %ecx */
+ uint32_t ecx;
+ /** Features returned via %edx */
+ uint32_t edx;
+};
+
+/** x86 CPU features */
+struct x86_features {
+ /** Intel-defined features (%eax=0x00000001) */
+ struct x86_feature_registers intel;
+ /** AMD-defined features (%eax=0x80000001) */
+ struct x86_feature_registers amd;
+};
+
+/** CPUID support flag */
+#define CPUID_FLAG 0x00200000UL
+
+/** Get vendor ID and largest standard function */
+#define CPUID_VENDOR_ID 0x00000000UL
+
+/** Get standard features */
+#define CPUID_FEATURES 0x00000001UL
+
+/** Get largest extended function */
+#define CPUID_AMD_MAX_FN 0x80000000UL
+
+/** Extended function existence check */
+#define CPUID_AMD_CHECK 0x80000000UL
+
+/** Extended function existence check mask */
+#define CPUID_AMD_CHECK_MASK 0xffff0000UL
+
+/** Get extended features */
+#define CPUID_AMD_FEATURES 0x80000001UL
+
+extern void x86_features ( struct x86_features *features );
+
+#endif /* _IPXE_CPUID_H */
#ifdef REBOOT_CMD
REQUIRE_OBJECT ( reboot_cmd );
#endif
+#ifdef CPUID_CMD
+REQUIRE_OBJECT ( cpuid_cmd );
+#endif
/*
* Drag in miscellaneous objects
#define SANBOOT_PROTO_FCP /* Fibre Channel protocol */
#define REBOOT_CMD /* Reboot command */
+#define CPUID_CMD /* x86 CPU feature detection command */
#endif /* CONFIG_DEFAULTS_PCBIOS_H */