This source file includes following definitions.
- verify_area
- copy_mem
- find_empty_process
- sys_fork
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <errno.h>
14
15 #include <linux/sched.h>
16 #include <linux/kernel.h>
17 #include <asm/segment.h>
18 #include <asm/system.h>
19
20 extern void write_verify(unsigned long address);
21
22 long last_pid=0;
23
24 void verify_area(void * addr,int size)
25 {
26 unsigned long start;
27
28 start = (unsigned long) addr;
29 size += start & 0xfff;
30 start &= 0xfffff000;
31 start += get_base(current->ldt[2]);
32 while (size>0) {
33 size -= 4096;
34 write_verify(start);
35 start += 4096;
36 }
37 }
38
39 int copy_mem(int nr,struct task_struct * p)
40 {
41 unsigned long old_data_base,new_data_base,data_limit;
42 unsigned long old_code_base,new_code_base,code_limit;
43
44 code_limit=get_limit(0x0f);
45 data_limit=get_limit(0x17);
46 old_code_base = get_base(current->ldt[1]);
47 old_data_base = get_base(current->ldt[2]);
48 if (old_data_base != old_code_base) {
49 printk("ldt[0]: %08x %08x\n",current->ldt[0].a,current->ldt[0].b);
50 printk("ldt[1]: %08x %08x\n",current->ldt[1].a,current->ldt[1].b);
51 printk("ldt[2]: %08x %08x\n",current->ldt[2].a,current->ldt[2].b);
52 panic("We don't support separate I&D");
53 }
54 if (data_limit < code_limit)
55 panic("Bad data_limit");
56 new_data_base = new_code_base = nr * TASK_SIZE;
57 p->start_code = new_code_base;
58 set_base(p->ldt[1],new_code_base);
59 set_base(p->ldt[2],new_data_base);
60 if (copy_page_tables(old_data_base,new_data_base,data_limit)) {
61 free_page_tables(new_data_base,data_limit);
62 return -ENOMEM;
63 }
64 return 0;
65 }
66
67 static int find_empty_process(void)
68 {
69 int i;
70
71 repeat:
72 if ((++last_pid)<0) last_pid=1;
73 for(i=0 ; i<NR_TASKS ; i++)
74 if (task[i] && ((task[i]->pid == last_pid) ||
75 (task[i]->pgrp == last_pid)))
76 goto repeat;
77 for(i=1 ; i<NR_TASKS ; i++)
78 if (!task[i])
79 return i;
80 return -EAGAIN;
81 }
82
83
84
85
86
87
88 int sys_fork(long ebx,long ecx,long edx,
89 long esi, long edi, long ebp, long eax, long ds,
90 long es, long fs, long gs, long orig_eax,
91 long eip,long cs,long eflags,long esp,long ss)
92 {
93 struct task_struct *p;
94 int i,nr;
95 struct file *f;
96
97 p = (struct task_struct *) get_free_page();
98 if (!p)
99 return -EAGAIN;
100 nr = find_empty_process();
101 if (nr < 0) {
102 free_page((unsigned long) p);
103 return nr;
104 }
105 task[nr] = p;
106 *p = *current;
107 p->state = TASK_UNINTERRUPTIBLE;
108 p->pid = last_pid;
109 p->counter = p->priority;
110 p->signal = 0;
111 p->alarm = 0;
112 p->leader = 0;
113 p->utime = p->stime = 0;
114 p->cutime = p->cstime = 0;
115 p->min_flt = p->maj_flt = 0;
116 p->cmin_flt = p->cmaj_flt = 0;
117 p->start_time = jiffies;
118 p->tss.back_link = 0;
119 p->tss.esp0 = PAGE_SIZE + (long) p;
120 p->tss.ss0 = 0x10;
121 p->tss.eip = eip;
122 p->tss.eflags = eflags;
123 p->tss.eax = 0;
124 p->tss.ecx = ecx;
125 p->tss.edx = edx;
126 p->tss.ebx = ebx;
127 p->tss.esp = esp;
128 p->tss.ebp = ebp;
129 p->tss.esi = esi;
130 p->tss.edi = edi;
131 p->tss.es = es & 0xffff;
132 p->tss.cs = cs & 0xffff;
133 p->tss.ss = ss & 0xffff;
134 p->tss.ds = ds & 0xffff;
135 p->tss.fs = fs & 0xffff;
136 p->tss.gs = gs & 0xffff;
137 p->tss.ldt = _LDT(nr);
138 p->tss.trace_bitmap = 0x80000000;
139 if (last_task_used_math == current)
140 __asm__("clts ; fnsave %0 ; frstor %0"::"m" (p->tss.i387));
141 if (copy_mem(nr,p)) {
142 task[nr] = NULL;
143 free_page((long) p);
144 return -EAGAIN;
145 }
146 for (i=0; i<NR_OPEN;i++)
147 if (f=p->filp[i])
148 f->f_count++;
149 if (current->pwd)
150 current->pwd->i_count++;
151 if (current->root)
152 current->root->i_count++;
153 if (current->executable)
154 current->executable->i_count++;
155 if (current->library)
156 current->library->i_count++;
157 set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));
158 set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt));
159 p->p_pptr = current;
160 p->p_cptr = 0;
161 p->p_ysptr = 0;
162 p->p_osptr = current->p_cptr;
163 if (p->p_osptr)
164 p->p_osptr->p_ysptr = p;
165 current->p_cptr = p;
166 p->state = TASK_RUNNING;
167 return p->pid;
168 }