From e9628f3739afa9edc15fe276df893f031cf6ca0d Mon Sep 17 00:00:00 2001
From: Amelia Coutard <eliottulio.coutard@gmail.com>
Date: Thu, 28 Apr 2022 00:30:35 +0200
Subject: [PATCH] Made a proper GDT.

---
 src/boot.S | 107 ++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 74 insertions(+), 33 deletions(-)

diff --git a/src/boot.S b/src/boot.S
index 26a779c..98217be 100644
--- a/src/boot.S
+++ b/src/boot.S
@@ -17,38 +17,65 @@ multiboot_header_start:
 multiboot_header_end:
 
 .section .data
-.set PRESENT, 1 << 7
-.set NOT_SYS, 1 << 4
-.set EXEC, 1 << 3
-.set DC, 1 << 2
-.set RW, 1 << 1
-.set ACCESSED, 1 << 0
- 
-.set GRAN_4K, 1 << 7
-.set SZ_32, 1 << 6
-.set LONG_MODE, 1 << 5
- 
 GDT:
-    .set GDT.NULL, . - GDT
-        .quad 0
-    .set GDT.CODE, . - GDT
-        .int 0xFFFF                            # Limit & Base (low, bits 0-15)
-        .byte 0                                # Base (mid, bits 16-23)
-        .byte PRESENT | NOT_SYS | EXEC | RW    # Access
-        .byte GRAN_4K | LONG_MODE | 0xF        # Flags & Limit (high, bits 16-19)
-        .byte 0                                # Base (high, bits 24-31)
-    .set GDT.DATA, . - GDT
-        .int 0xFFFF                            # Limit & Base (low, bits 0-15)
-        .byte 0                                # Base (mid, bits 16-23)
-        .byte PRESENT | NOT_SYS | RW           # Access
-        .byte GRAN_4K | SZ_32 | 0xF            # Flags & Limit (high, bits 16-19)
-        .byte 0                                # Base (high, bits 24-31)
-    .set GDT.TSS, . - GDT
-        .int 0x00000068
-        .int 0x00CF8900
-    GDT.PTR:
-        .short . - GDT - 1
-        .quad GDT - KERNEL_VMA
+.set GDT.NULL, . - GDT
+	.quad 0
+.set GDT.KERNEL_CODE, . - GDT
+	.short 0xFFFF # Limit[0:16]
+	.short 0x0000 # Base[0:16]
+	.byte 0x00 # Base[16:24]
+	.byte 0b10011010 # Access: present | readable | ring0
+	.byte 0b10101111 # Flags: page_gran | long_mode, Limit[16:20]
+	.byte 0x00 # Base[24:32]
+.set GDT.KERNEL_DATA, . - GDT
+	.short 0xFFFF # Limit[0:16]
+	.short 0x0000 # Base[0:16]
+	.byte 0x00 # Base[16:24]
+	.byte 0b10010010 # Access: present | writeable | ring0
+	.byte 0b11001111 # Flags: page_gran | d_b, Limit[16:20]
+	.byte 0x00 # Base[24:32]
+.set GDT.USER_CODE, . - GDT
+	.short 0xFFFF # Limit[0:16]
+	.short 0x0000 # Base[0:16]
+	.byte 0x00 # Base[16:24]
+	.byte 0b11111010 # Access: present | readable | ring3
+	.byte 0b10101111 # Flags: page_gran | long_mode, Limit[16:20]
+	.byte 0x00 # Base[24:32]
+.set GDT.USER_DATA, . - GDT
+	.short 0xFFFF # Limit[0:16]
+	.short 0x0000 # Base[0:16]
+	.byte 0x00 # Base[16:24]
+	.byte 0b11110010 # Access: present | writeable | ring3
+	.byte 0b11001111 # Flags: page_gran | d_b, Limit[16:20]
+	.byte 0x00 # Base[24:32]
+.set GDT.TSS, . - GDT
+	.short TSS_SIZE & 0xFFFF # Limit[0:16]
+	.short 0x0000 # Base[0:16] # TSS & 0xFFFF
+	.byte 0x00 # Base[16:24] # (TSS >> 16) & 0xFF
+	.byte 0b10001001 # Access
+	.byte (0b0000 << 4) | ((TSS_SIZE >> 16) & 0xF) # Flags, Limit[16:20]
+	.byte 0x00 # Base[24:32] # (TSS >> 24) & 0xFF
+GDT.PTR:
+	.short . - GDT - 1
+	.quad GDT - KERNEL_VMA
+
+TSS:
+	.skip 4
+	RSP0: .quad 0
+	RSP1: .quad 0
+	RSP2: .quad 0
+	.skip 8
+	IST1: .quad 0
+	IST2: .quad 0
+	IST3: .quad 0
+	IST4: .quad 0
+	IST5: .quad 0
+	IST6: .quad 0
+	IST7: .quad 0
+	.skip 10
+	IOPB: .short 0
+TSS_END:
+.set TSS_SIZE, TSS_END - TSS
 
 .section .bss
 .align 0x1000
@@ -164,14 +191,28 @@ _start:
 	or $1 << 31, %eax
 	mov %eax, %cr0
 
+	# Setup TSS address in GDT
+	mov $TSS - KERNEL_VMA, %eax
+	shr $0, %eax
+	and $0xFFFF, %eax
+	mov %ax, GDT.TSS + GDT - KERNEL_VMA + 2
+	mov $TSS - KERNEL_VMA, %eax
+	shr $16, %eax
+	and $0xFF, %eax
+	mov %al, GDT.TSS + GDT - KERNEL_VMA + 4
+	mov $TSS - KERNEL_VMA, %eax
+	shr $24, %eax
+	and $0xFF, %eax
+	mov %al, GDT.TSS + GDT - KERNEL_VMA + 7
+
 	# Jump to 64 bits:
 	lgdt (GDT.PTR - KERNEL_VMA)
-	jmp $GDT.CODE, $.trampoline
+	jmp $GDT.KERNEL_CODE, $.trampoline
 
 .code64
 .trampoline:
 	mov %esp, %esp
-	mov $GDT.DATA, %ax  # Set the A-register to the data descriptor.
+	mov $GDT.KERNEL_DATA, %ax  # Set the A-register to the data descriptor.
 	mov %ax, %ds        # Set the data segment to the A-register.
 	mov %ax, %es        # Set the extra segment to the A-register.
 	mov %ax, %fs        # Set the F-segment to the A-register.
-- 
2.46.0