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 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 #include <stdlib.h> 21 #include <stdio.h> 22 #include <stdarg.h> 23 #include <string.h> 24 #include <errno.h> 25 #include <unistd.h> 26 #include <machine/trap.h> 27 28 #include "qemu.h" 29 #include "qemu-common.h" 30 /* For tb_lock */ 31 #include "exec-all.h" 32 33 #define DEBUG_LOGFILE "/tmp/qemu.log" 34 35 static const char *interp_prefix = CONFIG_QEMU_PREFIX; 36 const char *qemu_uname_release = CONFIG_UNAME_RELEASE; 37 extern char **environ; 38 39 /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so 40 we allocate a bigger stack. Need a better solution, for example 41 by remapping the process stack directly at the right place */ 42 unsigned long x86_stack_size = 512 * 1024; 43 44 void gemu_log(const char *fmt, ...) 45 { 46 va_list ap; 47 48 va_start(ap, fmt); 49 vfprintf(stderr, fmt, ap); 50 va_end(ap); 51 } 52 #ifdef TARGET_SPARC 53 #define SPARC64_STACK_BIAS 2047 54 55 //#define DEBUG_WIN 56 /* WARNING: dealing with register windows _is_ complicated. More info 57 can be found at http://www.sics.se/~psm/sparcstack.html */ 58 static inline int get_reg_index(CPUSPARCState *env, int cwp, int index) 59 { 60 index = (index + cwp * 16) % (16 * env->nwindows); 61 /* wrap handling : if cwp is on the last window, then we use the 62 registers 'after' the end */ 63 if (index < 8 && env->cwp == env->nwindows - 1) 64 index += 16 * env->nwindows; 65 return index; 66 } 67 68 /* save the register window 'cwp1' */ 69 static inline void save_window_offset(CPUSPARCState *env, int cwp1) 70 { 71 unsigned int i; 72 abi_ulong sp_ptr; 73 74 sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; 75 #ifdef TARGET_SPARC64 76 if (sp_ptr & 3) 77 sp_ptr += SPARC64_STACK_BIAS; 78 #endif 79 #if defined(DEBUG_WIN) 80 printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n", 81 sp_ptr, cwp1); 82 #endif 83 for(i = 0; i < 16; i++) { 84 /* FIXME - what to do if put_user() fails? */ 85 put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr); 86 sp_ptr += sizeof(abi_ulong); 87 } 88 } 89 90 static void save_window(CPUSPARCState *env) 91 { 92 #ifndef TARGET_SPARC64 93 unsigned int new_wim; 94 new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) & 95 ((1LL << env->nwindows) - 1); 96 save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); 97 env->wim = new_wim; 98 #else 99 save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); 100 env->cansave++; 101 env->canrestore--; 102 #endif 103 } 104 105 static void restore_window(CPUSPARCState *env) 106 { 107 #ifndef TARGET_SPARC64 108 unsigned int new_wim; 109 #endif 110 unsigned int i, cwp1; 111 abi_ulong sp_ptr; 112 113 #ifndef TARGET_SPARC64 114 new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) & 115 ((1LL << env->nwindows) - 1); 116 #endif 117 118 /* restore the invalid window */ 119 cwp1 = cpu_cwp_inc(env, env->cwp + 1); 120 sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; 121 #ifdef TARGET_SPARC64 122 if (sp_ptr & 3) 123 sp_ptr += SPARC64_STACK_BIAS; 124 #endif 125 #if defined(DEBUG_WIN) 126 printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n", 127 sp_ptr, cwp1); 128 #endif 129 for(i = 0; i < 16; i++) { 130 /* FIXME - what to do if get_user() fails? */ 131 get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr); 132 sp_ptr += sizeof(abi_ulong); 133 } 134 #ifdef TARGET_SPARC64 135 env->canrestore++; 136 if (env->cleanwin < env->nwindows - 1) 137 env->cleanwin++; 138 env->cansave--; 139 #else 140 env->wim = new_wim; 141 #endif 142 } 143 144 static void flush_windows(CPUSPARCState *env) 145 { 146 int offset, cwp1; 147 148 offset = 1; 149 for(;;) { 150 /* if restore would invoke restore_window(), then we can stop */ 151 cwp1 = cpu_cwp_inc(env, env->cwp + offset); 152 #ifndef TARGET_SPARC64 153 if (env->wim & (1 << cwp1)) 154 break; 155 #else 156 if (env->canrestore == 0) 157 break; 158 env->cansave++; 159 env->canrestore--; 160 #endif 161 save_window_offset(env, cwp1); 162 offset++; 163 } 164 cwp1 = cpu_cwp_inc(env, env->cwp + 1); 165 #ifndef TARGET_SPARC64 166 /* set wim so that restore will reload the registers */ 167 env->wim = 1 << cwp1; 168 #endif 169 #if defined(DEBUG_WIN) 170 printf("flush_windows: nb=%d\n", offset - 1); 171 #endif 172 } 173 174 void cpu_loop(CPUSPARCState *env, enum BSDType bsd_type) 175 { 176 int trapnr, ret, syscall_nr; 177 //target_siginfo_t info; 178 179 while (1) { 180 trapnr = cpu_sparc_exec (env); 181 182 switch (trapnr) { 183 #ifndef TARGET_SPARC64 184 case 0x80: 185 #else 186 case 0x100: 187 #endif 188 syscall_nr = env->gregs[1]; 189 if (bsd_type == target_freebsd) 190 ret = do_freebsd_syscall(env, syscall_nr, 191 env->regwptr[0], env->regwptr[1], 192 env->regwptr[2], env->regwptr[3], 193 env->regwptr[4], env->regwptr[5]); 194 else if (bsd_type == target_netbsd) 195 ret = do_netbsd_syscall(env, syscall_nr, 196 env->regwptr[0], env->regwptr[1], 197 env->regwptr[2], env->regwptr[3], 198 env->regwptr[4], env->regwptr[5]); 199 else { //if (bsd_type == target_openbsd) 200 #if defined(TARGET_SPARC64) 201 syscall_nr &= ~(TARGET_OPENBSD_SYSCALL_G7RFLAG | 202 TARGET_OPENBSD_SYSCALL_G2RFLAG); 203 #endif 204 ret = do_openbsd_syscall(env, syscall_nr, 205 env->regwptr[0], env->regwptr[1], 206 env->regwptr[2], env->regwptr[3], 207 env->regwptr[4], env->regwptr[5]); 208 } 209 if ((unsigned int)ret >= (unsigned int)(-515)) { 210 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) 211 env->xcc |= PSR_CARRY; 212 #else 213 env->psr |= PSR_CARRY; 214 #endif 215 } else { 216 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) 217 env->xcc &= ~PSR_CARRY; 218 #else 219 env->psr &= ~PSR_CARRY; 220 #endif 221 } 222 env->regwptr[0] = ret; 223 /* next instruction */ 224 #if defined(TARGET_SPARC64) 225 if (bsd_type == target_openbsd && 226 env->gregs[1] & TARGET_OPENBSD_SYSCALL_G2RFLAG) { 227 env->pc = env->gregs[2]; 228 env->npc = env->pc + 4; 229 } else if (bsd_type == target_openbsd && 230 env->gregs[1] & TARGET_OPENBSD_SYSCALL_G7RFLAG) { 231 env->pc = env->gregs[7]; 232 env->npc = env->pc + 4; 233 } else { 234 env->pc = env->npc; 235 env->npc = env->npc + 4; 236 } 237 #else 238 env->pc = env->npc; 239 env->npc = env->npc + 4; 240 #endif 241 break; 242 case 0x83: /* flush windows */ 243 #ifdef TARGET_ABI32 244 case 0x103: 245 #endif 246 flush_windows(env); 247 /* next instruction */ 248 env->pc = env->npc; 249 env->npc = env->npc + 4; 250 break; 251 #ifndef TARGET_SPARC64 252 case TT_WIN_OVF: /* window overflow */ 253 save_window(env); 254 break; 255 case TT_WIN_UNF: /* window underflow */ 256 restore_window(env); 257 break; 258 case TT_TFAULT: 259 case TT_DFAULT: 260 #if 0 261 { 262 info.si_signo = SIGSEGV; 263 info.si_errno = 0; 264 /* XXX: check env->error_code */ 265 info.si_code = TARGET_SEGV_MAPERR; 266 info._sifields._sigfault._addr = env->mmuregs[4]; 267 queue_signal(env, info.si_signo, &info); 268 } 269 #endif 270 break; 271 #else 272 case TT_SPILL: /* window overflow */ 273 save_window(env); 274 break; 275 case TT_FILL: /* window underflow */ 276 restore_window(env); 277 break; 278 case TT_TFAULT: 279 case TT_DFAULT: 280 #if 0 281 { 282 info.si_signo = SIGSEGV; 283 info.si_errno = 0; 284 /* XXX: check env->error_code */ 285 info.si_code = TARGET_SEGV_MAPERR; 286 if (trapnr == TT_DFAULT) 287 info._sifields._sigfault._addr = env->dmmuregs[4]; 288 else 289 info._sifields._sigfault._addr = env->tsptr->tpc; 290 //queue_signal(env, info.si_signo, &info); 291 } 292 #endif 293 break; 294 #endif 295 case EXCP_INTERRUPT: 296 /* just indicate that signals should be handled asap */ 297 break; 298 case EXCP_DEBUG: 299 { 300 int sig; 301 302 sig = gdb_handlesig (env, TARGET_SIGTRAP); 303 #if 0 304 if (sig) 305 { 306 info.si_signo = sig; 307 info.si_errno = 0; 308 info.si_code = TARGET_TRAP_BRKPT; 309 //queue_signal(env, info.si_signo, &info); 310 } 311 #endif 312 } 313 break; 314 default: 315 printf ("Unhandled trap: 0x%x\n", trapnr); 316 cpu_dump_state(env, stderr, fprintf, 0); 317 exit (1); 318 } 319 process_pending_signals (env); 320 } 321 } 322 323 #endif 324 325 static void usage(void) 326 { 327 printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n" 328 "usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n" 329 "BSD CPU emulator (compiled for %s emulation)\n" 330 "\n" 331 "Standard options:\n" 332 "-h print this help\n" 333 "-g port wait gdb connection to port\n" 334 "-L path set the elf interpreter prefix (default=%s)\n" 335 "-s size set the stack size in bytes (default=%ld)\n" 336 "-cpu model select CPU (-cpu ? for list)\n" 337 "-drop-ld-preload drop LD_PRELOAD for target process\n" 338 "-bsd type select emulated BSD type FreeBSD/NetBSD/OpenBSD (default)\n" 339 "\n" 340 "Debug options:\n" 341 "-d options activate log (logfile=%s)\n" 342 "-p pagesize set the host page size to 'pagesize'\n" 343 "-strace log system calls\n" 344 "\n" 345 "Environment variables:\n" 346 "QEMU_STRACE Print system calls and arguments similar to the\n" 347 " 'strace' program. Enable by setting to any value.\n" 348 , 349 TARGET_ARCH, 350 interp_prefix, 351 x86_stack_size, 352 DEBUG_LOGFILE); 353 _exit(1); 354 } 355 356 THREAD CPUState *thread_env; 357 358 /* Assumes contents are already zeroed. */ 359 void init_task_state(TaskState *ts) 360 { 361 int i; 362 363 ts->used = 1; 364 ts->first_free = ts->sigqueue_table; 365 for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) { 366 ts->sigqueue_table[i].next = &ts->sigqueue_table[i + 1]; 367 } 368 ts->sigqueue_table[i].next = NULL; 369 } 370 371 int main(int argc, char **argv) 372 { 373 const char *filename; 374 const char *cpu_model; 375 struct target_pt_regs regs1, *regs = ®s1; 376 struct image_info info1, *info = &info1; 377 TaskState ts1, *ts = &ts1; 378 CPUState *env; 379 int optind; 380 const char *r; 381 int gdbstub_port = 0; 382 int drop_ld_preload = 0, environ_count = 0; 383 char **target_environ, **wrk, **dst; 384 enum BSDType bsd_type = target_openbsd; 385 386 if (argc <= 1) 387 usage(); 388 389 /* init debug */ 390 cpu_set_log_filename(DEBUG_LOGFILE); 391 392 cpu_model = NULL; 393 optind = 1; 394 for(;;) { 395 if (optind >= argc) 396 break; 397 r = argv[optind]; 398 if (r[0] != '-') 399 break; 400 optind++; 401 r++; 402 if (!strcmp(r, "-")) { 403 break; 404 } else if (!strcmp(r, "d")) { 405 int mask; 406 const CPULogItem *item; 407 408 if (optind >= argc) 409 break; 410 411 r = argv[optind++]; 412 mask = cpu_str_to_log_mask(r); 413 if (!mask) { 414 printf("Log items (comma separated):\n"); 415 for(item = cpu_log_items; item->mask != 0; item++) { 416 printf("%-10s %s\n", item->name, item->help); 417 } 418 exit(1); 419 } 420 cpu_set_log(mask); 421 } else if (!strcmp(r, "s")) { 422 r = argv[optind++]; 423 x86_stack_size = strtol(r, (char **)&r, 0); 424 if (x86_stack_size <= 0) 425 usage(); 426 if (*r == 'M') 427 x86_stack_size *= 1024 * 1024; 428 else if (*r == 'k' || *r == 'K') 429 x86_stack_size *= 1024; 430 } else if (!strcmp(r, "L")) { 431 interp_prefix = argv[optind++]; 432 } else if (!strcmp(r, "p")) { 433 qemu_host_page_size = atoi(argv[optind++]); 434 if (qemu_host_page_size == 0 || 435 (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) { 436 fprintf(stderr, "page size must be a power of two\n"); 437 exit(1); 438 } 439 } else if (!strcmp(r, "g")) { 440 gdbstub_port = atoi(argv[optind++]); 441 } else if (!strcmp(r, "r")) { 442 qemu_uname_release = argv[optind++]; 443 } else if (!strcmp(r, "cpu")) { 444 cpu_model = argv[optind++]; 445 if (strcmp(cpu_model, "?") == 0) { 446 /* XXX: implement xxx_cpu_list for targets that still miss it */ 447 #if defined(cpu_list) 448 cpu_list(stdout, &fprintf); 449 #endif 450 _exit(1); 451 } 452 } else if (!strcmp(r, "drop-ld-preload")) { 453 drop_ld_preload = 1; 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, "strace")) { 466 do_strace = 1; 467 } else 468 { 469 usage(); 470 } 471 } 472 if (optind >= argc) 473 usage(); 474 filename = argv[optind]; 475 476 /* Zero out regs */ 477 memset(regs, 0, sizeof(struct target_pt_regs)); 478 479 /* Zero out image_info */ 480 memset(info, 0, sizeof(struct image_info)); 481 482 /* Scan interp_prefix dir for replacement files. */ 483 init_paths(interp_prefix); 484 485 if (cpu_model == NULL) { 486 #if defined(TARGET_SPARC) 487 #ifdef TARGET_SPARC64 488 cpu_model = "TI UltraSparc II"; 489 #else 490 cpu_model = "Fujitsu MB86904"; 491 #endif 492 #else 493 cpu_model = "any"; 494 #endif 495 } 496 cpu_exec_init_all(0); 497 /* NOTE: we need to init the CPU at this stage to get 498 qemu_host_page_size */ 499 env = cpu_init(cpu_model); 500 if (!env) { 501 fprintf(stderr, "Unable to find CPU definition\n"); 502 exit(1); 503 } 504 thread_env = env; 505 506 if (getenv("QEMU_STRACE")) { 507 do_strace = 1; 508 } 509 510 wrk = environ; 511 while (*(wrk++)) 512 environ_count++; 513 514 target_environ = malloc((environ_count + 1) * sizeof(char *)); 515 if (!target_environ) 516 abort(); 517 for (wrk = environ, dst = target_environ; *wrk; wrk++) { 518 if (drop_ld_preload && !strncmp(*wrk, "LD_PRELOAD=", 11)) 519 continue; 520 *(dst++) = strdup(*wrk); 521 } 522 *dst = NULL; /* NULL terminate target_environ */ 523 524 if (loader_exec(filename, argv+optind, target_environ, regs, info) != 0) { 525 printf("Error loading %s\n", filename); 526 _exit(1); 527 } 528 529 for (wrk = target_environ; *wrk; wrk++) { 530 free(*wrk); 531 } 532 533 free(target_environ); 534 535 if (loglevel) { 536 page_dump(logfile); 537 538 fprintf(logfile, "start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk); 539 fprintf(logfile, "end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code); 540 fprintf(logfile, "start_code 0x" TARGET_ABI_FMT_lx "\n", 541 info->start_code); 542 fprintf(logfile, "start_data 0x" TARGET_ABI_FMT_lx "\n", 543 info->start_data); 544 fprintf(logfile, "end_data 0x" TARGET_ABI_FMT_lx "\n", info->end_data); 545 fprintf(logfile, "start_stack 0x" TARGET_ABI_FMT_lx "\n", 546 info->start_stack); 547 fprintf(logfile, "brk 0x" TARGET_ABI_FMT_lx "\n", info->brk); 548 fprintf(logfile, "entry 0x" TARGET_ABI_FMT_lx "\n", info->entry); 549 } 550 551 target_set_brk(info->brk); 552 syscall_init(); 553 signal_init(); 554 555 /* build Task State */ 556 memset(ts, 0, sizeof(TaskState)); 557 init_task_state(ts); 558 ts->info = info; 559 env->opaque = ts; 560 env->user_mode_only = 1; 561 562 #if defined(TARGET_SPARC) 563 { 564 int i; 565 env->pc = regs->pc; 566 env->npc = regs->npc; 567 env->y = regs->y; 568 for(i = 0; i < 8; i++) 569 env->gregs[i] = regs->u_regs[i]; 570 for(i = 0; i < 8; i++) 571 env->regwptr[i] = regs->u_regs[i + 8]; 572 } 573 #else 574 #error unsupported target CPU 575 #endif 576 577 if (gdbstub_port) { 578 gdbserver_start (gdbstub_port); 579 gdb_handlesig(env, 0); 580 } 581 cpu_loop(env, bsd_type); 582 /* never exits */ 583 return 0; 584 } 585