Consolidate cpuid code.

This commit is contained in:
Vladimir Serbinenko 2013-10-27 00:02:01 +02:00
parent c1bee64676
commit c81acb7ff3
5 changed files with 22 additions and 124 deletions

View file

@ -1,3 +1,7 @@
2013-10-26 Vladimir Serbinenko <phcoder@gmail.com>
Consolidate cpuid code.
2013-10-26 Vladimir Serbinenko <phcoder@gmail.com> 2013-10-26 Vladimir Serbinenko <phcoder@gmail.com>
Move cpuid code to cpuid.h and TSC code to tsc.c. Move cpuid code to cpuid.h and TSC code to tsc.c.

View file

@ -18,42 +18,10 @@
#include <grub/efiemu/efiemu.h> #include <grub/efiemu/efiemu.h>
#include <grub/command.h> #include <grub/command.h>
#include <grub/i386/cpuid.h>
#define cpuid(num,a,b,c,d) \
asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \
: "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
: "0" (num))
#define bit_LM (1 << 29)
const char * const char *
grub_efiemu_get_default_core_name (void) grub_efiemu_get_default_core_name (void)
{ {
return grub_cpuid_has_longmode ? "efiemu64.o" : "efiemu32.o";
unsigned int eax, ebx, ecx, edx;
unsigned int max_level;
unsigned int ext_level;
/* See if we can use cpuid. */
asm volatile ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
"pushl %0; popfl; pushfl; popl %0; popfl"
: "=&r" (eax), "=&r" (ebx)
: "i" (0x00200000));
if (((eax ^ ebx) & 0x00200000) == 0)
return "efiemu32.o";
/* Check the highest input value for eax. */
cpuid (0, eax, ebx, ecx, edx);
/* We only look at the first four characters. */
max_level = eax;
if (max_level == 0)
return "efiemu32.o";
cpuid (0x80000000, eax, ebx, ecx, edx);
ext_level = eax;
if (ext_level < 0x80000000)
return "efiemu32.o";
cpuid (0x80000001, eax, ebx, ecx, edx);
return (edx & bit_LM) ? "efiemu64.o" : "efiemu32.o";
} }

View file

@ -41,27 +41,11 @@ static __inline grub_uint64_t
grub_get_tsc (void) grub_get_tsc (void)
{ {
grub_uint32_t lo, hi; grub_uint32_t lo, hi;
grub_uint32_t a,b,c,d;
/* The CPUID instruction is a 'serializing' instruction, and /* The CPUID instruction is a 'serializing' instruction, and
avoids out-of-order execution of the RDTSC instruction. */ avoids out-of-order execution of the RDTSC instruction. */
#ifdef __APPLE__ grub_cpuid (0,a,b,c,d);
__asm__ __volatile__ ("xorl %%eax, %%eax\n\t"
#ifdef __x86_64__
"push %%rbx\n"
#else
"push %%ebx\n"
#endif
"cpuid\n"
#ifdef __x86_64__
"pop %%rbx\n"
#else
"pop %%ebx\n"
#endif
:::"%rax", "%rcx", "%rdx");
#else
__asm__ __volatile__ ("xorl %%eax, %%eax\n\t"
"cpuid":::"%rax", "%rbx", "%rcx", "%rdx");
#endif
/* Read TSC value. We cannot use "=A", since this would use /* Read TSC value. We cannot use "=A", since this would use
%rax on x86_64. */ %rax on x86_64. */
__asm__ __volatile__ ("rdtsc":"=a" (lo), "=d" (hi)); __asm__ __volatile__ ("rdtsc":"=a" (lo), "=d" (hi));
@ -72,34 +56,13 @@ grub_get_tsc (void)
static __inline int static __inline int
grub_cpu_is_tsc_supported (void) grub_cpu_is_tsc_supported (void)
{ {
grub_uint32_t a,b,c,d;
if (! grub_cpu_is_cpuid_supported ()) if (! grub_cpu_is_cpuid_supported ())
return 0; return 0;
grub_uint32_t features; grub_cpuid(1,a,b,c,d);
#ifdef __APPLE__
__asm__ ("movl $1, %%eax\n\t" return (d & (1 << 4)) != 0;
#ifdef __x86_64__
"push %%rbx\n"
#else
"push %%ebx\n"
#endif
"cpuid\n"
#ifdef __x86_64__
"pop %%rbx\n"
#else
"pop %%ebx\n"
#endif
: "=d" (features)
: /* No inputs. */
: /* Clobbered: */ "%rax", "%rcx");
#else
__asm__ ("movl $1, %%eax\n\t"
"cpuid\n"
: "=d" (features)
: /* No inputs. */
: /* Clobbered: */ "%rax", "%rbx", "%rcx");
#endif
return (features & (1 << 4)) != 0;
} }
static void static void

View file

@ -126,66 +126,22 @@ guessfsb (void)
{ {
const grub_uint64_t sane_value = 100000000; const grub_uint64_t sane_value = 100000000;
grub_uint32_t manufacturer[3], max_cpuid, capabilities, msrlow; grub_uint32_t manufacturer[3], max_cpuid, capabilities, msrlow;
grub_uint32_t a, b, d;
if (! grub_cpu_is_cpuid_supported ()) if (! grub_cpu_is_cpuid_supported ())
return sane_value; return sane_value;
#ifdef __APPLE__ grub_cpuid (0, max_cpuid, manufacturer[0], manufacturer[2], manufacturer[1]);
asm volatile ("movl $0, %%eax\n"
#ifdef __x86_64__
"push %%rbx\n"
#else
"push %%ebx\n"
#endif
"cpuid\n"
#ifdef __x86_64__
"pop %%rbx\n"
#else
"pop %%ebx\n"
#endif
: "=a" (max_cpuid),
"=d" (manufacturer[1]), "=c" (manufacturer[2]));
/* Only Intel for now is done. */
if (grub_memcmp (manufacturer + 1, "ineIntel", 12) != 0)
return sane_value;
#else
asm volatile ("movl $0, %%eax\n"
"cpuid"
: "=a" (max_cpuid), "=b" (manufacturer[0]),
"=d" (manufacturer[1]), "=c" (manufacturer[2]));
/* Only Intel for now is done. */ /* Only Intel for now is done. */
if (grub_memcmp (manufacturer, "GenuineIntel", 12) != 0) if (grub_memcmp (manufacturer, "GenuineIntel", 12) != 0)
return sane_value; return sane_value;
#endif
/* Check Speedstep. */ /* Check Speedstep. */
if (max_cpuid < 1) if (max_cpuid < 1)
return sane_value; return sane_value;
#ifdef __APPLE__ grub_cpuid (1, a, b, capabilities, d);
asm volatile ("movl $1, %%eax\n"
#ifdef __x86_64__
"push %%rbx\n"
#else
"push %%ebx\n"
#endif
"cpuid\n"
#ifdef __x86_64__
"pop %%rbx\n"
#else
"pop %%ebx\n"
#endif
: "=c" (capabilities):
: "%rax", "%rdx");
#else
asm volatile ("movl $1, %%eax\n"
"cpuid"
: "=c" (capabilities):
: "%rax", "%rbx", "%rdx");
#endif
if (! (capabilities & (1 << 7))) if (! (capabilities & (1 << 7)))
return sane_value; return sane_value;

View file

@ -69,9 +69,16 @@ grub_cpu_is_cpuid_supported (void)
#endif #endif
#ifdef __PIC__
#define grub_cpuid(num,a,b,c,d) \ #define grub_cpuid(num,a,b,c,d) \
asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \ asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \
: "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
: "0" (num)) : "0" (num))
#else
#define grub_cpuid(num,a,b,c,d) \
asm volatile ("cpuid" \
: "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
: "0" (num))
#endif
#endif #endif