So I'm working on a port from x86 to x86_64 (https://github.com/maxdev1/ghost/pull/48) and it all looks fine on single-core so far, but when starting up the AP I'm triple-faulting when trying to access some memory in kernel space.
I'm booting up with Limine and just passing on the initial page directory to the AP. My AP startup code is this:
Code: Select all
; Loaded by the kernel to this location
org 0x1000
; Real mode
BITS 16
startup:
; No interrupts & clear segments
cli
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
; Load the GDT
lgdt [gdtPointer]
; Enable protected mode
mov eax, cr0
or eax, 1
mov cr0, eax
; Far-JMP into protected mode code
jmp 0x8:protectedStart
; Protected mode
BITS 32
protectedStart:
; Code segments were set by far JMP, set data segments
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
; Lock all cores
acquireLock:
lock bts dword [interlock], 0
jc acquireLock
; Enable PAE and PGE
mov eax, cr4
or eax, (1 << 5) | (1 << 7)
mov cr4, eax
; Set page directory
mov eax, [0x500]
mov cr3, eax
; Set up EFER MSR to enable long mode (EFER.LME)
mov ecx, 0xC0000080
rdmsr
or eax, 1 << 8
wrmsr
; Enable paging
mov eax, cr0
or eax, 1 << 31
mov cr0, eax
; Get index of this AP and increment counter
mov eax, [0x510]
inc dword [0x510]
; Release lock
lock btr dword [interlock], 0
; Far-jump to 64 bits
jmp 0x18:longStart
; Long mode
[BITS 64]
longStart:
; 32-bit code provides AP index in EAX
; From the stack array, take the entry at offset multiplied by 8
shl rax, 3
mov rsp, [0x518 + rax]
mov rbp, rsp
; Set data segments
mov bx, 0x20
mov ds, bx
mov es, bx
mov fs, bx
mov gs, bx
mov ss, bx
; Jump into kernel code
mov rax, [0x508]
jmp rax
; Inter-core synchronization
interlock:
dd 0
; Basic setup GDT
gdt:
; null descriptor
dw 0x0000
dw 0x0000
dw 0x0000
dw 0x0000
; code descriptor
dw 0xFFFF
dw 0x0000
dw 0x9A00
dw 0x00CF
; data descriptor
dw 0xFFFF
dw 0x0000
dw 0x9200
dw 0x00CF
; 64-bit code descriptor
dw 0x0000
dw 0x0000
dw 0x9A00
dw 0x0020
; 64-bit data descriptor
dw 0x0000
dw 0x0000
dw 0x9200
dw 0x0000
gdtEnd:
align 4
gdtPointer:
dw gdtEnd - gdt - 1
dd gdt
I would say the values are read correctly on the AP - but it's faulting like this:
Code: Select all
rax=ffffffff80600004 rbx=0000000000000580 rcx=00000000c0000080 rdx=0000000000000000
rsi=0000000000000000 rdi=0000000000000000 r8 =0000000000000000 r9 =0000000000000000
r10=0000000000000000 r11=0000000000000000 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000 iopl=0 rf nv up di ng nz na pe nc
rip=ffffffff8020c77e rsp=ffffff809000ffe8 rbp=ffffff809000fff8
cs=0018 ds=0020 es=0020 fs=0020 gs=0020 ss=0020 rflags=4f6a368a00010082
%ffffffff8020c77e 8b 00 mov eax, dword [rax]
// ^ this goes wrong, an attempt to read from the faulty address below
cpu1.cr0=0xe0000011 // PE, ET, NW, CD, PG are set
cpu1.cr2=0xffffffff80600004 // faulty address
cpu1.cr3=0x00000000dff86000 // same phys address of PML4 that BSP uses
cpu1.cr4=0x000000a0 // PGE & PAE set
cpu1.efer=0x00000500 // LME & LMA set
Code: Select all
PML4[511] = 0x00000000dff85027 flags: PWU--A---
PDPT[510] = 0x00000000dff84027 flags: PWU--A---
PD[3] = 0x00000000dff80027 flags: PWU--A---
PT[0] = 0x80000000df735063 flags: PW---AD--

