Convert references to logfile/loglevel to use qemu_log*() macros
[qemu] / bsd-user / main.c
1 /*
2  *  qemu user main
3  *
4  *  Copyright (c) 2003-2008 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., 51 Franklin Street - Fifth Floor, Boston,
19  *  MA 02110-1301, USA.
20  */
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <stdarg.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #include <machine/trap.h>
28
29 #include "qemu.h"
30 #include "qemu-common.h"
31 /* For tb_lock */
32 #include "exec-all.h"
33
34 #define DEBUG_LOGFILE "/tmp/qemu.log"
35
36 static const char *interp_prefix = CONFIG_QEMU_PREFIX;
37 const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
38 extern char **environ;
39
40 /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
41    we allocate a bigger stack. Need a better solution, for example
42    by remapping the process stack directly at the right place */
43 unsigned long x86_stack_size = 512 * 1024;
44
45 void gemu_log(const char *fmt, ...)
46 {
47     va_list ap;
48
49     va_start(ap, fmt);
50     vfprintf(stderr, fmt, ap);
51     va_end(ap);
52 }
53 #ifdef TARGET_SPARC
54 #define SPARC64_STACK_BIAS 2047
55
56 //#define DEBUG_WIN
57 /* WARNING: dealing with register windows _is_ complicated. More info
58    can be found at http://www.sics.se/~psm/sparcstack.html */
59 static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
60 {
61     index = (index + cwp * 16) % (16 * env->nwindows);
62     /* wrap handling : if cwp is on the last window, then we use the
63        registers 'after' the end */
64     if (index < 8 && env->cwp == env->nwindows - 1)
65         index += 16 * env->nwindows;
66     return index;
67 }
68
69 /* save the register window 'cwp1' */
70 static inline void save_window_offset(CPUSPARCState *env, int cwp1)
71 {
72     unsigned int i;
73     abi_ulong sp_ptr;
74
75     sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
76 #ifdef TARGET_SPARC64
77     if (sp_ptr & 3)
78         sp_ptr += SPARC64_STACK_BIAS;
79 #endif
80 #if defined(DEBUG_WIN)
81     printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n",
82            sp_ptr, cwp1);
83 #endif
84     for(i = 0; i < 16; i++) {
85         /* FIXME - what to do if put_user() fails? */
86         put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
87         sp_ptr += sizeof(abi_ulong);
88     }
89 }
90
91 static void save_window(CPUSPARCState *env)
92 {
93 #ifndef TARGET_SPARC64
94     unsigned int new_wim;
95     new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) &
96         ((1LL << env->nwindows) - 1);
97     save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
98     env->wim = new_wim;
99 #else
100     save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
101     env->cansave++;
102     env->canrestore--;
103 #endif
104 }
105
106 static void restore_window(CPUSPARCState *env)
107 {
108 #ifndef TARGET_SPARC64
109     unsigned int new_wim;
110 #endif
111     unsigned int i, cwp1;
112     abi_ulong sp_ptr;
113
114 #ifndef TARGET_SPARC64
115     new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) &
116         ((1LL << env->nwindows) - 1);
117 #endif
118
119     /* restore the invalid window */
120     cwp1 = cpu_cwp_inc(env, env->cwp + 1);
121     sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
122 #ifdef TARGET_SPARC64
123     if (sp_ptr & 3)
124         sp_ptr += SPARC64_STACK_BIAS;
125 #endif
126 #if defined(DEBUG_WIN)
127     printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n",
128            sp_ptr, cwp1);
129 #endif
130     for(i = 0; i < 16; i++) {
131         /* FIXME - what to do if get_user() fails? */
132         get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
133         sp_ptr += sizeof(abi_ulong);
134     }
135 #ifdef TARGET_SPARC64
136     env->canrestore++;
137     if (env->cleanwin < env->nwindows - 1)
138         env->cleanwin++;
139     env->cansave--;
140 #else
141     env->wim = new_wim;
142 #endif
143 }
144
145 static void flush_windows(CPUSPARCState *env)
146 {
147     int offset, cwp1;
148
149     offset = 1;
150     for(;;) {
151         /* if restore would invoke restore_window(), then we can stop */
152         cwp1 = cpu_cwp_inc(env, env->cwp + offset);
153 #ifndef TARGET_SPARC64
154         if (env->wim & (1 << cwp1))
155             break;
156 #else
157         if (env->canrestore == 0)
158             break;
159         env->cansave++;
160         env->canrestore--;
161 #endif
162         save_window_offset(env, cwp1);
163         offset++;
164     }
165     cwp1 = cpu_cwp_inc(env, env->cwp + 1);
166 #ifndef TARGET_SPARC64
167     /* set wim so that restore will reload the registers */
168     env->wim = 1 << cwp1;
169 #endif
170 #if defined(DEBUG_WIN)
171     printf("flush_windows: nb=%d\n", offset - 1);
172 #endif
173 }
174
175 void cpu_loop(CPUSPARCState *env, enum BSDType bsd_type)
176 {
177     int trapnr, ret, syscall_nr;
178     //target_siginfo_t info;
179
180     while (1) {
181         trapnr = cpu_sparc_exec (env);
182
183         switch (trapnr) {
184 #ifndef TARGET_SPARC64
185         case 0x80:
186 #else
187         case 0x100:
188 #endif
189             syscall_nr = env->gregs[1];
190             if (bsd_type == target_freebsd)
191                 ret = do_freebsd_syscall(env, syscall_nr,
192                                          env->regwptr[0], env->regwptr[1],
193                                          env->regwptr[2], env->regwptr[3],
194                                          env->regwptr[4], env->regwptr[5]);
195             else if (bsd_type == target_netbsd)
196                 ret = do_netbsd_syscall(env, syscall_nr,
197                                         env->regwptr[0], env->regwptr[1],
198                                         env->regwptr[2], env->regwptr[3],
199                                         env->regwptr[4], env->regwptr[5]);
200             else { //if (bsd_type == target_openbsd)
201 #if defined(TARGET_SPARC64)
202                 syscall_nr &= ~(TARGET_OPENBSD_SYSCALL_G7RFLAG |
203                                 TARGET_OPENBSD_SYSCALL_G2RFLAG);
204 #endif
205                 ret = do_openbsd_syscall(env, syscall_nr,
206                                          env->regwptr[0], env->regwptr[1],
207                                          env->regwptr[2], env->regwptr[3],
208                                          env->regwptr[4], env->regwptr[5]);
209             }
210             if ((unsigned int)ret >= (unsigned int)(-515)) {
211 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
212                 env->xcc |= PSR_CARRY;
213 #else
214                 env->psr |= PSR_CARRY;
215 #endif
216             } else {
217 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
218                 env->xcc &= ~PSR_CARRY;
219 #else
220                 env->psr &= ~PSR_CARRY;
221 #endif
222             }
223             env->regwptr[0] = ret;
224             /* next instruction */
225 #if defined(TARGET_SPARC64)
226             if (bsd_type == target_openbsd &&
227                 env->gregs[1] & TARGET_OPENBSD_SYSCALL_G2RFLAG) {
228                 env->pc = env->gregs[2];
229                 env->npc = env->pc + 4;
230             } else if (bsd_type == target_openbsd &&
231                        env->gregs[1] & TARGET_OPENBSD_SYSCALL_G7RFLAG) {
232                 env->pc = env->gregs[7];
233                 env->npc = env->pc + 4;
234             } else {
235                 env->pc = env->npc;
236                 env->npc = env->npc + 4;
237             }
238 #else
239             env->pc = env->npc;
240             env->npc = env->npc + 4;
241 #endif
242             break;
243         case 0x83: /* flush windows */
244 #ifdef TARGET_ABI32
245         case 0x103:
246 #endif
247             flush_windows(env);
248             /* next instruction */
249             env->pc = env->npc;
250             env->npc = env->npc + 4;
251             break;
252 #ifndef TARGET_SPARC64
253         case TT_WIN_OVF: /* window overflow */
254             save_window(env);
255             break;
256         case TT_WIN_UNF: /* window underflow */
257             restore_window(env);
258             break;
259         case TT_TFAULT:
260         case TT_DFAULT:
261 #if 0
262             {
263                 info.si_signo = SIGSEGV;
264                 info.si_errno = 0;
265                 /* XXX: check env->error_code */
266                 info.si_code = TARGET_SEGV_MAPERR;
267                 info._sifields._sigfault._addr = env->mmuregs[4];
268                 queue_signal(env, info.si_signo, &info);
269             }
270 #endif
271             break;
272 #else
273         case TT_SPILL: /* window overflow */
274             save_window(env);
275             break;
276         case TT_FILL: /* window underflow */
277             restore_window(env);
278             break;
279         case TT_TFAULT:
280         case TT_DFAULT:
281 #if 0
282             {
283                 info.si_signo = SIGSEGV;
284                 info.si_errno = 0;
285                 /* XXX: check env->error_code */
286                 info.si_code = TARGET_SEGV_MAPERR;
287                 if (trapnr == TT_DFAULT)
288                     info._sifields._sigfault._addr = env->dmmuregs[4];
289                 else
290                     info._sifields._sigfault._addr = env->tsptr->tpc;
291                 //queue_signal(env, info.si_signo, &info);
292             }
293 #endif
294             break;
295 #endif
296         case EXCP_INTERRUPT:
297             /* just indicate that signals should be handled asap */
298             break;
299         case EXCP_DEBUG:
300             {
301                 int sig;
302
303                 sig = gdb_handlesig (env, TARGET_SIGTRAP);
304 #if 0
305                 if (sig)
306                   {
307                     info.si_signo = sig;
308                     info.si_errno = 0;
309                     info.si_code = TARGET_TRAP_BRKPT;
310                     //queue_signal(env, info.si_signo, &info);
311                   }
312 #endif
313             }
314             break;
315         default:
316             printf ("Unhandled trap: 0x%x\n", trapnr);
317             cpu_dump_state(env, stderr, fprintf, 0);
318             exit (1);
319         }
320         process_pending_signals (env);
321     }
322 }
323
324 #endif
325
326 static void usage(void)
327 {
328     printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n"
329            "usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n"
330            "BSD CPU emulator (compiled for %s emulation)\n"
331            "\n"
332            "Standard options:\n"
333            "-h                print this help\n"
334            "-g port           wait gdb connection to port\n"
335            "-L path           set the elf interpreter prefix (default=%s)\n"
336            "-s size           set the stack size in bytes (default=%ld)\n"
337            "-cpu model        select CPU (-cpu ? for list)\n"
338            "-drop-ld-preload  drop LD_PRELOAD for target process\n"
339            "-bsd type         select emulated BSD type FreeBSD/NetBSD/OpenBSD (default)\n"
340            "\n"
341            "Debug options:\n"
342            "-d options   activate log (logfile=%s)\n"
343            "-p pagesize  set the host page size to 'pagesize'\n"
344            "-strace      log system calls\n"
345            "\n"
346            "Environment variables:\n"
347            "QEMU_STRACE       Print system calls and arguments similar to the\n"
348            "                  'strace' program.  Enable by setting to any value.\n"
349            ,
350            TARGET_ARCH,
351            interp_prefix,
352            x86_stack_size,
353            DEBUG_LOGFILE);
354     _exit(1);
355 }
356
357 THREAD CPUState *thread_env;
358
359 /* Assumes contents are already zeroed.  */
360 void init_task_state(TaskState *ts)
361 {
362     int i;
363
364     ts->used = 1;
365     ts->first_free = ts->sigqueue_table;
366     for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) {
367         ts->sigqueue_table[i].next = &ts->sigqueue_table[i + 1];
368     }
369     ts->sigqueue_table[i].next = NULL;
370 }
371
372 int main(int argc, char **argv)
373 {
374     const char *filename;
375     const char *cpu_model;
376     struct target_pt_regs regs1, *regs = &regs1;
377     struct image_info info1, *info = &info1;
378     TaskState ts1, *ts = &ts1;
379     CPUState *env;
380     int optind;
381     const char *r;
382     int gdbstub_port = 0;
383     int drop_ld_preload = 0, environ_count = 0;
384     char **target_environ, **wrk, **dst;
385     enum BSDType bsd_type = target_openbsd;
386
387     if (argc <= 1)
388         usage();
389
390     /* init debug */
391     cpu_set_log_filename(DEBUG_LOGFILE);
392
393     cpu_model = NULL;
394     optind = 1;
395     for(;;) {
396         if (optind >= argc)
397             break;
398         r = argv[optind];
399         if (r[0] != '-')
400             break;
401         optind++;
402         r++;
403         if (!strcmp(r, "-")) {
404             break;
405         } else if (!strcmp(r, "d")) {
406             int mask;
407             const CPULogItem *item;
408
409             if (optind >= argc)
410                 break;
411
412             r = argv[optind++];
413             mask = cpu_str_to_log_mask(r);
414             if (!mask) {
415                 printf("Log items (comma separated):\n");
416                 for(item = cpu_log_items; item->mask != 0; item++) {
417                     printf("%-10s %s\n", item->name, item->help);
418                 }
419                 exit(1);
420             }
421             cpu_set_log(mask);
422         } else if (!strcmp(r, "s")) {
423             r = argv[optind++];
424             x86_stack_size = strtol(r, (char **)&r, 0);
425             if (x86_stack_size <= 0)
426                 usage();
427             if (*r == 'M')
428                 x86_stack_size *= 1024 * 1024;
429             else if (*r == 'k' || *r == 'K')
430                 x86_stack_size *= 1024;
431         } else if (!strcmp(r, "L")) {
432             interp_prefix = argv[optind++];
433         } else if (!strcmp(r, "p")) {
434             qemu_host_page_size = atoi(argv[optind++]);
435             if (qemu_host_page_size == 0 ||
436                 (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
437                 fprintf(stderr, "page size must be a power of two\n");
438                 exit(1);
439             }
440         } else if (!strcmp(r, "g")) {
441             gdbstub_port = atoi(argv[optind++]);
442         } else if (!strcmp(r, "r")) {
443             qemu_uname_release = argv[optind++];
444         } else if (!strcmp(r, "cpu")) {
445             cpu_model = argv[optind++];
446             if (strcmp(cpu_model, "?") == 0) {
447 /* XXX: implement xxx_cpu_list for targets that still miss it */
448 #if defined(cpu_list)
449                     cpu_list(stdout, &fprintf);
450 #endif
451                 _exit(1);
452             }
453         } else if (!strcmp(r, "drop-ld-preload")) {
454             drop_ld_preload = 1;
455         } else if (!strcmp(r, "bsd")) {
456             if (!strcasecmp(argv[optind], "freebsd")) {
457                 bsd_type = target_freebsd;
458             } else if (!strcasecmp(argv[optind], "netbsd")) {
459                 bsd_type = target_netbsd;
460             } else if (!strcasecmp(argv[optind], "openbsd")) {
461                 bsd_type = target_openbsd;
462             } else {
463                 usage();
464             }
465             optind++;
466         } else if (!strcmp(r, "strace")) {
467             do_strace = 1;
468         } else
469         {
470             usage();
471         }
472     }
473     if (optind >= argc)
474         usage();
475     filename = argv[optind];
476
477     /* Zero out regs */
478     memset(regs, 0, sizeof(struct target_pt_regs));
479
480     /* Zero out image_info */
481     memset(info, 0, sizeof(struct image_info));
482
483     /* Scan interp_prefix dir for replacement files. */
484     init_paths(interp_prefix);
485
486     if (cpu_model == NULL) {
487 #if defined(TARGET_SPARC)
488 #ifdef TARGET_SPARC64
489         cpu_model = "TI UltraSparc II";
490 #else
491         cpu_model = "Fujitsu MB86904";
492 #endif
493 #else
494         cpu_model = "any";
495 #endif
496     }
497     cpu_exec_init_all(0);
498     /* NOTE: we need to init the CPU at this stage to get
499        qemu_host_page_size */
500     env = cpu_init(cpu_model);
501     if (!env) {
502         fprintf(stderr, "Unable to find CPU definition\n");
503         exit(1);
504     }
505     thread_env = env;
506
507     if (getenv("QEMU_STRACE")) {
508         do_strace = 1;
509     }
510
511     wrk = environ;
512     while (*(wrk++))
513         environ_count++;
514
515     target_environ = malloc((environ_count + 1) * sizeof(char *));
516     if (!target_environ)
517         abort();
518     for (wrk = environ, dst = target_environ; *wrk; wrk++) {
519         if (drop_ld_preload && !strncmp(*wrk, "LD_PRELOAD=", 11))
520             continue;
521         *(dst++) = strdup(*wrk);
522     }
523     *dst = NULL; /* NULL terminate target_environ */
524
525     if (loader_exec(filename, argv+optind, target_environ, regs, info) != 0) {
526         printf("Error loading %s\n", filename);
527         _exit(1);
528     }
529
530     for (wrk = target_environ; *wrk; wrk++) {
531         free(*wrk);
532     }
533
534     free(target_environ);
535
536     log_page_dump();
537
538     qemu_log("start_brk   0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
539     qemu_log("end_code    0x" TARGET_ABI_FMT_lx "\n", info->end_code);
540     qemu_log("start_code  0x" TARGET_ABI_FMT_lx "\n",
541             info->start_code);
542     qemu_log("start_data  0x" TARGET_ABI_FMT_lx "\n",
543             info->start_data);
544     qemu_log("end_data    0x" TARGET_ABI_FMT_lx "\n", info->end_data);
545     qemu_log("start_stack 0x" TARGET_ABI_FMT_lx "\n",
546             info->start_stack);
547     qemu_log("brk         0x" TARGET_ABI_FMT_lx "\n", info->brk);
548     qemu_log("entry       0x" TARGET_ABI_FMT_lx "\n", info->entry);
549
550     target_set_brk(info->brk);
551     syscall_init();
552     signal_init();
553
554     /* build Task State */
555     memset(ts, 0, sizeof(TaskState));
556     init_task_state(ts);
557     ts->info = info;
558     env->opaque = ts;
559
560 #if defined(TARGET_SPARC)
561     {
562         int i;
563         env->pc = regs->pc;
564         env->npc = regs->npc;
565         env->y = regs->y;
566         for(i = 0; i < 8; i++)
567             env->gregs[i] = regs->u_regs[i];
568         for(i = 0; i < 8; i++)
569             env->regwptr[i] = regs->u_regs[i + 8];
570     }
571 #else
572 #error unsupported target CPU
573 #endif
574
575     if (gdbstub_port) {
576         gdbserver_start (gdbstub_port);
577         gdb_handlesig(env, 0);
578     }
579     cpu_loop(env, bsd_type);
580     /* never exits */
581     return 0;
582 }