diff options
| author | Jake Mannens <jake72360@gmail.com> | 2018-07-11 00:18:49 +1000 |
|---|---|---|
| committer | Jake Mannens <jake72360@gmail.com> | 2018-07-11 00:18:49 +1000 |
| commit | 99d16e98e04c73e108160d7d70244bafdb33b6fc (patch) | |
| tree | 4bdd78c2340e4c9ff2a875ad07908b5f258357fc /kernel/asm.s | |
| parent | b99a1b58d63dfefb319eecb564c07a4029e02233 (diff) | |
Implemented a basic scheduler using an array of task structures in which
each structure has a TSS inside, as well as several descriptor entries
in the GDT pointing to each task's TSS. Task switching is performed in
hardware by means of far jumping to the new task's TSS descriptor in the
GDT. Task states are saved manually by copying the saved state from the
interrupt handler's stack, back into the task's TSS.
Added the function save_state() to sched.c which can be called from
assembly to copy the state information of the suspended task from the
current stack, to it's respective task structure. NOTE: this assumes
that the pointer cstate has been set ahead of time to point to the state
information on the stack, and that the pointer ctask has not yet been
modified.
Added the function reschedule() which is currently called from the
timer's tick handler. Currently, this function merely alternates between
the two tasks created in sched_init(), but in future, will be expanded
to decided independently which task will run next.
The function userspace_init() was renamed to the more appropriate
sched_init().
Moved most of the code from the original userspace_init() to the new
function create_proc() which sets up a virtual address space and state
information, copies the specified binary into the new address space,
then returns a pointer to the newly created tasks entry in the task
table.
Defined the type pid_t in unistd.h as a 16-bit unsigned integer.
Added two new debugging system calls for checking which task is
currently active. The getpid() system calls returns the caller's PID
whilst the getpdir() call returns the physical location of the caller's
page directory (the value of CR3). The getpdir() call can be used as a
fallback to determine which task is *actually* running if the
information in ctask or the getpid() call is faulty.
Added two new subroutines; set_tss() and clear_tss() (whose prototypes
are defined in asm/system.h) for managing the task-state descriptor
entries in the GDT. set_tss() initializes a TSS descriptor and sets it's
base pointer to the supplied TSS pointer whilst clear_tss() simply marks
a TSS descriptor as 'not present' without clearing it.
Diffstat (limited to 'kernel/asm.s')
| -rw-r--r-- | kernel/asm.s | 120 |
1 files changed, 68 insertions, 52 deletions
diff --git a/kernel/asm.s b/kernel/asm.s index 4abe607..0bf9067 100644 --- a/kernel/asm.s +++ b/kernel/asm.s @@ -1,60 +1,76 @@ +global clear_tss global switch_to +global set_tss +extern cstate extern ctask -extern tss +extern gdt +extern save_state +; void switch_to(int n, struct task_struct *task); switch_to: push ebp mov ebp, esp - mov eax, [ebp+8] - mov [ctask], eax - mov esi, [ebp+12] - mov ecx, 13 -.loop: - lodsd - push eax - dec ecx - jz .end - jmp .loop -.end: - mov ax, 0x23 - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - popa - iret + ; abort if we're switching to the current task + mov ebx, [ctask] + cmp ebx, [ebp+12] + jne .skip + pop ebp + ret +.skip: + ; clear the busy flag in the current TSS + mov eax, 0 + str ax + add ax, gdt+5 + mov byte [eax], 0x89 + ; set the current TSS to null so it won't be overwritten by the switch + mov ax, 0 + ltr ax + ; copy the saved state into the previous TSS + call save_state + ; update ctask + mov ebx, [ebp+12] + mov [ctask], 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] +.tmp: + dq 0 -; uint32_t ss; -; uint32_t esp; -; uint32_t eflags; -; uint32_t cs; -; uint32_t eip; -; uint32_t eax; -; uint32_t ecx; -; uint32_t edx; -; uint32_t ebx; -; uint32_t esp_garbage; -; uint32_t ebp; -; uint32_t esi; -; uint32_t edi; +; 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 -; switch_to: - ; push ebp - ; mov ebp, esp - ; cli - ; mov ax, 0x23 - ; mov ds, ax - ; mov es, ax - ; mov fs, ax - ; mov gs, ax - ; mov eax, esp - ; ; save ESP in the TSS - ; mov [tss+4], eax - ; push dword 0x23 - ; push dword 0x00180000 - ; pushf - ; push dword 0x1B - ; push dword 0x00100000 - ; iret - ; 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 |
