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