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 52struct 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 68struct interrupt_descriptor { 69 uint32 a; 70 uint32 b; 71}; 72 73struct 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 90typedef segment_descriptor global_descriptor_table[GDT_SEGMENT_COUNT]; 91extern global_descriptor_table gGDTs[]; 92 93 94static inline void 95clear_segment_descriptor(segment_descriptor* desc) 96{ 97 *(long long*)desc = 0; 98} 99 100 101static inline void 102set_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 110static inline void 111set_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 139static inline void 140set_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 161static inline segment_descriptor* 162get_gdt(int32 cpu) 163{ 164 return gGDTs[cpu]; 165} 166 167 168#endif /* _ASSEMBLER */ 169 170#endif /* _KERNEL_ARCH_X86_32_DESCRIPTORS_H */ 171