feat(kernel): double linked list helper

This commit is contained in:
d0p1 🏳️‍⚧️ 2025-01-17 12:33:24 +01:00
parent cadddcbb13
commit 549c063b38
11 changed files with 504 additions and 77 deletions

View file

@ -28,6 +28,7 @@ SRCS = kernel.asm \
pic.inc \
idt.inc \
heap.inc \
queue.inc \
dev/console.inc \
dev/at/pit.inc \
dev/at/cga.inc \

View file

@ -2,6 +2,9 @@ KERNEL_VIRT_BASE = 0xC0000000
KERNEL_OFFSET = 0x100000
KBASE = KERNEL_VIRT_BASE + KERNEL_OFFSET
KERNEL_HEAP_BASE = KERNEL_VIRT_BASE + 0x800000
KERNEL_HEAP_SIZE = 260046848
PSIZE = 0x1000
STPDBOOT_MAGIC = 0x53545044
@ -17,6 +20,7 @@ BUILD_DATE equ "@DATE@"
CR = 0x0D
LF = 0x0A
CONFIG_COMPAT_I386 = 0
CONFIG_TRACE_PMM = 1
CONFIG_TRACE_VMEM = 1
CONFIG_TRACE_VMM = 1

View file

@ -47,6 +47,7 @@ kmain:
call mm_bootstrap
call pmm_init
call vmm_bootstrap
mov eax, 4
call pmm_alloc
@ -111,6 +112,7 @@ kmain:
jmp .halt
include 'klog.inc'
include 'queue.inc'
include 'dev/console.inc'
include 'dev/dev.inc'
include 'mm/mm.inc'
@ -132,7 +134,7 @@ kmain:
szMsgKernelAlive db "Kernel (", VERSION_FULL , ") is alive", 0
szMsgBuildDate db "Built ", BUILD_DATE, 0
szErrorBootProtocol db "Error: wrong magic number", 0
szKernelHeapStr db "KERNEL-HEAP", 0
;; Variable: stBootInfo
;; <BootInfo>
stBootInfo BootInfo

View file

@ -3,6 +3,7 @@ MM_KERNEL_PTE_BASE = 0xFFC00000
include '../sys/mmu.inc'
include 'bootstrap.inc'
include 'pmm.inc'
include 'vmem.inc'
include 'vmm.inc'
mm_init:

9
kernel/mm/uvm/uvm.inc Normal file
View file

@ -0,0 +1,9 @@
;; File: uvm.inc
include 'uvm_km.inc'
;; Function: uvm_init
;;
;; Sets up the UVM system
uvm_init:
ret

0
kernel/mm/uvm/uvm_km.inc Normal file
View file

View file

@ -0,0 +1,5 @@
;; File: uvm_map.inc
struc VmMap {
}

278
kernel/mm/vmem.inc Normal file
View file

@ -0,0 +1,278 @@
;; File: vmem.inc
;;
;; General purpose resource allocator.
;; Based on <tinyvmem at https://github.com/rdmsr/tinyvmem> and on <Bonwick's paper at https://www.usenix.org/legacy/event/usenix01/full_papers/bonwick/bonwick.pdf>
;;; MARK: macros and structs
VM_BESTFIT = (1 shl 0)
VM_INSTANTFIT = (1 shl 1)
VM_NEXTFIT = (1 shl 2)
VM_SLEEP = (1 shl 3)
VM_NOSLEEP = (1 shl 4)
VM_BOOTSTRAP = (1 shl 5)
STATIC_SEG_COUNT = 64
FREELISTS_N = 4 * 8
HASHTABLE_N = 16
SEGMENT_ALLOCATED = 0
SEGMENT_FREE = 1
SEGMENT_SPAN = 2
macro GET_LIST reg, N {
bsr reg, reg
xor reg, 31
add reg, -N
sub reg, 1
}
struc VmSegment {
.type db ?
.imported db ?
.base dd ?
.size dd ?
.spanlist ListEntry
.seglist ListEntry
}
DEFN VmSegment
;; Struc: Vmem
struc Vmem {
.name db 16 dup(0)
.base dd ?
.size dd ?
.quantum dd ?
.alloc dd ?
.free dd ?
.source dd ?
.vmflag dd ?
.freelist dd FREELISTS_N dup(0)
.hashtable dd HASHTABLE_N dup(0)
.spanlist ListHead 0
}
DEFN Vmem
;;; MARK: private functions
;; Function: _murmur32
;;
;; In:
;; EAX - Address
;;
;; Out:
;; EAX - Hash
;;
_murmur32:
; hash hash XOR (hash >> 16)
mov ecx, eax
shr ecx, 16
xor eax, ecx
; hash hash × 0x85ebca6b
mov ecx, 0x85ebca6b
mul ecx
; hash hash XOR (hash >> 13)
mov ecx, eax
shr ecx, 13
xor eax, ecx
; hash hash × 0xc2b2ae35
mov ecx, 0xc2b2ae35
mul ecx
; hash hash XOR (hash >> 16)
mov ecx, eax
shr ecx, 16
xor eax, ecx
ret
;; Function: _hash_table_addr
;;
;; In:
;; EAX - Vmem
;; EDX - ADDR
__hash_table_addr:
push ebp
mov ebp, esp
push esi
mov esi, eax
mov eax, edx
call _murmur32
and eax, HASHTABLE_N-1 ; x % y (y is a power of two)
shl eax, 2
mov edx, esi
add edx, Vmem.hashtable
add edx, eax
mov eax, [edx]
pop esi
leave
ret
;; Function: _vmm_segfree
;;
;; In:
;; EAX - Segment address
_vmm_segfree:
;mov ecx, eax
;add ecx, VmSegment.seglist.next
;mov edx, [pVmmFreeSegHead]
;or edx, edx
;jz @f
;mov [eax + VmSegment.seglist.next], edx
;mov [edx + VmSegment.seglist.prev], ecx
;@@:
; mov [pVmmFreeSegHead], eax
; mov [eax + VmSegment.seglist.prev], ecx
;
; inc [iVmmFreeSegCount]
ret
;
; ;; Function: _vmm_segalloc
;_vmm_segalloc:
; mov eax, [pVmmFreeSegHead]
; or eax, eax
; jz @f
;
; dec [iVmmFreeSegCount]
;@@:
; ret
;;; MARK: public functions
;; Function: vmem_create
;;
;; Creates a new <Vmem> arena whose initial span is [Base, Base + Size).
;;
;; In:
;; EAX - Pointer to a <Vmem> object.
;; EDX - String.
;; ECX - Base.
;; ESP[4] - Size in bytes.
;; ESP[8] - Quantum.
;; ESP[12] - Alloc function.
;; ESP[16] - Free function.
;; ESP[20] - Source.
;; ESP[24] - Flags. (<VM_SLEEP> or <VM_NOSLEEP>)
vmem_create:
push ebp
mov ebp, esp
mov [eax + Vmem.base], ecx
if CONFIG_TRACE_VMEM
push esi
push edi
push ebx
mov esi, eax
mov edi, edx
mov ebx, ecx
mov eax, esi
mov edx, edi
mov ecx, ebx
pop ebx
pop edi
pop esi
end if
leave
ret
;; Function: vmem_destroy
;;
;; Destroys an arena
;;
;; In:
;; EAX - Pointer to a <Vmem> object.
vmem_destroy:
ret
;; Function: vmem_alloc
;;
;; Allocates n-bytes from arena.
;;
;; In:
;; EAX - Pointer to a <Vmem> object.
;; EDX - Size in bytes.
;; ECX - Flags
;;
;; Out:
;; EAX - Allocated address on succes, 0 on failure.
vmem_alloc:
ret
;; Function: vmem_free
;;
;; Free n-bytes at address to arena
;;
;; In:
;; EAX - Pointer to a <Vmem> object.
;; EDX - Address.
;; ECX - Size in bytes.
vmem_free:
ret
;; Function: vmem_xalloc
;;
;; In:
;; EAX - Pointer to a <Vmem> object.
;; EDX - Size in bytes.
;; ECX - Alignment boundary.
;; ESP[4] - Phase.
;; ESP[8] - Nocross.
;; ESP[12] - Min address.
;; ESP[16] - Max address.
;; ESP[20] - Flags. (<VM_BESTFIT>, <VM_INSTANTFIT>, <VM_NEXTFIT>, <VM_SLEEP>, <VM_NOSLEEP>)
;;
;; Out:
;; EAX - Allocated address on succes, 0 on failure.
vmem_xalloc:
ret
;; Function: vmem_xfree
;;
;; Frees n-bytes at address.
;;
;; In:
;; EAX - Pointer to <Vmem> object.
;; EDX - Address.
;; ECX - Size in bytes.
vmem_xfree:
ret
;; Function: vmem_add
;;
;; Adds a span [Address, Address + Size) to an arena.
;;
;; In:
;; EAX - Pointer to <Vmem> object.
;; EDX - Address.
;; ECX - Size in bytes.
;; ESP[4] - Flags. (<VM_SLEEP> or <VM_NOSLEEP>)
;;
;; Out:
;; EAX - Return Address on success, 0 on failure.
vmem_add:
ret
;;; MARK: variables
aVmemStaticSegs db STATIC_SEG_COUNT*sizeof.VmSegment dup(0)
pVmemFreeSegHead dd 0
iVmemFreeSegCount dd 0
if CONFIG_TRACE_VMM
szTraceVmemCreate db "Trace(VMEM): Create %s [%x, %x)", 0
szTraceVmemAdd db "Trace(VMEM): %s: Add span [%x, %x)", 0
szTraceVmemDestroy db "Trace(VMEM): Destroy %s", 0
end if

View file

@ -1,80 +1,82 @@
;; File: vm.inc
;; Based on <https://github.com/rdmsr/tinyvmem at tinyvm>
;; Based on <tinyvmem at https://github.com/rdmsr/tinyvmem> and on <Bonwick's paper at https://www.usenix.org/legacy/event/usenix01/full_papers/bonwick/bonwick.pdf>
VM_BESTFIT = (1 shl 0)
VM_INSTANTFIT = (1 shl 1)
VM_NEXTFIT = (1 shl 2)
VM_SLEEP = (1 shl 3)
VM_NOSLEEP = (1 shl 4)
VM_BOOTSTRAP = (1 shl 5)
FREELISTS_N = 4 * 8
HASHTABLE_N = 16
SEGMENT_ALLOCATED = 0
SEGMENT_FREE = 1
SEGMENT_SPAN = 2
struc VmSegment {
.type db ?
.imported db ?
.base dd ?
.size dd ?
}
struc VmObject {
.tmp dd ?
}
struc VmPager {
.tmp dd ?
}
struc Vmem {
.name db 32 dup(0)
.base dd ?
.size dd ?
.quantum dd ?
.alloc dd ?
.free dd ?
.source dd ?
.qcache_max dd ?
.vmflag dd ? ;; db ?
.segqueue dd ?
.freelist dd FREELISTS_N dup(0)
.hashtable dd HASHTABLE_N dup(0)
.spanlist dd ?
}
;; Subroutine: _murmur32
;; Function: vmm_init
;;
;; Initializes a Vmem arena
;;
;; In:
;; EAX - Address
;;
;; Out:
;; EAX - Hash
;;
_murmur32:
; hash hash XOR (hash >> 16)
mov ecx, eax
shr ecx, 16
xor eax, ecx
; hash hash × 0x85ebca6b
mov ecx, 0x85ebca6b
mul ecx
; hash hash XOR (hash >> 13)
mov ecx, eax
shr ecx, 13
xor eax, ecx
; hash hash × 0xc2b2ae35
mov ecx, 0xc2b2ae35
mul ecx
; hash hash XOR (hash >> 16)
mov ecx, eax
shr ecx, 16
xor eax, ecx
;; EAX - Pointer to a Vmem dest
;; EDX - Base address
;; ECX - Size
;; ESP[4] - Quantum
;; ESP[8] - Pointer to alloc function
;; ESP[12] - Pointer to free function
;; ESP[16] - Poiter to Vmem source
;; ESP[20] - qcache max
;; ESP[24] - Flags
vmm_init:
push ebp
mov ebp, esp
push esi
push edi
mov [eax + Vmem.base], edx
mov [eax + Vmem.size], ecx
; copy other param from the stack
mov ecx, 28
mov edx, esp
add edx, 4
mov esi, edx
mov edx, eax
add edx, Vmem.quantum
mov edi, edx
rep movsd
mov ecx, [eax + Vmem.size]
or ecx, ecx
jz @f
mov edx, [eax + Vmem.source]
or edx, edx
jnz @f
mov edx, [eax + Vmem.base]
; call vmm_add
add esp, 4
@@:
pop edi
pop esi
leave
ret
vmem_init:
;; Function: vmm_bootstrap
;;
vmm_bootstrap:
push ebp
mov ebp, esp
push ebx
xor ebx, ebx
@@:
mov eax, aVmemStaticSegs
add eax, ebx
call _vmm_segfree
add ebx, sizeof.VmSegment
cmp ebx, STATIC_SEG_COUNT*sizeof.VmSegment
jl @b
pop ebx
leave
ret

125
kernel/queue.inc Normal file
View file

@ -0,0 +1,125 @@
;; File: queue.inc
;;; MARK: doubly linked lists
;; Group: List
;; Doubly linked lists
;; Struc: ListHead
struc ListHead initial {
.first dd initial
}
;; Struc: ListEntry
struc ListEntry {
.next dd ?
.prev dd ?
}
;; Function: list_insert_head
;;
;; In:
;; EAX - Head (see <ListHead>)
;; EDX - Element (see <ListEntry>)
;;
list_insert_head:
mov ecx, [eax]
mov [edx], ecx
or ecx, ecx
jz @f
mov [ecx + 4], edx
@@:
mov [eax], edx
mov [edx + 4], edx
ret
;; Function: list_remove
;;
;; In:
;; EAX - Element.
list_remove:
mov ecx, [eax + 4]
mov edx, [eax]
or edx, edx
jz @f
mov [edx + 4], ecx
@@:
mov [ecx], edx
ret
;; Function: list_map
;;
;; In:
;; EAX - Pointer to <ListHead>
;; EDX - Function to apply
;;
list_map:
push ebp
mov ebp, esp
push esi
push edi
; save function pointer
mov esi, edx
; load first elem
mov edi, [eax]
@@:
or edi, edi
jz @f ; exit loop if element is null
mov eax, edi
call esi
mov edi, [edi] ; load next element
jmp @b
@@:
pop edi
pop esi
leave
ret
;;; MARK: doubly linked tail queues
;; Group: TailQ
;; doubly linked tail queues
;; Struc: TailQHead
struc TailQHead {
.first dd ?
.last dd $$
}
;; Struc: TailQEntry
struc TailQEntry {
.next dd ?
.prev dd ?
}
;; Function: tailq_insert_head
;;
;; In:
;; EAX - Head.
;; EDX - Element.
tailq_insert_head:
ret
;; Function: tailq_insert_after
;;
tailq_insert_after:
ret
;; Function: tailq_insert_tail
tailq_insert_tail:
ret
;; Function: tailq_remove
tailq_remove:
ret
;; Function: tailq_map
tailq_map:
ret

View file

@ -1,7 +1,7 @@
;; File: cpu.inc
;; Structure: tss
;; Struc: tss
;;
;; > 31 23 15 7 0
;; > +----------|----------+----------|----------+
@ -93,7 +93,7 @@ struc GDTGate {
}
;; Structure: IDTGate
;; Struc: IDTGate
;; .offset_low - TODO
;; .selector - TODO
;; .zero - TODO