summaryrefslogtreecommitdiff
path: root/kernel/sched.c
diff options
context:
space:
mode:
authorJake Mannens <jake72360@gmail.com>2018-07-07 20:19:23 +1000
committerJake Mannens <jake72360@gmail.com>2018-07-07 20:19:23 +1000
commitec4f58e8e362e371718f656923c2d234f8ac215c (patch)
treeb84655b06de314c13007382b53a0f624cef2df6b /kernel/sched.c
parentfbbcb04f9e3197976d6ab4a79c45aa0a84e39aba (diff)
Added '-g' flag for GCC to all makefiles to ensure debugging information
is produced. This may change later. Added the new directory 'lib' to the source tree which build lib.a, an archive containing common library routines for both the kernel and userspace code to use. Added the file string.c to the lib directory (as well as the appropriate headers in /include) which provides some basic functions from the standard C string library. Added a physical memory manager which is now located in memory.c. This memory manager tracks free pages from 1MB-8MB with a simple table and allocates memory in blocks of 4KB pages. Multiple pages can be allocated in which they are returned as a linked list. Added a 'page window' in memory.c which allows the temporary mapping of a single page at a time into the current address space. Moved all paging routines that were previously located in page.s over to memory.c where they have been re-implemented as a mixture of C and inline assembly. Moved the primative userspace routines from usrspace.s over to the new sched.c. The only remaining routine, usrcall is now located in asm.s as 'switch_to' which takes two arguments, pointers to the task structure and task state structure of the new task which is being switched to. Pages for userspace are now allocated dynamically. The user binary is loaded in at 1GB upwards. The user stack is located at the end of the 4GB address space with the lower 1GB being reserved for the kernel. Updated the link.ld file for the userspace binary to include the new starting address 0x40000000 (1GB). Renamed the symbols for the user binary blob to make them shorter.
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);
+}