rev |
line source |
nuclear@52
|
1 #include <stdio.h>
|
nuclear@47
|
2 #include <string.h>
|
nuclear@52
|
3 #include <assert.h>
|
nuclear@42
|
4 #include "proc.h"
|
nuclear@42
|
5 #include "tss.h"
|
nuclear@45
|
6 #include "vm.h"
|
nuclear@47
|
7 #include "segm.h"
|
nuclear@47
|
8 #include "intr.h"
|
nuclear@47
|
9 #include "panic.h"
|
nuclear@51
|
10 #include "syscall.h"
|
nuclear@51
|
11 #include "sched.h"
|
nuclear@47
|
12
|
nuclear@52
|
13 #define FLAGS_INTR_BIT 9
|
nuclear@47
|
14
|
nuclear@47
|
15 /* defined in test_proc.S */
|
nuclear@47
|
16 void test_proc(void);
|
nuclear@47
|
17 void test_proc_end(void);
|
nuclear@42
|
18
|
nuclear@42
|
19 static struct process proc[MAX_PROC];
|
nuclear@42
|
20 static int cur_pid;
|
nuclear@42
|
21
|
nuclear@42
|
22 void init_proc(void)
|
nuclear@42
|
23 {
|
nuclear@47
|
24 int proc_size_pg, img_start_pg, stack_pg;
|
nuclear@45
|
25 void *img_start;
|
nuclear@51
|
26 cur_pid = 0;
|
nuclear@51
|
27
|
nuclear@51
|
28 init_syscall();
|
nuclear@42
|
29
|
nuclear@42
|
30 /* prepare the first process */
|
nuclear@51
|
31 proc[1].id = 1;
|
nuclear@51
|
32 proc[1].parent = 0;
|
nuclear@42
|
33
|
nuclear@42
|
34 /* allocate a chunk of memory for the process image
|
nuclear@42
|
35 * and copy the code of test_proc there.
|
nuclear@42
|
36 * (should be mapped at a fixed address)
|
nuclear@42
|
37 */
|
nuclear@51
|
38 proc_size_pg = (test_proc_end - test_proc) / PGSIZE + 1;
|
nuclear@45
|
39 if((img_start_pg = pgalloc(proc_size_pg, MEM_USER)) == -1) {
|
nuclear@45
|
40 panic("failed to allocate space for the init process image\n");
|
nuclear@45
|
41 }
|
nuclear@45
|
42 img_start = (void*)PAGE_TO_ADDR(img_start_pg);
|
nuclear@51
|
43 memcpy(img_start, test_proc, proc_size_pg * PGSIZE);
|
nuclear@45
|
44
|
nuclear@52
|
45 printf("copied init process at: %x\n", (unsigned int)img_start);
|
nuclear@52
|
46
|
nuclear@47
|
47 /* instruction pointer at the beginning of the process image */
|
nuclear@51
|
48 proc[1].ctx.instr_ptr = (uint32_t)img_start;
|
nuclear@47
|
49
|
nuclear@47
|
50 /* allocate the first page of the process stack */
|
nuclear@47
|
51 stack_pg = ADDR_TO_PAGE(KMEM_START) - 1;
|
nuclear@47
|
52 if(pgalloc_vrange(stack_pg, 1) == -1) {
|
nuclear@47
|
53 panic("failed to allocate user stack page\n");
|
nuclear@47
|
54 }
|
nuclear@51
|
55 proc[1].ctx.stack_ptr = PAGE_TO_ADDR(stack_pg) + PGSIZE;
|
nuclear@47
|
56
|
nuclear@52
|
57 proc[1].stack_end = KMEM_START;
|
nuclear@52
|
58 proc[1].stack_start = KMEM_START - PGSIZE;
|
nuclear@52
|
59
|
nuclear@45
|
60 /* create the virtual address space for this process */
|
nuclear@51
|
61 proc[1].ctx.pgtbl_paddr = clone_vm();
|
nuclear@45
|
62
|
nuclear@47
|
63 /* we don't need the image and the stack in this address space */
|
nuclear@51
|
64 unmap_page_range(img_start_pg, proc_size_pg);
|
nuclear@51
|
65 pgfree(img_start_pg, proc_size_pg);
|
nuclear@45
|
66
|
nuclear@47
|
67 unmap_page(stack_pg);
|
nuclear@47
|
68 pgfree(stack_pg, 1);
|
nuclear@42
|
69
|
nuclear@51
|
70 /* add it to the scheduler queues */
|
nuclear@52
|
71 add_proc(1, STATE_RUNNING);
|
nuclear@42
|
72
|
nuclear@51
|
73 /* switch to the initial process, this never returns */
|
nuclear@51
|
74 context_switch(1);
|
nuclear@42
|
75 }
|
nuclear@42
|
76
|
nuclear@47
|
77
|
nuclear@47
|
78 void context_switch(int pid)
|
nuclear@42
|
79 {
|
nuclear@52
|
80 struct context *ctx;
|
nuclear@47
|
81 struct intr_frame ifrm;
|
nuclear@52
|
82 struct intr_frame *cur_frame = get_intr_frame();
|
nuclear@47
|
83
|
nuclear@52
|
84 assert(0);
|
nuclear@49
|
85
|
nuclear@52
|
86 if(cur_pid == pid) {
|
nuclear@52
|
87 assert(cur_frame);
|
nuclear@52
|
88 intr_ret(*cur_frame);
|
nuclear@52
|
89 }
|
nuclear@52
|
90
|
nuclear@52
|
91 ctx = &proc[pid].ctx;
|
nuclear@47
|
92 cur_pid = pid;
|
nuclear@47
|
93
|
nuclear@47
|
94 ifrm.inum = ifrm.err = 0;
|
nuclear@47
|
95
|
nuclear@47
|
96 ifrm.regs = ctx->regs;
|
nuclear@52
|
97 ifrm.eflags = ctx->flags | (1 << FLAGS_INTR_BIT);
|
nuclear@47
|
98
|
nuclear@47
|
99 ifrm.eip = ctx->instr_ptr;
|
nuclear@49
|
100 ifrm.cs = selector(SEGM_KCODE, 0); /* XXX change this when we setup the TSS */
|
nuclear@52
|
101 /*ifrm.regs.esp = ctx->stack_ptr;*/ /* ... until then... */
|
nuclear@52
|
102 ifrm.esp = ctx->stack_ptr; /* this will only be used when we switch to userspace */
|
nuclear@52
|
103 ifrm.ss = selector(SEGM_KDATA, 0);
|
nuclear@47
|
104
|
nuclear@47
|
105 /* switch to the vm of the process */
|
nuclear@47
|
106 set_pgdir_addr(ctx->pgtbl_paddr);
|
nuclear@47
|
107 intr_ret(ifrm);
|
nuclear@47
|
108 }
|
nuclear@51
|
109
|
nuclear@51
|
110 int get_current_pid(void)
|
nuclear@51
|
111 {
|
nuclear@51
|
112 return cur_pid;
|
nuclear@51
|
113 }
|
nuclear@51
|
114
|
nuclear@51
|
115 struct process *get_current_proc(void)
|
nuclear@51
|
116 {
|
nuclear@51
|
117 return cur_pid ? &proc[cur_pid] : 0;
|
nuclear@51
|
118 }
|
nuclear@51
|
119
|
nuclear@51
|
120 struct process *get_process(int pid)
|
nuclear@51
|
121 {
|
nuclear@51
|
122 return &proc[pid];
|
nuclear@51
|
123 }
|