]> git.proxmox.com Git - mirror_qemu.git/blame - bsd-user/main.c
bsd-user: move arch specific defines out of elfload.c
[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
dca1173c 312THREAD 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;
346 TaskState ts1, *ts = &ts1;
9349b4f9 347 CPUArchState *env;
db6b81d4 348 CPUState *cpu;
29aabb4f 349 int optind, rv;
84778508 350 const char *r;
fcedd920 351 const char *gdbstub = NULL;
fc0d96b4
BS
352 char **target_environ, **wrk;
353 envlist_t *envlist = NULL;
78cfb07f 354 bsd_type = target_openbsd;
84778508 355
b23a51dc 356 if (argc <= 1) {
84778508 357 usage();
b23a51dc 358 }
84778508 359
f5852efa 360 error_init(argv[0]);
fe4db84d 361 module_call_init(MODULE_INIT_TRACE);
267f685b 362 qemu_init_cpu_list();
ce008c1f
AF
363 module_call_init(MODULE_INIT_QOM);
364
ec45bbe5 365 envlist = envlist_create();
fc0d96b4
BS
366
367 /* add current environment into the list */
368 for (wrk = environ; *wrk != NULL; wrk++) {
369 (void) envlist_setenv(envlist, *wrk);
370 }
371
84778508 372 cpu_model = NULL;
0c62de2f 373
6913e79c
LV
374 qemu_add_opts(&qemu_trace_opts);
375
84778508 376 optind = 1;
6913e79c 377 for (;;) {
b23a51dc 378 if (optind >= argc) {
84778508 379 break;
b23a51dc 380 }
84778508 381 r = argv[optind];
b23a51dc 382 if (r[0] != '-') {
84778508 383 break;
b23a51dc 384 }
84778508
BS
385 optind++;
386 r++;
387 if (!strcmp(r, "-")) {
388 break;
389 } else if (!strcmp(r, "d")) {
c235d738 390 if (optind >= argc) {
84778508 391 break;
84778508 392 }
c235d738
MF
393 log_mask = argv[optind++];
394 } else if (!strcmp(r, "D")) {
395 if (optind >= argc) {
396 break;
397 }
398 log_file = argv[optind++];
fc0d96b4
BS
399 } else if (!strcmp(r, "E")) {
400 r = argv[optind++];
b23a51dc 401 if (envlist_setenv(envlist, r) != 0) {
fc0d96b4 402 usage();
b23a51dc 403 }
f66724c9
SW
404 } else if (!strcmp(r, "ignore-environment")) {
405 envlist_free(envlist);
ec45bbe5 406 envlist = envlist_create();
fc0d96b4
BS
407 } else if (!strcmp(r, "U")) {
408 r = argv[optind++];
b23a51dc 409 if (envlist_unsetenv(envlist, r) != 0) {
fc0d96b4 410 usage();
b23a51dc 411 }
84778508
BS
412 } else if (!strcmp(r, "s")) {
413 r = argv[optind++];
29aabb4f
WL
414 rv = qemu_strtoul(r, &r, 0, &x86_stack_size);
415 if (rv < 0 || x86_stack_size <= 0) {
84778508 416 usage();
b23a51dc
WL
417 }
418 if (*r == 'M') {
66d26ddb 419 x86_stack_size *= MiB;
b23a51dc 420 } else if (*r == 'k' || *r == 'K') {
66d26ddb 421 x86_stack_size *= KiB;
b23a51dc 422 }
84778508
BS
423 } else if (!strcmp(r, "L")) {
424 interp_prefix = argv[optind++];
425 } else if (!strcmp(r, "p")) {
426 qemu_host_page_size = atoi(argv[optind++]);
427 if (qemu_host_page_size == 0 ||
428 (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
429 fprintf(stderr, "page size must be a power of two\n");
430 exit(1);
431 }
432 } else if (!strcmp(r, "g")) {
fcedd920 433 gdbstub = g_strdup(argv[optind++]);
84778508
BS
434 } else if (!strcmp(r, "r")) {
435 qemu_uname_release = argv[optind++];
436 } else if (!strcmp(r, "cpu")) {
437 cpu_model = argv[optind++];
c8057f95 438 if (is_help_option(cpu_model)) {
d60c3b93 439 /* XXX: implement xxx_cpu_list for targets that still miss it */
84778508 440#if defined(cpu_list)
d60c3b93 441 cpu_list();
84778508 442#endif
2d18e637 443 exit(1);
84778508 444 }
2fa5d9ba 445 } else if (!strcmp(r, "B")) {
29aabb4f
WL
446 rv = qemu_strtoul(argv[optind++], NULL, 0, &guest_base);
447 if (rv < 0) {
448 usage();
449 }
d60c3b93 450 have_guest_base = true;
84778508 451 } else if (!strcmp(r, "drop-ld-preload")) {
fc0d96b4 452 (void) envlist_unsetenv(envlist, "LD_PRELOAD");
84778508
BS
453 } else if (!strcmp(r, "bsd")) {
454 if (!strcasecmp(argv[optind], "freebsd")) {
455 bsd_type = target_freebsd;
456 } else if (!strcasecmp(argv[optind], "netbsd")) {
457 bsd_type = target_netbsd;
458 } else if (!strcasecmp(argv[optind], "openbsd")) {
459 bsd_type = target_openbsd;
460 } else {
461 usage();
462 }
463 optind++;
1b530a6d
AJ
464 } else if (!strcmp(r, "singlestep")) {
465 singlestep = 1;
84778508
BS
466 } else if (!strcmp(r, "strace")) {
467 do_strace = 1;
6913e79c 468 } else if (!strcmp(r, "trace")) {
92eecfff 469 trace_opt_parse(optarg);
6913e79c 470 } else {
84778508
BS
471 usage();
472 }
473 }
84778508 474
c235d738 475 /* init debug */
f2937a33 476 qemu_log_needs_buffers();
daa76aa4 477 qemu_set_log_filename(log_file, &error_fatal);
c235d738
MF
478 if (log_mask) {
479 int mask;
c235d738 480
4fde1eba 481 mask = qemu_str_to_log_mask(log_mask);
c235d738 482 if (!mask) {
59a6fa6e 483 qemu_print_log_usage(stdout);
c235d738
MF
484 exit(1);
485 }
24537a01 486 qemu_set_log(mask);
c235d738
MF
487 }
488
4b5dfd82
PM
489 if (optind >= argc) {
490 usage();
491 }
492 filename = argv[optind];
493
6913e79c
LV
494 if (!trace_init_backends()) {
495 exit(1);
496 }
92eecfff 497 trace_init_file();
6913e79c 498
84778508
BS
499 /* Zero out regs */
500 memset(regs, 0, sizeof(struct target_pt_regs));
501
502 /* Zero out image_info */
503 memset(info, 0, sizeof(struct image_info));
504
505 /* Scan interp_prefix dir for replacement files. */
506 init_paths(interp_prefix);
507
508 if (cpu_model == NULL) {
31fc12df
BS
509#if defined(TARGET_I386)
510#ifdef TARGET_X86_64
511 cpu_model = "qemu64";
512#else
513 cpu_model = "qemu32";
514#endif
84778508
BS
515#else
516 cpu_model = "any";
517#endif
518 }
2b5249b8 519
b86f59c7 520 cpu_type = parse_cpu_option(cpu_model);
2b5249b8 521 /* init tcg before creating CPUs and to get qemu_host_page_size */
940e43aa
CF
522 {
523 AccelClass *ac = ACCEL_GET_CLASS(current_accel());
2b5249b8 524
b86f59c7 525 accel_init_interfaces(ac);
92242f34 526 ac->init_machine(NULL);
940e43aa 527 }
2278b939 528 cpu = cpu_create(cpu_type);
2994fd96 529 env = cpu->env_ptr;
db6b81d4 530 cpu_reset(cpu);
db6b81d4 531 thread_cpu = cpu;
84778508
BS
532
533 if (getenv("QEMU_STRACE")) {
534 do_strace = 1;
535 }
536
fc0d96b4
BS
537 target_environ = envlist_to_environ(envlist, NULL);
538 envlist_free(envlist);
539
2fa5d9ba 540 /*
fa79cde6 541 * Now that page sizes are configured we can do
2fa5d9ba
BS
542 * proper page alignment for guest_base.
543 */
544 guest_base = HOST_PAGE_ALIGN(guest_base);
545
546 /*
547 * Read in mmap_min_addr kernel parameter. This value is used
548 * When loading the ELF image to determine whether guest_base
549 * is needed.
550 *
551 * When user has explicitly set the quest base, we skip this
552 * test.
553 */
554 if (!have_guest_base) {
555 FILE *fp;
556
b23a51dc
WL
557 fp = fopen("/proc/sys/vm/mmap_min_addr", "r");
558 if (fp != NULL) {
2fa5d9ba
BS
559 unsigned long tmp;
560 if (fscanf(fp, "%lu", &tmp) == 1) {
561 mmap_min_addr = tmp;
b23a51dc
WL
562 qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n",
563 mmap_min_addr);
2fa5d9ba
BS
564 }
565 fclose(fp);
566 }
567 }
84778508 568
d60c3b93 569 if (loader_exec(filename, argv + optind, target_environ, regs, info) != 0) {
84778508
BS
570 printf("Error loading %s\n", filename);
571 _exit(1);
572 }
573
574 for (wrk = target_environ; *wrk; wrk++) {
ec45bbe5 575 g_free(*wrk);
84778508
BS
576 }
577
ec45bbe5 578 g_free(target_environ);
84778508 579
13829020 580 if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
5ca870b9 581 qemu_log("guest_base %p\n", (void *)guest_base);
10d0d505 582 log_page_dump("binary load");
2e77eac6
BS
583
584 qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
585 qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code);
586 qemu_log("start_code 0x" TARGET_ABI_FMT_lx "\n",
587 info->start_code);
588 qemu_log("start_data 0x" TARGET_ABI_FMT_lx "\n",
589 info->start_data);
590 qemu_log("end_data 0x" TARGET_ABI_FMT_lx "\n", info->end_data);
591 qemu_log("start_stack 0x" TARGET_ABI_FMT_lx "\n",
592 info->start_stack);
593 qemu_log("brk 0x" TARGET_ABI_FMT_lx "\n", info->brk);
594 qemu_log("entry 0x" TARGET_ABI_FMT_lx "\n", info->entry);
595 }
84778508
BS
596
597 target_set_brk(info->brk);
598 syscall_init();
599 signal_init();
600
34bc8475
WL
601 /*
602 * Now that we've loaded the binary, GUEST_BASE is fixed. Delay
603 * generating the prologue until now so that the prologue can take
604 * the real value of GUEST_BASE into account.
605 */
b1311c4a 606 tcg_prologue_init(tcg_ctx);
9002ec79 607
84778508
BS
608 /* build Task State */
609 memset(ts, 0, sizeof(TaskState));
610 init_task_state(ts);
611 ts->info = info;
0429a971 612 cpu->opaque = ts;
84778508 613
31fc12df 614#if defined(TARGET_I386)
31fc12df 615 env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
b98dbc90 616 env->hflags |= HF_PE_MASK | HF_CPL_MASK;
0514ef2f 617 if (env->features[FEAT_1_EDX] & CPUID_SSE) {
31fc12df
BS
618 env->cr[4] |= CR4_OSFXSR_MASK;
619 env->hflags |= HF_OSFXSR_MASK;
620 }
621#ifndef TARGET_ABI32
622 /* enable 64 bit mode if possible */
0514ef2f 623 if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
31fc12df
BS
624 fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
625 exit(1);
626 }
627 env->cr[4] |= CR4_PAE_MASK;
628 env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
629 env->hflags |= HF_LMA_MASK;
630#endif
631
632 /* flags setup : we activate the IRQs by default as in user mode */
633 env->eflags |= IF_MASK;
634
635 /* linux register setup */
636#ifndef TARGET_ABI32
637 env->regs[R_EAX] = regs->rax;
638 env->regs[R_EBX] = regs->rbx;
639 env->regs[R_ECX] = regs->rcx;
640 env->regs[R_EDX] = regs->rdx;
641 env->regs[R_ESI] = regs->rsi;
642 env->regs[R_EDI] = regs->rdi;
643 env->regs[R_EBP] = regs->rbp;
644 env->regs[R_ESP] = regs->rsp;
645 env->eip = regs->rip;
646#else
647 env->regs[R_EAX] = regs->eax;
648 env->regs[R_EBX] = regs->ebx;
649 env->regs[R_ECX] = regs->ecx;
650 env->regs[R_EDX] = regs->edx;
651 env->regs[R_ESI] = regs->esi;
652 env->regs[R_EDI] = regs->edi;
653 env->regs[R_EBP] = regs->ebp;
654 env->regs[R_ESP] = regs->esp;
655 env->eip = regs->eip;
656#endif
657
658 /* linux interrupt setup */
659#ifndef TARGET_ABI32
660 env->idt.limit = 511;
661#else
662 env->idt.limit = 255;
663#endif
664 env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
d60c3b93
WL
665 PROT_READ | PROT_WRITE,
666 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
3e8f1628 667 idt_table = g2h_untagged(env->idt.base);
31fc12df
BS
668 set_idt(0, 0);
669 set_idt(1, 0);
670 set_idt(2, 0);
671 set_idt(3, 3);
672 set_idt(4, 3);
673 set_idt(5, 0);
674 set_idt(6, 0);
675 set_idt(7, 0);
676 set_idt(8, 0);
677 set_idt(9, 0);
678 set_idt(10, 0);
679 set_idt(11, 0);
680 set_idt(12, 0);
681 set_idt(13, 0);
682 set_idt(14, 0);
683 set_idt(15, 0);
684 set_idt(16, 0);
685 set_idt(17, 0);
686 set_idt(18, 0);
687 set_idt(19, 0);
688 set_idt(0x80, 3);
689
690 /* linux segment setup */
691 {
692 uint64_t *gdt_table;
693 env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
d60c3b93
WL
694 PROT_READ | PROT_WRITE,
695 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
31fc12df 696 env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
3e8f1628 697 gdt_table = g2h_untagged(env->gdt.base);
31fc12df
BS
698#ifdef TARGET_ABI32
699 write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
700 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
701 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
702#else
703 /* 64 bit code segment */
704 write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
705 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
706 DESC_L_MASK |
707 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
708#endif
709 write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
710 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
711 (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
712 }
713
714 cpu_x86_load_seg(env, R_CS, __USER_CS);
715 cpu_x86_load_seg(env, R_SS, __USER_DS);
716#ifdef TARGET_ABI32
717 cpu_x86_load_seg(env, R_DS, __USER_DS);
718 cpu_x86_load_seg(env, R_ES, __USER_DS);
719 cpu_x86_load_seg(env, R_FS, __USER_DS);
720 cpu_x86_load_seg(env, R_GS, __USER_DS);
721 /* This hack makes Wine work... */
722 env->segs[R_FS].selector = 0;
723#else
724 cpu_x86_load_seg(env, R_DS, 0);
725 cpu_x86_load_seg(env, R_ES, 0);
726 cpu_x86_load_seg(env, R_FS, 0);
727 cpu_x86_load_seg(env, R_GS, 0);
728#endif
84778508
BS
729#else
730#error unsupported target CPU
731#endif
732
fcedd920
AB
733 if (gdbstub) {
734 gdbserver_start(gdbstub);
db6b81d4 735 gdb_handlesig(cpu, 0);
84778508 736 }
78cfb07f 737 cpu_loop(env);
84778508
BS
738 /* never exits */
739 return 0;
740}