/* * hal_segmentation.h - Segmentation-related values and structures * * Copyright (c) 2017 Maxime Villard * * This file is part of ALMOS-MKH. * * ALMOS-MKH is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2.0 of the License. * * ALMOS-MKH is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ALMOS-MKH; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * The GDT has NGDT_MEM entries of 8-byte-sized, static memory entries. Then * there is a certain number of 16-byte-sized TSS entries, one for each CPU. */ #define GDT_NULL_SEL 0 /* Null descriptor */ #define GDT_KCODE_SEL 1 /* Kernel code descriptor */ #define GDT_KDATA_SEL 2 /* Kernel data descriptor */ #define GDT_UCODE32_SEL 3 /* User code descriptor - 32bit */ #define GDT_UCODE_SEL 4 /* User code descriptor */ #define GDT_UDATA_SEL 5 /* User data descriptor */ #define NGDT_MEM 6 /* aligned */ #define GDT_CPUTSS_SEL 0 /* cpu TSS base index */ #define NGDT_DYN CONFIG_MAX_LOCAL_CORES /* one TSS per core */ /* * GDT Selectors Privileges */ #define ISPL(s) ((s) & SEL_RPL) #define USERMODE(c, f) (ISPL(c) == SEL_UPL) #define KERNELMODE(c, f) (ISPL(c) == SEL_KPL) #define SEL_KPL 0 /* kernel privilege level */ #define SEL_UPL 3 /* user privilege level */ #define SEL_RPL 3 /* requester's privilege level mask */ #define SEL_LDT 4 /* local descriptor table */ #define SYSSEL_START (NGDT_MEM * 8) /* Create a selector, with an index and a privilege */ #define GDT_FIXED_SEL(s,r) (((s) << 3) | r) #define GDT_DYNAM_SEL(s,r) ((SYSSEL_START + ((s) << 4)) | r) #ifndef x86_ASM /* * Offsets. */ #define GDT_ADDR_MEM(s,i) \ ((struct gdt_memseg *)((s) + ((i) << 3))) #define GDT_ADDR_SYS(s,i) \ ((struct gdt_sysseg *)((s) + (SYSSEL_START + ((i) << 4)))) /* * System segment descriptor (16 bytes): used for TSS and LDT. */ struct gdt_sysseg { uint64_t sd_lolimit:16; /* segment extent (lsb) */ uint64_t sd_lobase:24; /* segment base address (lsb) */ uint64_t sd_type:5; /* segment type */ uint64_t sd_dpl:2; /* segment descriptor priority level */ uint64_t sd_p:1; /* segment descriptor present */ uint64_t sd_hilimit:4; /* segment extent (msb) */ uint64_t sd_xx1:3; /* avl, long and def32 (not used) */ uint64_t sd_gran:1; /* limit granularity (byte/page) */ uint64_t sd_hibase:40; /* segment base address (msb) */ uint64_t sd_xx2:8; /* reserved */ uint64_t sd_zero:5; /* must be zero */ uint64_t sd_xx3:19; /* reserved */ } __packed; /* * Memory segment descriptor (8 bytes): used for cs, ds, etc. */ struct gdt_memseg { unsigned sd_lolimit:16; /* segment extent (lsb) */ unsigned sd_lobase:24; /* segment base address (lsb) */ unsigned sd_type:5; /* segment type */ unsigned sd_dpl:2; /* segment descriptor priority level */ unsigned sd_p:1; /* segment descriptor present */ unsigned sd_hilimit:4; /* segment extent (msb) */ unsigned sd_avl:1; /* available */ unsigned sd_long:1; /* long mode */ unsigned sd_def32:1; /* default 32 vs 16 bit size */ unsigned sd_gran:1; /* limit granularity (byte/page) */ unsigned sd_hibase:8; /* segment base address (msb) */ } __packed; /* * Common part of the above structures. Used to walk descriptor tables. */ struct common_segment_descriptor { unsigned sdc_lolimit:16; unsigned sdc_lobase:24; unsigned sdc_type:5; unsigned sdc_other:19; } __packed; /* * IDT descriptors (16 bytes). */ struct idt_seg { uint64_t gd_looffset:16;/* gate offset (lsb) */ uint64_t gd_selector:16;/* gate segment selector */ uint64_t gd_ist:3; /* IST select */ uint64_t gd_xx1:5; /* reserved */ uint64_t gd_type:5; /* segment type */ uint64_t gd_dpl:2; /* segment descriptor priority level */ uint64_t gd_p:1; /* segment descriptor present */ uint64_t gd_hioffset:48;/* gate offset (msb) */ uint64_t gd_xx2:8; /* reserved */ uint64_t gd_zero:5; /* must be zero */ uint64_t gd_xx3:19; /* reserved */ } __packed; /* * Region descriptors, used to load gdt/idt tables before segments yet exist. */ struct region_descriptor { uint16_t rd_limit; /* segment extent */ uint64_t rd_base; /* base address */ } __packed; struct tss { uint32_t tss_reserved1; uint64_t tss_rsp0; /* kernel stack pointer ring 0 */ uint64_t tss_rsp1; /* kernel stack pointer ring 1 */ uint64_t tss_rsp2; /* kernel stack pointer ring 2 */ uint32_t tss_reserved2; uint32_t tss_reserved3; uint64_t tss_ist[7]; /* Interrupt stack table */ uint32_t tss_reserved4; uint32_t tss_reserved5; uint32_t tss_iobase; } __packed; #define IOMAP_INVALOFF 0xffff /* * Our definition of Thread-Local Storage. */ struct tls { void *tls_self; uint32_t tls_gid; uint32_t tls_lid; uint64_t tls_rsp0; /* pointer for fast access */ void *tls_thr; reg_t tls_intr; } __packed; typedef struct tls tls_t; void lgdt(struct region_descriptor *); void lidt(struct region_descriptor *); void ltr(uint16_t); tls_t *curtls(); #define INTRS_ENABLED 0xFFEFAAAA #define INTRS_DISABLED 0xD0CCCCC0 #endif /* !x86_ASM */ /* TLS offsets */ #define TLS_SELF 0 #define TLS_GID 8 #define TLS_LID 12 #define TLS_RSP0 16 /* system segments and gate types */ #define SDT_SYSNULL 0 /* system null */ #define SDT_SYS286TSS 1 /* system 286 TSS available */ #define SDT_SYSLDT 2 /* system local descriptor table */ #define SDT_SYS286BSY 3 /* system 286 TSS busy */ #define SDT_SYS286CGT 4 /* system 286 call gate */ #define SDT_SYSTASKGT 5 /* system task gate */ #define SDT_SYS286IGT 6 /* system 286 interrupt gate */ #define SDT_SYS286TGT 7 /* system 286 trap gate */ #define SDT_SYSNULL2 8 /* system null again */ #define SDT_SYS386TSS 9 /* system 386 TSS available */ #define SDT_SYSNULL3 10 /* system null again */ #define SDT_SYS386BSY 11 /* system 386 TSS busy */ #define SDT_SYS386CGT 12 /* system 386 call gate */ #define SDT_SYSNULL4 13 /* system null again */ #define SDT_SYS386IGT 14 /* system 386 interrupt gate */ #define SDT_SYS386TGT 15 /* system 386 trap gate */ /* memory segment types */ #define SDT_MEMRO 16 /* memory read only */ #define SDT_MEMROA 17 /* memory read only accessed */ #define SDT_MEMRW 18 /* memory read write */ #define SDT_MEMRWA 19 /* memory read write accessed */ #define SDT_MEMROD 20 /* memory read only expand dwn limit */ #define SDT_MEMRODA 21 /* memory read only expand dwn limit accessed */ #define SDT_MEMRWD 22 /* memory read write expand dwn limit */ #define SDT_MEMRWDA 23 /* memory read write expand dwn limit accessed */ #define SDT_MEME 24 /* memory execute only */ #define SDT_MEMEA 25 /* memory execute only accessed */ #define SDT_MEMER 26 /* memory execute read */ #define SDT_MEMERA 27 /* memory execute read accessed */ #define SDT_MEMEC 28 /* memory execute only conforming */ #define SDT_MEMEAC 29 /* memory execute only accessed conforming */ #define SDT_MEMERC 30 /* memory execute read conforming */ #define SDT_MEMERAC 31 /* memory execute read accessed conforming */ /* * Entries in the Interrupt Descriptor Table (IDT) */ #define CPUVEC_MIN 0 #define CPUVEC_MAX 32 /* reserved entries for CPU exceptions */ #define DYNVEC_MIN (CPUVEC_MAX + 0) #define DYNVEC_MAX (CPUVEC_MAX + 4) #define VECTOR_APIC_SPURIOU (DYNVEC_MIN + 0) /* debug only, will be moved soon */ #define LAPIC_TIMER_VECTOR (DYNVEC_MIN + 1) #define IOAPIC_COM1_VECTOR (DYNVEC_MIN + 2) #define IOAPIC_KEYBOARD_VECTOR (DYNVEC_MIN + 3) #define NIDT 256 /* total number of IDT entries */