Protected Mode Not Enabled

I am developing a custom bootloader for my 64-bit OS in x86_64 NASM on macOS aarch64 (yup, LLDB is only available to me) environment using QEMU. The bootloader is a 2-stage.

Current Behavior

  • Prints ‘Jumped to stage 2’
  • Enable A20 (which seems to be right)
  • The bootloader is frozen after A20 and/or between loading kernel to KERNEL_OFFSET_LOW which equals 0x100000

Relevant Code

;
; By alpluspluss 09/22/2024 AD
;
; second stage bootloader
; for x86_64

[BITS 16]
[ORG 0x7E00]

section .rodata
KERNEL_OFFSET_HIGH equ 0xFFFF_FFFF_8000_0000
KERNEL_OFFSET_LOW equ 0x100000

section .text
start:
    ; set up segments & stack at 0x9000
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, 0x9000

    ; print 'Jumped to stage 2'
    mov si, stage2Message
    call print_16bit

    mov dl, [bootDrive]

    call enable_A20                 ; enable A20 for mem access beyond 1 MB
    call load_kernel                ; load the rest of stage 2 and kernel
    call enable_protected_mode      ; load GDT and switch to protected mode

; @NOTE: this part is basically 'load_loop' from stage 1
; but has some extras & some stuff removed
load_kernel:
    mov ah, 0x02            ; BIOS read sector function
    mov al, 6               ; read 6 sectors / time
    mov ch, 0               ; cylinder number
    mov cl, 5               ; start from sector 5
    mov dh, 0               ; Head number
    mov bx, KERNEL_OFFSET_LOW
    int 0x13                ; read disk op
    jc disk_error           ; jump if disk error
    ret

enable_A20:
    in al, 0x92
    or al, 2
    out 0x92, al
    ret

enable_protected_mode:
    cli                             ; disable interrupt
    lgdt [gdt_descriptor]           ; load GDT descriptor

    ; init protected mode
    mov eax, cr0
    or eax, 1                       ; set PE bit
    mov cr0, eax

    jmp 0x08:protected_mode_entry   ; jump to segment 0x08

[BITS 32]
protected_mode_entry:
    ; setup segments
    mov ax, 0x10                    ; segment selector
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax

    ; set up stack at 0x200000
    mov esp, 0x200000

    ; say 'Entered protected mode'
    mov esi, protectedModeMessage
    call print_protected_mode

    ; setup paging for long mode
    call setup_paging

    lgdt [gdt64_descriptor]         ; load GDT descriptor in 64-bit

    call enable_long_mode
    jmp 0x08:long_mode_entry        ; jump to segment 0x08 at offset long_mode_entry

setup_paging:
    mov edi, 0x1000                 ; assuming they are 4KB aligned
    xor eax, eax
    mov ecx, 5 * 4096 / 4           ; number of 4 KB entries
    rep stosd                       ; zero page dir and tables

    ; *IMPORTANT*
    ; @NOTE: page fault can happen here
    ; Identity map first 2MB
    ; Map 0x0000000000000000-0x00000000001fffff
    ; to physical 0x00000000-0x001fffff
    mov dword [0x1000], 0x00002003  ; PML4[0] = 0x2000 | PRESENT | READWRITE
    mov dword [0x2000], 0x00003003  ; PDP[0]  = 0x3000 | PRESENT | READWRITE
    mov dword [0x3000], 0x00000083  ; PD[0]   = 0x0000 | PRESENT | READWRITE | 2MB_PAGE

    ; Map 0xFFFFFFFF80000000-0xffffffff801fffff
    ; to physical 0x00000000-0x001fffff
    mov dword [0x1000 + 8 * ((KERNEL_OFFSET_HIGH >> 39) & 0x1ff)], 0x00004003    ; PML4[511] = 0x4000 | PRESENT | READWRITE
    mov dword [0x4000 + 8 * ((KERNEL_OFFSET_HIGH >> 30) & 0x1ff)], 0x00005003    ; PDP[510]  = 0x5000 | PRESENT | READWRITE
    mov dword [0x5000 + 8 * ((KERNEL_OFFSET_HIGH >> 21) & 0x1ff)], 0x00000083    ; PD[0]     = 0x0000 | PRESENT | READWRITE | 2MB_PAGE

    mov edi, 0x1000
    mov cr3, edi                    ; load page dir base into cr3 to set PDBR
    ret

enable_long_mode:
    mov ecx, 0xC0000080
    rdmsr
    or eax, 1 << 8
    wrmsr

    mov eax, 10100000b
    mov cr4, eax

    ; enable PAE and PGE bits in CR0
    mov eax, cr0
    or eax, 1 << 32                 ; enable paging
    mov cr0, eax
    ret

[BITS 64]
long_mode_entry:
    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax

    ; setup stack for kernel higher half
    mov rsp, 0x90000 + KERNEL_OFFSET_HIGH

    ; print 'Reached long mode'
    mov rsi, longModeMessage
    call print_long_mode

    mov rax, KERNEL_OFFSET_HIGH + KERNEL_OFFSET_LOW
    jmp rax

[BITS 16]
print_16bit:
    lodsb
    or al, al
    jz .done
    mov ah, 0x0E
    int 0x10
    jmp print_16bit
.done:
    ret

[BITS 32]
print_protected_mode:
    push eax
    push ebx
    mov ebx, 0xB8000                ; VGA mem address
.loop:
    lodsb
    or al, al
    jz .done
    mov ah, 0x0F
    mov [ebx], ax
    add ebx, 2
    jmp .loop
.done:
    pop ebx
    pop eax
    ret

[BITS 64]
print_long_mode:
    push rax
    push rbx
    mov rbx, 0xB8000                ; VGA mem address
.loop:
    lodsb
    or al, al
    jz .done
    mov ah, 0x0F
    mov [rbx], ax
    add rbx, 2
    jmp .loop
.done:
    pop rbx
    pop rax
    ret

[BITS 16]
disk_error:
    mov si, diskErrorMessage
    call print_16bit
    cli
    hlt

section .data

bootDrive db 0
stage2Message db 'Jumped to stage 2', 13, 10, 0
diskErrorMessage db 'Disk error in stage 2', 13, 10, 0
longModeMessage db 'Entered long mode', 0
protectedModeMessage db 'Entered protected mode', 0

section .rodata
align 16
gdt_start:
    dq 0x0000000000000000           ; null descriptor
    dq 0x00CF9A000000FFFF           ; 32-bit code descriptor
    dq 0x00CF92000000FFFF           ; 32-bit data descriptor
gdt_end:

gdt_descriptor:
    dw gdt_end - gdt_start - 1
    dd gdt_start

gdt64_start:
    dq 0x0000000000000000           ; null descriptor
    dq 0x00AF9A000000FFFF           ; 64-bit code descriptor
    dq 0x00AF92000000FFFF           ; 64-bit data descriptor
gdt64_end:

gdt64_descriptor:
    dw gdt64_end - gdt64_start - 1
    dq gdt64_start

section .bss
align 16
stack_bottom:
    resb 16384
stack_top:

section .text
times 512 * 3 - ($ - $$) db 0       ; pad to 3 sectors

After debugging, it seems that enabled mode is not working due to:

  • Kernel not loading [Likely]
  • Invalid GDT Descriptor

You can visit the GitHub repository for more details & source code.

New contributor

typeAl_ is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật