]> git.proxmox.com Git - mirror_qemu.git/blame - bsd-user/main.c
bsd-user: add host-os.h
[mirror_qemu.git] / bsd-user / main.c
CommitLineData
84778508 1/*
4c0a4fe6 2 * qemu bsd user main
84778508
BS
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
4c0a4fe6 5 * Copyright (c) 2013-14 Stacey Son
84778508
BS
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
8167ee88 18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
84778508 19 */
14a48c1d 20
2231197c 21#include "qemu/osdep.h"
a8d25326 22#include "qemu-common.h"
66d26ddb 23#include "qemu/units.h"
940e43aa 24#include "qemu/accel.h"
14a48c1d 25#include "sysemu/tcg.h"
8c1c230a 26#include "qemu-version.h"
84778508
BS
27#include <machine/trap.h>
28
daa76aa4 29#include "qapi/error.h"
84778508 30#include "qemu.h"
6913e79c 31#include "qemu/config-file.h"
f5852efa 32#include "qemu/error-report.h"
f348b6d1
VB
33#include "qemu/path.h"
34#include "qemu/help_option.h"
0b8fa32f 35#include "qemu/module.h"
63c91552 36#include "exec/exec-all.h"
dcb32f1d 37#include "tcg/tcg.h"
1de7afc9
PB
38#include "qemu/timer.h"
39#include "qemu/envlist.h"
29aabb4f 40#include "qemu/cutils.h"
508127e2 41#include "exec/log.h"
6913e79c 42#include "trace/control.h"
fc0d96b4 43
1b530a6d 44int singlestep;
2fa5d9ba 45unsigned long mmap_min_addr;
5ca870b9 46uintptr_t guest_base;
e307c192 47bool have_guest_base;
d6ef40bf 48unsigned long reserved_va;
1b530a6d 49
7ee2822c 50static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
fccae322 51const char *qemu_uname_release;
78cfb07f 52enum BSDType bsd_type;
84778508 53
34bc8475
WL
54/*
55 * XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
56 * we allocate a bigger stack. Need a better solution, for example
57 * by remapping the process stack directly at the right place
58 */
84778508
BS
59unsigned long x86_stack_size = 512 * 1024;
60
61void gemu_log(const char *fmt, ...)
62{
63 va_list ap;
64
65 va_start(ap, fmt);
66 vfprintf(stderr, fmt, ap);
67 va_end(ap);
68}
9399f095 69
31fc12df 70#if defined(TARGET_I386)
b98e9ca8 71int cpu_get_pic_interrupt(CPUX86State *env)
31fc12df
BS
72{
73 return -1;
74}
75#endif
76
9399f095
BS
77void fork_start(void)
78{
79}
80
81void fork_end(int child)
82{
83 if (child) {
f7ec7f7b 84 gdbserver_fork(thread_cpu);
9399f095
BS
85 }
86}
87
31fc12df
BS
88#ifdef TARGET_I386
89/***********************************************************/
90/* CPUX86 core interface */
91
31fc12df
BS
92uint64_t cpu_get_tsc(CPUX86State *env)
93{
4a7428c5 94 return cpu_get_host_ticks();
31fc12df
BS
95}
96
97static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
98 int flags)
99{
100 unsigned int e1, e2;
101 uint32_t *p;
102 e1 = (addr << 16) | (limit & 0xffff);
103 e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
104 e2 |= flags;
105 p = ptr;
106 p[0] = tswap32(e1);
107 p[1] = tswap32(e2);
108}
109
110static uint64_t *idt_table;
111#ifdef TARGET_X86_64
112static void set_gate64(void *ptr, unsigned int type, unsigned int dpl,
113 uint64_t addr, unsigned int sel)
114{
115 uint32_t *p, e1, e2;
116 e1 = (addr & 0xffff) | (sel << 16);
117 e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
118 p = ptr;
119 p[0] = tswap32(e1);
120 p[1] = tswap32(e2);
121 p[2] = tswap32(addr >> 32);
122 p[3] = 0;
123}
124/* only dpl matters as we do only user space emulation */
125static void set_idt(int n, unsigned int dpl)
126{
127 set_gate64(idt_table + n * 2, 0, dpl, 0, 0);
128}
129#else
130static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
131 uint32_t addr, unsigned int sel)
132{
133 uint32_t *p, e1, e2;
134 e1 = (addr & 0xffff) | (sel << 16);
135 e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
136 p = ptr;
137 p[0] = tswap32(e1);
138 p[1] = tswap32(e2);
139}
140
141/* only dpl matters as we do only user space emulation */
142static void set_idt(int n, unsigned int dpl)
143{
144 set_gate(idt_table + n, 0, dpl, 0, 0);
145}
146#endif
147
78cfb07f 148void cpu_loop(CPUX86State *env)
31fc12df 149{
6aa9e42f 150 CPUState *cs = env_cpu(env);
31fc12df
BS
151 int trapnr;
152 abi_ulong pc;
81afda4a 153 /* target_siginfo_t info; */
31fc12df 154
d60c3b93 155 for (;;) {
d148d90e 156 cpu_exec_start(cs);
ded554cd 157 trapnr = cpu_exec(cs);
d148d90e
SF
158 cpu_exec_end(cs);
159 process_queued_cpu_work(cs);
160
d60c3b93 161 switch (trapnr) {
31fc12df
BS
162 case 0x80:
163 /* syscall from int $0x80 */
78cfb07f
JL
164 if (bsd_type == target_freebsd) {
165 abi_ulong params = (abi_ulong) env->regs[R_ESP] +
166 sizeof(int32_t);
167 int32_t syscall_nr = env->regs[R_EAX];
168 int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
169
170 if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
171 get_user_s32(syscall_nr, params);
172 params += sizeof(int32_t);
173 } else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
174 get_user_s32(syscall_nr, params);
175 params += sizeof(int64_t);
176 }
177 get_user_s32(arg1, params);
178 params += sizeof(int32_t);
179 get_user_s32(arg2, params);
180 params += sizeof(int32_t);
181 get_user_s32(arg3, params);
182 params += sizeof(int32_t);
183 get_user_s32(arg4, params);
184 params += sizeof(int32_t);
185 get_user_s32(arg5, params);
186 params += sizeof(int32_t);
187 get_user_s32(arg6, params);
188 params += sizeof(int32_t);
189 get_user_s32(arg7, params);
190 params += sizeof(int32_t);
191 get_user_s32(arg8, params);
192 env->regs[R_EAX] = do_freebsd_syscall(env,
193 syscall_nr,
194 arg1,
195 arg2,
196 arg3,
197 arg4,
198 arg5,
199 arg6,
200 arg7,
201 arg8);
81afda4a 202 } else { /* if (bsd_type == target_openbsd) */
78cfb07f
JL
203 env->regs[R_EAX] = do_openbsd_syscall(env,
204 env->regs[R_EAX],
205 env->regs[R_EBX],
206 env->regs[R_ECX],
207 env->regs[R_EDX],
208 env->regs[R_ESI],
209 env->regs[R_EDI],
210 env->regs[R_EBP]);
211 }
212 if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
213 env->regs[R_EAX] = -env->regs[R_EAX];
214 env->eflags |= CC_C;
215 } else {
216 env->eflags &= ~CC_C;
217 }
31fc12df
BS
218 break;
219#ifndef TARGET_ABI32
220 case EXCP_SYSCALL:
5ba18547 221 /* syscall from syscall instruction */
b23a51dc 222 if (bsd_type == target_freebsd) {
78cfb07f
JL
223 env->regs[R_EAX] = do_freebsd_syscall(env,
224 env->regs[R_EAX],
225 env->regs[R_EDI],
226 env->regs[R_ESI],
227 env->regs[R_EDX],
228 env->regs[R_ECX],
229 env->regs[8],
230 env->regs[9], 0, 0);
b23a51dc 231 } else { /* if (bsd_type == target_openbsd) */
78cfb07f
JL
232 env->regs[R_EAX] = do_openbsd_syscall(env,
233 env->regs[R_EAX],
234 env->regs[R_EDI],
235 env->regs[R_ESI],
236 env->regs[R_EDX],
237 env->regs[10],
238 env->regs[8],
239 env->regs[9]);
240 }
31fc12df 241 env->eip = env->exception_next_eip;
78cfb07f
JL
242 if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
243 env->regs[R_EAX] = -env->regs[R_EAX];
244 env->eflags |= CC_C;
245 } else {
246 env->eflags &= ~CC_C;
247 }
31fc12df 248 break;
31fc12df
BS
249#endif
250 case EXCP_INTERRUPT:
251 /* just indicate that signals should be handled asap */
252 break;
31fc12df
BS
253 default:
254 pc = env->segs[R_CS].base + env->eip;
b23a51dc
WL
255 fprintf(stderr,
256 "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
31fc12df
BS
257 (long)pc, trapnr);
258 abort();
259 }
260 process_pending_signals(env);
261 }
262}
263#endif
264
84778508
BS
265static void usage(void)
266{
7e563bfb 267 printf("qemu-" TARGET_NAME " version " QEMU_FULL_VERSION
0781dd6e 268 "\n" QEMU_COPYRIGHT "\n"
2e59915d 269 "usage: qemu-" TARGET_NAME " [options] program [arguments...]\n"
84778508
BS
270 "BSD CPU emulator (compiled for %s emulation)\n"
271 "\n"
272 "Standard options:\n"
273 "-h print this help\n"
274 "-g port wait gdb connection to port\n"
275 "-L path set the elf interpreter prefix (default=%s)\n"
276 "-s size set the stack size in bytes (default=%ld)\n"
c8057f95 277 "-cpu model select CPU (-cpu help for list)\n"
84778508 278 "-drop-ld-preload drop LD_PRELOAD for target process\n"
fc0d96b4
BS
279 "-E var=value sets/modifies targets environment variable(s)\n"
280 "-U var unsets targets environment variable(s)\n"
2fa5d9ba 281 "-B address set guest_base address to address\n"
84778508
BS
282 "-bsd type select emulated BSD type FreeBSD/NetBSD/OpenBSD (default)\n"
283 "\n"
284 "Debug options:\n"
989b697d
PM
285 "-d item1[,...] enable logging of specified items\n"
286 " (use '-d help' for a list of log items)\n"
287 "-D logfile write logs to 'logfile' (default stderr)\n"
288 "-p pagesize set the host page size to 'pagesize'\n"
289 "-singlestep always run in singlestep mode\n"
290 "-strace log system calls\n"
6913e79c
LV
291 "-trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
292 " specify tracing options\n"
84778508
BS
293 "\n"
294 "Environment variables:\n"
295 "QEMU_STRACE Print system calls and arguments similar to the\n"
296 " 'strace' program. Enable by setting to any value.\n"
fc0d96b4
BS
297 "You can use -E and -U options to set/unset environment variables\n"
298 "for target process. It is possible to provide several variables\n"
299 "by repeating the option. For example:\n"
300 " -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n"
301 "Note that if you provide several changes to single variable\n"
302 "last change will stay in effect.\n"
f5048cb7
EB
303 "\n"
304 QEMU_HELP_BOTTOM "\n"
84778508 305 ,
2e59915d 306 TARGET_NAME,
84778508 307 interp_prefix,
989b697d 308 x86_stack_size);
2d18e637 309 exit(1);
84778508
BS
310}
311
d42df502 312__thread CPUState *thread_cpu;
84778508 313
48f59211
EM
314bool qemu_cpu_is_self(CPUState *cpu)
315{
316 return thread_cpu == cpu;
317}
318
319void qemu_cpu_kick(CPUState *cpu)
320{
321 cpu_exit(cpu);
322}
323
84778508
BS
324/* Assumes contents are already zeroed. */
325void init_task_state(TaskState *ts)
326{
327 int i;
328
329 ts->used = 1;
330 ts->first_free = ts->sigqueue_table;
331 for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) {
332 ts->sigqueue_table[i].next = &ts->sigqueue_table[i + 1];
333 }
334 ts->sigqueue_table[i].next = NULL;
335}
336
337int main(int argc, char **argv)
338{
339 const char *filename;
340 const char *cpu_model;
2278b939 341 const char *cpu_type;
989b697d 342 const char *log_file = NULL;
c235d738 343 const char *log_mask = NULL;
84778508
BS
344 struct target_pt_regs regs1, *regs = &regs1;
345 struct image_info info1, *info = &info1;
d37853f9 346 struct bsd_binprm bprm;
84778508 347 TaskState ts1, *ts = &ts1;
9349b4f9 348 CPUArchState *env;
db6b81d4 349 CPUState *cpu;
29aabb4f 350 int optind, rv;
84778508 351 const char *r;
fcedd920 352 const char *gdbstub = NULL;
fc0d96b4
BS
353 char **target_environ, **wrk;
354 envlist_t *envlist = NULL;
78cfb07f 355 bsd_type = target_openbsd;
84778508 356
b23a51dc 357 if (argc <= 1) {
84778508 358 usage();
b23a51dc 359 }
84778508 360
f5852efa 361 error_init(argv[0]);
fe4db84d 362 module_call_init(MODULE_INIT_TRACE);
267f685b 363 qemu_init_cpu_list();
ce008c1f
AF
364 module_call_init(MODULE_INIT_QOM);
365
ec45bbe5 366 envlist = envlist_create();
fc0d96b4
BS
367
368 /* add current environment into the list */
369 for (wrk = environ; *wrk != NULL; wrk++) {
370 (void) envlist_setenv(envlist, *wrk);
371 }
372
84778508 373 cpu_model = NULL;
0c62de2f 374
6913e79c
LV
375 qemu_add_opts(&qemu_trace_opts);
376
84778508 377 optind = 1;
6913e79c 378 for (;;) {
b23a51dc 379 if (optind >= argc) {
84778508 380 break;
b23a51dc 381 }
84778508 382 r = argv[optind];
b23a51dc 383 if (r[0] != '-') {
84778508 384 break;
b23a51dc 385 }
84778508
BS
386 optind++;
387 r++;
388 if (!strcmp(r, "-")) {
389 break;
390 } else if (!strcmp(r, "d")) {
c235d738 391 if (optind >= argc) {
84778508 392 break;
84778508 393 }
c235d738
MF
394 log_mask = argv[optind++];
395 } else if (!strcmp(r, "D")) {
396 if (optind >= argc) {
397 break;
398 }
399 log_file = argv[optind++];
fc0d96b4
BS
400 } else if (!strcmp(r, "E")) {
401 r = argv[optind++];
b23a51dc 402 if (envlist_setenv(envlist, r) != 0) {
fc0d96b4 403 usage();
b23a51dc 404 }
f66724c9
SW
405 } else if (!strcmp(r, "ignore-environment")) {
406 envlist_free(envlist);
ec45bbe5 407 envlist = envlist_create();
fc0d96b4
BS
408 } else if (!strcmp(r, "U")) {
409 r = argv[optind++];
b23a51dc 410 if (envlist_unsetenv(envlist, r) != 0) {
fc0d96b4 411 usage();
b23a51dc 412 }
84778508
BS
413 } else if (!strcmp(r, "s")) {
414 r = argv[optind++];
29aabb4f
WL
415 rv = qemu_strtoul(r, &r, 0, &x86_stack_size);
416 if (rv < 0 || x86_stack_size <= 0) {
84778508 417 usage();
b23a51dc
WL
418 }
419 if (*r == 'M') {
66d26ddb 420 x86_stack_size *= MiB;
b23a51dc 421 } else if (*r == 'k' || *r == 'K') {
66d26ddb 422 x86_stack_size *= KiB;
b23a51dc 423 }
84778508
BS
424 } else if (!strcmp(r, "L")) {
425 interp_prefix = argv[optind++];
426 } else if (!strcmp(r, "p")) {
427 qemu_host_page_size = atoi(argv[optind++]);
428 if (qemu_host_page_size == 0 ||
429 (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
430 fprintf(stderr, "page size must be a power of two\n");
431 exit(1);
432 }
433 } else if (!strcmp(r, "g")) {
fcedd920 434 gdbstub = g_strdup(argv[optind++]);
84778508
BS
435 } else if (!strcmp(r, "r")) {
436 qemu_uname_release = argv[optind++];
437 } else if (!strcmp(r, "cpu")) {
438 cpu_model = argv[optind++];
c8057f95 439 if (is_help_option(cpu_model)) {
d60c3b93 440 /* XXX: implement xxx_cpu_list for targets that still miss it */
84778508 441#if defined(cpu_list)
d60c3b93 442 cpu_list();
84778508 443#endif
2d18e637 444 exit(1);
84778508 445 }
2fa5d9ba 446 } else if (!strcmp(r, "B")) {
29aabb4f
WL
447 rv = qemu_strtoul(argv[optind++], NULL, 0, &guest_base);
448 if (rv < 0) {
449 usage();
450 }
d60c3b93 451 have_guest_base = true;
84778508 452 } else if (!strcmp(r, "drop-ld-preload")) {
fc0d96b4 453 (void) envlist_unsetenv(envlist, "LD_PRELOAD");
84778508
BS
454 } else if (!strcmp(r, "bsd")) {
455 if (!strcasecmp(argv[optind], "freebsd")) {
456 bsd_type = target_freebsd;
457 } else if (!strcasecmp(argv[optind], "netbsd")) {
458 bsd_type = target_netbsd;
459 } else if (!strcasecmp(argv[optind], "openbsd")) {
460 bsd_type = target_openbsd;
461 } else {
462 usage();
463 }
464 optind++;
1b530a6d
AJ
465 } else if (!strcmp(r, "singlestep")) {
466 singlestep = 1;
84778508
BS
467 } else if (!strcmp(r, "strace")) {
468 do_strace = 1;
6913e79c 469 } else if (!strcmp(r, "trace")) {
92eecfff 470 trace_opt_parse(optarg);
6913e79c 471 } else {
84778508
BS
472 usage();
473 }
474 }
84778508 475
c235d738 476 /* init debug */
f2937a33 477 qemu_log_needs_buffers();
daa76aa4 478 qemu_set_log_filename(log_file, &error_fatal);
c235d738
MF
479 if (log_mask) {
480 int mask;
c235d738 481
4fde1eba 482 mask = qemu_str_to_log_mask(log_mask);
c235d738 483 if (!mask) {
59a6fa6e 484 qemu_print_log_usage(stdout);
c235d738
MF
485 exit(1);
486 }
24537a01 487 qemu_set_log(mask);
c235d738
MF
488 }
489
4b5dfd82
PM
490 if (optind >= argc) {
491 usage();
492 }
493 filename = argv[optind];
494
6913e79c
LV
495 if (!trace_init_backends()) {
496 exit(1);
497 }
92eecfff 498 trace_init_file();
6913e79c 499
84778508
BS
500 /* Zero out regs */
501 memset(regs, 0, sizeof(struct target_pt_regs));
502
d37853f9
WL
503 /* Zero bsd params */
504 memset(&bprm, 0, sizeof(bprm));
505
84778508
BS
506 /* Zero out image_info */
507 memset(info, 0, sizeof(struct image_info));
508
509 /* Scan interp_prefix dir for replacement files. */
510 init_paths(interp_prefix);
511
512 if (cpu_model == NULL) {
31fc12df
BS
513#if defined(TARGET_I386)
514#ifdef TARGET_X86_64
515 cpu_model = "qemu64";
516#else
517 cpu_model = "qemu32";
518#endif
84778508
BS
519#else
520 cpu_model = "any";
521#endif
522 }
2b5249b8 523
b86f59c7 524 cpu_type = parse_cpu_option(cpu_model);
2b5249b8 525 /* init tcg before creating CPUs and to get qemu_host_page_size */
940e43aa
CF
526 {
527 AccelClass *ac = ACCEL_GET_CLASS(current_accel());
2b5249b8 528
b86f59c7 529 accel_init_interfaces(ac);
92242f34 530 ac->init_machine(NULL);
940e43aa 531 }
2278b939 532 cpu = cpu_create(cpu_type);
2994fd96 533 env = cpu->env_ptr;
db6b81d4 534 cpu_reset(cpu);
db6b81d4 535 thread_cpu = cpu;
84778508
BS
536
537 if (getenv("QEMU_STRACE")) {
538 do_strace = 1;
539 }
540
fc0d96b4
BS
541 target_environ = envlist_to_environ(envlist, NULL);
542 envlist_free(envlist);
543
2fa5d9ba 544 /*
fa79cde6 545 * Now that page sizes are configured we can do
2fa5d9ba
BS
546 * proper page alignment for guest_base.
547 */
548 guest_base = HOST_PAGE_ALIGN(guest_base);
549
550 /*
551 * Read in mmap_min_addr kernel parameter. This value is used
552 * When loading the ELF image to determine whether guest_base
553 * is needed.
554 *
555 * When user has explicitly set the quest base, we skip this
556 * test.
557 */
558 if (!have_guest_base) {
559 FILE *fp;
560
b23a51dc
WL
561 fp = fopen("/proc/sys/vm/mmap_min_addr", "r");
562 if (fp != NULL) {
2fa5d9ba
BS
563 unsigned long tmp;
564 if (fscanf(fp, "%lu", &tmp) == 1) {
565 mmap_min_addr = tmp;
b23a51dc
WL
566 qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n",
567 mmap_min_addr);
2fa5d9ba
BS
568 }
569 fclose(fp);
570 }
571 }
84778508 572
d37853f9
WL
573 if (loader_exec(filename, argv + optind, target_environ, regs, info,
574 &bprm) != 0) {
84778508
BS
575 printf("Error loading %s\n", filename);
576 _exit(1);
577 }
578
579 for (wrk = target_environ; *wrk; wrk++) {
ec45bbe5 580 g_free(*wrk);
84778508
BS
581 }
582
ec45bbe5 583 g_free(target_environ);
84778508 584
13829020 585 if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
5ca870b9 586 qemu_log("guest_base %p\n", (void *)guest_base);
10d0d505 587 log_page_dump("binary load");
2e77eac6
BS
588
589 qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
590 qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code);
591 qemu_log("start_code 0x" TARGET_ABI_FMT_lx "\n",
592 info->start_code);
593 qemu_log("start_data 0x" TARGET_ABI_FMT_lx "\n",
594 info->start_data);
595 qemu_log("end_data 0x" TARGET_ABI_FMT_lx "\n", info->end_data);
596 qemu_log("start_stack 0x" TARGET_ABI_FMT_lx "\n",
597 info->start_stack);
598 qemu_log("brk 0x" TARGET_ABI_FMT_lx "\n", info->brk);
599 qemu_log("entry 0x" TARGET_ABI_FMT_lx "\n", info->entry);
600 }
84778508
BS
601
602 target_set_brk(info->brk);
603 syscall_init();
604 signal_init();
605
34bc8475
WL
606 /*
607 * Now that we've loaded the binary, GUEST_BASE is fixed. Delay
608 * generating the prologue until now so that the prologue can take
609 * the real value of GUEST_BASE into account.
610 */
b1311c4a 611 tcg_prologue_init(tcg_ctx);
9002ec79 612
84778508
BS
613 /* build Task State */
614 memset(ts, 0, sizeof(TaskState));
615 init_task_state(ts);
616 ts->info = info;
0429a971 617 cpu->opaque = ts;
84778508 618
31fc12df 619#if defined(TARGET_I386)
31fc12df 620 env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
b98dbc90 621 env->hflags |= HF_PE_MASK | HF_CPL_MASK;
0514ef2f 622 if (env->features[FEAT_1_EDX] & CPUID_SSE) {
31fc12df
BS
623 env->cr[4] |= CR4_OSFXSR_MASK;
624 env->hflags |= HF_OSFXSR_MASK;
625 }
626#ifndef TARGET_ABI32
627 /* enable 64 bit mode if possible */
0514ef2f 628 if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
31fc12df
BS
629 fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
630 exit(1);
631 }
632 env->cr[4] |= CR4_PAE_MASK;
633 env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
634 env->hflags |= HF_LMA_MASK;
635#endif
636
637 /* flags setup : we activate the IRQs by default as in user mode */
638 env->eflags |= IF_MASK;
639
640 /* linux register setup */
641#ifndef TARGET_ABI32
642 env->regs[R_EAX] = regs->rax;
643 env->regs[R_EBX] = regs->rbx;
644 env->regs[R_ECX] = regs->rcx;
645 env->regs[R_EDX] = regs->rdx;
646 env->regs[R_ESI] = regs->rsi;
647 env->regs[R_EDI] = regs->rdi;
648 env->regs[R_EBP] = regs->rbp;
649 env->regs[R_ESP] = regs->rsp;
650 env->eip = regs->rip;
651#else
652 env->regs[R_EAX] = regs->eax;
653 env->regs[R_EBX] = regs->ebx;
654 env->regs[R_ECX] = regs->ecx;
655 env->regs[R_EDX] = regs->edx;
656 env->regs[R_ESI] = regs->esi;
657 env->regs[R_EDI] = regs->edi;
658 env->regs[R_EBP] = regs->ebp;
659 env->regs[R_ESP] = regs->esp;
660 env->eip = regs->eip;
661#endif
662
663 /* linux interrupt setup */
664#ifndef TARGET_ABI32
665 env->idt.limit = 511;
666#else
667 env->idt.limit = 255;
668#endif
669 env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
d60c3b93
WL
670 PROT_READ | PROT_WRITE,
671 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
3e8f1628 672 idt_table = g2h_untagged(env->idt.base);
31fc12df
BS
673 set_idt(0, 0);
674 set_idt(1, 0);
675 set_idt(2, 0);
676 set_idt(3, 3);
677 set_idt(4, 3);
678 set_idt(5, 0);
679 set_idt(6, 0);
680 set_idt(7, 0);
681 set_idt(8, 0);
682 set_idt(9, 0);
683 set_idt(10, 0);
684 set_idt(11, 0);
685 set_idt(12, 0);
686 set_idt(13, 0);
687 set_idt(14, 0);
688 set_idt(15, 0);
689 set_idt(16, 0);
690 set_idt(17, 0);
691 set_idt(18, 0);
692 set_idt(19, 0);
693 set_idt(0x80, 3);
694
695 /* linux segment setup */
696 {
697 uint64_t *gdt_table;
698 env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
d60c3b93
WL
699 PROT_READ | PROT_WRITE,
700 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
31fc12df 701 env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
3e8f1628 702 gdt_table = g2h_untagged(env->gdt.base);
31fc12df
BS
703#ifdef TARGET_ABI32
704 write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
705 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
706 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
707#else
708 /* 64 bit code segment */
709 write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
710 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
711 DESC_L_MASK |
712 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
713#endif
714 write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
715 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
716 (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
717 }
718
719 cpu_x86_load_seg(env, R_CS, __USER_CS);
720 cpu_x86_load_seg(env, R_SS, __USER_DS);
721#ifdef TARGET_ABI32
722 cpu_x86_load_seg(env, R_DS, __USER_DS);
723 cpu_x86_load_seg(env, R_ES, __USER_DS);
724 cpu_x86_load_seg(env, R_FS, __USER_DS);
725 cpu_x86_load_seg(env, R_GS, __USER_DS);
726 /* This hack makes Wine work... */
727 env->segs[R_FS].selector = 0;
728#else
729 cpu_x86_load_seg(env, R_DS, 0);
730 cpu_x86_load_seg(env, R_ES, 0);
731 cpu_x86_load_seg(env, R_FS, 0);
732 cpu_x86_load_seg(env, R_GS, 0);
733#endif
84778508
BS
734#else
735#error unsupported target CPU
736#endif
737
fcedd920
AB
738 if (gdbstub) {
739 gdbserver_start(gdbstub);
db6b81d4 740 gdb_handlesig(cpu, 0);
84778508 741 }
78cfb07f 742 cpu_loop(env);
84778508
BS
743 /* never exits */
744 return 0;
745}