1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 18:37:34 +00:00

Kernel: Move kernel above the 3GB virtual address mark

The kernel and its static data structures are no longer identity-mapped
in the bottom 8MB of the address space, but instead move above 3GB.

The first 8MB above 3GB are pseudo-identity-mapped to the bottom 8MB of
the physical address space. But things don't have to stay this way!

Thanks to Jesse who made an earlier attempt at this, it was really easy
to get device drivers working once the page tables were in place! :^)

Fixes #734.
This commit is contained in:
Andreas Kling 2020-01-17 19:59:20 +01:00
parent cee597a728
commit e362b56b4f
17 changed files with 325 additions and 125 deletions

View file

@ -31,10 +31,20 @@ stack_bottom:
.skip 32768
stack_top:
.section .page_tables
.section .page_tables, "aw", @nobits
.align 4096
page_tables_start:
.skip 4096*9
.global boot_pdpt
boot_pdpt:
.skip 4096
.global boot_pd0
boot_pd0:
.skip 4096
.global boot_pd3
boot_pd3:
.skip 4096
.global boot_pd3_pde1023_pt
boot_pd3_pde1023_pt:
.skip 4096
.section .text
@ -47,17 +57,121 @@ page_tables_start:
.extern multiboot_info_ptr
.type multiboot_info_ptr, @object
/*
construct the following (32-bit PAE) page table layout:
pdpt
0: boot_pd0 (0-1GB)
1: n/a (1-2GB)
2: n/a (2-3GB)
3: boot_pd3 (3-4GB)
boot_pd0 : 512 pde's
0: (0-2MB) (id 2MB page)
1: (2-4MB) (id 2MB page)
2: (4-6MB) (id 2MB page)
3: (6-8MB) (id 2MB page)
boot_pd3 : 512 pde's
0: boot_pd3_pde0 (3072-3074MB) (pseudo)
1: boot_pd3_pde1 (3074-3076MB) (pseudo)
2: boot_pd3_pde2 (3076-3078MB) (pseudo)
3: boot_pd3_pde3 (3078-3080MB) (pseudo)
4: boot_pd3_pde1023_pt (4094-4096MB) (for page table mappings)
*/
start:
cli
cld
mov $stack_top, %esp
/* clear pdpt */
movl $(boot_pdpt - 0xc0000000), %edi
movl $1024, %ecx
xorl %eax, %eax
rep stosl
/* set up pdpt[0] and pdpt[3] */
movl $(boot_pdpt - 0xc0000000), %edi
movl $((boot_pd0 - 0xc0000000) + 1), 0(%edi)
movl $((boot_pd3 - 0xc0000000) + 1), 24(%edi)
/* clear pd0 */
movl $(boot_pd0 - 0xc0000000), %edi
movl $1024, %ecx
xorl %eax, %eax
rep stosl
/* identity map bottom 8MB using 2MB pages (only PDE, no PTE) */
movl $4, %ecx
xorl %eax, %eax
movl $(boot_pd0 - 0xc0000000), %edi
1:
movl %eax, 0(%edi)
/* PS(2MB) + R/W + Present */
orl $0x83, 0(%edi)
addl $8, %edi
addl $(1048576 * 2), %eax
loop 1b
/* clear pd3 */
movl $(boot_pd3 - 0xc0000000), %edi
movl $1024, %ecx
xorl %eax, %eax
rep stosl
/* pseudo-identity map first 8MB above 3GB mark using 2MB pages again */
movl $4, %ecx
xorl %eax, %eax
movl $(boot_pd3 - 0xc0000000), %edi
1:
movl %eax, 0(%edi)
/* PS(2MB) + R/W + Present */
orl $0x83, 0(%edi)
addl $8, %edi
addl $(1048576 * 2), %eax
loop 1b
/* create an empty page table for the top 2MB at the 4GB mark */
movl $(boot_pd3 - 0xc0000000), %edi
movl $(boot_pd3_pde1023_pt - 0xc0000000), 4088(%edi)
orl $0x3, 4088(%edi)
movl $0, 4092(%edi)
/* point CR3 to PDPT */
movl $(boot_pdpt - 0xc0000000), %eax
movl %eax, %cr3
/* enable PAE + PSE */
movl %cr4, %eax
orl $0x60, %eax
movl %eax, %cr4
/* enable PG */
movl %cr0, %eax
orl $0x80000000, %eax
movl %eax, %cr0
/* jmp to an address above the 3GB mark */
push %cs
push $1f
retf
1:
movl %cr3, %eax
movl %eax, %cr3
/* set up initial stack and jump into C++ land */
mov $stack_top, %esp
and $-16, %esp
mov %ebx, multiboot_info_ptr
addl $0xc0000000, %ebx
movl %ebx, multiboot_info_ptr
pushl $page_tables_start
call init
add $4, %esp