Index: trunk/hal/x86_64/hal_segmentation.h
===================================================================
--- trunk/hal/x86_64/hal_segmentation.h	(revision 25)
+++ trunk/hal/x86_64/hal_segmentation.h	(revision 29)
@@ -1,16 +1,14 @@
 /*
- * hal_boot.S - Kernel boot entry point
+ * hal_segmentation.h - Segmentation-related values and structures
  * 
- * Author        Maxime Villard (2017)
+ * Copyright (c) 2017 Maxime Villard
+ * 
+ * This file is part of ALMOS-MKH.
  *
- * Copyright (c) UPMC Sorbonne Universites
- * 
- * This file is part of ALMOS-kernel.
- *
- * ALMOS-kernel is free software; you can redistribute it and/or modify it
+ * 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-kernel is distributed in the hope that it will be useful, but
+ * 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
@@ -18,30 +16,180 @@
  *
  * You should have received a copy of the GNU General Public License
- * along with ALMOS-kernel; if not, write to the Free Software Foundation,
+ * along with ALMOS-MKH.; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 /*
- * Selectors
+ * 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_UCODE_SEL	3	/* User code descriptor */
+#define GDT_UDATA_SEL	4	/* User data descriptor */
+#define NGDT_MEM	6		/* aligned */
 
-#define ISPL(s)		((s) & SEL_RPL)	/* what is the priority level of a selector */
+#define GDT_CPU0TSS_SEL	0	/* cpu0's tss */
+#define NGDT_DYN	(256 - (NGDT_MEM / 2) * 16)
+
+/*
+ * 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 ISLDT(s)	((s) & SEL_LDT)	/* is it local or global */
 #define SEL_LDT		4		/* local descriptor table */
 
-#define GSEL(s,r)	(((s) << 3) | r)
+#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
 
 /*
- * Entries in the Global Descriptor Table (GDT). They remain static.
+ * Offsets.
  */
-#define GNULL_SEL	0	/* Null descriptor */
-#define GCODE_SEL	1	/* Kernel code descriptor */
-#define GDATA_SEL	2	/* Kernel data descriptor */
-#define GUCODE_SEL	3	/* User code descriptor */
-#define GUDATA_SEL	4	/* User data descriptor */
+#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;
+	uint64_t tss_rsp1;
+	uint64_t tss_rsp3;
+	uint32_t tss_reserved2;
+	uint32_t tss_reserved3;
+	uint64_t tss_ist[7];
+	uint32_t tss_reserved4;
+	uint32_t tss_reserved5;
+	uint32_t tss_iobase;
+} __packed;
+
+#define IOMAP_INVALOFF	0xffff
+
+void lgdt(struct region_descriptor *);
+void lidt(struct region_descriptor *);
+void ltr(u_short);
+
+#endif /* !x86_ASM */
+
+/* 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 NCPUIDT	32	/* reserved entries for CPU exceptions */
+#define NIDT	256	/* total number of IDT entries */
+
