xref: /openbmc/qemu/bsd-user/main.c (revision 03555199)
1 /*
2  *  qemu bsd user main
3  *
4  *  Copyright (c) 2003-2008 Fabrice Bellard
5  *  Copyright (c) 2013-14 Stacey Son
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "qemu/osdep.h"
22 #include <sys/resource.h>
23 #include <sys/sysctl.h>
24 
25 #include "qemu/help-texts.h"
26 #include "qemu/units.h"
27 #include "qemu/accel.h"
28 #include "qemu-version.h"
29 #include <machine/trap.h>
30 
31 #include "qapi/error.h"
32 #include "qemu.h"
33 #include "qemu/config-file.h"
34 #include "qemu/error-report.h"
35 #include "qemu/path.h"
36 #include "qemu/help_option.h"
37 #include "qemu/module.h"
38 #include "exec/exec-all.h"
39 #include "user/guest-base.h"
40 #include "tcg/startup.h"
41 #include "qemu/timer.h"
42 #include "qemu/envlist.h"
43 #include "qemu/cutils.h"
44 #include "exec/log.h"
45 #include "trace/control.h"
46 #include "crypto/init.h"
47 #include "qemu/guest-random.h"
48 #include "gdbstub/user.h"
49 
50 #include "host-os.h"
51 #include "target_arch_cpu.h"
52 
53 
54 /*
55  * TODO: Remove these and rely only on qemu_real_host_page_size().
56  */
57 uintptr_t qemu_host_page_size;
58 intptr_t qemu_host_page_mask;
59 
60 static bool opt_one_insn_per_tb;
61 uintptr_t guest_base;
62 bool have_guest_base;
63 /*
64  * When running 32-on-64 we should make sure we can fit all of the possible
65  * guest address space into a contiguous chunk of virtual host memory.
66  *
67  * This way we will never overlap with our own libraries or binaries or stack
68  * or anything else that QEMU maps.
69  *
70  * Many cpus reserve the high bit (or more than one for some 64-bit cpus)
71  * of the address for the kernel.  Some cpus rely on this and user space
72  * uses the high bit(s) for pointer tagging and the like.  For them, we
73  * must preserve the expected address space.
74  */
75 #ifndef MAX_RESERVED_VA
76 # if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
77 #  if TARGET_VIRT_ADDR_SPACE_BITS == 32 && \
78       (TARGET_LONG_BITS == 32 || defined(TARGET_ABI32))
79 #   define MAX_RESERVED_VA  0xfffffffful
80 #  else
81 #   define MAX_RESERVED_VA  ((1ul << TARGET_VIRT_ADDR_SPACE_BITS) - 1)
82 #  endif
83 # else
84 #  define MAX_RESERVED_VA  0
85 # endif
86 #endif
87 
88 /*
89  * That said, reserving *too* much vm space via mmap can run into problems
90  * with rlimits, oom due to page table creation, etc.  We will still try it,
91  * if directed by the command-line option, but not by default.
92  */
93 #if HOST_LONG_BITS == 64 && TARGET_VIRT_ADDR_SPACE_BITS <= 32
94 unsigned long reserved_va = MAX_RESERVED_VA;
95 #else
96 unsigned long reserved_va;
97 #endif
98 
99 const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
100 const char *qemu_uname_release;
101 char qemu_proc_pathname[PATH_MAX];  /* full path to exeutable */
102 
103 unsigned long target_maxtsiz = TARGET_MAXTSIZ;   /* max text size */
104 unsigned long target_dfldsiz = TARGET_DFLDSIZ;   /* initial data size limit */
105 unsigned long target_maxdsiz = TARGET_MAXDSIZ;   /* max data size */
106 unsigned long target_dflssiz = TARGET_DFLSSIZ;   /* initial data size limit */
107 unsigned long target_maxssiz = TARGET_MAXSSIZ;   /* max stack size */
108 unsigned long target_sgrowsiz = TARGET_SGROWSIZ; /* amount to grow stack */
109 
110 /* Helper routines for implementing atomic operations. */
111 
112 void fork_start(void)
113 {
114     start_exclusive();
115     cpu_list_lock();
116     mmap_fork_start();
117     gdbserver_fork_start();
118 }
119 
120 void fork_end(pid_t pid)
121 {
122     bool child = pid == 0;
123 
124     if (child) {
125         CPUState *cpu, *next_cpu;
126         /*
127          * Child processes created by fork() only have a single thread.  Discard
128          * information about the parent threads.
129          */
130         CPU_FOREACH_SAFE(cpu, next_cpu) {
131             if (cpu != thread_cpu) {
132                 QTAILQ_REMOVE_RCU(&cpus_queue, cpu, node);
133             }
134         }
135         mmap_fork_end(child);
136         /*
137          * qemu_init_cpu_list() takes care of reinitializing the exclusive
138          * state, so we don't need to end_exclusive() here.
139          */
140         qemu_init_cpu_list();
141         get_task_state(thread_cpu)->ts_tid = qemu_get_thread_id();
142         gdbserver_fork_end(thread_cpu, pid);
143     } else {
144         mmap_fork_end(child);
145         cpu_list_unlock();
146         gdbserver_fork_end(thread_cpu, pid);
147         end_exclusive();
148     }
149 }
150 
151 void cpu_loop(CPUArchState *env)
152 {
153     target_cpu_loop(env);
154 }
155 
156 static void usage(void)
157 {
158     printf("qemu-" TARGET_NAME " version " QEMU_FULL_VERSION
159            "\n" QEMU_COPYRIGHT "\n"
160            "usage: qemu-" TARGET_NAME " [options] program [arguments...]\n"
161            "BSD CPU emulator (compiled for %s emulation)\n"
162            "\n"
163            "Standard options:\n"
164            "-h                print this help\n"
165            "-g port           wait gdb connection to port\n"
166            "-L path           set the elf interpreter prefix (default=%s)\n"
167            "-s size           set the stack size in bytes (default=%ld)\n"
168            "-cpu model        select CPU (-cpu help for list)\n"
169            "-drop-ld-preload  drop LD_PRELOAD for target process\n"
170            "-E var=value      sets/modifies targets environment variable(s)\n"
171            "-U var            unsets targets environment variable(s)\n"
172            "-B address        set guest_base address to address\n"
173            "\n"
174            "Debug options:\n"
175            "-d item1[,...]    enable logging of specified items\n"
176            "                  (use '-d help' for a list of log items)\n"
177            "-D logfile        write logs to 'logfile' (default stderr)\n"
178            "-one-insn-per-tb  run with one guest instruction per emulated TB\n"
179            "-strace           log system calls\n"
180            "-trace            [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
181            "                  specify tracing options\n"
182            "\n"
183            "Environment variables:\n"
184            "QEMU_STRACE       Print system calls and arguments similar to the\n"
185            "                  'strace' program.  Enable by setting to any value.\n"
186            "You can use -E and -U options to set/unset environment variables\n"
187            "for target process.  It is possible to provide several variables\n"
188            "by repeating the option.  For example:\n"
189            "    -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n"
190            "Note that if you provide several changes to single variable\n"
191            "last change will stay in effect.\n"
192            "\n"
193            QEMU_HELP_BOTTOM "\n"
194            ,
195            TARGET_NAME,
196            interp_prefix,
197            target_dflssiz);
198     exit(1);
199 }
200 
201 __thread CPUState *thread_cpu;
202 
203 void stop_all_tasks(void)
204 {
205     /*
206      * We trust when using NPTL (pthreads) start_exclusive() handles thread
207      * stopping correctly.
208      */
209     start_exclusive();
210 }
211 
212 bool qemu_cpu_is_self(CPUState *cpu)
213 {
214     return thread_cpu == cpu;
215 }
216 
217 void qemu_cpu_kick(CPUState *cpu)
218 {
219     cpu_exit(cpu);
220 }
221 
222 /* Assumes contents are already zeroed.  */
223 static void init_task_state(TaskState *ts)
224 {
225     ts->sigaltstack_used = (struct target_sigaltstack) {
226         .ss_sp = 0,
227         .ss_size = 0,
228         .ss_flags = TARGET_SS_DISABLE,
229     };
230 }
231 
232 void gemu_log(const char *fmt, ...)
233 {
234     va_list ap;
235 
236     va_start(ap, fmt);
237     vfprintf(stderr, fmt, ap);
238     va_end(ap);
239 }
240 
241 static void
242 adjust_ssize(void)
243 {
244     struct rlimit rl;
245 
246     if (getrlimit(RLIMIT_STACK, &rl) != 0) {
247         return;
248     }
249 
250     target_maxssiz = MIN(target_maxssiz, rl.rlim_max);
251     target_dflssiz = MIN(MAX(target_dflssiz, rl.rlim_cur), target_maxssiz);
252 
253     rl.rlim_max = target_maxssiz;
254     rl.rlim_cur = target_dflssiz;
255     setrlimit(RLIMIT_STACK, &rl);
256 }
257 
258 static void save_proc_pathname(char *argv0)
259 {
260     int mib[4];
261     size_t len;
262 
263     mib[0] = CTL_KERN;
264     mib[1] = KERN_PROC;
265     mib[2] = KERN_PROC_PATHNAME;
266     mib[3] = -1;
267 
268     len = sizeof(qemu_proc_pathname);
269     if (sysctl(mib, 4, qemu_proc_pathname, &len, NULL, 0)) {
270         perror("sysctl");
271     }
272 }
273 
274 int main(int argc, char **argv)
275 {
276     const char *filename;
277     const char *cpu_model;
278     const char *cpu_type;
279     const char *log_file = NULL;
280     const char *log_mask = NULL;
281     const char *seed_optarg = NULL;
282     struct target_pt_regs regs1, *regs = &regs1;
283     struct image_info info1, *info = &info1;
284     struct bsd_binprm bprm;
285     TaskState *ts;
286     CPUArchState *env;
287     CPUState *cpu;
288     int optind, rv;
289     const char *r;
290     const char *gdbstub = NULL;
291     char **target_environ, **wrk;
292     envlist_t *envlist = NULL;
293     char *argv0 = NULL;
294 
295     adjust_ssize();
296 
297     if (argc <= 1) {
298         usage();
299     }
300 
301     save_proc_pathname(argv[0]);
302 
303     error_init(argv[0]);
304     module_call_init(MODULE_INIT_TRACE);
305     qemu_init_cpu_list();
306     module_call_init(MODULE_INIT_QOM);
307 
308     envlist = envlist_create();
309 
310     /*
311      * add current environment into the list
312      * envlist_setenv adds to the front of the list; to preserve environ
313      * order add from back to front
314      */
315     for (wrk = environ; *wrk != NULL; wrk++) {
316         continue;
317     }
318     while (wrk != environ) {
319         wrk--;
320         (void) envlist_setenv(envlist, *wrk);
321     }
322 
323     qemu_host_page_size = getpagesize();
324     qemu_host_page_size = MAX(qemu_host_page_size, TARGET_PAGE_SIZE);
325 
326     cpu_model = NULL;
327 
328     qemu_add_opts(&qemu_trace_opts);
329 
330     optind = 1;
331     for (;;) {
332         if (optind >= argc) {
333             break;
334         }
335         r = argv[optind];
336         if (r[0] != '-') {
337             break;
338         }
339         optind++;
340         r++;
341         if (!strcmp(r, "-")) {
342             break;
343         } else if (!strcmp(r, "d")) {
344             if (optind >= argc) {
345                 break;
346             }
347             log_mask = argv[optind++];
348         } else if (!strcmp(r, "D")) {
349             if (optind >= argc) {
350                 break;
351             }
352             log_file = argv[optind++];
353         } else if (!strcmp(r, "E")) {
354             r = argv[optind++];
355             if (envlist_setenv(envlist, r) != 0) {
356                 usage();
357             }
358         } else if (!strcmp(r, "ignore-environment")) {
359             envlist_free(envlist);
360             envlist = envlist_create();
361         } else if (!strcmp(r, "U")) {
362             r = argv[optind++];
363             if (envlist_unsetenv(envlist, r) != 0) {
364                 usage();
365             }
366         } else if (!strcmp(r, "s")) {
367             r = argv[optind++];
368             rv = qemu_strtoul(r, &r, 0, &target_dflssiz);
369             if (rv < 0 || target_dflssiz <= 0) {
370                 usage();
371             }
372             if (*r == 'M') {
373                 target_dflssiz *= 1024 * 1024;
374             } else if (*r == 'k' || *r == 'K') {
375                 target_dflssiz *= 1024;
376             }
377             if (target_dflssiz > target_maxssiz) {
378                 usage();
379             }
380         } else if (!strcmp(r, "L")) {
381             interp_prefix = argv[optind++];
382         } else if (!strcmp(r, "p")) {
383             unsigned size, want = qemu_real_host_page_size();
384 
385             r = argv[optind++];
386             if (qemu_strtoui(r, NULL, 10, &size) || size != want) {
387                 warn_report("Deprecated page size option cannot "
388                             "change host page size (%u)", want);
389             }
390         } else if (!strcmp(r, "g")) {
391             gdbstub = g_strdup(argv[optind++]);
392         } else if (!strcmp(r, "r")) {
393             qemu_uname_release = argv[optind++];
394         } else if (!strcmp(r, "cpu")) {
395             cpu_model = argv[optind++];
396             if (is_help_option(cpu_model)) {
397                 list_cpus();
398                 exit(1);
399             }
400         } else if (!strcmp(r, "B")) {
401             rv = qemu_strtoul(argv[optind++], NULL, 0, &guest_base);
402             if (rv < 0) {
403                 usage();
404             }
405             have_guest_base = true;
406         } else if (!strcmp(r, "drop-ld-preload")) {
407             (void) envlist_unsetenv(envlist, "LD_PRELOAD");
408         } else if (!strcmp(r, "seed")) {
409             seed_optarg = optarg;
410         } else if (!strcmp(r, "one-insn-per-tb")) {
411             opt_one_insn_per_tb = true;
412         } else if (!strcmp(r, "strace")) {
413             do_strace = 1;
414         } else if (!strcmp(r, "trace")) {
415             trace_opt_parse(optarg);
416         } else if (!strcmp(r, "0")) {
417             argv0 = argv[optind++];
418         } else {
419             usage();
420         }
421     }
422 
423     qemu_host_page_mask = -qemu_host_page_size;
424 
425     /* init debug */
426     {
427         int mask = 0;
428         if (log_mask) {
429             mask = qemu_str_to_log_mask(log_mask);
430             if (!mask) {
431                 qemu_print_log_usage(stdout);
432                 exit(1);
433             }
434         }
435         qemu_set_log_filename_flags(log_file, mask, &error_fatal);
436     }
437 
438     if (optind >= argc) {
439         usage();
440     }
441     filename = argv[optind];
442     if (argv0) {
443         argv[optind] = argv0;
444     }
445 
446     if (!trace_init_backends()) {
447         exit(1);
448     }
449     trace_init_file();
450 
451     /* Zero out regs */
452     memset(regs, 0, sizeof(struct target_pt_regs));
453 
454     /* Zero bsd params */
455     memset(&bprm, 0, sizeof(bprm));
456 
457     /* Zero out image_info */
458     memset(info, 0, sizeof(struct image_info));
459 
460     /* Scan interp_prefix dir for replacement files. */
461     init_paths(interp_prefix);
462 
463     if (cpu_model == NULL) {
464         cpu_model = TARGET_DEFAULT_CPU_MODEL;
465     }
466 
467     cpu_type = parse_cpu_option(cpu_model);
468 
469     /* init tcg before creating CPUs and to get qemu_host_page_size */
470     {
471         AccelState *accel = current_accel();
472         AccelClass *ac = ACCEL_GET_CLASS(accel);
473 
474         accel_init_interfaces(ac);
475         object_property_set_bool(OBJECT(accel), "one-insn-per-tb",
476                                  opt_one_insn_per_tb, &error_abort);
477         ac->init_machine(NULL);
478     }
479     cpu = cpu_create(cpu_type);
480     env = cpu_env(cpu);
481     cpu_reset(cpu);
482     thread_cpu = cpu;
483 
484     if (getenv("QEMU_STRACE")) {
485         do_strace = 1;
486     }
487 
488     target_environ = envlist_to_environ(envlist, NULL);
489     envlist_free(envlist);
490 
491     {
492         Error *err = NULL;
493         if (seed_optarg != NULL) {
494             qemu_guest_random_seed_main(seed_optarg, &err);
495         } else {
496             qcrypto_init(&err);
497         }
498         if (err) {
499             error_reportf_err(err, "cannot initialize crypto: ");
500             exit(1);
501         }
502     }
503 
504     /*
505      * Now that page sizes are configured we can do
506      * proper page alignment for guest_base.
507      */
508     if (have_guest_base) {
509         if (guest_base & ~qemu_host_page_mask) {
510             error_report("Selected guest base not host page aligned");
511             exit(1);
512         }
513     }
514 
515     /*
516      * If reserving host virtual address space, do so now.
517      * Combined with '-B', ensure that the chosen range is free.
518      */
519     if (reserved_va) {
520         void *p;
521 
522         if (have_guest_base) {
523             p = mmap((void *)guest_base, reserved_va + 1, PROT_NONE,
524                      MAP_ANON | MAP_PRIVATE | MAP_FIXED | MAP_EXCL, -1, 0);
525         } else {
526             p = mmap(NULL, reserved_va + 1, PROT_NONE,
527                      MAP_ANON | MAP_PRIVATE, -1, 0);
528         }
529         if (p == MAP_FAILED) {
530             const char *err = strerror(errno);
531             char *sz = size_to_str(reserved_va + 1);
532 
533             if (have_guest_base) {
534                 error_report("Cannot allocate %s bytes at -B %p for guest "
535                              "address space: %s", sz, (void *)guest_base, err);
536             } else {
537                 error_report("Cannot allocate %s bytes for guest "
538                              "address space: %s", sz, err);
539             }
540             exit(1);
541         }
542         guest_base = (uintptr_t)p;
543         have_guest_base = true;
544 
545         /* Ensure that mmap_next_start is within range. */
546         if (reserved_va <= mmap_next_start) {
547             mmap_next_start = (reserved_va / 4 * 3)
548                               & TARGET_PAGE_MASK & qemu_host_page_mask;
549         }
550     }
551 
552     if (loader_exec(filename, argv + optind, target_environ, regs, info,
553                     &bprm) != 0) {
554         printf("Error loading %s\n", filename);
555         _exit(1);
556     }
557 
558     for (wrk = target_environ; *wrk; wrk++) {
559         g_free(*wrk);
560     }
561 
562     g_free(target_environ);
563 
564     if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
565         FILE *f = qemu_log_trylock();
566         if (f) {
567             fprintf(f, "guest_base  %p\n", (void *)guest_base);
568             fprintf(f, "page layout changed following binary load\n");
569             page_dump(f);
570 
571             fprintf(f, "end_code    0x" TARGET_ABI_FMT_lx "\n",
572                     info->end_code);
573             fprintf(f, "start_code  0x" TARGET_ABI_FMT_lx "\n",
574                     info->start_code);
575             fprintf(f, "start_data  0x" TARGET_ABI_FMT_lx "\n",
576                     info->start_data);
577             fprintf(f, "end_data    0x" TARGET_ABI_FMT_lx "\n",
578                     info->end_data);
579             fprintf(f, "start_stack 0x" TARGET_ABI_FMT_lx "\n",
580                     info->start_stack);
581             fprintf(f, "brk         0x" TARGET_ABI_FMT_lx "\n", info->brk);
582             fprintf(f, "entry       0x" TARGET_ABI_FMT_lx "\n", info->entry);
583 
584             qemu_log_unlock(f);
585         }
586     }
587 
588     /* build Task State */
589     ts = g_new0(TaskState, 1);
590     init_task_state(ts);
591     ts->info = info;
592     ts->bprm = &bprm;
593     cpu->opaque = ts;
594 
595     target_set_brk(info->brk);
596     syscall_init();
597     signal_init();
598 
599     /*
600      * Now that we've loaded the binary, GUEST_BASE is fixed.  Delay
601      * generating the prologue until now so that the prologue can take
602      * the real value of GUEST_BASE into account.
603      */
604     tcg_prologue_init();
605 
606     target_cpu_init(env, regs);
607 
608     if (gdbstub) {
609         gdbserver_start(gdbstub);
610         gdb_handlesig(cpu, 0, NULL, NULL, 0);
611     }
612     cpu_loop(env);
613     /* never exits */
614     return 0;
615 }
616