summaryrefslogtreecommitdiff
path: root/stage3/paging.asm
diff options
context:
space:
mode:
authorLizzy Fleckenstein <eliasfleckenstein@web.de>2022-10-06 16:45:17 +0200
committerLizzy Fleckenstein <eliasfleckenstein@web.de>2022-10-06 16:45:17 +0200
commitf8397815545adb7d0da36614e0065aa68453a2e4 (patch)
treea771f526970c6724b2511577dceece8783450a49 /stage3/paging.asm
downloadcuddles-f8397815545adb7d0da36614e0065aa68453a2e4.tar.xz
Initial commit
Diffstat (limited to 'stage3/paging.asm')
-rw-r--r--stage3/paging.asm336
1 files changed, 336 insertions, 0 deletions
diff --git a/stage3/paging.asm b/stage3/paging.asm
new file mode 100644
index 0000000..8b1d571
--- /dev/null
+++ b/stage3/paging.asm
@@ -0,0 +1,336 @@
+global page_region
+extern print_hex, print_chr, newline, print_dec, print_str
+
+section .text
+
+pagebuf_init:
+ .start: dq 0x5000
+ .size: dq 0x2000
+ .used: dq 0
+
+pagebuf: dq pagebuf_init
+
+next_page: dq 0
+
+; allocate new page table buffer
+alloc:
+ ; rsi = buffer (result)
+ ; rdi = next_page
+ ; r8 = pagebuf
+ ; rbx = upper
+ ; rax = tmp; used_next
+
+ mov r8, [pagebuf] ; *pagebuf
+ mov rsi, [r8] ; start = pagebuf->start
+
+ mov rbx, [r8+8] ; size = pagebuf->size
+ add rbx, rsi ; upper_have = start + size
+
+ ; round *up* to 0x1000 align
+ mov rax, 0xfff
+ add rsi, rax
+ not rax
+ and rsi, rax ; aligned_start = (start + 0xfff) & (~0xfff)
+
+ mov rax, [r8+16] ; used = pagebuf->used
+ add rax, 0x1000
+ add rsi, rax ; upper_need = aligned_start + used + 0x1000
+
+ cmp rsi, rbx ; if upper_need > upper_have
+ ja .newbuf ; current region is full, get new
+
+ cmp rsi, r10 ; if upper_need >= next_page
+ jae .oom ; out of memory (target buffer isn't paged yet)
+
+ mov [r8+16], rax ; pagebuf->used = used + 0x1000
+
+ ; clear out buffer
+
+ mov rbx, rsi
+ sub rsi, 0x1000
+
+.clear:
+ sub rbx, 8
+ mov qword[rbx], 0
+ cmp rbx, rsi
+ jne .clear
+
+ ret
+
+; select next page buffer
+.newbuf:
+ cmp r8, pagebuf_init
+ jne .nextbuf
+
+ mov r8, 0x500
+ jmp .trybuf
+
+.nextbuf:
+ add r8, 24
+
+.trybuf:
+ cmp qword[r8], 0
+ je .oom ; last region reached
+
+ mov rax, [r8+16]
+
+ cmp rax, -1
+ je .nextbuf ; region is reserved
+
+ cmp rax, 0
+ jne .oom ; region has not been paged yet
+
+ mov [pagebuf], r8
+ jmp alloc
+
+.oom:
+ push rdi
+
+ mov rdi, .oom_msg
+ call print_str
+
+ pop rdi
+
+ call print_hex
+ call newline
+
+ jmp $
+
+.oom_msg: db "out of memory for page table", 10, "next_page = ", 0
+
+; get/create page tables
+get_tables:
+; level 4
+
+ ; rdi = address (arg, persist)
+ ; rax = tmp
+ ; rbx = mask
+ ; rcx = bits (persist)
+ ; rdx = level (persist)
+ ; r8 = table address
+ ; rsi = next offset (persist)
+
+ mov cl, 12+9*4
+ mov dl, 4
+
+ mov rsi, 0x1000
+
+; level 4
+.level:
+ dec dl
+ mov r8, rdi
+ mov rbx, -1 ; reset remainder mask
+ shl rbx, cl ; update remainder mask
+ not rbx ; negate remainder mask
+ and r8, rbx ; apply remainder mask
+
+ mov al, 9
+ mul dl
+ add al, 12
+ mov cl, al
+
+ shr r8, cl ; divide
+ shl r8, 3 ; multiply by 8
+
+ mov rbx, 0xfff ; 0x1000 alignment
+ not rbx ; offset mask
+
+ and rsi, rbx ; apply offset mask
+ add r8, rsi ; add offset
+ push r8 ; store
+
+ cmp dl, 0
+ je .done
+
+ mov rsi, [r8] ; next offset
+ cmp rsi, 0
+ jne .level
+
+ call alloc
+ or rsi, 3
+ mov r8, [rsp]
+ mov [r8], rsi
+
+ jmp .level
+
+.done:
+ pop r11
+ pop r12
+ pop r13
+ pop r14
+
+ ret
+
+space:
+ mov dil, ' '
+ jmp print_chr
+
+page_region:
+ push rbx
+ push r12
+ push r13
+ push r14
+ push r15
+
+ mov r9, rdi
+
+ mov rdi, [r9] ; ptr = mmap_entry->ptr
+ mov r10, [next_page]
+
+ push rdi
+
+ mov rax, 1 << 63
+
+ or rdi, rax
+ call print_hex
+ call space
+
+ mov rdi, [r9+8]
+ add rdi, [rsp]
+ or rdi, rax
+
+ call print_hex
+ call newline
+
+ pop rdi
+
+ ; for usable region (type = 1), set mmap_entry->used = 0
+ ; for reserved region (type = 2), set mmap_entry->used = -1
+ xor rax, rax
+ xor rbx, rbx
+ mov eax, dword[r9+16]
+ cmp rax, 1
+ je .set_used
+ dec rbx
+.set_used:
+ mov [r9+16], rbx
+
+ mov r10, rdi
+ mov r15, rdi ; r15 = end of region
+ add r15, [r9+8]
+
+ mov rax, 0xfff
+ not rax
+ and rdi, rax ; round down to 0x1000 aligned
+
+ cmp rdi, r10
+ jb .get_tables
+
+ mov r10, rdi
+
+.get_tables:
+ call get_tables ; page tables into r11-r14
+
+ ; start filling L1 map
+.l1:
+ mov rax, rdi
+ or rax, 3
+ mov [r11], rax
+
+ add rdi, 0x1000
+
+ cmp rdi, r10
+ jb .next
+
+ mov r10, rdi
+
+.next:
+ cmp rdi, r15 ; if next >= end
+ jae .done
+
+ ; prepare rcx mask for later
+ mov rcx, -1
+ shl rcx, 3
+
+ ; bump L1
+
+ add r11, 8
+ mov rax, r11
+ and rax, 0xfff
+ jnz .l1
+
+ ; bump L2
+
+ add r12, 8
+ mov rax, r12
+ and rax, 0xfff
+ jnz .l2
+
+ ; bump L3
+
+ add r13, 8
+ mov rax, r13
+ and rax, 0xfff
+ jnz .l3
+
+ ; bump L4
+
+ add r14, 8
+ mov rax, r14
+ and rax, 0xfff
+ jnz .l4
+
+ ; machine has more than 256TB of RAM, tell user to fuck off
+ jmp .bruh
+
+.l4:
+ mov r13, [r14]
+ and r13, rcx
+ jnz .l3
+
+ call alloc
+ mov r13, rsi
+ or rsi, 3
+ mov [r14], rsi
+
+.l3:
+ mov r12, [r13]
+ and r12, rcx
+ jnz .l2
+
+ call alloc
+ mov r12, rsi
+ or rsi, 3
+ mov [r13], rsi
+
+.l2:
+ mov r11, [r12]
+ and r11, rcx
+ jnz .l2
+
+ call alloc
+ mov r11, rsi
+ or rsi, 3
+ mov [r12], rsi
+
+ jmp .l1
+
+.done:
+ mov [next_page], r10
+
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop rbx
+
+ ret
+
+.bruh:
+ mov rdi, .bruh_msg
+ call print_str
+ jmp $
+
+.bruh_msg: db "bruh why do you have more than 256TB of RAM (you fucking glow)", 10, 0
+
+; identity map available memory
+old_page_map:
+ mov r9, 0x0500 ; mmap_entry
+.entry:
+ cmp qword[r9], 0
+ je .done
+ call page_region
+ add r9, 24
+ jmp .entry
+.done:
+ ret