From 0897e314b79d09b04349d3cfe6093a3fd6220da1 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 2 Jul 2012 18:47:06 +0100 Subject: [PATCH] Merged x86_64 headers into x86 headers. Not many changes seeing as there's not much x86_64 stuff done yet. Small differences are handled with ifdefs, large differences (descriptors.h, struct iframe) have separate headers under arch/x86/32 and arch/x86/64. --- headers/private/kernel/arch/common_x86/cpu.h | 294 -------------- .../private/kernel/arch/x86/32/descriptors.h | 140 +++++++ headers/private/kernel/arch/x86/32/iframe.h | 76 ++++ .../private/kernel/arch/x86/64/descriptors.h | 169 ++++++++ headers/private/kernel/arch/x86/64/iframe.h | 40 ++ headers/private/kernel/arch/x86/arch_cpu.h | 369 ++++++++++++++---- headers/private/kernel/arch/x86/arch_int.h | 19 +- headers/private/kernel/arch/x86/arch_kernel.h | 49 ++- headers/private/kernel/arch/x86/arch_thread.h | 48 ++- .../kernel/arch/x86/arch_thread_types.h | 16 +- headers/private/kernel/arch/x86/descriptors.h | 111 +----- src/system/boot/platform/bios_ia32/long.cpp | 6 +- 12 files changed, 830 insertions(+), 507 deletions(-) delete mode 100644 headers/private/kernel/arch/common_x86/cpu.h create mode 100644 headers/private/kernel/arch/x86/32/descriptors.h create mode 100644 headers/private/kernel/arch/x86/32/iframe.h create mode 100644 headers/private/kernel/arch/x86/64/descriptors.h create mode 100644 headers/private/kernel/arch/x86/64/iframe.h diff --git a/headers/private/kernel/arch/common_x86/cpu.h b/headers/private/kernel/arch/common_x86/cpu.h deleted file mode 100644 index f825d13567..0000000000 --- a/headers/private/kernel/arch/common_x86/cpu.h +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. - * Distributed under the terms of the MIT License. - * - * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. - * Distributed under the terms of the NewOS License. - */ -#ifndef _KERNEL_ARCH_COMMON_X86_CPU_H -#define _KERNEL_ARCH_COMMON_X86_CPU_H - - -#ifndef _ASSEMBLER -#include -#endif - - -#undef PAUSE -#define PAUSE() asm volatile ("pause;") - - -// MSR registers (possibly Intel specific) -#define IA32_MSR_TSC 0x10 -#define IA32_MSR_APIC_BASE 0x1b - -#define IA32_MSR_MTRR_CAPABILITIES 0xfe -#define IA32_MSR_SYSENTER_CS 0x174 -#define IA32_MSR_SYSENTER_ESP 0x175 -#define IA32_MSR_SYSENTER_EIP 0x176 -#define IA32_MSR_MTRR_DEFAULT_TYPE 0x2ff -#define IA32_MSR_MTRR_PHYSICAL_BASE_0 0x200 -#define IA32_MSR_MTRR_PHYSICAL_MASK_0 0x201 - -// K8 MSR registers -#define K8_MSR_IPM 0xc0010055 - -// x86 features from cpuid eax 1, edx register -// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-5) -#define IA32_FEATURE_FPU (1 << 0) // x87 fpu -#define IA32_FEATURE_VME (1 << 1) // virtual 8086 -#define IA32_FEATURE_DE (1 << 2) // debugging extensions -#define IA32_FEATURE_PSE (1 << 3) // page size extensions -#define IA32_FEATURE_TSC (1 << 4) // rdtsc instruction -#define IA32_FEATURE_MSR (1 << 5) // rdmsr/wrmsr instruction -#define IA32_FEATURE_PAE (1 << 6) // extended 3 level page table addressing -#define IA32_FEATURE_MCE (1 << 7) // machine check exception -#define IA32_FEATURE_CX8 (1 << 8) // cmpxchg8b instruction -#define IA32_FEATURE_APIC (1 << 9) // local apic on chip -// (1 << 10) // Reserved -#define IA32_FEATURE_SEP (1 << 11) // SYSENTER/SYSEXIT -#define IA32_FEATURE_MTRR (1 << 12) // MTRR -#define IA32_FEATURE_PGE (1 << 13) // paging global bit -#define IA32_FEATURE_MCA (1 << 14) // machine check architecture -#define IA32_FEATURE_CMOV (1 << 15) // cmov instruction -#define IA32_FEATURE_PAT (1 << 16) // page attribute table -#define IA32_FEATURE_PSE36 (1 << 17) // page size extensions with 4MB pages -#define IA32_FEATURE_PSN (1 << 18) // processor serial number -#define IA32_FEATURE_CLFSH (1 << 19) // cflush instruction -// (1 << 20) // Reserved -#define IA32_FEATURE_DS (1 << 21) // debug store -#define IA32_FEATURE_ACPI (1 << 22) // thermal monitor and clock ctrl -#define IA32_FEATURE_MMX (1 << 23) // mmx instructions -#define IA32_FEATURE_FXSR (1 << 24) // FXSAVE/FXRSTOR instruction -#define IA32_FEATURE_SSE (1 << 25) // SSE -#define IA32_FEATURE_SSE2 (1 << 26) // SSE2 -#define IA32_FEATURE_SS (1 << 27) // self snoop -#define IA32_FEATURE_HTT (1 << 28) // hyperthreading -#define IA32_FEATURE_TM (1 << 29) // thermal monitor -#define IA32_FEATURE_IA64 (1 << 30) // IA64 processor emulating x86 -#define IA32_FEATURE_PBE (1 << 31) // pending break enable - -// x86 features from cpuid eax 1, ecx register -// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-4) -#define IA32_FEATURE_EXT_SSE3 (1 << 0) // SSE3 -#define IA32_FEATURE_EXT_PCLMULQDQ (1 << 1) // PCLMULQDQ Instruction -#define IA32_FEATURE_EXT_DTES64 (1 << 2) // 64-Bit Debug Store -#define IA32_FEATURE_EXT_MONITOR (1 << 3) // MONITOR/MWAIT -#define IA32_FEATURE_EXT_DSCPL (1 << 4) // CPL qualified debug store -#define IA32_FEATURE_EXT_VMX (1 << 5) // Virtual Machine Extensions -#define IA32_FEATURE_EXT_SMX (1 << 6) // Safer Mode Extensions -#define IA32_FEATURE_EXT_EST (1 << 7) // Enhanced SpeedStep -#define IA32_FEATURE_EXT_TM2 (1 << 8) // Thermal Monitor 2 -#define IA32_FEATURE_EXT_SSSE3 (1 << 9) // Supplemental SSE-3 -#define IA32_FEATURE_EXT_CNXTID (1 << 10) // L1 Context ID -// (1 << 11) // Reserved -#define IA32_FEATURE_EXT_FMA (1 << 12) // Fused Multiply Add -#define IA32_FEATURE_EXT_CX16 (1 << 13) // CMPXCHG16B -#define IA32_FEATURE_EXT_XTPR (1 << 14) // xTPR Update Control -#define IA32_FEATURE_EXT_PDCM (1 << 15) // Perfmon and Debug Capability -// (1 << 16) // Reserved -#define IA32_FEATURE_EXT_PCID (1 << 17) // Process Context Identifiers -#define IA32_FEATURE_EXT_DCA (1 << 18) // Direct Cache Access -#define IA32_FEATURE_EXT_SSE4_1 (1 << 19) // SSE4.1 -#define IA32_FEATURE_EXT_SSE4_2 (1 << 20) // SSE4.2 -#define IA32_FEATURE_EXT_X2APIC (1 << 21) // Extended xAPIC Support -#define IA32_FEATURE_EXT_MOVBE (1 << 22) // MOVBE Instruction -#define IA32_FEATURE_EXT_POPCNT (1 << 23) // POPCNT Instruction -#define IA32_FEATURE_EXT_TSCDEADLINE (1 << 24) // Time Stamp Counter Deadline -#define IA32_FEATURE_EXT_AES (1 << 25) // AES Instruction Extensions -#define IA32_FEATURE_EXT_XSAVE (1 << 26) // XSAVE/XSTOR States -#define IA32_FEATURE_EXT_OSXSAVE (1 << 27) // OS-Enabled XSAVE -#define IA32_FEATURE_EXT_AVX (1 << 28) // Advanced Vector Extensions -#define IA32_FEATURE_EXT_F16C (1 << 29) // 16-bit FP conversion -#define IA32_FEATURE_EXT_RDRND (1 << 30) // RDRAND instruction -#define IA32_FEATURE_EXT_HYPERVISOR (1 << 31) // Running on a hypervisor - -// x86 features from cpuid eax 0x80000001, edx register (AMD) -// only care about the ones that are unique to this register -#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! - -// x86 defined features from cpuid eax 6, eax register -// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-11) -#define IA32_FEATURE_DTS (1 << 0) //Digital Thermal Sensor -#define IA32_FEATURE_ITB (1 << 1) //Intel Turbo Boost Technology -#define IA32_FEATURE_ARAT (1 << 2) //Always running APIC Timer -#define IA32_FEATURE_PLN (1 << 4) //Power Limit Notification -#define IA32_FEATURE_ECMD (1 << 5) //Extended Clock Modulation Duty -#define IA32_FEATURE_PTM (1 << 6) //Package Thermal Management - -// x86 defined features from cpuid eax 6, ecx register -// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-11) -#define IA32_FEATURE_APERFMPERF (1 << 0) //IA32_APERF, IA32_MPERF -#define IA32_FEATURE_EPB (1 << 3) //IA32_ENERGY_PERF_BIAS - -// cr4 flags -#define IA32_CR4_PAE (1UL << 5) -#define IA32_CR4_GLOBAL_PAGES (1UL << 7) - -// Memory type ranges -#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 - -// EFLAGS register -#define X86_EFLAGS_CARRY 0x00000001 -#define X86_EFLAGS_RESERVED1 0x00000002 -#define X86_EFLAGS_PARITY 0x00000004 -#define X86_EFLAGS_AUXILIARY_CARRY 0x00000010 -#define X86_EFLAGS_ZERO 0x00000040 -#define X86_EFLAGS_SIGN 0x00000080 -#define X86_EFLAGS_TRAP 0x00000100 -#define X86_EFLAGS_INTERRUPT 0x00000200 -#define X86_EFLAGS_DIRECTION 0x00000400 -#define X86_EFLAGS_OVERFLOW 0x00000800 -#define X86_EFLAGS_IO_PRIVILEG_LEVEL 0x00003000 -#define X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT 12 -#define X86_EFLAGS_NESTED_TASK 0x00004000 -#define X86_EFLAGS_RESUME 0x00010000 -#define X86_EFLAGS_V86_MODE 0x00020000 -#define X86_EFLAGS_ALIGNMENT_CHECK 0x00040000 -#define X86_EFLAGS_VIRTUAL_INTERRUPT 0x00080000 -#define X86_EFLAGS_VIRTUAL_INTERRUPT_PENDING 0x00100000 -#define X86_EFLAGS_ID 0x00200000 - -#define X86_EFLAGS_USER_FLAGS (X86_EFLAGS_CARRY | X86_EFLAGS_PARITY \ - | X86_EFLAGS_AUXILIARY_CARRY | X86_EFLAGS_ZERO | X86_EFLAGS_SIGN \ - | X86_EFLAGS_DIRECTION | X86_EFLAGS_OVERFLOW) - - -#ifndef _ASSEMBLER - - -typedef struct x86_mtrr_info { - uint64 base; - uint64 size; - uint8 type; -} x86_mtrr_info; - -typedef struct x86_optimized_functions { - void (*memcpy)(void* dest, const void* source, size_t count); - void* memcpy_end; - void (*memset)(void* dest, int value, size_t count); - void* memset_end; -} x86_optimized_functions; - -typedef struct x86_cpu_module_info { - module_info info; - uint32 (*count_mtrrs)(void); - void (*init_mtrrs)(void); - - void (*set_mtrr)(uint32 index, uint64 base, uint64 length, - uint8 type); - status_t (*get_mtrr)(uint32 index, uint64* _base, uint64* _length, - uint8* _type); - void (*set_mtrrs)(uint8 defaultType, const x86_mtrr_info* infos, - uint32 count); - - void (*get_optimized_functions)(x86_optimized_functions* functions); -} x86_cpu_module_info; - -// 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_6_EAX, // cpuid eax=6, eax registers - FEATURE_6_ECX, // cpuid eax=6, ecx registers - - 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, -}; - - -#define nop() __asm__ ("nop"::) - -#define read_cr2(value) \ - __asm__("mov %%cr2,%0" : "=r" (value)) - -#define read_cr3(value) \ - __asm__("mov %%cr3,%0" : "=r" (value)) - -#define write_cr3(value) \ - __asm__("mov %0,%%cr3" : : "r" (value)) - -#define read_dr3(value) \ - __asm__("mov %%dr3,%0" : "=r" (value)) - -#define write_dr3(value) \ - __asm__("mov %0,%%dr3" : : "r" (value)) - -#define invalidate_TLB(va) \ - __asm__("invlpg (%0)" : : "r" (va)) - -#define wbinvd() \ - __asm__("wbinvd") - -#define out8(value,port) \ - __asm__ ("outb %%al,%%dx" : : "a" (value), "d" (port)) - -#define out16(value,port) \ - __asm__ ("outw %%ax,%%dx" : : "a" (value), "d" (port)) - -#define out32(value,port) \ - __asm__ ("outl %%eax,%%dx" : : "a" (value), "d" (port)) - -#define in8(port) ({ \ - uint8 _v; \ - __asm__ volatile ("inb %%dx,%%al" : "=a" (_v) : "d" (port)); \ - _v; \ -}) - -#define in16(port) ({ \ - uint16 _v; \ - __asm__ volatile ("inw %%dx,%%ax":"=a" (_v) : "d" (port)); \ - _v; \ -}) - -#define in32(port) ({ \ - uint32 _v; \ - __asm__ volatile ("inl %%dx,%%eax":"=a" (_v) : "d" (port)); \ - _v; \ -}) - -#define out8_p(value,port) \ - __asm__ ("outb %%al,%%dx\n" \ - "\tjmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:" : : "a" (value), "d" (port)) - -#define in8_p(port) ({ \ - uint8 _v; \ - __asm__ volatile ("inb %%dx,%%al\n" \ - "\tjmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:" : "=a" (_v) : "d" (port)); \ - _v; \ -}) - - -#endif // !_ASSEMBLER - -#endif /* _KERNEL_ARCH_COMMON_X86_CPU_H */ diff --git a/headers/private/kernel/arch/x86/32/descriptors.h b/headers/private/kernel/arch/x86/32/descriptors.h new file mode 100644 index 0000000000..d57bf05da5 --- /dev/null +++ b/headers/private/kernel/arch/x86/32/descriptors.h @@ -0,0 +1,140 @@ +/* + * Copyright 2002-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ +#ifndef _KERNEL_ARCH_X86_32_DESCRIPTORS_H +#define _KERNEL_ARCH_X86_32_DESCRIPTORS_H + + +#define KERNEL_CODE_SEG 0x8 +#define KERNEL_DATA_SEG 0x10 + +#define USER_CODE_SEG 0x1b +#define USER_DATA_SEG 0x23 + +#define APM_CODE32_SEGMENT 0x28 +#define APM_CODE16_SEGMENT 0x30 +#define APM_DATA_SEGMENT 0x38 + +#define BIOS_DATA_SEGMENT 0x40 + +#ifndef _ASSEMBLER + // this file can also be included from assembler as well + // (and is in arch_interrupts.S) + +#define DOUBLE_FAULT_TSS_BASE_SEGMENT 9 +#define TSS_BASE_SEGMENT (DOUBLE_FAULT_TSS_BASE_SEGMENT + smp_get_num_cpus()) +#define TLS_BASE_SEGMENT (TSS_BASE_SEGMENT + smp_get_num_cpus()) +#define APM_BASE_SEGMENT (TLS_BASE_SEGMENT + smp_get_num_cpus()) + + +// defines entries in the GDT/LDT + +typedef struct segment_descriptor { + uint16 limit_00_15; // bit 0 - 15 + uint16 base_00_15; // 16 - 31 + uint32 base_23_16 : 8; // 0 - 7 + uint32 type : 4; // 8 - 11 + uint32 desc_type : 1; // 12 (0 = system, 1 = code/data) + uint32 privilege_level : 2; // 13 - 14 + uint32 present : 1; // 15 + uint32 limit_19_16 : 4; // 16 - 19 + uint32 available : 1; // 20 + uint32 zero : 1; // 21 + uint32 d_b : 1; // 22 + uint32 granularity : 1; // 23 + uint32 base_31_24 : 8; // 24 - 31 +} segment_descriptor; + +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; +}; + + +static inline void +clear_segment_descriptor(struct segment_descriptor *desc) +{ + *(long long *)desc = 0; +} + + +static inline void +set_segment_descriptor_base(struct segment_descriptor *desc, addr_t base) +{ + desc->base_00_15 = (addr_t)base & 0xffff; // base is 32 bits long + desc->base_23_16 = ((addr_t)base >> 16) & 0xff; + desc->base_31_24 = ((addr_t)base >> 24) & 0xff; +} + + +static inline void +set_segment_descriptor(struct segment_descriptor *desc, addr_t base, uint32 limit, + uint8 type, uint8 privilegeLevel) +{ + set_segment_descriptor_base(desc, base); + + // limit is 20 bits long + if (limit & 0xfff00000) { + desc->limit_00_15 = ((addr_t)limit >> 12) & 0x0ffff; + desc->limit_19_16 = ((addr_t)limit >> 28) & 0xf; + desc->granularity = 1; // 4 KB granularity + } else { + desc->limit_00_15 = (addr_t)limit & 0x0ffff; + desc->limit_19_16 = ((addr_t)limit >> 16) & 0xf; + desc->granularity = 0; // 1 byte granularity + } + limit >>= 12; + + + desc->type = type; + desc->desc_type = DT_CODE_DATA_SEGMENT; + desc->privilege_level = privilegeLevel; + + desc->present = 1; + desc->available = 0; // system available bit is currently not used + desc->d_b = 1; // 32-bit code + + desc->zero = 0; +} + + +static inline void +set_tss_descriptor(struct segment_descriptor *desc, addr_t base, uint32 limit) +{ + // the TSS descriptor has a special layout different from the standard descriptor + set_segment_descriptor_base(desc, base); + + desc->limit_00_15 = (addr_t)limit & 0x0ffff; + desc->limit_19_16 = 0; + + desc->type = DT_TSS; + desc->desc_type = DT_SYSTEM_SEGMENT; + desc->privilege_level = DPL_KERNEL; + + desc->present = 1; + desc->granularity = 0; // 1 Byte granularity + desc->available = 0; // system available bit is currently not used + desc->d_b = 0; + + desc->zero = 0; +} + +#endif /* _ASSEMBLER */ + +#endif /* _KERNEL_ARCH_X86_32_DESCRIPTORS_H */ diff --git a/headers/private/kernel/arch/x86/32/iframe.h b/headers/private/kernel/arch/x86/32/iframe.h new file mode 100644 index 0000000000..6da6c1f9b2 --- /dev/null +++ b/headers/private/kernel/arch/x86/32/iframe.h @@ -0,0 +1,76 @@ +/* + * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + * + * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ +#ifndef _KERNEL_ARCH_X86_32_IFRAME_H +#define _KERNEL_ARCH_X86_32_IFRAME_H + + +struct iframe { + uint32 type; // iframe type + 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; + + // user_esp and user_ss are only present when the iframe is a userland + // iframe (IFRAME_IS_USER()). A kernel iframe is shorter. + uint32 user_esp; + uint32 user_ss; +}; + +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; +}; + +#define IFRAME_IS_USER(f) ((f)->cs == USER_CODE_SEG \ + || ((f)->flags & 0x20000) != 0) +#define IFRAME_IS_VM86(f) (((f)->flags & 0x20000) != 0) + + +#endif /* _KERNEL_ARCH_X86_32_IFRAME_H */ diff --git a/headers/private/kernel/arch/x86/64/descriptors.h b/headers/private/kernel/arch/x86/64/descriptors.h new file mode 100644 index 0000000000..7e5efb9c83 --- /dev/null +++ b/headers/private/kernel/arch/x86/64/descriptors.h @@ -0,0 +1,169 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_ARCH_X86_64_DESCRIPTORS_H +#define _KERNEL_ARCH_X86_64_DESCRIPTORS_H + + +// Segment definitions. +// Note that the ordering of these is important to SYSCALL/SYSRET. +#define KERNEL_CODE_SEG 0x08 +#define KERNEL_DATA_SEG 0x10 +#define USER_DATA_SEG 0x1b +#define USER_CODE_SEG 0x23 + + +#ifndef _ASSEMBLER + + +#define TSS_BASE_SEGMENT 5 +#define TLS_BASE_SEGMENT (TSS_BASE_SEGMENT + smp_get_num_cpus()) + + +// Structure of a segment descriptor. +struct segment_descriptor { + uint32 limit0 : 16; + uint32 base0 : 24; + uint32 type : 4; + uint32 desc_type : 1; + uint32 dpl : 2; + uint32 present : 1; + uint32 limit1 : 4; + uint32 available : 1; + uint32 long_mode : 1; + uint32 d_b : 1; + uint32 granularity : 1; + uint32 base1 : 8; +} _PACKED; + +// Structure of a TSS segment descriptor. +struct tss_descriptor { + uint32 limit0 : 16; + uint32 base0 : 24; + uint32 type : 4; + uint32 desc_type : 1; + uint32 dpl : 2; + uint32 present : 1; + uint32 limit1 : 4; + uint32 available : 1; + uint32 unused1 : 2; + uint32 granularity : 1; + uint32 base1 : 8; + uint32 base2 : 32; + uint32 unused2 : 32; +} _PACKED; + +// Structure of an interrupt descriptor. +struct interrupt_descriptor { + uint32 base0 : 16; + uint32 sel : 16; + uint32 ist : 3; + uint32 unused1 : 5; + uint32 type : 4; + uint32 unused2 : 1; + uint32 dpl : 2; + uint32 present : 1; + uint32 base1 : 16; + uint32 base2 : 32; + uint32 reserved : 32; +} _PACKED; + +struct gdt_idt_descr { + uint16 limit; + addr_t base; +} _PACKED; + +struct tss { + uint32 _reserved1; + uint64 rsp0; + uint64 rsp1; + uint64 rsp2; + uint64 _reserved2; + uint64 ist1; + uint64 ist2; + uint64 ist3; + uint64 ist4; + uint64 ist5; + uint64 ist6; + uint64 ist7; + uint64 _reserved3; + uint16 _reserved4; + uint16 io_bitmap; +} _PACKED; + + +static inline void +clear_segment_descriptor(segment_descriptor* desc) +{ + *(uint64*)desc = 0; +} + + +static inline void +set_segment_descriptor(segment_descriptor* desc, uint8 type, uint8 dpl) +{ + clear_segment_descriptor(desc); + + // In 64-bit mode the CPU ignores the base/limit of code/data segments, + // it always treats base as 0 and does no limit checks. + desc->base0 = 0; + desc->base1 = 0; + desc->limit0 = 0xffff; + desc->limit1 = 0xf; + desc->granularity = 1; + + desc->type = type; + desc->desc_type = DT_CODE_DATA_SEGMENT; + desc->dpl = dpl; + desc->present = 1; + + desc->long_mode = (type & DT_CODE_EXECUTE_ONLY) ? 1 : 0; + // Must be set to 1 for code segments only. +} + + +static inline void +set_tss_descriptor(segment_descriptor* _desc, uint64 base, uint32 limit) +{ + clear_segment_descriptor(_desc); + clear_segment_descriptor(&_desc[1]); + + // The TSS descriptor is a special format in 64-bit mode, it is 16 bytes + // instead of 8. + tss_descriptor* desc = (tss_descriptor*)_desc; + + desc->base0 = base & 0xffffff; + desc->base1 = (base >> 24) & 0xff; + desc->base2 = (base >> 32); + desc->limit0 = limit & 0xffff; + desc->limit1 = (limit >> 16) & 0xf; + + desc->present = 1; + desc->type = DT_TSS; + desc->desc_type = DT_SYSTEM_SEGMENT; + desc->dpl = DPL_KERNEL; +} + + +static inline void +set_interrupt_descriptor(interrupt_descriptor* desc, uint64 addr, uint32 type, + uint16 seg, uint32 dpl, uint32 ist) +{ + desc->base0 = addr & 0xffff; + desc->base1 = (addr >> 16) & 0xffff; + desc->base2 = (addr >> 32) & 0xffffffff; + desc->sel = seg; + desc->ist = ist; + desc->type = type; + desc->dpl = dpl; + desc->present = 1; + desc->unused1 = 0; + desc->unused2 = 0; + desc->reserved = 0; +} + + +#endif /* _ASSEMBLER */ + +#endif /* _KERNEL_ARCH_X86_64_DESCRIPTORS_H */ diff --git a/headers/private/kernel/arch/x86/64/iframe.h b/headers/private/kernel/arch/x86/64/iframe.h new file mode 100644 index 0000000000..a0ca48f2c4 --- /dev/null +++ b/headers/private/kernel/arch/x86/64/iframe.h @@ -0,0 +1,40 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_ARCH_X86_64_IFRAME_H +#define _KERNEL_ARCH_X86_64_IFRAME_H + + +struct iframe { + uint64 type; + uint64 r15; + uint64 r14; + uint64 r13; + uint64 r12; + uint64 r11; + uint64 r10; + uint64 r9; + uint64 r8; + uint64 rbp; + uint64 rsi; + uint64 rdi; + uint64 rdx; + uint64 rcx; + uint64 rbx; + uint64 rax; + uint64 vector; + uint64 error_code; + uint64 rip; + uint64 cs; + uint64 flags; + + // Only present when the iframe is a userland iframe (IFRAME_IS_USER()). + uint64 user_rsp; + uint64 user_ss; +} _PACKED; + +#define IFRAME_IS_USER(f) (((f)->cs & DPL_USER) == DPL_USER) + + +#endif /* _KERNEL_ARCH_X86_64_IFRAME_H */ diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index cfe380c820..d5e284e006 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -1,5 +1,6 @@ /* * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. * Distributed under the terms of the MIT License. * * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. @@ -9,14 +10,170 @@ #define _KERNEL_ARCH_x86_CPU_H -#include "../common_x86/cpu.h" - #ifndef _ASSEMBLER -# ifndef _BOOT_MODE -# include -# endif + +#include +#include + +#ifdef __x86_64__ +# include +#else +# include #endif +#endif // !_ASSEMBLER + + +#undef PAUSE +#define PAUSE() asm volatile ("pause;") + + +// MSR registers (possibly Intel specific) +#define IA32_MSR_TSC 0x10 +#define IA32_MSR_APIC_BASE 0x1b + +#define IA32_MSR_MTRR_CAPABILITIES 0xfe +#define IA32_MSR_SYSENTER_CS 0x174 +#define IA32_MSR_SYSENTER_ESP 0x175 +#define IA32_MSR_SYSENTER_EIP 0x176 +#define IA32_MSR_MTRR_DEFAULT_TYPE 0x2ff +#define IA32_MSR_MTRR_PHYSICAL_BASE_0 0x200 +#define IA32_MSR_MTRR_PHYSICAL_MASK_0 0x201 + +// K8 MSR registers +#define K8_MSR_IPM 0xc0010055 + +// x86 features from cpuid eax 1, edx register +// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-5) +#define IA32_FEATURE_FPU (1 << 0) // x87 fpu +#define IA32_FEATURE_VME (1 << 1) // virtual 8086 +#define IA32_FEATURE_DE (1 << 2) // debugging extensions +#define IA32_FEATURE_PSE (1 << 3) // page size extensions +#define IA32_FEATURE_TSC (1 << 4) // rdtsc instruction +#define IA32_FEATURE_MSR (1 << 5) // rdmsr/wrmsr instruction +#define IA32_FEATURE_PAE (1 << 6) // extended 3 level page table addressing +#define IA32_FEATURE_MCE (1 << 7) // machine check exception +#define IA32_FEATURE_CX8 (1 << 8) // cmpxchg8b instruction +#define IA32_FEATURE_APIC (1 << 9) // local apic on chip +// (1 << 10) // Reserved +#define IA32_FEATURE_SEP (1 << 11) // SYSENTER/SYSEXIT +#define IA32_FEATURE_MTRR (1 << 12) // MTRR +#define IA32_FEATURE_PGE (1 << 13) // paging global bit +#define IA32_FEATURE_MCA (1 << 14) // machine check architecture +#define IA32_FEATURE_CMOV (1 << 15) // cmov instruction +#define IA32_FEATURE_PAT (1 << 16) // page attribute table +#define IA32_FEATURE_PSE36 (1 << 17) // page size extensions with 4MB pages +#define IA32_FEATURE_PSN (1 << 18) // processor serial number +#define IA32_FEATURE_CLFSH (1 << 19) // cflush instruction +// (1 << 20) // Reserved +#define IA32_FEATURE_DS (1 << 21) // debug store +#define IA32_FEATURE_ACPI (1 << 22) // thermal monitor and clock ctrl +#define IA32_FEATURE_MMX (1 << 23) // mmx instructions +#define IA32_FEATURE_FXSR (1 << 24) // FXSAVE/FXRSTOR instruction +#define IA32_FEATURE_SSE (1 << 25) // SSE +#define IA32_FEATURE_SSE2 (1 << 26) // SSE2 +#define IA32_FEATURE_SS (1 << 27) // self snoop +#define IA32_FEATURE_HTT (1 << 28) // hyperthreading +#define IA32_FEATURE_TM (1 << 29) // thermal monitor +#define IA32_FEATURE_IA64 (1 << 30) // IA64 processor emulating x86 +#define IA32_FEATURE_PBE (1 << 31) // pending break enable + +// x86 features from cpuid eax 1, ecx register +// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-4) +#define IA32_FEATURE_EXT_SSE3 (1 << 0) // SSE3 +#define IA32_FEATURE_EXT_PCLMULQDQ (1 << 1) // PCLMULQDQ Instruction +#define IA32_FEATURE_EXT_DTES64 (1 << 2) // 64-Bit Debug Store +#define IA32_FEATURE_EXT_MONITOR (1 << 3) // MONITOR/MWAIT +#define IA32_FEATURE_EXT_DSCPL (1 << 4) // CPL qualified debug store +#define IA32_FEATURE_EXT_VMX (1 << 5) // Virtual Machine Extensions +#define IA32_FEATURE_EXT_SMX (1 << 6) // Safer Mode Extensions +#define IA32_FEATURE_EXT_EST (1 << 7) // Enhanced SpeedStep +#define IA32_FEATURE_EXT_TM2 (1 << 8) // Thermal Monitor 2 +#define IA32_FEATURE_EXT_SSSE3 (1 << 9) // Supplemental SSE-3 +#define IA32_FEATURE_EXT_CNXTID (1 << 10) // L1 Context ID +// (1 << 11) // Reserved +#define IA32_FEATURE_EXT_FMA (1 << 12) // Fused Multiply Add +#define IA32_FEATURE_EXT_CX16 (1 << 13) // CMPXCHG16B +#define IA32_FEATURE_EXT_XTPR (1 << 14) // xTPR Update Control +#define IA32_FEATURE_EXT_PDCM (1 << 15) // Perfmon and Debug Capability +// (1 << 16) // Reserved +#define IA32_FEATURE_EXT_PCID (1 << 17) // Process Context Identifiers +#define IA32_FEATURE_EXT_DCA (1 << 18) // Direct Cache Access +#define IA32_FEATURE_EXT_SSE4_1 (1 << 19) // SSE4.1 +#define IA32_FEATURE_EXT_SSE4_2 (1 << 20) // SSE4.2 +#define IA32_FEATURE_EXT_X2APIC (1 << 21) // Extended xAPIC Support +#define IA32_FEATURE_EXT_MOVBE (1 << 22) // MOVBE Instruction +#define IA32_FEATURE_EXT_POPCNT (1 << 23) // POPCNT Instruction +#define IA32_FEATURE_EXT_TSCDEADLINE (1 << 24) // Time Stamp Counter Deadline +#define IA32_FEATURE_EXT_AES (1 << 25) // AES Instruction Extensions +#define IA32_FEATURE_EXT_XSAVE (1 << 26) // XSAVE/XSTOR States +#define IA32_FEATURE_EXT_OSXSAVE (1 << 27) // OS-Enabled XSAVE +#define IA32_FEATURE_EXT_AVX (1 << 28) // Advanced Vector Extensions +#define IA32_FEATURE_EXT_F16C (1 << 29) // 16-bit FP conversion +#define IA32_FEATURE_EXT_RDRND (1 << 30) // RDRAND instruction +#define IA32_FEATURE_EXT_HYPERVISOR (1 << 31) // Running on a hypervisor + +// x86 features from cpuid eax 0x80000001, edx register (AMD) +// only care about the ones that are unique to this register +#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! + +// x86 defined features from cpuid eax 6, eax register +// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-11) +#define IA32_FEATURE_DTS (1 << 0) //Digital Thermal Sensor +#define IA32_FEATURE_ITB (1 << 1) //Intel Turbo Boost Technology +#define IA32_FEATURE_ARAT (1 << 2) //Always running APIC Timer +#define IA32_FEATURE_PLN (1 << 4) //Power Limit Notification +#define IA32_FEATURE_ECMD (1 << 5) //Extended Clock Modulation Duty +#define IA32_FEATURE_PTM (1 << 6) //Package Thermal Management + +// x86 defined features from cpuid eax 6, ecx register +// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-11) +#define IA32_FEATURE_APERFMPERF (1 << 0) //IA32_APERF, IA32_MPERF +#define IA32_FEATURE_EPB (1 << 3) //IA32_ENERGY_PERF_BIAS + +// cr4 flags +#define IA32_CR4_PAE (1UL << 5) +#define IA32_CR4_GLOBAL_PAGES (1UL << 7) + +// Memory type ranges +#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 + +// EFLAGS register +#define X86_EFLAGS_CARRY 0x00000001 +#define X86_EFLAGS_RESERVED1 0x00000002 +#define X86_EFLAGS_PARITY 0x00000004 +#define X86_EFLAGS_AUXILIARY_CARRY 0x00000010 +#define X86_EFLAGS_ZERO 0x00000040 +#define X86_EFLAGS_SIGN 0x00000080 +#define X86_EFLAGS_TRAP 0x00000100 +#define X86_EFLAGS_INTERRUPT 0x00000200 +#define X86_EFLAGS_DIRECTION 0x00000400 +#define X86_EFLAGS_OVERFLOW 0x00000800 +#define X86_EFLAGS_IO_PRIVILEG_LEVEL 0x00003000 +#define X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT 12 +#define X86_EFLAGS_NESTED_TASK 0x00004000 +#define X86_EFLAGS_RESUME 0x00010000 +#define X86_EFLAGS_V86_MODE 0x00020000 +#define X86_EFLAGS_ALIGNMENT_CHECK 0x00040000 +#define X86_EFLAGS_VIRTUAL_INTERRUPT 0x00080000 +#define X86_EFLAGS_VIRTUAL_INTERRUPT_PENDING 0x00100000 +#define X86_EFLAGS_ID 0x00200000 + +#define X86_EFLAGS_USER_FLAGS (X86_EFLAGS_CARRY | X86_EFLAGS_PARITY \ + | X86_EFLAGS_AUXILIARY_CARRY | X86_EFLAGS_ZERO | X86_EFLAGS_SIGN \ + | X86_EFLAGS_DIRECTION | X86_EFLAGS_OVERFLOW) + // iframe types #define IFRAME_TYPE_SYSCALL 0x1 @@ -26,87 +183,64 @@ #ifndef _ASSEMBLER + struct X86PagingStructures; -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; + +typedef struct x86_mtrr_info { + uint64 base; + uint64 size; + uint8 type; +} x86_mtrr_info; + +typedef struct x86_optimized_functions { + void (*memcpy)(void* dest, const void* source, size_t count); + void* memcpy_end; + void (*memset)(void* dest, int value, size_t count); + void* memset_end; +} x86_optimized_functions; + +typedef struct x86_cpu_module_info { + module_info info; + uint32 (*count_mtrrs)(void); + void (*init_mtrrs)(void); + + void (*set_mtrr)(uint32 index, uint64 base, uint64 length, + uint8 type); + status_t (*get_mtrr)(uint32 index, uint64* _base, uint64* _length, + uint8* _type); + void (*set_mtrrs)(uint8 defaultType, const x86_mtrr_info* infos, + uint32 count); + + void (*get_optimized_functions)(x86_optimized_functions* functions); +} x86_cpu_module_info; + +// 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_6_EAX, // cpuid eax=6, eax registers + FEATURE_6_ECX, // cpuid eax=6, ecx registers + + FEATURE_NUM }; -struct iframe { - uint32 type; // iframe type - 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; +enum x86_vendors { + VENDOR_INTEL = 0, + VENDOR_AMD, + VENDOR_CYRIX, + VENDOR_UMC, + VENDOR_NEXGEN, + VENDOR_CENTAUR, + VENDOR_RISE, + VENDOR_TRANSMETA, + VENDOR_NSC, - // user_esp and user_ss are only present when the iframe is a userland - // iframe (IFRAME_IS_USER()). A kernel iframe is shorter. - uint32 user_esp; - uint32 user_ss; + VENDOR_NUM, + VENDOR_UNKNOWN, }; -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; -}; - -#define IFRAME_IS_USER(f) ((f)->cs == USER_CODE_SEG \ - || ((f)->flags & 0x20000) != 0) -#define IFRAME_IS_VM86(f) (((f)->flags & 0x20000) != 0) typedef struct arch_cpu_info { // saved cpu info @@ -128,15 +262,86 @@ typedef struct arch_cpu_info { // local TSS for this cpu struct tss tss; +#ifndef __x86_64__ struct tss double_fault_tss; +#endif } arch_cpu_info; +#define nop() __asm__ ("nop"::) + +#define read_cr2(value) \ + __asm__("mov %%cr2,%0" : "=r" (value)) + +#define read_cr3(value) \ + __asm__("mov %%cr3,%0" : "=r" (value)) + +#define write_cr3(value) \ + __asm__("mov %0,%%cr3" : : "r" (value)) + +#define read_dr3(value) \ + __asm__("mov %%dr3,%0" : "=r" (value)) + +#define write_dr3(value) \ + __asm__("mov %0,%%dr3" : : "r" (value)) + +#define invalidate_TLB(va) \ + __asm__("invlpg (%0)" : : "r" (va)) + +#define wbinvd() \ + __asm__("wbinvd") + +#define out8(value,port) \ + __asm__ ("outb %%al,%%dx" : : "a" (value), "d" (port)) + +#define out16(value,port) \ + __asm__ ("outw %%ax,%%dx" : : "a" (value), "d" (port)) + +#define out32(value,port) \ + __asm__ ("outl %%eax,%%dx" : : "a" (value), "d" (port)) + +#define in8(port) ({ \ + uint8 _v; \ + __asm__ volatile ("inb %%dx,%%al" : "=a" (_v) : "d" (port)); \ + _v; \ +}) + +#define in16(port) ({ \ + uint16 _v; \ + __asm__ volatile ("inw %%dx,%%ax":"=a" (_v) : "d" (port)); \ + _v; \ +}) + +#define in32(port) ({ \ + uint32 _v; \ + __asm__ volatile ("inl %%dx,%%eax":"=a" (_v) : "d" (port)); \ + _v; \ +}) + +#define out8_p(value,port) \ + __asm__ ("outb %%al,%%dx\n" \ + "\tjmp 1f\n" \ + "1:\tjmp 1f\n" \ + "1:" : : "a" (value), "d" (port)) + +#define in8_p(port) ({ \ + uint8 _v; \ + __asm__ volatile ("inb %%dx,%%al\n" \ + "\tjmp 1f\n" \ + "1:\tjmp 1f\n" \ + "1:" : "=a" (_v) : "d" (port)); \ + _v; \ +}) + + #ifdef __cplusplus extern "C" { #endif +// temporary +#ifndef __x86_64__ + struct arch_thread; void __x86_setup_system_time(uint32 conversionFactor, @@ -176,12 +381,12 @@ int32 x86_double_fault_get_cpu(void); void x86_double_fault_exception(struct iframe* frame); void x86_page_fault_exception_double_fault(struct iframe* frame); - -#ifndef _BOOT_MODE -extern segment_descriptor* gGDT; #endif +extern segment_descriptor* gGDT; + + #ifdef __cplusplus } // extern "C" { #endif diff --git a/headers/private/kernel/arch/x86/arch_int.h b/headers/private/kernel/arch/x86/arch_int.h index b8a5828d23..f00b56e91e 100644 --- a/headers/private/kernel/arch/x86/arch_int.h +++ b/headers/private/kernel/arch/x86/arch_int.h @@ -1,5 +1,6 @@ /* * Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. * Distributed under the terms of the MIT License. */ #ifndef _KERNEL_ARCH_x86_INT_H @@ -20,30 +21,30 @@ arch_int_enable_interrupts_inline(void) static inline int arch_int_disable_interrupts_inline(void) { - int flags; + unsigned long flags; - asm volatile("pushfl;\n" - "popl %0;\n" + asm volatile("pushf;\n" + "pop %0;\n" "cli" : "=g" (flags)); - return flags ; + return (flags & 0x200) != 0; } static inline void arch_int_restore_interrupts_inline(int oldState) { - if (oldState & 0x200) - asm("sti"); + if (oldState) + asm("sti"); } static inline bool arch_int_are_interrupts_enabled_inline(void) { - int flags; + unsigned long flags; - asm volatile("pushfl;\n" - "popl %0;\n" : "=g" (flags)); + asm volatile("pushf;\n" + "pop %0;\n" : "=g" (flags)); return (flags & 0x200) != 0; } diff --git a/headers/private/kernel/arch/x86/arch_kernel.h b/headers/private/kernel/arch/x86/arch_kernel.h index 00e2ea868d..a30eb94656 100644 --- a/headers/private/kernel/arch/x86/arch_kernel.h +++ b/headers/private/kernel/arch/x86/arch_kernel.h @@ -1,6 +1,6 @@ /* * Copyright 2004-2008, Haiku Inc. All rights reserved. - * Distributes under the terms of the MIT license. + * Distributed under the terms of the MIT license. * * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. * Distributed under the terms of the NewOS License. @@ -8,19 +8,53 @@ #ifndef _KERNEL_ARCH_x86_KERNEL_H #define _KERNEL_ARCH_x86_KERNEL_H + #ifndef _ASSEMBLER # include #endif + +#ifdef _BOOT_MODE + + +// 32-bit and 64-bit kernel load addresses. +#define KERNEL_BASE 0x80000000 +#define KERNEL_BASE_64BIT 0xffffffff80000000ll + + +#elif defined(__x86_64__) + + +// Base of the kernel address space. +// When compiling the bootloader, KERNEL_BASE is set to the x86 base address, +// KERNEL_BASE_64BIT is set to where the kernel loaded to. +// For the kernel, KERNEL_BASE is the base of the kernel address space. This is +// NOT the address where the kernel is loaded to: the kernel is loaded in the +// top 2GB of the virtual address space as required by GCC's kernel code model. +// The whole kernel address space is the top 512GB of the address space. +#define KERNEL_BASE 0xffffff8000000000 +#define KERNEL_SIZE 0x8000000000 +#define KERNEL_TOP (KERNEL_BASE + (KERNEL_SIZE - 1)) + +// Userspace address space layout. +#define USER_BASE 0x0 +#define USER_BASE_ANY 0x100000 +#define USER_SIZE 0x800000000000 +#define USER_TOP (USER_BASE + USER_SIZE) + +#define KERNEL_USER_DATA_BASE 0x7fffefff0000 +#define USER_STACK_REGION 0x7ffff0000000 +#define USER_STACK_REGION_SIZE (USER_TOP - USER_STACK_REGION) + + +#else // __x86_64__ + + // memory layout #define KERNEL_BASE 0x80000000 #define KERNEL_SIZE 0x80000000 #define KERNEL_TOP (KERNEL_BASE + (KERNEL_SIZE - 1)) -#ifdef _BOOT_MODE -# define KERNEL_BASE_64BIT 0xffffffff80000000ll -#endif - /* User space layout is a little special: * The user space does not completely cover the space not covered by the * kernel. There is a gap of 64kb between the user and kernel space. The 64kb @@ -40,4 +74,7 @@ #define USER_STACK_REGION 0x70000000 #define USER_STACK_REGION_SIZE (USER_TOP - USER_STACK_REGION) -#endif /* _KERNEL_ARCH_x86_KERNEL_H */ + +#endif // __x86_64__ + +#endif // _KERNEL_ARCH_x86_KERNEL_H diff --git a/headers/private/kernel/arch/x86/arch_thread.h b/headers/private/kernel/arch/x86/arch_thread.h index f0513717c9..567d4caff0 100644 --- a/headers/private/kernel/arch/x86/arch_thread.h +++ b/headers/private/kernel/arch/x86/arch_thread.h @@ -16,39 +16,65 @@ extern "C" { #endif -struct iframe *i386_get_user_iframe(void); -struct iframe *i386_get_current_iframe(void); -struct iframe *i386_get_thread_user_iframe(Thread *thread); -uint32 x86_next_page_directory(Thread *from, Thread *to); +struct iframe* i386_get_user_iframe(void); +struct iframe* i386_get_current_iframe(void); +struct iframe* i386_get_thread_user_iframe(Thread* thread); -void x86_restart_syscall(struct iframe *frame); +uint32 x86_next_page_directory(Thread* from, Thread* to); + +void x86_restart_syscall(struct iframe* frame); + +void x86_set_tls_context(Thread* thread); + + +#ifdef __x86_64__ + + +// TODO +static inline Thread* +arch_thread_get_current_thread(void) +{ + return NULL; +} + + +static inline void +arch_thread_set_current_thread(Thread* t) +{ + +} + + +#else // __x86_64__ -void x86_set_tls_context(Thread *thread); // override empty macro #undef arch_syscall_64_bit_return_value void arch_syscall_64_bit_return_value(void); -static -inline Thread * +static inline Thread* arch_thread_get_current_thread(void) { - Thread *t; + Thread* t; read_dr3(t); return t; } + static inline void -arch_thread_set_current_thread(Thread *t) +arch_thread_set_current_thread(Thread* t) { write_dr3(t); } + +#endif // __x86_64__ + + #ifdef __cplusplus } #endif #endif /* _KERNEL_ARCH_x86_THREAD_H */ - diff --git a/headers/private/kernel/arch/x86/arch_thread_types.h b/headers/private/kernel/arch/x86/arch_thread_types.h index 0df49071c0..900046fd0b 100644 --- a/headers/private/kernel/arch/x86/arch_thread_types.h +++ b/headers/private/kernel/arch/x86/arch_thread_types.h @@ -11,23 +11,31 @@ #include + #define _ALIGNED(bytes) __attribute__((aligned(bytes))) // move this to somewhere else, maybe BeBuild.h? + struct farcall { - uint32 *esp; - uint32 *ss; + uint32* esp; + uint32* ss; }; + // architecture specific thread info struct arch_thread { +#ifdef __x86_64__ + uint64* rsp; +#else struct farcall current_stack; struct farcall interrupt_stack; +#endif // 512 byte floating point save point - this must be 16 byte aligned - uint8 fpu_state[512]; + uint8 fpu_state[512] _ALIGNED(16); } _ALIGNED(16); + struct arch_team { // gcc treats empty structures as zero-length in C, but as if they contain // a char in C++. So we have to put a dummy in to be able to use the struct @@ -35,8 +43,10 @@ struct arch_team { char dummy; }; + struct arch_fork_arg { struct iframe iframe; }; + #endif /* _KERNEL_ARCH_x86_THREAD_TYPES_H */ diff --git a/headers/private/kernel/arch/x86/descriptors.h b/headers/private/kernel/arch/x86/descriptors.h index 19d7e93a71..69699c8745 100644 --- a/headers/private/kernel/arch/x86/descriptors.h +++ b/headers/private/kernel/arch/x86/descriptors.h @@ -9,45 +9,8 @@ #define _KERNEL_ARCH_x86_DESCRIPTORS_H -#define KERNEL_CODE_SEG 0x8 -#define KERNEL_DATA_SEG 0x10 - -#define USER_CODE_SEG 0x1b -#define USER_DATA_SEG 0x23 - -#define APM_CODE32_SEGMENT 0x28 -#define APM_CODE16_SEGMENT 0x30 -#define APM_DATA_SEGMENT 0x38 - -#define BIOS_DATA_SEGMENT 0x40 - #ifndef _ASSEMBLER - // this file can also be included from assembler as well - // (and is in arch_interrupts.S) -#define DOUBLE_FAULT_TSS_BASE_SEGMENT 9 -#define TSS_BASE_SEGMENT (DOUBLE_FAULT_TSS_BASE_SEGMENT + smp_get_num_cpus()) -#define TLS_BASE_SEGMENT (TSS_BASE_SEGMENT + smp_get_num_cpus()) -#define APM_BASE_SEGMENT (TLS_BASE_SEGMENT + smp_get_num_cpus()) - - -// defines entries in the GDT/LDT - -typedef struct segment_descriptor { - uint16 limit_00_15; // bit 0 - 15 - uint16 base_00_15; // 16 - 31 - uint32 base_23_16 : 8; // 0 - 7 - uint32 type : 4; // 8 - 11 - uint32 desc_type : 1; // 12 (0 = system, 1 = code/data) - uint32 privilege_level : 2; // 13 - 14 - uint32 present : 1; // 15 - uint32 limit_19_16 : 4; // 16 - 19 - uint32 available : 1; // 20 - uint32 zero : 1; // 21 - uint32 d_b : 1; // 22 - uint32 granularity : 1; // 23 - uint32 base_31_24 : 8; // 24 - 31 -} segment_descriptor; enum descriptor_privilege_levels { DPL_KERNEL = 0, @@ -73,74 +36,20 @@ enum descriptor_types { DT_CODE_DATA_SEGMENT = 1, }; -static inline void -clear_segment_descriptor(struct segment_descriptor *desc) -{ - *(long long *)desc = 0; -} +enum gate_types { + GATE_INTERRUPT = 14, + GATE_TRAP = 15, +}; -static inline void -set_segment_descriptor_base(struct segment_descriptor *desc, addr_t base) -{ - desc->base_00_15 = (addr_t)base & 0xffff; // base is 32 bits long - desc->base_23_16 = ((addr_t)base >> 16) & 0xff; - desc->base_31_24 = ((addr_t)base >> 24) & 0xff; -} +#endif // !_ASSEMBLER -static inline void -set_segment_descriptor(struct segment_descriptor *desc, addr_t base, uint32 limit, - uint8 type, uint8 privilegeLevel) -{ - set_segment_descriptor_base(desc, base); +#ifdef __x86_64__ +# include +#else +# include +#endif - // limit is 20 bits long - if (limit & 0xfff00000) { - desc->limit_00_15 = ((addr_t)limit >> 12) & 0x0ffff; - desc->limit_19_16 = ((addr_t)limit >> 28) & 0xf; - desc->granularity = 1; // 4 KB granularity - } else { - desc->limit_00_15 = (addr_t)limit & 0x0ffff; - desc->limit_19_16 = ((addr_t)limit >> 16) & 0xf; - desc->granularity = 0; // 1 byte granularity - } - limit >>= 12; - - - desc->type = type; - desc->desc_type = DT_CODE_DATA_SEGMENT; - desc->privilege_level = privilegeLevel; - - desc->present = 1; - desc->available = 0; // system available bit is currently not used - desc->d_b = 1; // 32-bit code - - desc->zero = 0; -} - - -static inline void -set_tss_descriptor(struct segment_descriptor *desc, addr_t base, uint32 limit) -{ - // the TSS descriptor has a special layout different from the standard descriptor - set_segment_descriptor_base(desc, base); - - desc->limit_00_15 = (addr_t)limit & 0x0ffff; - desc->limit_19_16 = 0; - - desc->type = DT_TSS; - desc->desc_type = DT_SYSTEM_SEGMENT; - desc->privilege_level = DPL_KERNEL; - - desc->present = 1; - desc->granularity = 0; // 1 Byte granularity - desc->available = 0; // system available bit is currently not used - desc->d_b = 0; - - desc->zero = 0; -} - -#endif /* _ASSEMBLER */ #endif /* _KERNEL_ARCH_x86_DESCRIPTORS_H */ diff --git a/src/system/boot/platform/bios_ia32/long.cpp b/src/system/boot/platform/bios_ia32/long.cpp index cafc2ed3a2..567c5f34fc 100644 --- a/src/system/boot/platform/bios_ia32/long.cpp +++ b/src/system/boot/platform/bios_ia32/long.cpp @@ -8,7 +8,11 @@ #include -#include +// Include the x86_64 version of descriptors.h +#define __x86_64__ +#include +#undef __x86_64__ + #include #include #include