blob: 063f6a987d912fe5aa6f69cbd96c6b4cfbb8be65 [file] [log] [blame]
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001/*
2 * QEMU System Emulator
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080024#include <unistd.h>
25#include <fcntl.h>
26#include <signal.h>
27#include <time.h>
28#include <errno.h>
29#include <sys/time.h>
30#include <zlib.h>
31
David 'Digit' Turner2c538c82010-05-10 16:48:20 -070032/* Needed early for CONFIG_BSD etc. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070033#include "config-host.h"
34
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080035#ifndef _WIN32
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070036#include <libgen.h>
37#include <pwd.h>
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080038#include <sys/times.h>
39#include <sys/wait.h>
40#include <termios.h>
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080041#include <sys/mman.h>
42#include <sys/ioctl.h>
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070043#include <sys/resource.h>
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080044#include <sys/socket.h>
45#include <netinet/in.h>
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070046#include <net/if.h>
47#if defined(__NetBSD__)
48#include <net/if_tap.h>
49#endif
50#ifdef __linux__
51#include <linux/if_tun.h>
52#endif
53#include <arpa/inet.h>
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080054#include <dirent.h>
55#include <netdb.h>
56#include <sys/select.h>
David 'Digit' Turner2c538c82010-05-10 16:48:20 -070057#ifdef CONFIG_BSD
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080058#include <sys/stat.h>
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070059#if defined(__FreeBSD__) || defined(__DragonFly__)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080060#include <libutil.h>
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070061#else
62#include <util.h>
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080063#endif
64#elif defined (__GLIBC__) && defined (__FreeBSD_kernel__)
65#include <freebsd/stdlib.h>
66#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070067#ifdef __linux__
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080068#include <pty.h>
69#include <malloc.h>
70#include <linux/rtc.h>
71
72/* For the benefit of older linux systems which don't supply it,
73 we use a local copy of hpet.h. */
74/* #include <linux/hpet.h> */
75#include "hpet.h"
76
77#include <linux/ppdev.h>
78#include <linux/parport.h>
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070079#endif
80#ifdef __sun__
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080081#include <sys/stat.h>
82#include <sys/ethernet.h>
83#include <sys/sockio.h>
84#include <netinet/arp.h>
85#include <netinet/in.h>
86#include <netinet/in_systm.h>
87#include <netinet/ip.h>
88#include <netinet/ip_icmp.h> // must come after ip.h
89#include <netinet/udp.h>
90#include <netinet/tcp.h>
91#include <net/if.h>
92#include <syslog.h>
93#include <stropts.h>
94#endif
95#endif
96#endif
97
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080098#if defined(__OpenBSD__)
99#include <util.h>
100#endif
101
102#if defined(CONFIG_VDE)
103#include <libvdeplug.h>
104#endif
105
106#ifdef _WIN32
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700107#include <windows.h>
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800108#include <malloc.h>
109#include <sys/timeb.h>
110#include <mmsystem.h>
111#define getopt_long_only getopt_long
112#define memalign(align, size) malloc(size)
113#endif
114
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700115#ifdef CONFIG_SDL
116#ifdef __APPLE__
117#include <SDL.h>
118int qemu_main(int argc, char **argv, char **envp);
119int main(int argc, char **argv)
120{
121 qemu_main(argc, argv, NULL);
122}
123#undef main
124#define main qemu_main
125#endif
126#endif /* CONFIG_SDL */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800127
128#ifdef CONFIG_COCOA
129#undef main
130#define main qemu_main
131#endif /* CONFIG_COCOA */
132
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700133#include "hw/hw.h"
134#include "hw/boards.h"
135#include "hw/usb.h"
136#include "hw/pcmcia.h"
137#include "hw/pc.h"
138#include "hw/audiodev.h"
139#include "hw/isa.h"
140#include "hw/baum.h"
141#include "hw/bt.h"
142#include "hw/watchdog.h"
143#include "hw/smbios.h"
144#include "hw/xen.h"
145#include "bt-host.h"
146#include "net.h"
147#include "monitor.h"
148#include "console.h"
149#include "sysemu.h"
150#include "gdbstub.h"
151#include "qemu-timer.h"
152#include "qemu-char.h"
153#include "cache-utils.h"
154#include "block.h"
155#include "dma.h"
156#include "audio/audio.h"
157#include "migration.h"
158#include "kvm.h"
159#include "balloon.h"
160#include "qemu-option.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800161
162#include "disas.h"
163
164#include "exec-all.h"
165
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700166#include "qemu_socket.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800167
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700168#if defined(CONFIG_SLIRP)
169#include "libslirp.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800170#endif
171
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800172
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700173
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700174#define DEFAULT_RAM_SIZE 128
175
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800176/* Max number of USB devices that can be specified on the commandline. */
177#define MAX_USB_CMDLINE 8
178
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700179/* Max number of bluetooth switches on the commandline. */
180#define MAX_BT_CMDLINE 10
181
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800182/* XXX: use a two level table to limit memory usage */
183#define MAX_IOPORTS 65536
184
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700185static const char *data_dir;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800186const char *bios_name = NULL;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700187static void *ioport_opaque[MAX_IOPORTS];
188static IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
189static IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800190/* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available
191 to store the VM snapshots */
192DriveInfo drives_table[MAX_DRIVES+1];
193int nb_drives;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700194enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
195static DisplayState *display_state;
196DisplayType display_type = DT_DEFAULT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800197const char* keyboard_layout = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800198ram_addr_t ram_size;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800199int nb_nics;
200NICInfo nd_table[MAX_NICS];
201int vm_running;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700202static int autostart;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800203static int rtc_utc = 1;
204static int rtc_date_offset = -1; /* -1 means no change */
205int cirrus_vga_enabled = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700206int std_vga_enabled = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800207int vmsvga_enabled = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700208int xenfb_enabled = 0;
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -0700209QEMUClock *rtc_clock;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800210#ifdef TARGET_SPARC
211int graphic_width = 1024;
212int graphic_height = 768;
213int graphic_depth = 8;
214#else
215int graphic_width = 800;
216int graphic_height = 600;
217int graphic_depth = 15;
218#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700219static int full_screen = 0;
220#ifdef CONFIG_SDL
221static int no_frame = 0;
222#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800223int no_quit = 0;
224CharDriverState *serial_hds[MAX_SERIAL_PORTS];
225CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700226CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800227#ifdef TARGET_I386
228int win2k_install_hack = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700229int rtc_td_hack = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800230#endif
231int usb_enabled = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700232int singlestep = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800233int smp_cpus = 1;
234const char *vnc_display;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800235int acpi_enabled = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700236int no_hpet = 0;
237int no_virtio_balloon = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800238int fd_bootchk = 1;
239int no_reboot = 0;
240int no_shutdown = 0;
241int cursor_hide = 1;
242int graphic_rotate = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700243#ifndef _WIN32
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800244int daemonize = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700245#endif
246WatchdogTimerModel *watchdog = NULL;
247int watchdog_action = WDT_RESET;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800248const char *option_rom[MAX_OPTION_ROMS];
249int nb_option_roms;
250int semihosting_enabled = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800251#ifdef TARGET_ARM
252int old_param = 0;
253#endif
254const char *qemu_name;
255int alt_grab = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700256#if defined(TARGET_SPARC) || defined(TARGET_PPC)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800257unsigned int nb_prom_envs = 0;
258const char *prom_envs[MAX_PROM_ENVS];
259#endif
260int nb_drives_opt;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700261struct drive_opt drives_opt[MAX_DRIVES];
262
263int nb_numa_nodes;
264uint64_t node_mem[MAX_NODES];
265uint64_t node_cpumask[MAX_NODES];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800266
267static CPUState *cur_cpu;
268static CPUState *next_cpu;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700269static int timer_alarm_pending = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700270static QEMUTimer *nographic_timer;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800271
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700272uint8_t qemu_uuid[16];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800273
274/***********************************************************/
275/* x86 ISA bus support */
276
277target_phys_addr_t isa_mem_base = 0;
278PicState2 *isa_pic;
279
280static IOPortReadFunc default_ioport_readb, default_ioport_readw, default_ioport_readl;
281static IOPortWriteFunc default_ioport_writeb, default_ioport_writew, default_ioport_writel;
282
283static uint32_t ioport_read(int index, uint32_t address)
284{
285 static IOPortReadFunc *default_func[3] = {
286 default_ioport_readb,
287 default_ioport_readw,
288 default_ioport_readl
289 };
290 IOPortReadFunc *func = ioport_read_table[index][address];
291 if (!func)
292 func = default_func[index];
293 return func(ioport_opaque[address], address);
294}
295
296static void ioport_write(int index, uint32_t address, uint32_t data)
297{
298 static IOPortWriteFunc *default_func[3] = {
299 default_ioport_writeb,
300 default_ioport_writew,
301 default_ioport_writel
302 };
303 IOPortWriteFunc *func = ioport_write_table[index][address];
304 if (!func)
305 func = default_func[index];
306 func(ioport_opaque[address], address, data);
307}
308
309static uint32_t default_ioport_readb(void *opaque, uint32_t address)
310{
311#ifdef DEBUG_UNUSED_IOPORT
312 fprintf(stderr, "unused inb: port=0x%04x\n", address);
313#endif
314 return 0xff;
315}
316
317static void default_ioport_writeb(void *opaque, uint32_t address, uint32_t data)
318{
319#ifdef DEBUG_UNUSED_IOPORT
320 fprintf(stderr, "unused outb: port=0x%04x data=0x%02x\n", address, data);
321#endif
322}
323
324/* default is to make two byte accesses */
325static uint32_t default_ioport_readw(void *opaque, uint32_t address)
326{
327 uint32_t data;
328 data = ioport_read(0, address);
329 address = (address + 1) & (MAX_IOPORTS - 1);
330 data |= ioport_read(0, address) << 8;
331 return data;
332}
333
334static void default_ioport_writew(void *opaque, uint32_t address, uint32_t data)
335{
336 ioport_write(0, address, data & 0xff);
337 address = (address + 1) & (MAX_IOPORTS - 1);
338 ioport_write(0, address, (data >> 8) & 0xff);
339}
340
341static uint32_t default_ioport_readl(void *opaque, uint32_t address)
342{
343#ifdef DEBUG_UNUSED_IOPORT
344 fprintf(stderr, "unused inl: port=0x%04x\n", address);
345#endif
346 return 0xffffffff;
347}
348
349static void default_ioport_writel(void *opaque, uint32_t address, uint32_t data)
350{
351#ifdef DEBUG_UNUSED_IOPORT
352 fprintf(stderr, "unused outl: port=0x%04x data=0x%02x\n", address, data);
353#endif
354}
355
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800356
357/***********************************************************/
358void hw_error(const char *fmt, ...)
359{
360 va_list ap;
361 CPUState *env;
362
363 va_start(ap, fmt);
364 fprintf(stderr, "qemu: hardware error: ");
365 vfprintf(stderr, fmt, ap);
366 fprintf(stderr, "\n");
367 for(env = first_cpu; env != NULL; env = env->next_cpu) {
368 fprintf(stderr, "CPU #%d:\n", env->cpu_index);
369#ifdef TARGET_I386
370 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU);
371#else
372 cpu_dump_state(env, stderr, fprintf, 0);
373#endif
374 }
375 va_end(ap);
376 abort();
377}
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700378
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -0700379static void set_proc_name(const char *s)
380{
381#if defined(__linux__) && defined(PR_SET_NAME)
382 char name[16];
383 if (!s)
384 return;
385 name[sizeof(name) - 1] = 0;
386 strncpy(name, s, sizeof(name));
387 /* Could rewrite argv[0] too, but that's a bit more complicated.
388 This simple way is enough for `top'. */
389 prctl(PR_SET_NAME, name);
390#endif
391}
392
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700393/***************/
394/* ballooning */
395
396static QEMUBalloonEvent *qemu_balloon_event;
397void *qemu_balloon_event_opaque;
398
399void qemu_add_balloon_handler(QEMUBalloonEvent *func, void *opaque)
400{
401 qemu_balloon_event = func;
402 qemu_balloon_event_opaque = opaque;
403}
404
405void qemu_balloon(ram_addr_t target)
406{
407 if (qemu_balloon_event)
408 qemu_balloon_event(qemu_balloon_event_opaque, target);
409}
410
411ram_addr_t qemu_balloon_status(void)
412{
413 if (qemu_balloon_event)
414 return qemu_balloon_event(qemu_balloon_event_opaque, 0);
415 return 0;
416}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800417
418/***********************************************************/
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -0700419/* real time host monotonic timer */
420
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800421/* compute with 96 bit intermediate result: (a*b)/c */
422uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
423{
424 union {
425 uint64_t ll;
426 struct {
David 'Digit' Turner20894ae2010-05-10 17:07:36 -0700427#ifdef HOST_WORDS_BIGENDIAN
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800428 uint32_t high, low;
429#else
430 uint32_t low, high;
431#endif
432 } l;
433 } u, res;
434 uint64_t rl, rh;
435
436 u.ll = a;
437 rl = (uint64_t)u.l.low * (uint64_t)b;
438 rh = (uint64_t)u.l.high * (uint64_t)b;
439 rh += (rl >> 32);
440 res.l.high = rh / c;
441 res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
442 return res.ll;
443}
444
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800445/***********************************************************/
446/* host time/date access */
447void qemu_get_timedate(struct tm *tm, int offset)
448{
449 time_t ti;
450 struct tm *ret;
451
452 time(&ti);
453 ti += offset;
454 if (rtc_date_offset == -1) {
455 if (rtc_utc)
456 ret = gmtime(&ti);
457 else
458 ret = localtime(&ti);
459 } else {
460 ti -= rtc_date_offset;
461 ret = gmtime(&ti);
462 }
463
464 memcpy(tm, ret, sizeof(struct tm));
465}
466
467int qemu_timedate_diff(struct tm *tm)
468{
469 time_t seconds;
470
471 if (rtc_date_offset == -1)
472 if (rtc_utc)
473 seconds = mktimegm(tm);
474 else
475 seconds = mktime(tm);
476 else
477 seconds = mktimegm(tm) + rtc_date_offset;
478
479 return seconds - time(NULL);
480}
481
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800482#ifdef _WIN32
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700483static void socket_cleanup(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800484{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700485 WSACleanup();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800486}
487
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700488static int socket_init(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800489{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700490 WSADATA Data;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800491 int ret, err;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800492
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700493 ret = WSAStartup(MAKEWORD(2,2), &Data);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800494 if (ret != 0) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700495 err = WSAGetLastError();
496 fprintf(stderr, "WSAStartup: %d\n", err);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800497 return -1;
498 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700499 atexit(socket_cleanup);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800500 return 0;
501}
502#endif
503
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700504int get_param_value(char *buf, int buf_size,
505 const char *tag, const char *str)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800506{
507 const char *p;
508 char option[128];
509
510 p = str;
511 for(;;) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700512 p = get_opt_name(option, sizeof(option), p, '=');
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800513 if (*p != '=')
514 break;
515 p++;
516 if (!strcmp(tag, option)) {
517 (void)get_opt_value(buf, buf_size, p);
518 return strlen(buf);
519 } else {
520 p = get_opt_value(NULL, 0, p);
521 }
522 if (*p != ',')
523 break;
524 p++;
525 }
526 return 0;
527}
528
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700529int check_params(char *buf, int buf_size,
530 const char * const *params, const char *str)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800531{
532 const char *p;
533 int i;
534
535 p = str;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700536 while (*p != '\0') {
537 p = get_opt_name(buf, buf_size, p, '=');
538 if (*p != '=') {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800539 return -1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700540 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800541 p++;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700542 for (i = 0; params[i] != NULL; i++) {
543 if (!strcmp(params[i], buf)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800544 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700545 }
546 }
547 if (params[i] == NULL) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800548 return -1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700549 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800550 p = get_opt_value(NULL, 0, p);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700551 if (*p != ',') {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800552 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700553 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800554 p++;
555 }
556 return 0;
557}
558
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700559/***********************************************************/
560/* Bluetooth support */
561static int nb_hcis;
562static int cur_hci;
563static struct HCIInfo *hci_table[MAX_NICS];
564
565static struct bt_vlan_s {
566 struct bt_scatternet_s net;
567 int id;
568 struct bt_vlan_s *next;
569} *first_bt_vlan;
570
571/* find or alloc a new bluetooth "VLAN" */
572static struct bt_scatternet_s *qemu_find_bt_vlan(int id)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800573{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700574 struct bt_vlan_s **pvlan, *vlan;
575 for (vlan = first_bt_vlan; vlan != NULL; vlan = vlan->next) {
576 if (vlan->id == id)
577 return &vlan->net;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800578 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700579 vlan = qemu_mallocz(sizeof(struct bt_vlan_s));
580 vlan->id = id;
581 pvlan = &first_bt_vlan;
582 while (*pvlan != NULL)
583 pvlan = &(*pvlan)->next;
584 *pvlan = vlan;
585 return &vlan->net;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800586}
587
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700588static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, int len)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800589{
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800590}
591
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700592static int null_hci_addr_set(struct HCIInfo *hci, const uint8_t *bd_addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800593{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700594 return -ENOTSUP;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800595}
596
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700597static struct HCIInfo null_hci = {
598 .cmd_send = null_hci_send,
599 .sco_send = null_hci_send,
600 .acl_send = null_hci_send,
601 .bdaddr_set = null_hci_addr_set,
602};
603
604struct HCIInfo *qemu_next_hci(void)
605{
606 if (cur_hci == nb_hcis)
607 return &null_hci;
608
609 return hci_table[cur_hci++];
610}
611
612static struct HCIInfo *hci_init(const char *str)
613{
614 char *endp;
615 struct bt_scatternet_s *vlan = 0;
616
617 if (!strcmp(str, "null"))
618 /* null */
619 return &null_hci;
620 else if (!strncmp(str, "host", 4) && (str[4] == '\0' || str[4] == ':'))
621 /* host[:hciN] */
622 return bt_host_hci(str[4] ? str + 5 : "hci0");
623 else if (!strncmp(str, "hci", 3)) {
624 /* hci[,vlan=n] */
625 if (str[3]) {
626 if (!strncmp(str + 3, ",vlan=", 6)) {
627 vlan = qemu_find_bt_vlan(strtol(str + 9, &endp, 0));
628 if (*endp)
629 vlan = 0;
630 }
631 } else
632 vlan = qemu_find_bt_vlan(0);
633 if (vlan)
634 return bt_new_hci(vlan);
635 }
636
637 fprintf(stderr, "qemu: Unknown bluetooth HCI `%s'.\n", str);
638
639 return 0;
640}
641
642static int bt_hci_parse(const char *str)
643{
644 struct HCIInfo *hci;
645 bdaddr_t bdaddr;
646
647 if (nb_hcis >= MAX_NICS) {
648 fprintf(stderr, "qemu: Too many bluetooth HCIs (max %i).\n", MAX_NICS);
649 return -1;
650 }
651
652 hci = hci_init(str);
653 if (!hci)
654 return -1;
655
656 bdaddr.b[0] = 0x52;
657 bdaddr.b[1] = 0x54;
658 bdaddr.b[2] = 0x00;
659 bdaddr.b[3] = 0x12;
660 bdaddr.b[4] = 0x34;
661 bdaddr.b[5] = 0x56 + nb_hcis;
662 hci->bdaddr_set(hci, bdaddr.b);
663
664 hci_table[nb_hcis++] = hci;
665
666 return 0;
667}
668
669static void bt_vhci_add(int vlan_id)
670{
671 struct bt_scatternet_s *vlan = qemu_find_bt_vlan(vlan_id);
672
673 if (!vlan->slave)
674 fprintf(stderr, "qemu: warning: adding a VHCI to "
675 "an empty scatternet %i\n", vlan_id);
676
677 bt_vhci_init(bt_new_hci(vlan));
678}
679
680static struct bt_device_s *bt_device_add(const char *opt)
681{
682 struct bt_scatternet_s *vlan;
683 int vlan_id = 0;
684 char *endp = strstr(opt, ",vlan=");
685 int len = (endp ? endp - opt : strlen(opt)) + 1;
686 char devname[10];
687
688 pstrcpy(devname, MIN(sizeof(devname), len), opt);
689
690 if (endp) {
691 vlan_id = strtol(endp + 6, &endp, 0);
692 if (*endp) {
693 fprintf(stderr, "qemu: unrecognised bluetooth vlan Id\n");
694 return 0;
695 }
696 }
697
698 vlan = qemu_find_bt_vlan(vlan_id);
699
700 if (!vlan->slave)
701 fprintf(stderr, "qemu: warning: adding a slave device to "
702 "an empty scatternet %i\n", vlan_id);
703
704 if (!strcmp(devname, "keyboard"))
705 return bt_keyboard_init(vlan);
706
707 fprintf(stderr, "qemu: unsupported bluetooth device `%s'\n", devname);
708 return 0;
709}
710
711static int bt_parse(const char *opt)
712{
713 const char *endp, *p;
714 int vlan;
715
716 if (strstart(opt, "hci", &endp)) {
717 if (!*endp || *endp == ',') {
718 if (*endp)
719 if (!strstart(endp, ",vlan=", 0))
720 opt = endp + 1;
721
722 return bt_hci_parse(opt);
723 }
724 } else if (strstart(opt, "vhci", &endp)) {
725 if (!*endp || *endp == ',') {
726 if (*endp) {
727 if (strstart(endp, ",vlan=", &p)) {
728 vlan = strtol(p, (char **) &endp, 0);
729 if (*endp) {
730 fprintf(stderr, "qemu: bad scatternet '%s'\n", p);
731 return 1;
732 }
733 } else {
734 fprintf(stderr, "qemu: bad parameter '%s'\n", endp + 1);
735 return 1;
736 }
737 } else
738 vlan = 0;
739
740 bt_vhci_add(vlan);
741 return 0;
742 }
743 } else if (strstart(opt, "device:", &endp))
744 return !bt_device_add(endp);
745
746 fprintf(stderr, "qemu: bad bluetooth parameter '%s'\n", opt);
747 return 1;
748}
749
750/***********************************************************/
751/* QEMU Block devices */
752
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800753#define HD_ALIAS "index=%d,media=disk"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800754#define CDROM_ALIAS "index=2,media=cdrom"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800755#define FD_ALIAS "index=%d,if=floppy"
756#define PFLASH_ALIAS "if=pflash"
757#define MTD_ALIAS "if=mtd"
758#define SD_ALIAS "index=0,if=sd"
759
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700760static int drive_opt_get_free_idx(void)
761{
762 int index;
763
764 for (index = 0; index < MAX_DRIVES; index++)
765 if (!drives_opt[index].used) {
766 drives_opt[index].used = 1;
767 return index;
768 }
769
770 return -1;
771}
772
773static int drive_get_free_idx(void)
774{
775 int index;
776
777 for (index = 0; index < MAX_DRIVES; index++)
778 if (!drives_table[index].used) {
779 drives_table[index].used = 1;
780 return index;
781 }
782
783 return -1;
784}
785
786int drive_add(const char *file, const char *fmt, ...)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800787{
788 va_list ap;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700789 int index = drive_opt_get_free_idx();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800790
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700791 if (nb_drives_opt >= MAX_DRIVES || index == -1) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800792 fprintf(stderr, "qemu: too many drives\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700793 return -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800794 }
795
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700796 drives_opt[index].file = file;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800797 va_start(ap, fmt);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700798 vsnprintf(drives_opt[index].opt,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800799 sizeof(drives_opt[0].opt), fmt, ap);
800 va_end(ap);
801
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700802 nb_drives_opt++;
803 return index;
804}
805
806void drive_remove(int index)
807{
808 drives_opt[index].used = 0;
809 nb_drives_opt--;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800810}
811
812int drive_get_index(BlockInterfaceType type, int bus, int unit)
813{
814 int index;
815
816 /* seek interface, bus and unit */
817
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700818 for (index = 0; index < MAX_DRIVES; index++)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800819 if (drives_table[index].type == type &&
820 drives_table[index].bus == bus &&
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700821 drives_table[index].unit == unit &&
822 drives_table[index].used)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800823 return index;
824
825 return -1;
826}
827
828int drive_get_max_bus(BlockInterfaceType type)
829{
830 int max_bus;
831 int index;
832
833 max_bus = -1;
834 for (index = 0; index < nb_drives; index++) {
835 if(drives_table[index].type == type &&
836 drives_table[index].bus > max_bus)
837 max_bus = drives_table[index].bus;
838 }
839 return max_bus;
840}
841
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700842const char *drive_get_serial(BlockDriverState *bdrv)
843{
844 int index;
845
846 for (index = 0; index < nb_drives; index++)
847 if (drives_table[index].bdrv == bdrv)
848 return drives_table[index].serial;
849
850 return "\0";
851}
852
853BlockInterfaceErrorAction drive_get_onerror(BlockDriverState *bdrv)
854{
855 int index;
856
857 for (index = 0; index < nb_drives; index++)
858 if (drives_table[index].bdrv == bdrv)
859 return drives_table[index].onerror;
860
861 return BLOCK_ERR_STOP_ENOSPC;
862}
863
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800864static void bdrv_format_print(void *opaque, const char *name)
865{
866 fprintf(stderr, " %s", name);
867}
868
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700869void drive_uninit(BlockDriverState *bdrv)
870{
871 int i;
872
873 for (i = 0; i < MAX_DRIVES; i++)
874 if (drives_table[i].bdrv == bdrv) {
875 drives_table[i].bdrv = NULL;
876 drives_table[i].used = 0;
877 drive_remove(drives_table[i].drive_opt_idx);
878 nb_drives--;
879 break;
880 }
881}
882
883int drive_init(struct drive_opt *arg, int snapshot, void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800884{
885 char buf[128];
886 char file[1024];
887 char devname[128];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700888 char serial[21];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800889 const char *mediastr = "";
890 BlockInterfaceType type;
891 enum { MEDIA_DISK, MEDIA_CDROM } media;
892 int bus_id, unit_id;
893 int cyls, heads, secs, translation;
894 BlockDriverState *bdrv;
895 BlockDriver *drv = NULL;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700896 QEMUMachine *machine = opaque;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800897 int max_devs;
898 int index;
899 int cache;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700900 int bdrv_flags, onerror;
901 int drives_table_idx;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800902 char *str = arg->opt;
903 static const char * const params[] = { "bus", "unit", "if", "index",
904 "cyls", "heads", "secs", "trans",
905 "media", "snapshot", "file",
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700906 "cache", "format", "serial", "werror",
907 NULL };
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800908
909 if (check_params(buf, sizeof(buf), params, str) < 0) {
910 fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n",
911 buf, str);
912 return -1;
913 }
914
915 file[0] = 0;
916 cyls = heads = secs = 0;
917 bus_id = 0;
918 unit_id = -1;
919 translation = BIOS_ATA_TRANSLATION_AUTO;
920 index = -1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700921 cache = 3;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800922
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700923 if (machine->use_scsi) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800924 type = IF_SCSI;
925 max_devs = MAX_SCSI_DEVS;
926 pstrcpy(devname, sizeof(devname), "scsi");
927 } else {
928 type = IF_IDE;
929 max_devs = MAX_IDE_DEVS;
930 pstrcpy(devname, sizeof(devname), "ide");
931 }
932 media = MEDIA_DISK;
933
934 /* extract parameters */
935
936 if (get_param_value(buf, sizeof(buf), "bus", str)) {
937 bus_id = strtol(buf, NULL, 0);
938 if (bus_id < 0) {
939 fprintf(stderr, "qemu: '%s' invalid bus id\n", str);
940 return -1;
941 }
942 }
943
944 if (get_param_value(buf, sizeof(buf), "unit", str)) {
945 unit_id = strtol(buf, NULL, 0);
946 if (unit_id < 0) {
947 fprintf(stderr, "qemu: '%s' invalid unit id\n", str);
948 return -1;
949 }
950 }
951
952 if (get_param_value(buf, sizeof(buf), "if", str)) {
953 pstrcpy(devname, sizeof(devname), buf);
954 if (!strcmp(buf, "ide")) {
955 type = IF_IDE;
956 max_devs = MAX_IDE_DEVS;
957 } else if (!strcmp(buf, "scsi")) {
958 type = IF_SCSI;
959 max_devs = MAX_SCSI_DEVS;
960 } else if (!strcmp(buf, "floppy")) {
961 type = IF_FLOPPY;
962 max_devs = 0;
963 } else if (!strcmp(buf, "pflash")) {
964 type = IF_PFLASH;
965 max_devs = 0;
966 } else if (!strcmp(buf, "mtd")) {
967 type = IF_MTD;
968 max_devs = 0;
969 } else if (!strcmp(buf, "sd")) {
970 type = IF_SD;
971 max_devs = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700972 } else if (!strcmp(buf, "virtio")) {
973 type = IF_VIRTIO;
974 max_devs = 0;
975 } else if (!strcmp(buf, "xen")) {
976 type = IF_XEN;
977 max_devs = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800978 } else {
979 fprintf(stderr, "qemu: '%s' unsupported bus type '%s'\n", str, buf);
980 return -1;
981 }
982 }
983
984 if (get_param_value(buf, sizeof(buf), "index", str)) {
985 index = strtol(buf, NULL, 0);
986 if (index < 0) {
987 fprintf(stderr, "qemu: '%s' invalid index\n", str);
988 return -1;
989 }
990 }
991
992 if (get_param_value(buf, sizeof(buf), "cyls", str)) {
993 cyls = strtol(buf, NULL, 0);
994 }
995
996 if (get_param_value(buf, sizeof(buf), "heads", str)) {
997 heads = strtol(buf, NULL, 0);
998 }
999
1000 if (get_param_value(buf, sizeof(buf), "secs", str)) {
1001 secs = strtol(buf, NULL, 0);
1002 }
1003
1004 if (cyls || heads || secs) {
1005 if (cyls < 1 || cyls > 16383) {
1006 fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", str);
1007 return -1;
1008 }
1009 if (heads < 1 || heads > 16) {
1010 fprintf(stderr, "qemu: '%s' invalid physical heads number\n", str);
1011 return -1;
1012 }
1013 if (secs < 1 || secs > 63) {
1014 fprintf(stderr, "qemu: '%s' invalid physical secs number\n", str);
1015 return -1;
1016 }
1017 }
1018
1019 if (get_param_value(buf, sizeof(buf), "trans", str)) {
1020 if (!cyls) {
1021 fprintf(stderr,
1022 "qemu: '%s' trans must be used with cyls,heads and secs\n",
1023 str);
1024 return -1;
1025 }
1026 if (!strcmp(buf, "none"))
1027 translation = BIOS_ATA_TRANSLATION_NONE;
1028 else if (!strcmp(buf, "lba"))
1029 translation = BIOS_ATA_TRANSLATION_LBA;
1030 else if (!strcmp(buf, "auto"))
1031 translation = BIOS_ATA_TRANSLATION_AUTO;
1032 else {
1033 fprintf(stderr, "qemu: '%s' invalid translation type\n", str);
1034 return -1;
1035 }
1036 }
1037
1038 if (get_param_value(buf, sizeof(buf), "media", str)) {
1039 if (!strcmp(buf, "disk")) {
1040 media = MEDIA_DISK;
1041 } else if (!strcmp(buf, "cdrom")) {
1042 if (cyls || secs || heads) {
1043 fprintf(stderr,
1044 "qemu: '%s' invalid physical CHS format\n", str);
1045 return -1;
1046 }
1047 media = MEDIA_CDROM;
1048 } else {
1049 fprintf(stderr, "qemu: '%s' invalid media\n", str);
1050 return -1;
1051 }
1052 }
1053
1054 if (get_param_value(buf, sizeof(buf), "snapshot", str)) {
1055 if (!strcmp(buf, "on"))
1056 snapshot = 1;
1057 else if (!strcmp(buf, "off"))
1058 snapshot = 0;
1059 else {
1060 fprintf(stderr, "qemu: '%s' invalid snapshot option\n", str);
1061 return -1;
1062 }
1063 }
1064
1065 if (get_param_value(buf, sizeof(buf), "cache", str)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001066 if (!strcmp(buf, "off") || !strcmp(buf, "none"))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001067 cache = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001068 else if (!strcmp(buf, "writethrough"))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001069 cache = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001070 else if (!strcmp(buf, "writeback"))
1071 cache = 2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001072 else {
1073 fprintf(stderr, "qemu: invalid cache option\n");
1074 return -1;
1075 }
1076 }
1077
1078 if (get_param_value(buf, sizeof(buf), "format", str)) {
1079 if (strcmp(buf, "?") == 0) {
1080 fprintf(stderr, "qemu: Supported formats:");
1081 bdrv_iterate_format(bdrv_format_print, NULL);
1082 fprintf(stderr, "\n");
1083 return -1;
1084 }
1085 drv = bdrv_find_format(buf);
1086 if (!drv) {
1087 fprintf(stderr, "qemu: '%s' invalid format\n", buf);
1088 return -1;
1089 }
1090 }
1091
1092 if (arg->file == NULL)
1093 get_param_value(file, sizeof(file), "file", str);
1094 else
1095 pstrcpy(file, sizeof(file), arg->file);
1096
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001097 if (!get_param_value(serial, sizeof(serial), "serial", str))
1098 memset(serial, 0, sizeof(serial));
1099
1100 onerror = BLOCK_ERR_STOP_ENOSPC;
1101 if (get_param_value(buf, sizeof(serial), "werror", str)) {
1102 if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO) {
1103 fprintf(stderr, "werror is no supported by this format\n");
1104 return -1;
1105 }
1106 if (!strcmp(buf, "ignore"))
1107 onerror = BLOCK_ERR_IGNORE;
1108 else if (!strcmp(buf, "enospc"))
1109 onerror = BLOCK_ERR_STOP_ENOSPC;
1110 else if (!strcmp(buf, "stop"))
1111 onerror = BLOCK_ERR_STOP_ANY;
1112 else if (!strcmp(buf, "report"))
1113 onerror = BLOCK_ERR_REPORT;
1114 else {
1115 fprintf(stderr, "qemu: '%s' invalid write error action\n", buf);
1116 return -1;
1117 }
1118 }
1119
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001120 /* compute bus and unit according index */
1121
1122 if (index != -1) {
1123 if (bus_id != 0 || unit_id != -1) {
1124 fprintf(stderr,
1125 "qemu: '%s' index cannot be used with bus and unit\n", str);
1126 return -1;
1127 }
1128 if (max_devs == 0)
1129 {
1130 unit_id = index;
1131 bus_id = 0;
1132 } else {
1133 unit_id = index % max_devs;
1134 bus_id = index / max_devs;
1135 }
1136 }
1137
1138 /* if user doesn't specify a unit_id,
1139 * try to find the first free
1140 */
1141
1142 if (unit_id == -1) {
1143 unit_id = 0;
1144 while (drive_get_index(type, bus_id, unit_id) != -1) {
1145 unit_id++;
1146 if (max_devs && unit_id >= max_devs) {
1147 unit_id -= max_devs;
1148 bus_id++;
1149 }
1150 }
1151 }
1152
1153 /* check unit id */
1154
1155 if (max_devs && unit_id >= max_devs) {
1156 fprintf(stderr, "qemu: '%s' unit %d too big (max is %d)\n",
1157 str, unit_id, max_devs - 1);
1158 return -1;
1159 }
1160
1161 /*
1162 * ignore multiple definitions
1163 */
1164
1165 if (drive_get_index(type, bus_id, unit_id) != -1)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001166 return -2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001167
1168 /* init */
1169
1170 if (type == IF_IDE || type == IF_SCSI)
1171 mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
1172 if (max_devs)
1173 snprintf(buf, sizeof(buf), "%s%i%s%i",
1174 devname, bus_id, mediastr, unit_id);
1175 else
1176 snprintf(buf, sizeof(buf), "%s%s%i",
1177 devname, mediastr, unit_id);
1178 bdrv = bdrv_new(buf);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001179 drives_table_idx = drive_get_free_idx();
1180 drives_table[drives_table_idx].bdrv = bdrv;
1181 drives_table[drives_table_idx].type = type;
1182 drives_table[drives_table_idx].bus = bus_id;
1183 drives_table[drives_table_idx].unit = unit_id;
1184 drives_table[drives_table_idx].onerror = onerror;
1185 drives_table[drives_table_idx].drive_opt_idx = arg - drives_opt;
1186 strncpy(drives_table[drives_table_idx].serial, serial, sizeof(serial));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001187 nb_drives++;
1188
1189 switch(type) {
1190 case IF_IDE:
1191 case IF_SCSI:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001192 case IF_XEN:
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001193 switch(media) {
1194 case MEDIA_DISK:
1195 if (cyls != 0) {
1196 bdrv_set_geometry_hint(bdrv, cyls, heads, secs);
1197 bdrv_set_translation_hint(bdrv, translation);
1198 }
1199 break;
1200 case MEDIA_CDROM:
1201 bdrv_set_type_hint(bdrv, BDRV_TYPE_CDROM);
1202 break;
1203 }
1204 break;
1205 case IF_SD:
1206 /* FIXME: This isn't really a floppy, but it's a reasonable
1207 approximation. */
1208 case IF_FLOPPY:
1209 bdrv_set_type_hint(bdrv, BDRV_TYPE_FLOPPY);
1210 break;
1211 case IF_PFLASH:
1212 case IF_MTD:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001213 case IF_VIRTIO:
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001214 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001215 case IF_COUNT:
1216 abort();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001217 }
1218 if (!file[0])
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001219 return -2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001220 bdrv_flags = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001221 if (snapshot) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001222 bdrv_flags |= BDRV_O_SNAPSHOT;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001223 cache = 2; /* always use write-back with snapshot */
1224 }
1225 if (cache == 0) /* no caching */
1226 bdrv_flags |= BDRV_O_NOCACHE;
1227 else if (cache == 2) /* write-back */
1228 bdrv_flags |= BDRV_O_CACHE_WB;
1229 else if (cache == 3) /* not specified */
1230 bdrv_flags |= BDRV_O_CACHE_DEF;
1231 if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001232 fprintf(stderr, "qemu: could not open disk image %s\n",
1233 file);
1234 return -1;
1235 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001236 if (bdrv_key_required(bdrv))
1237 autostart = 0;
1238 return drives_table_idx;
1239}
1240
1241static void numa_add(const char *optarg)
1242{
1243 char option[128];
1244 char *endptr;
1245 unsigned long long value, endvalue;
1246 int nodenr;
1247
1248 optarg = get_opt_name(option, 128, optarg, ',') + 1;
1249 if (!strcmp(option, "node")) {
1250 if (get_param_value(option, 128, "nodeid", optarg) == 0) {
1251 nodenr = nb_numa_nodes;
1252 } else {
1253 nodenr = strtoull(option, NULL, 10);
1254 }
1255
1256 if (get_param_value(option, 128, "mem", optarg) == 0) {
1257 node_mem[nodenr] = 0;
1258 } else {
1259 value = strtoull(option, &endptr, 0);
1260 switch (*endptr) {
1261 case 0: case 'M': case 'm':
1262 value <<= 20;
1263 break;
1264 case 'G': case 'g':
1265 value <<= 30;
1266 break;
1267 }
1268 node_mem[nodenr] = value;
1269 }
1270 if (get_param_value(option, 128, "cpus", optarg) == 0) {
1271 node_cpumask[nodenr] = 0;
1272 } else {
1273 value = strtoull(option, &endptr, 10);
1274 if (value >= 64) {
1275 value = 63;
1276 fprintf(stderr, "only 64 CPUs in NUMA mode supported.\n");
1277 } else {
1278 if (*endptr == '-') {
1279 endvalue = strtoull(endptr+1, &endptr, 10);
1280 if (endvalue >= 63) {
1281 endvalue = 62;
1282 fprintf(stderr,
1283 "only 63 CPUs in NUMA mode supported.\n");
1284 }
1285 value = (1 << (endvalue + 1)) - (1 << value);
1286 } else {
1287 value = 1 << value;
1288 }
1289 }
1290 node_cpumask[nodenr] = value;
1291 }
1292 nb_numa_nodes++;
1293 }
1294 return;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001295}
1296
1297/***********************************************************/
1298/* USB devices */
1299
1300static USBPort *used_usb_ports;
1301static USBPort *free_usb_ports;
1302
1303/* ??? Maybe change this to register a hub to keep track of the topology. */
1304void qemu_register_usb_port(USBPort *port, void *opaque, int index,
1305 usb_attachfn attach)
1306{
1307 port->opaque = opaque;
1308 port->index = index;
1309 port->attach = attach;
1310 port->next = free_usb_ports;
1311 free_usb_ports = port;
1312}
1313
1314int usb_device_add_dev(USBDevice *dev)
1315{
1316 USBPort *port;
1317
1318 /* Find a USB port to add the device to. */
1319 port = free_usb_ports;
1320 if (!port->next) {
1321 USBDevice *hub;
1322
1323 /* Create a new hub and chain it on. */
1324 free_usb_ports = NULL;
1325 port->next = used_usb_ports;
1326 used_usb_ports = port;
1327
1328 hub = usb_hub_init(VM_USB_HUB_SIZE);
1329 usb_attach(port, hub);
1330 port = free_usb_ports;
1331 }
1332
1333 free_usb_ports = port->next;
1334 port->next = used_usb_ports;
1335 used_usb_ports = port;
1336 usb_attach(port, dev);
1337 return 0;
1338}
1339
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001340static void usb_msd_password_cb(void *opaque, int err)
1341{
1342 USBDevice *dev = opaque;
1343
1344 if (!err)
1345 usb_device_add_dev(dev);
1346 else
1347 dev->handle_destroy(dev);
1348}
1349
1350static int usb_device_add(const char *devname, int is_hotplug)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001351{
1352 const char *p;
1353 USBDevice *dev;
1354
1355 if (!free_usb_ports)
1356 return -1;
1357
1358 if (strstart(devname, "host:", &p)) {
1359 dev = usb_host_device_open(p);
1360 } else if (!strcmp(devname, "mouse")) {
1361 dev = usb_mouse_init();
1362 } else if (!strcmp(devname, "tablet")) {
1363 dev = usb_tablet_init();
1364 } else if (!strcmp(devname, "keyboard")) {
1365 dev = usb_keyboard_init();
1366 } else if (strstart(devname, "disk:", &p)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001367 BlockDriverState *bs;
1368
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001369 dev = usb_msd_init(p);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001370 if (!dev)
1371 return -1;
1372 bs = usb_msd_get_bdrv(dev);
1373 if (bdrv_key_required(bs)) {
1374 autostart = 0;
1375 if (is_hotplug) {
1376 monitor_read_bdrv_key_start(cur_mon, bs, usb_msd_password_cb,
1377 dev);
1378 return 0;
1379 }
1380 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001381 } else if (!strcmp(devname, "wacom-tablet")) {
1382 dev = usb_wacom_init();
1383 } else if (strstart(devname, "serial:", &p)) {
1384 dev = usb_serial_init(p);
1385#ifdef CONFIG_BRLAPI
1386 } else if (!strcmp(devname, "braille")) {
1387 dev = usb_baum_init();
1388#endif
1389 } else if (strstart(devname, "net:", &p)) {
1390 int nic = nb_nics;
1391
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001392 if (net_client_init(NULL, "nic", p) < 0)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001393 return -1;
1394 nd_table[nic].model = "usb";
1395 dev = usb_net_init(&nd_table[nic]);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001396 } else if (!strcmp(devname, "bt") || strstart(devname, "bt:", &p)) {
1397 dev = usb_bt_init(devname[2] ? hci_init(p) :
1398 bt_new_hci(qemu_find_bt_vlan(0)));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001399 } else {
1400 return -1;
1401 }
1402 if (!dev)
1403 return -1;
1404
1405 return usb_device_add_dev(dev);
1406}
1407
1408int usb_device_del_addr(int bus_num, int addr)
1409{
1410 USBPort *port;
1411 USBPort **lastp;
1412 USBDevice *dev;
1413
1414 if (!used_usb_ports)
1415 return -1;
1416
1417 if (bus_num != 0)
1418 return -1;
1419
1420 lastp = &used_usb_ports;
1421 port = used_usb_ports;
1422 while (port && port->dev->addr != addr) {
1423 lastp = &port->next;
1424 port = port->next;
1425 }
1426
1427 if (!port)
1428 return -1;
1429
1430 dev = port->dev;
1431 *lastp = port->next;
1432 usb_attach(port, NULL);
1433 dev->handle_destroy(dev);
1434 port->next = free_usb_ports;
1435 free_usb_ports = port;
1436 return 0;
1437}
1438
1439static int usb_device_del(const char *devname)
1440{
1441 int bus_num, addr;
1442 const char *p;
1443
1444 if (strstart(devname, "host:", &p))
1445 return usb_host_device_close(p);
1446
1447 if (!used_usb_ports)
1448 return -1;
1449
1450 p = strchr(devname, '.');
1451 if (!p)
1452 return -1;
1453 bus_num = strtoul(devname, NULL, 0);
1454 addr = strtoul(p + 1, NULL, 0);
1455
1456 return usb_device_del_addr(bus_num, addr);
1457}
1458
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001459void do_usb_add(Monitor *mon, const char *devname)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001460{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001461 usb_device_add(devname, 1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001462}
1463
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001464void do_usb_del(Monitor *mon, const char *devname)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001465{
1466 usb_device_del(devname);
1467}
1468
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001469void usb_info(Monitor *mon)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001470{
1471 USBDevice *dev;
1472 USBPort *port;
1473 const char *speed_str;
1474
1475 if (!usb_enabled) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001476 monitor_printf(mon, "USB support not enabled\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001477 return;
1478 }
1479
1480 for (port = used_usb_ports; port; port = port->next) {
1481 dev = port->dev;
1482 if (!dev)
1483 continue;
1484 switch(dev->speed) {
1485 case USB_SPEED_LOW:
1486 speed_str = "1.5";
1487 break;
1488 case USB_SPEED_FULL:
1489 speed_str = "12";
1490 break;
1491 case USB_SPEED_HIGH:
1492 speed_str = "480";
1493 break;
1494 default:
1495 speed_str = "?";
1496 break;
1497 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001498 monitor_printf(mon, " Device %d.%d, Speed %s Mb/s, Product %s\n",
1499 0, dev->addr, speed_str, dev->devname);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001500 }
1501}
1502
1503/***********************************************************/
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001504/* PCMCIA/Cardbus */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001505
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001506static struct pcmcia_socket_entry_s {
1507 PCMCIASocket *socket;
1508 struct pcmcia_socket_entry_s *next;
1509} *pcmcia_sockets = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001510
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001511void pcmcia_socket_register(PCMCIASocket *socket)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001512{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001513 struct pcmcia_socket_entry_s *entry;
1514
1515 entry = qemu_malloc(sizeof(struct pcmcia_socket_entry_s));
1516 entry->socket = socket;
1517 entry->next = pcmcia_sockets;
1518 pcmcia_sockets = entry;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001519}
1520
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001521void pcmcia_socket_unregister(PCMCIASocket *socket)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001522{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001523 struct pcmcia_socket_entry_s *entry, **ptr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001524
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001525 ptr = &pcmcia_sockets;
1526 for (entry = *ptr; entry; ptr = &entry->next, entry = *ptr)
1527 if (entry->socket == socket) {
1528 *ptr = entry->next;
1529 qemu_free(entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001530 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001531}
1532
1533void pcmcia_info(Monitor *mon)
1534{
1535 struct pcmcia_socket_entry_s *iter;
1536
1537 if (!pcmcia_sockets)
1538 monitor_printf(mon, "No PCMCIA sockets\n");
1539
1540 for (iter = pcmcia_sockets; iter; iter = iter->next)
1541 monitor_printf(mon, "%s: %s\n", iter->socket->slot_string,
1542 iter->socket->attached ? iter->socket->card_string :
1543 "Empty");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001544}
1545
1546/***********************************************************/
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001547/* register display */
1548
1549struct DisplayAllocator default_allocator = {
1550 defaultallocator_create_displaysurface,
1551 defaultallocator_resize_displaysurface,
1552 defaultallocator_free_displaysurface
1553};
1554
1555void register_displaystate(DisplayState *ds)
1556{
1557 DisplayState **s;
1558 s = &display_state;
1559 while (*s != NULL)
1560 s = &(*s)->next;
1561 ds->next = NULL;
1562 *s = ds;
1563}
1564
1565DisplayState *get_displaystate(void)
1566{
1567 return display_state;
1568}
1569
1570DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da)
1571{
1572 if(ds->allocator == &default_allocator) ds->allocator = da;
1573 return ds->allocator;
1574}
1575
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001576/* dumb display */
1577
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001578static void dumb_display_init(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001579{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001580 DisplayState *ds = qemu_mallocz(sizeof(DisplayState));
1581 ds->allocator = &default_allocator;
1582 ds->surface = qemu_create_displaysurface(ds, 640, 480);
1583 register_displaystate(ds);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001584}
1585
1586/***********************************************************/
1587/* I/O handling */
1588
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001589typedef struct IOHandlerRecord {
1590 int fd;
David Turner4143d8f2010-09-10 11:05:02 +02001591 IOCanReadHandler *fd_read_poll;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001592 IOHandler *fd_read;
1593 IOHandler *fd_write;
1594 int deleted;
1595 void *opaque;
1596 /* temporary data */
1597 struct pollfd *ufd;
David Turner025c32f2010-09-10 14:52:42 +02001598 QLIST_ENTRY(IOHandlerRecord) next;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001599} IOHandlerRecord;
1600
David Turner025c32f2010-09-10 14:52:42 +02001601static QLIST_HEAD(, IOHandlerRecord) io_handlers =
1602 QLIST_HEAD_INITIALIZER(io_handlers);
1603
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001604
1605/* XXX: fd_read_poll should be suppressed, but an API change is
1606 necessary in the character devices to suppress fd_can_read(). */
1607int qemu_set_fd_handler2(int fd,
David Turner4143d8f2010-09-10 11:05:02 +02001608 IOCanReadHandler *fd_read_poll,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001609 IOHandler *fd_read,
1610 IOHandler *fd_write,
1611 void *opaque)
1612{
David Turner025c32f2010-09-10 14:52:42 +02001613 IOHandlerRecord *ioh;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001614
1615 if (!fd_read && !fd_write) {
David Turner025c32f2010-09-10 14:52:42 +02001616 QLIST_FOREACH(ioh, &io_handlers, next) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001617 if (ioh->fd == fd) {
1618 ioh->deleted = 1;
1619 break;
1620 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001621 }
1622 } else {
David Turner025c32f2010-09-10 14:52:42 +02001623 QLIST_FOREACH(ioh, &io_handlers, next) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001624 if (ioh->fd == fd)
1625 goto found;
1626 }
1627 ioh = qemu_mallocz(sizeof(IOHandlerRecord));
David Turner025c32f2010-09-10 14:52:42 +02001628 QLIST_INSERT_HEAD(&io_handlers, ioh, next);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001629 found:
1630 ioh->fd = fd;
1631 ioh->fd_read_poll = fd_read_poll;
1632 ioh->fd_read = fd_read;
1633 ioh->fd_write = fd_write;
1634 ioh->opaque = opaque;
1635 ioh->deleted = 0;
1636 }
1637 return 0;
1638}
1639
1640int qemu_set_fd_handler(int fd,
1641 IOHandler *fd_read,
1642 IOHandler *fd_write,
1643 void *opaque)
1644{
1645 return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque);
1646}
1647
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001648#ifdef _WIN32
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001649/***********************************************************/
1650/* Polling handling */
1651
1652typedef struct PollingEntry {
1653 PollingFunc *func;
1654 void *opaque;
1655 struct PollingEntry *next;
1656} PollingEntry;
1657
1658static PollingEntry *first_polling_entry;
1659
1660int qemu_add_polling_cb(PollingFunc *func, void *opaque)
1661{
1662 PollingEntry **ppe, *pe;
1663 pe = qemu_mallocz(sizeof(PollingEntry));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001664 pe->func = func;
1665 pe->opaque = opaque;
1666 for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next);
1667 *ppe = pe;
1668 return 0;
1669}
1670
1671void qemu_del_polling_cb(PollingFunc *func, void *opaque)
1672{
1673 PollingEntry **ppe, *pe;
1674 for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next) {
1675 pe = *ppe;
1676 if (pe->func == func && pe->opaque == opaque) {
1677 *ppe = pe->next;
1678 qemu_free(pe);
1679 break;
1680 }
1681 }
1682}
1683
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001684/***********************************************************/
1685/* Wait objects support */
1686typedef struct WaitObjects {
1687 int num;
1688 HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
1689 WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
1690 void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
1691} WaitObjects;
1692
1693static WaitObjects wait_objects = {0};
1694
1695int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
1696{
1697 WaitObjects *w = &wait_objects;
1698
1699 if (w->num >= MAXIMUM_WAIT_OBJECTS)
1700 return -1;
1701 w->events[w->num] = handle;
1702 w->func[w->num] = func;
1703 w->opaque[w->num] = opaque;
1704 w->num++;
1705 return 0;
1706}
1707
1708void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
1709{
1710 int i, found;
1711 WaitObjects *w = &wait_objects;
1712
1713 found = 0;
1714 for (i = 0; i < w->num; i++) {
1715 if (w->events[i] == handle)
1716 found = 1;
1717 if (found) {
1718 w->events[i] = w->events[i + 1];
1719 w->func[i] = w->func[i + 1];
1720 w->opaque[i] = w->opaque[i + 1];
1721 }
1722 }
1723 if (found)
1724 w->num--;
1725}
1726#endif
1727
1728/***********************************************************/
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001729/* ram save/restore */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001730
1731static int ram_get_page(QEMUFile *f, uint8_t *buf, int len)
1732{
1733 int v;
1734
1735 v = qemu_get_byte(f);
1736 switch(v) {
1737 case 0:
1738 if (qemu_get_buffer(f, buf, len) != len)
1739 return -EIO;
1740 break;
1741 case 1:
1742 v = qemu_get_byte(f);
1743 memset(buf, v, len);
1744 break;
1745 default:
1746 return -EINVAL;
1747 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001748
1749 if (qemu_file_has_error(f))
1750 return -EIO;
1751
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001752 return 0;
1753}
1754
1755static int ram_load_v1(QEMUFile *f, void *opaque)
1756{
1757 int ret;
1758 ram_addr_t i;
1759
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001760 if (qemu_get_be32(f) != last_ram_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001761 return -EINVAL;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001762 for(i = 0; i < last_ram_offset; i+= TARGET_PAGE_SIZE) {
1763 ret = ram_get_page(f, qemu_get_ram_ptr(i), TARGET_PAGE_SIZE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001764 if (ret)
1765 return ret;
1766 }
1767 return 0;
1768}
1769
1770#define BDRV_HASH_BLOCK_SIZE 1024
1771#define IOBUF_SIZE 4096
1772#define RAM_CBLOCK_MAGIC 0xfabe
1773
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001774typedef struct RamDecompressState {
1775 z_stream zstream;
1776 QEMUFile *f;
1777 uint8_t buf[IOBUF_SIZE];
1778} RamDecompressState;
1779
1780static int ram_decompress_open(RamDecompressState *s, QEMUFile *f)
1781{
1782 int ret;
1783 memset(s, 0, sizeof(*s));
1784 s->f = f;
1785 ret = inflateInit(&s->zstream);
1786 if (ret != Z_OK)
1787 return -1;
1788 return 0;
1789}
1790
1791static int ram_decompress_buf(RamDecompressState *s, uint8_t *buf, int len)
1792{
1793 int ret, clen;
1794
1795 s->zstream.avail_out = len;
1796 s->zstream.next_out = buf;
1797 while (s->zstream.avail_out > 0) {
1798 if (s->zstream.avail_in == 0) {
1799 if (qemu_get_be16(s->f) != RAM_CBLOCK_MAGIC)
1800 return -1;
1801 clen = qemu_get_be16(s->f);
1802 if (clen > IOBUF_SIZE)
1803 return -1;
1804 qemu_get_buffer(s->f, s->buf, clen);
1805 s->zstream.avail_in = clen;
1806 s->zstream.next_in = s->buf;
1807 }
1808 ret = inflate(&s->zstream, Z_PARTIAL_FLUSH);
1809 if (ret != Z_OK && ret != Z_STREAM_END) {
1810 return -1;
1811 }
1812 }
1813 return 0;
1814}
1815
1816static void ram_decompress_close(RamDecompressState *s)
1817{
1818 inflateEnd(&s->zstream);
1819}
1820
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001821#define RAM_SAVE_FLAG_FULL 0x01
1822#define RAM_SAVE_FLAG_COMPRESS 0x02
1823#define RAM_SAVE_FLAG_MEM_SIZE 0x04
1824#define RAM_SAVE_FLAG_PAGE 0x08
1825#define RAM_SAVE_FLAG_EOS 0x10
1826
1827static int is_dup_page(uint8_t *page, uint8_t ch)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001828{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001829 uint32_t val = ch << 24 | ch << 16 | ch << 8 | ch;
1830 uint32_t *array = (uint32_t *)page;
1831 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001832
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001833 for (i = 0; i < (TARGET_PAGE_SIZE / 4); i++) {
1834 if (array[i] != val)
1835 return 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001836 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001837
1838 return 1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001839}
1840
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001841static int ram_save_block(QEMUFile *f)
1842{
1843 static ram_addr_t current_addr = 0;
1844 ram_addr_t saved_addr = current_addr;
1845 ram_addr_t addr = 0;
1846 int found = 0;
1847
1848 while (addr < last_ram_offset) {
1849 if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
1850 uint8_t *p;
1851
1852 cpu_physical_memory_reset_dirty(current_addr,
1853 current_addr + TARGET_PAGE_SIZE,
1854 MIGRATION_DIRTY_FLAG);
1855
1856 p = qemu_get_ram_ptr(current_addr);
1857
1858 if (is_dup_page(p, *p)) {
1859 qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_COMPRESS);
1860 qemu_put_byte(f, *p);
1861 } else {
1862 qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_PAGE);
1863 qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
1864 }
1865
1866 found = 1;
1867 break;
1868 }
1869 addr += TARGET_PAGE_SIZE;
1870 current_addr = (saved_addr + addr) % last_ram_offset;
1871 }
1872
1873 return found;
1874}
1875
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07001876static uint64_t bytes_transferred;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001877
1878static ram_addr_t ram_save_remaining(void)
1879{
1880 ram_addr_t addr;
1881 ram_addr_t count = 0;
1882
1883 for (addr = 0; addr < last_ram_offset; addr += TARGET_PAGE_SIZE) {
1884 if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
1885 count++;
1886 }
1887
1888 return count;
1889}
1890
1891uint64_t ram_bytes_remaining(void)
1892{
1893 return ram_save_remaining() * TARGET_PAGE_SIZE;
1894}
1895
1896uint64_t ram_bytes_transferred(void)
1897{
1898 return bytes_transferred;
1899}
1900
1901uint64_t ram_bytes_total(void)
1902{
1903 return last_ram_offset;
1904}
1905
1906static int ram_save_live(QEMUFile *f, int stage, void *opaque)
1907{
1908 ram_addr_t addr;
1909 uint64_t bytes_transferred_last;
1910 double bwidth = 0;
1911 uint64_t expected_time = 0;
1912
1913 if (cpu_physical_sync_dirty_bitmap(0, TARGET_PHYS_ADDR_MAX) != 0) {
1914 qemu_file_set_error(f);
1915 return 0;
1916 }
1917
1918 if (stage == 1) {
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07001919 bytes_transferred = 0;
1920
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001921 /* Make sure all dirty bits are set */
1922 for (addr = 0; addr < last_ram_offset; addr += TARGET_PAGE_SIZE) {
1923 if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
1924 cpu_physical_memory_set_dirty(addr);
1925 }
1926
1927 /* Enable dirty memory tracking */
1928 cpu_physical_memory_set_dirty_tracking(1);
1929
1930 qemu_put_be64(f, last_ram_offset | RAM_SAVE_FLAG_MEM_SIZE);
1931 }
1932
1933 bytes_transferred_last = bytes_transferred;
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07001934 bwidth = qemu_get_clock_ns(rt_clock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001935
1936 while (!qemu_file_rate_limit(f)) {
1937 int ret;
1938
1939 ret = ram_save_block(f);
1940 bytes_transferred += ret * TARGET_PAGE_SIZE;
1941 if (ret == 0) /* no more blocks */
1942 break;
1943 }
1944
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07001945 bwidth = qemu_get_clock_ns(rt_clock) - bwidth;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001946 bwidth = (bytes_transferred - bytes_transferred_last) / bwidth;
1947
1948 /* if we haven't transferred anything this round, force expected_time to a
1949 * a very high value, but without crashing */
1950 if (bwidth == 0)
1951 bwidth = 0.000001;
1952
1953 /* try transferring iterative blocks of memory */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001954 if (stage == 3) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001955 /* flush all remaining blocks regardless of rate limiting */
1956 while (ram_save_block(f) != 0) {
1957 bytes_transferred += TARGET_PAGE_SIZE;
1958 }
1959 cpu_physical_memory_set_dirty_tracking(0);
1960 }
1961
1962 qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
1963
1964 expected_time = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth;
1965
1966 return (stage == 2) && (expected_time <= migrate_max_downtime());
1967}
1968
1969static int ram_load_dead(QEMUFile *f, void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001970{
1971 RamDecompressState s1, *s = &s1;
1972 uint8_t buf[10];
1973 ram_addr_t i;
1974
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001975 if (ram_decompress_open(s, f) < 0)
1976 return -EINVAL;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001977 for(i = 0; i < last_ram_offset; i+= BDRV_HASH_BLOCK_SIZE) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001978 if (ram_decompress_buf(s, buf, 1) < 0) {
1979 fprintf(stderr, "Error while reading ram block header\n");
1980 goto error;
1981 }
1982 if (buf[0] == 0) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001983 if (ram_decompress_buf(s, qemu_get_ram_ptr(i),
1984 BDRV_HASH_BLOCK_SIZE) < 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001985 fprintf(stderr, "Error while reading ram block address=0x%08" PRIx64, (uint64_t)i);
1986 goto error;
1987 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001988 } else {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001989 error:
1990 printf("Error block header\n");
1991 return -EINVAL;
1992 }
1993 }
1994 ram_decompress_close(s);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001995
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001996 return 0;
1997}
1998
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001999static int ram_load(QEMUFile *f, void *opaque, int version_id)
2000{
2001 ram_addr_t addr;
2002 int flags;
2003
2004 if (version_id == 1)
2005 return ram_load_v1(f, opaque);
2006
2007 if (version_id == 2) {
2008 if (qemu_get_be32(f) != last_ram_offset)
2009 return -EINVAL;
2010 return ram_load_dead(f, opaque);
2011 }
2012
2013 if (version_id != 3)
2014 return -EINVAL;
2015
2016 do {
2017 addr = qemu_get_be64(f);
2018
2019 flags = addr & ~TARGET_PAGE_MASK;
2020 addr &= TARGET_PAGE_MASK;
2021
2022 if (flags & RAM_SAVE_FLAG_MEM_SIZE) {
2023 if (addr != last_ram_offset)
2024 return -EINVAL;
2025 }
2026
2027 if (flags & RAM_SAVE_FLAG_FULL) {
2028 if (ram_load_dead(f, opaque) < 0)
2029 return -EINVAL;
2030 }
2031
2032 if (flags & RAM_SAVE_FLAG_COMPRESS) {
2033 uint8_t ch = qemu_get_byte(f);
2034 memset(qemu_get_ram_ptr(addr), ch, TARGET_PAGE_SIZE);
2035 } else if (flags & RAM_SAVE_FLAG_PAGE)
2036 qemu_get_buffer(f, qemu_get_ram_ptr(addr), TARGET_PAGE_SIZE);
2037 } while (!(flags & RAM_SAVE_FLAG_EOS));
2038
2039 return 0;
2040}
2041
2042void qemu_service_io(void)
2043{
2044 qemu_notify_event();
2045}
2046
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002047/***********************************************************/
2048/* bottom halves (can be seen as timers which expire ASAP) */
2049
2050struct QEMUBH {
2051 QEMUBHFunc *cb;
2052 void *opaque;
2053 int scheduled;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002054 int idle;
2055 int deleted;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002056 QEMUBH *next;
2057};
2058
2059static QEMUBH *first_bh = NULL;
2060
2061QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
2062{
2063 QEMUBH *bh;
2064 bh = qemu_mallocz(sizeof(QEMUBH));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002065 bh->cb = cb;
2066 bh->opaque = opaque;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002067 bh->next = first_bh;
2068 first_bh = bh;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002069 return bh;
2070}
2071
2072int qemu_bh_poll(void)
2073{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002074 QEMUBH *bh, **bhp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002075 int ret;
2076
2077 ret = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002078 for (bh = first_bh; bh; bh = bh->next) {
2079 if (!bh->deleted && bh->scheduled) {
2080 bh->scheduled = 0;
2081 if (!bh->idle)
2082 ret = 1;
2083 bh->idle = 0;
2084 bh->cb(bh->opaque);
2085 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002086 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002087
2088 /* remove deleted bhs */
2089 bhp = &first_bh;
2090 while (*bhp) {
2091 bh = *bhp;
2092 if (bh->deleted) {
2093 *bhp = bh->next;
2094 qemu_free(bh);
2095 } else
2096 bhp = &bh->next;
2097 }
2098
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002099 return ret;
2100}
2101
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002102void qemu_bh_schedule_idle(QEMUBH *bh)
2103{
2104 if (bh->scheduled)
2105 return;
2106 bh->scheduled = 1;
2107 bh->idle = 1;
2108}
2109
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002110void qemu_bh_schedule(QEMUBH *bh)
2111{
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002112 if (bh->scheduled)
2113 return;
2114 bh->scheduled = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002115 bh->idle = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002116 /* stop the currently executing CPU to execute the BH ASAP */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002117 qemu_notify_event();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002118}
2119
2120void qemu_bh_cancel(QEMUBH *bh)
2121{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002122 bh->scheduled = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002123}
2124
2125void qemu_bh_delete(QEMUBH *bh)
2126{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002127 bh->scheduled = 0;
2128 bh->deleted = 1;
2129}
2130
David Turnerd0659942010-09-10 10:42:32 +02002131void qemu_bh_update_timeout(int *timeout)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002132{
2133 QEMUBH *bh;
2134
2135 for (bh = first_bh; bh; bh = bh->next) {
2136 if (!bh->deleted && bh->scheduled) {
2137 if (bh->idle) {
2138 /* idle bottom halves will be polled at least
2139 * every 10ms */
2140 *timeout = MIN(10, *timeout);
2141 } else {
2142 /* non-idle bottom halves will be executed
2143 * immediately */
2144 *timeout = 0;
2145 break;
2146 }
2147 }
2148 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002149}
2150
2151/***********************************************************/
2152/* machine registration */
2153
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002154static QEMUMachine *first_machine = NULL;
2155QEMUMachine *current_machine = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002156
2157int qemu_register_machine(QEMUMachine *m)
2158{
2159 QEMUMachine **pm;
2160 pm = &first_machine;
2161 while (*pm != NULL)
2162 pm = &(*pm)->next;
2163 m->next = NULL;
2164 *pm = m;
2165 return 0;
2166}
2167
2168static QEMUMachine *find_machine(const char *name)
2169{
2170 QEMUMachine *m;
2171
2172 for(m = first_machine; m != NULL; m = m->next) {
2173 if (!strcmp(m->name, name))
2174 return m;
2175 }
2176 return NULL;
2177}
2178
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002179static QEMUMachine *find_default_machine(void)
2180{
2181 QEMUMachine *m;
2182
2183 for(m = first_machine; m != NULL; m = m->next) {
2184 if (m->is_default) {
2185 return m;
2186 }
2187 }
2188 return NULL;
2189}
2190
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002191/***********************************************************/
2192/* main execution loop */
2193
2194static void gui_update(void *opaque)
2195{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002196 uint64_t interval = GUI_REFRESH_INTERVAL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002197 DisplayState *ds = opaque;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002198 DisplayChangeListener *dcl = ds->listeners;
2199
2200 dpy_refresh(ds);
2201
2202 while (dcl != NULL) {
2203 if (dcl->gui_timer_interval &&
2204 dcl->gui_timer_interval < interval)
2205 interval = dcl->gui_timer_interval;
2206 dcl = dcl->next;
2207 }
2208 qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock(rt_clock));
2209}
2210
2211static void nographic_update(void *opaque)
2212{
2213 uint64_t interval = GUI_REFRESH_INTERVAL;
2214
2215 qemu_mod_timer(nographic_timer, interval + qemu_get_clock(rt_clock));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002216}
2217
2218struct vm_change_state_entry {
2219 VMChangeStateHandler *cb;
2220 void *opaque;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002221 QLIST_ENTRY (vm_change_state_entry) entries;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002222};
2223
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002224static QLIST_HEAD(vm_change_state_head, vm_change_state_entry) vm_change_state_head;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002225
2226VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb,
2227 void *opaque)
2228{
2229 VMChangeStateEntry *e;
2230
2231 e = qemu_mallocz(sizeof (*e));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002232
2233 e->cb = cb;
2234 e->opaque = opaque;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002235 QLIST_INSERT_HEAD(&vm_change_state_head, e, entries);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002236 return e;
2237}
2238
2239void qemu_del_vm_change_state_handler(VMChangeStateEntry *e)
2240{
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002241 QLIST_REMOVE (e, entries);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002242 qemu_free (e);
2243}
2244
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002245static void vm_state_notify(int running, int reason)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002246{
2247 VMChangeStateEntry *e;
2248
2249 for (e = vm_change_state_head.lh_first; e; e = e->entries.le_next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002250 e->cb(e->opaque, running, reason);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002251 }
2252}
2253
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002254static void resume_all_vcpus(void);
2255static void pause_all_vcpus(void);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002256
2257void vm_start(void)
2258{
2259 if (!vm_running) {
2260 cpu_enable_ticks();
2261 vm_running = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002262 vm_state_notify(1, 0);
David Turner6a9ef172010-09-09 22:54:36 +02002263 //qemu_rearm_alarm_timer(alarm_timer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002264 resume_all_vcpus();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002265 }
2266}
2267
2268/* reset/shutdown handler */
2269
2270typedef struct QEMUResetEntry {
David Turner025c32f2010-09-10 14:52:42 +02002271 QTAILQ_ENTRY(QEMUResetEntry) entry;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002272 QEMUResetHandler *func;
2273 void *opaque;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002274} QEMUResetEntry;
2275
David Turner025c32f2010-09-10 14:52:42 +02002276static QTAILQ_HEAD(reset_handlers, QEMUResetEntry) reset_handlers =
2277 QTAILQ_HEAD_INITIALIZER(reset_handlers);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002278static int reset_requested;
2279static int shutdown_requested;
2280static int powerdown_requested;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002281static int debug_requested;
2282static int vmstop_requested;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002283
2284int qemu_shutdown_requested(void)
2285{
2286 int r = shutdown_requested;
2287 shutdown_requested = 0;
2288 return r;
2289}
2290
2291int qemu_reset_requested(void)
2292{
2293 int r = reset_requested;
2294 reset_requested = 0;
2295 return r;
2296}
2297
2298int qemu_powerdown_requested(void)
2299{
2300 int r = powerdown_requested;
2301 powerdown_requested = 0;
2302 return r;
2303}
2304
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002305static int qemu_debug_requested(void)
2306{
2307 int r = debug_requested;
2308 debug_requested = 0;
2309 return r;
2310}
2311
2312static int qemu_vmstop_requested(void)
2313{
2314 int r = vmstop_requested;
2315 vmstop_requested = 0;
2316 return r;
2317}
2318
David Turner025c32f2010-09-10 14:52:42 +02002319void qemu_register_reset(QEMUResetHandler *func, void *opaque)
2320{
2321 QEMUResetEntry *re = qemu_mallocz(sizeof(QEMUResetEntry));
2322
2323 re->func = func;
2324 re->opaque = opaque;
2325 QTAILQ_INSERT_TAIL(&reset_handlers, re, entry);
2326}
2327
2328void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
2329{
2330 QEMUResetEntry *re;
2331
2332 QTAILQ_FOREACH(re, &reset_handlers, entry) {
2333 if (re->func == func && re->opaque == opaque) {
2334 QTAILQ_REMOVE(&reset_handlers, re, entry);
2335 qemu_free(re);
2336 return;
2337 }
2338 }
2339}
2340
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002341static void do_vm_stop(int reason)
2342{
2343 if (vm_running) {
2344 cpu_disable_ticks();
2345 vm_running = 0;
2346 pause_all_vcpus();
2347 vm_state_notify(0, reason);
2348 }
2349}
2350
2351void qemu_register_reset(QEMUResetHandler *func, int order, void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002352{
2353 QEMUResetEntry **pre, *re;
2354
2355 pre = &first_reset_entry;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002356 while (*pre != NULL && (*pre)->order >= order) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002357 pre = &(*pre)->next;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002358 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002359 re = qemu_mallocz(sizeof(QEMUResetEntry));
2360 re->func = func;
2361 re->opaque = opaque;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002362 re->order = order;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002363 re->next = NULL;
2364 *pre = re;
2365}
2366
2367void qemu_system_reset(void)
2368{
2369 QEMUResetEntry *re;
2370
2371 /* reset all devices */
David Turner025c32f2010-09-10 14:52:42 +02002372 QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002373 re->func(re->opaque);
2374 }
2375}
2376
2377void qemu_system_reset_request(void)
2378{
2379 if (no_reboot) {
2380 shutdown_requested = 1;
2381 } else {
2382 reset_requested = 1;
2383 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002384 qemu_notify_event();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002385}
2386
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002387void qemu_system_shutdown_request(void)
2388{
2389 shutdown_requested = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002390 qemu_notify_event();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002391}
2392
2393void qemu_system_powerdown_request(void)
2394{
2395 powerdown_requested = 1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002396 qemu_notify_event();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002397}
2398
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002399#ifdef CONFIG_IOTHREAD
2400static void qemu_system_vmstop_request(int reason)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002401{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002402 vmstop_requested = reason;
2403 qemu_notify_event();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002404}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002405#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002406
2407#ifndef _WIN32
2408static int io_thread_fd = -1;
2409
2410static void qemu_event_increment(void)
2411{
2412 static const char byte = 0;
2413
2414 if (io_thread_fd == -1)
2415 return;
2416
2417 write(io_thread_fd, &byte, sizeof(byte));
2418}
2419
2420static void qemu_event_read(void *opaque)
2421{
2422 int fd = (unsigned long)opaque;
2423 ssize_t len;
2424
2425 /* Drain the notify pipe */
2426 do {
2427 char buffer[512];
2428 len = read(fd, buffer, sizeof(buffer));
2429 } while ((len == -1 && errno == EINTR) || len > 0);
2430}
2431
2432static int qemu_event_init(void)
2433{
2434 int err;
2435 int fds[2];
2436
2437 err = pipe(fds);
2438 if (err == -1)
2439 return -errno;
2440
2441 err = fcntl_setfl(fds[0], O_NONBLOCK);
2442 if (err < 0)
2443 goto fail;
2444
2445 err = fcntl_setfl(fds[1], O_NONBLOCK);
2446 if (err < 0)
2447 goto fail;
2448
2449 qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL,
2450 (void *)(unsigned long)fds[0]);
2451
2452 io_thread_fd = fds[1];
2453 return 0;
2454
2455fail:
2456 close(fds[0]);
2457 close(fds[1]);
2458 return err;
2459}
2460#else
2461HANDLE qemu_event_handle;
2462
2463static void dummy_event_handler(void *opaque)
2464{
2465}
2466
2467static int qemu_event_init(void)
2468{
2469 qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
2470 if (!qemu_event_handle) {
2471 perror("Failed CreateEvent");
2472 return -1;
2473 }
2474 qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL);
2475 return 0;
2476}
2477
2478static void qemu_event_increment(void)
2479{
2480 SetEvent(qemu_event_handle);
2481}
2482#endif
2483
2484static int cpu_can_run(CPUState *env)
2485{
2486 if (env->stop)
2487 return 0;
2488 if (env->stopped)
2489 return 0;
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07002490 if (!vm_running)
2491 return 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002492 return 1;
2493}
2494
2495#ifndef CONFIG_IOTHREAD
2496static int qemu_init_main_loop(void)
2497{
2498 return qemu_event_init();
2499}
2500
2501void qemu_init_vcpu(void *_env)
2502{
2503 CPUState *env = _env;
2504
2505 if (kvm_enabled())
2506 kvm_init_vcpu(env);
2507 return;
2508}
2509
2510int qemu_cpu_self(void *env)
2511{
2512 return 1;
2513}
2514
2515static void resume_all_vcpus(void)
2516{
2517}
2518
2519static void pause_all_vcpus(void)
2520{
2521}
2522
2523void qemu_cpu_kick(void *env)
2524{
2525 return;
2526}
2527
2528void qemu_notify_event(void)
2529{
2530 CPUState *env = cpu_single_env;
2531
2532 if (env) {
2533 cpu_exit(env);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002534 }
2535}
2536
2537#define qemu_mutex_lock_iothread() do { } while (0)
2538#define qemu_mutex_unlock_iothread() do { } while (0)
2539
2540void vm_stop(int reason)
2541{
2542 do_vm_stop(reason);
2543}
2544
2545#else /* CONFIG_IOTHREAD */
2546
2547#include "qemu-thread.h"
2548
2549QemuMutex qemu_global_mutex;
2550static QemuMutex qemu_fair_mutex;
2551
2552static QemuThread io_thread;
2553
2554static QemuThread *tcg_cpu_thread;
2555static QemuCond *tcg_halt_cond;
2556
2557static int qemu_system_ready;
2558/* cpu creation */
2559static QemuCond qemu_cpu_cond;
2560/* system init */
2561static QemuCond qemu_system_cond;
2562static QemuCond qemu_pause_cond;
2563
2564static void block_io_signals(void);
2565static void unblock_io_signals(void);
2566static int tcg_has_work(void);
2567
2568static int qemu_init_main_loop(void)
2569{
2570 int ret;
2571
2572 ret = qemu_event_init();
2573 if (ret)
2574 return ret;
2575
2576 qemu_cond_init(&qemu_pause_cond);
2577 qemu_mutex_init(&qemu_fair_mutex);
2578 qemu_mutex_init(&qemu_global_mutex);
2579 qemu_mutex_lock(&qemu_global_mutex);
2580
2581 unblock_io_signals();
2582 qemu_thread_self(&io_thread);
2583
2584 return 0;
2585}
2586
2587static void qemu_wait_io_event(CPUState *env)
2588{
2589 while (!tcg_has_work())
2590 qemu_cond_timedwait(env->halt_cond, &qemu_global_mutex, 1000);
2591
2592 qemu_mutex_unlock(&qemu_global_mutex);
2593
2594 /*
2595 * Users of qemu_global_mutex can be starved, having no chance
2596 * to acquire it since this path will get to it first.
2597 * So use another lock to provide fairness.
2598 */
2599 qemu_mutex_lock(&qemu_fair_mutex);
2600 qemu_mutex_unlock(&qemu_fair_mutex);
2601
2602 qemu_mutex_lock(&qemu_global_mutex);
2603 if (env->stop) {
2604 env->stop = 0;
2605 env->stopped = 1;
2606 qemu_cond_signal(&qemu_pause_cond);
2607 }
2608}
2609
2610static int qemu_cpu_exec(CPUState *env);
2611
2612static void *kvm_cpu_thread_fn(void *arg)
2613{
2614 CPUState *env = arg;
2615
2616 block_io_signals();
2617 qemu_thread_self(env->thread);
2618
2619 /* signal CPU creation */
2620 qemu_mutex_lock(&qemu_global_mutex);
2621 env->created = 1;
2622 qemu_cond_signal(&qemu_cpu_cond);
2623
2624 /* and wait for machine initialization */
2625 while (!qemu_system_ready)
2626 qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100);
2627
2628 while (1) {
2629 if (cpu_can_run(env))
2630 qemu_cpu_exec(env);
2631 qemu_wait_io_event(env);
2632 }
2633
2634 return NULL;
2635}
2636
2637static void tcg_cpu_exec(void);
2638
2639static void *tcg_cpu_thread_fn(void *arg)
2640{
2641 CPUState *env = arg;
2642
2643 block_io_signals();
2644 qemu_thread_self(env->thread);
2645
2646 /* signal CPU creation */
2647 qemu_mutex_lock(&qemu_global_mutex);
2648 for (env = first_cpu; env != NULL; env = env->next_cpu)
2649 env->created = 1;
2650 qemu_cond_signal(&qemu_cpu_cond);
2651
2652 /* and wait for machine initialization */
2653 while (!qemu_system_ready)
2654 qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100);
2655
2656 while (1) {
2657 tcg_cpu_exec();
2658 qemu_wait_io_event(cur_cpu);
2659 }
2660
2661 return NULL;
2662}
2663
2664void qemu_cpu_kick(void *_env)
2665{
2666 CPUState *env = _env;
2667 qemu_cond_broadcast(env->halt_cond);
2668 if (kvm_enabled())
2669 qemu_thread_signal(env->thread, SIGUSR1);
2670}
2671
2672int qemu_cpu_self(void *env)
2673{
2674 return (cpu_single_env != NULL);
2675}
2676
2677static void cpu_signal(int sig)
2678{
2679 if (cpu_single_env)
2680 cpu_exit(cpu_single_env);
2681}
2682
2683static void block_io_signals(void)
2684{
2685 sigset_t set;
2686 struct sigaction sigact;
2687
2688 sigemptyset(&set);
2689 sigaddset(&set, SIGUSR2);
2690 sigaddset(&set, SIGIO);
2691 sigaddset(&set, SIGALRM);
2692 pthread_sigmask(SIG_BLOCK, &set, NULL);
2693
2694 sigemptyset(&set);
2695 sigaddset(&set, SIGUSR1);
2696 pthread_sigmask(SIG_UNBLOCK, &set, NULL);
2697
2698 memset(&sigact, 0, sizeof(sigact));
2699 sigact.sa_handler = cpu_signal;
2700 sigaction(SIGUSR1, &sigact, NULL);
2701}
2702
2703static void unblock_io_signals(void)
2704{
2705 sigset_t set;
2706
2707 sigemptyset(&set);
2708 sigaddset(&set, SIGUSR2);
2709 sigaddset(&set, SIGIO);
2710 sigaddset(&set, SIGALRM);
2711 pthread_sigmask(SIG_UNBLOCK, &set, NULL);
2712
2713 sigemptyset(&set);
2714 sigaddset(&set, SIGUSR1);
2715 pthread_sigmask(SIG_BLOCK, &set, NULL);
2716}
2717
2718static void qemu_signal_lock(unsigned int msecs)
2719{
2720 qemu_mutex_lock(&qemu_fair_mutex);
2721
2722 while (qemu_mutex_trylock(&qemu_global_mutex)) {
2723 qemu_thread_signal(tcg_cpu_thread, SIGUSR1);
2724 if (!qemu_mutex_timedlock(&qemu_global_mutex, msecs))
2725 break;
2726 }
2727 qemu_mutex_unlock(&qemu_fair_mutex);
2728}
2729
2730static void qemu_mutex_lock_iothread(void)
2731{
2732 if (kvm_enabled()) {
2733 qemu_mutex_lock(&qemu_fair_mutex);
2734 qemu_mutex_lock(&qemu_global_mutex);
2735 qemu_mutex_unlock(&qemu_fair_mutex);
2736 } else
2737 qemu_signal_lock(100);
2738}
2739
2740static void qemu_mutex_unlock_iothread(void)
2741{
2742 qemu_mutex_unlock(&qemu_global_mutex);
2743}
2744
2745static int all_vcpus_paused(void)
2746{
2747 CPUState *penv = first_cpu;
2748
2749 while (penv) {
2750 if (!penv->stopped)
2751 return 0;
2752 penv = (CPUState *)penv->next_cpu;
2753 }
2754
2755 return 1;
2756}
2757
2758static void pause_all_vcpus(void)
2759{
2760 CPUState *penv = first_cpu;
2761
2762 while (penv) {
2763 penv->stop = 1;
2764 qemu_thread_signal(penv->thread, SIGUSR1);
2765 qemu_cpu_kick(penv);
2766 penv = (CPUState *)penv->next_cpu;
2767 }
2768
2769 while (!all_vcpus_paused()) {
2770 qemu_cond_timedwait(&qemu_pause_cond, &qemu_global_mutex, 100);
2771 penv = first_cpu;
2772 while (penv) {
2773 qemu_thread_signal(penv->thread, SIGUSR1);
2774 penv = (CPUState *)penv->next_cpu;
2775 }
2776 }
2777}
2778
2779static void resume_all_vcpus(void)
2780{
2781 CPUState *penv = first_cpu;
2782
2783 while (penv) {
2784 penv->stop = 0;
2785 penv->stopped = 0;
2786 qemu_thread_signal(penv->thread, SIGUSR1);
2787 qemu_cpu_kick(penv);
2788 penv = (CPUState *)penv->next_cpu;
2789 }
2790}
2791
2792static void tcg_init_vcpu(void *_env)
2793{
2794 CPUState *env = _env;
2795 /* share a single thread for all cpus with TCG */
2796 if (!tcg_cpu_thread) {
2797 env->thread = qemu_mallocz(sizeof(QemuThread));
2798 env->halt_cond = qemu_mallocz(sizeof(QemuCond));
2799 qemu_cond_init(env->halt_cond);
2800 qemu_thread_create(env->thread, tcg_cpu_thread_fn, env);
2801 while (env->created == 0)
2802 qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100);
2803 tcg_cpu_thread = env->thread;
2804 tcg_halt_cond = env->halt_cond;
2805 } else {
2806 env->thread = tcg_cpu_thread;
2807 env->halt_cond = tcg_halt_cond;
2808 }
2809}
2810
2811static void kvm_start_vcpu(CPUState *env)
2812{
2813 kvm_init_vcpu(env);
2814 env->thread = qemu_mallocz(sizeof(QemuThread));
2815 env->halt_cond = qemu_mallocz(sizeof(QemuCond));
2816 qemu_cond_init(env->halt_cond);
2817 qemu_thread_create(env->thread, kvm_cpu_thread_fn, env);
2818 while (env->created == 0)
2819 qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100);
2820}
2821
2822void qemu_init_vcpu(void *_env)
2823{
2824 CPUState *env = _env;
2825
2826 if (kvm_enabled())
2827 kvm_start_vcpu(env);
2828 else
2829 tcg_init_vcpu(env);
2830}
2831
2832void qemu_notify_event(void)
2833{
2834 qemu_event_increment();
2835}
2836
2837void vm_stop(int reason)
2838{
2839 QemuThread me;
2840 qemu_thread_self(&me);
2841
2842 if (!qemu_thread_equal(&me, &io_thread)) {
2843 qemu_system_vmstop_request(reason);
2844 /*
2845 * FIXME: should not return to device code in case
2846 * vm_stop() has been requested.
2847 */
2848 if (cpu_single_env) {
2849 cpu_exit(cpu_single_env);
2850 cpu_single_env->stop = 1;
2851 }
2852 return;
2853 }
2854 do_vm_stop(reason);
2855}
2856
2857#endif
2858
2859
2860#ifdef _WIN32
2861static void host_main_loop_wait(int *timeout)
2862{
2863 int ret, ret2, i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002864 PollingEntry *pe;
2865
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002866
2867 /* XXX: need to suppress polling by better using win32 events */
2868 ret = 0;
2869 for(pe = first_polling_entry; pe != NULL; pe = pe->next) {
2870 ret |= pe->func(pe->opaque);
2871 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002872 if (ret == 0) {
2873 int err;
2874 WaitObjects *w = &wait_objects;
2875
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002876 ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002877 if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
2878 if (w->func[ret - WAIT_OBJECT_0])
2879 w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
2880
2881 /* Check for additional signaled events */
2882 for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
2883
2884 /* Check if event is signaled */
2885 ret2 = WaitForSingleObject(w->events[i], 0);
2886 if(ret2 == WAIT_OBJECT_0) {
2887 if (w->func[i])
2888 w->func[i](w->opaque[i]);
2889 } else if (ret2 == WAIT_TIMEOUT) {
2890 } else {
2891 err = GetLastError();
2892 fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
2893 }
2894 }
2895 } else if (ret == WAIT_TIMEOUT) {
2896 } else {
2897 err = GetLastError();
2898 fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
2899 }
2900 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002901
2902 *timeout = 0;
2903}
2904#else
2905static void host_main_loop_wait(int *timeout)
2906{
2907}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002908#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002909
2910void main_loop_wait(int timeout)
2911{
2912 IOHandlerRecord *ioh;
2913 fd_set rfds, wfds, xfds;
2914 int ret, nfds;
2915 struct timeval tv;
2916
2917 qemu_bh_update_timeout(&timeout);
2918
2919 host_main_loop_wait(&timeout);
2920
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002921 /* poll any events */
2922 /* XXX: separate device handlers from system ones */
2923 nfds = -1;
2924 FD_ZERO(&rfds);
2925 FD_ZERO(&wfds);
2926 FD_ZERO(&xfds);
David Turner025c32f2010-09-10 14:52:42 +02002927 QLIST_FOREACH(ioh, &io_handlers, next) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002928 if (ioh->deleted)
2929 continue;
2930 if (ioh->fd_read &&
2931 (!ioh->fd_read_poll ||
2932 ioh->fd_read_poll(ioh->opaque) != 0)) {
2933 FD_SET(ioh->fd, &rfds);
2934 if (ioh->fd > nfds)
2935 nfds = ioh->fd;
2936 }
2937 if (ioh->fd_write) {
2938 FD_SET(ioh->fd, &wfds);
2939 if (ioh->fd > nfds)
2940 nfds = ioh->fd;
2941 }
2942 }
2943
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002944 tv.tv_sec = timeout / 1000;
2945 tv.tv_usec = (timeout % 1000) * 1000;
2946
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002947#if defined(CONFIG_SLIRP)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002948 if (slirp_is_inited()) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002949 slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
2950 }
2951#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002952 qemu_mutex_unlock_iothread();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002953 ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002954 qemu_mutex_lock_iothread();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002955 if (ret > 0) {
David Turner025c32f2010-09-10 14:52:42 +02002956 IOHandlerRecord *pioh;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002957
David Turner025c32f2010-09-10 14:52:42 +02002958 QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
2959 if (ioh->deleted) {
2960 QLIST_REMOVE(ioh, next);
2961 qemu_free(ioh);
2962 continue;
2963 }
2964 if (ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002965 ioh->fd_read(ioh->opaque);
2966 }
David Turner025c32f2010-09-10 14:52:42 +02002967 if (ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002968 ioh->fd_write(ioh->opaque);
2969 }
2970 }
2971
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002972#if defined(CONFIG_SLIRP)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002973 if (slirp_is_inited()) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002974 if (ret < 0) {
2975 FD_ZERO(&rfds);
2976 FD_ZERO(&wfds);
2977 FD_ZERO(&xfds);
2978 }
2979 slirp_select_poll(&rfds, &wfds, &xfds);
2980 }
2981#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002982
David Turner6a9ef172010-09-09 22:54:36 +02002983 qemu_run_all_timers();
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07002984
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002985 /* Check bottom-halves last in case any of the earlier events triggered
2986 them. */
2987 qemu_bh_poll();
2988
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002989}
2990
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002991static int qemu_cpu_exec(CPUState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002992{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002993 int ret;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002994#ifdef CONFIG_PROFILER
2995 int64_t ti;
2996#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002997
2998#ifdef CONFIG_PROFILER
2999 ti = profile_getclock();
3000#endif
3001 if (use_icount) {
3002 int64_t count;
3003 int decr;
3004 qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
3005 env->icount_decr.u16.low = 0;
3006 env->icount_extra = 0;
3007 count = qemu_next_deadline();
3008 count = (count + (1 << icount_time_shift) - 1)
3009 >> icount_time_shift;
3010 qemu_icount += count;
3011 decr = (count > 0xffff) ? 0xffff : count;
3012 count -= decr;
3013 env->icount_decr.u16.low = decr;
3014 env->icount_extra = count;
3015 }
3016 ret = cpu_exec(env);
3017#ifdef CONFIG_PROFILER
3018 qemu_time += profile_getclock() - ti;
3019#endif
3020 if (use_icount) {
3021 /* Fold pending instructions back into the
3022 instruction counter, and clear the interrupt flag. */
3023 qemu_icount -= (env->icount_decr.u16.low
3024 + env->icount_extra);
3025 env->icount_decr.u32 = 0;
3026 env->icount_extra = 0;
3027 }
3028 return ret;
3029}
3030
3031static void tcg_cpu_exec(void)
3032{
3033 int ret = 0;
3034
3035 if (next_cpu == NULL)
3036 next_cpu = first_cpu;
3037 for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) {
3038 CPUState *env = cur_cpu = next_cpu;
3039
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003040 if (timer_alarm_pending) {
3041 timer_alarm_pending = 0;
3042 break;
3043 }
3044 if (cpu_can_run(env))
3045 ret = qemu_cpu_exec(env);
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07003046 else if (env->stop)
3047 break;
3048
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003049 if (ret == EXCP_DEBUG) {
3050 gdb_set_stop_cpu(env);
3051 debug_requested = 1;
3052 break;
3053 }
3054 }
3055}
3056
3057static int cpu_has_work(CPUState *env)
3058{
3059 if (env->stop)
3060 return 1;
3061 if (env->stopped)
3062 return 0;
3063 if (!env->halted)
3064 return 1;
3065 if (qemu_cpu_has_work(env))
3066 return 1;
3067 return 0;
3068}
3069
3070static int tcg_has_work(void)
3071{
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003072 CPUState *env;
3073
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003074 for (env = first_cpu; env != NULL; env = env->next_cpu)
3075 if (cpu_has_work(env))
3076 return 1;
3077 return 0;
3078}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003079
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003080
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003081static int vm_can_run(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003082{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003083 if (powerdown_requested)
3084 return 0;
3085 if (reset_requested)
3086 return 0;
3087 if (shutdown_requested)
3088 return 0;
3089 if (debug_requested)
3090 return 0;
3091 return 1;
3092}
3093
3094static void main_loop(void)
3095{
3096 int r;
3097
3098#ifdef CONFIG_IOTHREAD
3099 qemu_system_ready = 1;
3100 qemu_cond_broadcast(&qemu_system_cond);
3101#endif
3102
3103 for (;;) {
3104 do {
3105#ifdef CONFIG_PROFILER
3106 int64_t ti;
3107#endif
3108#ifndef CONFIG_IOTHREAD
3109 tcg_cpu_exec();
3110#endif
3111#ifdef CONFIG_PROFILER
3112 ti = profile_getclock();
3113#endif
3114 main_loop_wait(qemu_calculate_timeout());
3115#ifdef CONFIG_PROFILER
3116 dev_time += profile_getclock() - ti;
3117#endif
3118 } while (vm_can_run());
3119
3120 if (qemu_debug_requested())
3121 vm_stop(EXCP_DEBUG);
3122 if (qemu_shutdown_requested()) {
3123 if (no_shutdown) {
3124 vm_stop(0);
3125 no_shutdown = 0;
3126 } else
3127 break;
3128 }
3129 if (qemu_reset_requested()) {
3130 pause_all_vcpus();
3131 qemu_system_reset();
3132 resume_all_vcpus();
3133 }
3134 if (qemu_powerdown_requested())
3135 qemu_system_powerdown();
3136 if ((r = qemu_vmstop_requested()))
3137 vm_stop(r);
3138 }
3139 pause_all_vcpus();
3140}
3141
3142static void version(void)
3143{
3144 printf("QEMU PC emulator version " QEMU_VERSION QEMU_PKGVERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n");
3145}
3146
3147static void help(int exitcode)
3148{
3149 version();
3150 printf("usage: %s [options] [disk_image]\n"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003151 "\n"
3152 "'disk_image' is a raw hard image image for IDE hard disk 0\n"
3153 "\n"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003154#define DEF(option, opt_arg, opt_enum, opt_help) \
3155 opt_help
3156#define DEFHEADING(text) stringify(text) "\n"
3157#include "qemu-options.h"
3158#undef DEF
3159#undef DEFHEADING
3160#undef GEN_DOCS
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003161 "\n"
3162 "During emulation, the following keys are useful:\n"
3163 "ctrl-alt-f toggle full screen\n"
3164 "ctrl-alt-n switch to virtual console 'n'\n"
3165 "ctrl-alt toggle mouse and keyboard grab\n"
3166 "\n"
3167 "When using -nographic, press 'ctrl-a h' to get some help.\n"
3168 ,
3169 "qemu",
3170 DEFAULT_RAM_SIZE,
3171#ifndef _WIN32
3172 DEFAULT_NETWORK_SCRIPT,
3173 DEFAULT_NETWORK_DOWN_SCRIPT,
3174#endif
3175 DEFAULT_GDBSTUB_PORT,
3176 "/tmp/qemu.log");
3177 exit(exitcode);
3178}
3179
3180#define HAS_ARG 0x0001
3181
3182enum {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003183#define DEF(option, opt_arg, opt_enum, opt_help) \
3184 opt_enum,
3185#define DEFHEADING(text)
3186#include "qemu-options.h"
3187#undef DEF
3188#undef DEFHEADING
3189#undef GEN_DOCS
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003190};
3191
3192typedef struct QEMUOption {
3193 const char *name;
3194 int flags;
3195 int index;
3196} QEMUOption;
3197
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003198static const QEMUOption qemu_options[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003199 { "h", 0, QEMU_OPTION_h },
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003200#define DEF(option, opt_arg, opt_enum, opt_help) \
3201 { option, opt_arg, opt_enum },
3202#define DEFHEADING(text)
3203#include "qemu-options.h"
3204#undef DEF
3205#undef DEFHEADING
3206#undef GEN_DOCS
3207 { NULL },
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003208};
3209
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003210#ifdef HAS_AUDIO
3211struct soundhw soundhw[] = {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003212#ifdef HAS_AUDIO_CHOICE
3213#if defined(TARGET_I386) || defined(TARGET_MIPS)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003214 {
3215 "pcspk",
3216 "PC speaker",
3217 0,
3218 1,
3219 { .init_isa = pcspk_audio_init }
3220 },
3221#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003222
3223#ifdef CONFIG_SB16
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003224 {
3225 "sb16",
3226 "Creative Sound Blaster 16",
3227 0,
3228 1,
3229 { .init_isa = SB16_init }
3230 },
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003231#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003232
3233#ifdef CONFIG_CS4231A
3234 {
3235 "cs4231a",
3236 "CS4231A",
3237 0,
3238 1,
3239 { .init_isa = cs4231a_init }
3240 },
3241#endif
3242
3243#ifdef CONFIG_ADLIB
3244 {
3245 "adlib",
3246#ifdef HAS_YMF262
3247 "Yamaha YMF262 (OPL3)",
3248#else
3249 "Yamaha YM3812 (OPL2)",
3250#endif
3251 0,
3252 1,
3253 { .init_isa = Adlib_init }
3254 },
3255#endif
3256
3257#ifdef CONFIG_GUS
3258 {
3259 "gus",
3260 "Gravis Ultrasound GF1",
3261 0,
3262 1,
3263 { .init_isa = GUS_init }
3264 },
3265#endif
3266
3267#ifdef CONFIG_AC97
3268 {
3269 "ac97",
3270 "Intel 82801AA AC97 Audio",
3271 0,
3272 0,
3273 { .init_pci = ac97_init }
3274 },
3275#endif
3276
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003277#ifdef CONFIG_ES1370
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003278 {
3279 "es1370",
3280 "ENSONIQ AudioPCI ES1370",
3281 0,
3282 0,
3283 { .init_pci = es1370_init }
3284 },
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003285#endif
3286
3287#endif /* HAS_AUDIO_CHOICE */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003288
3289 { NULL, NULL, 0, 0, { NULL } }
3290};
3291
3292static void select_soundhw (const char *optarg)
3293{
3294 struct soundhw *c;
3295
3296 if (*optarg == '?') {
3297 show_valid_cards:
3298
3299 printf ("Valid sound card names (comma separated):\n");
3300 for (c = soundhw; c->name; ++c) {
3301 printf ("%-11s %s\n", c->name, c->descr);
3302 }
3303 printf ("\n-soundhw all will enable all of the above\n");
3304 exit (*optarg != '?');
3305 }
3306 else {
3307 size_t l;
3308 const char *p;
3309 char *e;
3310 int bad_card = 0;
3311
3312 if (!strcmp (optarg, "all")) {
3313 for (c = soundhw; c->name; ++c) {
3314 c->enabled = 1;
3315 }
3316 return;
3317 }
3318
3319 p = optarg;
3320 while (*p) {
3321 e = strchr (p, ',');
3322 l = !e ? strlen (p) : (size_t) (e - p);
3323
3324 for (c = soundhw; c->name; ++c) {
3325 if (!strncmp (c->name, p, l)) {
3326 c->enabled = 1;
3327 break;
3328 }
3329 }
3330
3331 if (!c->name) {
3332 if (l > 80) {
3333 fprintf (stderr,
3334 "Unknown sound card name (too big to show)\n");
3335 }
3336 else {
3337 fprintf (stderr, "Unknown sound card name `%.*s'\n",
3338 (int) l, p);
3339 }
3340 bad_card = 1;
3341 }
3342 p += l + (e != NULL);
3343 }
3344
3345 if (bad_card)
3346 goto show_valid_cards;
3347 }
3348}
3349#endif
3350
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003351static void select_vgahw (const char *p)
3352{
3353 const char *opts;
3354
3355 cirrus_vga_enabled = 0;
3356 std_vga_enabled = 0;
3357 vmsvga_enabled = 0;
3358 xenfb_enabled = 0;
3359 if (strstart(p, "std", &opts)) {
3360 std_vga_enabled = 1;
3361 } else if (strstart(p, "cirrus", &opts)) {
3362 cirrus_vga_enabled = 1;
3363 } else if (strstart(p, "vmware", &opts)) {
3364 vmsvga_enabled = 1;
3365 } else if (strstart(p, "xenfb", &opts)) {
3366 xenfb_enabled = 1;
3367 } else if (!strstart(p, "none", &opts)) {
3368 invalid_vga:
3369 fprintf(stderr, "Unknown vga type: %s\n", p);
3370 exit(1);
3371 }
3372 while (*opts) {
3373 const char *nextopt;
3374
3375 if (strstart(opts, ",retrace=", &nextopt)) {
3376 opts = nextopt;
3377 if (strstart(opts, "dumb", &nextopt))
3378 vga_retrace_method = VGA_RETRACE_DUMB;
3379 else if (strstart(opts, "precise", &nextopt))
3380 vga_retrace_method = VGA_RETRACE_PRECISE;
3381 else goto invalid_vga;
3382 } else goto invalid_vga;
3383 opts = nextopt;
3384 }
3385}
3386
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003387#ifdef _WIN32
3388static BOOL WINAPI qemu_ctrl_handler(DWORD type)
3389{
3390 exit(STATUS_CONTROL_C_EXIT);
3391 return TRUE;
3392}
3393#endif
3394
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003395int qemu_uuid_parse(const char *str, uint8_t *uuid)
3396{
3397 int ret;
3398
3399 if(strlen(str) != 36)
3400 return -1;
3401
3402 ret = sscanf(str, UUID_FMT, &uuid[0], &uuid[1], &uuid[2], &uuid[3],
3403 &uuid[4], &uuid[5], &uuid[6], &uuid[7], &uuid[8], &uuid[9],
3404 &uuid[10], &uuid[11], &uuid[12], &uuid[13], &uuid[14], &uuid[15]);
3405
3406 if(ret != 16)
3407 return -1;
3408
3409#ifdef TARGET_I386
3410 smbios_add_field(1, offsetof(struct smbios_type_1, uuid), 16, uuid);
3411#endif
3412
3413 return 0;
3414}
3415
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003416#define MAX_NET_CLIENTS 32
3417
3418#ifndef _WIN32
3419
3420static void termsig_handler(int signal)
3421{
3422 qemu_system_shutdown_request();
3423}
3424
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003425static void sigchld_handler(int signal)
3426{
3427 waitpid(-1, NULL, WNOHANG);
3428}
3429
3430static void sighandler_setup(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003431{
3432 struct sigaction act;
3433
3434 memset(&act, 0, sizeof(act));
3435 act.sa_handler = termsig_handler;
3436 sigaction(SIGINT, &act, NULL);
3437 sigaction(SIGHUP, &act, NULL);
3438 sigaction(SIGTERM, &act, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003439
3440 act.sa_handler = sigchld_handler;
3441 act.sa_flags = SA_NOCLDSTOP;
3442 sigaction(SIGCHLD, &act, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003443}
3444
3445#endif
3446
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003447#ifdef _WIN32
3448/* Look for support files in the same directory as the executable. */
3449static char *find_datadir(const char *argv0)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003450{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003451 char *p;
3452 char buf[MAX_PATH];
3453 DWORD len;
3454
3455 len = GetModuleFileName(NULL, buf, sizeof(buf) - 1);
3456 if (len == 0) {
3457 return NULL;
3458 }
3459
3460 buf[len] = 0;
3461 p = buf + len - 1;
3462 while (p != buf && *p != '\\')
3463 p--;
3464 *p = 0;
3465 if (access(buf, R_OK) == 0) {
3466 return qemu_strdup(buf);
3467 }
3468 return NULL;
3469}
3470#else /* !_WIN32 */
3471
3472/* Find a likely location for support files using the location of the binary.
3473 For installed binaries this will be "$bindir/../share/qemu". When
3474 running from the build tree this will be "$bindir/../pc-bios". */
3475#define SHARE_SUFFIX "/share/qemu"
3476#define BUILD_SUFFIX "/pc-bios"
3477static char *find_datadir(const char *argv0)
3478{
3479 char *dir;
3480 char *p = NULL;
3481 char *res;
3482#ifdef PATH_MAX
3483 char buf[PATH_MAX];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003484#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003485 size_t max_len;
3486
3487#if defined(__linux__)
3488 {
3489 int len;
3490 len = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
3491 if (len > 0) {
3492 buf[len] = 0;
3493 p = buf;
3494 }
3495 }
3496#elif defined(__FreeBSD__)
3497 {
3498 int len;
3499 len = readlink("/proc/curproc/file", buf, sizeof(buf) - 1);
3500 if (len > 0) {
3501 buf[len] = 0;
3502 p = buf;
3503 }
3504 }
3505#endif
3506 /* If we don't have any way of figuring out the actual executable
3507 location then try argv[0]. */
3508 if (!p) {
3509#ifdef PATH_MAX
3510 p = buf;
3511#endif
3512 p = realpath(argv0, p);
3513 if (!p) {
3514 return NULL;
3515 }
3516 }
3517 dir = dirname(p);
3518 dir = dirname(dir);
3519
3520 max_len = strlen(dir) +
3521 MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1;
3522 res = qemu_mallocz(max_len);
3523 snprintf(res, max_len, "%s%s", dir, SHARE_SUFFIX);
3524 if (access(res, R_OK)) {
3525 snprintf(res, max_len, "%s%s", dir, BUILD_SUFFIX);
3526 if (access(res, R_OK)) {
3527 qemu_free(res);
3528 res = NULL;
3529 }
3530 }
3531#ifndef PATH_MAX
3532 free(p);
3533#endif
3534 return res;
3535}
3536#undef SHARE_SUFFIX
3537#undef BUILD_SUFFIX
3538#endif
3539
3540char *qemu_find_file(int type, const char *name)
3541{
3542 int len;
3543 const char *subdir;
3544 char *buf;
3545
3546 /* If name contains path separators then try it as a straight path. */
3547 if ((strchr(name, '/') || strchr(name, '\\'))
3548 && access(name, R_OK) == 0) {
David Turner025c32f2010-09-10 14:52:42 +02003549 return qemu_strdup(name);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003550 }
3551 switch (type) {
3552 case QEMU_FILE_TYPE_BIOS:
3553 subdir = "";
3554 break;
3555 case QEMU_FILE_TYPE_KEYMAP:
3556 subdir = "keymaps/";
3557 break;
3558 default:
3559 abort();
3560 }
3561 len = strlen(data_dir) + strlen(name) + strlen(subdir) + 2;
3562 buf = qemu_mallocz(len);
3563 snprintf(buf, len, "%s/%s%s", data_dir, subdir, name);
3564 if (access(buf, R_OK)) {
3565 qemu_free(buf);
3566 return NULL;
3567 }
3568 return buf;
3569}
3570
3571int main(int argc, char **argv, char **envp)
3572{
3573 const char *gdbstub_dev = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003574 uint32_t boot_devices_bitmap = 0;
3575 int i;
3576 int snapshot, linux_boot, net_boot;
David Turner6a9ef172010-09-09 22:54:36 +02003577 const char *icount_option = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003578 const char *initrd_filename;
3579 const char *kernel_filename, *kernel_cmdline;
3580 const char *boot_devices = "";
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003581 DisplayState *ds;
3582 DisplayChangeListener *dcl;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003583 int cyls, heads, secs, translation;
3584 const char *net_clients[MAX_NET_CLIENTS];
3585 int nb_net_clients;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003586 const char *bt_opts[MAX_BT_CMDLINE];
3587 int nb_bt_opts;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003588 int hda_index;
3589 int optind;
3590 const char *r, *optarg;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003591 CharDriverState *monitor_hd = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003592 const char *monitor_device;
3593 const char *serial_devices[MAX_SERIAL_PORTS];
3594 int serial_device_index;
3595 const char *parallel_devices[MAX_PARALLEL_PORTS];
3596 int parallel_device_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003597 const char *virtio_consoles[MAX_VIRTIO_CONSOLES];
3598 int virtio_console_index;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003599 const char *loadvm = NULL;
3600 QEMUMachine *machine;
3601 const char *cpu_model;
3602 const char *usb_devices[MAX_USB_CMDLINE];
3603 int usb_devices_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003604#ifndef _WIN32
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003605 int fds[2];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003606#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003607 int tb_size;
3608 const char *pid_file = NULL;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003609 const char *incoming = NULL;
3610#ifndef _WIN32
3611 int fd = 0;
3612 struct passwd *pwd = NULL;
3613 const char *chroot_dir = NULL;
3614 const char *run_as = NULL;
3615#endif
3616 CPUState *env;
3617 int show_vnc_port = 0;
3618
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07003619 init_clocks();
3620
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003621 qemu_cache_utils_init(envp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003622
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003623 QLIST_INIT (&vm_change_state_head);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003624#ifndef _WIN32
3625 {
3626 struct sigaction act;
3627 sigfillset(&act.sa_mask);
3628 act.sa_flags = 0;
3629 act.sa_handler = SIG_IGN;
3630 sigaction(SIGPIPE, &act, NULL);
3631 }
3632#else
3633 SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE);
3634 /* Note: cpu_interrupt() is currently not SMP safe, so we force
3635 QEMU to run on a single CPU */
3636 {
3637 HANDLE h;
3638 DWORD mask, smask;
3639 int i;
3640 h = GetCurrentProcess();
3641 if (GetProcessAffinityMask(h, &mask, &smask)) {
3642 for(i = 0; i < 32; i++) {
3643 if (mask & (1 << i))
3644 break;
3645 }
3646 if (i != 32) {
3647 mask = 1 << i;
3648 SetProcessAffinityMask(h, mask);
3649 }
3650 }
3651 }
3652#endif
3653
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003654 module_call_init(MODULE_INIT_MACHINE);
3655 machine = find_default_machine();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003656 cpu_model = NULL;
3657 initrd_filename = NULL;
3658 ram_size = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003659 snapshot = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003660 kernel_filename = NULL;
3661 kernel_cmdline = "";
3662 cyls = heads = secs = 0;
3663 translation = BIOS_ATA_TRANSLATION_AUTO;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003664 monitor_device = "vc:80Cx24C";
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003665
3666 serial_devices[0] = "vc:80Cx24C";
3667 for(i = 1; i < MAX_SERIAL_PORTS; i++)
3668 serial_devices[i] = NULL;
3669 serial_device_index = 0;
3670
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003671 parallel_devices[0] = "vc:80Cx24C";
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003672 for(i = 1; i < MAX_PARALLEL_PORTS; i++)
3673 parallel_devices[i] = NULL;
3674 parallel_device_index = 0;
3675
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003676 for(i = 0; i < MAX_VIRTIO_CONSOLES; i++)
3677 virtio_consoles[i] = NULL;
3678 virtio_console_index = 0;
3679
3680 for (i = 0; i < MAX_NODES; i++) {
3681 node_mem[i] = 0;
3682 node_cpumask[i] = 0;
3683 }
3684
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003685 usb_devices_index = 0;
3686
3687 nb_net_clients = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003688 nb_bt_opts = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003689 nb_drives = 0;
3690 nb_drives_opt = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003691 nb_numa_nodes = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003692 hda_index = -1;
3693
3694 nb_nics = 0;
3695
3696 tb_size = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003697 autostart= 1;
3698
3699 register_watchdogs();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003700
3701 optind = 1;
3702 for(;;) {
3703 if (optind >= argc)
3704 break;
3705 r = argv[optind];
3706 if (r[0] != '-') {
3707 hda_index = drive_add(argv[optind++], HD_ALIAS, 0);
3708 } else {
3709 const QEMUOption *popt;
3710
3711 optind++;
3712 /* Treat --foo the same as -foo. */
3713 if (r[1] == '-')
3714 r++;
3715 popt = qemu_options;
3716 for(;;) {
3717 if (!popt->name) {
3718 fprintf(stderr, "%s: invalid option -- '%s'\n",
3719 argv[0], r);
3720 exit(1);
3721 }
3722 if (!strcmp(popt->name, r + 1))
3723 break;
3724 popt++;
3725 }
3726 if (popt->flags & HAS_ARG) {
3727 if (optind >= argc) {
3728 fprintf(stderr, "%s: option '%s' requires an argument\n",
3729 argv[0], r);
3730 exit(1);
3731 }
3732 optarg = argv[optind++];
3733 } else {
3734 optarg = NULL;
3735 }
3736
3737 switch(popt->index) {
3738 case QEMU_OPTION_M:
3739 machine = find_machine(optarg);
3740 if (!machine) {
3741 QEMUMachine *m;
3742 printf("Supported machines are:\n");
3743 for(m = first_machine; m != NULL; m = m->next) {
3744 printf("%-10s %s%s\n",
3745 m->name, m->desc,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003746 m->is_default ? " (default)" : "");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003747 }
3748 exit(*optarg != '?');
3749 }
3750 break;
3751 case QEMU_OPTION_cpu:
3752 /* hw initialization will check this */
3753 if (*optarg == '?') {
3754/* XXX: implement xxx_cpu_list for targets that still miss it */
3755#if defined(cpu_list)
3756 cpu_list(stdout, &fprintf);
3757#endif
3758 exit(0);
3759 } else {
3760 cpu_model = optarg;
3761 }
3762 break;
3763 case QEMU_OPTION_initrd:
3764 initrd_filename = optarg;
3765 break;
3766 case QEMU_OPTION_hda:
3767 if (cyls == 0)
3768 hda_index = drive_add(optarg, HD_ALIAS, 0);
3769 else
3770 hda_index = drive_add(optarg, HD_ALIAS
3771 ",cyls=%d,heads=%d,secs=%d%s",
3772 0, cyls, heads, secs,
3773 translation == BIOS_ATA_TRANSLATION_LBA ?
3774 ",trans=lba" :
3775 translation == BIOS_ATA_TRANSLATION_NONE ?
3776 ",trans=none" : "");
3777 break;
3778 case QEMU_OPTION_hdb:
3779 case QEMU_OPTION_hdc:
3780 case QEMU_OPTION_hdd:
3781 drive_add(optarg, HD_ALIAS, popt->index - QEMU_OPTION_hda);
3782 break;
3783 case QEMU_OPTION_drive:
3784 drive_add(NULL, "%s", optarg);
3785 break;
3786 case QEMU_OPTION_mtdblock:
3787 drive_add(optarg, MTD_ALIAS);
3788 break;
3789 case QEMU_OPTION_sd:
3790 drive_add(optarg, SD_ALIAS);
3791 break;
3792 case QEMU_OPTION_pflash:
3793 drive_add(optarg, PFLASH_ALIAS);
3794 break;
3795 case QEMU_OPTION_snapshot:
3796 snapshot = 1;
3797 break;
3798 case QEMU_OPTION_hdachs:
3799 {
3800 const char *p;
3801 p = optarg;
3802 cyls = strtol(p, (char **)&p, 0);
3803 if (cyls < 1 || cyls > 16383)
3804 goto chs_fail;
3805 if (*p != ',')
3806 goto chs_fail;
3807 p++;
3808 heads = strtol(p, (char **)&p, 0);
3809 if (heads < 1 || heads > 16)
3810 goto chs_fail;
3811 if (*p != ',')
3812 goto chs_fail;
3813 p++;
3814 secs = strtol(p, (char **)&p, 0);
3815 if (secs < 1 || secs > 63)
3816 goto chs_fail;
3817 if (*p == ',') {
3818 p++;
3819 if (!strcmp(p, "none"))
3820 translation = BIOS_ATA_TRANSLATION_NONE;
3821 else if (!strcmp(p, "lba"))
3822 translation = BIOS_ATA_TRANSLATION_LBA;
3823 else if (!strcmp(p, "auto"))
3824 translation = BIOS_ATA_TRANSLATION_AUTO;
3825 else
3826 goto chs_fail;
3827 } else if (*p != '\0') {
3828 chs_fail:
3829 fprintf(stderr, "qemu: invalid physical CHS format\n");
3830 exit(1);
3831 }
3832 if (hda_index != -1)
3833 snprintf(drives_opt[hda_index].opt,
3834 sizeof(drives_opt[hda_index].opt),
3835 HD_ALIAS ",cyls=%d,heads=%d,secs=%d%s",
3836 0, cyls, heads, secs,
3837 translation == BIOS_ATA_TRANSLATION_LBA ?
3838 ",trans=lba" :
3839 translation == BIOS_ATA_TRANSLATION_NONE ?
3840 ",trans=none" : "");
3841 }
3842 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003843 case QEMU_OPTION_numa:
3844 if (nb_numa_nodes >= MAX_NODES) {
3845 fprintf(stderr, "qemu: too many NUMA nodes\n");
3846 exit(1);
3847 }
3848 numa_add(optarg);
3849 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003850 case QEMU_OPTION_nographic:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003851 display_type = DT_NOGRAPHIC;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003852 break;
3853#ifdef CONFIG_CURSES
3854 case QEMU_OPTION_curses:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003855 display_type = DT_CURSES;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003856 break;
3857#endif
3858 case QEMU_OPTION_portrait:
3859 graphic_rotate = 1;
3860 break;
3861 case QEMU_OPTION_kernel:
3862 kernel_filename = optarg;
3863 break;
3864 case QEMU_OPTION_append:
3865 kernel_cmdline = optarg;
3866 break;
3867 case QEMU_OPTION_cdrom:
3868 drive_add(optarg, CDROM_ALIAS);
3869 break;
3870 case QEMU_OPTION_boot:
3871 boot_devices = optarg;
3872 /* We just do some generic consistency checks */
3873 {
3874 /* Could easily be extended to 64 devices if needed */
3875 const char *p;
3876
3877 boot_devices_bitmap = 0;
3878 for (p = boot_devices; *p != '\0'; p++) {
3879 /* Allowed boot devices are:
3880 * a b : floppy disk drives
3881 * c ... f : IDE disk drives
3882 * g ... m : machine implementation dependant drives
3883 * n ... p : network devices
3884 * It's up to each machine implementation to check
3885 * if the given boot devices match the actual hardware
3886 * implementation and firmware features.
3887 */
3888 if (*p < 'a' || *p > 'q') {
3889 fprintf(stderr, "Invalid boot device '%c'\n", *p);
3890 exit(1);
3891 }
3892 if (boot_devices_bitmap & (1 << (*p - 'a'))) {
3893 fprintf(stderr,
3894 "Boot device '%c' was given twice\n",*p);
3895 exit(1);
3896 }
3897 boot_devices_bitmap |= 1 << (*p - 'a');
3898 }
3899 }
3900 break;
3901 case QEMU_OPTION_fda:
3902 case QEMU_OPTION_fdb:
3903 drive_add(optarg, FD_ALIAS, popt->index - QEMU_OPTION_fda);
3904 break;
3905#ifdef TARGET_I386
3906 case QEMU_OPTION_no_fd_bootchk:
3907 fd_bootchk = 0;
3908 break;
3909#endif
3910 case QEMU_OPTION_net:
3911 if (nb_net_clients >= MAX_NET_CLIENTS) {
3912 fprintf(stderr, "qemu: too many network clients\n");
3913 exit(1);
3914 }
3915 net_clients[nb_net_clients] = optarg;
3916 nb_net_clients++;
3917 break;
3918#ifdef CONFIG_SLIRP
3919 case QEMU_OPTION_tftp:
3920 tftp_prefix = optarg;
3921 break;
3922 case QEMU_OPTION_bootp:
3923 bootp_filename = optarg;
3924 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003925#ifndef _WIN32
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003926 case QEMU_OPTION_smb:
3927 net_slirp_smb(optarg);
3928 break;
3929#endif
3930 case QEMU_OPTION_redir:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003931 net_slirp_redir(NULL, optarg, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003932 break;
3933#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003934 case QEMU_OPTION_bt:
3935 if (nb_bt_opts >= MAX_BT_CMDLINE) {
3936 fprintf(stderr, "qemu: too many bluetooth options\n");
3937 exit(1);
3938 }
3939 bt_opts[nb_bt_opts++] = optarg;
3940 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003941#ifdef HAS_AUDIO
3942 case QEMU_OPTION_audio_help:
3943 AUD_help ();
3944 exit (0);
3945 break;
3946 case QEMU_OPTION_soundhw:
3947 select_soundhw (optarg);
3948 break;
3949#endif
3950 case QEMU_OPTION_h:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003951 help(0);
3952 break;
3953 case QEMU_OPTION_version:
3954 version();
3955 exit(0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003956 break;
3957 case QEMU_OPTION_m: {
3958 uint64_t value;
3959 char *ptr;
3960
3961 value = strtoul(optarg, &ptr, 10);
3962 switch (*ptr) {
3963 case 0: case 'M': case 'm':
3964 value <<= 20;
3965 break;
3966 case 'G': case 'g':
3967 value <<= 30;
3968 break;
3969 default:
3970 fprintf(stderr, "qemu: invalid ram size: %s\n", optarg);
3971 exit(1);
3972 }
3973
3974 /* On 32-bit hosts, QEMU is limited by virtual address space */
David Turner025c32f2010-09-10 14:52:42 +02003975 if (value > (2047 << 20) && HOST_LONG_BITS == 32) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003976 fprintf(stderr, "qemu: at most 2047 MB RAM can be simulated\n");
3977 exit(1);
3978 }
3979 if (value != (uint64_t)(ram_addr_t)value) {
3980 fprintf(stderr, "qemu: ram size too large\n");
3981 exit(1);
3982 }
3983 ram_size = value;
3984 break;
3985 }
3986 case QEMU_OPTION_d:
3987 {
3988 int mask;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003989 const CPULogItem *item;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003990
3991 mask = cpu_str_to_log_mask(optarg);
3992 if (!mask) {
3993 printf("Log items (comma separated):\n");
3994 for(item = cpu_log_items; item->mask != 0; item++) {
3995 printf("%-10s %s\n", item->name, item->help);
3996 }
3997 exit(1);
3998 }
3999 cpu_set_log(mask);
4000 }
4001 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004002 case QEMU_OPTION_s:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004003 gdbstub_dev = "tcp::" DEFAULT_GDBSTUB_PORT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004004 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004005 case QEMU_OPTION_gdb:
4006 gdbstub_dev = optarg;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004007 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004008 case QEMU_OPTION_L:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004009 data_dir = optarg;
4010 break;
4011 case QEMU_OPTION_bios:
4012 bios_name = optarg;
4013 break;
4014 case QEMU_OPTION_singlestep:
4015 singlestep = 1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004016 break;
4017 case QEMU_OPTION_S:
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004018 autostart = 0;
4019 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004020#ifndef _WIN32
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004021 case QEMU_OPTION_k:
4022 keyboard_layout = optarg;
4023 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004024#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004025 case QEMU_OPTION_localtime:
4026 rtc_utc = 0;
4027 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004028 case QEMU_OPTION_vga:
4029 select_vgahw (optarg);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004030 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004031#if defined(TARGET_PPC) || defined(TARGET_SPARC)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004032 case QEMU_OPTION_g:
4033 {
4034 const char *p;
4035 int w, h, depth;
4036 p = optarg;
4037 w = strtol(p, (char **)&p, 10);
4038 if (w <= 0) {
4039 graphic_error:
4040 fprintf(stderr, "qemu: invalid resolution or depth\n");
4041 exit(1);
4042 }
4043 if (*p != 'x')
4044 goto graphic_error;
4045 p++;
4046 h = strtol(p, (char **)&p, 10);
4047 if (h <= 0)
4048 goto graphic_error;
4049 if (*p == 'x') {
4050 p++;
4051 depth = strtol(p, (char **)&p, 10);
4052 if (depth != 8 && depth != 15 && depth != 16 &&
4053 depth != 24 && depth != 32)
4054 goto graphic_error;
4055 } else if (*p == '\0') {
4056 depth = graphic_depth;
4057 } else {
4058 goto graphic_error;
4059 }
4060
4061 graphic_width = w;
4062 graphic_height = h;
4063 graphic_depth = depth;
4064 }
4065 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004066#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004067 case QEMU_OPTION_echr:
4068 {
4069 char *r;
4070 term_escape_char = strtol(optarg, &r, 0);
4071 if (r == optarg)
4072 printf("Bad argument to echr\n");
4073 break;
4074 }
4075 case QEMU_OPTION_monitor:
4076 monitor_device = optarg;
4077 break;
4078 case QEMU_OPTION_serial:
4079 if (serial_device_index >= MAX_SERIAL_PORTS) {
4080 fprintf(stderr, "qemu: too many serial ports\n");
4081 exit(1);
4082 }
4083 serial_devices[serial_device_index] = optarg;
4084 serial_device_index++;
4085 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004086 case QEMU_OPTION_watchdog:
4087 i = select_watchdog(optarg);
4088 if (i > 0)
4089 exit (i == 1 ? 1 : 0);
4090 break;
4091 case QEMU_OPTION_watchdog_action:
4092 if (select_watchdog_action(optarg) == -1) {
4093 fprintf(stderr, "Unknown -watchdog-action parameter\n");
4094 exit(1);
4095 }
4096 break;
4097 case QEMU_OPTION_virtiocon:
4098 if (virtio_console_index >= MAX_VIRTIO_CONSOLES) {
4099 fprintf(stderr, "qemu: too many virtio consoles\n");
4100 exit(1);
4101 }
4102 virtio_consoles[virtio_console_index] = optarg;
4103 virtio_console_index++;
4104 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004105 case QEMU_OPTION_parallel:
4106 if (parallel_device_index >= MAX_PARALLEL_PORTS) {
4107 fprintf(stderr, "qemu: too many parallel ports\n");
4108 exit(1);
4109 }
4110 parallel_devices[parallel_device_index] = optarg;
4111 parallel_device_index++;
4112 break;
4113 case QEMU_OPTION_loadvm:
4114 loadvm = optarg;
4115 break;
4116 case QEMU_OPTION_full_screen:
4117 full_screen = 1;
4118 break;
4119#ifdef CONFIG_SDL
4120 case QEMU_OPTION_no_frame:
4121 no_frame = 1;
4122 break;
4123 case QEMU_OPTION_alt_grab:
4124 alt_grab = 1;
4125 break;
4126 case QEMU_OPTION_no_quit:
4127 no_quit = 1;
4128 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004129 case QEMU_OPTION_sdl:
4130 display_type = DT_SDL;
4131 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004132#endif
4133 case QEMU_OPTION_pidfile:
4134 pid_file = optarg;
4135 break;
4136#ifdef TARGET_I386
4137 case QEMU_OPTION_win2k_hack:
4138 win2k_install_hack = 1;
4139 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004140 case QEMU_OPTION_rtc_td_hack:
4141 rtc_td_hack = 1;
4142 break;
4143 case QEMU_OPTION_acpitable:
4144 if(acpi_table_add(optarg) < 0) {
4145 fprintf(stderr, "Wrong acpi table provided\n");
4146 exit(1);
4147 }
4148 break;
4149 case QEMU_OPTION_smbios:
4150 if(smbios_entry_add(optarg) < 0) {
4151 fprintf(stderr, "Wrong smbios provided\n");
4152 exit(1);
4153 }
4154 break;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004155#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004156#ifdef CONFIG_KQEMU
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004157 case QEMU_OPTION_no_kqemu:
4158 kqemu_allowed = 0;
4159 break;
4160 case QEMU_OPTION_kernel_kqemu:
4161 kqemu_allowed = 2;
4162 break;
4163#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004164#ifdef CONFIG_KVM
4165 case QEMU_OPTION_enable_kvm:
4166 kvm_allowed = 1;
4167#ifdef CONFIG_KQEMU
4168 kqemu_allowed = 0;
4169#endif
4170 break;
4171#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004172 case QEMU_OPTION_usb:
4173 usb_enabled = 1;
4174 break;
4175 case QEMU_OPTION_usbdevice:
4176 usb_enabled = 1;
4177 if (usb_devices_index >= MAX_USB_CMDLINE) {
4178 fprintf(stderr, "Too many USB devices\n");
4179 exit(1);
4180 }
4181 usb_devices[usb_devices_index] = optarg;
4182 usb_devices_index++;
4183 break;
4184 case QEMU_OPTION_smp:
4185 smp_cpus = atoi(optarg);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004186 if (smp_cpus < 1) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004187 fprintf(stderr, "Invalid number of CPUs\n");
4188 exit(1);
4189 }
4190 break;
4191 case QEMU_OPTION_vnc:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004192 display_type = DT_VNC;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004193 vnc_display = optarg;
4194 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004195#ifdef TARGET_I386
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004196 case QEMU_OPTION_no_acpi:
4197 acpi_enabled = 0;
4198 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004199 case QEMU_OPTION_no_hpet:
4200 no_hpet = 1;
4201 break;
4202 case QEMU_OPTION_no_virtio_balloon:
4203 no_virtio_balloon = 1;
4204 break;
4205#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004206 case QEMU_OPTION_no_reboot:
4207 no_reboot = 1;
4208 break;
4209 case QEMU_OPTION_no_shutdown:
4210 no_shutdown = 1;
4211 break;
4212 case QEMU_OPTION_show_cursor:
4213 cursor_hide = 0;
4214 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004215 case QEMU_OPTION_uuid:
4216 if(qemu_uuid_parse(optarg, qemu_uuid) < 0) {
4217 fprintf(stderr, "Fail to parse UUID string."
4218 " Wrong format.\n");
4219 exit(1);
4220 }
4221 break;
4222#ifndef _WIN32
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004223 case QEMU_OPTION_daemonize:
4224 daemonize = 1;
4225 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004226#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004227 case QEMU_OPTION_option_rom:
4228 if (nb_option_roms >= MAX_OPTION_ROMS) {
4229 fprintf(stderr, "Too many option ROMs\n");
4230 exit(1);
4231 }
4232 option_rom[nb_option_roms] = optarg;
4233 nb_option_roms++;
4234 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004235#if defined(TARGET_ARM) || defined(TARGET_M68K)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004236 case QEMU_OPTION_semihosting:
4237 semihosting_enabled = 1;
4238 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004239#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004240 case QEMU_OPTION_name:
4241 qemu_name = optarg;
4242 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004243#if defined(TARGET_SPARC) || defined(TARGET_PPC)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004244 case QEMU_OPTION_prom_env:
4245 if (nb_prom_envs >= MAX_PROM_ENVS) {
4246 fprintf(stderr, "Too many prom variables\n");
4247 exit(1);
4248 }
4249 prom_envs[nb_prom_envs] = optarg;
4250 nb_prom_envs++;
4251 break;
4252#endif
4253#ifdef TARGET_ARM
4254 case QEMU_OPTION_old_param:
4255 old_param = 1;
4256 break;
4257#endif
4258 case QEMU_OPTION_clock:
4259 configure_alarms(optarg);
4260 break;
4261 case QEMU_OPTION_startdate:
4262 {
4263 struct tm tm;
4264 time_t rtc_start_date;
4265 if (!strcmp(optarg, "now")) {
4266 rtc_date_offset = -1;
4267 } else {
4268 if (sscanf(optarg, "%d-%d-%dT%d:%d:%d",
4269 &tm.tm_year,
4270 &tm.tm_mon,
4271 &tm.tm_mday,
4272 &tm.tm_hour,
4273 &tm.tm_min,
4274 &tm.tm_sec) == 6) {
4275 /* OK */
4276 } else if (sscanf(optarg, "%d-%d-%d",
4277 &tm.tm_year,
4278 &tm.tm_mon,
4279 &tm.tm_mday) == 3) {
4280 tm.tm_hour = 0;
4281 tm.tm_min = 0;
4282 tm.tm_sec = 0;
4283 } else {
4284 goto date_fail;
4285 }
4286 tm.tm_year -= 1900;
4287 tm.tm_mon--;
4288 rtc_start_date = mktimegm(&tm);
4289 if (rtc_start_date == -1) {
4290 date_fail:
4291 fprintf(stderr, "Invalid date format. Valid format are:\n"
4292 "'now' or '2006-06-17T16:01:21' or '2006-06-17'\n");
4293 exit(1);
4294 }
4295 rtc_date_offset = time(NULL) - rtc_start_date;
4296 }
4297 }
4298 break;
4299 case QEMU_OPTION_tb_size:
4300 tb_size = strtol(optarg, NULL, 0);
4301 if (tb_size < 0)
4302 tb_size = 0;
4303 break;
4304 case QEMU_OPTION_icount:
David Turner6a9ef172010-09-09 22:54:36 +02004305 icount_option = optarg;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004306 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004307 case QEMU_OPTION_incoming:
4308 incoming = optarg;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004309 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004310#ifndef _WIN32
4311 case QEMU_OPTION_chroot:
4312 chroot_dir = optarg;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004313 break;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004314 case QEMU_OPTION_runas:
4315 run_as = optarg;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004316 break;
4317#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004318#ifdef CONFIG_XEN
4319 case QEMU_OPTION_xen_domid:
4320 xen_domid = atoi(optarg);
4321 break;
4322 case QEMU_OPTION_xen_create:
4323 xen_mode = XEN_CREATE;
4324 break;
4325 case QEMU_OPTION_xen_attach:
4326 xen_mode = XEN_ATTACH;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004327 break;
4328#endif
4329 }
4330 }
4331 }
4332
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004333 /* If no data_dir is specified then try to find it relative to the
4334 executable path. */
4335 if (!data_dir) {
4336 data_dir = find_datadir(argv[0]);
4337 }
4338 /* If all else fails use the install patch specified when building. */
4339 if (!data_dir) {
4340 data_dir = CONFIG_QEMU_SHAREDIR;
4341 }
4342
4343#if defined(CONFIG_KVM) && defined(CONFIG_KQEMU)
4344 if (kvm_allowed && kqemu_allowed) {
4345 fprintf(stderr,
4346 "You can not enable both KVM and kqemu at the same time\n");
4347 exit(1);
4348 }
4349#endif
4350
4351 machine->max_cpus = machine->max_cpus ?: 1; /* Default to UP */
4352 if (smp_cpus > machine->max_cpus) {
4353 fprintf(stderr, "Number of SMP cpus requested (%d), exceeds max cpus "
4354 "supported by machine `%s' (%d)\n", smp_cpus, machine->name,
4355 machine->max_cpus);
4356 exit(1);
4357 }
4358
4359 if (display_type == DT_NOGRAPHIC) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004360 if (serial_device_index == 0)
4361 serial_devices[0] = "stdio";
4362 if (parallel_device_index == 0)
4363 parallel_devices[0] = "null";
4364 if (strncmp(monitor_device, "vc", 2) == 0)
4365 monitor_device = "stdio";
4366 }
4367
4368#ifndef _WIN32
4369 if (daemonize) {
4370 pid_t pid;
4371
4372 if (pipe(fds) == -1)
4373 exit(1);
4374
4375 pid = fork();
4376 if (pid > 0) {
4377 uint8_t status;
4378 ssize_t len;
4379
4380 close(fds[1]);
4381
4382 again:
4383 len = read(fds[0], &status, 1);
4384 if (len == -1 && (errno == EINTR))
4385 goto again;
4386
4387 if (len != 1)
4388 exit(1);
4389 else if (status == 1) {
4390 fprintf(stderr, "Could not acquire pidfile\n");
4391 exit(1);
4392 } else
4393 exit(0);
4394 } else if (pid < 0)
4395 exit(1);
4396
4397 setsid();
4398
4399 pid = fork();
4400 if (pid > 0)
4401 exit(0);
4402 else if (pid < 0)
4403 exit(1);
4404
4405 umask(027);
4406
4407 signal(SIGTSTP, SIG_IGN);
4408 signal(SIGTTOU, SIG_IGN);
4409 signal(SIGTTIN, SIG_IGN);
4410 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004411
4412 if (pid_file && qemu_create_pidfile(pid_file) != 0) {
4413 if (daemonize) {
4414 uint8_t status = 1;
4415 write(fds[1], &status, 1);
4416 } else
4417 fprintf(stderr, "Could not acquire pid file\n");
4418 exit(1);
4419 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004420#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004421
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004422#ifdef CONFIG_KQEMU
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004423 if (smp_cpus > 1)
4424 kqemu_allowed = 0;
4425#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004426 if (qemu_init_main_loop()) {
4427 fprintf(stderr, "qemu_init_main_loop failed\n");
4428 exit(1);
4429 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004430 linux_boot = (kernel_filename != NULL);
4431 net_boot = (boot_devices_bitmap >> ('n' - 'a')) & 0xF;
4432
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004433 if (!linux_boot && *kernel_cmdline != '\0') {
4434 fprintf(stderr, "-append only allowed with -kernel option\n");
4435 exit(1);
4436 }
4437
4438 if (!linux_boot && initrd_filename != NULL) {
4439 fprintf(stderr, "-initrd only allowed with -kernel option\n");
4440 exit(1);
4441 }
4442
4443 /* boot to floppy or the default cd if no hard disk defined yet */
4444 if (!boot_devices[0]) {
4445 boot_devices = "cad";
4446 }
4447 setvbuf(stdout, NULL, _IOLBF, 0);
4448
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004449 if (init_timer_alarm() < 0) {
4450 fprintf(stderr, "could not initialize alarm timer\n");
4451 exit(1);
4452 }
David Turner6a9ef172010-09-09 22:54:36 +02004453 configure_icount(icount_option);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004454
4455#ifdef _WIN32
4456 socket_init();
4457#endif
4458
4459 /* init network clients */
4460 if (nb_net_clients == 0) {
4461 /* if no clients, we use a default config */
4462 net_clients[nb_net_clients++] = "nic";
4463#ifdef CONFIG_SLIRP
4464 net_clients[nb_net_clients++] = "user";
4465#endif
4466 }
4467
4468 for(i = 0;i < nb_net_clients; i++) {
4469 if (net_client_parse(net_clients[i]) < 0)
4470 exit(1);
4471 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004472 net_client_check();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004473
4474#ifdef TARGET_I386
4475 /* XXX: this should be moved in the PC machine instantiation code */
4476 if (net_boot != 0) {
4477 int netroms = 0;
4478 for (i = 0; i < nb_nics && i < 4; i++) {
4479 const char *model = nd_table[i].model;
4480 char buf[1024];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004481 char *filename;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004482 if (net_boot & (1 << i)) {
4483 if (model == NULL)
4484 model = "ne2k_pci";
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004485 snprintf(buf, sizeof(buf), "pxe-%s.bin", model);
4486 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, buf);
4487 if (filename && get_image_size(filename) > 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004488 if (nb_option_roms >= MAX_OPTION_ROMS) {
4489 fprintf(stderr, "Too many option ROMs\n");
4490 exit(1);
4491 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004492 option_rom[nb_option_roms] = qemu_strdup(buf);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004493 nb_option_roms++;
4494 netroms++;
4495 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004496 if (filename) {
4497 qemu_free(filename);
4498 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004499 }
4500 }
4501 if (netroms == 0) {
4502 fprintf(stderr, "No valid PXE rom found for network device\n");
4503 exit(1);
4504 }
4505 }
4506#endif
4507
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004508 /* init the bluetooth world */
4509 for (i = 0; i < nb_bt_opts; i++)
4510 if (bt_parse(bt_opts[i]))
4511 exit(1);
4512
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004513 /* init the memory */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004514 if (ram_size == 0)
4515 ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004516
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004517#ifdef CONFIG_KQEMU
4518 /* FIXME: This is a nasty hack because kqemu can't cope with dynamic
4519 guest ram allocation. It needs to go away. */
4520 if (kqemu_allowed) {
4521 kqemu_phys_ram_size = ram_size + 8 * 1024 * 1024 + 4 * 1024 * 1024;
4522 kqemu_phys_ram_base = qemu_vmalloc(kqemu_phys_ram_size);
4523 if (!kqemu_phys_ram_base) {
4524 fprintf(stderr, "Could not allocate physical memory\n");
4525 exit(1);
4526 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004527 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004528#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004529
4530 /* init the dynamic translator */
4531 cpu_exec_init_all(tb_size * 1024 * 1024);
4532
4533 bdrv_init();
4534
4535 /* we always create the cdrom drive, even if no disk is there */
4536
4537 if (nb_drives_opt < MAX_DRIVES)
4538 drive_add(NULL, CDROM_ALIAS);
4539
4540 /* we always create at least one floppy */
4541
4542 if (nb_drives_opt < MAX_DRIVES)
4543 drive_add(NULL, FD_ALIAS, 0);
4544
4545 /* we always create one sd slot, even if no card is in it */
4546
4547 if (nb_drives_opt < MAX_DRIVES)
4548 drive_add(NULL, SD_ALIAS);
4549
4550 /* open the virtual block devices */
4551
4552 for(i = 0; i < nb_drives_opt; i++)
4553 if (drive_init(&drives_opt[i], snapshot, machine) == -1)
4554 exit(1);
4555
David Turner6a9ef172010-09-09 22:54:36 +02004556 //register_savevm("timer", 0, 2, timer_save, timer_load, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004557 register_savevm_live("ram", 0, 3, ram_save_live, NULL, ram_load, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004558
4559#ifndef _WIN32
4560 /* must be after terminal init, SDL library changes signal handlers */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004561 sighandler_setup();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004562#endif
4563
4564 /* Maintain compatibility with multiple stdio monitors */
4565 if (!strcmp(monitor_device,"stdio")) {
4566 for (i = 0; i < MAX_SERIAL_PORTS; i++) {
4567 const char *devname = serial_devices[i];
4568 if (devname && !strcmp(devname,"mon:stdio")) {
4569 monitor_device = NULL;
4570 break;
4571 } else if (devname && !strcmp(devname,"stdio")) {
4572 monitor_device = NULL;
4573 serial_devices[i] = "mon:stdio";
4574 break;
4575 }
4576 }
4577 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004578
4579 if (nb_numa_nodes > 0) {
4580 int i;
4581
4582 if (nb_numa_nodes > smp_cpus) {
4583 nb_numa_nodes = smp_cpus;
4584 }
4585
4586 /* If no memory size if given for any node, assume the default case
4587 * and distribute the available memory equally across all nodes
4588 */
4589 for (i = 0; i < nb_numa_nodes; i++) {
4590 if (node_mem[i] != 0)
4591 break;
4592 }
4593 if (i == nb_numa_nodes) {
4594 uint64_t usedmem = 0;
4595
4596 /* On Linux, the each node's border has to be 8MB aligned,
4597 * the final node gets the rest.
4598 */
4599 for (i = 0; i < nb_numa_nodes - 1; i++) {
4600 node_mem[i] = (ram_size / nb_numa_nodes) & ~((1 << 23UL) - 1);
4601 usedmem += node_mem[i];
4602 }
4603 node_mem[i] = ram_size - usedmem;
4604 }
4605
4606 for (i = 0; i < nb_numa_nodes; i++) {
4607 if (node_cpumask[i] != 0)
4608 break;
4609 }
4610 /* assigning the VCPUs round-robin is easier to implement, guest OSes
4611 * must cope with this anyway, because there are BIOSes out there in
4612 * real machines which also use this scheme.
4613 */
4614 if (i == nb_numa_nodes) {
4615 for (i = 0; i < smp_cpus; i++) {
4616 node_cpumask[i % nb_numa_nodes] |= 1 << i;
4617 }
4618 }
4619 }
4620
4621 if (kvm_enabled()) {
4622 int ret;
4623
4624 ret = kvm_init(smp_cpus);
4625 if (ret < 0) {
4626 fprintf(stderr, "failed to initialize KVM\n");
4627 exit(1);
4628 }
4629 }
4630
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004631 if (monitor_device) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004632 monitor_hd = qemu_chr_open("monitor", monitor_device, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004633 if (!monitor_hd) {
4634 fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device);
4635 exit(1);
4636 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004637 }
4638
4639 for(i = 0; i < MAX_SERIAL_PORTS; i++) {
4640 const char *devname = serial_devices[i];
4641 if (devname && strcmp(devname, "none")) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004642 char label[32];
4643 snprintf(label, sizeof(label), "serial%d", i);
4644 serial_hds[i] = qemu_chr_open(label, devname, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004645 if (!serial_hds[i]) {
4646 fprintf(stderr, "qemu: could not open serial device '%s'\n",
4647 devname);
4648 exit(1);
4649 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004650 }
4651 }
4652
4653 for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
4654 const char *devname = parallel_devices[i];
4655 if (devname && strcmp(devname, "none")) {
4656 char label[32];
4657 snprintf(label, sizeof(label), "parallel%d", i);
4658 parallel_hds[i] = qemu_chr_open(label, devname, NULL);
4659 if (!parallel_hds[i]) {
4660 fprintf(stderr, "qemu: could not open parallel device '%s'\n",
4661 devname);
4662 exit(1);
4663 }
4664 }
4665 }
4666
4667 for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
4668 const char *devname = virtio_consoles[i];
4669 if (devname && strcmp(devname, "none")) {
4670 char label[32];
4671 snprintf(label, sizeof(label), "virtcon%d", i);
4672 virtcon_hds[i] = qemu_chr_open(label, devname, NULL);
4673 if (!virtcon_hds[i]) {
4674 fprintf(stderr, "qemu: could not open virtio console '%s'\n",
4675 devname);
4676 exit(1);
4677 }
4678 }
4679 }
4680
4681 module_call_init(MODULE_INIT_DEVICE);
4682
4683 machine->init(ram_size, boot_devices,
4684 kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
4685
4686
4687 for (env = first_cpu; env != NULL; env = env->next_cpu) {
4688 for (i = 0; i < nb_numa_nodes; i++) {
4689 if (node_cpumask[i] & (1 << env->cpu_index)) {
4690 env->numa_node = i;
4691 }
4692 }
4693 }
4694
4695 current_machine = machine;
4696
4697 /* Set KVM's vcpu state to qemu's initial CPUState. */
4698 if (kvm_enabled()) {
4699 int ret;
4700
4701 ret = kvm_sync_vcpus();
4702 if (ret < 0) {
4703 fprintf(stderr, "failed to initialize vcpus\n");
4704 exit(1);
4705 }
4706 }
4707
4708 /* init USB devices */
4709 if (usb_enabled) {
4710 for(i = 0; i < usb_devices_index; i++) {
4711 if (usb_device_add(usb_devices[i], 0) < 0) {
4712 fprintf(stderr, "Warning: could not add USB device %s\n",
4713 usb_devices[i]);
4714 }
4715 }
4716 }
4717
4718 if (!display_state)
4719 dumb_display_init();
4720 /* just use the first displaystate for the moment */
4721 ds = display_state;
4722
4723 if (display_type == DT_DEFAULT) {
4724#if defined(CONFIG_SDL) || defined(CONFIG_COCOA)
4725 display_type = DT_SDL;
4726#else
4727 display_type = DT_VNC;
4728 vnc_display = "localhost:0,to=99";
4729 show_vnc_port = 1;
4730#endif
4731 }
4732
4733
4734 switch (display_type) {
4735 case DT_NOGRAPHIC:
4736 break;
4737#if defined(CONFIG_CURSES)
4738 case DT_CURSES:
4739 curses_display_init(ds, full_screen);
4740 break;
4741#endif
4742#if defined(CONFIG_SDL)
4743 case DT_SDL:
4744 sdl_display_init(ds, full_screen, no_frame);
4745 break;
4746#elif defined(CONFIG_COCOA)
4747 case DT_SDL:
4748 cocoa_display_init(ds, full_screen);
4749 break;
4750#endif
4751 case DT_VNC:
4752 vnc_display_init(ds);
4753 if (vnc_display_open(ds, vnc_display) < 0)
4754 exit(1);
4755
4756 if (show_vnc_port) {
4757 printf("VNC server running on `%s'\n", vnc_display_local_addr(ds));
4758 }
4759 break;
4760 default:
4761 break;
4762 }
4763 dpy_resize(ds);
4764
4765 dcl = ds->listeners;
4766 while (dcl != NULL) {
4767 if (dcl->dpy_refresh != NULL) {
4768 ds->gui_timer = qemu_new_timer(rt_clock, gui_update, ds);
4769 qemu_mod_timer(ds->gui_timer, qemu_get_clock(rt_clock));
4770 }
4771 dcl = dcl->next;
4772 }
4773
4774 if (display_type == DT_NOGRAPHIC || display_type == DT_VNC) {
4775 nographic_timer = qemu_new_timer(rt_clock, nographic_update, NULL);
4776 qemu_mod_timer(nographic_timer, qemu_get_clock(rt_clock));
4777 }
4778
4779 text_consoles_set_display(display_state);
4780 qemu_chr_initial_reset();
4781
4782 if (monitor_device && monitor_hd)
4783 monitor_init(monitor_hd, MONITOR_USE_READLINE | MONITOR_IS_DEFAULT);
4784
4785 for(i = 0; i < MAX_SERIAL_PORTS; i++) {
4786 const char *devname = serial_devices[i];
4787 if (devname && strcmp(devname, "none")) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004788 if (strstart(devname, "vc", 0))
4789 qemu_chr_printf(serial_hds[i], "serial%d console\r\n", i);
4790 }
4791 }
4792
4793 for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
4794 const char *devname = parallel_devices[i];
4795 if (devname && strcmp(devname, "none")) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004796 if (strstart(devname, "vc", 0))
4797 qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i);
4798 }
4799 }
4800
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004801 for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
4802 const char *devname = virtio_consoles[i];
4803 if (virtcon_hds[i] && devname) {
4804 if (strstart(devname, "vc", 0))
4805 qemu_chr_printf(virtcon_hds[i], "virtio console%d\r\n", i);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004806 }
4807 }
4808
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004809 if (gdbstub_dev && gdbserver_start(gdbstub_dev) < 0) {
4810 fprintf(stderr, "qemu: could not open gdbserver on device '%s'\n",
4811 gdbstub_dev);
4812 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004813 }
4814
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004815 if (loadvm)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004816 do_loadvm(cur_mon, loadvm);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004817
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004818 if (incoming) {
4819 autostart = 0; /* fixme how to deal with -daemonize */
4820 qemu_start_incoming_migration(incoming);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004821 }
4822
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004823 if (autostart)
4824 vm_start();
4825
4826#ifndef _WIN32
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004827 if (daemonize) {
4828 uint8_t status = 0;
4829 ssize_t len;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004830
4831 again1:
4832 len = write(fds[1], &status, 1);
4833 if (len == -1 && (errno == EINTR))
4834 goto again1;
4835
4836 if (len != 1)
4837 exit(1);
4838
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07004839 if (chdir("/")) {
4840 perror("not able to chdir to /");
4841 exit(1);
4842 }
4843 TFR(fd = qemu_open("/dev/null", O_RDWR));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004844 if (fd == -1)
4845 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004846 }
4847
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004848 if (run_as) {
4849 pwd = getpwnam(run_as);
4850 if (!pwd) {
4851 fprintf(stderr, "User \"%s\" doesn't exist\n", run_as);
4852 exit(1);
4853 }
4854 }
4855
4856 if (chroot_dir) {
4857 if (chroot(chroot_dir) < 0) {
4858 fprintf(stderr, "chroot failed\n");
4859 exit(1);
4860 }
David 'Digit' Turnera7fb77d2010-05-10 23:50:54 -07004861 if (chdir("/")) {
4862 perror("not able to chdir to /");
4863 exit(1);
4864 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004865 }
4866
4867 if (run_as) {
4868 if (setgid(pwd->pw_gid) < 0) {
4869 fprintf(stderr, "Failed to setgid(%d)\n", pwd->pw_gid);
4870 exit(1);
4871 }
4872 if (setuid(pwd->pw_uid) < 0) {
4873 fprintf(stderr, "Failed to setuid(%d)\n", pwd->pw_uid);
4874 exit(1);
4875 }
4876 if (setuid(0) != -1) {
4877 fprintf(stderr, "Dropping privileges failed\n");
4878 exit(1);
4879 }
4880 }
4881
4882 if (daemonize) {
4883 dup2(fd, 0);
4884 dup2(fd, 1);
4885 dup2(fd, 2);
4886
4887 close(fd);
4888 }
4889#endif
4890
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004891 main_loop();
4892 quit_timers();
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07004893 net_cleanup();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004894
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08004895 return 0;
4896}