Skip to content

Commit

Permalink
kern/vmm: Add x86-64 5-level paging support
Browse files Browse the repository at this point in the history
  • Loading branch information
mintsuki committed Jul 11, 2024
1 parent 215c987 commit 921e593
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 8 deletions.
19 changes: 14 additions & 5 deletions kernel/modules/limine/limine.v
Original file line number Diff line number Diff line change
Expand Up @@ -142,21 +142,30 @@ pub mut:
response &LimineFramebufferResponse
}

// 5-level paging
// Paging mode

pub struct Limine5LevelPagingResponse {
pub const (
limine_paging_mode_x86_64_4lvl = 0
limine_paging_mode_x86_64_5lvl = 1
)

pub struct LiminePagingModeResponse {
pub mut:
revision u64
mode u64
flags u64
}

pub struct Limine5LevelPagingRequest {
pub struct LiminePagingModeRequest {
pub mut:
id [4]u64 = [
u64(0xc7b1dd30df4c8b88), 0x0a82e883a194f07b,
0x94469551da9b3192, 0xebe5e86db7382888
0x95c1a0edab0944cb, 0xa4e5cb3842f7488a
]!
revision u64
response &Limine5LevelPagingResponse
response &LiminePagingModeResponse
mode u64
flags u64
}

// SMP
Expand Down
4 changes: 4 additions & 0 deletions kernel/modules/memory/physical.v
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ __global (
volatile hhdm_req = limine.LimineHHDMRequest{
response: unsafe { nil }
}
volatile paging_mode_req = limine.LiminePagingModeRequest{
response: unsafe { nil }
mode: limine.limine_paging_mode_x86_64_5lvl
}
)

pub fn print_free() {
Expand Down
42 changes: 39 additions & 3 deletions kernel/modules/memory/virtual.v
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub const (

__global (
page_size = u64(0x1000)
la57 = bool(false)
kernel_pagemap Pagemap
vmm_initialised = bool(false)
)
Expand Down Expand Up @@ -60,12 +61,18 @@ pub fn new_pagemap() &Pagemap {
}

pub fn (pagemap &Pagemap) virt2pte(virt u64, allocate bool) ?&u64 {
pml5_entry := (virt & (u64(0x1ff) << 48)) >> 48
pml4_entry := (virt & (u64(0x1ff) << 39)) >> 39
pml3_entry := (virt & (u64(0x1ff) << 30)) >> 30
pml2_entry := (virt & (u64(0x1ff) << 21)) >> 21
pml1_entry := (virt & (u64(0x1ff) << 12)) >> 12

pml4 := pagemap.top_level
pml5 := pagemap.top_level
pml4 := if !la57 {
pagemap.top_level
} else {
get_next_level(pml5, pml5_entry, allocate) or { return none }
}
pml3 := get_next_level(pml4, pml4_entry, allocate) or { return none }
pml2 := get_next_level(pml3, pml3_entry, allocate) or { return none }
pml1 := get_next_level(pml2, pml2_entry, allocate) or { return none }
Expand Down Expand Up @@ -116,12 +123,19 @@ fn get_next_level(current_level &u64, index u64, allocate bool) ?&u64 {
}

pub fn (mut pagemap Pagemap) unmap_page(virt u64) ? {
pml5_entry := (virt & (u64(0x1ff) << 48)) >> 48
pml4_entry := (virt & (u64(0x1ff) << 39)) >> 39
pml3_entry := (virt & (u64(0x1ff) << 30)) >> 30
pml2_entry := (virt & (u64(0x1ff) << 21)) >> 21
pml1_entry := (virt & (u64(0x1ff) << 12)) >> 12

mut pml4 := pagemap.top_level
mut pml5 := pagemap.top_level
mut pml5_p := unsafe { &u64(u64(pml5) + higher_half) }
mut pml4 := if !la57 {
pagemap.top_level
} else {
get_next_level(pml5, pml5_entry, false) or { return none }
}
mut pml4_p := unsafe { &u64(u64(pml4) + higher_half) }
mut pml3 := get_next_level(pml4, pml4_entry, false) or { return none }
mut pml3_p := unsafe { &u64(u64(pml3) + higher_half) }
Expand Down Expand Up @@ -167,6 +181,17 @@ pub fn (mut pagemap Pagemap) unmap_page(virt u64) ? {
pmm_free(pml3, 1)
pml4_p[pml4_entry] = 0
}
if la57 {
for ; i < 512; i++ {
if pml4_p[i] != 0 {
break
}
}
if i == 512 {
pmm_free(pml4, 1)
pml5_p[pml5_entry] = 0
}
}
}

current_cr3 := cpu.read_cr3()
Expand Down Expand Up @@ -195,12 +220,18 @@ pub fn (mut pagemap Pagemap) map_page(virt u64, phys u64, flags u64) ? {
pagemap.l.release()
}

pml5_entry := (virt & (u64(0x1ff) << 48)) >> 48
pml4_entry := (virt & (u64(0x1ff) << 39)) >> 39
pml3_entry := (virt & (u64(0x1ff) << 30)) >> 30
pml2_entry := (virt & (u64(0x1ff) << 21)) >> 21
pml1_entry := (virt & (u64(0x1ff) << 12)) >> 12

pml4 := pagemap.top_level
pml5 := pagemap.top_level
pml4 := if !la57 {
pagemap.top_level
} else {
get_next_level(pml5, pml5_entry, true) or { return none }
}
pml3 := get_next_level(pml4, pml4_entry, true) or { return none }
pml2 := get_next_level(pml3, pml3_entry, true) or { return none }
mut pml1 := get_next_level(pml2, pml2_entry, true) or { return none }
Expand Down Expand Up @@ -234,6 +265,11 @@ fn map_kernel_span(virt u64, phys u64, len u64, flags u64) {
}

pub fn vmm_init() {
if paging_mode_req.response.mode == limine.limine_paging_mode_x86_64_5lvl {
print('vmm: Using 5 level paging\n')
la57 = true
}

print('vmm: Kernel physical base: 0x${kaddr_req.response.physical_base:x}\n')
print('vmm: Kernel virtual base: 0x${kaddr_req.response.virtual_base:x}\n')

Expand Down

0 comments on commit 921e593

Please sign in to comment.