diff --git a/ChangeLog b/ChangeLog index 86b5aab0b..70b9b747e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2013-10-26 Vladimir Serbinenko + + Move cpuid code to cpuid.h and TSC code to tsc.c. + 2013-10-26 Grégoire Sutre * util/grub.d/00_header.in: Don't use LANG if it's not set. diff --git a/grub-core/commands/i386/cpuid.c b/grub-core/commands/i386/cpuid.c index 3b895cb93..af753590d 100644 --- a/grub-core/commands/i386/cpuid.c +++ b/grub-core/commands/i386/cpuid.c @@ -29,11 +29,6 @@ GRUB_MOD_LICENSE ("GPLv3+"); -#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)) - static const struct grub_arg_option options[] = { /* TRANSLATORS: "(default)" at the end means that this option is used if @@ -78,18 +73,18 @@ GRUB_MOD_INIT(cpuid) goto done; /* Check the highest input value for eax. */ - cpuid (0, eax, ebx, ecx, edx); + grub_cpuid (0, eax, ebx, ecx, edx); /* We only look at the first four characters. */ max_level = eax; if (max_level == 0) goto done; - cpuid (0x80000000, eax, ebx, ecx, edx); + grub_cpuid (0x80000000, eax, ebx, ecx, edx); ext_level = eax; if (ext_level < 0x80000000) goto done; - cpuid (0x80000001, eax, ebx, ecx, edx); + grub_cpuid (0x80000001, eax, ebx, ecx, edx); grub_cpuid_has_longmode = !!(edx & bit_LM); done: #endif diff --git a/grub-core/kern/i386/tsc.c b/grub-core/kern/i386/tsc.c index 9efd6338c..d5c5669d2 100644 --- a/grub-core/kern/i386/tsc.c +++ b/grub-core/kern/i386/tsc.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,72 @@ static grub_uint64_t tsc_boot_time; in 32-bit. */ grub_uint32_t grub_tsc_rate; +/* Read the TSC value, which increments with each CPU clock cycle. */ +static __inline grub_uint64_t +grub_get_tsc (void) +{ + grub_uint32_t lo, hi; + + /* The CPUID instruction is a 'serializing' instruction, and + avoids out-of-order execution of the RDTSC instruction. */ +#ifdef __APPLE__ + __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 + %rax on x86_64. */ + __asm__ __volatile__ ("rdtsc":"=a" (lo), "=d" (hi)); + + return (((grub_uint64_t) hi) << 32) | lo; +} + +static __inline int +grub_cpu_is_tsc_supported (void) +{ + if (! grub_cpu_is_cpuid_supported ()) + return 0; + + grub_uint32_t features; +#ifdef __APPLE__ + __asm__ ("movl $1, %%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 + : "=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 grub_pit_wait (grub_uint16_t tics) { @@ -63,7 +130,7 @@ grub_pit_wait (grub_uint16_t tics) GRUB_PIT_SPEAKER_PORT); } -grub_uint64_t +static grub_uint64_t grub_tsc_get_time_ms (void) { grub_uint64_t a = grub_get_tsc () - tsc_boot_time; diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c index 497529bc3..1c574e4cf 100644 --- a/grub-core/loader/i386/xnu.c +++ b/grub-core/loader/i386/xnu.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index f6cd51c7f..a29a15dc3 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -58,11 +58,6 @@ real2pm (grub_vbe_farptr_t ptr) + ((unsigned long) ptr & 0x0000FFFF)); } -#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 rdmsr(num,a,d) \ asm volatile ("rdmsr" : "=a" (a), "=d" (d) : "c" (num)) @@ -136,7 +131,7 @@ grub_vbe_enable_mtrr (grub_uint8_t *base, grub_size_t size) if (! grub_cpu_is_cpuid_supported ()) return; - cpuid (1, eax, ebx, ecx, edx); + grub_cpuid (1, eax, ebx, ecx, edx); features = edx; if (! (features & 0x00001000)) /* MTRR */ return; @@ -147,11 +142,11 @@ grub_vbe_enable_mtrr (grub_uint8_t *base, grub_size_t size) return; var_mtrrs = (mtrrcap & 0xFF); - cpuid (0x80000000, eax, ebx, ecx, edx); + grub_cpuid (0x80000000, eax, ebx, ecx, edx); max_extended_cpuid = eax; if (max_extended_cpuid >= 0x80000008) { - cpuid (0x80000008, eax, ebx, ecx, edx); + grub_cpuid (0x80000008, eax, ebx, ecx, edx); maxphyaddr = (eax & 0xFF); } else diff --git a/include/grub/i386/cpuid.h b/include/grub/i386/cpuid.h index 09b313bb8..ce087b619 100644 --- a/include/grub/i386/cpuid.h +++ b/include/grub/i386/cpuid.h @@ -21,4 +21,57 @@ extern unsigned char grub_cpuid_has_longmode; +#ifdef __x86_64__ + +static __inline int +grub_cpu_is_cpuid_supported (void) +{ + grub_uint64_t id_supported; + + __asm__ ("pushfq\n\t" + "popq %%rax /* Get EFLAGS into EAX */\n\t" + "movq %%rax, %%rcx /* Save original flags in ECX */\n\t" + "xorq $0x200000, %%rax /* Flip ID bit in EFLAGS */\n\t" + "pushq %%rax /* Store modified EFLAGS on stack */\n\t" + "popfq /* Replace current EFLAGS */\n\t" + "pushfq /* Read back the EFLAGS */\n\t" + "popq %%rax /* Get EFLAGS into EAX */\n\t" + "xorq %%rcx, %%rax /* Check if flag could be modified */\n\t" + : "=a" (id_supported) + : /* No inputs. */ + : /* Clobbered: */ "%rcx"); + + return id_supported != 0; +} + +#else + +static __inline int +grub_cpu_is_cpuid_supported (void) +{ + grub_uint32_t id_supported; + + __asm__ ("pushfl\n\t" + "popl %%eax /* Get EFLAGS into EAX */\n\t" + "movl %%eax, %%ecx /* Save original flags in ECX */\n\t" + "xorl $0x200000, %%eax /* Flip ID bit in EFLAGS */\n\t" + "pushl %%eax /* Store modified EFLAGS on stack */\n\t" + "popfl /* Replace current EFLAGS */\n\t" + "pushfl /* Read back the EFLAGS */\n\t" + "popl %%eax /* Get EFLAGS into EAX */\n\t" + "xorl %%ecx, %%eax /* Check if flag could be modified */\n\t" + : "=a" (id_supported) + : /* No inputs. */ + : /* Clobbered: */ "%rcx"); + + return id_supported != 0; +} + +#endif + +#define grub_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)) + #endif diff --git a/include/grub/i386/tsc.h b/include/grub/i386/tsc.h index d25d0e3e9..71b32e6b8 100644 --- a/include/grub/i386/tsc.h +++ b/include/grub/i386/tsc.h @@ -21,122 +21,7 @@ #include -/* Read the TSC value, which increments with each CPU clock cycle. */ -static __inline grub_uint64_t -grub_get_tsc (void) -{ - grub_uint32_t lo, hi; - - /* The CPUID instruction is a 'serializing' instruction, and - avoids out-of-order execution of the RDTSC instruction. */ -#ifdef __APPLE__ - __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 - %rax on x86_64. */ - __asm__ __volatile__ ("rdtsc":"=a" (lo), "=d" (hi)); - - return (((grub_uint64_t) hi) << 32) | lo; -} - -#ifdef __x86_64__ - -static __inline int -grub_cpu_is_cpuid_supported (void) -{ - grub_uint64_t id_supported; - - __asm__ ("pushfq\n\t" - "popq %%rax /* Get EFLAGS into EAX */\n\t" - "movq %%rax, %%rcx /* Save original flags in ECX */\n\t" - "xorq $0x200000, %%rax /* Flip ID bit in EFLAGS */\n\t" - "pushq %%rax /* Store modified EFLAGS on stack */\n\t" - "popfq /* Replace current EFLAGS */\n\t" - "pushfq /* Read back the EFLAGS */\n\t" - "popq %%rax /* Get EFLAGS into EAX */\n\t" - "xorq %%rcx, %%rax /* Check if flag could be modified */\n\t" - : "=a" (id_supported) - : /* No inputs. */ - : /* Clobbered: */ "%rcx"); - - return id_supported != 0; -} - -#else - -static __inline int -grub_cpu_is_cpuid_supported (void) -{ - grub_uint32_t id_supported; - - __asm__ ("pushfl\n\t" - "popl %%eax /* Get EFLAGS into EAX */\n\t" - "movl %%eax, %%ecx /* Save original flags in ECX */\n\t" - "xorl $0x200000, %%eax /* Flip ID bit in EFLAGS */\n\t" - "pushl %%eax /* Store modified EFLAGS on stack */\n\t" - "popfl /* Replace current EFLAGS */\n\t" - "pushfl /* Read back the EFLAGS */\n\t" - "popl %%eax /* Get EFLAGS into EAX */\n\t" - "xorl %%ecx, %%eax /* Check if flag could be modified */\n\t" - : "=a" (id_supported) - : /* No inputs. */ - : /* Clobbered: */ "%rcx"); - - return id_supported != 0; -} - -#endif - -static __inline int -grub_cpu_is_tsc_supported (void) -{ - if (! grub_cpu_is_cpuid_supported ()) - return 0; - - grub_uint32_t features; -#ifdef __APPLE__ - __asm__ ("movl $1, %%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 - : "=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; -} - void grub_tsc_init (void); -grub_uint64_t grub_tsc_get_time_ms (void); /* In ms per 2^32 ticks. */ extern grub_uint32_t EXPORT_VAR(grub_tsc_rate);