Make cpuid functions usable when compiled with PIC
[coreboot.git] / src / arch / x86 / include / arch / cpu.h
1 #ifndef ARCH_CPU_H
2 #define ARCH_CPU_H
3
4 /*
5  * EFLAGS bits
6  */
7 #define X86_EFLAGS_CF   0x00000001 /* Carry Flag */
8 #define X86_EFLAGS_PF   0x00000004 /* Parity Flag */
9 #define X86_EFLAGS_AF   0x00000010 /* Auxillary carry Flag */
10 #define X86_EFLAGS_ZF   0x00000040 /* Zero Flag */
11 #define X86_EFLAGS_SF   0x00000080 /* Sign Flag */
12 #define X86_EFLAGS_TF   0x00000100 /* Trap Flag */
13 #define X86_EFLAGS_IF   0x00000200 /* Interrupt Flag */
14 #define X86_EFLAGS_DF   0x00000400 /* Direction Flag */
15 #define X86_EFLAGS_OF   0x00000800 /* Overflow Flag */
16 #define X86_EFLAGS_IOPL 0x00003000 /* IOPL mask */
17 #define X86_EFLAGS_NT   0x00004000 /* Nested Task */
18 #define X86_EFLAGS_RF   0x00010000 /* Resume Flag */
19 #define X86_EFLAGS_VM   0x00020000 /* Virtual Mode */
20 #define X86_EFLAGS_AC   0x00040000 /* Alignment Check */
21 #define X86_EFLAGS_VIF  0x00080000 /* Virtual Interrupt Flag */
22 #define X86_EFLAGS_VIP  0x00100000 /* Virtual Interrupt Pending */
23 #define X86_EFLAGS_ID   0x00200000 /* CPUID detection flag */
24
25 struct cpuid_result {
26         uint32_t eax;
27         uint32_t ebx;
28         uint32_t ecx;
29         uint32_t edx;
30 };
31
32 /*
33  * Generic CPUID function
34  */
35 static inline struct cpuid_result cpuid(int op)
36 {
37         struct cpuid_result result;
38         asm volatile(
39                 "mov %%ebx, %%edi;"
40                 "cpuid;"
41                 "mov %%ebx, %%esi;"
42                 "mov %%edi, %%ebx;"
43                 : "=a" (result.eax),
44                   "=S" (result.ebx),
45                   "=c" (result.ecx),
46                   "=d" (result.edx)
47                 : "0" (op)
48                 : "edi");
49         return result;
50 }
51
52 /*
53  * Generic Extended CPUID function
54  */
55 static inline struct cpuid_result cpuid_ext(int op, unsigned ecx)
56 {
57         struct cpuid_result result;
58         asm volatile(
59                 "mov %%ebx, %%edi;"
60                 "cpuid;"
61                 "mov %%ebx, %%esi;"
62                 "mov %%edi, %%ebx;"
63                 : "=a" (result.eax),
64                   "=S" (result.ebx),
65                   "=c" (result.ecx),
66                   "=d" (result.edx)
67                 : "0" (op), "2" (ecx)
68                 : "edi");
69         return result;
70 }
71
72 /*
73  * CPUID functions returning a single datum
74  */
75 static inline unsigned int cpuid_eax(unsigned int op)
76 {
77         unsigned int eax;
78
79         __asm__("mov %%ebx, %%edi;"
80                 "cpuid;"
81                 "mov %%edi, %%ebx;"
82                 : "=a" (eax)
83                 : "0" (op)
84                 : "ecx", "edx", "edi");
85         return eax;
86 }
87
88 static inline unsigned int cpuid_ebx(unsigned int op)
89 {
90         unsigned int eax, ebx;
91
92         __asm__("mov %%ebx, %%edi;"
93                 "cpuid;"
94                 "mov %%edi, %%ebx;"
95                 "mov %%edi, %%esi;"
96                 : "=a" (eax), "=S" (ebx)
97                 : "0" (op)
98                 : "ecx", "edx", "edi");
99         return ebx;
100 }
101
102 static inline unsigned int cpuid_ecx(unsigned int op)
103 {
104         unsigned int eax, ecx;
105
106         __asm__("mov %%ebx, %%edi;"
107                 "cpuid;"
108                 "mov %%edi, %%ebx;"
109                 : "=a" (eax), "=c" (ecx)
110                 : "0" (op)
111                 : "edx", "edi");
112         return ecx;
113 }
114
115 static inline unsigned int cpuid_edx(unsigned int op)
116 {
117         unsigned int eax, edx;
118
119         __asm__("mov %%ebx, %%edi;"
120                 "cpuid;"
121                 "mov %%edi, %%ebx;"
122                 : "=a" (eax), "=d" (edx)
123                 : "0" (op)
124                 : "ecx", "edi");
125         return edx;
126 }
127
128 #define X86_VENDOR_INVALID    0
129 #define X86_VENDOR_INTEL      1
130 #define X86_VENDOR_CYRIX      2
131 #define X86_VENDOR_AMD        3
132 #define X86_VENDOR_UMC        4
133 #define X86_VENDOR_NEXGEN     5
134 #define X86_VENDOR_CENTAUR    6
135 #define X86_VENDOR_RISE       7
136 #define X86_VENDOR_TRANSMETA  8
137 #define X86_VENDOR_NSC        9
138 #define X86_VENDOR_SIS       10
139 #define X86_VENDOR_UNKNOWN 0xff
140
141 #if !defined(__PRE_RAM__)
142 #include <device/device.h>
143
144 int cpu_phys_address_size(void);
145 int cpu_have_cpuid(void);
146
147 struct cpu_device_id {
148         unsigned vendor;
149         unsigned device;
150 };
151
152 struct cpu_driver {
153         struct device_operations *ops;
154         struct cpu_device_id *id_table;
155 };
156
157 struct cpu_info {
158         device_t cpu;
159         unsigned long index;
160 };
161
162 static inline struct cpu_info *cpu_info(void)
163 {
164         struct cpu_info *ci;
165         __asm__("andl %%esp,%0; "
166                 "orl  %2, %0 "
167                 :"=r" (ci)
168                 : "0" (~(CONFIG_STACK_SIZE - 1)),
169                 "r" (CONFIG_STACK_SIZE - sizeof(struct cpu_info))
170         );
171         return ci;
172 }
173
174 static inline unsigned long cpu_index(void)
175 {
176         struct cpu_info *ci;
177         ci = cpu_info();
178         return ci->index;
179 }
180
181 struct cpuinfo_x86 {
182         uint8_t    x86;            /* CPU family */
183         uint8_t    x86_vendor;     /* CPU vendor */
184         uint8_t    x86_model;
185         uint8_t    x86_mask;
186 };
187
188 static void inline get_fms(struct cpuinfo_x86 *c, uint32_t tfms)
189 {
190         c->x86 = (tfms >> 8) & 0xf;
191         c->x86_model = (tfms >> 4) & 0xf;
192         c->x86_mask = tfms & 0xf;
193         if (c->x86 == 0xf)
194                 c->x86 += (tfms >> 20) & 0xff;
195         if (c->x86 >= 0x6)
196                 c->x86_model += ((tfms >> 16) & 0xF) << 4;
197
198 }
199 #endif
200
201 #endif /* ARCH_CPU_H */