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 #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 25 #ifndef _ASSEMBLER 26 // this file can also be included from assembler as well 27 // (and is in arch_interrupts.S) 28 29 #define DOUBLE_FAULT_TSS_BASE_SEGMENT 9 30 #define TSS_BASE_SEGMENT (DOUBLE_FAULT_TSS_BASE_SEGMENT + smp_get_num_cpus()) 31 #define TLS_BASE_SEGMENT (TSS_BASE_SEGMENT + smp_get_num_cpus()) 32 #define APM_BASE_SEGMENT (TLS_BASE_SEGMENT + smp_get_num_cpus()) 33 34 #define TSS_SEGMENT(cpu) (TSS_BASE_SEGMENT + cpu) 35 36 // defines entries in the GDT/LDT 37 38 struct segment_descriptor { 39 uint16 limit_00_15; // bit 0 - 15 40 uint16 base_00_15; // 16 - 31 41 uint32 base_23_16 : 8; // 0 - 7 42 uint32 type : 4; // 8 - 11 43 uint32 desc_type : 1; // 12 (0 = system, 1 = code/data) 44 uint32 privilege_level : 2; // 13 - 14 45 uint32 present : 1; // 15 46 uint32 limit_19_16 : 4; // 16 - 19 47 uint32 available : 1; // 20 48 uint32 zero : 1; // 21 49 uint32 d_b : 1; // 22 50 uint32 granularity : 1; // 23 51 uint32 base_31_24 : 8; // 24 - 31 52 }; 53 54 struct interrupt_descriptor { 55 uint32 a; 56 uint32 b; 57 }; 58 59 struct tss { 60 uint16 prev_task; 61 uint16 unused0; 62 uint32 sp0; 63 uint32 ss0; 64 uint32 sp1; 65 uint32 ss1; 66 uint32 sp2; 67 uint32 ss2; 68 uint32 cr3; 69 uint32 eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi; 70 uint32 es, cs, ss, ds, fs, gs; 71 uint32 ldt_seg_selector; 72 uint16 unused1; 73 uint16 io_map_base; 74 }; 75 76 77 static inline void 78 clear_segment_descriptor(segment_descriptor* desc) 79 { 80 *(long long*)desc = 0; 81 } 82 83 84 static inline void 85 set_segment_descriptor_base(segment_descriptor* desc, addr_t base) 86 { 87 desc->base_00_15 = (addr_t)base & 0xffff; // base is 32 bits long 88 desc->base_23_16 = ((addr_t)base >> 16) & 0xff; 89 desc->base_31_24 = ((addr_t)base >> 24) & 0xff; 90 } 91 92 93 static inline void 94 set_segment_descriptor(segment_descriptor* desc, addr_t base, uint32 limit, 95 uint8 type, uint8 privilegeLevel) 96 { 97 set_segment_descriptor_base(desc, base); 98 99 // limit is 20 bits long 100 if (limit & 0xfff00000) { 101 desc->limit_00_15 = ((addr_t)limit >> 12) & 0x0ffff; 102 desc->limit_19_16 = ((addr_t)limit >> 28) & 0xf; 103 desc->granularity = 1; // 4 KB granularity 104 } else { 105 desc->limit_00_15 = (addr_t)limit & 0x0ffff; 106 desc->limit_19_16 = ((addr_t)limit >> 16) & 0xf; 107 desc->granularity = 0; // 1 byte granularity 108 } 109 110 desc->type = type; 111 desc->desc_type = DT_CODE_DATA_SEGMENT; 112 desc->privilege_level = privilegeLevel; 113 114 desc->present = 1; 115 desc->available = 0; // system available bit is currently not used 116 desc->d_b = 1; // 32-bit code 117 118 desc->zero = 0; 119 } 120 121 122 static inline void 123 set_tss_descriptor(segment_descriptor* desc, addr_t base, uint32 limit) 124 { 125 // the TSS descriptor has a special layout different from the standard descriptor 126 set_segment_descriptor_base(desc, base); 127 128 desc->limit_00_15 = (addr_t)limit & 0x0ffff; 129 desc->limit_19_16 = 0; 130 131 desc->type = DT_TSS; 132 desc->desc_type = DT_SYSTEM_SEGMENT; 133 desc->privilege_level = DPL_KERNEL; 134 135 desc->present = 1; 136 desc->granularity = 0; // 1 Byte granularity 137 desc->available = 0; // system available bit is currently not used 138 desc->d_b = 0; 139 140 desc->zero = 0; 141 } 142 143 144 #endif /* _ASSEMBLER */ 145 146 #endif /* _KERNEL_ARCH_X86_32_DESCRIPTORS_H */ 147