rev |
line source |
nuclear@47
|
1 #include <string.h>
|
nuclear@42
|
2 #include "proc.h"
|
nuclear@42
|
3 #include "tss.h"
|
nuclear@45
|
4 #include "vm.h"
|
nuclear@47
|
5 #include "segm.h"
|
nuclear@47
|
6 #include "intr.h"
|
nuclear@47
|
7 #include "panic.h"
|
nuclear@47
|
8
|
nuclear@47
|
9
|
nuclear@47
|
10 /* defined in test_proc.S */
|
nuclear@47
|
11 void test_proc(void);
|
nuclear@47
|
12 void test_proc_end(void);
|
nuclear@42
|
13
|
nuclear@42
|
14 static struct process proc[MAX_PROC];
|
nuclear@42
|
15 static int cur_pid;
|
nuclear@42
|
16
|
nuclear@42
|
17 void init_proc(void)
|
nuclear@42
|
18 {
|
nuclear@47
|
19 int proc_size_pg, img_start_pg, stack_pg;
|
nuclear@45
|
20 void *img_start;
|
nuclear@42
|
21 cur_pid = -1;
|
nuclear@42
|
22
|
nuclear@42
|
23 /* prepare the first process */
|
nuclear@42
|
24
|
nuclear@42
|
25 /* allocate a chunk of memory for the process image
|
nuclear@42
|
26 * and copy the code of test_proc there.
|
nuclear@42
|
27 * (should be mapped at a fixed address)
|
nuclear@42
|
28 */
|
nuclear@49
|
29 /*proc_size_pg = (test_proc_end - test_proc) / PGSIZE + 1;
|
nuclear@45
|
30 if((img_start_pg = pgalloc(proc_size_pg, MEM_USER)) == -1) {
|
nuclear@45
|
31 panic("failed to allocate space for the init process image\n");
|
nuclear@45
|
32 }
|
nuclear@45
|
33 img_start = (void*)PAGE_TO_ADDR(img_start_pg);
|
nuclear@49
|
34 memcpy(img_start, test_proc, proc_size_pg * PGSIZE);*/
|
nuclear@49
|
35 img_start = test_proc;
|
nuclear@45
|
36
|
nuclear@47
|
37 /* instruction pointer at the beginning of the process image */
|
nuclear@47
|
38 proc[0].ctx.instr_ptr = (uint32_t)img_start;
|
nuclear@47
|
39
|
nuclear@47
|
40 /* allocate the first page of the process stack */
|
nuclear@47
|
41 stack_pg = ADDR_TO_PAGE(KMEM_START) - 1;
|
nuclear@47
|
42 if(pgalloc_vrange(stack_pg, 1) == -1) {
|
nuclear@47
|
43 panic("failed to allocate user stack page\n");
|
nuclear@47
|
44 }
|
nuclear@47
|
45 proc[0].ctx.stack_ptr = PAGE_TO_ADDR(stack_pg) + PGSIZE;
|
nuclear@47
|
46
|
nuclear@45
|
47 /* create the virtual address space for this process */
|
nuclear@47
|
48 proc[0].ctx.pgtbl_paddr = clone_vm();
|
nuclear@45
|
49
|
nuclear@47
|
50 /* we don't need the image and the stack in this address space */
|
nuclear@49
|
51 /*unmap_page_range(img_start_pg, proc_size_pg);
|
nuclear@49
|
52 pgfree(img_start_pg, proc_size_pg);*/
|
nuclear@45
|
53
|
nuclear@47
|
54 unmap_page(stack_pg);
|
nuclear@47
|
55 pgfree(stack_pg, 1);
|
nuclear@42
|
56
|
nuclear@42
|
57
|
nuclear@42
|
58 /* switch to it by calling a function that takes the context
|
nuclear@42
|
59 * of the current process, plugs the values into the interrupt
|
nuclear@42
|
60 * stack, and calls iret.
|
nuclear@42
|
61 * (should also set ss0/sp0 in TSS before returning)
|
nuclear@42
|
62 */
|
nuclear@47
|
63 context_switch(0);
|
nuclear@47
|
64 /* XXX this will never return */
|
nuclear@42
|
65 }
|
nuclear@42
|
66
|
nuclear@47
|
67
|
nuclear@47
|
68 void context_switch(int pid)
|
nuclear@42
|
69 {
|
nuclear@47
|
70 struct intr_frame ifrm;
|
nuclear@47
|
71 struct context *ctx = &proc[pid].ctx;
|
nuclear@47
|
72
|
nuclear@49
|
73
|
nuclear@47
|
74 cur_pid = pid;
|
nuclear@47
|
75
|
nuclear@47
|
76 ifrm.inum = ifrm.err = 0;
|
nuclear@47
|
77
|
nuclear@47
|
78 ifrm.regs = ctx->regs;
|
nuclear@47
|
79 ifrm.eflags = ctx->flags;
|
nuclear@47
|
80
|
nuclear@49
|
81 ifrm.err = 0xbadf00d;
|
nuclear@49
|
82
|
nuclear@49
|
83 asm volatile (
|
nuclear@49
|
84 "pushf\n\t"
|
nuclear@49
|
85 "popl %0\n\t"
|
nuclear@49
|
86 : "=a" (ifrm.eflags)
|
nuclear@49
|
87 );
|
nuclear@49
|
88
|
nuclear@47
|
89 ifrm.eip = ctx->instr_ptr;
|
nuclear@49
|
90 ifrm.cs = selector(SEGM_KCODE, 0); /* XXX change this when we setup the TSS */
|
nuclear@49
|
91 ifrm.esp = 0;/*ctx->stack_ptr; /* this will only be used when we switch to userspace */
|
nuclear@49
|
92 ifrm.regs.esp = ctx->stack_ptr; /* ... until then... */
|
nuclear@49
|
93 ifrm.ss = 0;/*selector(SEGM_KDATA, 0); /* XXX */
|
nuclear@47
|
94
|
nuclear@47
|
95 /* switch to the vm of the process */
|
nuclear@47
|
96 set_pgdir_addr(ctx->pgtbl_paddr);
|
nuclear@47
|
97
|
nuclear@47
|
98 intr_ret(ifrm);
|
nuclear@47
|
99 }
|