1 /* 2 * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef _KERNEL_ARCH_X86_64_DESCRIPTORS_H 6 #define _KERNEL_ARCH_X86_64_DESCRIPTORS_H 7 8 9 // Segment definitions. 10 // Note that the ordering of these is important to SYSCALL/SYSRET. 11 #define KERNEL_CODE_SEGMENT 1 12 #define KERNEL_DATA_SEGMENT 2 13 #define USER32_CODE_SEGMENT 3 14 #define USER_DATA_SEGMENT 4 15 #define USER_CODE_SEGMENT 5 16 17 #define BOOT_GDT_SEGMENT_COUNT (USER_CODE_SEGMENT + 1) 18 19 #define KERNEL_CODE_SELECTOR ((KERNEL_CODE_SEGMENT << 3) | DPL_KERNEL) 20 #define KERNEL_DATA_SELECTOR ((KERNEL_DATA_SEGMENT << 3) | DPL_KERNEL) 21 22 #define USER32_CODE_SELECTOR ((USER32_CODE_SEGMENT << 3) | DPL_USER) 23 #define USER_CODE_SELECTOR ((USER_CODE_SEGMENT << 3) | DPL_USER) 24 #define USER_DATA_SELECTOR ((USER_DATA_SEGMENT << 3) | DPL_USER) 25 26 27 #ifndef _ASSEMBLER 28 29 30 // Structure of a segment descriptor. 31 struct segment_descriptor { 32 uint32 limit0 : 16; 33 uint32 base0 : 24; 34 uint32 type : 4; 35 uint32 desc_type : 1; 36 uint32 dpl : 2; 37 uint32 present : 1; 38 uint32 limit1 : 4; 39 uint32 available : 1; 40 uint32 long_mode : 1; 41 uint32 d_b : 1; 42 uint32 granularity : 1; 43 uint32 base1 : 8; 44 } _PACKED; 45 46 struct tss { 47 uint32 _reserved1; 48 uint64 sp0; 49 uint64 sp1; 50 uint64 sp2; 51 uint64 _reserved2; 52 uint64 ist1; 53 uint64 ist2; 54 uint64 ist3; 55 uint64 ist4; 56 uint64 ist5; 57 uint64 ist6; 58 uint64 ist7; 59 uint64 _reserved3; 60 uint16 _reserved4; 61 uint16 io_map_base; 62 } _PACKED; 63 64 65 static inline void clear_segment_descriptor(segment_descriptor * desc)66clear_segment_descriptor(segment_descriptor* desc) 67 { 68 *(uint64*)desc = 0; 69 } 70 71 72 static inline void set_segment_descriptor(segment_descriptor * desc,uint8 type,uint8 dpl)73set_segment_descriptor(segment_descriptor* desc, uint8 type, uint8 dpl) 74 { 75 clear_segment_descriptor(desc); 76 77 // In 64-bit mode the CPU ignores the base/limit of code/data segments, 78 // it always treats base as 0 and does no limit checks. 79 desc->base0 = 0; 80 desc->base1 = 0; 81 desc->limit0 = 0xffff; 82 desc->limit1 = 0xf; 83 desc->granularity = 1; 84 85 desc->type = type; 86 desc->desc_type = DT_CODE_DATA_SEGMENT; 87 desc->dpl = dpl; 88 desc->present = 1; 89 90 desc->long_mode = (type & DT_CODE_EXECUTE_ONLY) ? 1 : 0; 91 // Must be set to 1 for code segments only. 92 } 93 94 95 unsigned x86_64_set_user_tls_segment_base(int cpu, addr_t base); 96 97 98 #endif /* _ASSEMBLER */ 99 100 #endif /* _KERNEL_ARCH_X86_64_DESCRIPTORS_H */ 101