maybe i'm close to fixing multitasking
This commit is contained in:
+53
-106
@@ -1,117 +1,64 @@
|
||||
extern current
|
||||
global switchProcess
|
||||
|
||||
struc PCB
|
||||
.PID resd 1 ; Offset: 0
|
||||
.STATE resd 1 ; Offset: 4
|
||||
.PROGRAM_COUNTER resd 1 ; Offset: 8
|
||||
.STACK_BASE resd 1 ; Offset: 12
|
||||
.STACK_POINTER resd 1 ; Offset: 16
|
||||
.FLAGS resd 1 ; Offset: 20
|
||||
.NEXT resd 1 ; Offset: 24
|
||||
.PID resd 1 ; Offset: 0
|
||||
.STATE resd 1 ; Offset: 4
|
||||
.KSTACK resd 1 ; Offset: 8
|
||||
.CONTEXT resd 1 ; Offset: 12
|
||||
.TF resd 1 ; Offset: 16
|
||||
.FLAGS resd 1 ; Offset: 20
|
||||
.NEXT resd 1 ; Offset: 24
|
||||
.PAGE_DIRECTORY resd 1 ; Offset: 28
|
||||
endstruc
|
||||
|
||||
section .text
|
||||
|
||||
|
||||
; void switchProcess(Process* next)
|
||||
section .text
|
||||
global switchProcess
|
||||
extern current
|
||||
extern trapret
|
||||
|
||||
switchProcess:
|
||||
; __________Stack___________
|
||||
; |------------------------|
|
||||
; | Return Address (EIP) | +0
|
||||
; |------------------------|
|
||||
; | Process* next | +4
|
||||
; |------------------------|
|
||||
; Сохраняем регистры текущего процесса
|
||||
push ebx
|
||||
push esi
|
||||
push edi
|
||||
push ebp
|
||||
|
||||
; Push volatile registers (per the 32-bit System V ABI)
|
||||
push ebx
|
||||
push esi
|
||||
push edi
|
||||
push ebp
|
||||
; Сохраняем указатель стека в current->context
|
||||
mov edi, [current]
|
||||
mov [edi + 12], esp ; PCB.CONTEXT находится по смещению 12
|
||||
|
||||
; __________Stack___________
|
||||
; |------------------------|
|
||||
; | EBP | +0
|
||||
; |------------------------|
|
||||
; | EDI | +4
|
||||
; |------------------------|
|
||||
; | ESI | +8
|
||||
; |------------------------|
|
||||
; | EBX | +12
|
||||
; |-------- ---------------|
|
||||
; | Return Address (EIP) | +16
|
||||
; |------------------------|
|
||||
; | Process* next | +20
|
||||
; |------------------------|
|
||||
; Загружаем следующий процесс
|
||||
mov esi, [esp + 20] ; next (первый аргумент)
|
||||
mov [current], esi
|
||||
mov esp, [esi + 12] ; Загружаем esp из next->context
|
||||
|
||||
; Save current process' state
|
||||
mov edi, [current]
|
||||
; EDI now contains the pointer to [Process* current]
|
||||
; |-----|
|
||||
; | EDI | <== [Process* current]
|
||||
; |-----|
|
||||
; Восстанавливаем регистры
|
||||
pop ebp
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebx
|
||||
|
||||
; Set [current->PCB.STACK_POINTER] to the value in ESP
|
||||
; Process* current->PCB.STACK_POINTER <== ESP
|
||||
mov [edi + PCB.STACK_POINTER], esp
|
||||
; Проверяем ring процесса
|
||||
mov eax, [esi + 20] ; PCB.RING находится по смещению 20
|
||||
cmp eax, 3
|
||||
je .ring3
|
||||
ret ; Для ring 0 просто возвращаемся
|
||||
.ring3:
|
||||
jmp trapret ; Для ring 3 переходим через trapret
|
||||
|
||||
trapret:
|
||||
; Восстанавливаем общие регистры из trap frame
|
||||
popal ; edi, esi, ebp, oesp, ebx, edx, ecx, eax
|
||||
add esp, 4 ; Пропускаем oesp (не используется)
|
||||
|
||||
; Восстанавливаем сегментные регистры
|
||||
pop gs
|
||||
pop fs
|
||||
pop es
|
||||
pop ds
|
||||
|
||||
; Пропускаем trapno и err
|
||||
add esp, 8 ; trapno (4 байта) + err (4 байта)
|
||||
|
||||
|
||||
; Load next process' state
|
||||
; ESP has been decremented by 16, so instead of +4,
|
||||
; we need to do +20. 4 pushes, 1 return address, 4
|
||||
; bytes each.
|
||||
mov esi, [esp + 20]
|
||||
; ESI now contains the pointer to [Process* next]
|
||||
; __________Stack___________
|
||||
; |------------------------|
|
||||
; | Return Address (EIP) | +16
|
||||
; |-----| |------------------------|
|
||||
; | ESI | <== | Process* next | +20
|
||||
; |-----| |------------------------|
|
||||
|
||||
|
||||
; Set [EXTERN Process* current] to the value in ESI
|
||||
; Process* current <== ESI (Process* next)
|
||||
mov [current], esi
|
||||
|
||||
mov esp, [esi + PCB.STACK_POINTER]
|
||||
; |-----| |-----|
|
||||
; | ESP | <== | ESI |
|
||||
; |-----| |-----|
|
||||
|
||||
; Restore non-volatile registers (per the 32-bit System V ABI)
|
||||
pop ebp
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebx
|
||||
|
||||
; The stack is now restored to its original state.
|
||||
; __________Stack___________
|
||||
; |------------------------|
|
||||
; | Return Address (EIP) | +0
|
||||
; |------------------------|
|
||||
; | Process* next | +4
|
||||
; |------------------------|
|
||||
|
||||
ret
|
||||
|
||||
global jump_usermode
|
||||
extern test_user_function
|
||||
jump_usermode:
|
||||
mov ax, (4 * 8) | 3 ; ring 3 data with bottom 2 bits set for ring 3
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax ; SS is handled by iret
|
||||
|
||||
; and eax, ~0x80000000
|
||||
; mov cr0, eax
|
||||
|
||||
; set up the stack frame iret expects
|
||||
mov eax, esp
|
||||
push (4 * 8) | 3 ; data selector
|
||||
push eax ; current esp
|
||||
pushf ; eflags
|
||||
push (3 * 8) | 3 ; code selector (ring 3 code with bottom 2 bits set for ring 3)
|
||||
push test_user_function ; instruction address to return to
|
||||
iret
|
||||
; Теперь ESP указывает на eip, cs, eflags, esp, ss
|
||||
iret
|
||||
Reference in New Issue
Block a user