[25] | 1 | /* |
---|
[29] | 2 | * hal_segmentation.h - Segmentation-related values and structures |
---|
[25] | 3 | * |
---|
[29] | 4 | * Copyright (c) 2017 Maxime Villard |
---|
[25] | 5 | * |
---|
[29] | 6 | * This file is part of ALMOS-MKH. |
---|
[25] | 7 | * |
---|
[29] | 8 | * ALMOS-MKH is free software; you can redistribute it and/or modify it |
---|
[25] | 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 | * |
---|
[29] | 12 | * ALMOS-MKH is distributed in the hope that it will be useful, but |
---|
[25] | 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 |
---|
[29] | 18 | * along with ALMOS-MKH.; if not, write to the Free Software Foundation, |
---|
[25] | 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
---|
| 20 | */ |
---|
| 21 | |
---|
| 22 | /* |
---|
[29] | 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] | 25 | */ |
---|
[29] | 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 */ |
---|
[25] | 32 | |
---|
[29] | 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) |
---|
[25] | 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 | |
---|
[29] | 47 | #define SYSSEL_START (NGDT_MEM * 8) |
---|
[25] | 48 | |
---|
[29] | 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) |
---|
[25] | 52 | |
---|
[29] | 53 | #ifndef x86_ASM |
---|
[25] | 54 | |
---|
| 55 | /* |
---|
[29] | 56 | * Offsets. |
---|
[25] | 57 | */ |
---|
[29] | 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)))) |
---|
[25] | 62 | |
---|
[29] | 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 *); |
---|
[31] | 150 | void ltr(uint16_t); |
---|
[29] | 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 NCPUIDT 32 /* reserved entries for CPU exceptions */ |
---|
| 194 | #define NIDT 256 /* total number of IDT entries */ |
---|
| 195 | |
---|