diff options
author | Anton Kling <anton@kling.gg> | 2024-02-07 11:36:21 +0100 |
---|---|---|
committer | Anton Kling <anton@kling.gg> | 2024-02-07 22:25:47 +0100 |
commit | 35958c8c6b600482f68fef08ac26547b5655e987 (patch) | |
tree | a3329136adc1b92885c60462e7dd74c98eaa0953 /kernel/process.s | |
parent | b7fa1457727338416499d1b0144f1042a6878a97 (diff) |
A lot of small changes
Diffstat (limited to 'kernel/process.s')
-rw-r--r-- | kernel/process.s | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/kernel/process.s b/kernel/process.s index 24e1869..9f8ee71 100644 --- a/kernel/process.s +++ b/kernel/process.s @@ -31,3 +31,117 @@ copy_page_physical: popf pop ebx ret + + +.extern current_task_TCB +.global TCB + +.section .data + + .struct 0 +TCB: +TCB.ESP: + .space 4 +TCB.CR3: + .space 4 +TCB.ESP0: + .space 4 + +.global switch_to_task +.global insert_eip_on_stack +.global internal_fork +.extern create_process + +.section .text + +internal_fork: + push ebp + mov ecx, esp + mov ebp, esp + + mov eax, [ebp+8] # current_task + + lea edx, after_internal_fork + push edx + push ecx + push eax + call create_process + add esp, 0xC + + pop ebp + ret +after_internal_fork: + pop ebp + mov eax, 0 + ret + +insert_eip_on_stack: + push ebp + mov ebp, esp + mov eax, [ebp+8] # cr3 + mov ecx, [ebp+8+4] # address + mov edx, [ebp+8+4+4] # value + + push ebx + + mov ebx, cr3 + mov cr3, eax + + mov [ecx], edx + + mov cr3, ebx + + pop ebx + pop ebp + ret + +# C declaration: +# void switch_to_task(thread_control_block *next_thread); +# +# WARNING: Caller is expected to disable IRQs before calling, and enable IRQs again after function returns + +switch_to_task: + cli + + # Save previous task's state + + # Notes: + # For cdecl; EAX, ECX, and EDX are already saved by the caller and don't need to be saved again + # EIP is already saved on the stack by the caller's "CALL" instruction + # The task isn't able to change CR3 so it doesn't need to be saved + # Segment registers are constants (while running kernel code) so they don't need to be saved + + push ebx + push esi + push edi + push ebp + + mov edi,[current_task_TCB] # edi = address of the previous task's "thread control block" + mov [edi+TCB.ESP],esp # Save ESP for previous task's kernel stack in the thread's TCB + + # Load next task's state + + mov esi,[esp+(4+1)*4] # esi = address of the next task's "thread control block" (parameter passed on stack) + mov [current_task_TCB],esi # Current task's TCB is the next task TCB + + mov esp,[esi+TCB.ESP] # Load ESP for next task's kernel stack from the thread's TCB + mov eax,[esi+TCB.CR3] # eax = address of page directory for next task + mov ebx,[esi+TCB.ESP0] # ebx = address for the top of the next task's kernel stack +# mov [TSS.ESP0],ebx # Adjust the ESP0 field in the TSS (used by CPU for for CPL=3 -> CPL=0 privilege level changes) +# mov ecx,cr3 # ecx = previous task's virtual address space + +# FIXME: This branch gets a from the assembler, something about "relaxed branches". +# this branch would probably not be used anyway but should be checked on later anyway. +# cmp eax,ecx # Does the virtual address space need to being changed? + +# je .doneVAS # no, virtual address space is the same, so don't reload it and cause TLB flushes + mov cr3,eax # yes, load the next task's virtual address space +#.doneVAS: + + pop ebp + pop edi + pop esi + pop ebx + + sti + ret # Load next task's EIP from its kernel stack |