aa5b758d6421e5cc5e544667942fef8f19d530d4
[qemu] / linux-user / main.c
1 /*
2  *  qemu user main
3  * 
4  *  Copyright (c) 2003 Fabrice Bellard
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <unistd.h>
26
27 #include "qemu.h"
28
29 #define DEBUG_LOGFILE "/tmp/qemu.log"
30
31 static const char *interp_prefix = CONFIG_QEMU_PREFIX;
32
33 #if defined(__i386__) && !defined(CONFIG_STATIC)
34 /* Force usage of an ELF interpreter even if it is an ELF shared
35    object ! */
36 const char interp[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";
37 #endif
38
39 /* for recent libc, we add these dummy symbols which are not declared
40    when generating a linked object (bug in ld ?) */
41 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)
42 long __init_array_start[0];
43 long __init_array_end[0];
44 long __fini_array_start[0];
45 long __fini_array_end[0];
46 #endif
47
48 /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
49    we allocate a bigger stack. Need a better solution, for example
50    by remapping the process stack directly at the right place */
51 unsigned long x86_stack_size = 512 * 1024;
52
53 void gemu_log(const char *fmt, ...)
54 {
55     va_list ap;
56
57     va_start(ap, fmt);
58     vfprintf(stderr, fmt, ap);
59     va_end(ap);
60 }
61
62 #ifdef TARGET_I386
63 /***********************************************************/
64 /* CPUX86 core interface */
65
66 void cpu_x86_outb(CPUX86State *env, int addr, int val)
67 {
68     fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);
69 }
70
71 void cpu_x86_outw(CPUX86State *env, int addr, int val)
72 {
73     fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);
74 }
75
76 void cpu_x86_outl(CPUX86State *env, int addr, int val)
77 {
78     fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);
79 }
80
81 int cpu_x86_inb(CPUX86State *env, int addr)
82 {
83     fprintf(stderr, "inb: port=0x%04x\n", addr);
84     return 0;
85 }
86
87 int cpu_x86_inw(CPUX86State *env, int addr)
88 {
89     fprintf(stderr, "inw: port=0x%04x\n", addr);
90     return 0;
91 }
92
93 int cpu_x86_inl(CPUX86State *env, int addr)
94 {
95     fprintf(stderr, "inl: port=0x%04x\n", addr);
96     return 0;
97 }
98
99 int cpu_x86_get_pic_interrupt(CPUX86State *env)
100 {
101     return -1;
102 }
103
104 static void write_dt(void *ptr, unsigned long addr, unsigned long limit, 
105                      int flags)
106 {
107     unsigned int e1, e2;
108     e1 = (addr << 16) | (limit & 0xffff);
109     e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
110     e2 |= flags;
111     stl((uint8_t *)ptr, e1);
112     stl((uint8_t *)ptr + 4, e2);
113 }
114
115 static void set_gate(void *ptr, unsigned int type, unsigned int dpl, 
116                      unsigned long addr, unsigned int sel)
117 {
118     unsigned int e1, e2;
119     e1 = (addr & 0xffff) | (sel << 16);
120     e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
121     stl((uint8_t *)ptr, e1);
122     stl((uint8_t *)ptr + 4, e2);
123 }
124
125 uint64_t gdt_table[6];
126 uint64_t idt_table[256];
127
128 /* only dpl matters as we do only user space emulation */
129 static void set_idt(int n, unsigned int dpl)
130 {
131     set_gate(idt_table + n, 0, dpl, 0, 0);
132 }
133
134 void cpu_loop(CPUX86State *env)
135 {
136     int trapnr;
137     uint8_t *pc;
138     target_siginfo_t info;
139
140     for(;;) {
141         trapnr = cpu_x86_exec(env);
142         switch(trapnr) {
143         case 0x80:
144             /* linux syscall */
145             env->regs[R_EAX] = do_syscall(env, 
146                                           env->regs[R_EAX], 
147                                           env->regs[R_EBX],
148                                           env->regs[R_ECX],
149                                           env->regs[R_EDX],
150                                           env->regs[R_ESI],
151                                           env->regs[R_EDI],
152                                           env->regs[R_EBP]);
153             break;
154         case EXCP0B_NOSEG:
155         case EXCP0C_STACK:
156             info.si_signo = SIGBUS;
157             info.si_errno = 0;
158             info.si_code = TARGET_SI_KERNEL;
159             info._sifields._sigfault._addr = 0;
160             queue_signal(info.si_signo, &info);
161             break;
162         case EXCP0D_GPF:
163             if (env->eflags & VM_MASK) {
164                 handle_vm86_fault(env);
165             } else {
166                 info.si_signo = SIGSEGV;
167                 info.si_errno = 0;
168                 info.si_code = TARGET_SI_KERNEL;
169                 info._sifields._sigfault._addr = 0;
170                 queue_signal(info.si_signo, &info);
171             }
172             break;
173         case EXCP0E_PAGE:
174             info.si_signo = SIGSEGV;
175             info.si_errno = 0;
176             if (!(env->error_code & 1))
177                 info.si_code = TARGET_SEGV_MAPERR;
178             else
179                 info.si_code = TARGET_SEGV_ACCERR;
180             info._sifields._sigfault._addr = env->cr[2];
181             queue_signal(info.si_signo, &info);
182             break;
183         case EXCP00_DIVZ:
184             if (env->eflags & VM_MASK) {
185                 handle_vm86_trap(env, trapnr);
186             } else {
187                 /* division by zero */
188                 info.si_signo = SIGFPE;
189                 info.si_errno = 0;
190                 info.si_code = TARGET_FPE_INTDIV;
191                 info._sifields._sigfault._addr = env->eip;
192                 queue_signal(info.si_signo, &info);
193             }
194             break;
195         case EXCP01_SSTP:
196         case EXCP03_INT3:
197             if (env->eflags & VM_MASK) {
198                 handle_vm86_trap(env, trapnr);
199             } else {
200                 info.si_signo = SIGTRAP;
201                 info.si_errno = 0;
202                 if (trapnr == EXCP01_SSTP) {
203                     info.si_code = TARGET_TRAP_BRKPT;
204                     info._sifields._sigfault._addr = env->eip;
205                 } else {
206                     info.si_code = TARGET_SI_KERNEL;
207                     info._sifields._sigfault._addr = 0;
208                 }
209                 queue_signal(info.si_signo, &info);
210             }
211             break;
212         case EXCP04_INTO:
213         case EXCP05_BOUND:
214             if (env->eflags & VM_MASK) {
215                 handle_vm86_trap(env, trapnr);
216             } else {
217                 info.si_signo = SIGSEGV;
218                 info.si_errno = 0;
219                 info.si_code = TARGET_SI_KERNEL;
220                 info._sifields._sigfault._addr = 0;
221                 queue_signal(info.si_signo, &info);
222             }
223             break;
224         case EXCP06_ILLOP:
225             info.si_signo = SIGILL;
226             info.si_errno = 0;
227             info.si_code = TARGET_ILL_ILLOPN;
228             info._sifields._sigfault._addr = env->eip;
229             queue_signal(info.si_signo, &info);
230             break;
231         case EXCP_INTERRUPT:
232             /* just indicate that signals should be handled asap */
233             break;
234         default:
235             pc = env->segs[R_CS].base + env->eip;
236             fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n", 
237                     (long)pc, trapnr);
238             abort();
239         }
240         process_pending_signals(env);
241     }
242 }
243 #endif
244
245 #ifdef TARGET_ARM
246
247 void cpu_loop(CPUARMState *env)
248 {
249     int trapnr;
250     unsigned int n, insn;
251     target_siginfo_t info;
252     
253     for(;;) {
254         trapnr = cpu_arm_exec(env);
255         switch(trapnr) {
256         case EXCP_UDEF:
257             info.si_signo = SIGILL;
258             info.si_errno = 0;
259             info.si_code = TARGET_ILL_ILLOPN;
260             info._sifields._sigfault._addr = env->regs[15];
261             queue_signal(info.si_signo, &info);
262             break;
263         case EXCP_SWI:
264             {
265                 /* system call */
266                 insn = ldl((void *)(env->regs[15] - 4));
267                 n = insn & 0xffffff;
268                 if (n >= ARM_SYSCALL_BASE) {
269                     /* linux syscall */
270                     n -= ARM_SYSCALL_BASE;
271                     env->regs[0] = do_syscall(env, 
272                                               n, 
273                                               env->regs[0],
274                                               env->regs[1],
275                                               env->regs[2],
276                                               env->regs[3],
277                                               env->regs[4],
278                                               0);
279                 } else {
280                     goto error;
281                 }
282             }
283             break;
284         case EXCP_INTERRUPT:
285             /* just indicate that signals should be handled asap */
286             break;
287         default:
288         error:
289             fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", 
290                     trapnr);
291             cpu_arm_dump_state(env, stderr, 0);
292             abort();
293         }
294         process_pending_signals(env);
295     }
296 }
297
298 #endif
299
300 #ifdef TARGET_SPARC
301
302 void cpu_loop (CPUSPARCState *env)
303 {
304         int trapnr;
305
306         while (1) {
307                 trapnr = cpu_sparc_exec (env);
308
309                 switch (trapnr) {
310                   case 0x8: case 0x10:
311                         env->regwptr[0] = do_syscall (env, env->gregs[1],
312                                 env->regwptr[0], env->regwptr[1], env->regwptr[2],
313                                 env->regwptr[3], env->regwptr[4], env->regwptr[13]);
314                         if (env->regwptr[0] >= 0xffffffe0)
315                                 env->psr |= PSR_CARRY;
316                         break;
317                   default:
318                         printf ("Invalid trap: %d\n", trapnr);
319                         exit (1);
320                 }
321                 process_pending_signals (env);
322         }
323 }
324
325 #endif
326
327 #ifdef TARGET_PPC
328
329 void cpu_loop(CPUPPCState *env)
330 {
331     int trapnr;
332     target_siginfo_t info;
333     
334     for(;;) {
335         trapnr = cpu_ppc_exec(env);
336         switch(trapnr) {
337         case EXCP_NONE:
338         case EXCP_INTERRUPT:
339         case EXCP_MTMSR: /* mtmsr instruction:               */
340         case EXCP_BRANCH: /* branch instruction               */
341             /* Single step mode */
342             break;
343 #if 0
344         case EXCP_RESET: /* System reset                     */
345             fprintf(stderr, "RESET asked... Stop emulation\n");
346             cpu_ppc_dump_state(env, stderr, 0);
347             abort();
348 #endif
349         case EXCP_MACHINE_CHECK: /* Machine check exception          */
350             fprintf(stderr, "Machine check exeption... "
351                     "See you in kernel code !\n");
352             cpu_ppc_dump_state(env, stderr, 0);
353             abort();
354         case EXCP_DSI:  /* Impossible memory access         */
355             fprintf(stderr, "Invalid memory access\n");
356             info.si_signo = SIGSEGV;
357             info.si_errno = 0;
358             info.si_code = TARGET_ILL_ILLOPN;
359             info._sifields._sigfault._addr = env->nip;
360             queue_signal(info.si_signo, &info);
361             break;
362         case EXCP_ISI: /* Impossible instruction fetch     */
363             fprintf(stderr, "Invalid instruction fetch\n");
364             info.si_signo = SIGBUS;
365             info.si_errno = 0;
366             info.si_code = TARGET_ILL_ILLOPN;
367             info._sifields._sigfault._addr = env->nip;
368             queue_signal(info.si_signo, &info);
369             break;
370         case EXCP_EXTERNAL: /* External interruption            */
371             fprintf(stderr, "External access exeption\n");
372             cpu_ppc_dump_state(env, stderr, 0);
373             abort();
374         case EXCP_ALIGN: /* Alignment exception              */
375             fprintf(stderr, "Alignment exception\n");
376             cpu_ppc_dump_state(env, stderr, 0);
377             abort();
378         case EXCP_PROGRAM: /* Program exception                */
379             fprintf(stderr, "Program exception\n");
380             cpu_ppc_dump_state(env, stderr, 0);
381             abort();
382             break;
383         /* Trap */
384         case EXCP_TRAP: /* Trap                             */
385         case EXCP_TRACE: /* Trace exception (optional)       */
386             info.si_signo = SIGTRAP;
387             info.si_errno = 0;
388             info.si_code = TARGET_ILL_ILLOPN;
389             info._sifields._sigfault._addr = env->nip;
390             queue_signal(info.si_signo, &info);
391             break;
392         /* Invalid instruction */
393         case EXCP_INVAL:
394             info.si_signo = SIGILL;
395             info.si_errno = 0;
396             info.si_code = TARGET_ILL_ILLOPN;
397             info._sifields._sigfault._addr = env->nip;
398             queue_signal(info.si_signo, &info);
399             break;
400         /* Privileged instruction */
401         case EXCP_PRIV: /* Privileged instruction           */
402             info.si_signo = SIGILL;
403             info.si_errno = 0;
404             info.si_code = TARGET_ILL_ILLOPN;
405             info._sifields._sigfault._addr = env->nip;
406             queue_signal(info.si_signo, &info);
407             break;
408         case EXCP_NO_FP: /* No floating point                */
409         case EXCP_DECR: /* Decrementer exception            */
410         case EXCP_RESA: /* Implementation specific          */
411         case EXCP_RESB: /* Implementation specific          */
412         case EXCP_FP_ASSIST: /* Floating-point assist (optional) */
413             fprintf(stderr, "Misc expt...\n");
414             cpu_ppc_dump_state(env, stderr, 0);
415             abort();
416
417         case EXCP_SYSCALL:
418         {
419             uint32_t ret;
420             /* system call */
421             /* WARNING:
422              * PPC ABI uses overflow flag in cr0 to signal an error
423              * in syscalls.
424              */
425             env->crf[0] &= ~0x1;
426             ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
427                              env->gpr[5], env->gpr[6], env->gpr[7],
428                              env->gpr[8]);
429             if (ret > (uint32_t)(-515)) {
430                 env->crf[0] |= 0x1;
431                 ret = -ret;
432             }
433             env->gpr[3] = ret;
434             break;
435         }
436         default:
437 //        error:
438             fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", 
439                     trapnr);
440             cpu_ppc_dump_state(env, stderr, 0);
441             abort();
442         }
443         process_pending_signals(env);
444     }
445 }
446 #endif
447
448 void usage(void)
449 {
450     printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
451            "usage: qemu-" TARGET_ARCH " [-h] [-d] [-L path] [-s size] program [arguments...]\n"
452            "Linux CPU emulator (compiled for %s emulation)\n"
453            "\n"
454            "-h           print this help\n"
455            "-L path      set the elf interpreter prefix (default=%s)\n"
456            "-s size      set the stack size in bytes (default=%ld)\n"
457            "\n"
458            "debug options:\n"
459            "-d           activate log (logfile=%s)\n"
460            "-p pagesize  set the host page size to 'pagesize'\n",
461            TARGET_ARCH,
462            interp_prefix, 
463            x86_stack_size,
464            DEBUG_LOGFILE);
465     _exit(1);
466 }
467
468 /* XXX: currently only used for async signals (see signal.c) */
469 CPUState *global_env;
470 /* used only if single thread */
471 CPUState *cpu_single_env = NULL;
472
473 /* used to free thread contexts */
474 TaskState *first_task_state;
475
476 int main(int argc, char **argv)
477 {
478     const char *filename;
479     struct target_pt_regs regs1, *regs = &regs1;
480     struct image_info info1, *info = &info1;
481     TaskState ts1, *ts = &ts1;
482     CPUState *env;
483     int optind;
484     const char *r;
485     
486     if (argc <= 1)
487         usage();
488
489     /* init debug */
490     cpu_set_log_filename(DEBUG_LOGFILE);
491
492     optind = 1;
493     for(;;) {
494         if (optind >= argc)
495             break;
496         r = argv[optind];
497         if (r[0] != '-')
498             break;
499         optind++;
500         r++;
501         if (!strcmp(r, "-")) {
502             break;
503         } else if (!strcmp(r, "d")) {
504             cpu_set_log(CPU_LOG_ALL);
505         } else if (!strcmp(r, "s")) {
506             r = argv[optind++];
507             x86_stack_size = strtol(r, (char **)&r, 0);
508             if (x86_stack_size <= 0)
509                 usage();
510             if (*r == 'M')
511                 x86_stack_size *= 1024 * 1024;
512             else if (*r == 'k' || *r == 'K')
513                 x86_stack_size *= 1024;
514         } else if (!strcmp(r, "L")) {
515             interp_prefix = argv[optind++];
516         } else if (!strcmp(r, "p")) {
517             host_page_size = atoi(argv[optind++]);
518             if (host_page_size == 0 ||
519                 (host_page_size & (host_page_size - 1)) != 0) {
520                 fprintf(stderr, "page size must be a power of two\n");
521                 exit(1);
522             }
523         } else {
524             usage();
525         }
526     }
527     if (optind >= argc)
528         usage();
529     filename = argv[optind];
530
531     /* Zero out regs */
532     memset(regs, 0, sizeof(struct target_pt_regs));
533
534     /* Zero out image_info */
535     memset(info, 0, sizeof(struct image_info));
536
537     /* Scan interp_prefix dir for replacement files. */
538     init_paths(interp_prefix);
539
540     /* NOTE: we need to init the CPU at this stage to get the
541        host_page_size */
542     env = cpu_init();
543     
544     if (elf_exec(filename, argv+optind, environ, regs, info) != 0) {
545         printf("Error loading %s\n", filename);
546         _exit(1);
547     }
548     
549     if (loglevel) {
550         page_dump(logfile);
551     
552         fprintf(logfile, "start_brk   0x%08lx\n" , info->start_brk);
553         fprintf(logfile, "end_code    0x%08lx\n" , info->end_code);
554         fprintf(logfile, "start_code  0x%08lx\n" , info->start_code);
555         fprintf(logfile, "end_data    0x%08lx\n" , info->end_data);
556         fprintf(logfile, "start_stack 0x%08lx\n" , info->start_stack);
557         fprintf(logfile, "brk         0x%08lx\n" , info->brk);
558         fprintf(logfile, "entry       0x%08lx\n" , info->entry);
559     }
560
561     target_set_brk((char *)info->brk);
562     syscall_init();
563     signal_init();
564
565     global_env = env;
566
567     /* build Task State */
568     memset(ts, 0, sizeof(TaskState));
569     env->opaque = ts;
570     ts->used = 1;
571     env->user_mode_only = 1;
572     
573 #if defined(TARGET_I386)
574     cpu_x86_set_cpl(env, 3);
575
576     env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
577
578     /* linux register setup */
579     env->regs[R_EAX] = regs->eax;
580     env->regs[R_EBX] = regs->ebx;
581     env->regs[R_ECX] = regs->ecx;
582     env->regs[R_EDX] = regs->edx;
583     env->regs[R_ESI] = regs->esi;
584     env->regs[R_EDI] = regs->edi;
585     env->regs[R_EBP] = regs->ebp;
586     env->regs[R_ESP] = regs->esp;
587     env->eip = regs->eip;
588
589     /* linux interrupt setup */
590     env->idt.base = (void *)idt_table;
591     env->idt.limit = sizeof(idt_table) - 1;
592     set_idt(0, 0);
593     set_idt(1, 0);
594     set_idt(2, 0);
595     set_idt(3, 3);
596     set_idt(4, 3);
597     set_idt(5, 3);
598     set_idt(6, 0);
599     set_idt(7, 0);
600     set_idt(8, 0);
601     set_idt(9, 0);
602     set_idt(10, 0);
603     set_idt(11, 0);
604     set_idt(12, 0);
605     set_idt(13, 0);
606     set_idt(14, 0);
607     set_idt(15, 0);
608     set_idt(16, 0);
609     set_idt(17, 0);
610     set_idt(18, 0);
611     set_idt(19, 0);
612     set_idt(0x80, 3);
613
614     /* linux segment setup */
615     env->gdt.base = (void *)gdt_table;
616     env->gdt.limit = sizeof(gdt_table) - 1;
617     write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
618              DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | 
619              (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
620     write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
621              DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | 
622              (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
623     cpu_x86_load_seg(env, R_CS, __USER_CS);
624     cpu_x86_load_seg(env, R_DS, __USER_DS);
625     cpu_x86_load_seg(env, R_ES, __USER_DS);
626     cpu_x86_load_seg(env, R_SS, __USER_DS);
627     cpu_x86_load_seg(env, R_FS, __USER_DS);
628     cpu_x86_load_seg(env, R_GS, __USER_DS);
629
630 #elif defined(TARGET_ARM)
631     {
632         int i;
633         for(i = 0; i < 16; i++) {
634             env->regs[i] = regs->uregs[i];
635         }
636         env->cpsr = regs->uregs[16];
637     }
638 #elif defined(TARGET_SPARC)
639         env->pc = regs->u_regs[0];
640         env->regwptr[6] = regs->u_regs[1]-0x40;
641 #elif defined(TARGET_PPC)
642     {
643         int i;
644         for (i = 0; i < 32; i++)
645             env->msr[i] = (regs->msr >> i) & 1;
646         env->nip = regs->nip;
647         for(i = 0; i < 32; i++) {
648             env->gpr[i] = regs->gpr[i];
649         }
650     }
651 #else
652 #error unsupported target CPU
653 #endif
654
655     cpu_loop(env);
656     /* never exits */
657     return 0;
658 }