diff options
Diffstat (limited to 'kernel/sched.c')
| -rw-r--r-- | kernel/sched.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/kernel/sched.c b/kernel/sched.c new file mode 100644 index 0000000..f0b79fc --- /dev/null +++ b/kernel/sched.c @@ -0,0 +1,131 @@ +#include <asm/system.h> +#include <kernel/con.h> +#include <kernel/memory.h> +#include <kernel/sched.h> +#include <string.h> +#include <sys/types.h> + +#define USRSTART ((void*) 0x40000000) + +#define pages(n) \ + ((n / 4096) + 1) + +#define tables(n) \ + ((n / 1024) + 1) + +#define getpage(name, p) ({\ + void **_next; \ + _next = map_page(p); \ + name = p; \ + p = *_next; \ + }) + +extern char _usrbin_start; +extern char _usrbin_size; + +struct task_struct *ctask; + +static struct task_struct task; + +static inline void empty_table(void *t) { + int i; + + for(i = 0; i < PGENT; i++) + ((uint32_t*) t)[i] = 0; +} + +void userspace_init(void) { + int i, j; + int c; + size_t totpages, npages, ntables; + void *p, *page, *tab, *map; + void *pdir, *stackt, *stackp; + + size_t usrsize = (size_t) &_usrbin_size; + + npages = pages(usrsize); + ntables = tables(pages(usrsize)); + totpages = npages + ntables + 3; + + /* here we allocate pages to setup the process' + * address space. in addition to the pages that + * will hold the binary image, the following + * pages are allocated: + * - page directory (1 page) + * - page tables + * - stack page (1 page) + * - stack table (1 page) + */ + p = alloc_physical_pages(totpages); + printf("Allocating %x pages for userspace process\n", totpages); + if(p == NULL) { + printf("Failed to allocate memory for userspace!\n"); + return; + } + + getpage(pdir, p); + getpage(stackt, p); + getpage(stackp, p); + printf(" Page directory: 0x%08x\n", (uint32_t) pdir); + printf(" Stack table: 0x%08x\n", (uint32_t) stackt); + printf(" Stack page: 0x%08x\n", (uint32_t) stackp); + printf(" Page tables:\n"); + + /* populate the page directory */ + c = npages; + map = map_page(pdir); + empty_table(map); + for(i = 0; i < ntables; i++) { + /* add the table entry to the directory */ + getpage(tab, p); + printf(" 0x%08x\n", (uint32_t) tab); + map = map_page(pdir); + ((uint32_t*) map)[i + (PGENT / 4)] = (uint32_t) tab | 0x007; + + /* populate the page table */ + map = map_page(tab); + for(j = 0; j < PGENT; j++) { + ((uint32_t*) map)[j] = 0; + if(c <= 0) + continue; + + getpage(page, p); + map = map_page(tab); + ((uint32_t*) map)[j] = (uint32_t) page | 0x007; + c--; + } + } + + /* populate the stack table */ + map = map_page(stackt); + empty_table(map); + ((uint32_t*) map)[PGENT - 1] = (uint32_t) stackp | 0x007; + + /* add the stack page table to the directory */ + map = map_page(pdir); + ((uint32_t*) map)[PGENT - 1] = (uint32_t) stackt | 0x007; + /* add the kernel's page table to the directory */ + ((uint32_t*) map)[0] = (uint32_t) ktab | 0x003; + + __asm__ volatile ("mov %%eax, %%cr3" :: "a" (pdir)); + + memcpy(USRSTART, &_usrbin_start, usrsize); + + /* + * here we initialize the task struct. + * currently, we only setup state information + * necessary to begin execution. + */ + memset(&task, 0, sizeof(task)); + task.state.cs = 0x1B; + task.state.ss = 0x23; + task.state.eip = (uint32_t) USRSTART; + task.state.esp = 0xFFFFFFFF; + __asm__ ( + "pushf\n" \ + "pop %%eax" \ + : "=a" (task.state.eflags) \ + ::); + + switch_to(&task, &task.state); +} |
