1 /* 2 * Copyright 2002-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. 6 * Distributed under the terms of the NewOS License. 7 */ 8 #ifndef _KERNEL_ARCH_x86_DESCRIPTORS_H 9 #define _KERNEL_ARCH_x86_DESCRIPTORS_H 10 11 12 #define KERNEL_CODE_SEG 0x8 13 #define KERNEL_DATA_SEG 0x10 14 15 #define USER_CODE_SEG 0x1b 16 #define USER_DATA_SEG 0x23 17 18 #define APM_CODE32_SEGMENT 0x28 19 #define APM_CODE16_SEGMENT 0x30 20 #define APM_DATA_SEGMENT 0x38 21 22 #define BIOS_DATA_SEGMENT 0x40 23 24 #ifndef _ASSEMBLER 25 // this file can also be included from assembler as well 26 // (and is in arch_interrupts.S) 27 28 #define DOUBLE_FAULT_TSS_BASE_SEGMENT 9 29 #define TSS_BASE_SEGMENT (DOUBLE_FAULT_TSS_BASE_SEGMENT + smp_get_num_cpus()) 30 #define TLS_BASE_SEGMENT (TSS_BASE_SEGMENT + smp_get_num_cpus()) 31 #define APM_BASE_SEGMENT (TLS_BASE_SEGMENT + smp_get_num_cpus()) 32 33 34 // defines entries in the GDT/LDT 35 36 typedef struct segment_descriptor { 37 uint16 limit_00_15; // bit 0 - 15 38 uint16 base_00_15; // 16 - 31 39 uint32 base_23_16 : 8; // 0 - 7 40 uint32 type : 4; // 8 - 11 41 uint32 desc_type : 1; // 12 (0 = system, 1 = code/data) 42 uint32 privilege_level : 2; // 13 - 14 43 uint32 present : 1; // 15 44 uint32 limit_19_16 : 4; // 16 - 19 45 uint32 available : 1; // 20 46 uint32 zero : 1; // 21 47 uint32 d_b : 1; // 22 48 uint32 granularity : 1; // 23 49 uint32 base_31_24 : 8; // 24 - 31 50 } segment_descriptor; 51 52 enum descriptor_privilege_levels { 53 DPL_KERNEL = 0, 54 DPL_USER = 3, 55 }; 56 57 enum descriptor_types { 58 // segment types 59 DT_CODE_EXECUTE_ONLY = 0x8, 60 DT_CODE_ACCESSED = 0x9, 61 DT_CODE_READABLE = 0xa, 62 DT_CODE_CONFORM = 0xc, 63 DT_DATA_READ_ONLY = 0x0, 64 DT_DATA_ACCESSED = 0x1, 65 DT_DATA_WRITEABLE = 0x2, 66 DT_DATA_EXPANSION_DOWN = 0x4, 67 68 DT_TSS = 9, 69 /* non busy, 32 bit */ 70 71 // descriptor types 72 DT_SYSTEM_SEGMENT = 0, 73 DT_CODE_DATA_SEGMENT = 1, 74 }; 75 76 static inline void 77 clear_segment_descriptor(struct segment_descriptor *desc) 78 { 79 *(long long *)desc = 0; 80 } 81 82 83 static inline void 84 set_segment_descriptor_base(struct segment_descriptor *desc, addr_t base) 85 { 86 desc->base_00_15 = (addr_t)base & 0xffff; // base is 32 bits long 87 desc->base_23_16 = ((addr_t)base >> 16) & 0xff; 88 desc->base_31_24 = ((addr_t)base >> 24) & 0xff; 89 } 90 91 92 static inline void 93 set_segment_descriptor(struct segment_descriptor *desc, addr_t base, uint32 limit, 94 uint8 type, uint8 privilegeLevel) 95 { 96 set_segment_descriptor_base(desc, base); 97 98 // limit is 20 bits long 99 if (limit & 0xfff00000) { 100 desc->limit_00_15 = ((addr_t)limit >> 12) & 0x0ffff; 101 desc->limit_19_16 = ((addr_t)limit >> 28) & 0xf; 102 desc->granularity = 1; // 4 KB granularity 103 } else { 104 desc->limit_00_15 = (addr_t)limit & 0x0ffff; 105 desc->limit_19_16 = ((addr_t)limit >> 16) & 0xf; 106 desc->granularity = 0; // 1 byte granularity 107 } 108 limit >>= 12; 109 110 111 desc->type = type; 112 desc->desc_type = DT_CODE_DATA_SEGMENT; 113 desc->privilege_level = privilegeLevel; 114 115 desc->present = 1; 116 desc->available = 0; // system available bit is currently not used 117 desc->d_b = 1; // 32-bit code 118 119 desc->zero = 0; 120 } 121 122 123 static inline void 124 set_tss_descriptor(struct segment_descriptor *desc, addr_t base, uint32 limit) 125 { 126 // the TSS descriptor has a special layout different from the standard descriptor 127 set_segment_descriptor_base(desc, base); 128 129 desc->limit_00_15 = (addr_t)limit & 0x0ffff; 130 desc->limit_19_16 = 0; 131 132 desc->type = DT_TSS; 133 desc->desc_type = DT_SYSTEM_SEGMENT; 134 desc->privilege_level = DPL_KERNEL; 135 136 desc->present = 1; 137 desc->granularity = 0; // 1 Byte granularity 138 desc->available = 0; // system available bit is currently not used 139 desc->d_b = 0; 140 141 desc->zero = 0; 142 } 143 144 #endif /* _ASSEMBLER */ 145 146 #endif /* _KERNEL_ARCH_x86_DESCRIPTORS_H */ 147