#include #include #include #include #include #include #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); printk("Allocating %x pages for userspace process\n", totpages); if(p == NULL) { printk("Failed to allocate memory for userspace!\n"); return; } getpage(pdir, p); getpage(stackt, p); getpage(stackp, p); printk(" Page directory: 0x%08x\n", (uint32_t) pdir); printk(" Stack table: 0x%08x\n", (uint32_t) stackt); printk(" Stack page: 0x%08x\n", (uint32_t) stackp); printk(" 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); printk(" 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); }