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
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
|
/*
* Copyright (c) 2018 Richard Braun.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef X86_CPU_I_H
#define X86_CPU_I_H
/*
* Exception frame offets.
*/
#ifdef __LP64__
#define CPU_EXC_FRAME_RAX 0
#define CPU_EXC_FRAME_RBX 1
#define CPU_EXC_FRAME_RCX 2
#define CPU_EXC_FRAME_RDX 3
#define CPU_EXC_FRAME_RBP 4
#define CPU_EXC_FRAME_RSI 5
#define CPU_EXC_FRAME_RDI 6
#define CPU_EXC_FRAME_R8 7
#define CPU_EXC_FRAME_R9 8
#define CPU_EXC_FRAME_R10 9
#define CPU_EXC_FRAME_R11 10
#define CPU_EXC_FRAME_R12 11
#define CPU_EXC_FRAME_R13 12
#define CPU_EXC_FRAME_R14 13
#define CPU_EXC_FRAME_R15 14
#define CPU_EXC_FRAME_VECTOR 15
#define CPU_EXC_FRAME_ERROR 16
#define CPU_EXC_FRAME_RIP 17
#define CPU_EXC_FRAME_CS 18
#define CPU_EXC_FRAME_RFLAGS 19
#define CPU_EXC_FRAME_RSP 20
#define CPU_EXC_FRAME_SS 21
#define CPU_EXC_FRAME_SIZE 22
#define CPU_EXC_FRAME_FP CPU_EXC_FRAME_RBP
#define CPU_EXC_FRAME_SP CPU_EXC_FRAME_RSP
#define CPU_EXC_FRAME_PC CPU_EXC_FRAME_RIP
#else /* __LP64__ */
#define CPU_EXC_FRAME_EAX 0
#define CPU_EXC_FRAME_EBX 1
#define CPU_EXC_FRAME_ECX 2
#define CPU_EXC_FRAME_EDX 3
#define CPU_EXC_FRAME_EBP 4
#define CPU_EXC_FRAME_ESI 5
#define CPU_EXC_FRAME_EDI 6
#define CPU_EXC_FRAME_DS 7
#define CPU_EXC_FRAME_ES 8
#define CPU_EXC_FRAME_FS 9
#define CPU_EXC_FRAME_GS 10
#define CPU_EXC_FRAME_VECTOR 11
#define CPU_EXC_FRAME_ERROR 12
#define CPU_EXC_FRAME_EIP 13
#define CPU_EXC_FRAME_CS 14
#define CPU_EXC_FRAME_EFLAGS 15
#define CPU_EXC_FRAME_ESP 16
#define CPU_EXC_FRAME_SS 17 /* esp and ss are undefined if trapped in kernel */
#define CPU_EXC_FRAME_SIZE 18
#define CPU_EXC_FRAME_FP CPU_EXC_FRAME_EBP
#define CPU_EXC_FRAME_SP CPU_EXC_FRAME_ESP
#define CPU_EXC_FRAME_PC CPU_EXC_FRAME_EIP
#endif /* __LP64__ */
/*
* EFLAGS register flags.
*/
#define CPU_EFL_ONE 0x00000002 /* Reserved, must be set */
#define CPU_EFL_IF 0x00000200
/*
* GDT segment selectors.
*
* Keep in mind that, on amd64, the size of a GDT entry referred to
* by a selector depends on the descriptor type.
*/
#define CPU_GDT_SEL_NULL 0
#define CPU_GDT_SEL_CODE 8
#define CPU_GDT_SEL_DATA 16
#define CPU_GDT_SEL_TSS 24
#ifdef __LP64__
#define CPU_GDT_SIZE 40
#else /* __LP64__ */
#define CPU_GDT_SEL_DF_TSS 32
#define CPU_GDT_SEL_PERCPU 40
#define CPU_GDT_SEL_TLS 48
#define CPU_GDT_SIZE 56
#endif /* __LP64__ */
#ifndef __ASSEMBLER__
#include <stdalign.h>
#include <stdbool.h>
#include <stdint.h>
#include <kern/bitmap.h>
struct cpu_tss {
#ifdef __LP64__
uint32_t reserved0;
uint64_t rsp0;
uint64_t rsp1;
uint64_t rsp2;
uint64_t ist[8];
uint64_t reserved1;
uint16_t reserved2;
#else /* __LP64__ */
uint32_t link;
uint32_t esp0;
uint32_t ss0;
uint32_t esp1;
uint32_t ss1;
uint32_t esp2;
uint32_t ss2;
uint32_t cr3;
uint32_t eip;
uint32_t eflags;
uint32_t eax;
uint32_t ecx;
uint32_t edx;
uint32_t ebx;
uint32_t esp;
uint32_t ebp;
uint32_t esi;
uint32_t edi;
uint32_t es;
uint32_t cs;
uint32_t ss;
uint32_t ds;
uint32_t fs;
uint32_t gs;
uint32_t ldt;
uint16_t trap_bit;
#endif /* __LP64__ */
uint16_t iobp_base;
} __packed;
/*
* LDT or TSS system segment descriptor.
*/
struct cpu_sysseg_desc {
uint32_t word1;
uint32_t word2;
#ifdef __LP64__
uint32_t word3;
uint32_t word4;
#endif /* __LP64__ */
};
struct cpu_gdt {
alignas(CPU_L1_SIZE) char descs[CPU_GDT_SIZE];
};
#define CPU_VENDOR_ID_SIZE 13
#define CPU_MODEL_NAME_SIZE 49
struct cpu_feature_map {
BITMAP_DECLARE(flags, CPU_NR_FEATURES);
};
struct cpu {
unsigned int id;
unsigned int apic_id;
char vendor_str[CPU_VENDOR_STR_SIZE];
char model_name[CPU_MODEL_NAME_SIZE];
unsigned int cpuid_max_basic;
unsigned int cpuid_max_extended;
unsigned int vendor_id;
unsigned int type;
unsigned int family;
unsigned int model;
unsigned int stepping;
unsigned int clflush_size;
unsigned int initial_apic_id;
struct cpu_feature_map feature_map;
unsigned short phys_addr_width;
unsigned short virt_addr_width;
struct cpu_gdt gdt;
/*
* TSS segments, one set per CPU.
*
* One TSS at least is required per processor to provide the following :
* - stacks for double fault handlers, implemented with task switching
* on i386, interrupt stack tables on amd64
* - stacks for each privilege level
* - I/O permission bitmaps
*
* See Intel 64 and IA-32 Architecture Software Developer's Manual,
* Volume 3 System Programming Guide :
* - 6.12.2 Interrupt tasks
* - 7.3 Task switching
*/
struct cpu_tss tss;
#ifndef __LP64__
struct cpu_tss df_tss;
#endif /* __LP64__ */
unsigned int started;
alignas(CPU_DATA_ALIGN) char intr_stack[CPU_INTR_STACK_SIZE];
alignas(CPU_DATA_ALIGN) char df_stack[CPU_INTR_STACK_SIZE];
};
/*
* This percpu variable contains the address of the percpu area for the local
* processor. This is normally the same value stored in the percpu module, but
* it can be directly accessed through a segment register.
*/
extern void *cpu_local_area;
static inline bool
cpu_feature_map_test(const struct cpu_feature_map *map,
enum cpu_feature feature)
{
return bitmap_test(map->flags, feature);
}
/*
* Return the content of the EFLAGS register.
*
* Implies a compiler barrier.
*
* TODO Add cpu_flags_t type.
*/
static __always_inline unsigned long
cpu_get_eflags(void)
{
unsigned long eflags;
asm volatile("pushf\n"
"pop %0\n"
: "=r" (eflags)
: : "memory");
return eflags;
}
#endif /* __ASSEMBLER__ */
#endif /* X86_CPU_I_H */
|