summaryrefslogtreecommitdiff
path: root/kernel/sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sched.c')
-rw-r--r--kernel/sched.c131
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);
+}