|
| 1 | +[EXTERN _current_task_small] |
| 2 | +[EXTERN _task_context_offset] |
| 3 | +[EXTERN task_die] |
| 4 | + |
| 5 | +[GLOBAL context_switch] |
| 6 | +[GLOBAL _task_bootstrap] |
| 7 | +[GLOBAL _first_context_switch] |
| 8 | + |
| 9 | +_first_context_switch: |
| 10 | + ; Save arg to function containing task to switch to in ecx |
| 11 | + mov rcx, rdi |
| 12 | + jmp _context_switch_restore_state |
| 13 | + |
| 14 | + |
| 15 | +context_switch: |
| 16 | + ; Save arg to function containing task to switch to in ecx |
| 17 | + mov rcx, rdi |
| 18 | + |
| 19 | +;Save the old task's state |
| 20 | + ; Save registers that are supposed to be callee-saved |
| 21 | + push rax |
| 22 | + push rbx |
| 23 | + push rsi |
| 24 | + push rdi |
| 25 | + push rbp |
| 26 | + |
| 27 | + ; Save preempted task's esp as _current_task->machine_state |
| 28 | + mov rax, [_current_task_small] |
| 29 | + mov rbx, [_task_context_offset] |
| 30 | + add rax, rbx |
| 31 | + mov [rax], rsp |
| 32 | + |
| 33 | +;Load the new task's state |
| 34 | +_context_switch_restore_state: |
| 35 | + ; Set the provided argument to _current_task_small |
| 36 | + mov [_current_task_small], rcx |
| 37 | + |
| 38 | + ; Load rsp with _current_task->machine_state |
| 39 | + mov rbx, [_task_context_offset] |
| 40 | + add rcx, rbx |
| 41 | + mov rsp,[rcx] |
| 42 | + |
| 43 | + ; Restore registers that were callee-saved |
| 44 | + pop rbp |
| 45 | + pop rdi |
| 46 | + pop rsi |
| 47 | + pop rbx |
| 48 | + pop rax |
| 49 | + |
| 50 | + ; Return to the new task's EIP (that was stored on its stack) |
| 51 | + sti |
| 52 | + ret |
| 53 | + |
| 54 | + |
| 55 | +_task_bootstrap: |
| 56 | + ; rsp+8: entry point pointer |
| 57 | + ; rsp+16: entry point arg1 |
| 58 | + ; rsp+24: entry point arg2 |
| 59 | + ; rsp+32: entry point arg3 |
| 60 | + ; Entry point arg1 |
| 61 | + mov rdi, [rsp+16] |
| 62 | + ; Entry point arg2 |
| 63 | + mov rsi, [rsp+24] |
| 64 | + ; Entry point arg3 |
| 65 | + mov rdx, [rsp+32] |
| 66 | + ; Entry point |
| 67 | + call [rsp+8] |
| 68 | + |
| 69 | + mov rdx, rax |
| 70 | + call task_die |
| 71 | + ; Should never execute... |
| 72 | + ; Try to force a page fault |
| 73 | + mov rax, 0x0 |
| 74 | + call rax |
| 75 | + ret |