reorganized 64bit paging initialization
This commit is contained in:
parent
403c529e8b
commit
3be25b99d2
1 changed files with 128 additions and 120 deletions
|
@ -88,11 +88,11 @@ SECTION .data
|
|||
; create default page tables for the 64bit kernel
|
||||
global boot_pml4
|
||||
ALIGN 4096 ; of course, the page tables have to be page aligned
|
||||
NOPTS equ 512
|
||||
MAP_ENTRIES equ 512
|
||||
boot_pml4 times 512 DQ 0
|
||||
boot_pdpt times 512 DQ 0
|
||||
boot_pd times 512 DQ 0
|
||||
boot_pt times (NOPTS*512) DQ 0
|
||||
boot_pt times (MAP_ENTRIES*512) DQ 0
|
||||
|
||||
SECTION .text
|
||||
ALIGN 8
|
||||
|
@ -101,17 +101,16 @@ global smp_entry
|
|||
smp_entry:
|
||||
; initialize cpu features
|
||||
call cpu_init
|
||||
|
||||
; initialize page table
|
||||
; initialize cr3 register
|
||||
mov edi, boot_pml4
|
||||
mov cr3, edi
|
||||
|
||||
; we need to enable PAE modus
|
||||
; enable PAE
|
||||
mov eax, cr4
|
||||
or eax, 1 << 5
|
||||
mov cr4, eax
|
||||
|
||||
; switch to the compatibility mode (which is part of long mode)
|
||||
; enable longmode (compatibility mode)
|
||||
mov ecx, 0xC0000080
|
||||
rdmsr
|
||||
or eax, 1 << 8
|
||||
|
@ -122,6 +121,7 @@ smp_entry:
|
|||
or eax, 1 << 31 | 1 << 0 ; Set the PG-bit, which is the 31nd bit, and the PE-bit, which is the 0th bit.
|
||||
mov cr0, eax ; According to the multiboot spec the PE-bit has to be set by bootloader already!
|
||||
|
||||
; jump to 64-bit longmode
|
||||
mov edi, [esp+4] ; set argumet for smp_start
|
||||
lgdt [GDT64.Pointer] ; Load the 64-bit global descriptor table.
|
||||
jmp GDT64.Code:smp_start64 ; Set the code segment and enter 64-bit long mode.
|
||||
|
@ -129,36 +129,89 @@ smp_entry:
|
|||
jmp $ ; endless loop
|
||||
%endif
|
||||
|
||||
search_apic:
|
||||
; search MP Floating Pointer Structure
|
||||
search_mps:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
push ecx
|
||||
|
||||
xor eax, eax
|
||||
mov ecx, [ebp+8]
|
||||
L1:
|
||||
.l1:
|
||||
cmp [ecx], DWORD 0x5f504d5f ; MP_FLT_SIGNATURE
|
||||
jne L2
|
||||
jne .l2
|
||||
mov al, BYTE [ecx+9]
|
||||
cmp eax, 4
|
||||
ja L2
|
||||
ja .l2
|
||||
mov al, BYTE [ecx+11]
|
||||
cmp eax, 0
|
||||
jne L2
|
||||
jne .l2
|
||||
mov eax, ecx
|
||||
jmp L3
|
||||
jmp .l3
|
||||
|
||||
L2:
|
||||
.l2:
|
||||
add ecx, 4
|
||||
cmp ecx, [ebp+12]
|
||||
jb L1
|
||||
jb .l1
|
||||
xor eax, eax
|
||||
|
||||
L3:
|
||||
.l3:
|
||||
pop ecx
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
check_longmode:
|
||||
; check for cpuid instruction
|
||||
pushfd
|
||||
pop eax
|
||||
mov ecx, eax
|
||||
xor eax, 1 << 21
|
||||
push eax
|
||||
popfd
|
||||
pushfd
|
||||
pop eax
|
||||
push ecx
|
||||
popfd
|
||||
xor eax, ecx
|
||||
jz .unsupported
|
||||
; check for extended cpu features (cpuid > 0x80000000)
|
||||
mov eax, 0x80000000
|
||||
cpuid
|
||||
cmp eax, 0x80000001
|
||||
jb .unsupported ; It is less, there is no long mode.
|
||||
; check if longmode is supported
|
||||
mov eax, 0x80000001
|
||||
cpuid
|
||||
test edx, 1 << 29 ; Test if the LM-bit, which is bit 29, is set in the D-register.
|
||||
jz .unsupported ; They aren't, there is no long mode.
|
||||
ret
|
||||
.unsupported:
|
||||
jmp $
|
||||
|
||||
check_lapic:
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
mov eax, 1
|
||||
cpuid
|
||||
and edx, 0x200
|
||||
cmp edx, 0
|
||||
je .unsupported
|
||||
; map lapic at 0xFEE00000 below the kernel
|
||||
mov edi, kernel_start - 0x1000
|
||||
shr edi, 9 ; (edi >> 12) * 8
|
||||
add edi, boot_pt
|
||||
mov ebx, 0xFEE00000 ; LAPIC base address
|
||||
or ebx, 0x00000013
|
||||
mov DWORD [edi], ebx
|
||||
.unsupported:
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
ret
|
||||
|
||||
cpu_init:
|
||||
mov eax, cr0
|
||||
; enable caching, disable paging and fpu emulation
|
||||
|
@ -182,112 +235,30 @@ stublet:
|
|||
push ebx
|
||||
; initialize cpu features
|
||||
call cpu_init
|
||||
; do we have the instruction cpuid?
|
||||
pushfd
|
||||
pop eax
|
||||
mov ecx, eax
|
||||
xor eax, 1 << 21
|
||||
push eax
|
||||
popfd
|
||||
pushfd
|
||||
pop eax
|
||||
push ecx
|
||||
popfd
|
||||
xor eax, ecx
|
||||
jz Linvalid
|
||||
; cpuid > 0x80000000?
|
||||
mov eax, 0x80000000
|
||||
cpuid
|
||||
cmp eax, 0x80000001
|
||||
jb Linvalid ; It is less, there is no long mode.
|
||||
; do we have a long mode?
|
||||
mov eax, 0x80000001
|
||||
cpuid
|
||||
test edx, 1 << 29 ; Test if the LM-bit, which is bit 29, is set in the D-register.
|
||||
jz Linvalid ; They aren't, there is no long mode.
|
||||
; check if longmode is supported
|
||||
call check_longmode
|
||||
; check if lapic is available
|
||||
call check_lapic
|
||||
|
||||
; initialize page table
|
||||
mov edi, boot_pml4
|
||||
mov cr3, edi
|
||||
|
||||
; So lets make PML4T[0] point to the PDPT and so on:
|
||||
mov DWORD [edi], boot_pdpt ; Set the double word at the destination index to pdpt.
|
||||
or DWORD [edi], 0x00000003 ; Set present and writeable bit
|
||||
mov edi, boot_pdpt
|
||||
mov DWORD [edi], boot_pd ; Set the double word at the destination index to pd.
|
||||
or DWORD [edi], 0x00000003 ; Set present and writeable bit
|
||||
mov edi, boot_pd
|
||||
mov ebx, boot_pt
|
||||
mov ecx, NOPTS
|
||||
L0:
|
||||
mov DWORD [edi], ebx ; Set the double word at the destination index to pt.
|
||||
or DWORD [edi], 0x00000003 ; Set present and writeable bit
|
||||
add edi, 8
|
||||
add ebx, 0x1000
|
||||
loop L0
|
||||
|
||||
%ifdef CONFIG_VGA
|
||||
; map the VGA address into the virtual address space
|
||||
mov edi, 0xB8000
|
||||
shr edi, 9 ; (edi >> 12) * 8
|
||||
add edi, boot_pt
|
||||
mov ebx, 0xB8000
|
||||
or ebx, 0x00000013
|
||||
mov DWORD [edi], ebx
|
||||
%endif
|
||||
|
||||
; map multiboot structure into the virtual address space
|
||||
mov edi, [esp]
|
||||
and edi, 0xFFFFF000
|
||||
shr edi, 9 ; (edi >> 12) * 8
|
||||
add edi, boot_pt
|
||||
mov ebx, [esp]
|
||||
and ebx, 0xFFFFF000
|
||||
or ebx, 0x00000003
|
||||
mov DWORD [edi], ebx
|
||||
|
||||
; check if lapic is available
|
||||
push eax
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
mov eax, 1
|
||||
cpuid
|
||||
and edx, 0x200
|
||||
cmp edx, 0
|
||||
je no_lapic
|
||||
; map lapic at 0xFEE00000 below the kernel
|
||||
mov edi, kernel_start - 0x1000
|
||||
shr edi, 9 ; (edi >> 12) * 8
|
||||
add edi, boot_pt
|
||||
mov ebx, 0xFEE00000
|
||||
or ebx, 0x00000013
|
||||
mov DWORD [edi], ebx
|
||||
no_lapic:
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
|
||||
; search APIC
|
||||
; find MP Floating Pointer Structure
|
||||
push DWORD 0x100000
|
||||
push DWORD 0xF0000
|
||||
call search_apic
|
||||
call search_mps
|
||||
add esp, 8
|
||||
|
||||
cmp eax, 0
|
||||
jne La
|
||||
jne map_mps
|
||||
|
||||
push DWORD 0xA0000
|
||||
push DWORD 0x9F000
|
||||
call search_apic
|
||||
call search_mps
|
||||
add esp, 8
|
||||
|
||||
cmp eax, 0
|
||||
je Lb
|
||||
|
||||
La:
|
||||
; map MP Floating Pointer Structure
|
||||
cmp eax, 0
|
||||
je map_kernel
|
||||
|
||||
map_mps:
|
||||
; map MP Floating Pointer Structure
|
||||
mov DWORD [apic_mp], eax
|
||||
mov edi, eax
|
||||
and edi, 0xFFFFF000
|
||||
|
@ -298,7 +269,7 @@ La:
|
|||
or ebx, 0x00000013
|
||||
mov DWORD [edi], ebx
|
||||
|
||||
; map mp_config
|
||||
; map mp_config
|
||||
mov edi, [eax+4]
|
||||
and edi, 0xFFFFF000
|
||||
shr edi, 9 ; (edi >> 12) * 8
|
||||
|
@ -308,7 +279,27 @@ La:
|
|||
or ebx, 0x00000013
|
||||
mov DWORD [edi], ebx
|
||||
|
||||
Lb:
|
||||
%ifdef CONFIG_VGA
|
||||
map_vga:
|
||||
mov edi, 0xB8000
|
||||
shr edi, 9 ; (edi >> 12) * 8
|
||||
add edi, boot_pt
|
||||
mov ebx, 0xB8000
|
||||
or ebx, 0x00000013
|
||||
mov DWORD [edi], ebx
|
||||
%endif
|
||||
|
||||
map_multiboot:
|
||||
mov edi, [esp]
|
||||
and edi, 0xFFFFF000
|
||||
shr edi, 9 ; (edi >> 12) * 8
|
||||
add edi, boot_pt
|
||||
mov ebx, [esp]
|
||||
and ebx, 0xFFFFF000
|
||||
or ebx, 0x00000003
|
||||
mov DWORD [edi], ebx
|
||||
|
||||
map_kernel:
|
||||
mov edi, kernel_start
|
||||
shr edi, 9 ; (kernel_start >> 12) * 8
|
||||
add edi, boot_pt
|
||||
|
@ -319,18 +310,37 @@ Lb:
|
|||
shr ecx, 12
|
||||
inc ecx
|
||||
|
||||
Lc:
|
||||
mov DWORD [edi], ebx ; Set the double word at the destination index to the B-register.
|
||||
.l1:
|
||||
mov DWORD [edi], ebx ; Set the double word at the destination index to the B-register.
|
||||
add edi, 8
|
||||
add ebx, 0x1000
|
||||
loop Lc
|
||||
loop .l1
|
||||
|
||||
; we need to enable PAE modus
|
||||
init_paging:
|
||||
mov edi, boot_pml4
|
||||
mov cr3, edi
|
||||
; So lets make PML4T[0] point to the PDPT and so on:
|
||||
mov DWORD [edi], boot_pdpt ; Set the double word at the destination index to pdpt.
|
||||
or DWORD [edi], 0x00000003 ; Set present and writeable bit
|
||||
mov edi, boot_pdpt
|
||||
mov DWORD [edi], boot_pd ; Set the double word at the destination index to pd.
|
||||
or DWORD [edi], 0x00000003 ; Set present and writeable bit
|
||||
mov edi, boot_pd
|
||||
mov ebx, boot_pt
|
||||
mov ecx, MAP_ENTRIES
|
||||
.l1:
|
||||
mov DWORD [edi], ebx ; Set the double word at the destination index to pt.
|
||||
or DWORD [edi], 0x00000003 ; Set present and writeable bit
|
||||
add edi, 8
|
||||
add ebx, 0x1000
|
||||
loop .l1
|
||||
|
||||
; enable PAE
|
||||
mov eax, cr4
|
||||
or eax, 1 << 5
|
||||
mov cr4, eax
|
||||
|
||||
; switch to the compatibility mode (which is part of long mode)
|
||||
; enable longmode (compatibility mode)
|
||||
mov ecx, 0xC0000080
|
||||
rdmsr
|
||||
or eax, 1 << 8
|
||||
|
@ -341,13 +351,11 @@ Lc:
|
|||
or eax, 1 << 31 | 1 << 0 ; Set the PG-bit, which is the 31nd bit, and the PE-bit, which is the 0th bit.
|
||||
mov cr0, eax
|
||||
|
||||
; jump to 64-bit longmode
|
||||
pop ebx ; restore pointer to multiboot structure
|
||||
lgdt [GDT64.Pointer] ; Load the 64-bit global descriptor table.
|
||||
jmp GDT64.Code:start64 ; Set the code segment and enter 64-bit long mode.
|
||||
|
||||
Linvalid:
|
||||
jmp $
|
||||
|
||||
[BITS 64]
|
||||
start64:
|
||||
; initialize segment registers
|
||||
|
|
Loading…
Add table
Reference in a new issue