1 /**
2  * \file
3  * \brief  CPU related functions
4  *
5  * \author Frank Mehnert <fm3@os.inf.tu-dresden.de> */
6 
7 /*
8  * (c) 2004-2009 Author(s)
9  *     economic rights: Technische Universität Dresden (Germany)
10  * This file is part of TUD:OS and distributed under the terms of the
11  * GNU Lesser General Public License 2.1.
12  * Please see the COPYING-LGPL-2.1 file for details.
13  */
14 
15 #ifndef __L4_UTIL_CPU_H
16 #define __L4_UTIL_CPU_H
17 
18 #include <l4/sys/compiler.h>
19 
20 EXTERN_C_BEGIN
21 
22 /**
23  * \defgroup l4util_cpu CPU related functions
24  * \ingroup l4util_api
25  */
26 /*@{*/
27 
28 /**
29  * Check whether the CPU supports the "cpuid" instruction.
30  *
31  * \return 1 if it has, 0 if it has not
32  */
33 L4_INLINE int          l4util_cpu_has_cpuid(void);
34 
35 /**
36  * Returns the CPU capabilities if the "cpuid" instruction is available.
37  *
38  * \return CPU capabilities if the "cpuid" instruction is available,
39  *         0 if the "cpuid" instruction is not supported.
40  */
41 L4_INLINE unsigned int l4util_cpu_capabilities(void);
42 
43 /**
44  * Returns the CPU capabilities.
45  *
46  * \return CPU capabilities.
47  */
48 L4_INLINE unsigned int l4util_cpu_capabilities_nocheck(void);
49 
50 /**
51  * Generic CPUID access function.
52  */
53 L4_INLINE void
54 l4util_cpu_cpuid(unsigned long mode,
55                  unsigned long *eax, unsigned long *ebx,
56                  unsigned long *ecx, unsigned long *edx);
57 
58 /*@}*/
59 static inline void
l4util_cpu_pause(void)60 l4util_cpu_pause(void)
61 {
62   __asm__ __volatile__ ("rep; nop");
63 }
64 
65 L4_INLINE int
l4util_cpu_has_cpuid(void)66 l4util_cpu_has_cpuid(void)
67 {
68   unsigned long eax;
69 
70   asm volatile("pushl %%ebx             \t\n"
71                "pushfl			\t\n"
72                "popl %%eax		\t\n" /* get eflags */
73                "movl %%eax, %%ebx	\t\n" /* save it */
74                "xorl $0x200000, %%eax	\t\n" /* toggle ID bit */
75                "pushl %%eax		\t\n"
76                "popfl			\t\n" /* set again */
77                "pushfl			\t\n"
78                "popl %%eax		\t\n" /* get it again */
79                "xorl %%ebx, %%eax	\t\n"
80                "pushl %%ebx		\t\n"
81                "popfl			\t\n" /* restore saved flags */
82                "popl %%ebx              \t\n"
83                : "=a" (eax)
84                : /* no input */
85                );
86 
87   return eax & 0x200000;
88 }
89 
90 L4_INLINE void
l4util_cpu_cpuid(unsigned long mode,unsigned long * eax,unsigned long * ebx,unsigned long * ecx,unsigned long * edx)91 l4util_cpu_cpuid(unsigned long mode,
92                  unsigned long *eax, unsigned long *ebx,
93                  unsigned long *ecx, unsigned long *edx)
94 {
95   asm volatile("pushl %%ebx      \t\n"
96                "cpuid            \t\n"
97                "mov %%ebx, %%esi \t\n"
98                "popl %%ebx       \t\n"
99                : "=a" (*eax),
100                  "=S" (*ebx),
101                  "=c" (*ecx),
102                  "=d" (*edx)
103                : "a"  (mode));
104 }
105 
106 L4_INLINE unsigned int
l4util_cpu_capabilities_nocheck(void)107 l4util_cpu_capabilities_nocheck(void)
108 {
109   unsigned long dummy, capability;
110 
111   /* get CPU capabilities */
112   l4util_cpu_cpuid(1, &dummy, &dummy, &dummy, &capability);
113 
114   return capability;
115 }
116 
117 L4_INLINE unsigned int
l4util_cpu_capabilities(void)118 l4util_cpu_capabilities(void)
119 {
120   if (!l4util_cpu_has_cpuid())
121     return 0; /* CPU has not cpuid instruction */
122 
123   return l4util_cpu_capabilities_nocheck();
124 }
125 
126 EXTERN_C_END
127 
128 #endif
129 
130