Fix paging #PF, simplify init_tasks
Unsure what fixed the paging #PF in init_tasks, but allocating a page
now works as expected. Originally a #PF would occur if alloc_page was
called after a certain point in init_tasks.
diff --git a/src/kernel/x86_32/task.c b/src/kernel/x86_32/task.c
index 1ec1337..2f8c3a8 100644
--- a/src/kernel/x86_32/task.c
+++ b/src/kernel/x86_32/task.c
@@ -5,28 +5,14 @@
#include "paging.h"
#include "pic.h"
-struct process processes[1024] = {0};
-struct ll_task_i *first_task = NULL, *last_task = NULL, *current_task = NULL;
+static struct process processes[1024] = {0};
+static struct ll_task_i *first_task = NULL, *last_task = NULL, *current_task = NULL;
static uint next_task_id = 0;
bool tasks_initialized = false;
-void _init_tasks(struct registers *regs);
-
void init_tasks()
{
- add_interrupt_handler(INIT_TASKS_INTERRUPT, _sys_init_tasks_h);
-
- asm("int $0x81");
-}
-
-void _sys_init_tasks_h(struct registers *regs)
-{
- _init_tasks(regs);
-}
-
-void _init_tasks(struct registers *regs)
-{
processes[0] = (struct process){
.exists = true,
.id = 0,
@@ -49,9 +35,12 @@
first_task->next = NULL;
first_task->prev = NULL;
memset(&first_task->task, 0, sizeof(struct task));
+ // state will be filled in upon task switch. TODO: task switch
+ // before spawning thread (or fill in CS, etc manually) to avoid
+ // #GP on task switch. New threads based on parent task
first_task->task = (struct task){
.proc = &processes[0],
- .state = *regs,
+ .state = { 0 },
.id = next_task_id++,
.waiting = false,
};
@@ -89,17 +78,18 @@
// Virtual location of new stack, with space reserved for argument
// and return address to kill_this_thread().
- uint new_stack_base_v = proc->last_stack_pos;
+ uint *new_stack_base_v = (uint *)proc->last_stack_pos;
proc->last_stack_pos -= 0x1000;
// Alloc a new page in the current process mapping to the new stack
alloc_page(dir_v, (void *)proc->last_stack_pos);
- kprintf(INFO "new_stack_base_v = %p\n", new_stack_base_v);
- new_stack_base_v -= sizeof(uint);
- *((uint *)new_stack_base_v) = (size_t)data;
- new_stack_base_v -= sizeof(uint);
- *((uint *)new_stack_base_v) = (size_t)&kill_this_thread;
+ kprintf(INFO "new_stack_base_v = %p, last_stack_pos = %p\n",
+ new_stack_base_v, proc->last_stack_pos);
+
+ // Write data argument and return pointer to new threads stack
+ new_stack_base_v[-1] = (size_t)data;
+ new_stack_base_v[-2] = (size_t)&kill_this_thread;
kprintf(DEBUG "Set stack\n");
@@ -113,7 +103,7 @@
// Namely a new TID
task->id = next_task_id++;
// And stack, frame, and instruction pointers
- task->state.ebp = task->state.esp = new_stack_base_v;
+ task->state.ebp = task->state.esp = (uint)(new_stack_base_v - 2);
task->state.eip = (uint)function;
task->waiting = false;
@@ -162,6 +152,8 @@
asm("sti");
}
+extern uint _get_cr3();
+
extern void _switch_to_task(uint page_directory, struct registers ctx);
#if 0
{
@@ -174,6 +166,8 @@
void switch_to_task(struct task *task)
{
+ kprintf(DEBUG "switch_to_task cr3=0x%x\n", task->proc->page_directory_p);
+
_switch_to_task(task->proc->page_directory_p, task->state);
__builtin_unreachable();
}
@@ -183,7 +177,9 @@
// Resetting eflags in _switch_to_task iret will switch this back
asm("cli");
- kprintf(DEBUG "switching tasks\n");
+ kprintf(DEBUG "switching tasks, alleged cr3=0x%x, real cr3=0x%x\n",
+ current_task->task.proc->page_directory_p,
+ _get_cr3());
// save context for this task
current_task->task.state = regs;