001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020 #include <sos/types.h>
021 #include <sos/klibc.h>
022 #include <drivers/bochs.h>
023 #include <sos/physmem.h>
024 #include <sos/assert.h>
025
026 #include <sos/process.h>
027 #include <sos/thread.h>
028
029
030
031
032
033
034
035
036
037
038
039
040
041 struct userprog_entry
042 {
043 const char *name;
044 sos_vaddr_t bottom_vaddr;
045 sos_vaddr_t top_vaddr;
046 };
047
048
049
050
051
052
053 extern char _userprogs_table;
054
055
056
057
058
059
060
061
062
063
064 static struct userprog_entry * lookup_userprog(const char *name);
065
066
067
068
069
070
071
072
073
074
075
076 static sos_uaddr_t load_elf_prog(const struct userprog_entry *prog);
077
078
079
080
081
082
083
084 static sos_ret_t spawn_program(const char *progname,
085 unsigned nb_uthreads);
086
087
088
089
090
091 void test_art7()
092 {
093 spawn_program("myprog5", 5);
094 spawn_program("myprog1", 10);
095 spawn_program("myprog5", 1);
096 spawn_program("myprog6", 12);
097 spawn_program("myprog2", 10);
098 spawn_program("myprog5", 1);
099 spawn_program("myprog3", 10);
100 spawn_program("myprog5", 1);
101 spawn_program("myprog1", 10);
102 spawn_program("myprog6", 12);
103 spawn_program("myprog5", 1);
104 spawn_program("myprog4", 10);
105 spawn_program("myprog5", 1);
106 spawn_program("myprog2", 10);
107 spawn_program("myprog6", 12);
108 spawn_program("myprog5", 1);
109 }
110
111
112 static sos_ret_t spawn_program(const char *progname,
113 unsigned nb_uthreads)
114 {
115 int i;
116
117 sos_uaddr_t prog_entry, stack_top_uaddr;
118 struct userprog_entry *prog;
119 struct sos_process *new_proc;
120
121 prog = lookup_userprog(progname);
122 if (! prog)
123 return -SOS_EINVAL;
124
125 new_proc = sos_process_create_empty(progname);
126 if (! new_proc)
127 return -SOS_ENOMEM;
128
129
130 SOS_ASSERT_FATAL(SOS_OK
131 == sos_thread_change_current_mm_context(sos_process_get_mm_context(new_proc)));
132
133
134 prog_entry = load_elf_prog(prog);
135 if (! prog_entry)
136 {
137 sos_process_unref(new_proc);
138 return -SOS_ENOMEM;
139 }
140
141
142
143
144
145
146 #define USTACK_NPAGES 8
147 for (i = 0, stack_top_uaddr = 0xfffffffc ;
148 i < nb_uthreads ;
149 i++, stack_top_uaddr -= (USTACK_NPAGES + 4)*SOS_PAGE_SIZE)
150 {
151 int p;
152 char thrname[16];
153 sos_uaddr_t stack_base = SOS_PAGE_ALIGN_INF(stack_top_uaddr);
154
155
156 for (p = 0 ; p < USTACK_NPAGES ; p++, stack_base -= SOS_PAGE_SIZE)
157 {
158 sos_ret_t retval;
159 sos_paddr_t ppage;
160
161 ppage = sos_physmem_ref_physpage_new(FALSE);
162 SOS_ASSERT_FATAL(ppage != 0);
163
164
165
166 retval = sos_paging_map(ppage, stack_base, TRUE,
167 SOS_VM_MAP_PROT_READ
168 | SOS_VM_MAP_PROT_WRITE);
169 SOS_ASSERT_FATAL(retval == SOS_OK);
170
171 retval = sos_physmem_unref_physpage(ppage);
172 SOS_ASSERT_FATAL(retval == 0);
173
174
175
176 memset((void*)stack_base, 0xa5, SOS_PAGE_SIZE);
177 }
178
179
180 snprintf(thrname, sizeof(thrname), "%s:%d", progname, i);
181 sos_bochs_printf("Spawning %s\n", thrname);
182 sos_create_user_thread(thrname,
183 new_proc,
184 prog_entry,
185 0, 0,
186 stack_top_uaddr,
187 SOS_SCHED_PRIO_TS_LOWEST);
188
189 sos_thread_yield();
190 }
191
192
193 sos_process_unref(new_proc);
194
195
196 SOS_ASSERT_FATAL(SOS_OK
197 == sos_thread_change_current_mm_context(NULL));
198
199 return SOS_OK;
200 }
201
202
203
204
205
206 static struct userprog_entry * lookup_userprog(const char *name)
207 {
208 struct userprog_entry *prog;
209
210 if (! name)
211 return NULL;
212
213
214
215 for (prog = (struct userprog_entry*) & _userprogs_table ;
216 prog && (prog->name != NULL) ;
217 prog++)
218 {
219 if (0 == strcmp(name, prog->name))
220
221 return prog;
222 }
223
224 return NULL;
225 }
226
227
228
229
230
231
232
233
234 static sos_uaddr_t load_elf_prog(const struct userprog_entry *prog)
235 {
236 int i;
237
238
239
240
241
242 typedef unsigned long Elf32_Addr;
243 typedef unsigned long Elf32_Word;
244 typedef unsigned short Elf32_Half;
245 typedef unsigned long Elf32_Off;
246 typedef signed long Elf32_Sword;
247
248
249
250 #define EI_NIDENT 16
251 typedef struct {
252 unsigned char e_ident[EI_NIDENT];
253 Elf32_Half e_type;
254 Elf32_Half e_machine;
255 Elf32_Word e_version;
256 Elf32_Addr e_entry;
257 Elf32_Off e_phoff;
258 Elf32_Off e_shoff;
259 Elf32_Word e_flags;
260 Elf32_Half e_ehsize;
261 Elf32_Half e_phentsize;
262 Elf32_Half e_phnum;
263 Elf32_Half e_shentsize;
264 Elf32_Half e_shnum;
265 Elf32_Half e_shstrndx;
266 } __attribute__((packed)) Elf32_Ehdr_t;
267
268
269 #define ELFMAG0 0x7f
270 #define ELFMAG1 'E'
271 #define ELFMAG2 'L'
272 #define ELFMAG3 'F'
273
274
275 #define EI_MAG0 0
276 #define EI_MAG1 1
277 #define EI_MAG2 2
278 #define EI_MAG3 3
279 #define EI_CLASS 4
280 #define EI_DATA 5
281 #define EI_VERSION 6
282 #define EI_PAD 7
283
284
285 #define ELFCLASSNONE 0
286 #define ELFCLASS32 1
287 #define ELFCLASS64 2
288
289
290 #define ELFDATANONE 0
291 #define ELFDATA2LSB 1
292 #define ELFDATA2MSB 2
293
294
295 #define ET_NONE 0
296 #define ET_REL 1
297 #define ET_EXEC 2
298 #define ET_DYN 3
299 #define ET_CORE 4
300 #define ET_LOPROC 0xff00
301 #define ET_HIPROC 0xffff
302
303
304 #define EM_NONE 0
305 #define EM_M32 1
306 #define EM_SPARC 2
307 #define EM_386 3
308 #define EM_68K 4
309 #define EM_88K 5
310 #define EM_860 7
311 #define EM_MIPS 8
312
313
314 #define EV_NONE 0
315 #define EV_CURRENT 1
316
317 typedef struct {
318 Elf32_Word p_type;
319 Elf32_Off p_offset;
320 Elf32_Addr p_vaddr;
321 Elf32_Addr p_paddr;
322 Elf32_Word p_filesz;
323 Elf32_Word p_memsz;
324 Elf32_Word p_flags;
325 Elf32_Word p_align;
326 } __attribute__((packed)) Elf32_Phdr_t;
327
328
329 #define PT_NULL 0
330 #define PT_LOAD 1
331 #define PT_DYNAMIC 2
332 #define PT_INTERP 3
333 #define PT_NOTE 4
334 #define PT_SHLIB 5
335 #define PT_PHDR 6
336 #define PT_LOPROC 0x70000000
337 #define PT_HIPROC 0x7fffffff
338
339
340 #define PF_X 1
341 #define PF_W 2
342 #define PF_R 4
343
344
345 Elf32_Ehdr_t *elf_hdr = (Elf32_Ehdr_t*) prog->bottom_vaddr;
346 Elf32_Phdr_t *elf_phdrs;
347
348
349
350 if (prog->bottom_vaddr + sizeof(Elf32_Ehdr_t) > prog->top_vaddr)
351 {
352 sos_bochs_printf("ELF prog %s: incorrect header\n", prog->name);
353 return 0;
354 }
355
356
357 #define ELF_CHECK(hdr,field,expected_value) \
358 ({ if ((hdr)->field != (expected_value)) \
359 { \
360 sos_bochs_printf("ELF prog %s: for %s, expected %x, got %x\n", \
361 prog->name, \
362 #field, \
363 (unsigned)(expected_value), \
364 (unsigned)(hdr)->field); \
365 return 0; \
366 } \
367 })
368
369 ELF_CHECK(elf_hdr, e_ident[EI_MAG0], ELFMAG0);
370 ELF_CHECK(elf_hdr, e_ident[EI_MAG1], ELFMAG1);
371 ELF_CHECK(elf_hdr, e_ident[EI_MAG2], ELFMAG2);
372 ELF_CHECK(elf_hdr, e_ident[EI_MAG3], ELFMAG3);
373 ELF_CHECK(elf_hdr, e_ident[EI_CLASS], ELFCLASS32);
374 ELF_CHECK(elf_hdr, e_ident[EI_DATA], ELFDATA2LSB);
375 ELF_CHECK(elf_hdr, e_type, ET_EXEC);
376 ELF_CHECK(elf_hdr, e_version, EV_CURRENT);
377
378
379 elf_phdrs = (Elf32_Phdr_t*) (prog->bottom_vaddr + elf_hdr->e_phoff);
380
381
382
383 for (i = 0 ; i < elf_hdr->e_phnum ; i++)
384 {
385 sos_uaddr_t uaddr;
386
387
388 if (elf_phdrs[i].p_type != PT_LOAD)
389 {
390 if (elf_phdrs[i].p_memsz != 0)
391 {
392 SOS_FATAL_ERROR("ELF: non-empty non-LOAD segments not supported yet");
393 }
394 continue;
395 }
396
397 if (elf_phdrs[i].p_vaddr < SOS_PAGING_BASE_USER_ADDRESS)
398 {
399 SOS_FATAL_ERROR("User program has an incorrect address");
400 }
401
402
403 for (uaddr = SOS_PAGE_ALIGN_INF(elf_phdrs[i].p_vaddr) ;
404 uaddr < elf_phdrs[i].p_vaddr + elf_phdrs[i].p_memsz ;
405 uaddr += SOS_PAGE_SIZE)
406 {
407 sos_ret_t retval;
408 sos_paddr_t ppage;
409 ppage = sos_physmem_ref_physpage_new(TRUE);
410
411 retval = sos_paging_map(ppage, uaddr, TRUE,
412 SOS_VM_MAP_PROT_READ
413 | SOS_VM_MAP_PROT_WRITE);
414 SOS_ASSERT_FATAL(retval == SOS_OK);
415
416 retval = sos_physmem_unref_physpage(ppage);
417 SOS_ASSERT_FATAL(retval == 0);
418 }
419
420
421 memcpy((void*) elf_phdrs[i].p_vaddr,
422 (void*) (prog->bottom_vaddr + elf_phdrs[i].p_offset),
423 elf_phdrs[i].p_filesz);
424 }
425
426 return elf_hdr->e_entry;
427 }