Merge branch 'paging-fork' of https://github.com/stv0g/eduOS into stage6

This commit is contained in:
Stefan Lankes 2014-11-30 09:08:49 +01:00
commit 2245eaecbb
3 changed files with 107 additions and 3 deletions

View file

@ -58,6 +58,12 @@ static size_t* self[PAGE_LEVELS] = {
(size_t *) 0xFFFFF000
};
/** An other self-reference for page_map_copy() */
static size_t * other[PAGE_LEVELS] = {
(size_t *) 0xFF800000,
(size_t *) 0xFFFFE000
};
/* Addresses of child/parent tables */
#define CHILD(map, lvl, vpn) &map[lvl-1][vpn<<PAGE_MAP_BITS]
#define PARENT(map, lvl, vpn) &map[lvl+1][vpn>>PAGE_MAP_BITS]
@ -142,6 +148,77 @@ int page_unmap(size_t viraddr, size_t npages)
return 0;
}
int page_map_drop()
{
void traverse(int lvl, long vpn) {
kprintf("traverse(lvl=%d, vpn=%#lx)\n", lvl, vpn);
long stop;
for (stop=vpn+PAGE_MAP_ENTRIES; vpn<stop; vpn++) {
if (self[lvl][vpn] & PG_PRESENT) {
if (self[lvl][vpn] & PG_BOOT)
continue;
// ost-order traversal
if (lvl > 1)
traverse(lvl-1, vpn<<PAGE_MAP_BITS);
kprintf("%#lx, ", self[lvl][vpn] & PAGE_MASK);
//put_page(self[lvl][vpn] & PAGE_MASK);
atomic_int32_dec(&current_task->user_usage);
}
}
}
spinlock_irqsave_lock(&current_task->page_lock);
traverse(PAGE_LEVELS-1, 0);
spinlock_irqsave_unlock(&current_task->page_lock);
return 0;
}
int page_map_copy(size_t dest)
{
int traverse(int lvl, long vpn) {
long stop;
for (stop=vpn+PAGE_MAP_ENTRIES; vpn<stop; vpn++) {
if (self[lvl][vpn] & PG_PRESENT) {
size_t phyaddr = get_pages(1);
if (BUILTIN_EXPECT(phyaddr, 0))
return -ENOMEM;
other[lvl][vpn] = phyaddr;
other[lvl][vpn] |= self[lvl][vpn] & ~PAGE_MASK;
memcpy(CHILD(other, lvl, vpn), CHILD(self, lvl, vpn), PAGE_SIZE);
// pre-order traversal
if (lvl)
traverse(lvl-1, vpn<<PAGE_MAP_BITS);
}
}
return 0;
}
spinlock_lock(&kslock);
// create another temporary self-reference
self[PAGE_LEVELS-1][PAGE_MAP_ENTRIES-2] = dest | PG_PRESENT | PG_RW;
traverse(PAGE_LEVELS-1, 0);
// remove temporary self-reference
self[PAGE_LEVELS-1][PAGE_MAP_ENTRIES-2] = 0;
spinlock_unlock(&kslock);
return 0;
}
void page_fault_handler(struct state *s)
{
size_t viraddr = read_cr2();

View file

@ -39,7 +39,9 @@
#include <eduos/stddef.h>
#include <eduos/spinlock_types.h>
#include <asm/tasks_types.h>
#include <asm/atomic.h>
#ifdef __cplusplus
extern "C" {
@ -73,6 +75,12 @@ typedef struct task {
void* stack;
/// Task priority
uint8_t prio;
/// Physical address of root page table
size_t page_map;
/// Lock for page tables
spinlock_irqsave_t page_lock;
/// usage in number of pages (including page map tables)
atomic_int32_t user_usage;
/// next task in the queue
struct task* next;
/// previous task in the queue

View file

@ -34,14 +34,17 @@
#include <eduos/spinlock.h>
#include <eduos/errno.h>
#include <eduos/syscall.h>
#include <eduos/memory.h>
#include <asm/page.h>
/** @brief Array of task structures (aka PCB)
*
* A task's id will be its position in this array.
*/
static task_t task_table[MAX_TASKS] = { \
[0] = {0, TASK_IDLE, NULL, NULL, 0, NULL, NULL}, \
[1 ... MAX_TASKS-1] = {0, TASK_INVALID, NULL, NULL, 0, NULL, NULL}};
[0] = {0, TASK_IDLE, NULL, NULL, 0, 0, SPINLOCK_IRQSAVE_INIT, ATOMIC_INIT(0), NULL, NULL}, \
[1 ... MAX_TASKS-1] = {0, TASK_INVALID, NULL, NULL, 0, 0, SPINLOCK_IRQSAVE_INIT, ATOMIC_INIT(0), NULL, NULL}};
static spinlock_irqsave_t table_lock = SPINLOCK_IRQSAVE_INIT;
@ -53,7 +56,7 @@ extern const void boot_stack;
/** @brief helper function for the assembly code to determine the current task
* @return Pointer to the task_t structure of current task
*/
task_t* get_current_task(void)
task_t* get_current_task(void)
{
return current_task;
}
@ -118,6 +121,8 @@ static void NORETURN do_exit(int arg)
kprintf("Terminate task: %u, return value %d\n", curr_task->id, arg);
page_map_drop();
curr_task->status = TASK_FINISHED;
reschedule();
@ -160,6 +165,8 @@ void NORETURN abort(void) {
}
/** @brief Create a task with a specific entry point
*
* @todo Dont aquire table_lock for the whole task creation.
*
* @param id Pointer to a tid_t struct were the id shall be set
* @param ep Pointer to the function the task shall start with
@ -193,6 +200,17 @@ static int create_task(tid_t* id, entry_point_t ep, void* arg, uint8_t prio)
task_table[i].stack = create_stack(i);
task_table[i].prio = prio;
spinlock_irqsave_init(&task_table[i].page_lock);
atomic_int32_set(&task_table[i].user_usage, 0);
/* Allocated new PGD or PML4 and copy page table */
size_t map = get_pages(1);
if (BUILTIN_EXPECT(map, 0))
goto out;
page_map_copy(map);
task_table[i].page_map = map;
if (id)
*id = i;
@ -217,6 +235,7 @@ static int create_task(tid_t* id, entry_point_t ep, void* arg, uint8_t prio)
}
}
out:
spinlock_irqsave_unlock(&table_lock);
return ret;