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