2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2008,2009 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #ifndef KERNEL_CPU_TSC_HEADER
20 #define KERNEL_CPU_TSC_HEADER 1
22 #include <grub/types.h>
24 /* Read the TSC value, which increments with each CPU clock cycle. */
25 static __inline grub_uint64_t
30 /* The CPUID instruction is a 'serializing' instruction, and
31 avoids out-of-order execution of the RDTSC instruction. */
33 __asm__
__volatile__ ("xorl %%eax, %%eax\n\t"
45 :::"%rax", "%rcx", "%rdx");
47 __asm__
__volatile__ ("xorl %%eax, %%eax\n\t"
48 "cpuid":::"%rax", "%rbx", "%rcx", "%rdx");
50 /* Read TSC value. We cannot use "=A", since this would use
52 __asm__
__volatile__ ("rdtsc":"=a" (lo
), "=d" (hi
));
54 return (((grub_uint64_t
) hi
) << 32) | lo
;
60 grub_cpu_is_cpuid_supported (void)
62 grub_uint64_t id_supported
;
65 "popq %%rax /* Get EFLAGS into EAX */\n\t"
66 "movq %%rax, %%rcx /* Save original flags in ECX */\n\t"
67 "xorq $0x200000, %%rax /* Flip ID bit in EFLAGS */\n\t"
68 "pushq %%rax /* Store modified EFLAGS on stack */\n\t"
69 "popfq /* Replace current EFLAGS */\n\t"
70 "pushfq /* Read back the EFLAGS */\n\t"
71 "popq %%rax /* Get EFLAGS into EAX */\n\t"
72 "xorq %%rcx, %%rax /* Check if flag could be modified */\n\t"
75 : /* Clobbered: */ "%rcx");
77 return id_supported
!= 0;
83 grub_cpu_is_cpuid_supported (void)
85 grub_uint32_t id_supported
;
88 "popl %%eax /* Get EFLAGS into EAX */\n\t"
89 "movl %%eax, %%ecx /* Save original flags in ECX */\n\t"
90 "xorl $0x200000, %%eax /* Flip ID bit in EFLAGS */\n\t"
91 "pushl %%eax /* Store modified EFLAGS on stack */\n\t"
92 "popfl /* Replace current EFLAGS */\n\t"
93 "pushfl /* Read back the EFLAGS */\n\t"
94 "popl %%eax /* Get EFLAGS into EAX */\n\t"
95 "xorl %%ecx, %%eax /* Check if flag could be modified */\n\t"
98 : /* Clobbered: */ "%rcx");
100 return id_supported
!= 0;
106 grub_cpu_is_tsc_supported (void)
108 if (! grub_cpu_is_cpuid_supported ())
111 grub_uint32_t features
;
113 __asm__ ("movl $1, %%eax\n\t"
127 : /* Clobbered: */ "%rax", "%rcx");
129 __asm__ ("movl $1, %%eax\n\t"
133 : /* Clobbered: */ "%rax", "%rbx", "%rcx");
135 return (features
& (1 << 4)) != 0;
138 void grub_tsc_init (void);
139 grub_uint64_t
grub_tsc_get_time_ms (void);
141 #endif /* ! KERNEL_CPU_TSC_HEADER */