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