进入保护模式:三重故障

Entering Protected Mode: Triple-Fault

我正在将 SMP 添加到我的内核中,AP 应该在其中启动。它以实模式启动,并在进入保护模式时出错。需要明确的是,它在 JMP 0x8:... 加载 CR0 后出错。我确信 AP 正在获取它的代码,因为在两者之间的任何地方循环可以防止错误。将代码区域 APBoot-APBootSequenceEnd 复制到 9*64KB 的物理内存位置。我尝试了多种编码方式,在代码的注释中给出 -

 ;             +============================================================================ =
; 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:

我找到了问题的答案。 NASM 汇编程序没有警告我需要覆盖地址。地址(9*64*1024+InitSoftwareEnvironment)溢出16位数据大小。所以,我需要使用地址覆盖选项 - 通过更改

JMP 0x8:(9*64*1024+InitSoftwareEnvironment-APBoot)

JMP DWORD 0x8:(9*64*1024+InitSoftwareEnvironment-APBoot)