I am adding SMP to my kernel, in which the AP should boot. It starts in realmode and faults on entering protected mode. To be clear, it faults on the JMP 0x8:... after loading CR0. I am sure that the AP is getting its code, because looping anywhere in between prevents a fault. The copies the code area APBoot-APBootSequenceEnd to a physical memory location at 9*64KB. I have tried multiple ways to code it, giving it in the comments in the code -
; +============================================================================ =
; File: APBoot.asm
; =
; Summary: This file contains the code for initializing APs (application processors)
; on a SMP system.
;
; The code is copyed to 9*64*1024 before sending INIT-SIPI-SIPI
;
; Copyright (C) 2017 - Shukant Pal
;=============================================================================+
global APBoot
global apSetupInfo
global APBootSequenceStart
[bits 16]
SECTION .TEXT
ALIGN 4
APBoot: ; Page-aligned Booting File (copyed and filled by PROCESSOR_SETUP_INFO.BootManager)
XOR EAX, EAX
MOV AX, CS ; Load CS into AX
MOV DS, AX ; Copy CS into DS
CLI
MOV ES, AX ; Copy CS into ES
MOV GS, AX ; Copy CS into GS
MOV FS, AX ; Copy CS into FS
XOR EAX, EAX
MOV AX, CS
SHL EAX, 4
ADD EAX, defaultBootGDTPointer-APBoot
LGDT [EAX] ; Even LGDT [9*64*1024+defaultBootGDTPointer-APBoot] doesn't work (why?)
MOV EAX, CR0 ; Load CR0 into EDX
OR AL, 0x1 ; Set PM-bit in EDX
MOV CR0, EAX ; Enable Protected-Mode
;[bits 32]; Even if I turn this off, still triple-faults
JMP 0x8:(9*64*1024+InitSoftwareEnvironment-APBoot) ; Triple Fault
ALIGN 4
apSetupInfo: ; (ALIGNED) PROCESSOR_SETUP_INFO
apBootManager: DD 0x00000000 ; PROCESSOR_SETUP_INFO.BootManager
apBootAddress: DD 0x00000000 ; PROCESSOR_SETUP_INFO.BootAddress
apBootStack: DD 0x00000000 ; PROCESSOR_SETUP_INFO.BootStack
apStatus: DD 0x00000002 ; PROCESSOR_SETUP_INFO.StatusCounter
apErrorReg: DD 0xE0000000 ; PROCESSOR_SETUP_INFO.ErrorRegister (equ AP_NO_BOOT_ERR)
apErrorReg1: DD 0
apErrorReg2: DD 0
apErrorReg4: DD 0
defaultBootGDT: ; PROCESSOR_SETUP_INFO.DefaultBootGDT
defaultBootGDTStart:
DQ 0x0000000000000000 ; NULL GDT_ENTRY
; GDT_ENTRY - KernelCode
DW 0xFFFF ; KernelCode.Limit
DW 0x0000 ; KernelCode.BaseLow
DB 0x00 ; KernelCode.BaseMiddle
DB 0x9A ; KernelCode.Access
DB 0xCF ; KernelCode.Granularity
DB 0x00 ; KernelCode.BaseHigh
; GDT_ENTRY - KernelData
DW 0xFFFF ; KernelData.Limit
DW 0x0000 ; KernelData.BaseLow
DB 0x00 ; KernelData.BaseMiddle
DB 0x92 ; KernelData.Access
DB 0xCF ; KernelData.Granularity
DB 0x00 ; KernelCode.BaseHigh
DQ 0
DQ 0
defaultBootGDTEnd:
defaultBootGDTPointer: ; PROCESSOR_SETUP_INFO.DefaultBootGDTPointer
DW 23 ; defaultBootGDTPointer.Limit (loaded at Runtime)
DD (9*64*1024+defaultBootGDT-APBoot) ; defaultBootGDTPointer.Base (loaded at Runtime)
APBootSequenceStart:
ALIGN 4
[bits 32]
InitSoftwareEnvironment:
JMP $
MOV AX, 0x10
MOV DS, AX
MOV GS, AX
MOV ES, AX
MOV FS, AX
MOV SS, AX
; MOV EBX, 632 * 1024 + apStatus - APBoot
; MOV DWORD [EBX], 0x1
; MOV DWORD [0xB8000], 0xFFFFFFFF
JMP $
global APBootSequenceEnd
APBootSequenceEnd:
I have found the answer to my question. NASM assembler didn't warn me about the address overriding needed. The address (9*64*1024+InitSoftwareEnvironment) overflows the 16-bit data size. So, I need to use the address overriding option - by changing
to