xref: /haiku/headers/private/kernel/arch/x86/arch_cpu.h (revision 922e7ba1f3228e6f28db69b0ded8f86eb32dea17)
1 /*
2  * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  *
5  * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
6  * Distributed under the terms of the NewOS License.
7  */
8 #ifndef _KERNEL_ARCH_x86_CPU_H
9 #define _KERNEL_ARCH_x86_CPU_H
10 
11 
12 #ifndef _ASSEMBLER
13 
14 #include <module.h>
15 #include <arch/x86/descriptors.h>
16 
17 #endif	// !_ASSEMBLER
18 
19 
20 #undef PAUSE
21 #define PAUSE() asm volatile ("pause;")
22 
23 
24 // MSR registers (possibly Intel specific)
25 #define IA32_MSR_TSC					0x10
26 #define IA32_MSR_APIC_BASE				0x1b
27 
28 #define IA32_MSR_MTRR_CAPABILITIES		0xfe
29 #define IA32_MSR_SYSENTER_CS			0x174
30 #define IA32_MSR_SYSENTER_ESP			0x175
31 #define IA32_MSR_SYSENTER_EIP			0x176
32 #define IA32_MSR_MTRR_DEFAULT_TYPE		0x2ff
33 #define IA32_MSR_MTRR_PHYSICAL_BASE_0	0x200
34 #define IA32_MSR_MTRR_PHYSICAL_MASK_0	0x201
35 
36 // x86 features from cpuid eax 1, edx register
37 // reference http://www.intel.com/assets/pdf/appnote/241618.pdf (Table 5-5)
38 #define IA32_FEATURE_FPU	0x00000001 // x87 fpu
39 #define IA32_FEATURE_VME	0x00000002 // virtual 8086
40 #define IA32_FEATURE_DE		0x00000004 // debugging extensions
41 #define IA32_FEATURE_PSE	0x00000008 // page size extensions
42 #define IA32_FEATURE_TSC	0x00000010 // rdtsc instruction
43 #define IA32_FEATURE_MSR	0x00000020 // rdmsr/wrmsr instruction
44 #define IA32_FEATURE_PAE	0x00000040 // extended 3 level page table addressing
45 #define IA32_FEATURE_MCE	0x00000080 // machine check exception
46 #define IA32_FEATURE_CX8	0x00000100 // cmpxchg8b instruction
47 #define IA32_FEATURE_APIC	0x00000200 // local apic on chip
48 #define IA32_FEATURE_SEP	0x00000800 // SYSENTER/SYSEXIT
49 #define IA32_FEATURE_MTRR	0x00001000 // MTRR
50 #define IA32_FEATURE_PGE	0x00002000 // paging global bit
51 #define IA32_FEATURE_MCA	0x00004000 // machine check architecture
52 #define IA32_FEATURE_CMOV	0x00008000 // cmov instruction
53 #define IA32_FEATURE_PAT	0x00010000 // page attribute table
54 #define IA32_FEATURE_PSE36	0x00020000 // page size extensions with 4MB pages
55 #define IA32_FEATURE_PSN	0x00040000 // processor serial number
56 #define IA32_FEATURE_CLFSH	0x00080000 // cflush instruction
57 #define IA32_FEATURE_DS		0x00200000 // debug store
58 #define IA32_FEATURE_ACPI	0x00400000 // thermal monitor and clock ctrl
59 #define IA32_FEATURE_MMX	0x00800000 // mmx instructions
60 #define IA32_FEATURE_FXSR	0x01000000 // FXSAVE/FXRSTOR instruction
61 #define IA32_FEATURE_SSE	0x02000000 // SSE
62 #define IA32_FEATURE_SSE2	0x04000000 // SSE2
63 #define IA32_FEATURE_SS		0x08000000 // self snoop
64 #define IA32_FEATURE_HTT	0x10000000 // hyperthreading
65 #define IA32_FEATURE_TM		0x20000000 // thermal monitor
66 #define IA32_FEATURE_PBE	0x80000000 // pending break enable
67 
68 // x86 features from cpuid eax 1, ecx register
69 // reference http://www.intel.com/assets/pdf/appnote/241618.pdf (Table 5-4)
70 #define IA32_FEATURE_EXT_SSE3		0x00000001	// SSE3
71 #define IA32_FEATURE_EXT_PCLMULQDQ	0x00000002	// PCLMULQDQ Instruction
72 #define IA32_FEATURE_EXT_DTES64		0x00000004	// 64-Bit Debug Store
73 #define IA32_FEATURE_EXT_MONITOR	0x00000008	// MONITOR/MWAIT
74 #define IA32_FEATURE_EXT_DSCPL		0x00000010	// CPL qualified debug store
75 #define IA32_FEATURE_EXT_VMX		0x00000020	// Virtual Machine Extensions
76 #define IA32_FEATURE_EXT_SMX		0x00000040	// Safer Mode Extensions
77 #define IA32_FEATURE_EXT_EST		0x00000080	// Enhanced SpeedStep
78 #define IA32_FEATURE_EXT_TM2		0x00000100	// Thermal Monitor 2
79 #define IA32_FEATURE_EXT_SSSE3		0x00000200	// Supplemental SSE-3
80 #define IA32_FEATURE_EXT_CNXTID		0x00000400	// L1 Context ID
81 #define IA32_FEATURE_EXT_FMA		0x00001000	// Fused Multiply Add
82 #define IA32_FEATURE_EXT_CX16		0x00002000	// CMPXCHG16B
83 #define IA32_FEATURE_EXT_XTPR		0x00004000	// xTPR Update Control
84 #define IA32_FEATURE_EXT_PDCM		0x00008000	// Perfmon and Debug Capability
85 #define IA32_FEATURE_EXT_PCID		0x00020000	// Process Context Identifiers
86 #define IA32_FEATURE_EXT_DCA		0x00040000	// Direct Cache Access
87 #define IA32_FEATURE_EXT_SSE4_1		0x00080000	// SSE4.1
88 #define IA32_FEATURE_EXT_SSE4_2		0x00100000	// SSE4.2
89 #define IA32_FEATURE_EXT_X2APIC		0x00200000	// Extended xAPIC Support
90 #define IA32_FEATURE_EXT_MOVBE 		0x00400000	// MOVBE Instruction
91 #define IA32_FEATURE_EXT_POPCNT		0x00800000	// POPCNT Instruction
92 #define IA32_FEATURE_EXT_TSCDEADLINE	0x01000000	// Time Stamp Counter Deadline
93 #define IA32_FEATURE_EXT_AES		0x02000000	// AES Instruction Extensions
94 #define IA32_FEATURE_EXT_XSAVE		0x04000000	// XSAVE/XSTOR States
95 #define IA32_FEATURE_EXT_OSXSAVE	0x08000000	// OS-Enabled XSAVE
96 #define IA32_FEATURE_EXT_AVX		0x10000000	// Advanced Vector Extensions
97 #define IA32_FEATURE_EXT_F16C		0x20000000	// 16-bit FP conversion
98 #define IA32_FEATURE_EXT_RDRND		0x40000000	// RDRAND instruction
99 #define IA32_FEATURE_EXT_HYPERVISOR	0x80000000	// Running on a hypervisor
100 
101 // x86 features from cpuid eax 0x80000001, edx register (AMD)
102 // only care about the ones that are unique to this register
103 #define IA32_FEATURE_AMD_EXT_SYSCALL	(1 << 11)	// SYSCALL/SYSRET
104 #define IA32_FEATURE_AMD_EXT_NX			(1 << 20)	// no execute bit
105 #define IA32_FEATURE_AMD_EXT_MMXEXT		(1 << 22)	// mmx extensions
106 #define IA32_FEATURE_AMD_EXT_FFXSR		(1 << 25)	// fast FXSAVE/FXRSTOR
107 #define IA32_FEATURE_AMD_EXT_RDTSCP		(1 << 27)	// rdtscp instruction
108 #define IA32_FEATURE_AMD_EXT_LONG		(1 << 29)	// long mode
109 #define IA32_FEATURE_AMD_EXT_3DNOWEXT	(1 << 30)	// 3DNow! extensions
110 #define IA32_FEATURE_AMD_EXT_3DNOW		(1 << 31)	// 3DNow!
111 
112 // cr4 flags
113 #define IA32_CR4_PAE					(1UL << 5)
114 #define IA32_CR4_GLOBAL_PAGES			(1UL << 7)
115 
116 // Memory type ranges
117 #define IA32_MTR_UNCACHED				0
118 #define IA32_MTR_WRITE_COMBINING		1
119 #define IA32_MTR_WRITE_THROUGH			4
120 #define IA32_MTR_WRITE_PROTECTED		5
121 #define IA32_MTR_WRITE_BACK				6
122 
123 
124 // EFLAGS register
125 #define X86_EFLAGS_CARRY						0x00000001
126 #define X86_EFLAGS_RESERVED1					0x00000002
127 #define X86_EFLAGS_PARITY						0x00000004
128 #define X86_EFLAGS_AUXILIARY_CARRY				0x00000010
129 #define X86_EFLAGS_ZERO							0x00000040
130 #define X86_EFLAGS_SIGN							0x00000080
131 #define X86_EFLAGS_TRAP							0x00000100
132 #define X86_EFLAGS_INTERRUPT					0x00000200
133 #define X86_EFLAGS_DIRECTION					0x00000400
134 #define X86_EFLAGS_OVERFLOW						0x00000800
135 #define X86_EFLAGS_IO_PRIVILEG_LEVEL			0x00003000
136 #define X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT		12
137 #define X86_EFLAGS_NESTED_TASK					0x00004000
138 #define X86_EFLAGS_RESUME						0x00010000
139 #define X86_EFLAGS_V86_MODE						0x00020000
140 #define X86_EFLAGS_ALIGNMENT_CHECK				0x00040000
141 #define X86_EFLAGS_VIRTUAL_INTERRUPT			0x00080000
142 #define X86_EFLAGS_VIRTUAL_INTERRUPT_PENDING	0x00100000
143 #define X86_EFLAGS_ID							0x00200000
144 
145 #define X86_EFLAGS_USER_FLAGS	(X86_EFLAGS_CARRY | X86_EFLAGS_PARITY \
146 	| X86_EFLAGS_AUXILIARY_CARRY | X86_EFLAGS_ZERO | X86_EFLAGS_SIGN \
147 	| X86_EFLAGS_DIRECTION | X86_EFLAGS_OVERFLOW)
148 
149 
150 // iframe types
151 #define IFRAME_TYPE_SYSCALL				0x1
152 #define IFRAME_TYPE_OTHER				0x2
153 #define IFRAME_TYPE_MASK				0xf
154 
155 
156 #ifndef _ASSEMBLER
157 
158 struct X86PagingStructures;
159 
160 
161 typedef struct x86_mtrr_info {
162 	uint64	base;
163 	uint64	size;
164 	uint8	type;
165 } x86_mtrr_info;
166 
167 typedef struct x86_optimized_functions {
168 	void 	(*memcpy)(void* dest, const void* source, size_t count);
169 	void*	memcpy_end;
170 	void 	(*memset)(void* dest, int value, size_t count);
171 	void*	memset_end;
172 } x86_optimized_functions;
173 
174 typedef struct x86_cpu_module_info {
175 	module_info	info;
176 	uint32		(*count_mtrrs)(void);
177 	void		(*init_mtrrs)(void);
178 
179 	void		(*set_mtrr)(uint32 index, uint64 base, uint64 length,
180 					uint8 type);
181 	status_t	(*get_mtrr)(uint32 index, uint64* _base, uint64* _length,
182 					uint8* _type);
183 	void		(*set_mtrrs)(uint8 defaultType, const x86_mtrr_info* infos,
184 					uint32 count);
185 
186 	void		(*get_optimized_functions)(x86_optimized_functions* functions);
187 } x86_cpu_module_info;
188 
189 
190 struct tss {
191 	uint16 prev_task;
192 	uint16 unused0;
193 	uint32 sp0;
194 	uint32 ss0;
195 	uint32 sp1;
196 	uint32 ss1;
197 	uint32 sp2;
198 	uint32 ss2;
199 	uint32 cr3;
200 	uint32 eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi;
201 	uint32 es, cs, ss, ds, fs, gs;
202 	uint32 ldt_seg_selector;
203 	uint16 unused1;
204 	uint16 io_map_base;
205 };
206 
207 struct iframe {
208 	uint32 type;	// iframe type
209 	uint32 gs;
210 	uint32 fs;
211 	uint32 es;
212 	uint32 ds;
213 	uint32 edi;
214 	uint32 esi;
215 	uint32 ebp;
216 	uint32 esp;
217 	uint32 ebx;
218 	uint32 edx;
219 	uint32 ecx;
220 	uint32 eax;
221 	uint32 orig_eax;
222 	uint32 orig_edx;
223 	uint32 vector;
224 	uint32 error_code;
225 	uint32 eip;
226 	uint32 cs;
227 	uint32 flags;
228 
229 	// user_esp and user_ss are only present when the iframe is a userland
230 	// iframe (IFRAME_IS_USER()). A kernel iframe is shorter.
231 	uint32 user_esp;
232 	uint32 user_ss;
233 };
234 
235 struct vm86_iframe {
236 	uint32 type;	// iframe type
237 	uint32 __null_gs;
238 	uint32 __null_fs;
239 	uint32 __null_es;
240 	uint32 __null_ds;
241 	uint32 edi;
242 	uint32 esi;
243 	uint32 ebp;
244 	uint32 __kern_esp;
245 	uint32 ebx;
246 	uint32 edx;
247 	uint32 ecx;
248 	uint32 eax;
249 	uint32 orig_eax;
250 	uint32 orig_edx;
251 	uint32 vector;
252 	uint32 error_code;
253 	uint32 eip;
254 	uint16 cs, __csh;
255 	uint32 flags;
256 	uint32 esp;
257 	uint16 ss, __ssh;
258 
259 	/* vm86 mode specific part */
260 	uint16 es, __esh;
261 	uint16 ds, __dsh;
262 	uint16 fs, __fsh;
263 	uint16 gs, __gsh;
264 };
265 
266 #define IFRAME_IS_USER(f) ((f)->cs == USER_CODE_SEG \
267 							|| ((f)->flags & 0x20000) != 0)
268 #define IFRAME_IS_VM86(f) (((f)->flags & 0x20000) != 0)
269 
270 // features
271 enum x86_feature_type {
272 	FEATURE_COMMON = 0,     // cpuid eax=1, ecx register
273 	FEATURE_EXT,            // cpuid eax=1, edx register
274 	FEATURE_EXT_AMD,        // cpuid eax=0x80000001, edx register (AMD)
275 
276 	FEATURE_NUM
277 };
278 
279 enum x86_vendors {
280 	VENDOR_INTEL = 0,
281 	VENDOR_AMD,
282 	VENDOR_CYRIX,
283 	VENDOR_UMC,
284 	VENDOR_NEXGEN,
285 	VENDOR_CENTAUR,
286 	VENDOR_RISE,
287 	VENDOR_TRANSMETA,
288 	VENDOR_NSC,
289 
290 	VENDOR_NUM,
291 	VENDOR_UNKNOWN,
292 };
293 
294 typedef struct arch_cpu_info {
295 	// saved cpu info
296 	enum x86_vendors	vendor;
297 	uint32				feature[FEATURE_NUM];
298 	char				model_name[49];
299 	const char*			vendor_name;
300 	int					type;
301 	int					family;
302 	int					extended_family;
303 	int					stepping;
304 	int					model;
305 	int					extended_model;
306 
307 	struct X86PagingStructures* active_paging_structures;
308 
309 	uint32				dr6;	// temporary storage for debug registers (cf.
310 	uint32				dr7;	// x86_exit_user_debug_at_kernel_entry())
311 
312 	// local TSS for this cpu
313 	struct tss			tss;
314 	struct tss			double_fault_tss;
315 } arch_cpu_info;
316 
317 #ifdef __cplusplus
318 extern "C" {
319 #endif
320 
321 #define nop() __asm__ ("nop"::)
322 
323 struct arch_thread;
324 
325 void __x86_setup_system_time(uint32 conversionFactor,
326 	uint32 conversionFactorNsecs, bool conversionFactorNsecsShift);
327 void x86_context_switch(struct arch_thread* oldState,
328 	struct arch_thread* newState);
329 void x86_userspace_thread_exit(void);
330 void x86_end_userspace_thread_exit(void);
331 void x86_swap_pgdir(uint32 newPageDir);
332 void i386_set_tss_and_kstack(addr_t kstack);
333 void i386_fnsave(void* fpuState);
334 void i386_fxsave(void* fpuState);
335 void i386_frstor(const void* fpuState);
336 void i386_fxrstor(const void* fpuState);
337 void i386_fnsave_swap(void* oldFpuState, const void* newFpuState);
338 void i386_fxsave_swap(void* oldFpuState, const void* newFpuState);
339 uint32 x86_read_ebp();
340 uint32 x86_read_cr0();
341 void x86_write_cr0(uint32 value);
342 uint32 x86_read_cr4();
343 void x86_write_cr4(uint32 value);
344 uint64 x86_read_msr(uint32 registerNumber);
345 void x86_write_msr(uint32 registerNumber, uint64 value);
346 void x86_set_task_gate(int32 cpu, int32 n, int32 segment);
347 void* x86_get_idt(int32 cpu);
348 uint32 x86_count_mtrrs(void);
349 void x86_set_mtrr(uint32 index, uint64 base, uint64 length, uint8 type);
350 status_t x86_get_mtrr(uint32 index, uint64* _base, uint64* _length,
351 	uint8* _type);
352 void x86_set_mtrrs(uint8 defaultType, const x86_mtrr_info* infos,
353 	uint32 count);
354 bool x86_check_feature(uint32 feature, enum x86_feature_type type);
355 void* x86_get_double_fault_stack(int32 cpu, size_t* _size);
356 int32 x86_double_fault_get_cpu(void);
357 void x86_double_fault_exception(struct iframe* frame);
358 void x86_page_fault_exception_double_fault(struct iframe* frame);
359 
360 
361 #define read_cr3(value) \
362 	__asm__("movl	%%cr3,%0" : "=r" (value))
363 
364 #define write_cr3(value) \
365 	__asm__("movl	%0,%%cr3" : : "r" (value))
366 
367 #define read_dr3(value) \
368 	__asm__("movl	%%dr3,%0" : "=r" (value))
369 
370 #define write_dr3(value) \
371 	__asm__("movl	%0,%%dr3" : : "r" (value))
372 
373 #define invalidate_TLB(va) \
374 	__asm__("invlpg (%0)" : : "r" (va))
375 
376 #define wbinvd() \
377 	__asm__("wbinvd")
378 
379 #define out8(value,port) \
380 	__asm__ ("outb %%al,%%dx" : : "a" (value), "d" (port))
381 
382 #define out16(value,port) \
383 	__asm__ ("outw %%ax,%%dx" : : "a" (value), "d" (port))
384 
385 #define out32(value,port) \
386 	__asm__ ("outl %%eax,%%dx" : : "a" (value), "d" (port))
387 
388 #define in8(port) ({ \
389 	uint8 _v; \
390 	__asm__ volatile ("inb %%dx,%%al" : "=a" (_v) : "d" (port)); \
391 	_v; \
392 })
393 
394 #define in16(port) ({ \
395 	uint16 _v; \
396 	__asm__ volatile ("inw %%dx,%%ax":"=a" (_v) : "d" (port)); \
397 	_v; \
398 })
399 
400 #define in32(port) ({ \
401 	uint32 _v; \
402 	__asm__ volatile ("inl %%dx,%%eax":"=a" (_v) : "d" (port)); \
403 	_v; \
404 })
405 
406 #define out8_p(value,port) \
407 	__asm__ ("outb %%al,%%dx\n" \
408 		"\tjmp 1f\n" \
409 		"1:\tjmp 1f\n" \
410 		"1:" : : "a" (value), "d" (port))
411 
412 #define in8_p(port) ({ \
413 	uint8 _v; \
414 	__asm__ volatile ("inb %%dx,%%al\n" \
415 		"\tjmp 1f\n" \
416 		"1:\tjmp 1f\n" \
417 		"1:" : "=a" (_v) : "d" (port)); \
418 	_v; \
419 })
420 
421 extern segment_descriptor* gGDT;
422 
423 
424 #ifdef __cplusplus
425 }	// extern "C" {
426 #endif
427 
428 #endif	// !_ASSEMBLER
429 
430 #endif	/* _KERNEL_ARCH_x86_CPU_H */
431