Shrink cpu.c and render it useful for our purposes.
authorMichael Brown <mcb30@etherboot.org>
Sat, 14 Jul 2007 18:12:13 +0000 (19:12 +0100)
committerMichael Brown <mcb30@etherboot.org>
Sat, 14 Jul 2007 18:12:13 +0000 (19:12 +0100)
src/arch/i386/core/cpu.c
src/arch/i386/include/bits/cpu.h

index cbef6a1..c24fa4e 100644 (file)
@@ -1,88 +1,73 @@
-#ifdef CONFIG_X86_64
-#include "stdint.h"
-#include "string.h"
-#include "bits/cpu.h"
-#include <gpxe/init.h>
+#include <stdint.h>
+#include <string.h>
+#include <cpu.h>
 
+/** @file
+ *
+ * CPU identification
+ *
+ */
 
-/* Standard macro to see if a specific flag is changeable */
-static inline int flag_is_changeable_p(uint32_t flag)
-{
+/**
+ * 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));
+       __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;
+       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;
 
-/* Probe for the CPUID instruction */
-static inline int have_cpuid_p(void)
-{
-       return flag_is_changeable_p(X86_EFLAGS_ID);
-}
-
-static void identify_cpu(struct cpuinfo_x86 *c)
-{
-       unsigned xlvl;
-
-       c->cpuid_level = -1;            /* CPUID not detected */
-       c->x86_model = c->x86_mask = 0; /* So far unknown... */
-       c->x86_vendor_id[0] = '\0';     /* Unset */
-       memset(&c->x86_capability, 0, sizeof c->x86_capability);
-       
-       if (!have_cpuid_p()) {
-               /* CPU doesn'thave CPUID */
+       memset ( cpu, 0, sizeof ( *cpu ) );
 
-               /* If there are any capabilities, they'r vendor-specific */
-               /* enable_cpuid() would have set c->x86 for us. */
+       /* Check for CPUID instruction */
+       if ( ! flag_is_changeable ( X86_EFLAGS_ID ) ) {
+               DBG ( "CPUID not supported\n" );
+               return;
        }
-       else {
-               /* CPU does have CPUID */
 
-               /* Get vendor name */
-               cpuid(0x00000000, &c->cpuid_level,
-                     (int *)&c->x86_vendor_id[0],
-                     (int *)&c->x86_vendor_id[8],
-                     (int *)&c->x86_vendor_id[4]);
-               
-               /* Initialize the standard set of capabilities */
-               /* Note that the vendor-specific code below might override */
-
-               /* Intel-defined flags: level 0x00000001 */
-               if ( c->cpuid_level >= 0x00000001 ) {
-                       unsigned tfms, junk;
-                       cpuid(0x00000001, &tfms, &junk, &junk,
-                             &c->x86_capability[0]);
-                       c->x86 = (tfms >> 8) & 15;
-                       c->x86_model = (tfms >> 4) & 15;
-                       c->x86_mask = tfms & 15;
-               }
+       /* 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" );
+       }
 
-               /* AMD-defined flags: level 0x80000001 */
-               xlvl = cpuid_eax(0x80000000);
-               if ( (xlvl & 0xffff0000) == 0x80000000 ) {
-                       if ( xlvl >= 0x80000001 )
-                               c->x86_capability[1] = cpuid_edx(0x80000001);
+       /* 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 );
                }
        }
 }
-
-struct cpuinfo_x86 cpu_info;
-void cpu_setup(void)
-{
-       identify_cpu(&cpu_info);
-}
-
-#endif /* CONFIG_X86_64 */
index 2e9b27b..83339dd 100644 (file)
@@ -1,88 +1,54 @@
 #ifndef I386_BITS_CPU_H
 #define I386_BITS_CPU_H
 
-
-/* Sample usage: CPU_FEATURE_P(cpu.x86_capability, FPU) */
-#define CPU_FEATURE_P(CAP, FEATURE) \
-       (!!(CAP[(X86_FEATURE_##FEATURE)/32] & ((X86_FEATURE_##FEATURE) & 0x1f)))
-
-#define NCAPINTS       4       /* Currently we have 4 32-bit words worth of info */
-
 /* Intel-defined CPU features, CPUID level 0x00000001, word 0 */
-#define X86_FEATURE_FPU                (0*32+ 0) /* Onboard FPU */
-#define X86_FEATURE_VME                (0*32+ 1) /* Virtual Mode Extensions */
-#define X86_FEATURE_DE         (0*32+ 2) /* Debugging Extensions */
-#define X86_FEATURE_PSE        (0*32+ 3) /* Page Size Extensions */
-#define X86_FEATURE_TSC                (0*32+ 4) /* Time Stamp Counter */
-#define X86_FEATURE_MSR                (0*32+ 5) /* Model-Specific Registers, RDMSR, WRMSR */
-#define X86_FEATURE_PAE                (0*32+ 6) /* Physical Address Extensions */
-#define X86_FEATURE_MCE                (0*32+ 7) /* Machine Check Architecture */
-#define X86_FEATURE_CX8                (0*32+ 8) /* CMPXCHG8 instruction */
-#define X86_FEATURE_APIC       (0*32+ 9) /* Onboard APIC */
-#define X86_FEATURE_SEP                (0*32+11) /* SYSENTER/SYSEXIT */
-#define X86_FEATURE_MTRR       (0*32+12) /* Memory Type Range Registers */
-#define X86_FEATURE_PGE                (0*32+13) /* Page Global Enable */
-#define X86_FEATURE_MCA                (0*32+14) /* Machine Check Architecture */
-#define X86_FEATURE_CMOV       (0*32+15) /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */
-#define X86_FEATURE_PAT                (0*32+16) /* Page Attribute Table */
-#define X86_FEATURE_PSE36      (0*32+17) /* 36-bit PSEs */
-#define X86_FEATURE_PN         (0*32+18) /* Processor serial number */
-#define X86_FEATURE_CLFLSH     (0*32+19) /* Supports the CLFLUSH instruction */
-#define X86_FEATURE_DTES       (0*32+21) /* Debug Trace Store */
-#define X86_FEATURE_ACPI       (0*32+22) /* ACPI via MSR */
-#define X86_FEATURE_MMX                (0*32+23) /* Multimedia Extensions */
-#define X86_FEATURE_FXSR       (0*32+24) /* FXSAVE and FXRSTOR instructions (fast save and restore */
+#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                (0*32+25) /* Streaming SIMD Extensions */
-#define X86_FEATURE_XMM2       (0*32+26) /* Streaming SIMD Extensions-2 */
-#define X86_FEATURE_SELFSNOOP  (0*32+27) /* CPU self snoop */
-#define X86_FEATURE_HT         (0*32+28) /* Hyper-Threading */
-#define X86_FEATURE_ACC                (0*32+29) /* Automatic clock control */
-#define X86_FEATURE_IA64       (0*32+30) /* IA-64 processor */
+#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    (1*32+11) /* SYSCALL/SYSRET */
-#define X86_FEATURE_MMXEXT     (1*32+22) /* AMD MMX extensions */
-#define X86_FEATURE_LM         (1*32+29) /* Long Mode (x86-64) */
-#define X86_FEATURE_3DNOWEXT   (1*32+30) /* AMD 3DNow! extensions */
-#define X86_FEATURE_3DNOW      (1*32+31) /* 3DNow! */
-
-/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */
-#define X86_FEATURE_RECOVERY   (2*32+ 0) /* CPU in recovery mode */
-#define X86_FEATURE_LONGRUN    (2*32+ 1) /* Longrun power control */
-#define X86_FEATURE_LRTI       (2*32+ 3) /* LongRun table interface */
-
-/* Other features, Linux-defined mapping, word 3 */
-/* This range is used for feature bits which conflict or are synthesized */
-#define X86_FEATURE_CXMMX      (3*32+ 0) /* Cyrix MMX extensions */
-#define X86_FEATURE_K6_MTRR    (3*32+ 1) /* AMD K6 nonstandard MTRRs */
-#define X86_FEATURE_CYRIX_ARR  (3*32+ 2) /* Cyrix ARRs (= MTRRs) */
-#define X86_FEATURE_CENTAUR_MCR        (3*32+ 3) /* Centaur MCRs (= MTRRs) */
+#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! */
 
-#define MAX_X86_VENDOR_ID 16
+/** x86 CPU information */
 struct cpuinfo_x86 {
-       uint8_t  x86;           /* CPU family */
-       uint8_t  x86_model;
-       uint8_t  x86_mask;
-
-               int      cpuid_level;   /* Maximum supported CPUID level, -1=no CPUID */
-       unsigned x86_capability[NCAPINTS];
-       char     x86_vendor_id[MAX_X86_VENDOR_ID];
+       /** CPU features */
+       unsigned int features;
+       /** 64-bit CPU features */
+       unsigned int amd_features;
 };
 
-
-#define X86_VENDOR_INTEL 0
-#define X86_VENDOR_CYRIX 1
-#define X86_VENDOR_AMD 2
-#define X86_VENDOR_UMC 3
-#define X86_VENDOR_NEXGEN 4
-#define X86_VENDOR_CENTAUR 5
-#define X86_VENDOR_RISE 6
-#define X86_VENDOR_TRANSMETA 7
-#define X86_VENDOR_NSC 8
-#define X86_VENDOR_UNKNOWN 0xff
-
 /*
  * EFLAGS bits
  */
@@ -107,137 +73,14 @@ struct cpuinfo_x86 {
 /*
  * Generic CPUID function
  */
-static 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));
-}
-
-/*
- * CPUID functions returning a single datum
- */
-static inline unsigned int cpuid_eax(unsigned int op)
-{
-       unsigned int eax;
-
-       __asm__("cpuid"
-               : "=a" (eax)
-               : "0" (op)
-               : "bx", "cx", "dx");
-       return eax;
-}
-static inline unsigned int cpuid_ebx(unsigned int op)
-{
-       unsigned int eax, ebx;
-
-       __asm__("cpuid"
-               : "=a" (eax), "=b" (ebx)
-               : "0" (op)
-               : "cx", "dx" );
-       return ebx;
-}
-static inline unsigned int cpuid_ecx(unsigned int op)
-{
-       unsigned int eax, ecx;
-
-       __asm__("cpuid"
-               : "=a" (eax), "=c" (ecx)
-               : "0" (op)
-               : "bx", "dx" );
-       return ecx;
+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 ) );
 }
-static inline unsigned int cpuid_edx(unsigned int op)
-{
-       unsigned int eax, edx;
-
-       __asm__("cpuid"
-               : "=a" (eax), "=d" (edx)
-               : "0" (op)
-               : "bx", "cx");
-       return edx;
-}
-
-/*
- * Intel CPU features in CR4
- */
-#define X86_CR4_VME            0x0001  /* enable vm86 extensions */
-#define X86_CR4_PVI            0x0002  /* virtual interrupts flag enable */
-#define X86_CR4_TSD            0x0004  /* disable time stamp at ipl 3 */
-#define X86_CR4_DE             0x0008  /* enable debugging extensions */
-#define X86_CR4_PSE            0x0010  /* enable page size extensions */
-#define X86_CR4_PAE            0x0020  /* enable physical address extensions */
-#define X86_CR4_MCE            0x0040  /* Machine check enable */
-#define X86_CR4_PGE            0x0080  /* enable global pages */
-#define X86_CR4_PCE            0x0100  /* enable performance counters at ipl 3 */
-#define X86_CR4_OSFXSR         0x0200  /* enable fast FPU save and restore */
-#define X86_CR4_OSXMMEXCPT     0x0400  /* enable unmasked SSE exceptions */
-
-
-#define MSR_K6_EFER                    0xC0000080
-/* EFER bits: */ 
-#define _EFER_SCE 0  /* SYSCALL/SYSRET */
-#define _EFER_LME 8  /* Long mode enable */
-#define _EFER_LMA 10 /* Long mode active (read-only) */
-#define _EFER_NX 11  /* No execute enable */
-
-#define EFER_SCE (1<<_EFER_SCE)
-#define EFER_LME (1<<EFER_LME)
-#define EFER_LMA (1<<EFER_LMA)
-#define EFER_NX (1<<_EFER_NX)
-
-#define rdmsr(msr,val1,val2) \
-     __asm__ __volatile__("rdmsr" \
-                         : "=a" (val1), "=d" (val2) \
-                         : "c" (msr))
-
-#define wrmsr(msr,val1,val2) \
-     __asm__ __volatile__("wrmsr" \
-                         : /* no outputs */ \
-                         : "c" (msr), "a" (val1), "d" (val2))
-
-
-#define read_cr0()     ({ \
-       unsigned int __dummy; \
-       __asm__( \
-               "movl %%cr0, %0\n\t" \
-               :"=r" (__dummy)); \
-       __dummy; \
-})
-#define write_cr0(x) \
-       __asm__("movl %0,%%cr0": :"r" (x));
-
-#define read_cr3()     ({ \
-       unsigned int __dummy; \
-       __asm__( \
-               "movl %%cr3, %0\n\t" \
-               :"=r" (__dummy)); \
-       __dummy; \
-})
-#define write_cr3x(x) \
-       __asm__("movl %0,%%cr3": :"r" (x));
-
-
-#define read_cr4()     ({ \
-       unsigned int __dummy; \
-       __asm__( \
-               "movl %%cr4, %0\n\t" \
-               :"=r" (__dummy)); \
-       __dummy; \
-})
-#define write_cr4x(x) \
-       __asm__("movl %0,%%cr4": :"r" (x));
-
 
-extern struct cpuinfo_x86 cpu_info;
-#ifdef CONFIG_X86_64
-extern void cpu_setup(void);
-#else
-#define cpu_setup() do {} while(0)
-#endif
+extern void get_cpuinfo ( struct cpuinfo_x86 *cpu );
 
 #endif /* I386_BITS_CPU_H */