However, when I try to call kernel_main I get a triple fault (as no IDT is in place at the moment, and everything prior to seems okay) with the following from Bochs:
00150944080e[CPU0 ] interrupt(long mode): vector must be within IDT table limits, IDT.limit = 0x0
00150944080e[CPU0 ] interrupt(long mode): vector must be within IDT table limits, IDT.limit = 0x0
00150944080i[CPU0 ] CPU is in long mode (active)
00150944080i[CPU0 ] CS.mode = 64 bit
00150944080i[CPU0 ] SS.mode = 64 bit
00150944080i[CPU0 ] EFER = 0x00000500
00150944080i[CPU0 ] | RAX=000000b8e5894855 RBX=0000000000010000
00150944080i[CPU0 ] | RCX=00000000c0000080 RDX=0000000000000000
00150944080i[CPU0 ] | RSP=000000000007fef8 RBP=0000000000000000
00150944080i[CPU0 ] | RSI=0000000000000000 RDI=0000000000000000
00150944080i[CPU0 ] | R8=0000000000000000 R9=0000000000000000
00150944080i[CPU0 ] | R10=0000000000000000 R11=0000000000000000
00150944080i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
00150944080i[CPU0 ] | R14=0000000000000000 R15=0000000000000000
00150944080i[CPU0 ] | IOPL=0 ID vip vif ac vm RF nt of df if tf SF zf af PF cf
00150944080i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00150944080i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 00000000 0 0
00150944080i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 00000000 0 0
00150944080i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 00000000 0 0
00150944080i[CPU0 ] | ES:0010( 0002| 0| 0) 00000000 00000000 0 0
00150944080i[CPU0 ] | FS:0018( 0003| 0| 0) 00000000 ffffffff 1 1
00150944080i[CPU0 ] | GS:0018( 0003| 0| 0) 00000000 ffffffff 1 1
00150944080i[CPU0 ] | MSR_FS_BASE:0000000000000000
00150944080i[CPU0 ] | MSR_GS_BASE:0000000000000000
00150944080i[CPU0 ] | RIP=000000b8e5894855 (000000b8e5894855)
00150944080i[CPU0 ] | CR0=0xe0000011 CR2=0x000000b8e5894855
00150944080i[CPU0 ] | CR3=0x00101000 CR4=0x00000020
00150944080e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
00150944080i[SYS ] bx_pc_system_c::Reset(HARDWARE) called
00150944080i[CPU0 ] cpu hardware reset
00150944080i[APIC0 ] allocate APIC id=0 (MMIO enabled) to 0x0000fee00000
My bootstrap code:
Code: Select all
[BITS 32]
MBALIGN equ 1<<0 ; align loaded modules on page boundaries
MEMINFO equ 1<<1 ; provide memory map
FLAGS equ MBALIGN | MEMINFO ; this is the Multiboot 'flag' field
MAGIC equ 0x1BADB002 ; 'magic number' lets bootloader find the header
CHECKSUM equ -(MAGIC + FLAGS) ; checksum of above, to prove we are multiboot
; Multiboot Header
section .multiboot
align 4
dd MAGIC
dd FLAGS
dd CHECKSUM
section .bootstrap
global entry32
entry32:
; With all that multiboot stuff out of the way...
; It's time to do some 32-bit -> 64-bit stuff
; Paging Structures (4 KiB pages, PAE)
align 4096
pml4_table:
times 4096 db 0
pdpt1_table:
times 4096 db 0
pd1_table:
times 4096 db 0
pt1_table:
times 4096 db 0
pdpt2_table:
times 4096 db 0
pd2_table:
times 4096 db 0
pt2_table:
times 4096 db 0
; Setup Identity Mapping
mov eax, pdpt1_table
or eax, 0b11 ; present + writable
mov [pml4_table], eax
mov eax, pd1_table
or eax, 0b11 ; present + writable
mov [pdpt1_table], eax
mov eax, pt1_table
or eax, 0b11 ; present + writable
mov [pd1_table], eax
mov ecx, 0
.map_pt1_table:
mov eax, 0x1000
mul ecx
or eax, 0b11 ; present + writable
mov [pt1_table + ecx * 8], eax
inc ecx
cmp ecx, 512
jne .map_pt1_table
; Map 0xffff800000000000 -> 0x0000000000000000
mov eax, pdpt2_table
or eax, 0b11 ; present + writable
mov [pml4_table + 256 * 8], eax
mov eax, pd2_table
or eax, 0b11 ; present + writable
mov [pdpt2_table], eax
mov eax, pt2_table
or eax, 0b11 ; present + writable
mov [pd2_table], eax
mov ecx, 0
.map_pt2_table:
mov eax, 0x1000
mul ecx
or eax, 0b11 ; present + writable
mov [pt2_table + ecx * 8], eax
inc ecx
cmp ecx, 512
jne .map_pt2_table
; Enable Paging
enable_paging:
mov eax, pml4_table
mov cr3, eax
; Set PAE bit
mov eax, cr4
or eax, 1 << 5
mov cr4, eax
; Set Long Mode Bit
mov ecx, 0xC0000080
rdmsr
or eax, 1 << 8
wrmsr
mov eax, cr0
or eax, 1 << 31
mov cr0, eax
; 64-bit GDT
; Load GDT
lgdt [gdt64.ptr]
jmp gdt64.code:entry64
gdt64:
dq 0 ; zero entry
.code: equ $ - gdt64 ; new
dq (1<<44) | (1<<47) | (1<<41) | (1<<43) | (1<<53) ; code segment
.data: equ $ - gdt64 ; new
dq (1<<44) | (1<<47) | (1<<41) ; data segment
.ptr:
dw $ - gdt64 - 1
dq gdt64
[BITS 64]
entry64:
mov ax, gdt64.data
mov ss, ax
mov ds, ax
mov es, ax
mov rsp, stack_top
extern kernel_main
mov rax, [qword kernel_main]
jmp rax
cli
hlt
; Stack
section .my_stack, nobits
align 4
stack_bottom:
resb 16384
stack_top:
Code: Select all
ENTRY(entry32)
SECTIONS
{
. = 1M;
KERNEL_VMA = 0xffff800000000000;
.multiboot ALIGN(4K):
{
*(.multiboot)
}
.bootstrap ALIGN(4K):
{
arch/x86_64/boot/entry32.o (.text)
}
. += KERNEL_VMA;
.text ALIGN(4K): AT(ADDR(.text) - KERNEL_VMA)
{
*(EXCLUDE_FILE(*arch/x86_64/boot/entry64.o) .text)
*(.rodata*)
}
.data ALIGN(4K): AT(ADDR(.data) - KERNEL_VMA)
{
*(.data)
}
.bss ALIGN(4K): AT(ADDR(.bss) - KERNEL_VMA)
{
*(COMMON)
*(.bss)
*(.my_stack)
}
.eh_frame ALIGN(4K): AT(ADDR(.eh_frame) - KERNEL_VMA)
{
*(.eh_frame)
}
}