global clear_tss global invlpg global set_tss global switch_to extern ctask extern ctaskn extern gdt extern save_state ; void switch_to(int n, struct task_struct *task) switch_to: push ebp mov ebp, esp push ebx ; abort if we're switching to the current task mov ebx, [ctask] cmp ebx, [ebp+12] jne .skip pop ebx pop ebp ret .skip: ; update ctask and ctaskn mov ebx, [ebp+12] mov [ctask], ebx mov ebx, [ebp+8] mov [ctaskn], ebx ; calculate the task segment index and jump to it mov ebx, [ebp+8] add ebx, 5 shl ebx, 3 mov [.tmp+4], bx jmp far [.tmp] pop ebx pop ebp ret .tmp: dq 0 ; void invlpg(void *page) invlpg: push ebp mov ebp, esp ; test if we're running on a i386 and abort if so (only i486+ have caches) pushf pop eax and eax, 0xFFFBFFFF push eax popf pushf pop eax test eax, 0x40000 jnz .skip pushf pop eax or eax, 0x40000 push eax popf pushf pop eax test eax, 0x40000 jz .skip mov eax, [ebp+8] invlpg [eax] .skip: pop ebp ret ; void set_tss(unsigned int n, void *tss) set_tss: push ebp mov ebp, esp push ebx mov eax, [ebp+12] mov ebx, [ebp+8] shl ebx, 3 add ebx, gdt+40 mov [ebx+2], ax shr eax, 16 mov [ebx+4], al mov [ebx+7], ah mov eax, 103 ; limit - 1 mov [ebx], ax shr eax, 16 and al, 0x0F mov [ebx+6], al mov byte [ebx+5], 0x89 pop ebx pop ebp ret ; void clear_tss(unsigned int n) clear_tss: push ebp mov ebp, esp push ebx mov ebx, [ebp+8] shl ebx, 3 add ebx, gdt+40 mov byte [ebx+5], 0 pop ebx pop ebp ret