From adf192f56633f90d500015c3f0e0ae74cc92ac10 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 14 Jul 2007 19:12:13 +0100 Subject: [PATCH] Shrink cpu.c and render it useful for our purposes. --- src/arch/i386/core/cpu.c | 131 +++++++--------- src/arch/i386/include/bits/cpu.h | 249 ++++++------------------------- 2 files changed, 104 insertions(+), 276 deletions(-) diff --git a/src/arch/i386/core/cpu.c b/src/arch/i386/core/cpu.c index cbef6a1a..c24fa4e6 100644 --- a/src/arch/i386/core/cpu.c +++ b/src/arch/i386/core/cpu.c @@ -1,88 +1,73 @@ -#ifdef CONFIG_X86_64 -#include "stdint.h" -#include "string.h" -#include "bits/cpu.h" -#include +#include +#include +#include +/** @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); -} + memset ( cpu, 0, sizeof ( *cpu ) ); -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 */ - - /* 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 */ + /* 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" ); + } - /* 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; - } - - /* 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 */ diff --git a/src/arch/i386/include/bits/cpu.h b/src/arch/i386/include/bits/cpu.h index 2e9b27ba..83339ddd 100644 --- a/src/arch/i386/include/bits/cpu.h +++ b/src/arch/i386/include/bits/cpu.h @@ -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! */ +#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! */ -/* 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 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)); +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 ) ); } -/* - * 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 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<