69 lines
2.1 KiB
NASM
69 lines
2.1 KiB
NASM
section .text
|
|
global switch_to_task
|
|
extern currentTask
|
|
extern tss
|
|
;WARNING: Caller is expected to disable IRQs before calling, and enable IRQs again after function returns
|
|
|
|
switch_to_task:
|
|
|
|
;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,[currentTask] ;edi = address of the previous task's data structure
|
|
mov [edi],esp ;Save ESP for the task's kernel stack in the task's data structure
|
|
|
|
;Load next task's state
|
|
|
|
mov esi,[esp+(4+1)*4] ;esi = address of the next task's data structure
|
|
mov [currentTask],esi ;Current task's task data is the next task thread data
|
|
|
|
mov esp,[esi] ;Load ESP for next task's kernel stack from the task's data structure
|
|
mov eax,[esi+8] ;eax = address of page directory for next task
|
|
mov ebx,[esi+4] ;ebx = address for the top of the next task's kernel stack
|
|
mov [tss+4],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
|
|
|
|
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
|
|
|
|
ret ;Load next task's EIP from its kernel stack
|
|
|
|
global task_init
|
|
|
|
task_init:
|
|
pop ecx
|
|
pop ebx
|
|
cli
|
|
mov ax, 0x23
|
|
mov ds, ax
|
|
mov es, ax
|
|
mov fs, ax
|
|
mov gs, ax
|
|
mov eax, ecx
|
|
push 0x23
|
|
push eax
|
|
pushf
|
|
pop eax
|
|
or eax, 0x200
|
|
push eax
|
|
push 0x1B
|
|
push ebx
|
|
iret
|