| 1 | /* | 
|---|
| 2 |  * hal_segmentation.h - Segmentation-related values and structures | 
|---|
| 3 |  *  | 
|---|
| 4 |  * Copyright (c) 2017 Maxime Villard | 
|---|
| 5 |  *  | 
|---|
| 6 |  * This file is part of ALMOS-MKH. | 
|---|
| 7 |  * | 
|---|
| 8 |  * ALMOS-MKH is free software; you can redistribute it and/or modify it | 
|---|
| 9 |  * under the terms of the GNU General Public License as published by | 
|---|
| 10 |  * the Free Software Foundation; version 2.0 of the License. | 
|---|
| 11 |  * | 
|---|
| 12 |  * ALMOS-MKH is distributed in the hope that it will be useful, but | 
|---|
| 13 |  * WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 14 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|---|
| 15 |  * General Public License for more details. | 
|---|
| 16 |  * | 
|---|
| 17 |  * You should have received a copy of the GNU General Public License | 
|---|
| 18 |  * along with ALMOS-MKH.; if not, write to the Free Software Foundation, | 
|---|
| 19 |  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 
|---|
| 20 |  */ | 
|---|
| 21 |  | 
|---|
| 22 | /* | 
|---|
| 23 |  * The GDT has NGDT_MEM entries of 8-byte-sized, static memory entries. Then | 
|---|
| 24 |  * there is a certain number of 16-byte-sized TSS entries, one for each CPU. | 
|---|
| 25 |  */ | 
|---|
| 26 | #define GDT_NULL_SEL    0       /* Null descriptor */ | 
|---|
| 27 | #define GDT_KCODE_SEL   1       /* Kernel code descriptor */ | 
|---|
| 28 | #define GDT_KDATA_SEL   2       /* Kernel data descriptor */ | 
|---|
| 29 | #define GDT_UCODE_SEL   3       /* User code descriptor */ | 
|---|
| 30 | #define GDT_UDATA_SEL   4       /* User data descriptor */ | 
|---|
| 31 | #define NGDT_MEM        6               /* aligned */ | 
|---|
| 32 |  | 
|---|
| 33 | #define GDT_CPU0TSS_SEL 0       /* cpu0's tss */ | 
|---|
| 34 | #define NGDT_DYN        (256 - (NGDT_MEM / 2) * 16) | 
|---|
| 35 |  | 
|---|
| 36 | /* | 
|---|
| 37 |  * GDT Selectors Privileges | 
|---|
| 38 |  */ | 
|---|
| 39 | #define ISPL(s)         ((s) & SEL_RPL) | 
|---|
| 40 | #define USERMODE(c, f)          (ISPL(c) == SEL_UPL) | 
|---|
| 41 | #define KERNELMODE(c, f)        (ISPL(c) == SEL_KPL) | 
|---|
| 42 | #define SEL_KPL         0               /* kernel privilege level */ | 
|---|
| 43 | #define SEL_UPL         3               /* user privilege level */ | 
|---|
| 44 | #define SEL_RPL         3               /* requester's privilege level mask */ | 
|---|
| 45 | #define SEL_LDT         4               /* local descriptor table */ | 
|---|
| 46 |  | 
|---|
| 47 | #define SYSSEL_START    (NGDT_MEM * 8) | 
|---|
| 48 |  | 
|---|
| 49 | /* Create a selector, with an index and a privilege */ | 
|---|
| 50 | #define GDT_FIXED_SEL(s,r)      (((s) << 3) | r) | 
|---|
| 51 | #define GDT_DYNAM_SEL(s,r)      ((SYSSEL_START + ((s) << 4)) | r) | 
|---|
| 52 |  | 
|---|
| 53 | #ifndef x86_ASM | 
|---|
| 54 |  | 
|---|
| 55 | /* | 
|---|
| 56 |  * Offsets. | 
|---|
| 57 |  */ | 
|---|
| 58 | #define GDT_ADDR_MEM(s,i)       \ | 
|---|
| 59 |         ((struct gdt_memseg *)((s) + ((i) << 3))) | 
|---|
| 60 | #define GDT_ADDR_SYS(s,i)       \ | 
|---|
| 61 |         ((struct gdt_sysseg *)((s) + (SYSSEL_START + ((i) << 4)))) | 
|---|
| 62 |  | 
|---|
| 63 | /* | 
|---|
| 64 |  * System segment descriptor (16 bytes): used for TSS and LDT. | 
|---|
| 65 |  */ | 
|---|
| 66 | struct gdt_sysseg { | 
|---|
| 67 |         uint64_t sd_lolimit:16; /* segment extent (lsb) */ | 
|---|
| 68 |         uint64_t sd_lobase:24;  /* segment base address (lsb) */ | 
|---|
| 69 |         uint64_t sd_type:5;     /* segment type */ | 
|---|
| 70 |         uint64_t sd_dpl:2;      /* segment descriptor priority level */ | 
|---|
| 71 |         uint64_t sd_p:1;        /* segment descriptor present */ | 
|---|
| 72 |         uint64_t sd_hilimit:4;  /* segment extent (msb) */ | 
|---|
| 73 |         uint64_t sd_xx1:3;      /* avl, long and def32 (not used) */ | 
|---|
| 74 |         uint64_t sd_gran:1;     /* limit granularity (byte/page) */ | 
|---|
| 75 |         uint64_t sd_hibase:40;  /* segment base address (msb) */ | 
|---|
| 76 |         uint64_t sd_xx2:8;      /* reserved */ | 
|---|
| 77 |         uint64_t sd_zero:5;     /* must be zero */ | 
|---|
| 78 |         uint64_t sd_xx3:19;     /* reserved */ | 
|---|
| 79 | } __packed; | 
|---|
| 80 |  | 
|---|
| 81 | /* | 
|---|
| 82 |  * Memory segment descriptor (8 bytes): used for cs, ds, etc. | 
|---|
| 83 |  */ | 
|---|
| 84 | struct gdt_memseg { | 
|---|
| 85 |         unsigned sd_lolimit:16; /* segment extent (lsb) */ | 
|---|
| 86 |         unsigned sd_lobase:24;  /* segment base address (lsb) */ | 
|---|
| 87 |         unsigned sd_type:5;     /* segment type */ | 
|---|
| 88 |         unsigned sd_dpl:2;      /* segment descriptor priority level */ | 
|---|
| 89 |         unsigned sd_p:1;        /* segment descriptor present */ | 
|---|
| 90 |         unsigned sd_hilimit:4;  /* segment extent (msb) */ | 
|---|
| 91 |         unsigned sd_avl:1;      /* available */ | 
|---|
| 92 |         unsigned sd_long:1;     /* long mode */ | 
|---|
| 93 |         unsigned sd_def32:1;    /* default 32 vs 16 bit size */ | 
|---|
| 94 |         unsigned sd_gran:1;     /* limit granularity (byte/page) */ | 
|---|
| 95 |         unsigned sd_hibase:8;   /* segment base address (msb) */ | 
|---|
| 96 | } __packed; | 
|---|
| 97 |  | 
|---|
| 98 | /* | 
|---|
| 99 |  * Common part of the above structures. Used to walk descriptor tables. | 
|---|
| 100 |  */ | 
|---|
| 101 | struct common_segment_descriptor { | 
|---|
| 102 |         unsigned sdc_lolimit:16; | 
|---|
| 103 |         unsigned sdc_lobase:24; | 
|---|
| 104 |         unsigned sdc_type:5; | 
|---|
| 105 |         unsigned sdc_other:19; | 
|---|
| 106 | } __packed; | 
|---|
| 107 |  | 
|---|
| 108 | /* | 
|---|
| 109 |  * IDT descriptors (16 bytes). | 
|---|
| 110 |  */ | 
|---|
| 111 | struct idt_seg { | 
|---|
| 112 |         uint64_t gd_looffset:16;/* gate offset (lsb) */ | 
|---|
| 113 |         uint64_t gd_selector:16;/* gate segment selector */ | 
|---|
| 114 |         uint64_t gd_ist:3;      /* IST select */ | 
|---|
| 115 |         uint64_t gd_xx1:5;      /* reserved */ | 
|---|
| 116 |         uint64_t gd_type:5;     /* segment type */ | 
|---|
| 117 |         uint64_t gd_dpl:2;      /* segment descriptor priority level */ | 
|---|
| 118 |         uint64_t gd_p:1;        /* segment descriptor present */ | 
|---|
| 119 |         uint64_t gd_hioffset:48;/* gate offset (msb) */ | 
|---|
| 120 |         uint64_t gd_xx2:8;      /* reserved */ | 
|---|
| 121 |         uint64_t gd_zero:5;     /* must be zero */ | 
|---|
| 122 |         uint64_t gd_xx3:19;     /* reserved */ | 
|---|
| 123 | } __packed; | 
|---|
| 124 |  | 
|---|
| 125 | /* | 
|---|
| 126 |  * Region descriptors, used to load gdt/idt tables before segments yet exist. | 
|---|
| 127 |  */ | 
|---|
| 128 | struct region_descriptor { | 
|---|
| 129 |         uint16_t rd_limit;      /* segment extent */ | 
|---|
| 130 |         uint64_t rd_base;       /* base address  */ | 
|---|
| 131 | } __packed; | 
|---|
| 132 |  | 
|---|
| 133 | struct tss { | 
|---|
| 134 |         uint32_t tss_reserved1; | 
|---|
| 135 |         uint64_t tss_rsp0; | 
|---|
| 136 |         uint64_t tss_rsp1; | 
|---|
| 137 |         uint64_t tss_rsp3; | 
|---|
| 138 |         uint32_t tss_reserved2; | 
|---|
| 139 |         uint32_t tss_reserved3; | 
|---|
| 140 |         uint64_t tss_ist[7]; | 
|---|
| 141 |         uint32_t tss_reserved4; | 
|---|
| 142 |         uint32_t tss_reserved5; | 
|---|
| 143 |         uint32_t tss_iobase; | 
|---|
| 144 | } __packed; | 
|---|
| 145 |  | 
|---|
| 146 | #define IOMAP_INVALOFF  0xffff | 
|---|
| 147 |  | 
|---|
| 148 | void lgdt(struct region_descriptor *); | 
|---|
| 149 | void lidt(struct region_descriptor *); | 
|---|
| 150 | void ltr(uint16_t); | 
|---|
| 151 |  | 
|---|
| 152 | #endif /* !x86_ASM */ | 
|---|
| 153 |  | 
|---|
| 154 | /* system segments and gate types */ | 
|---|
| 155 | #define SDT_SYSNULL      0      /* system null */ | 
|---|
| 156 | #define SDT_SYS286TSS    1      /* system 286 TSS available */ | 
|---|
| 157 | #define SDT_SYSLDT       2      /* system local descriptor table */ | 
|---|
| 158 | #define SDT_SYS286BSY    3      /* system 286 TSS busy */ | 
|---|
| 159 | #define SDT_SYS286CGT    4      /* system 286 call gate */ | 
|---|
| 160 | #define SDT_SYSTASKGT    5      /* system task gate */ | 
|---|
| 161 | #define SDT_SYS286IGT    6      /* system 286 interrupt gate */ | 
|---|
| 162 | #define SDT_SYS286TGT    7      /* system 286 trap gate */ | 
|---|
| 163 | #define SDT_SYSNULL2     8      /* system null again */ | 
|---|
| 164 | #define SDT_SYS386TSS    9      /* system 386 TSS available */ | 
|---|
| 165 | #define SDT_SYSNULL3    10      /* system null again */ | 
|---|
| 166 | #define SDT_SYS386BSY   11      /* system 386 TSS busy */ | 
|---|
| 167 | #define SDT_SYS386CGT   12      /* system 386 call gate */ | 
|---|
| 168 | #define SDT_SYSNULL4    13      /* system null again */ | 
|---|
| 169 | #define SDT_SYS386IGT   14      /* system 386 interrupt gate */ | 
|---|
| 170 | #define SDT_SYS386TGT   15      /* system 386 trap gate */ | 
|---|
| 171 |  | 
|---|
| 172 | /* memory segment types */ | 
|---|
| 173 | #define SDT_MEMRO       16      /* memory read only */ | 
|---|
| 174 | #define SDT_MEMROA      17      /* memory read only accessed */ | 
|---|
| 175 | #define SDT_MEMRW       18      /* memory read write */ | 
|---|
| 176 | #define SDT_MEMRWA      19      /* memory read write accessed */ | 
|---|
| 177 | #define SDT_MEMROD      20      /* memory read only expand dwn limit */ | 
|---|
| 178 | #define SDT_MEMRODA     21      /* memory read only expand dwn limit accessed */ | 
|---|
| 179 | #define SDT_MEMRWD      22      /* memory read write expand dwn limit */ | 
|---|
| 180 | #define SDT_MEMRWDA     23      /* memory read write expand dwn limit accessed */ | 
|---|
| 181 | #define SDT_MEME        24      /* memory execute only */ | 
|---|
| 182 | #define SDT_MEMEA       25      /* memory execute only accessed */ | 
|---|
| 183 | #define SDT_MEMER       26      /* memory execute read */ | 
|---|
| 184 | #define SDT_MEMERA      27      /* memory execute read accessed */ | 
|---|
| 185 | #define SDT_MEMEC       28      /* memory execute only conforming */ | 
|---|
| 186 | #define SDT_MEMEAC      29      /* memory execute only accessed conforming */ | 
|---|
| 187 | #define SDT_MEMERC      30      /* memory execute read conforming */ | 
|---|
| 188 | #define SDT_MEMERAC     31      /* memory execute read accessed conforming */ | 
|---|
| 189 |  | 
|---|
| 190 | /* | 
|---|
| 191 |  * Entries in the Interrupt Descriptor Table (IDT) | 
|---|
| 192 |  */ | 
|---|
| 193 | #define CPUVEC_MIN      0 | 
|---|
| 194 | #define CPUVEC_MAX      32      /* reserved entries for CPU exceptions */ | 
|---|
| 195 | #define LAPICVEC_MIN    CPUVEC_MAX | 
|---|
| 196 | #define LAPICVEC_MAX    (LAPICVEC_MIN + 1) | 
|---|
| 197 |  | 
|---|
| 198 | #define NIDT    256     /* total number of IDT entries */ | 
|---|
| 199 |  | 
|---|