| 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_UCODE32_SEL 3 /* User code descriptor - 32bit */ |
|---|
| 30 | #define GDT_UCODE_SEL 4 /* User code descriptor */ |
|---|
| 31 | #define GDT_UDATA_SEL 5 /* User data descriptor */ |
|---|
| 32 | #define NGDT_MEM 6 /* aligned */ |
|---|
| 33 | |
|---|
| 34 | #define GDT_CPUTSS_SEL 0 /* cpu TSS base index */ |
|---|
| 35 | #define NGDT_DYN CONFIG_MAX_LOCAL_CORES /* one TSS per core */ |
|---|
| 36 | |
|---|
| 37 | /* |
|---|
| 38 | * GDT Selectors Privileges |
|---|
| 39 | */ |
|---|
| 40 | #define ISPL(s) ((s) & SEL_RPL) |
|---|
| 41 | #define USERMODE(c, f) (ISPL(c) == SEL_UPL) |
|---|
| 42 | #define KERNELMODE(c, f) (ISPL(c) == SEL_KPL) |
|---|
| 43 | #define SEL_KPL 0 /* kernel privilege level */ |
|---|
| 44 | #define SEL_UPL 3 /* user privilege level */ |
|---|
| 45 | #define SEL_RPL 3 /* requester's privilege level mask */ |
|---|
| 46 | #define SEL_LDT 4 /* local descriptor table */ |
|---|
| 47 | |
|---|
| 48 | #define SYSSEL_START (NGDT_MEM * 8) |
|---|
| 49 | |
|---|
| 50 | /* Create a selector, with an index and a privilege */ |
|---|
| 51 | #define GDT_FIXED_SEL(s,r) (((s) << 3) | r) |
|---|
| 52 | #define GDT_DYNAM_SEL(s,r) ((SYSSEL_START + ((s) << 4)) | r) |
|---|
| 53 | |
|---|
| 54 | #ifndef x86_ASM |
|---|
| 55 | |
|---|
| 56 | /* |
|---|
| 57 | * Offsets. |
|---|
| 58 | */ |
|---|
| 59 | #define GDT_ADDR_MEM(s,i) \ |
|---|
| 60 | ((struct gdt_memseg *)((s) + ((i) << 3))) |
|---|
| 61 | #define GDT_ADDR_SYS(s,i) \ |
|---|
| 62 | ((struct gdt_sysseg *)((s) + (SYSSEL_START + ((i) << 4)))) |
|---|
| 63 | |
|---|
| 64 | /* |
|---|
| 65 | * System segment descriptor (16 bytes): used for TSS and LDT. |
|---|
| 66 | */ |
|---|
| 67 | struct gdt_sysseg { |
|---|
| 68 | uint64_t sd_lolimit:16; /* segment extent (lsb) */ |
|---|
| 69 | uint64_t sd_lobase:24; /* segment base address (lsb) */ |
|---|
| 70 | uint64_t sd_type:5; /* segment type */ |
|---|
| 71 | uint64_t sd_dpl:2; /* segment descriptor priority level */ |
|---|
| 72 | uint64_t sd_p:1; /* segment descriptor present */ |
|---|
| 73 | uint64_t sd_hilimit:4; /* segment extent (msb) */ |
|---|
| 74 | uint64_t sd_xx1:3; /* avl, long and def32 (not used) */ |
|---|
| 75 | uint64_t sd_gran:1; /* limit granularity (byte/page) */ |
|---|
| 76 | uint64_t sd_hibase:40; /* segment base address (msb) */ |
|---|
| 77 | uint64_t sd_xx2:8; /* reserved */ |
|---|
| 78 | uint64_t sd_zero:5; /* must be zero */ |
|---|
| 79 | uint64_t sd_xx3:19; /* reserved */ |
|---|
| 80 | } __packed; |
|---|
| 81 | |
|---|
| 82 | /* |
|---|
| 83 | * Memory segment descriptor (8 bytes): used for cs, ds, etc. |
|---|
| 84 | */ |
|---|
| 85 | struct gdt_memseg { |
|---|
| 86 | unsigned sd_lolimit:16; /* segment extent (lsb) */ |
|---|
| 87 | unsigned sd_lobase:24; /* segment base address (lsb) */ |
|---|
| 88 | unsigned sd_type:5; /* segment type */ |
|---|
| 89 | unsigned sd_dpl:2; /* segment descriptor priority level */ |
|---|
| 90 | unsigned sd_p:1; /* segment descriptor present */ |
|---|
| 91 | unsigned sd_hilimit:4; /* segment extent (msb) */ |
|---|
| 92 | unsigned sd_avl:1; /* available */ |
|---|
| 93 | unsigned sd_long:1; /* long mode */ |
|---|
| 94 | unsigned sd_def32:1; /* default 32 vs 16 bit size */ |
|---|
| 95 | unsigned sd_gran:1; /* limit granularity (byte/page) */ |
|---|
| 96 | unsigned sd_hibase:8; /* segment base address (msb) */ |
|---|
| 97 | } __packed; |
|---|
| 98 | |
|---|
| 99 | /* |
|---|
| 100 | * Common part of the above structures. Used to walk descriptor tables. |
|---|
| 101 | */ |
|---|
| 102 | struct common_segment_descriptor { |
|---|
| 103 | unsigned sdc_lolimit:16; |
|---|
| 104 | unsigned sdc_lobase:24; |
|---|
| 105 | unsigned sdc_type:5; |
|---|
| 106 | unsigned sdc_other:19; |
|---|
| 107 | } __packed; |
|---|
| 108 | |
|---|
| 109 | /* |
|---|
| 110 | * IDT descriptors (16 bytes). |
|---|
| 111 | */ |
|---|
| 112 | struct idt_seg { |
|---|
| 113 | uint64_t gd_looffset:16;/* gate offset (lsb) */ |
|---|
| 114 | uint64_t gd_selector:16;/* gate segment selector */ |
|---|
| 115 | uint64_t gd_ist:3; /* IST select */ |
|---|
| 116 | uint64_t gd_xx1:5; /* reserved */ |
|---|
| 117 | uint64_t gd_type:5; /* segment type */ |
|---|
| 118 | uint64_t gd_dpl:2; /* segment descriptor priority level */ |
|---|
| 119 | uint64_t gd_p:1; /* segment descriptor present */ |
|---|
| 120 | uint64_t gd_hioffset:48;/* gate offset (msb) */ |
|---|
| 121 | uint64_t gd_xx2:8; /* reserved */ |
|---|
| 122 | uint64_t gd_zero:5; /* must be zero */ |
|---|
| 123 | uint64_t gd_xx3:19; /* reserved */ |
|---|
| 124 | } __packed; |
|---|
| 125 | |
|---|
| 126 | /* |
|---|
| 127 | * Region descriptors, used to load gdt/idt tables before segments yet exist. |
|---|
| 128 | */ |
|---|
| 129 | struct region_descriptor { |
|---|
| 130 | uint16_t rd_limit; /* segment extent */ |
|---|
| 131 | uint64_t rd_base; /* base address */ |
|---|
| 132 | } __packed; |
|---|
| 133 | |
|---|
| 134 | struct tss { |
|---|
| 135 | uint32_t tss_reserved1; |
|---|
| 136 | uint64_t tss_rsp0; /* kernel stack pointer ring 0 */ |
|---|
| 137 | uint64_t tss_rsp1; /* kernel stack pointer ring 1 */ |
|---|
| 138 | uint64_t tss_rsp2; /* kernel stack pointer ring 2 */ |
|---|
| 139 | uint32_t tss_reserved2; |
|---|
| 140 | uint32_t tss_reserved3; |
|---|
| 141 | uint64_t tss_ist[7]; /* Interrupt stack table */ |
|---|
| 142 | uint32_t tss_reserved4; |
|---|
| 143 | uint32_t tss_reserved5; |
|---|
| 144 | uint32_t tss_iobase; |
|---|
| 145 | } __packed; |
|---|
| 146 | |
|---|
| 147 | #define IOMAP_INVALOFF 0xffff |
|---|
| 148 | |
|---|
| 149 | /* |
|---|
| 150 | * Our definition of Thread-Local Storage. |
|---|
| 151 | */ |
|---|
| 152 | struct tls { |
|---|
| 153 | void *tls_self; |
|---|
| 154 | uint32_t tls_gid; |
|---|
| 155 | uint32_t tls_lid; |
|---|
| 156 | uint64_t tls_rsp0; /* pointer for fast access */ |
|---|
| 157 | reg_t tls_intr; |
|---|
| 158 | void *tls_thr; |
|---|
| 159 | } __packed; |
|---|
| 160 | typedef struct tls tls_t; |
|---|
| 161 | |
|---|
| 162 | void lgdt(struct region_descriptor *); |
|---|
| 163 | void lidt(struct region_descriptor *); |
|---|
| 164 | void ltr(uint16_t); |
|---|
| 165 | tls_t *curtls( void ); |
|---|
| 166 | |
|---|
| 167 | #define INTRS_ENABLED 0xFFEFAAAA |
|---|
| 168 | #define INTRS_DISABLED 0xD0CCCCC0 |
|---|
| 169 | |
|---|
| 170 | #endif /* !x86_ASM */ |
|---|
| 171 | |
|---|
| 172 | /* TLS offsets */ |
|---|
| 173 | #define TLS_SELF 0 |
|---|
| 174 | #define TLS_GID 8 |
|---|
| 175 | #define TLS_LID 12 |
|---|
| 176 | #define TLS_RSP0 16 |
|---|
| 177 | #define TLS_INTR 24 |
|---|
| 178 | |
|---|
| 179 | /* system segments and gate types */ |
|---|
| 180 | #define SDT_SYSNULL 0 /* system null */ |
|---|
| 181 | #define SDT_SYS286TSS 1 /* system 286 TSS available */ |
|---|
| 182 | #define SDT_SYSLDT 2 /* system local descriptor table */ |
|---|
| 183 | #define SDT_SYS286BSY 3 /* system 286 TSS busy */ |
|---|
| 184 | #define SDT_SYS286CGT 4 /* system 286 call gate */ |
|---|
| 185 | #define SDT_SYSTASKGT 5 /* system task gate */ |
|---|
| 186 | #define SDT_SYS286IGT 6 /* system 286 interrupt gate */ |
|---|
| 187 | #define SDT_SYS286TGT 7 /* system 286 trap gate */ |
|---|
| 188 | #define SDT_SYSNULL2 8 /* system null again */ |
|---|
| 189 | #define SDT_SYS386TSS 9 /* system 386 TSS available */ |
|---|
| 190 | #define SDT_SYSNULL3 10 /* system null again */ |
|---|
| 191 | #define SDT_SYS386BSY 11 /* system 386 TSS busy */ |
|---|
| 192 | #define SDT_SYS386CGT 12 /* system 386 call gate */ |
|---|
| 193 | #define SDT_SYSNULL4 13 /* system null again */ |
|---|
| 194 | #define SDT_SYS386IGT 14 /* system 386 interrupt gate */ |
|---|
| 195 | #define SDT_SYS386TGT 15 /* system 386 trap gate */ |
|---|
| 196 | |
|---|
| 197 | /* memory segment types */ |
|---|
| 198 | #define SDT_MEMRO 16 /* memory read only */ |
|---|
| 199 | #define SDT_MEMROA 17 /* memory read only accessed */ |
|---|
| 200 | #define SDT_MEMRW 18 /* memory read write */ |
|---|
| 201 | #define SDT_MEMRWA 19 /* memory read write accessed */ |
|---|
| 202 | #define SDT_MEMROD 20 /* memory read only expand dwn limit */ |
|---|
| 203 | #define SDT_MEMRODA 21 /* memory read only expand dwn limit accessed */ |
|---|
| 204 | #define SDT_MEMRWD 22 /* memory read write expand dwn limit */ |
|---|
| 205 | #define SDT_MEMRWDA 23 /* memory read write expand dwn limit accessed */ |
|---|
| 206 | #define SDT_MEME 24 /* memory execute only */ |
|---|
| 207 | #define SDT_MEMEA 25 /* memory execute only accessed */ |
|---|
| 208 | #define SDT_MEMER 26 /* memory execute read */ |
|---|
| 209 | #define SDT_MEMERA 27 /* memory execute read accessed */ |
|---|
| 210 | #define SDT_MEMEC 28 /* memory execute only conforming */ |
|---|
| 211 | #define SDT_MEMEAC 29 /* memory execute only accessed conforming */ |
|---|
| 212 | #define SDT_MEMERC 30 /* memory execute read conforming */ |
|---|
| 213 | #define SDT_MEMERAC 31 /* memory execute read accessed conforming */ |
|---|
| 214 | |
|---|
| 215 | /* |
|---|
| 216 | * Entries in the Interrupt Descriptor Table (IDT) |
|---|
| 217 | */ |
|---|
| 218 | #define CPUVEC_MIN 0 |
|---|
| 219 | #define CPUVEC_MAX 32 /* reserved entries for CPU exceptions */ |
|---|
| 220 | |
|---|
| 221 | #define DYNVEC_MIN (CPUVEC_MAX + 0) |
|---|
| 222 | #define DYNVEC_MAX (CPUVEC_MAX + 4) |
|---|
| 223 | |
|---|
| 224 | #define VECTOR_APIC_SPURIOU (DYNVEC_MIN + 0) |
|---|
| 225 | |
|---|
| 226 | /* debug only, will be moved soon */ |
|---|
| 227 | #define LAPIC_TIMER_VECTOR (DYNVEC_MIN + 1) |
|---|
| 228 | #define IOAPIC_COM1_VECTOR (DYNVEC_MIN + 2) |
|---|
| 229 | #define IOAPIC_KEYBOARD_VECTOR (DYNVEC_MIN + 3) |
|---|
| 230 | |
|---|
| 231 | #define NIDT 256 /* total number of IDT entries */ |
|---|
| 232 | |
|---|