2002-07-09 16:24:59 +04:00
|
|
|
/*
|
2009-10-27 21:22:39 +03:00
|
|
|
* Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
|
2005-10-27 03:39:38 +04:00
|
|
|
* Distributed under the terms of the MIT License.
|
|
|
|
*
|
|
|
|
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
|
|
|
* Distributed under the terms of the NewOS License.
|
|
|
|
*/
|
2002-07-09 16:24:59 +04:00
|
|
|
#ifndef _KERNEL_ARCH_x86_CPU_H
|
|
|
|
#define _KERNEL_ARCH_x86_CPU_H
|
|
|
|
|
2004-11-19 22:40:05 +03:00
|
|
|
|
2008-01-11 03:36:44 +03:00
|
|
|
#ifndef _ASSEMBLER
|
|
|
|
|
2005-12-12 20:04:36 +03:00
|
|
|
#include <module.h>
|
2002-07-25 00:59:25 +04:00
|
|
|
#include <arch/x86/descriptors.h>
|
2002-07-09 16:24:59 +04:00
|
|
|
|
2008-01-11 03:36:44 +03:00
|
|
|
#endif // !_ASSEMBLER
|
|
|
|
|
2004-11-19 22:40:05 +03:00
|
|
|
|
2008-10-17 20:53:31 +04:00
|
|
|
#undef PAUSE
|
|
|
|
#define PAUSE() asm volatile ("pause;")
|
|
|
|
|
|
|
|
|
2005-10-27 03:39:38 +04:00
|
|
|
// MSR registers (possibly Intel specific)
|
2009-04-21 04:38:11 +04:00
|
|
|
#define IA32_MSR_TSC 0x10
|
2005-12-13 03:06:52 +03:00
|
|
|
#define IA32_MSR_APIC_BASE 0x1b
|
|
|
|
|
|
|
|
#define IA32_MSR_MTRR_CAPABILITIES 0xfe
|
2008-01-11 03:36:44 +03:00
|
|
|
#define IA32_MSR_SYSENTER_CS 0x174
|
|
|
|
#define IA32_MSR_SYSENTER_ESP 0x175
|
|
|
|
#define IA32_MSR_SYSENTER_EIP 0x176
|
2005-12-13 03:06:52 +03:00
|
|
|
#define IA32_MSR_MTRR_DEFAULT_TYPE 0x2ff
|
|
|
|
#define IA32_MSR_MTRR_PHYSICAL_BASE_0 0x200
|
|
|
|
#define IA32_MSR_MTRR_PHYSICAL_MASK_0 0x201
|
2005-03-02 02:52:09 +03:00
|
|
|
|
2007-02-05 04:46:28 +03:00
|
|
|
// x86 features from cpuid eax 1, edx register
|
2009-10-27 21:22:39 +03:00
|
|
|
#define IA32_FEATURE_FPU 0x00000001 // x87 fpu
|
|
|
|
#define IA32_FEATURE_VME 0x00000002 // virtual 8086
|
|
|
|
#define IA32_FEATURE_DE 0x00000004 // debugging extensions
|
|
|
|
#define IA32_FEATURE_PSE 0x00000008 // page size extensions
|
|
|
|
#define IA32_FEATURE_TSC 0x00000010 // rdtsc instruction
|
|
|
|
#define IA32_FEATURE_MSR 0x00000020 // rdmsr/wrmsr instruction
|
|
|
|
#define IA32_FEATURE_PAE 0x00000040 // extended 3 level page table addressing
|
|
|
|
#define IA32_FEATURE_MCE 0x00000080 // machine check exception
|
|
|
|
#define IA32_FEATURE_CX8 0x00000100 // cmpxchg8b instruction
|
|
|
|
#define IA32_FEATURE_APIC 0x00000200 // local apic on chip
|
|
|
|
#define IA32_FEATURE_SEP 0x00000800 // SYSENTER/SYSEXIT
|
|
|
|
#define IA32_FEATURE_MTRR 0x00001000 // MTRR
|
|
|
|
#define IA32_FEATURE_PGE 0x00002000 // paging global bit
|
|
|
|
#define IA32_FEATURE_MCA 0x00004000 // machine check architecture
|
|
|
|
#define IA32_FEATURE_CMOV 0x00008000 // cmov instruction
|
|
|
|
#define IA32_FEATURE_PAT 0x00010000 // page attribute table
|
|
|
|
#define IA32_FEATURE_PSE36 0x00020000 // page size extensions with 4MB pages
|
|
|
|
#define IA32_FEATURE_PSN 0x00040000 // processor serial number
|
|
|
|
#define IA32_FEATURE_CLFSH 0x00080000 // cflush instruction
|
|
|
|
#define IA32_FEATURE_DS 0x00200000 // debug store
|
|
|
|
#define IA32_FEATURE_ACPI 0x00400000 // thermal monitor and clock ctrl
|
|
|
|
#define IA32_FEATURE_MMX 0x00800000 // mmx instructions
|
|
|
|
#define IA32_FEATURE_FXSR 0x01000000 // FXSAVE/FXRSTOR instruction
|
|
|
|
#define IA32_FEATURE_SSE 0x02000000 // SSE
|
|
|
|
#define IA32_FEATURE_SSE2 0x04000000 // SSE2
|
|
|
|
#define IA32_FEATURE_SS 0x08000000 // self snoop
|
|
|
|
#define IA32_FEATURE_HTT 0x10000000 // hyperthreading
|
|
|
|
#define IA32_FEATURE_TM 0x20000000 // thermal monitor
|
|
|
|
#define IA32_FEATURE_PBE 0x80000000 // pending break enable
|
2007-02-05 04:46:28 +03:00
|
|
|
|
|
|
|
// x86 features from cpuid eax 1, ecx register
|
2009-10-27 21:22:39 +03:00
|
|
|
#define IA32_FEATURE_EXT_SSE3 0x00000001 // SSE3
|
|
|
|
#define IA32_FEATURE_EXT_MONITOR 0x00000008 // MONITOR/MWAIT
|
|
|
|
#define IA32_FEATURE_EXT_DSCPL 0x00000010 // CPL qualified debug store
|
|
|
|
#define IA32_FEATURE_EXT_EST 0x00000080 // speedstep
|
|
|
|
#define IA32_FEATURE_EXT_TM2 0x00000100 // thermal monitor 2
|
|
|
|
#define IA32_FEATURE_EXT_CNXTID 0x00000400 // L1 context ID
|
2007-02-05 04:46:28 +03:00
|
|
|
|
|
|
|
// x86 features from cpuid eax 0x80000001, edx register (AMD)
|
|
|
|
// only care about the ones that are unique to this register
|
2009-10-27 21:22:39 +03:00
|
|
|
#define IA32_FEATURE_AMD_EXT_SYSCALL (1 << 11) // SYSCALL/SYSRET
|
|
|
|
#define IA32_FEATURE_AMD_EXT_NX (1 << 20) // no execute bit
|
|
|
|
#define IA32_FEATURE_AMD_EXT_MMXEXT (1 << 22) // mmx extensions
|
|
|
|
#define IA32_FEATURE_AMD_EXT_FFXSR (1 << 25) // fast FXSAVE/FXRSTOR
|
|
|
|
#define IA32_FEATURE_AMD_EXT_RDTSCP (1 << 27) // rdtscp instruction
|
|
|
|
#define IA32_FEATURE_AMD_EXT_LONG (1 << 29) // long mode
|
|
|
|
#define IA32_FEATURE_AMD_EXT_3DNOWEXT (1 << 30) // 3DNow! extensions
|
|
|
|
#define IA32_FEATURE_AMD_EXT_3DNOW (1 << 31) // 3DNow!
|
2005-12-16 15:25:49 +03:00
|
|
|
|
2005-12-14 20:07:37 +03:00
|
|
|
// cr4 flags
|
2010-06-10 01:21:48 +04:00
|
|
|
#define IA32_CR4_PAE (1UL << 5)
|
2009-10-27 21:22:39 +03:00
|
|
|
#define IA32_CR4_GLOBAL_PAGES (1UL << 7)
|
2005-12-14 20:07:37 +03:00
|
|
|
|
The short story: we now have MTRR support on Intel and AMD CPUs (the latter
has not yet been tested, though - I'll do this after this commit):
* Removed the arch_memory_type stuff from vm_area; since there are only 8 memory
ranges on x86, it's simply overkill. The MTRR code now remembers the area ID
and finds the MTRR that way (it could also iterate over the existing MTRRs).
* Introduced some post_modules() init functions.
* If the other x86 CPUs out there don't differ a lot, MTRR functionality might
be put back into the kernel.
* x86_write_msr() was broken, it wrote the 64 bit number with the 32 bit words
switched - it took me some time (and lots of #GPs) to figure that one out.
* Removed the macro read_ebp() and introduced a function x86_read_ebp()
(it's not really a time critical call).
* Followed the Intel docs on how to change MTRRs (symmetrically on all CPUs
with caches turned off).
* Asking for memory types will automatically change the requested length to
a power of two - note that BeOS seems to behave in the same, although that's
not really very clean.
* fixed MTRRs are ignored for now - we should make sure at least, though,
that they are identical on all CPUs (or turn them off, even though I'd
prefer the BIOS stuff to be uncacheable, which we don't enforce yet, though).
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15528 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-12-13 19:34:29 +03:00
|
|
|
// Memory type ranges
|
2009-10-27 21:22:39 +03:00
|
|
|
#define IA32_MTR_UNCACHED 0
|
|
|
|
#define IA32_MTR_WRITE_COMBINING 1
|
|
|
|
#define IA32_MTR_WRITE_THROUGH 4
|
|
|
|
#define IA32_MTR_WRITE_PROTECTED 5
|
|
|
|
#define IA32_MTR_WRITE_BACK 6
|
2005-12-12 20:04:36 +03:00
|
|
|
|
2008-01-11 03:36:44 +03:00
|
|
|
|
|
|
|
// iframe types
|
2009-10-27 21:22:39 +03:00
|
|
|
#define IFRAME_TYPE_SYSCALL 0x1
|
|
|
|
#define IFRAME_TYPE_OTHER 0x2
|
|
|
|
#define IFRAME_TYPE_MASK 0xf
|
2008-01-11 03:36:44 +03:00
|
|
|
|
|
|
|
|
|
|
|
#ifndef _ASSEMBLER
|
|
|
|
|
2010-06-06 01:51:05 +04:00
|
|
|
struct X86PagingStructures;
|
|
|
|
|
|
|
|
|
2009-11-23 18:06:08 +03:00
|
|
|
typedef struct x86_mtrr_info {
|
|
|
|
uint64 base;
|
|
|
|
uint64 size;
|
|
|
|
uint8 type;
|
|
|
|
} x86_mtrr_info;
|
|
|
|
|
2008-01-11 03:36:44 +03:00
|
|
|
typedef struct x86_optimized_functions {
|
|
|
|
void (*memcpy)(void* dest, const void* source, size_t count);
|
|
|
|
void* memcpy_end;
|
2008-10-10 22:43:46 +04:00
|
|
|
void (*memset)(void* dest, int value, size_t count);
|
|
|
|
void* memset_end;
|
2008-01-11 03:36:44 +03:00
|
|
|
} x86_optimized_functions;
|
|
|
|
|
2005-12-12 20:04:36 +03:00
|
|
|
typedef struct x86_cpu_module_info {
|
|
|
|
module_info info;
|
|
|
|
uint32 (*count_mtrrs)(void);
|
The short story: we now have MTRR support on Intel and AMD CPUs (the latter
has not yet been tested, though - I'll do this after this commit):
* Removed the arch_memory_type stuff from vm_area; since there are only 8 memory
ranges on x86, it's simply overkill. The MTRR code now remembers the area ID
and finds the MTRR that way (it could also iterate over the existing MTRRs).
* Introduced some post_modules() init functions.
* If the other x86 CPUs out there don't differ a lot, MTRR functionality might
be put back into the kernel.
* x86_write_msr() was broken, it wrote the 64 bit number with the 32 bit words
switched - it took me some time (and lots of #GPs) to figure that one out.
* Removed the macro read_ebp() and introduced a function x86_read_ebp()
(it's not really a time critical call).
* Followed the Intel docs on how to change MTRRs (symmetrically on all CPUs
with caches turned off).
* Asking for memory types will automatically change the requested length to
a power of two - note that BeOS seems to behave in the same, although that's
not really very clean.
* fixed MTRRs are ignored for now - we should make sure at least, though,
that they are identical on all CPUs (or turn them off, even though I'd
prefer the BIOS stuff to be uncacheable, which we don't enforce yet, though).
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15528 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-12-13 19:34:29 +03:00
|
|
|
void (*init_mtrrs)(void);
|
2005-12-13 03:06:52 +03:00
|
|
|
|
2009-10-27 21:22:39 +03:00
|
|
|
void (*set_mtrr)(uint32 index, uint64 base, uint64 length,
|
|
|
|
uint8 type);
|
|
|
|
status_t (*get_mtrr)(uint32 index, uint64* _base, uint64* _length,
|
|
|
|
uint8* _type);
|
2010-02-18 16:52:43 +03:00
|
|
|
void (*set_mtrrs)(uint8 defaultType, const x86_mtrr_info* infos,
|
|
|
|
uint32 count);
|
2008-01-11 03:36:44 +03:00
|
|
|
|
|
|
|
void (*get_optimized_functions)(x86_optimized_functions* functions);
|
2005-12-12 20:04:36 +03:00
|
|
|
} x86_cpu_module_info;
|
|
|
|
|
|
|
|
|
2002-07-09 16:24:59 +04:00
|
|
|
struct tss {
|
|
|
|
uint16 prev_task;
|
|
|
|
uint16 unused0;
|
|
|
|
uint32 sp0;
|
|
|
|
uint32 ss0;
|
|
|
|
uint32 sp1;
|
|
|
|
uint32 ss1;
|
|
|
|
uint32 sp2;
|
|
|
|
uint32 ss2;
|
|
|
|
uint32 cr3;
|
|
|
|
uint32 eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi;
|
|
|
|
uint32 es, cs, ss, ds, fs, gs;
|
|
|
|
uint32 ldt_seg_selector;
|
|
|
|
uint16 unused1;
|
|
|
|
uint16 io_map_base;
|
|
|
|
};
|
|
|
|
|
2002-08-14 01:42:53 +04:00
|
|
|
struct iframe {
|
2008-01-11 03:36:44 +03:00
|
|
|
uint32 type; // iframe type
|
2005-10-27 03:39:38 +04:00
|
|
|
uint32 gs;
|
|
|
|
uint32 fs;
|
|
|
|
uint32 es;
|
|
|
|
uint32 ds;
|
|
|
|
uint32 edi;
|
|
|
|
uint32 esi;
|
|
|
|
uint32 ebp;
|
|
|
|
uint32 esp;
|
|
|
|
uint32 ebx;
|
|
|
|
uint32 edx;
|
|
|
|
uint32 ecx;
|
|
|
|
uint32 eax;
|
|
|
|
uint32 orig_eax;
|
|
|
|
uint32 orig_edx;
|
|
|
|
uint32 vector;
|
|
|
|
uint32 error_code;
|
|
|
|
uint32 eip;
|
|
|
|
uint32 cs;
|
|
|
|
uint32 flags;
|
2008-08-05 01:45:50 +04:00
|
|
|
|
|
|
|
// user_esp and user_ss are only present when the iframe is a userland
|
|
|
|
// iframe (IFRAME_IS_USER()). A kernel iframe is shorter.
|
2005-10-27 03:39:38 +04:00
|
|
|
uint32 user_esp;
|
|
|
|
uint32 user_ss;
|
2002-08-14 01:42:53 +04:00
|
|
|
};
|
|
|
|
|
2008-05-22 17:54:28 +04:00
|
|
|
struct vm86_iframe {
|
|
|
|
uint32 type; // iframe type
|
|
|
|
uint32 __null_gs;
|
|
|
|
uint32 __null_fs;
|
|
|
|
uint32 __null_es;
|
|
|
|
uint32 __null_ds;
|
|
|
|
uint32 edi;
|
|
|
|
uint32 esi;
|
|
|
|
uint32 ebp;
|
|
|
|
uint32 __kern_esp;
|
|
|
|
uint32 ebx;
|
|
|
|
uint32 edx;
|
|
|
|
uint32 ecx;
|
|
|
|
uint32 eax;
|
|
|
|
uint32 orig_eax;
|
|
|
|
uint32 orig_edx;
|
|
|
|
uint32 vector;
|
|
|
|
uint32 error_code;
|
|
|
|
uint32 eip;
|
|
|
|
uint16 cs, __csh;
|
|
|
|
uint32 flags;
|
|
|
|
uint32 esp;
|
|
|
|
uint16 ss, __ssh;
|
|
|
|
|
|
|
|
/* vm86 mode specific part */
|
|
|
|
uint16 es, __esh;
|
|
|
|
uint16 ds, __dsh;
|
|
|
|
uint16 fs, __fsh;
|
|
|
|
uint16 gs, __gsh;
|
|
|
|
};
|
|
|
|
|
2009-10-27 21:22:39 +03:00
|
|
|
#define IFRAME_IS_USER(f) ((f)->cs == USER_CODE_SEG \
|
|
|
|
|| ((f)->flags & 0x20000) != 0)
|
|
|
|
#define IFRAME_IS_VM86(f) (((f)->flags & 0x20000) != 0)
|
2008-05-22 15:59:47 +04:00
|
|
|
|
2007-02-05 04:46:28 +03:00
|
|
|
// features
|
|
|
|
enum x86_feature_type {
|
|
|
|
FEATURE_COMMON = 0, // cpuid eax=1, ecx register
|
|
|
|
FEATURE_EXT, // cpuid eax=1, edx register
|
|
|
|
FEATURE_EXT_AMD, // cpuid eax=0x80000001, edx register (AMD)
|
|
|
|
|
|
|
|
FEATURE_NUM
|
|
|
|
};
|
|
|
|
|
|
|
|
enum x86_vendors {
|
|
|
|
VENDOR_INTEL = 0,
|
|
|
|
VENDOR_AMD,
|
|
|
|
VENDOR_CYRIX,
|
|
|
|
VENDOR_UMC,
|
|
|
|
VENDOR_NEXGEN,
|
|
|
|
VENDOR_CENTAUR,
|
|
|
|
VENDOR_RISE,
|
|
|
|
VENDOR_TRANSMETA,
|
|
|
|
VENDOR_NSC,
|
|
|
|
|
|
|
|
VENDOR_NUM,
|
|
|
|
VENDOR_UNKNOWN,
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct arch_cpu_info {
|
2007-02-14 09:24:59 +03:00
|
|
|
// saved cpu info
|
2009-10-27 21:22:39 +03:00
|
|
|
enum x86_vendors vendor;
|
|
|
|
uint32 feature[FEATURE_NUM];
|
|
|
|
char model_name[49];
|
|
|
|
const char* vendor_name;
|
|
|
|
int type;
|
|
|
|
int family;
|
|
|
|
int extended_family;
|
|
|
|
int stepping;
|
|
|
|
int model;
|
|
|
|
int extended_model;
|
2007-02-14 09:24:59 +03:00
|
|
|
|
2010-06-06 01:51:05 +04:00
|
|
|
struct X86PagingStructures* active_paging_structures;
|
2008-10-22 19:12:32 +04:00
|
|
|
|
2010-03-26 03:03:53 +03:00
|
|
|
uint32 dr6; // temporary storage for debug registers (cf.
|
|
|
|
uint32 dr7; // x86_exit_user_debug_at_kernel_entry())
|
|
|
|
|
2007-02-14 09:24:59 +03:00
|
|
|
// local TSS for this cpu
|
2009-10-27 21:22:39 +03:00
|
|
|
struct tss tss;
|
|
|
|
struct tss double_fault_tss;
|
2007-02-05 04:46:28 +03:00
|
|
|
} arch_cpu_info;
|
2005-10-27 03:39:38 +04:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2002-07-09 16:24:59 +04:00
|
|
|
#define nop() __asm__ ("nop"::)
|
|
|
|
|
2004-10-12 07:54:03 +04:00
|
|
|
struct arch_thread;
|
|
|
|
|
2009-12-08 00:43:19 +03:00
|
|
|
void __x86_setup_system_time(uint32 conversionFactor,
|
|
|
|
uint32 conversionFactorNsecs, bool conversionFactorNsecsShift);
|
2010-06-06 02:09:24 +04:00
|
|
|
void x86_context_switch(struct arch_thread* oldState,
|
|
|
|
struct arch_thread* newState);
|
2007-01-12 21:26:32 +03:00
|
|
|
void x86_userspace_thread_exit(void);
|
|
|
|
void x86_end_userspace_thread_exit(void);
|
2007-01-12 23:40:39 +03:00
|
|
|
void x86_enter_userspace(addr_t entry, addr_t stackTop);
|
2010-06-06 01:53:32 +04:00
|
|
|
void x86_swap_pgdir(uint32 newPageDir);
|
2004-10-20 04:33:06 +04:00
|
|
|
void i386_set_tss_and_kstack(addr_t kstack);
|
2009-10-27 21:22:39 +03:00
|
|
|
void i386_fnsave(void* fpuState);
|
|
|
|
void i386_fxsave(void* fpuState);
|
|
|
|
void i386_frstor(const void* fpuState);
|
|
|
|
void i386_fxrstor(const void* fpuState);
|
|
|
|
void i386_fnsave_swap(void* oldFpuState, const void* newFpuState);
|
|
|
|
void i386_fxsave_swap(void* oldFpuState, const void* newFpuState);
|
The short story: we now have MTRR support on Intel and AMD CPUs (the latter
has not yet been tested, though - I'll do this after this commit):
* Removed the arch_memory_type stuff from vm_area; since there are only 8 memory
ranges on x86, it's simply overkill. The MTRR code now remembers the area ID
and finds the MTRR that way (it could also iterate over the existing MTRRs).
* Introduced some post_modules() init functions.
* If the other x86 CPUs out there don't differ a lot, MTRR functionality might
be put back into the kernel.
* x86_write_msr() was broken, it wrote the 64 bit number with the 32 bit words
switched - it took me some time (and lots of #GPs) to figure that one out.
* Removed the macro read_ebp() and introduced a function x86_read_ebp()
(it's not really a time critical call).
* Followed the Intel docs on how to change MTRRs (symmetrically on all CPUs
with caches turned off).
* Asking for memory types will automatically change the requested length to
a power of two - note that BeOS seems to behave in the same, although that's
not really very clean.
* fixed MTRRs are ignored for now - we should make sure at least, though,
that they are identical on all CPUs (or turn them off, even though I'd
prefer the BIOS stuff to be uncacheable, which we don't enforce yet, though).
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15528 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-12-13 19:34:29 +03:00
|
|
|
uint32 x86_read_ebp();
|
|
|
|
uint32 x86_read_cr0();
|
|
|
|
void x86_write_cr0(uint32 value);
|
2005-12-14 20:07:37 +03:00
|
|
|
uint32 x86_read_cr4();
|
|
|
|
void x86_write_cr4(uint32 value);
|
2005-12-12 20:04:36 +03:00
|
|
|
uint64 x86_read_msr(uint32 registerNumber);
|
|
|
|
void x86_write_msr(uint32 registerNumber, uint64 value);
|
2009-08-01 05:53:54 +04:00
|
|
|
void x86_set_task_gate(int32 cpu, int32 n, int32 segment);
|
|
|
|
void* x86_get_idt(int32 cpu);
|
2005-12-12 20:04:36 +03:00
|
|
|
uint32 x86_count_mtrrs(void);
|
The short story: we now have MTRR support on Intel and AMD CPUs (the latter
has not yet been tested, though - I'll do this after this commit):
* Removed the arch_memory_type stuff from vm_area; since there are only 8 memory
ranges on x86, it's simply overkill. The MTRR code now remembers the area ID
and finds the MTRR that way (it could also iterate over the existing MTRRs).
* Introduced some post_modules() init functions.
* If the other x86 CPUs out there don't differ a lot, MTRR functionality might
be put back into the kernel.
* x86_write_msr() was broken, it wrote the 64 bit number with the 32 bit words
switched - it took me some time (and lots of #GPs) to figure that one out.
* Removed the macro read_ebp() and introduced a function x86_read_ebp()
(it's not really a time critical call).
* Followed the Intel docs on how to change MTRRs (symmetrically on all CPUs
with caches turned off).
* Asking for memory types will automatically change the requested length to
a power of two - note that BeOS seems to behave in the same, although that's
not really very clean.
* fixed MTRRs are ignored for now - we should make sure at least, though,
that they are identical on all CPUs (or turn them off, even though I'd
prefer the BIOS stuff to be uncacheable, which we don't enforce yet, though).
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15528 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-12-13 19:34:29 +03:00
|
|
|
void x86_set_mtrr(uint32 index, uint64 base, uint64 length, uint8 type);
|
2009-10-27 21:22:39 +03:00
|
|
|
status_t x86_get_mtrr(uint32 index, uint64* _base, uint64* _length,
|
|
|
|
uint8* _type);
|
2010-02-18 16:52:43 +03:00
|
|
|
void x86_set_mtrrs(uint8 defaultType, const x86_mtrr_info* infos,
|
|
|
|
uint32 count);
|
2007-02-05 04:46:28 +03:00
|
|
|
bool x86_check_feature(uint32 feature, enum x86_feature_type type);
|
2008-08-04 06:51:38 +04:00
|
|
|
void* x86_get_double_fault_stack(int32 cpu, size_t* _size);
|
2009-08-01 05:53:54 +04:00
|
|
|
int32 x86_double_fault_get_cpu(void);
|
|
|
|
void x86_double_fault_exception(struct iframe* frame);
|
2009-08-03 16:39:56 +04:00
|
|
|
void x86_page_fault_exception_double_fault(struct iframe* frame);
|
2005-04-05 01:43:47 +04:00
|
|
|
|
2007-02-05 04:46:28 +03:00
|
|
|
|
2004-12-14 04:46:46 +03:00
|
|
|
#define read_cr3(value) \
|
|
|
|
__asm__("movl %%cr3,%0" : "=r" (value))
|
|
|
|
|
2005-11-04 18:58:04 +03:00
|
|
|
#define write_cr3(value) \
|
|
|
|
__asm__("movl %0,%%cr3" : : "r" (value))
|
|
|
|
|
2002-07-09 16:24:59 +04:00
|
|
|
#define read_dr3(value) \
|
|
|
|
__asm__("movl %%dr3,%0" : "=r" (value))
|
|
|
|
|
|
|
|
#define write_dr3(value) \
|
2003-05-20 07:02:19 +04:00
|
|
|
__asm__("movl %0,%%dr3" : : "r" (value))
|
2002-07-09 16:24:59 +04:00
|
|
|
|
|
|
|
#define invalidate_TLB(va) \
|
|
|
|
__asm__("invlpg (%0)" : : "r" (va))
|
|
|
|
|
2005-12-13 04:49:44 +03:00
|
|
|
#define wbinvd() \
|
|
|
|
__asm__("wbinvd")
|
|
|
|
|
2002-07-09 16:24:59 +04:00
|
|
|
#define out8(value,port) \
|
2005-12-13 04:49:44 +03:00
|
|
|
__asm__ ("outb %%al,%%dx" : : "a" (value), "d" (port))
|
2002-07-09 16:24:59 +04:00
|
|
|
|
|
|
|
#define out16(value,port) \
|
2005-12-13 04:49:44 +03:00
|
|
|
__asm__ ("outw %%ax,%%dx" : : "a" (value), "d" (port))
|
2002-07-09 16:24:59 +04:00
|
|
|
|
|
|
|
#define out32(value,port) \
|
2005-12-13 04:49:44 +03:00
|
|
|
__asm__ ("outl %%eax,%%dx" : : "a" (value), "d" (port))
|
2002-07-09 16:24:59 +04:00
|
|
|
|
|
|
|
#define in8(port) ({ \
|
2005-12-13 04:49:44 +03:00
|
|
|
uint8 _v; \
|
|
|
|
__asm__ volatile ("inb %%dx,%%al" : "=a" (_v) : "d" (port)); \
|
|
|
|
_v; \
|
2002-07-09 16:24:59 +04:00
|
|
|
})
|
|
|
|
|
|
|
|
#define in16(port) ({ \
|
2005-12-13 04:49:44 +03:00
|
|
|
uint16 _v; \
|
|
|
|
__asm__ volatile ("inw %%dx,%%ax":"=a" (_v) : "d" (port)); \
|
|
|
|
_v; \
|
2002-07-09 16:24:59 +04:00
|
|
|
})
|
|
|
|
|
|
|
|
#define in32(port) ({ \
|
2005-12-13 04:49:44 +03:00
|
|
|
uint32 _v; \
|
|
|
|
__asm__ volatile ("inl %%dx,%%eax":"=a" (_v) : "d" (port)); \
|
|
|
|
_v; \
|
2002-07-09 16:24:59 +04:00
|
|
|
})
|
|
|
|
|
|
|
|
#define out8_p(value,port) \
|
2005-12-13 04:49:44 +03:00
|
|
|
__asm__ ("outb %%al,%%dx\n" \
|
2002-07-09 16:24:59 +04:00
|
|
|
"\tjmp 1f\n" \
|
|
|
|
"1:\tjmp 1f\n" \
|
2003-05-20 07:02:19 +04:00
|
|
|
"1:" : : "a" (value), "d" (port))
|
2002-07-09 16:24:59 +04:00
|
|
|
|
|
|
|
#define in8_p(port) ({ \
|
2005-12-13 04:49:44 +03:00
|
|
|
uint8 _v; \
|
|
|
|
__asm__ volatile ("inb %%dx,%%al\n" \
|
|
|
|
"\tjmp 1f\n" \
|
|
|
|
"1:\tjmp 1f\n" \
|
|
|
|
"1:" : "=a" (_v) : "d" (port)); \
|
|
|
|
_v; \
|
2002-07-09 16:24:59 +04:00
|
|
|
})
|
|
|
|
|
2009-10-27 21:22:39 +03:00
|
|
|
extern segment_descriptor* gGDT;
|
2002-07-09 16:24:59 +04:00
|
|
|
|
2005-03-02 02:52:09 +03:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
} // extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2008-01-11 03:36:44 +03:00
|
|
|
#endif // !_ASSEMBLER
|
2005-03-02 02:52:09 +03:00
|
|
|
|
2003-01-06 11:02:44 +03:00
|
|
|
#endif /* _KERNEL_ARCH_x86_CPU_H */
|