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
|
; create default page tables for the 64bit kernel
|
||||||
global boot_pml4
|
global boot_pml4
|
||||||
ALIGN 4096 ; of course, the page tables have to be page aligned
|
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_pml4 times 512 DQ 0
|
||||||
boot_pdpt times 512 DQ 0
|
boot_pdpt times 512 DQ 0
|
||||||
boot_pd 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
|
SECTION .text
|
||||||
ALIGN 8
|
ALIGN 8
|
||||||
|
@ -101,17 +101,16 @@ global smp_entry
|
||||||
smp_entry:
|
smp_entry:
|
||||||
; initialize cpu features
|
; initialize cpu features
|
||||||
call cpu_init
|
call cpu_init
|
||||||
|
; initialize cr3 register
|
||||||
; initialize page table
|
|
||||||
mov edi, boot_pml4
|
mov edi, boot_pml4
|
||||||
mov cr3, edi
|
mov cr3, edi
|
||||||
|
|
||||||
; we need to enable PAE modus
|
; enable PAE
|
||||||
mov eax, cr4
|
mov eax, cr4
|
||||||
or eax, 1 << 5
|
or eax, 1 << 5
|
||||||
mov cr4, eax
|
mov cr4, eax
|
||||||
|
|
||||||
; switch to the compatibility mode (which is part of long mode)
|
; enable longmode (compatibility mode)
|
||||||
mov ecx, 0xC0000080
|
mov ecx, 0xC0000080
|
||||||
rdmsr
|
rdmsr
|
||||||
or eax, 1 << 8
|
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.
|
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!
|
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
|
mov edi, [esp+4] ; set argumet for smp_start
|
||||||
lgdt [GDT64.Pointer] ; Load the 64-bit global descriptor table.
|
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.
|
jmp GDT64.Code:smp_start64 ; Set the code segment and enter 64-bit long mode.
|
||||||
|
@ -129,36 +129,89 @@ smp_entry:
|
||||||
jmp $ ; endless loop
|
jmp $ ; endless loop
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
search_apic:
|
; search MP Floating Pointer Structure
|
||||||
|
search_mps:
|
||||||
push ebp
|
push ebp
|
||||||
mov ebp, esp
|
mov ebp, esp
|
||||||
push ecx
|
push ecx
|
||||||
|
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
mov ecx, [ebp+8]
|
mov ecx, [ebp+8]
|
||||||
L1:
|
.l1:
|
||||||
cmp [ecx], DWORD 0x5f504d5f ; MP_FLT_SIGNATURE
|
cmp [ecx], DWORD 0x5f504d5f ; MP_FLT_SIGNATURE
|
||||||
jne L2
|
jne .l2
|
||||||
mov al, BYTE [ecx+9]
|
mov al, BYTE [ecx+9]
|
||||||
cmp eax, 4
|
cmp eax, 4
|
||||||
ja L2
|
ja .l2
|
||||||
mov al, BYTE [ecx+11]
|
mov al, BYTE [ecx+11]
|
||||||
cmp eax, 0
|
cmp eax, 0
|
||||||
jne L2
|
jne .l2
|
||||||
mov eax, ecx
|
mov eax, ecx
|
||||||
jmp L3
|
jmp .l3
|
||||||
|
|
||||||
L2:
|
.l2:
|
||||||
add ecx, 4
|
add ecx, 4
|
||||||
cmp ecx, [ebp+12]
|
cmp ecx, [ebp+12]
|
||||||
jb L1
|
jb .l1
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
|
|
||||||
L3:
|
.l3:
|
||||||
pop ecx
|
pop ecx
|
||||||
pop ebp
|
pop ebp
|
||||||
ret
|
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:
|
cpu_init:
|
||||||
mov eax, cr0
|
mov eax, cr0
|
||||||
; enable caching, disable paging and fpu emulation
|
; enable caching, disable paging and fpu emulation
|
||||||
|
@ -182,112 +235,30 @@ stublet:
|
||||||
push ebx
|
push ebx
|
||||||
; initialize cpu features
|
; initialize cpu features
|
||||||
call cpu_init
|
call cpu_init
|
||||||
; do we have the instruction cpuid?
|
; check if longmode is supported
|
||||||
pushfd
|
call check_longmode
|
||||||
pop eax
|
; check if lapic is available
|
||||||
mov ecx, eax
|
call check_lapic
|
||||||
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.
|
|
||||||
|
|
||||||
; initialize page table
|
; find MP Floating Pointer Structure
|
||||||
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
|
|
||||||
push DWORD 0x100000
|
push DWORD 0x100000
|
||||||
push DWORD 0xF0000
|
push DWORD 0xF0000
|
||||||
call search_apic
|
call search_mps
|
||||||
add esp, 8
|
add esp, 8
|
||||||
|
|
||||||
cmp eax, 0
|
cmp eax, 0
|
||||||
jne La
|
jne map_mps
|
||||||
|
|
||||||
push DWORD 0xA0000
|
push DWORD 0xA0000
|
||||||
push DWORD 0x9F000
|
push DWORD 0x9F000
|
||||||
call search_apic
|
call search_mps
|
||||||
add esp, 8
|
add esp, 8
|
||||||
|
|
||||||
cmp eax, 0
|
|
||||||
je Lb
|
|
||||||
|
|
||||||
La:
|
cmp eax, 0
|
||||||
; map MP Floating Pointer Structure
|
je map_kernel
|
||||||
|
|
||||||
|
map_mps:
|
||||||
|
; map MP Floating Pointer Structure
|
||||||
mov DWORD [apic_mp], eax
|
mov DWORD [apic_mp], eax
|
||||||
mov edi, eax
|
mov edi, eax
|
||||||
and edi, 0xFFFFF000
|
and edi, 0xFFFFF000
|
||||||
|
@ -298,7 +269,7 @@ La:
|
||||||
or ebx, 0x00000013
|
or ebx, 0x00000013
|
||||||
mov DWORD [edi], ebx
|
mov DWORD [edi], ebx
|
||||||
|
|
||||||
; map mp_config
|
; map mp_config
|
||||||
mov edi, [eax+4]
|
mov edi, [eax+4]
|
||||||
and edi, 0xFFFFF000
|
and edi, 0xFFFFF000
|
||||||
shr edi, 9 ; (edi >> 12) * 8
|
shr edi, 9 ; (edi >> 12) * 8
|
||||||
|
@ -308,7 +279,27 @@ La:
|
||||||
or ebx, 0x00000013
|
or ebx, 0x00000013
|
||||||
mov DWORD [edi], ebx
|
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
|
mov edi, kernel_start
|
||||||
shr edi, 9 ; (kernel_start >> 12) * 8
|
shr edi, 9 ; (kernel_start >> 12) * 8
|
||||||
add edi, boot_pt
|
add edi, boot_pt
|
||||||
|
@ -319,18 +310,37 @@ Lb:
|
||||||
shr ecx, 12
|
shr ecx, 12
|
||||||
inc ecx
|
inc ecx
|
||||||
|
|
||||||
Lc:
|
.l1:
|
||||||
mov DWORD [edi], ebx ; Set the double word at the destination index to the B-register.
|
mov DWORD [edi], ebx ; Set the double word at the destination index to the B-register.
|
||||||
add edi, 8
|
add edi, 8
|
||||||
add ebx, 0x1000
|
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
|
mov eax, cr4
|
||||||
or eax, 1 << 5
|
or eax, 1 << 5
|
||||||
mov cr4, eax
|
mov cr4, eax
|
||||||
|
|
||||||
; switch to the compatibility mode (which is part of long mode)
|
; enable longmode (compatibility mode)
|
||||||
mov ecx, 0xC0000080
|
mov ecx, 0xC0000080
|
||||||
rdmsr
|
rdmsr
|
||||||
or eax, 1 << 8
|
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.
|
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
|
mov cr0, eax
|
||||||
|
|
||||||
|
; jump to 64-bit longmode
|
||||||
pop ebx ; restore pointer to multiboot structure
|
pop ebx ; restore pointer to multiboot structure
|
||||||
lgdt [GDT64.Pointer] ; Load the 64-bit global descriptor table.
|
lgdt [GDT64.Pointer] ; Load the 64-bit global descriptor table.
|
||||||
jmp GDT64.Code:start64 ; Set the code segment and enter 64-bit long mode.
|
jmp GDT64.Code:start64 ; Set the code segment and enter 64-bit long mode.
|
||||||
|
|
||||||
Linvalid:
|
|
||||||
jmp $
|
|
||||||
|
|
||||||
[BITS 64]
|
[BITS 64]
|
||||||
start64:
|
start64:
|
||||||
; initialize segment registers
|
; initialize segment registers
|
||||||
|
|
Loading…
Add table
Reference in a new issue