reorganized 64bit paging initialization

This commit is contained in:
Steffen Vogel 2013-10-17 11:36:02 +02:00
parent 403c529e8b
commit 3be25b99d2

View file

@ -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