libhermit-rs 0.6.3

A Rust-based library operating system
Documentation
; This is the entry point for the application processors.
; It is loaded at 0x8000 by HermitCore and filled with parameters.
; It does the switch from Real Mode -> Protected Mode -> Long Mode,
; sets up CR3 for this CPU, and then calls into _start.
;
; In contrast to this self-contained entry point, _start is linked
; to the rest of HermitCore and thus has access to all exported symbols
; (like the actual Rust entry point).


CR0_PG       equ (1 << 31)
CR4_PAE      equ (1 << 5)
MSR_EFER     equ 0xC0000080
EFER_LME     equ (1 << 8)
EFER_NXE     equ (1 << 11)

[BITS 16]
SECTION .text
GLOBAL _start
ORG 0x8000
_start:
	jmp _rmstart

; PARAMETERS
align 8
	entry_point dq 0xDEADC0DE
	cpu_id dd 0xC0DECAFE
	boot_info dq 0xBEEFBEEF
	pml4 dd 0xDEADBEEF
	pad dd 0;

_rmstart:
	cli
	lgdt [gdtr]

	; switch to protected mode by setting PE bit
	mov eax, cr0
	or al, 0x1
	mov cr0, eax

	; far jump to the 32bit code
	jmp dword codesel : _pmstart

[BITS 32]
ALIGN 4
_pmstart:
	xor eax, eax
	mov ax, datasel
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov ss, ax

	jmp short stublet
	jmp $

; GDT for the protected mode
ALIGN 4
gdtr:                           ; descritor table
        dw gdt_end-gdt-1        ; limit
        dd gdt                  ; base address
gdt:
        dd 0,0                  ; null descriptor
codesel equ $-gdt
        dw 0xFFFF               ; segment size 0..15
        dw 0x0000               ; segment address 0..15
        db 0x00                 ; segment address 16..23
        db 0x9A                 ; access permissions und type
        db 0xCF                 ; additional information and segment size 16...19
        db 0x00                 ; segment address 24..31
datasel equ $-gdt
        dw 0xFFFF               ; segment size 0..15
        dw 0x0000               ; segment address 0..15
        db 0x00                 ; segment address 16..23
        db 0x92                 ; access permissions and type
        db 0xCF                 ; additional informationen and degment size 16...19
        db 0x00                 ; segment address 24..31
gdt_end:

ALIGN 4
GDTR64:
    dw GDT64_end - GDT64 - 1     ; Limit.
    dq GDT64                     ; Base.

; we need a new GDT to switch in the 64bit modus
GDT64:                           ; Global Descriptor Table (64-bit).
    .Null: equ $ - GDT64         ; The null descriptor.
    dw 0                         ; Limit (low).
    dw 0                         ; Base (low).
    db 0                         ; Base (middle)
    db 0                         ; Access.
    db 0                         ; Granularity.
    db 0                         ; Base (high).
    .Code: equ $ - GDT64         ; The code descriptor.
    dw 0                         ; Limit (low).
    dw 0                         ; Base (low).
    db 0                         ; Base (middle)
    db 10011010b                 ; Access.
    db 00100000b                 ; Granularity.
    db 0                         ; Base (high).
    .Data: equ $ - GDT64         ; The data descriptor.
    dw 0                         ; Limit (low).
    dw 0                         ; Base (low).
    db 0                         ; Base (middle)
    db 10010010b                 ; Access.
    db 00000000b                 ; Granularity.
    db 0                         ; Base (high).
GDT64_end:

ALIGN 4
stublet:
    ; Enable PAE mode.
    mov eax, cr4
    or eax, CR4_PAE
    mov cr4, eax

    ; Set the address to PML4 in CR3.
    mov eax, dword [pml4]
    mov cr3, eax

    ; Enable x86-64 Compatibility Mode by setting EFER_LME.
    ; Also enable early access to NO_EXECUTE-protected memory through EFER_NXE.
    mov ecx, MSR_EFER
    rdmsr
    or eax, EFER_LME | EFER_NXE
    wrmsr

    ; Enable Paging.
    mov eax, cr0
    or eax, CR0_PG
    mov cr0, eax

    ; Load the 64-bit global descriptor table.
    lgdt [GDTR64]
    mov ax, GDT64.Data
    mov ss, ax
    mov ds, ax
    mov es, ax

    ; Set the code segment and enter 64-bit long mode.
    jmp GDT64.Code:start64

[BITS 64]
ALIGN 8
start64:
    ; forward address to boot info
    mov rdi, qword [boot_info]
    mov esi, dword [cpu_id]
    ; Jump to _start
    jmp qword [entry_point]