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 \ pic.inc \
idt.inc \ idt.inc \
heap.inc \ heap.inc \
queue.inc \
dev/console.inc \ dev/console.inc \
dev/at/pit.inc \ dev/at/pit.inc \
dev/at/cga.inc \ dev/at/cga.inc \

View file

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

View file

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

View file

@ -3,6 +3,7 @@ MM_KERNEL_PTE_BASE = 0xFFC00000
include '../sys/mmu.inc' include '../sys/mmu.inc'
include 'bootstrap.inc' include 'bootstrap.inc'
include 'pmm.inc' include 'pmm.inc'
include 'vmem.inc'
include 'vmm.inc' include 'vmm.inc'
mm_init: 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 ;; 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) ;; Function: vmm_init
VM_INSTANTFIT = (1 shl 1) ;;
VM_NEXTFIT = (1 shl 2) ;; Initializes a Vmem arena
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
;; ;;
;; In: ;; In:
;; EAX - Address ;; EAX - Pointer to a Vmem dest
;; ;; EDX - Base address
;; Out: ;; ECX - Size
;; EAX - Hash ;; ESP[4] - Quantum
;; ;; ESP[8] - Pointer to alloc function
_murmur32: ;; ESP[12] - Pointer to free function
; hash hash XOR (hash >> 16) ;; ESP[16] - Poiter to Vmem source
mov ecx, eax ;; ESP[20] - qcache max
shr ecx, 16 ;; ESP[24] - Flags
xor eax, ecx vmm_init:
; hash hash × 0x85ebca6b push ebp
mov ecx, 0x85ebca6b mov ebp, esp
mul ecx
; hash hash XOR (hash >> 13) push esi
mov ecx, eax push edi
shr ecx, 13
xor eax, ecx mov [eax + Vmem.base], edx
; hash hash × 0xc2b2ae35 mov [eax + Vmem.size], ecx
mov ecx, 0xc2b2ae35
mul ecx ; copy other param from the stack
; hash hash XOR (hash >> 16) mov ecx, 28
mov ecx, eax mov edx, esp
shr ecx, 16 add edx, 4
xor eax, ecx 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 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 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 ;; File: cpu.inc
;; Structure: tss ;; Struc: tss
;; ;;
;; > 31 23 15 7 0 ;; > 31 23 15 7 0
;; > +----------|----------+----------|----------+ ;; > +----------|----------+----------|----------+
@ -93,7 +93,7 @@ struc GDTGate {
} }
;; Structure: IDTGate ;; Struc: IDTGate
;; .offset_low - TODO ;; .offset_low - TODO
;; .selector - TODO ;; .selector - TODO
;; .zero - TODO ;; .zero - TODO