feat(kernel): double linked list helper
This commit is contained in:
parent
cadddcbb13
commit
549c063b38
11 changed files with 504 additions and 77 deletions
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
9
kernel/mm/uvm/uvm.inc
Normal 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
0
kernel/mm/uvm/uvm_km.inc
Normal file
5
kernel/mm/uvm/uvm_map.inc
Normal file
5
kernel/mm/uvm/uvm_map.inc
Normal file
|
@ -0,0 +1,5 @@
|
|||
;; File: uvm_map.inc
|
||||
|
||||
struc VmMap {
|
||||
|
||||
}
|
278
kernel/mm/vmem.inc
Normal file
278
kernel/mm/vmem.inc
Normal 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
|
|
@ -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
125
kernel/queue.inc
Normal 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
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue