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