main.c 17 KB

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