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