2002-07-09 16:24:59 +04:00
|
|
|
/*
|
2006-03-02 20:12:56 +03:00
|
|
|
* Copyright 2002-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
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
|
|
|
|
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
|
|
|
|
2004-11-19 22:40:05 +03:00
|
|
|
|
2005-10-27 03:39:38 +04:00
|
|
|
// MSR registers (possibly Intel specific)
|
2005-12-13 03:06:52 +03:00
|
|
|
#define IA32_MSR_APIC_BASE 0x1b
|
|
|
|
|
|
|
|
#define IA32_MSR_MTRR_CAPABILITIES 0xfe
|
|
|
|
#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
|
|
|
|
2005-12-16 15:25:49 +03:00
|
|
|
// cpuid eax 1 features
|
|
|
|
#define IA32_FEATURE_MTRR (1UL << 12)
|
|
|
|
#define IA32_FEATURE_GLOBAL_PAGES (1UL << 13)
|
2006-03-02 20:12:56 +03:00
|
|
|
#define IA32_FEATURE_SSE (1UL << 25)
|
|
|
|
#define IA32_FEATURE_FXSR (1UL << 24)
|
2005-12-16 15:25:49 +03:00
|
|
|
|
2005-12-14 20:07:37 +03:00
|
|
|
// cr4 flags
|
|
|
|
#define IA32_CR4_GLOBAL_PAGES (1UL << 7)
|
|
|
|
|
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
|
|
|
|
#define IA32_MTR_UNCACHED 0
|
2005-12-16 15:25:49 +03:00
|
|
|
#define IA32_MTR_WRITE_COMBINING 1
|
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
|
|
|
#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
|
|
|
|
|
|
|
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
|
|
|
|
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 (*set_mtrr)(uint32 index, uint64 base, uint64 length, uint8 type);
|
|
|
|
status_t (*get_mtrr)(uint32 index, uint64 *_base, uint64 *_length,
|
|
|
|
uint8 *_type);
|
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 {
|
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;
|
|
|
|
uint32 user_esp;
|
|
|
|
uint32 user_ss;
|
2002-08-14 01:42:53 +04:00
|
|
|
};
|
|
|
|
|
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;
|
|
|
|
|
2006-01-04 05:17:59 +03:00
|
|
|
void __x86_setup_system_time(uint32 cv_factor);
|
2004-10-20 04:33:06 +04:00
|
|
|
void i386_context_switch(struct arch_thread *old_state, struct arch_thread *new_state, addr_t new_pgdir);
|
|
|
|
void i386_enter_uspace(addr_t entry, void *args1, void *args2, addr_t ustack_top);
|
|
|
|
void i386_set_tss_and_kstack(addr_t kstack);
|
|
|
|
void i386_switch_stack_and_call(addr_t stack, void (*func)(void *), void *arg);
|
|
|
|
void i386_swap_pgdir(addr_t new_pgdir);
|
2002-10-23 21:31:10 +04:00
|
|
|
void i386_fsave(void *fpu_state);
|
|
|
|
void i386_fxsave(void *fpu_state);
|
2005-03-02 02:52:09 +03:00
|
|
|
void i386_frstor(const void *fpu_state);
|
|
|
|
void i386_fxrstor(const void *fpu_state);
|
|
|
|
void i386_fsave_swap(void *old_fpu_state, const void *new_fpu_state);
|
|
|
|
void i386_fxsave_swap(void *old_fpu_state, const void *new_fpu_state);
|
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);
|
2004-12-14 04:46:46 +03:00
|
|
|
void x86_set_task_gate(int32 n, int32 segment);
|
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);
|
|
|
|
status_t x86_get_mtrr(uint32 index, uint64 *_base, uint64 *_length, uint8 *_type);
|
2005-04-05 01:43:47 +04:00
|
|
|
struct tss *x86_get_main_tss(void);
|
|
|
|
|
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
|
|
|
})
|
|
|
|
|
2003-01-06 11:02:44 +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
|
|
|
|
|
|
|
|
|
2003-01-06 11:02:44 +03:00
|
|
|
#endif /* _KERNEL_ARCH_x86_CPU_H */
|