diff --git a/arch/x86/tools/.gitignore b/arch/x86/tools/.gitignore
new file mode 100644
index 0000000..5ac19b6
--- /dev/null
+++ b/arch/x86/tools/.gitignore
@@ -0,0 +1 @@
+./gdt
diff --git a/arch/x86/tools/gdt.c b/arch/x86/tools/gdt.c
new file mode 100644
index 0000000..cc97aed
--- /dev/null
+++ b/arch/x86/tools/gdt.c
@@ -0,0 +1,134 @@
+/*
+ * This program generates the GDT entries for the x86.
+ * Taken from <https://wiki.osdev.org/GDT_Tutorial> and modified to our needs.
+ * It conforms to ISO C99 and can be built on any POSIX compliant system using
+ * the command `make gdt.c`.  It outputs the assembly directives for the GDT.
+ *
+ * May nobody need to touch this mess ever again.
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdio.h>
+
+/*
+ * Each define here is for a specific flag in the descriptor.
+ * See the Intel SDM vol 3A, sec 3.4, fig 3-8 for details.
+ */
+#define SEG_TYPE(x)	 ((x) << 12) /* Descriptor type (0 for system, 1 for code/data) */
+#define SEG_PRIV(x)	(((x) & 3) << 13) /* Descriptor Privilege Level (0 - 3) */
+#define SEG_PRES(x)	 ((x) << 15) /* Present */
+#define SEG_AVL(x)	 ((x) << 20) /* Available for system use (we don't use that) */
+#define SEG_LONG(x)	 ((x) << 21) /* 64-bit Long mode code segment */
+#define SEG_SIZE(x)	 ((x) << 22) /* Size (0 for 16/64-bit, 1 for 32) */
+#define SEG_GRAN(x)	 ((x) << 23) /* Granularity (0 for 1B - 1MB, 1 for 4KB - 4GB) */
+
+#define SEG_DATA_R	0x000 /* read                               */
+#define SEG_DATA_RA	0x100 /* read,                     accessed */
+#define SEG_DATA_RW	0x200 /* read,              write           */
+#define SEG_DATA_RWA	0x300 /* read,              write, accessed */
+#define SEG_DATA_RE	0x400 /* read, expand-down                  */
+#define SEG_DATA_REA	0x500 /* read, expand-down,        accessed */
+#define SEG_DATA_REW	0x600 /* read,              write           */
+#define SEG_DATA_REWA	0x700 /* read, expand-down, write, accessed */
+
+#define SEG_CODE_X	0x800 /* execute                             */
+#define SEG_CODE_XA	0x900 /* execute,                   accessed */
+#define SEG_CODE_XR	0xa00 /* execute,             read           */
+#define SEG_CODE_XRA	0xb00 /* execute,             read, accessed */
+#define SEG_CODE_XC	0xc00 /* execute, conforming                 */
+#define SEG_CODE_XCA	0xd00 /* execute, conforming,       accessed */
+#define SEG_CODE_XCR	0xe00 /* execute, conforming, read           */
+#define SEG_CODE_XCRA	0xf00 /* execute, conforming, read, accessed */
+
+#define KERN_CODE32 (					\
+	SEG_TYPE(1) | SEG_PRES(1) | SEG_AVL(0)  |	\
+	SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) |	\
+	SEG_PRIV(0) | SEG_CODE_XR			\
+)
+
+#define USER_CODE32 (					\
+	SEG_TYPE(1) | SEG_PRES(1) | SEG_AVL(0)  |	\
+	SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) |	\
+	SEG_PRIV(3) | SEG_CODE_XR			\
+)
+
+#define KERN_CODE64 (					\
+	SEG_TYPE(1) | SEG_PRES(1) | SEG_AVL(0)  |	\
+	SEG_LONG(1) | SEG_SIZE(0) | SEG_GRAN(1) |	\
+	SEG_PRIV(0) | SEG_CODE_XR			\
+)
+
+#define USER_CODE64 (					\
+	SEG_TYPE(1) | SEG_PRES(1) | SEG_AVL(0)  |	\
+	SEG_LONG(1) | SEG_SIZE(0) | SEG_GRAN(1) |	\
+	SEG_PRIV(3) | SEG_CODE_XR			\
+)
+
+#define KERN_DATA (					\
+	SEG_TYPE(1) | SEG_PRES(1) | SEG_AVL(0)  |	\
+	SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) |	\
+	SEG_PRIV(0) | SEG_DATA_RW			\
+)
+
+#define USER_DATA (					\
+	SEG_TYPE(1) | SEG_PRES(1) | SEG_AVL(0)  |	\
+	SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) |	\
+	SEG_PRIV(3) | SEG_DATA_RW			\
+)
+
+#define KERN_TSS (					\
+	SEG_TYPE(0) | SEG_PRES(1) | SEG_AVL(0)  |	\
+	SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(0) |	\
+	SEG_PRIV(0) | SEG_CODE_XA			\
+)
+
+#define USER_TSS (					\
+	SEG_TYPE(0) | SEG_PRES(1) | SEG_AVL(0)  |	\
+	SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(0) |	\
+	SEG_PRIV(3) | SEG_CODE_XA			\
+)
+
+int offset(void)
+{
+	static int i = 0;
+	return i++ * 8;
+}
+
+void print_desc(uint32_t base, uint32_t limit, uint32_t flag, const char *comment)
+{
+	uint32_t low_desc, high_desc;
+
+	/* Create the low 32 bit segment part */
+	low_desc  = base  << 16;		/* set base bits 15:0 */
+	low_desc |= limit  & 0x0000FFFF;	/* set limit bits 15:0 */
+
+	/* Create the high 32 bit segment part */
+	high_desc  =  limit       & 0x000F0000;	/* set limit bits 19:16 */
+	high_desc |=  flag        & 0x00F0FF00;	/* set type, p, dpl, s, g, d/b, l and avl fields */
+	high_desc |= (base >> 16) & 0x000000FF;	/* set base bits 23:16 */
+	high_desc |=  base        & 0xFF000000;	/* set base bits 31:24 */
+
+	printf("\t.quad 0x%08"PRIx32"%08"PRIx32" /* 0x%02x %s */\n",
+	       high_desc, low_desc, offset(), comment);
+}
+
+int main(void)
+{
+	print_desc(0, 0x00000000, 0,           "null descriptor   ");
+	print_desc(0, 0x00000000, 0,           "unused            ");
+	print_desc(0, 0x000fffff, KERN_CODE32, "kernel code 32-bit");
+	print_desc(0, 0x000fffff, USER_CODE32, "user   code 32-bit");
+	print_desc(0, 0x000fffff, KERN_CODE64, "kernel code 64-bit");
+	print_desc(0, 0x000fffff, USER_CODE64, "user   code 64-bit");
+	print_desc(0, 0x000fffff, KERN_DATA,   "kernel data       ");
+	print_desc(0, 0x000fffff, USER_DATA,   "user   data       ");
+	/* the TSS bases are initialized dynamically in arch/x86/boot/setup{32,64}.S */
+	print_desc(0, 0x00000068, KERN_TSS,    "kernel TSS        ");
+	print_desc(0, 0x00000000, 0,           " .. pad for 64-bit");
+	print_desc(0, 0x00000068, USER_TSS,    "user   TSS        ");
+	print_desc(0, 0x00000000, 0,           " .. pad for 64-bit");
+
+	return 0;
+}