aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Auvolat <alex.auvolat@ens.fr>2014-12-07 20:11:06 +0100
committerAlex Auvolat <alex.auvolat@ens.fr>2014-12-07 20:11:06 +0100
commitbd1ed224590700c7568dd6a73a2dadcda238b1d5 (patch)
tree65d1204bfd1ef486529c314f3c9f942bd728e78e
parentf0475a3d517b4df8eb2b73f22eaec91a72bcc51f (diff)
downloadkogata-bd1ed224590700c7568dd6a73a2dadcda238b1d5.tar.gz
kogata-bd1ed224590700c7568dd6a73a2dadcda238b1d5.zip
Information about current PD now stored in current_task->current_pd_d
-rw-r--r--kernel/include/task.h4
-rw-r--r--kernel/l0/paging.c13
-rw-r--r--kernel/l0/task.c9
3 files changed, 18 insertions, 8 deletions
diff --git a/kernel/include/task.h b/kernel/include/task.h
index 8ba50b0..2c3f6ef 100644
--- a/kernel/include/task.h
+++ b/kernel/include/task.h
@@ -1,6 +1,7 @@
#pragma once
#include <sys.h>
+#include <paging.h>
#include <region.h>
#define T_STATE_RUNNING 1
@@ -9,6 +10,8 @@
#define KPROC_STACK_SIZE 0x8000 // 8Kb
+#define TASK_SWITCH_FREQUENCY 100 // in herz
+
typedef struct saved_context {
uint32_t *esp;
void (*eip)();
@@ -16,6 +19,7 @@ typedef struct saved_context {
typedef struct task {
saved_context_t ctx;
+ pagedir_t *current_pd_d;
uint32_t state;
void* result;
diff --git a/kernel/l0/paging.c b/kernel/l0/paging.c
index 3f38997..93cbc38 100644
--- a/kernel/l0/paging.c
+++ b/kernel/l0/paging.c
@@ -4,6 +4,7 @@
#include <dbglog.h>
#include <region.h>
#include <mutex.h>
+#include <task.h>
#define PAGE_OF_ADDR(x) (((size_t)x >> PAGE_SHIFT) % N_PAGES_IN_PT)
#define PT_OF_ADDR(x) ((size_t)x >> (PAGE_SHIFT + PT_SHIFT))
@@ -43,7 +44,6 @@ static pagetable_t __attribute__((aligned(PAGE_SIZE))) kernel_pt0;
extern char kernel_stack_protector;
static pagedir_t kernel_pd_d;
-static pagedir_t *current_pd_d;
#define current_pt ((pagetable_t*)PD_MIRROR_ADDR)
#define current_pd ((pagetable_t*)(PD_MIRROR_ADDR + (N_PAGES_IN_PT-1)*PAGE_SIZE))
@@ -85,7 +85,7 @@ void page_fault_handler(registers_t *regs) {
dbg_print_region_stats();
PANIC("Unhandled kernel space page fault");
}
- i->pf(current_pd_d, i, vaddr);
+ i->pf(get_current_pagedir(), i, vaddr);
} else {
if (regs->eflags & EFLAGS_IF) asm volatile("sti"); // userspace PF handlers should always be preemptible
@@ -131,7 +131,6 @@ void paging_setup(void* kernel_data_end) {
invlpg((void*)K_HIGHHALF_ADDR);
// paging already enabled in loader, nothing to do.
- switch_pagedir(&kernel_pd_d);
// disable 4M pages (remove PSE bit in CR4)
uint32_t cr4;
@@ -143,7 +142,8 @@ void paging_setup(void* kernel_data_end) {
}
pagedir_t *get_current_pagedir() {
- return current_pd_d;
+ if (current_task == 0) return &kernel_pd_d;
+ return current_task->current_pd_d;
}
pagedir_t *get_kernel_pagedir() {
@@ -152,7 +152,7 @@ pagedir_t *get_kernel_pagedir() {
void switch_pagedir(pagedir_t *pd) {
asm volatile("movl %0, %%cr3":: "r"(pd->phys_addr));
- current_pd_d = pd;
+ if (current_task != 0) current_task->current_pd_d = pd;
}
// ============================== //
@@ -176,7 +176,8 @@ int pd_map_page(void* vaddr, uint32_t frame_id, bool rw) {
ASSERT((size_t)vaddr < PD_MIRROR_ADDR);
- pagedir_t *pdd = ((size_t)vaddr >= K_HIGHHALF_ADDR ? &kernel_pd_d : current_pd_d);
+ pagedir_t *pdd = ((size_t)vaddr >= K_HIGHHALF_ADDR || current_task == 0
+ ? &kernel_pd_d : current_task->current_pd_d);
pagetable_t *pd = ((size_t)vaddr >= K_HIGHHALF_ADDR ? &kernel_pd : current_pd);
mutex_lock(&pdd->mutex);
diff --git a/kernel/l0/task.c b/kernel/l0/task.c
index e02dcf6..f8750e6 100644
--- a/kernel/l0/task.c
+++ b/kernel/l0/task.c
@@ -84,8 +84,10 @@ static void run_task(void (*entry)(void*)) {
ASSERT(current_task->state == T_STATE_RUNNING);
ASSERT(current_task->has_result);
- current_task->has_result = false;
+ switch_pagedir(get_kernel_pagedir());
+ current_task->has_result = false;
+
asm volatile("sti");
entry(current_task->result);
@@ -125,13 +127,15 @@ task_t *new_task(entry_t entry) {
t->result = 0;
t->has_result = false;
+ t->current_pd_d = get_kernel_pagedir();
+
t->more_data = 0;
return t;
}
void tasking_setup(entry_t cont, void* arg) {
- set_pit_frequency(100);
+ set_pit_frequency(TASK_SWITCH_FREQUENCY);
idt_set_irq_handler(IRQ0, yield);
task_t *t = new_task(cont);
@@ -146,6 +150,7 @@ void tasking_setup(entry_t cont, void* arg) {
void yield() {
if (current_task == 0) {
// might happen before tasking is initialized
+ // (but should not...)
dbg_printf("Warning: probable deadlock.");
} else {
save_context_and_enter_scheduler(&current_task->ctx);