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
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.