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_32_DESCRIPTORS_H 9 #define _KERNEL_ARCH_X86_32_DESCRIPTORS_H 10 11 12 // Segments common for all CPUs. 13 #define KERNEL_CODE_SEGMENT 1 14 #define KERNEL_DATA_SEGMENT 2 15 16 #define USER_CODE_SEGMENT 3 17 #define USER_DATA_SEGMENT 4 18 19 #define BOOT_GDT_SEGMENT_COUNT (USER_DATA_SEGMENT + 2) // match x86_64 20 21 #define APM_CODE32_SEGMENT 5 22 #define APM_CODE16_SEGMENT 6 23 #define APM_DATA_SEGMENT 7 24 25 #define BIOS_DATA_SEGMENT 8 26 27 // Per-CPU segments. 28 #define TSS_SEGMENT 9 29 #define DOUBLE_FAULT_TSS_SEGMENT 10 30 #define KERNEL_TLS_SEGMENT 11 31 #define USER_TLS_SEGMENT 12 32 #define APM_SEGMENT 13 33 34 #define GDT_SEGMENT_COUNT 14 35 36 37 #define KERNEL_CODE_SELECTOR ((KERNEL_CODE_SEGMENT << 3) | DPL_KERNEL) 38 #define KERNEL_DATA_SELECTOR ((KERNEL_DATA_SEGMENT << 3) | DPL_KERNEL) 39 40 #define USER_CODE_SELECTOR ((USER_CODE_SEGMENT << 3) | DPL_USER) 41 #define USER_DATA_SELECTOR ((USER_DATA_SEGMENT << 3) | DPL_USER) 42 43 #define KERNEL_TLS_SELECTOR ((KERNEL_TLS_SEGMENT << 3) | DPL_KERNEL) 44 45 46 #ifndef _ASSEMBLER 47 // this file can also be included from assembler as well 48 // (and is in arch_interrupts.S) 49 50 // defines entries in the GDT/LDT 51 52 struct segment_descriptor { 53 uint16 limit_00_15; // bit 0 - 15 54 uint16 base_00_15; // 16 - 31 55 uint32 base_23_16 : 8; // 0 - 7 56 uint32 type : 4; // 8 - 11 57 uint32 desc_type : 1; // 12 (0 = system, 1 = code/data) 58 uint32 privilege_level : 2; // 13 - 14 59 uint32 present : 1; // 15 60 uint32 limit_19_16 : 4; // 16 - 19 61 uint32 available : 1; // 20 62 uint32 zero : 1; // 21 63 uint32 d_b : 1; // 22 64 uint32 granularity : 1; // 23 65 uint32 base_31_24 : 8; // 24 - 31 66 }; 67 68 struct interrupt_descriptor { 69 uint32 a; 70 uint32 b; 71 }; 72 73 struct tss { 74 uint16 prev_task; 75 uint16 unused0; 76 uint32 sp0; 77 uint32 ss0; 78 uint32 sp1; 79 uint32 ss1; 80 uint32 sp2; 81 uint32 ss2; 82 uint32 cr3; 83 uint32 eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi; 84 uint32 es, cs, ss, ds, fs, gs; 85 uint32 ldt_seg_selector; 86 uint16 unused1; 87 uint16 io_map_base; 88 }; 89 90 typedef segment_descriptor global_descriptor_table[GDT_SEGMENT_COUNT]; 91 extern global_descriptor_table gGDTs[]; 92 93 94 static inline void 95 clear_segment_descriptor(segment_descriptor* desc) 96 { 97 *(long long*)desc = 0; 98 } 99 100 101 static inline void 102 set_segment_descriptor_base(segment_descriptor* desc, addr_t base) 103 { 104 desc->base_00_15 = (addr_t)base & 0xffff; // base is 32 bits long 105 desc->base_23_16 = ((addr_t)base >> 16) & 0xff; 106 desc->base_31_24 = ((addr_t)base >> 24) & 0xff; 107 } 108 109 110 static inline void 111 set_segment_descriptor(segment_descriptor* desc, addr_t base, uint32 limit, 112 uint8 type, uint8 privilegeLevel) 113 { 114 set_segment_descriptor_base(desc, base); 115 116 // limit is 20 bits long 117 if (limit & 0xfff00000) { 118 desc->limit_00_15 = ((addr_t)limit >> 12) & 0x0ffff; 119 desc->limit_19_16 = ((addr_t)limit >> 28) & 0xf; 120 desc->granularity = 1; // 4 KB granularity 121 } else { 122 desc->limit_00_15 = (addr_t)limit & 0x0ffff; 123 desc->limit_19_16 = ((addr_t)limit >> 16) & 0xf; 124 desc->granularity = 0; // 1 byte granularity 125 } 126 127 desc->type = type; 128 desc->desc_type = DT_CODE_DATA_SEGMENT; 129 desc->privilege_level = privilegeLevel; 130 131 desc->present = 1; 132 desc->available = 0; // system available bit is currently not used 133 desc->d_b = 1; // 32-bit code 134 135 desc->zero = 0; 136 } 137 138 139 static inline void 140 set_tss_descriptor(segment_descriptor* desc, addr_t base, uint32 limit) 141 { 142 // the TSS descriptor has a special layout different from the standard descriptor 143 set_segment_descriptor_base(desc, base); 144 145 desc->limit_00_15 = (addr_t)limit & 0x0ffff; 146 desc->limit_19_16 = 0; 147 148 desc->type = DT_TSS; 149 desc->desc_type = DT_SYSTEM_SEGMENT; 150 desc->privilege_level = DPL_KERNEL; 151 152 desc->present = 1; 153 desc->granularity = 0; // 1 Byte granularity 154 desc->available = 0; // system available bit is currently not used 155 desc->d_b = 0; 156 157 desc->zero = 0; 158 } 159 160 161 static inline segment_descriptor* 162 get_gdt(int32 cpu) 163 { 164 return gGDTs[cpu]; 165 } 166 167 168 #endif /* _ASSEMBLER */ 169 170 #endif /* _KERNEL_ARCH_X86_32_DESCRIPTORS_H */ 171