1 /* 2 * Copyright (c) 2009 Corey Tabaka 3 * Copyright (c) 2014 Intel Corporation 4 * Copyright (c) 2024 Travis Geiselbrecht 5 * 6 * Use of this source code is governed by a MIT-style 7 * license that can be found in the LICENSE file or at 8 * https://opensource.org/licenses/MIT 9 */ 10 #pragma once 11 12 // System Selectors 13 #define NULL_SELECTOR 0x00 14 15 // ********* x86 selectors ********* 16 // Laid out slightly differently based on 32 vs 64 bit mode 17 #if ARCH_X86_64 18 19 #define CODE_SELECTOR 0x08 20 #define CODE_64_SELECTOR 0x10 21 #define DATA_SELECTOR 0x18 22 #define USER_CODE_32_SELECTOR 0x20 23 #define USER_DATA_32_SELECTOR 0x28 24 #define USER_CODE_64_SELECTOR 0x30 25 #define USER_DATA_64_SELECTOR 0x38 26 #define TSS_SELECTOR_BASE 0x40 27 28 #elif ARCH_X86_32 29 30 #define CODE_SELECTOR 0x08 31 #define DATA_SELECTOR 0x10 32 #define USER_CODE_32_SELECTOR 0x18 33 #define USER_DATA_32_SELECTOR 0x20 34 #define TSS_SELECTOR_BASE 0x28 35 36 #else 37 #error unknown architecture 38 #endif 39 40 // Base selector for a gs segment per cpu (SMP_MAX_CPUS) 41 #define PERCPU_SELECTOR_BASE (TSS_SELECTOR_BASE + 8 * SMP_MAX_CPUS) 42 43 // Worksheet of what the syscall instructions do which affects the GDT layout: 44 // SYSENTER 45 // CS = IA32_SYSENTER_CS 46 // SS = IA32_SYSENTER_CS + 8 47 // SYSEXIT 32 48 // CS = IA32_SYSENTER_CS + 16 49 // SS = IA32_SYSENTER_CS + 24 50 // SYSEXIT 64 51 // CS = IA32_SYSENTER_CS + 32 52 // SS = IA32_SYSENTER_CS + 40 53 54 // SYSCALL 55 // CS = IA32_STAR.SYSCALL_CS 56 // SS = IA32_STAR.SYSCALL_CS + 8 57 // SYSRET 32 58 // CS = IA32_STAR.SYSRET_CS 59 // SS = IA32_STAR.SYSRET_CS + 8 60 // SYSRET 64 61 // CS = IA32_STAR.SYSRET_CS + 16 62 // SS = IA32_STAR.SYSRET_CS + 8 63 64 // code/data segment types (S = 1) 65 // bit 0 is A (accessed) 66 // bit 1 is W (accessed) 67 // bit 2 is E (expand-down) 68 // bit 3 is data (0) vs code (1) 69 70 // data segment types: 71 #define SEG_TYPE_DATA_RO 0x0 72 #define SEG_TYPE_DATA_RW 0x2 73 #define SEG_TYPE_DATA_RO_EXPAND_DOWN 0x4 74 #define SEG_TYPE_DATA_RW_EXPAND_DOWN 0x6 75 76 // code segment types: 77 // bit 3 is C (conforming) 78 #define SEG_TYPE_CODE_XO 0x9 79 #define SEG_TYPE_CODE_RO 0xa 80 #define SEG_TYPE_CODE_XO_CONFORMING 0xc 81 #define SEG_TYPE_CODE_RO_CONFORMING 0xe 82 83 // system segment types (S = 0) 84 #define SEG_TYPE_TSS_16 0x1 85 #define SEG_TYPE_LDT 0x2 // usable in 64bit 86 #define SEG_TYPE_TSS_16_BUSY 0x3 87 #define SEG_TYPE_CALL_GATE_16 0x4 88 #define SEG_TYPE_TASK_GATE 0x5 89 #define SEG_TYPE_INT_GATE_16 0x6 90 #define SEG_TYPE_TRAP_GATE_16 0x7 91 #define SEG_TYPE_TSS 0x9 // usable in 64bit 92 #define SEG_TYPE_TSS_BUSY 0xb // usable in 64bit 93 #define SEG_TYPE_CALL_GATE 0xc // usable in 64bit 94 #define SEG_TYPE_INT_GATE 0xe // usable in 64bit 95 #define SEG_TYPE_TRAP_GATE 0xf // usable in 64bit 96 97 #ifndef ASSEMBLY 98 99 #include <sys/types.h> 100 101 typedef uint16_t seg_sel_t; 102 103 void x86_set_gdt_descriptor(seg_sel_t sel, void *base, uint32_t limit, 104 uint8_t present, uint8_t ring, uint8_t sys, uint8_t type, uint8_t gran, uint8_t bits); 105 106 #endif 107