-
Notifications
You must be signed in to change notification settings - Fork 143
/
Copy pathcpu_x86_64.h
267 lines (230 loc) · 7.05 KB
/
cpu_x86_64.h
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
262
263
264
265
266
267
/*
* Copyright (c) 2015-2019 Contributors as noted in the AUTHORS file
*
* This file is part of Solo5, a sandboxed execution environment.
*
* Permission to use, copy, modify, and/or distribute this software
* for any purpose with or without fee is hereby granted, provided
* that the above copyright notice and this permission notice appear
* in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BITUL
#ifdef ASM_FILE
#define _AC(X,Y) X
#define _AT(T,X) X
#else
#define __AC(X,Y) (X##Y)
#define _AC(X,Y) __AC(X,Y)
#define _AT(T,X) ((T)(X))
#endif
#define _BITUL(x) (_AC(1,UL) << (x))
#define _BITULL(x) (_AC(1,ULL) << (x))
#endif
/*
* Basic CPU control in CR0
*/
#define X86_CR0_PE_BIT 0 /* Protection Enable */
#define X86_CR0_PE _BITUL(X86_CR0_PE_BIT)
#define X86_CR0_MP_BIT 1 /* Monitor Coprocessor */
#define X86_CR0_MP _BITUL(X86_CR0_MP_BIT)
#define X86_CR0_EM_BIT 2 /* Emulation */
#define X86_CR0_EM _BITUL(X86_CR0_EM_BIT)
#define X86_CR0_NE_BIT 5 /* Numeric Exception */
#define X86_CR0_NE _BITUL(X86_CR0_NE_BIT)
#define X86_CR0_WP_BIT 16 /* Write Protect */
#define X86_CR0_WP _BITUL(X86_CR0_WP_BIT)
#define X86_CR0_PG_BIT 31 /* Paging */
#define X86_CR0_PG _BITUL(X86_CR0_PG_BIT)
/*
* Intel CPU features in CR4
*/
#define X86_CR4_PAE_BIT 5 /* enable physical address extensions */
#define X86_CR4_PAE _BITUL(X86_CR4_PAE_BIT)
#define X86_CR4_OSFXSR_BIT 9 /* OS support for FXSAVE/FXRSTOR */
#define X86_CR4_OSFXSR _BITUL(X86_CR4_OSFXSR_BIT)
#define X86_CR4_OSXMMEXCPT_BIT 10 /* OS support for FP exceptions */
#define X86_CR4_OSXMMEXCPT _BITUL(X86_CR4_OSXMMEXCPT_BIT)
#define X86_CR4_VMXE_BIT 13 /* VMX enabled */
#define X86_CR4_VMXE _BITUL(X86_CR4_VMXE_BIT)
/*
* Intel CPU features in EFER
*/
#define X86_EFER_LME_BIT 8 /* Long mode enable (R/W) */
#define X86_EFER_LME _BITUL(X86_EFER_LME_BIT)
#define X86_EFER_LMA_BIT 10 /* Long mode active (R/O) */
#define X86_EFER_LMA _BITUL(X86_EFER_LMA_BIT)
#define X86_EFER_NXE_BIT 11 /* No-execute enable */
#define X86_EFER_NXE _BITUL(X86_EFER_NXE_BIT)
#define PAGE_SIZE 4096
#define PAGE_SHIFT 12
#define PAGE_MASK ~(0xfff)
/*
* Long-mode page table entries.
*/
#define X86_PTE_P_BIT 0 /* Present */
#define X86_PTE_P _BITUL(X86_PTE_P_BIT)
#define X86_PTE_W_BIT 1 /* Read/Write */
#define X86_PTE_W _BITUL(X86_PTE_W_BIT)
#define X86_PTE_PS_BIT 7 /* Page Size */
#define X86_PTE_PS _BITUL(X86_PTE_PS_BIT)
#define X86_PTE_XD_BIT 63 /* Execute disable */
#define X86_PTE_XD _BITUL(X86_PTE_XD_BIT)
/*
* GDT layout
*
*/
#define GDT_DESC_NULL 0
#define GDT_DESC_CODE 1
#define GDT_DESC_DATA 2
#define GDT_DESC_TSS_LO 3
#define GDT_DESC_TSS_HI 4
#define GDT_DESC_TSS GDT_DESC_TSS_LO
#define GDT_DESC_OFFSET(n) ((n) * 0x8)
#define GDT_NUM_ENTRIES 5
#define GDT_DESC_CODE_VAL 0x00af99000000ffff
#define GDT_DESC_DATA_VAL 0x00cf93000000ffff
#ifndef ASM_FILE
/*
* The remainder of this file is used only from C.
*/
struct gdtptr {
uint16_t limit;
uint64_t base;
} __attribute__((packed));
#define IDT_NUM_ENTRIES 48
struct idt_gate_desc {
uint64_t offset_lo:16;
uint64_t selector:16;
uint64_t ist:3;
uint64_t reserved:5;
uint64_t type:5;
uint64_t dpl:2;
uint64_t p:1;
uint64_t offset_hi:48;
uint64_t reserved1:32;
} __attribute__((packed));
struct idtptr {
uint16_t limit;
uint64_t base;
} __attribute__((packed));
struct tss {
uint32_t reserved;
uint64_t rsp[3];
uint64_t reserved2;
uint64_t ist[7];
uint64_t reserved3;
uint16_t reserved4;
uint16_t iomap_base;
} __attribute__((packed));
struct tss_desc {
uint64_t limit_lo:16;
uint64_t base_lo:24;
uint64_t type:5;
uint64_t dpl:2;
uint64_t p:1;
uint64_t limit_hi:4;
uint64_t unused:3;
uint64_t gran:1;
uint64_t base_hi:40;
uint64_t reserved:8;
uint64_t zero:5;
uint64_t reserved1:19;
} __attribute__((packed));
struct trap_regs {
uint64_t cr2;
uint64_t ec;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
};
static inline uint64_t cpu_rdtsc(void)
{
unsigned long l, h;
__asm__ __volatile__("rdtsc" : "=a"(l), "=d"(h));
return ((uint64_t)h << 32) | l;
}
static inline uint64_t mul64_32(uint64_t a, uint32_t b, uint8_t s)
{
uint64_t prod;
__asm__ (
"mul %%rdx ; "
"shrd %%cl, %%rdx, %%rax"
: "=a" (prod)
: "0" (a), "d" ((uint64_t)b), "Ic" (s)
);
return prod;
}
/* accessing devices via port space */
static inline void outb(uint16_t port, uint8_t v)
{
__asm__ __volatile__("outb %0,%1" : : "a" (v), "dN" (port));
}
static inline void outw(uint16_t port, uint16_t v)
{
__asm__ __volatile__("outw %0,%1" : : "a" (v), "dN" (port));
}
static inline void outl(uint16_t port, uint32_t v)
{
__asm__ __volatile__("outl %0,%1" : : "a" (v), "dN" (port));
}
static inline uint8_t inb(uint16_t port)
{
uint8_t v;
__asm__ __volatile__("inb %1,%0" : "=a" (v) : "dN" (port));
return v;
}
static inline uint16_t inw(uint16_t port)
{
uint16_t v;
__asm__ __volatile__("inw %1,%0" : "=a" (v) : "dN" (port));
return v;
}
static inline uint32_t inl(uint16_t port)
{
uint32_t v;
__asm__ __volatile__("inl %1,%0" : "=a" (v) : "dN" (port));
return v;
}
static inline uint64_t inq(uint16_t port_lo)
{
uint16_t port_hi = port_lo + 4;
uint32_t lo, hi;
__asm__ __volatile__("inl %1,%0" : "=a" (lo) : "dN" (port_lo));
__asm__ __volatile__("inl %1,%0" : "=a" (hi) : "dN" (port_hi));
return ((uint64_t)lo) | ((uint64_t)hi << 32);
}
static inline void cpu_set_tls_base(uint64_t base)
{
__asm__ __volatile("wrmsr" ::
"c" (0xc0000100), /* IA32_FS_BASE */
"a" ((uint32_t)(base)),
"d" ((uint32_t)(base >> 32))
);
}
static inline void
x86_cpuid(uint32_t level, uint32_t *eax_out, uint32_t *ebx_out,
uint32_t *ecx_out, uint32_t *edx_out)
{
uint32_t eax_, ebx_, ecx_, edx_;
__asm__(
"cpuid"
: "=a" (eax_), "=b" (ebx_), "=c" (ecx_), "=d" (edx_)
: "0" (level)
);
*eax_out = eax_;
*ebx_out = ebx_;
*ecx_out = ecx_;
*edx_out = edx_;
}
#endif /* !ASM_FILE */