]> git.proxmox.com Git - mirror_qemu.git/blob - bsd-user/main.c
bsd-user: pass the bsd_param into loader_exec
[mirror_qemu.git] / bsd-user / main.c
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 "qemu-common.h"
23 #include "qemu/units.h"
24 #include "qemu/accel.h"
25 #include "sysemu/tcg.h"
26 #include "qemu-version.h"
27 #include <machine/trap.h>
28
29 #include "qapi/error.h"
30 #include "qemu.h"
31 #include "qemu/config-file.h"
32 #include "qemu/error-report.h"
33 #include "qemu/path.h"
34 #include "qemu/help_option.h"
35 #include "qemu/module.h"
36 #include "exec/exec-all.h"
37 #include "tcg/tcg.h"
38 #include "qemu/timer.h"
39 #include "qemu/envlist.h"
40 #include "qemu/cutils.h"
41 #include "exec/log.h"
42 #include "trace/control.h"
43
44 int singlestep;
45 unsigned long mmap_min_addr;
46 uintptr_t guest_base;
47 bool have_guest_base;
48 unsigned long reserved_va;
49
50 static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
51 const char *qemu_uname_release;
52 enum BSDType bsd_type;
53
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 */
59 unsigned long x86_stack_size = 512 * 1024;
60
61 void 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 }
69
70 #if defined(TARGET_I386)
71 int cpu_get_pic_interrupt(CPUX86State *env)
72 {
73 return -1;
74 }
75 #endif
76
77 void fork_start(void)
78 {
79 }
80
81 void fork_end(int child)
82 {
83 if (child) {
84 gdbserver_fork(thread_cpu);
85 }
86 }
87
88 #ifdef TARGET_I386
89 /***********************************************************/
90 /* CPUX86 core interface */
91
92 uint64_t cpu_get_tsc(CPUX86State *env)
93 {
94 return cpu_get_host_ticks();
95 }
96
97 static 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
110 static uint64_t *idt_table;
111 #ifdef TARGET_X86_64
112 static 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 */
125 static void set_idt(int n, unsigned int dpl)
126 {
127 set_gate64(idt_table + n * 2, 0, dpl, 0, 0);
128 }
129 #else
130 static 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 */
142 static void set_idt(int n, unsigned int dpl)
143 {
144 set_gate(idt_table + n, 0, dpl, 0, 0);
145 }
146 #endif
147
148 void cpu_loop(CPUX86State *env)
149 {
150 CPUState *cs = env_cpu(env);
151 int trapnr;
152 abi_ulong pc;
153 /* target_siginfo_t info; */
154
155 for (;;) {
156 cpu_exec_start(cs);
157 trapnr = cpu_exec(cs);
158 cpu_exec_end(cs);
159 process_queued_cpu_work(cs);
160
161 switch (trapnr) {
162 case 0x80:
163 /* syscall from int $0x80 */
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);
202 } else { /* if (bsd_type == target_openbsd) */
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 }
218 break;
219 #ifndef TARGET_ABI32
220 case EXCP_SYSCALL:
221 /* syscall from syscall instruction */
222 if (bsd_type == target_freebsd) {
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);
231 } else { /* if (bsd_type == target_openbsd) */
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 }
241 env->eip = env->exception_next_eip;
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 }
248 break;
249 #endif
250 case EXCP_INTERRUPT:
251 /* just indicate that signals should be handled asap */
252 break;
253 default:
254 pc = env->segs[R_CS].base + env->eip;
255 fprintf(stderr,
256 "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
257 (long)pc, trapnr);
258 abort();
259 }
260 process_pending_signals(env);
261 }
262 }
263 #endif
264
265 static void usage(void)
266 {
267 printf("qemu-" TARGET_NAME " version " QEMU_FULL_VERSION
268 "\n" QEMU_COPYRIGHT "\n"
269 "usage: qemu-" TARGET_NAME " [options] program [arguments...]\n"
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"
277 "-cpu model select CPU (-cpu help for list)\n"
278 "-drop-ld-preload drop LD_PRELOAD for target process\n"
279 "-E var=value sets/modifies targets environment variable(s)\n"
280 "-U var unsets targets environment variable(s)\n"
281 "-B address set guest_base address to address\n"
282 "-bsd type select emulated BSD type FreeBSD/NetBSD/OpenBSD (default)\n"
283 "\n"
284 "Debug options:\n"
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"
291 "-trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
292 " specify tracing options\n"
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"
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"
303 "\n"
304 QEMU_HELP_BOTTOM "\n"
305 ,
306 TARGET_NAME,
307 interp_prefix,
308 x86_stack_size);
309 exit(1);
310 }
311
312 THREAD CPUState *thread_cpu;
313
314 bool qemu_cpu_is_self(CPUState *cpu)
315 {
316 return thread_cpu == cpu;
317 }
318
319 void qemu_cpu_kick(CPUState *cpu)
320 {
321 cpu_exit(cpu);
322 }
323
324 /* Assumes contents are already zeroed. */
325 void 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
337 int main(int argc, char **argv)
338 {
339 const char *filename;
340 const char *cpu_model;
341 const char *cpu_type;
342 const char *log_file = NULL;
343 const char *log_mask = NULL;
344 struct target_pt_regs regs1, *regs = &regs1;
345 struct image_info info1, *info = &info1;
346 struct bsd_binprm bprm;
347 TaskState ts1, *ts = &ts1;
348 CPUArchState *env;
349 CPUState *cpu;
350 int optind, rv;
351 const char *r;
352 const char *gdbstub = NULL;
353 char **target_environ, **wrk;
354 envlist_t *envlist = NULL;
355 bsd_type = target_openbsd;
356
357 if (argc <= 1) {
358 usage();
359 }
360
361 error_init(argv[0]);
362 module_call_init(MODULE_INIT_TRACE);
363 qemu_init_cpu_list();
364 module_call_init(MODULE_INIT_QOM);
365
366 envlist = envlist_create();
367
368 /* add current environment into the list */
369 for (wrk = environ; *wrk != NULL; wrk++) {
370 (void) envlist_setenv(envlist, *wrk);
371 }
372
373 cpu_model = NULL;
374
375 qemu_add_opts(&qemu_trace_opts);
376
377 optind = 1;
378 for (;;) {
379 if (optind >= argc) {
380 break;
381 }
382 r = argv[optind];
383 if (r[0] != '-') {
384 break;
385 }
386 optind++;
387 r++;
388 if (!strcmp(r, "-")) {
389 break;
390 } else if (!strcmp(r, "d")) {
391 if (optind >= argc) {
392 break;
393 }
394 log_mask = argv[optind++];
395 } else if (!strcmp(r, "D")) {
396 if (optind >= argc) {
397 break;
398 }
399 log_file = argv[optind++];
400 } else if (!strcmp(r, "E")) {
401 r = argv[optind++];
402 if (envlist_setenv(envlist, r) != 0) {
403 usage();
404 }
405 } else if (!strcmp(r, "ignore-environment")) {
406 envlist_free(envlist);
407 envlist = envlist_create();
408 } else if (!strcmp(r, "U")) {
409 r = argv[optind++];
410 if (envlist_unsetenv(envlist, r) != 0) {
411 usage();
412 }
413 } else if (!strcmp(r, "s")) {
414 r = argv[optind++];
415 rv = qemu_strtoul(r, &r, 0, &x86_stack_size);
416 if (rv < 0 || x86_stack_size <= 0) {
417 usage();
418 }
419 if (*r == 'M') {
420 x86_stack_size *= MiB;
421 } else if (*r == 'k' || *r == 'K') {
422 x86_stack_size *= KiB;
423 }
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")) {
434 gdbstub = g_strdup(argv[optind++]);
435 } else if (!strcmp(r, "r")) {
436 qemu_uname_release = argv[optind++];
437 } else if (!strcmp(r, "cpu")) {
438 cpu_model = argv[optind++];
439 if (is_help_option(cpu_model)) {
440 /* XXX: implement xxx_cpu_list for targets that still miss it */
441 #if defined(cpu_list)
442 cpu_list();
443 #endif
444 exit(1);
445 }
446 } else if (!strcmp(r, "B")) {
447 rv = qemu_strtoul(argv[optind++], NULL, 0, &guest_base);
448 if (rv < 0) {
449 usage();
450 }
451 have_guest_base = true;
452 } else if (!strcmp(r, "drop-ld-preload")) {
453 (void) envlist_unsetenv(envlist, "LD_PRELOAD");
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++;
465 } else if (!strcmp(r, "singlestep")) {
466 singlestep = 1;
467 } else if (!strcmp(r, "strace")) {
468 do_strace = 1;
469 } else if (!strcmp(r, "trace")) {
470 trace_opt_parse(optarg);
471 } else {
472 usage();
473 }
474 }
475
476 /* init debug */
477 qemu_log_needs_buffers();
478 qemu_set_log_filename(log_file, &error_fatal);
479 if (log_mask) {
480 int mask;
481
482 mask = qemu_str_to_log_mask(log_mask);
483 if (!mask) {
484 qemu_print_log_usage(stdout);
485 exit(1);
486 }
487 qemu_set_log(mask);
488 }
489
490 if (optind >= argc) {
491 usage();
492 }
493 filename = argv[optind];
494
495 if (!trace_init_backends()) {
496 exit(1);
497 }
498 trace_init_file();
499
500 /* Zero out regs */
501 memset(regs, 0, sizeof(struct target_pt_regs));
502
503 /* Zero bsd params */
504 memset(&bprm, 0, sizeof(bprm));
505
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) {
513 #if defined(TARGET_I386)
514 #ifdef TARGET_X86_64
515 cpu_model = "qemu64";
516 #else
517 cpu_model = "qemu32";
518 #endif
519 #else
520 cpu_model = "any";
521 #endif
522 }
523
524 cpu_type = parse_cpu_option(cpu_model);
525 /* init tcg before creating CPUs and to get qemu_host_page_size */
526 {
527 AccelClass *ac = ACCEL_GET_CLASS(current_accel());
528
529 accel_init_interfaces(ac);
530 ac->init_machine(NULL);
531 }
532 cpu = cpu_create(cpu_type);
533 env = cpu->env_ptr;
534 cpu_reset(cpu);
535 thread_cpu = cpu;
536
537 if (getenv("QEMU_STRACE")) {
538 do_strace = 1;
539 }
540
541 target_environ = envlist_to_environ(envlist, NULL);
542 envlist_free(envlist);
543
544 /*
545 * Now that page sizes are configured we can do
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
561 fp = fopen("/proc/sys/vm/mmap_min_addr", "r");
562 if (fp != NULL) {
563 unsigned long tmp;
564 if (fscanf(fp, "%lu", &tmp) == 1) {
565 mmap_min_addr = tmp;
566 qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n",
567 mmap_min_addr);
568 }
569 fclose(fp);
570 }
571 }
572
573 if (loader_exec(filename, argv + optind, target_environ, regs, info,
574 &bprm) != 0) {
575 printf("Error loading %s\n", filename);
576 _exit(1);
577 }
578
579 for (wrk = target_environ; *wrk; wrk++) {
580 g_free(*wrk);
581 }
582
583 g_free(target_environ);
584
585 if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
586 qemu_log("guest_base %p\n", (void *)guest_base);
587 log_page_dump("binary load");
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 }
601
602 target_set_brk(info->brk);
603 syscall_init();
604 signal_init();
605
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 */
611 tcg_prologue_init(tcg_ctx);
612
613 /* build Task State */
614 memset(ts, 0, sizeof(TaskState));
615 init_task_state(ts);
616 ts->info = info;
617 cpu->opaque = ts;
618
619 #if defined(TARGET_I386)
620 env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
621 env->hflags |= HF_PE_MASK | HF_CPL_MASK;
622 if (env->features[FEAT_1_EDX] & CPUID_SSE) {
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 */
628 if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
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),
670 PROT_READ | PROT_WRITE,
671 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
672 idt_table = g2h_untagged(env->idt.base);
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,
699 PROT_READ | PROT_WRITE,
700 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
701 env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
702 gdt_table = g2h_untagged(env->gdt.base);
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
734 #else
735 #error unsupported target CPU
736 #endif
737
738 if (gdbstub) {
739 gdbserver_start(gdbstub);
740 gdb_handlesig(cpu, 0);
741 }
742 cpu_loop(env);
743 /* never exits */
744 return 0;
745 }