]> Git Repo - qemu.git/blobdiff - vl.c
make tags useful for block drivers and hardaware devices
[qemu.git] / vl.c
diff --git a/vl.c b/vl.c
index 2d38ded49da256356ecbb766ed0466c334baa610..eb2449a1334abeb63398c5611dc9cde014db027a 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -33,6 +33,7 @@
 #include "config-host.h"
 
 #ifndef _WIN32
 #include "config-host.h"
 
 #ifndef _WIN32
+#include <libgen.h>
 #include <pwd.h>
 #include <sys/times.h>
 #include <sys/wait.h>
 #include <pwd.h>
 #include <sys/times.h>
 #include <sys/wait.h>
 #endif
 
 #ifdef CONFIG_SDL
 #endif
 
 #ifdef CONFIG_SDL
-#ifdef __APPLE__
-#include <SDL/SDL.h>
+#if defined(__APPLE__) || defined(main)
+#include <SDL.h>
 int qemu_main(int argc, char **argv, char **envp);
 int main(int argc, char **argv)
 {
 int qemu_main(int argc, char **argv, char **envp);
 int main(int argc, char **argv)
 {
-    qemu_main(argc, argv, NULL);
+    return qemu_main(argc, argv, NULL);
 }
 #undef main
 #define main qemu_main
 }
 #undef main
 #define main qemu_main
@@ -156,6 +157,7 @@ int main(int argc, char **argv)
 #include "migration.h"
 #include "kvm.h"
 #include "balloon.h"
 #include "migration.h"
 #include "kvm.h"
 #include "balloon.h"
+#include "qemu-option.h"
 
 #include "disas.h"
 
 
 #include "disas.h"
 
@@ -163,9 +165,7 @@ int main(int argc, char **argv)
 
 #include "qemu_socket.h"
 
 
 #include "qemu_socket.h"
 
-#if defined(CONFIG_SLIRP)
-#include "libslirp.h"
-#endif
+#include "slirp/libslirp.h"
 
 //#define DEBUG_UNUSED_IOPORT
 //#define DEBUG_IOPORT
 
 //#define DEBUG_UNUSED_IOPORT
 //#define DEBUG_IOPORT
@@ -190,7 +190,7 @@ int main(int argc, char **argv)
 /* XXX: use a two level table to limit memory usage */
 #define MAX_IOPORTS 65536
 
 /* XXX: use a two level table to limit memory usage */
 #define MAX_IOPORTS 65536
 
-const char *bios_dir = CONFIG_QEMU_SHAREDIR;
+static const char *data_dir;
 const char *bios_name = NULL;
 static void *ioport_opaque[MAX_IOPORTS];
 static IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
 const char *bios_name = NULL;
 static void *ioport_opaque[MAX_IOPORTS];
 static IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
@@ -199,12 +199,9 @@ static IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
    to store the VM snapshots */
 DriveInfo drives_table[MAX_DRIVES+1];
 int nb_drives;
    to store the VM snapshots */
 DriveInfo drives_table[MAX_DRIVES+1];
 int nb_drives;
-static int vga_ram_size;
 enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
 static DisplayState *display_state;
 enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
 static DisplayState *display_state;
-int nographic;
-static int curses;
-static int sdl;
+DisplayType display_type = DT_DEFAULT;
 const char* keyboard_layout = NULL;
 int64_t ticks_per_sec;
 ram_addr_t ram_size;
 const char* keyboard_layout = NULL;
 int64_t ticks_per_sec;
 ram_addr_t ram_size;
@@ -245,6 +242,7 @@ int smp_cpus = 1;
 const char *vnc_display;
 int acpi_enabled = 1;
 int no_hpet = 0;
 const char *vnc_display;
 int acpi_enabled = 1;
 int no_hpet = 0;
+int no_virtio_balloon = 0;
 int fd_bootchk = 1;
 int no_reboot = 0;
 int no_shutdown = 0;
 int fd_bootchk = 1;
 int no_reboot = 0;
 int no_shutdown = 0;
@@ -916,7 +914,7 @@ struct qemu_alarm_timer {
 
 static inline int alarm_has_dynticks(struct qemu_alarm_timer *t)
 {
 
 static inline int alarm_has_dynticks(struct qemu_alarm_timer *t)
 {
-    return t->flags & ALARM_FLAG_DYNTICKS;
+    return t && (t->flags & ALARM_FLAG_DYNTICKS);
 }
 
 static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
 }
 
 static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
@@ -1350,7 +1348,7 @@ static void host_alarm_handler(int host_signum)
         qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME],
                            qemu_get_clock(rt_clock))) {
         qemu_event_increment();
         qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME],
                            qemu_get_clock(rt_clock))) {
         qemu_event_increment();
-        alarm_timer->flags |= ALARM_FLAG_EXPIRED;
+        if (alarm_timer) alarm_timer->flags |= ALARM_FLAG_EXPIRED;
 
 #ifndef CONFIG_IOTHREAD
         if (next_cpu) {
 
 #ifndef CONFIG_IOTHREAD
         if (next_cpu) {
@@ -1543,6 +1541,11 @@ static int dynticks_start_timer(struct qemu_alarm_timer *t)
 
     sigaction(SIGALRM, &act, NULL);
 
 
     sigaction(SIGALRM, &act, NULL);
 
+    /* 
+     * Initialize ev struct to 0 to avoid valgrind complaining
+     * about uninitialized data in timer_create call
+     */
+    memset(&ev, 0, sizeof(ev));
     ev.sigev_value.sival_int = 0;
     ev.sigev_notify = SIGEV_SIGNAL;
     ev.sigev_signo = SIGALRM;
     ev.sigev_value.sival_int = 0;
     ev.sigev_notify = SIGEV_SIGNAL;
     ev.sigev_signo = SIGALRM;
@@ -1807,57 +1810,23 @@ static int socket_init(void)
 }
 #endif
 
 }
 #endif
 
-const char *get_opt_name(char *buf, int buf_size, const char *p, char delim)
-{
-    char *q;
-
-    q = buf;
-    while (*p != '\0' && *p != delim) {
-        if (q && (q - buf) < buf_size - 1)
-            *q++ = *p;
-        p++;
-    }
-    if (q)
-        *q = '\0';
-
-    return p;
-}
-
-const char *get_opt_value(char *buf, int buf_size, const char *p)
-{
-    char *q;
-
-    q = buf;
-    while (*p != '\0') {
-        if (*p == ',') {
-            if (*(p + 1) != ',')
-                break;
-            p++;
-        }
-        if (q && (q - buf) < buf_size - 1)
-            *q++ = *p;
-        p++;
-    }
-    if (q)
-        *q = '\0';
-
-    return p;
-}
-
-int get_param_value(char *buf, int buf_size,
-                    const char *tag, const char *str)
+int get_next_param_value(char *buf, int buf_size,
+                         const char *tag, const char **pstr)
 {
     const char *p;
     char option[128];
 
 {
     const char *p;
     char option[128];
 
-    p = str;
+    p = *pstr;
     for(;;) {
         p = get_opt_name(option, sizeof(option), p, '=');
         if (*p != '=')
             break;
         p++;
         if (!strcmp(tag, option)) {
     for(;;) {
         p = get_opt_name(option, sizeof(option), p, '=');
         if (*p != '=')
             break;
         p++;
         if (!strcmp(tag, option)) {
-            (void)get_opt_value(buf, buf_size, p);
+            *pstr = get_opt_value(buf, buf_size, p);
+            if (**pstr == ',') {
+                (*pstr)++;
+            }
             return strlen(buf);
         } else {
             p = get_opt_value(NULL, 0, p);
             return strlen(buf);
         } else {
             p = get_opt_value(NULL, 0, p);
@@ -1869,45 +1838,40 @@ int get_param_value(char *buf, int buf_size,
     return 0;
 }
 
     return 0;
 }
 
-int check_params(const char * const *params, const char *str)
+int get_param_value(char *buf, int buf_size,
+                    const char *tag, const char *str)
+{
+    return get_next_param_value(buf, buf_size, tag, &str);
+}
+
+int check_params(char *buf, int buf_size,
+                 const char * const *params, const char *str)
 {
 {
-    int name_buf_size = 1;
     const char *p;
     const char *p;
-    char *name_buf;
-    int i, len;
-    int ret = 0;
-
-    for (i = 0; params[i] != NULL; i++) {
-        len = strlen(params[i]) + 1;
-        if (len > name_buf_size) {
-            name_buf_size = len;
-        }
-    }
-    name_buf = qemu_malloc(name_buf_size);
+    int i;
 
     p = str;
     while (*p != '\0') {
 
     p = str;
     while (*p != '\0') {
-        p = get_opt_name(name_buf, name_buf_size, p, '=');
+        p = get_opt_name(buf, buf_size, p, '=');
         if (*p != '=') {
         if (*p != '=') {
-            ret = -1;
-            break;
+            return -1;
         }
         p++;
         }
         p++;
-        for(i = 0; params[i] != NULL; i++)
-            if (!strcmp(params[i], name_buf))
+        for (i = 0; params[i] != NULL; i++) {
+            if (!strcmp(params[i], buf)) {
                 break;
                 break;
+            }
+        }
         if (params[i] == NULL) {
         if (params[i] == NULL) {
-            ret = -1;
-            break;
+            return -1;
         }
         p = get_opt_value(NULL, 0, p);
         }
         p = get_opt_value(NULL, 0, p);
-        if (*p != ',')
+        if (*p != ',') {
             break;
             break;
+        }
         p++;
     }
         p++;
     }
-
-    qemu_free(name_buf);
-    return ret;
+    return 0;
 }
 
 /***********************************************************/
 }
 
 /***********************************************************/
@@ -2252,15 +2216,17 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque)
     int index;
     int cache;
     int bdrv_flags, onerror;
     int index;
     int cache;
     int bdrv_flags, onerror;
+    const char *devaddr;
     int drives_table_idx;
     char *str = arg->opt;
     static const char * const params[] = { "bus", "unit", "if", "index",
                                            "cyls", "heads", "secs", "trans",
                                            "media", "snapshot", "file",
     int drives_table_idx;
     char *str = arg->opt;
     static const char * const params[] = { "bus", "unit", "if", "index",
                                            "cyls", "heads", "secs", "trans",
                                            "media", "snapshot", "file",
-                                           "cache", "format", "serial", "werror",
+                                           "cache", "format", "serial",
+                                           "werror", "addr",
                                            NULL };
 
                                            NULL };
 
-    if (check_params(params, str) < 0) {
+    if (check_params(buf, sizeof(buf), params, str) < 0) {
          fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n",
                          buf, str);
          return -1;
          fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n",
                          buf, str);
          return -1;
@@ -2471,6 +2437,15 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque)
         }
     }
 
         }
     }
 
+    devaddr = NULL;
+    if (get_param_value(buf, sizeof(buf), "addr", str)) {
+        if (type != IF_VIRTIO) {
+            fprintf(stderr, "addr is not supported by in '%s'\n", str);
+            return -1;
+        }
+        devaddr = strdup(buf);
+    }
+
     /* compute bus and unit according index */
 
     if (index != -1) {
     /* compute bus and unit according index */
 
     if (index != -1) {
@@ -2532,12 +2507,13 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque)
     bdrv = bdrv_new(buf);
     drives_table_idx = drive_get_free_idx();
     drives_table[drives_table_idx].bdrv = bdrv;
     bdrv = bdrv_new(buf);
     drives_table_idx = drive_get_free_idx();
     drives_table[drives_table_idx].bdrv = bdrv;
+    drives_table[drives_table_idx].devaddr = devaddr;
     drives_table[drives_table_idx].type = type;
     drives_table[drives_table_idx].bus = bus_id;
     drives_table[drives_table_idx].unit = unit_id;
     drives_table[drives_table_idx].onerror = onerror;
     drives_table[drives_table_idx].drive_opt_idx = arg - drives_opt;
     drives_table[drives_table_idx].type = type;
     drives_table[drives_table_idx].bus = bus_id;
     drives_table[drives_table_idx].unit = unit_id;
     drives_table[drives_table_idx].onerror = onerror;
     drives_table[drives_table_idx].drive_opt_idx = arg - drives_opt;
-    strncpy(drives_table[nb_drives].serial, serial, sizeof(serial));
+    strncpy(drives_table[drives_table_idx].serial, serial, sizeof(serial));
     nb_drives++;
 
     switch(type) {
     nb_drives++;
 
     switch(type) {
@@ -2566,6 +2542,8 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque)
     case IF_MTD:
     case IF_VIRTIO:
         break;
     case IF_MTD:
     case IF_VIRTIO:
         break;
+    case IF_COUNT:
+        abort();
     }
     if (!file[0])
         return -2;
     }
     if (!file[0])
         return -2;
@@ -2741,7 +2719,7 @@ static int usb_device_add(const char *devname, int is_hotplug)
     } else if (strstart(devname, "net:", &p)) {
         int nic = nb_nics;
 
     } else if (strstart(devname, "net:", &p)) {
         int nic = nb_nics;
 
-        if (net_client_init("nic", p) < 0)
+        if (net_client_init(NULL, "nic", p) < 0)
             return -1;
         nd_table[nic].model = "usb";
         dev = usb_net_init(&nd_table[nic]);
             return -1;
         nd_table[nic].model = "usb";
         dev = usb_net_init(&nd_table[nic]);
@@ -2856,11 +2834,11 @@ void usb_info(Monitor *mon)
 /* PCMCIA/Cardbus */
 
 static struct pcmcia_socket_entry_s {
 /* PCMCIA/Cardbus */
 
 static struct pcmcia_socket_entry_s {
-    struct pcmcia_socket_s *socket;
+    PCMCIASocket *socket;
     struct pcmcia_socket_entry_s *next;
 } *pcmcia_sockets = 0;
 
     struct pcmcia_socket_entry_s *next;
 } *pcmcia_sockets = 0;
 
-void pcmcia_socket_register(struct pcmcia_socket_s *socket)
+void pcmcia_socket_register(PCMCIASocket *socket)
 {
     struct pcmcia_socket_entry_s *entry;
 
 {
     struct pcmcia_socket_entry_s *entry;
 
@@ -2870,7 +2848,7 @@ void pcmcia_socket_register(struct pcmcia_socket_s *socket)
     pcmcia_sockets = entry;
 }
 
     pcmcia_sockets = entry;
 }
 
-void pcmcia_socket_unregister(struct pcmcia_socket_s *socket)
+void pcmcia_socket_unregister(PCMCIASocket *socket)
 {
     struct pcmcia_socket_entry_s *entry, **ptr;
 
 {
     struct pcmcia_socket_entry_s *entry, **ptr;
 
@@ -3229,7 +3207,7 @@ static int ram_save_block(QEMUFile *f)
     return found;
 }
 
     return found;
 }
 
-static ram_addr_t ram_save_threshold = 10;
+static uint64_t bytes_transferred = 0;
 
 static ram_addr_t ram_save_remaining(void)
 {
 
 static ram_addr_t ram_save_remaining(void)
 {
@@ -3244,9 +3222,32 @@ static ram_addr_t ram_save_remaining(void)
     return count;
 }
 
     return count;
 }
 
+uint64_t ram_bytes_remaining(void)
+{
+    return ram_save_remaining() * TARGET_PAGE_SIZE;
+}
+
+uint64_t ram_bytes_transferred(void)
+{
+    return bytes_transferred;
+}
+
+uint64_t ram_bytes_total(void)
+{
+    return last_ram_offset;
+}
+
 static int ram_save_live(QEMUFile *f, int stage, void *opaque)
 {
     ram_addr_t addr;
 static int ram_save_live(QEMUFile *f, int stage, void *opaque)
 {
     ram_addr_t addr;
+    uint64_t bytes_transferred_last;
+    double bwidth = 0;
+    uint64_t expected_time = 0;
+
+    if (cpu_physical_sync_dirty_bitmap(0, TARGET_PHYS_ADDR_MAX) != 0) {
+        qemu_file_set_error(f);
+        return 0;
+    }
 
     if (stage == 1) {
         /* Make sure all dirty bits are set */
 
     if (stage == 1) {
         /* Make sure all dirty bits are set */
@@ -3254,33 +3255,49 @@ static int ram_save_live(QEMUFile *f, int stage, void *opaque)
             if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
                 cpu_physical_memory_set_dirty(addr);
         }
             if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
                 cpu_physical_memory_set_dirty(addr);
         }
-        
+
         /* Enable dirty memory tracking */
         cpu_physical_memory_set_dirty_tracking(1);
 
         qemu_put_be64(f, last_ram_offset | RAM_SAVE_FLAG_MEM_SIZE);
     }
 
         /* Enable dirty memory tracking */
         cpu_physical_memory_set_dirty_tracking(1);
 
         qemu_put_be64(f, last_ram_offset | RAM_SAVE_FLAG_MEM_SIZE);
     }
 
+    bytes_transferred_last = bytes_transferred;
+    bwidth = get_clock();
+
     while (!qemu_file_rate_limit(f)) {
         int ret;
 
         ret = ram_save_block(f);
     while (!qemu_file_rate_limit(f)) {
         int ret;
 
         ret = ram_save_block(f);
+        bytes_transferred += ret * TARGET_PAGE_SIZE;
         if (ret == 0) /* no more blocks */
             break;
     }
 
         if (ret == 0) /* no more blocks */
             break;
     }
 
+    bwidth = get_clock() - bwidth;
+    bwidth = (bytes_transferred - bytes_transferred_last) / bwidth;
+
+    /* if we haven't transferred anything this round, force expected_time to a
+     * a very high value, but without crashing */
+    if (bwidth == 0)
+        bwidth = 0.000001;
+
     /* try transferring iterative blocks of memory */
 
     if (stage == 3) {
 
         /* flush all remaining blocks regardless of rate limiting */
     /* try transferring iterative blocks of memory */
 
     if (stage == 3) {
 
         /* flush all remaining blocks regardless of rate limiting */
-        while (ram_save_block(f) != 0);
+        while (ram_save_block(f) != 0) {
+            bytes_transferred += TARGET_PAGE_SIZE;
+        }
         cpu_physical_memory_set_dirty_tracking(0);
     }
 
     qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
 
         cpu_physical_memory_set_dirty_tracking(0);
     }
 
     qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
 
-    return (stage == 2) && (ram_save_remaining() < ram_save_threshold);
+    expected_time = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth;
+
+    return (stage == 2) && (expected_time <= migrate_max_downtime());
 }
 
 static int ram_load_dead(QEMUFile *f, void *opaque)
 }
 
 static int ram_load_dead(QEMUFile *f, void *opaque)
@@ -3349,6 +3366,12 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
         if (flags & RAM_SAVE_FLAG_COMPRESS) {
             uint8_t ch = qemu_get_byte(f);
             memset(qemu_get_ram_ptr(addr), ch, TARGET_PAGE_SIZE);
         if (flags & RAM_SAVE_FLAG_COMPRESS) {
             uint8_t ch = qemu_get_byte(f);
             memset(qemu_get_ram_ptr(addr), ch, TARGET_PAGE_SIZE);
+#ifndef _WIN32
+            if (ch == 0 &&
+                (!kvm_enabled() || kvm_has_sync_mmu())) {
+                madvise(qemu_get_ram_ptr(addr), TARGET_PAGE_SIZE, MADV_DONTNEED);
+            }
+#endif
         } else if (flags & RAM_SAVE_FLAG_PAGE)
             qemu_get_buffer(f, qemu_get_ram_ptr(addr), TARGET_PAGE_SIZE);
     } while (!(flags & RAM_SAVE_FLAG_EOS));
         } else if (flags & RAM_SAVE_FLAG_PAGE)
             qemu_get_buffer(f, qemu_get_ram_ptr(addr), TARGET_PAGE_SIZE);
     } while (!(flags & RAM_SAVE_FLAG_EOS));
@@ -3493,6 +3516,18 @@ static QEMUMachine *find_machine(const char *name)
     return NULL;
 }
 
     return NULL;
 }
 
+static QEMUMachine *find_default_machine(void)
+{
+    QEMUMachine *m;
+
+    for(m = first_machine; m != NULL; m = m->next) {
+        if (m->is_default) {
+            return m;
+        }
+    }
+    return NULL;
+}
+
 /***********************************************************/
 /* main execution loop */
 
 /***********************************************************/
 /* main execution loop */
 
@@ -3575,6 +3610,7 @@ void vm_start(void)
 typedef struct QEMUResetEntry {
     QEMUResetHandler *func;
     void *opaque;
 typedef struct QEMUResetEntry {
     QEMUResetHandler *func;
     void *opaque;
+    int order;
     struct QEMUResetEntry *next;
 } QEMUResetEntry;
 
     struct QEMUResetEntry *next;
 } QEMUResetEntry;
 
@@ -3630,16 +3666,18 @@ static void do_vm_stop(int reason)
     }
 }
 
     }
 }
 
-void qemu_register_reset(QEMUResetHandler *func, void *opaque)
+void qemu_register_reset(QEMUResetHandler *func, int order, void *opaque)
 {
     QEMUResetEntry **pre, *re;
 
     pre = &first_reset_entry;
 {
     QEMUResetEntry **pre, *re;
 
     pre = &first_reset_entry;
-    while (*pre != NULL)
+    while (*pre != NULL && (*pre)->order >= order) {
         pre = &(*pre)->next;
         pre = &(*pre)->next;
+    }
     re = qemu_mallocz(sizeof(QEMUResetEntry));
     re->func = func;
     re->opaque = opaque;
     re = qemu_mallocz(sizeof(QEMUResetEntry));
     re->func = func;
     re->opaque = opaque;
+    re->order = order;
     re->next = NULL;
     *pre = re;
 }
     re->next = NULL;
     *pre = re;
 }
@@ -3652,8 +3690,6 @@ void qemu_system_reset(void)
     for(re = first_reset_entry; re != NULL; re = re->next) {
         re->func(re->opaque);
     }
     for(re = first_reset_entry; re != NULL; re = re->next) {
         re->func(re->opaque);
     }
-    if (kvm_enabled())
-        kvm_sync_vcpus();
 }
 
 void qemu_system_reset_request(void)
 }
 
 void qemu_system_reset_request(void)
@@ -4228,11 +4264,8 @@ void main_loop_wait(int timeout)
     tv.tv_sec = timeout / 1000;
     tv.tv_usec = (timeout % 1000) * 1000;
 
     tv.tv_sec = timeout / 1000;
     tv.tv_usec = (timeout % 1000) * 1000;
 
-#if defined(CONFIG_SLIRP)
-    if (slirp_is_inited()) {
-        slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
-    }
-#endif
+    slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
+
     qemu_mutex_unlock_iothread();
     ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
     qemu_mutex_lock_iothread();
     qemu_mutex_unlock_iothread();
     ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
     qemu_mutex_lock_iothread();
@@ -4259,16 +4292,8 @@ void main_loop_wait(int timeout)
                 pioh = &ioh->next;
         }
     }
                 pioh = &ioh->next;
         }
     }
-#if defined(CONFIG_SLIRP)
-    if (slirp_is_inited()) {
-        if (ret < 0) {
-            FD_ZERO(&rfds);
-            FD_ZERO(&wfds);
-            FD_ZERO(&xfds);
-        }
-        slirp_select_poll(&rfds, &wfds, &xfds);
-    }
-#endif
+
+    slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0));
 
     /* rearm timer, if not periodic */
     if (alarm_timer->flags & ALARM_FLAG_EXPIRED) {
 
     /* rearm timer, if not periodic */
     if (alarm_timer->flags & ALARM_FLAG_EXPIRED) {
@@ -4383,6 +4408,7 @@ static int tcg_has_work(void)
 
 static int qemu_calculate_timeout(void)
 {
 
 static int qemu_calculate_timeout(void)
 {
+#ifndef CONFIG_IOTHREAD
     int timeout;
 
     if (!vm_running)
     int timeout;
 
     if (!vm_running)
@@ -4428,6 +4454,9 @@ static int qemu_calculate_timeout(void)
     }
 
     return timeout;
     }
 
     return timeout;
+#else /* CONFIG_IOTHREAD */
+    return 1000;
+#endif
 }
 
 static int vm_can_run(void)
 }
 
 static int vm_can_run(void)
@@ -4463,11 +4492,7 @@ static void main_loop(void)
 #ifdef CONFIG_PROFILER
             ti = profile_getclock();
 #endif
 #ifdef CONFIG_PROFILER
             ti = profile_getclock();
 #endif
-#ifdef CONFIG_IOTHREAD
-            main_loop_wait(1000);
-#else
             main_loop_wait(qemu_calculate_timeout());
             main_loop_wait(qemu_calculate_timeout());
-#endif
 #ifdef CONFIG_PROFILER
             dev_time += profile_getclock() - ti;
 #endif
 #ifdef CONFIG_PROFILER
             dev_time += profile_getclock() - ti;
 #endif
@@ -4778,7 +4803,12 @@ static void termsig_handler(int signal)
     qemu_system_shutdown_request();
 }
 
     qemu_system_shutdown_request();
 }
 
-static void termsig_setup(void)
+static void sigchld_handler(int signal)
+{
+    waitpid(-1, NULL, WNOHANG);
+}
+
+static void sighandler_setup(void)
 {
     struct sigaction act;
 
 {
     struct sigaction act;
 
@@ -4787,15 +4817,141 @@ static void termsig_setup(void)
     sigaction(SIGINT,  &act, NULL);
     sigaction(SIGHUP,  &act, NULL);
     sigaction(SIGTERM, &act, NULL);
     sigaction(SIGINT,  &act, NULL);
     sigaction(SIGHUP,  &act, NULL);
     sigaction(SIGTERM, &act, NULL);
+
+    act.sa_handler = sigchld_handler;
+    act.sa_flags = SA_NOCLDSTOP;
+    sigaction(SIGCHLD, &act, NULL);
+}
+
+#endif
+
+#ifdef _WIN32
+/* Look for support files in the same directory as the executable.  */
+static char *find_datadir(const char *argv0)
+{
+    char *p;
+    char buf[MAX_PATH];
+    DWORD len;
+
+    len = GetModuleFileName(NULL, buf, sizeof(buf) - 1);
+    if (len == 0) {
+        return NULL;
+    }
+
+    buf[len] = 0;
+    p = buf + len - 1;
+    while (p != buf && *p != '\\')
+        p--;
+    *p = 0;
+    if (access(buf, R_OK) == 0) {
+        return qemu_strdup(buf);
+    }
+    return NULL;
 }
 }
+#else /* !_WIN32 */
+
+/* Find a likely location for support files using the location of the binary.
+   For installed binaries this will be "$bindir/../share/qemu".  When
+   running from the build tree this will be "$bindir/../pc-bios".  */
+#define SHARE_SUFFIX "/share/qemu"
+#define BUILD_SUFFIX "/pc-bios"
+static char *find_datadir(const char *argv0)
+{
+    char *dir;
+    char *p = NULL;
+    char *res;
+#ifdef PATH_MAX
+    char buf[PATH_MAX];
+#endif
+    size_t max_len;
 
 
+#if defined(__linux__)
+    {
+        int len;
+        len = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
+        if (len > 0) {
+            buf[len] = 0;
+            p = buf;
+        }
+    }
+#elif defined(__FreeBSD__)
+    {
+        int len;
+        len = readlink("/proc/curproc/file", buf, sizeof(buf) - 1);
+        if (len > 0) {
+            buf[len] = 0;
+            p = buf;
+        }
+    }
+#endif
+    /* If we don't have any way of figuring out the actual executable
+       location then try argv[0].  */
+    if (!p) {
+#ifdef PATH_MAX
+        p = buf;
+#endif
+        p = realpath(argv0, p);
+        if (!p) {
+            return NULL;
+        }
+    }
+    dir = dirname(p);
+    dir = dirname(dir);
+
+    max_len = strlen(dir) +
+        MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1;
+    res = qemu_mallocz(max_len);
+    snprintf(res, max_len, "%s%s", dir, SHARE_SUFFIX);
+    if (access(res, R_OK)) {
+        snprintf(res, max_len, "%s%s", dir, BUILD_SUFFIX);
+        if (access(res, R_OK)) {
+            qemu_free(res);
+            res = NULL;
+        }
+    }
+#ifndef PATH_MAX
+    free(p);
+#endif
+    return res;
+}
+#undef SHARE_SUFFIX
+#undef BUILD_SUFFIX
 #endif
 
 #endif
 
+char *qemu_find_file(int type, const char *name)
+{
+    int len;
+    const char *subdir;
+    char *buf;
+
+    /* If name contains path separators then try it as a straight path.  */
+    if ((strchr(name, '/') || strchr(name, '\\'))
+        && access(name, R_OK) == 0) {
+        return strdup(name);
+    }
+    switch (type) {
+    case QEMU_FILE_TYPE_BIOS:
+        subdir = "";
+        break;
+    case QEMU_FILE_TYPE_KEYMAP:
+        subdir = "keymaps/";
+        break;
+    default:
+        abort();
+    }
+    len = strlen(data_dir) + strlen(name) + strlen(subdir) + 2;
+    buf = qemu_mallocz(len);
+    snprintf(buf, len, "%s/%s%s", data_dir, subdir, name);
+    if (access(buf, R_OK)) {
+        qemu_free(buf);
+        return NULL;
+    }
+    return buf;
+}
+
 int main(int argc, char **argv, char **envp)
 {
 int main(int argc, char **argv, char **envp)
 {
-#ifdef CONFIG_GDBSTUB
     const char *gdbstub_dev = NULL;
     const char *gdbstub_dev = NULL;
-#endif
     uint32_t boot_devices_bitmap = 0;
     int i;
     int snapshot, linux_boot, net_boot;
     uint32_t boot_devices_bitmap = 0;
     int i;
     int snapshot, linux_boot, net_boot;
@@ -4838,6 +4994,7 @@ int main(int argc, char **argv, char **envp)
     const char *run_as = NULL;
 #endif
     CPUState *env;
     const char *run_as = NULL;
 #endif
     CPUState *env;
+    int show_vnc_port = 0;
 
     qemu_cache_utils_init(envp);
 
 
     qemu_cache_utils_init(envp);
 
@@ -4872,15 +5029,12 @@ int main(int argc, char **argv, char **envp)
     }
 #endif
 
     }
 #endif
 
-    register_machines();
-    machine = first_machine;
+    module_call_init(MODULE_INIT_MACHINE);
+    machine = find_default_machine();
     cpu_model = NULL;
     initrd_filename = NULL;
     ram_size = 0;
     cpu_model = NULL;
     initrd_filename = NULL;
     ram_size = 0;
-    vga_ram_size = VGA_RAM_SIZE;
     snapshot = 0;
     snapshot = 0;
-    nographic = 0;
-    curses = 0;
     kernel_filename = NULL;
     kernel_cmdline = "";
     cyls = heads = secs = 0;
     kernel_filename = NULL;
     kernel_cmdline = "";
     cyls = heads = secs = 0;
@@ -4967,7 +5121,7 @@ int main(int argc, char **argv, char **envp)
                     for(m = first_machine; m != NULL; m = m->next) {
                         printf("%-10s %s%s\n",
                                m->name, m->desc,
                     for(m = first_machine; m != NULL; m = m->next) {
                         printf("%-10s %s%s\n",
                                m->name, m->desc,
-                               m == first_machine ? " (default)" : "");
+                               m->is_default ? " (default)" : "");
                     }
                     exit(*optarg != '?');
                 }
                     }
                     exit(*optarg != '?');
                 }
@@ -5072,11 +5226,11 @@ int main(int argc, char **argv, char **envp)
                 numa_add(optarg);
                 break;
             case QEMU_OPTION_nographic:
                 numa_add(optarg);
                 break;
             case QEMU_OPTION_nographic:
-                nographic = 1;
+                display_type = DT_NOGRAPHIC;
                 break;
 #ifdef CONFIG_CURSES
             case QEMU_OPTION_curses:
                 break;
 #ifdef CONFIG_CURSES
             case QEMU_OPTION_curses:
-                curses = 1;
+                display_type = DT_CURSES;
                 break;
 #endif
             case QEMU_OPTION_portrait:
                 break;
 #endif
             case QEMU_OPTION_portrait:
@@ -5141,18 +5295,18 @@ int main(int argc, char **argv, char **envp)
                 break;
 #ifdef CONFIG_SLIRP
             case QEMU_OPTION_tftp:
                 break;
 #ifdef CONFIG_SLIRP
             case QEMU_OPTION_tftp:
-               tftp_prefix = optarg;
+                legacy_tftp_prefix = optarg;
                 break;
             case QEMU_OPTION_bootp:
                 break;
             case QEMU_OPTION_bootp:
-                bootp_filename = optarg;
+                legacy_bootp_filename = optarg;
                 break;
 #ifndef _WIN32
             case QEMU_OPTION_smb:
                 break;
 #ifndef _WIN32
             case QEMU_OPTION_smb:
-               net_slirp_smb(optarg);
+                net_slirp_smb(optarg);
                 break;
 #endif
             case QEMU_OPTION_redir:
                 break;
 #endif
             case QEMU_OPTION_redir:
-                net_slirp_redir(NULL, optarg);
+                net_slirp_redir(optarg);
                 break;
 #endif
             case QEMU_OPTION_bt:
                 break;
 #endif
             case QEMU_OPTION_bt:
@@ -5227,16 +5381,14 @@ int main(int argc, char **argv, char **envp)
                     cpu_set_log(mask);
                 }
                 break;
                     cpu_set_log(mask);
                 }
                 break;
-#ifdef CONFIG_GDBSTUB
             case QEMU_OPTION_s:
                 gdbstub_dev = "tcp::" DEFAULT_GDBSTUB_PORT;
                 break;
             case QEMU_OPTION_gdb:
                 gdbstub_dev = optarg;
                 break;
             case QEMU_OPTION_s:
                 gdbstub_dev = "tcp::" DEFAULT_GDBSTUB_PORT;
                 break;
             case QEMU_OPTION_gdb:
                 gdbstub_dev = optarg;
                 break;
-#endif
             case QEMU_OPTION_L:
             case QEMU_OPTION_L:
-                bios_dir = optarg;
+                data_dir = optarg;
                 break;
             case QEMU_OPTION_bios:
                 bios_name = optarg;
                 break;
             case QEMU_OPTION_bios:
                 bios_name = optarg;
@@ -5357,7 +5509,7 @@ int main(int argc, char **argv, char **envp)
                 no_quit = 1;
                 break;
             case QEMU_OPTION_sdl:
                 no_quit = 1;
                 break;
             case QEMU_OPTION_sdl:
-                sdl = 1;
+                display_type = DT_SDL;
                 break;
 #endif
             case QEMU_OPTION_pidfile:
                 break;
 #endif
             case QEMU_OPTION_pidfile:
@@ -5419,6 +5571,7 @@ int main(int argc, char **argv, char **envp)
                 }
                 break;
            case QEMU_OPTION_vnc:
                 }
                 break;
            case QEMU_OPTION_vnc:
+                display_type = DT_VNC;
                vnc_display = optarg;
                break;
 #ifdef TARGET_I386
                vnc_display = optarg;
                break;
 #ifdef TARGET_I386
@@ -5428,6 +5581,9 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_no_hpet:
                 no_hpet = 1;
                 break;
             case QEMU_OPTION_no_hpet:
                 no_hpet = 1;
                 break;
+            case QEMU_OPTION_no_virtio_balloon:
+                no_virtio_balloon = 1;
+                break;
 #endif
             case QEMU_OPTION_no_reboot:
                 no_reboot = 1;
 #endif
             case QEMU_OPTION_no_reboot:
                 no_reboot = 1;
@@ -5561,6 +5717,16 @@ int main(int argc, char **argv, char **envp)
         }
     }
 
         }
     }
 
+    /* If no data_dir is specified then try to find it relative to the
+       executable path.  */
+    if (!data_dir) {
+        data_dir = find_datadir(argv[0]);
+    }
+    /* If all else fails use the install patch specified when building.  */
+    if (!data_dir) {
+        data_dir = CONFIG_QEMU_SHAREDIR;
+    }
+
 #if defined(CONFIG_KVM) && defined(CONFIG_KQEMU)
     if (kvm_allowed && kqemu_allowed) {
         fprintf(stderr,
 #if defined(CONFIG_KVM) && defined(CONFIG_KQEMU)
     if (kvm_allowed && kqemu_allowed) {
         fprintf(stderr,
@@ -5577,7 +5743,7 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
 
         exit(1);
     }
 
-    if (nographic) {
+    if (display_type == DT_NOGRAPHIC) {
        if (serial_device_index == 0)
            serial_devices[0] = "stdio";
        if (parallel_device_index == 0)
        if (serial_device_index == 0)
            serial_devices[0] = "stdio";
        if (parallel_device_index == 0)
@@ -5649,7 +5815,6 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
     linux_boot = (kernel_filename != NULL);
         exit(1);
     }
     linux_boot = (kernel_filename != NULL);
-    net_boot = (boot_devices_bitmap >> ('n' - 'a')) & 0xF;
 
     if (!linux_boot && *kernel_cmdline != '\0') {
         fprintf(stderr, "-append only allowed with -kernel option\n");
 
     if (!linux_boot && *kernel_cmdline != '\0') {
         fprintf(stderr, "-append only allowed with -kernel option\n");
@@ -5697,36 +5862,11 @@ int main(int argc, char **argv, char **envp)
         if (net_client_parse(net_clients[i]) < 0)
             exit(1);
     }
         if (net_client_parse(net_clients[i]) < 0)
             exit(1);
     }
-    net_client_check();
 
 
-#ifdef TARGET_I386
-    /* XXX: this should be moved in the PC machine instantiation code */
-    if (net_boot != 0) {
-        int netroms = 0;
-       for (i = 0; i < nb_nics && i < 4; i++) {
-           const char *model = nd_table[i].model;
-           char buf[1024];
-            if (net_boot & (1 << i)) {
-                if (model == NULL)
-                    model = "ne2k_pci";
-                snprintf(buf, sizeof(buf), "%s/pxe-%s.bin", bios_dir, model);
-                if (get_image_size(buf) > 0) {
-                    if (nb_option_roms >= MAX_OPTION_ROMS) {
-                        fprintf(stderr, "Too many option ROMs\n");
-                        exit(1);
-                    }
-                    option_rom[nb_option_roms] = strdup(buf);
-                    nb_option_roms++;
-                    netroms++;
-                }
-            }
-       }
-       if (netroms == 0) {
-           fprintf(stderr, "No valid PXE rom found for network device\n");
-           exit(1);
-       }
-    }
-#endif
+    net_boot = (boot_devices_bitmap >> ('n' - 'a')) & 0xF;
+    net_set_boot_mask(net_boot);
+
+    net_client_check();
 
     /* init the bluetooth world */
     for (i = 0; i < nb_bt_opts; i++)
 
     /* init the bluetooth world */
     for (i = 0; i < nb_bt_opts; i++)
@@ -5741,7 +5881,7 @@ int main(int argc, char **argv, char **envp)
     /* FIXME: This is a nasty hack because kqemu can't cope with dynamic
        guest ram allocation.  It needs to go away.  */
     if (kqemu_allowed) {
     /* FIXME: This is a nasty hack because kqemu can't cope with dynamic
        guest ram allocation.  It needs to go away.  */
     if (kqemu_allowed) {
-        kqemu_phys_ram_size = ram_size + VGA_RAM_SIZE + 4 * 1024 * 1024;
+        kqemu_phys_ram_size = ram_size + 8 * 1024 * 1024 + 4 * 1024 * 1024;
         kqemu_phys_ram_base = qemu_vmalloc(kqemu_phys_ram_size);
         if (!kqemu_phys_ram_base) {
             fprintf(stderr, "Could not allocate physical memory\n");
         kqemu_phys_ram_base = qemu_vmalloc(kqemu_phys_ram_size);
         if (!kqemu_phys_ram_base) {
             fprintf(stderr, "Could not allocate physical memory\n");
@@ -5754,7 +5894,6 @@ int main(int argc, char **argv, char **envp)
     cpu_exec_init_all(tb_size * 1024 * 1024);
 
     bdrv_init();
     cpu_exec_init_all(tb_size * 1024 * 1024);
 
     bdrv_init();
-    dma_helper_init();
 
     /* we always create the cdrom drive, even if no disk is there */
 
 
     /* we always create the cdrom drive, even if no disk is there */
 
@@ -5782,7 +5921,7 @@ int main(int argc, char **argv, char **envp)
 
 #ifndef _WIN32
     /* must be after terminal init, SDL library changes signal handlers */
 
 #ifndef _WIN32
     /* must be after terminal init, SDL library changes signal handlers */
-    termsig_setup();
+    sighandler_setup();
 #endif
 
     /* Maintain compatibility with multiple stdio monitors */
 #endif
 
     /* Maintain compatibility with multiple stdio monitors */
@@ -5902,7 +6041,9 @@ int main(int argc, char **argv, char **envp)
         }
     }
 
         }
     }
 
-    machine->init(ram_size, vga_ram_size, boot_devices,
+    module_call_init(MODULE_INIT_DEVICE);
+
+    machine->init(ram_size, boot_devices,
                   kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
 
 
                   kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
 
 
@@ -5941,33 +6082,46 @@ int main(int argc, char **argv, char **envp)
         dumb_display_init();
     /* just use the first displaystate for the moment */
     ds = display_state;
         dumb_display_init();
     /* just use the first displaystate for the moment */
     ds = display_state;
-    /* terminal init */
-    if (nographic) {
-        if (curses) {
-            fprintf(stderr, "fatal: -nographic can't be used with -curses\n");
-            exit(1);
-        }
-    } else { 
+
+    if (display_type == DT_DEFAULT) {
+#if defined(CONFIG_SDL) || defined(CONFIG_COCOA)
+        display_type = DT_SDL;
+#else
+        display_type = DT_VNC;
+        vnc_display = "localhost:0,to=99";
+        show_vnc_port = 1;
+#endif
+    }
+        
+
+    switch (display_type) {
+    case DT_NOGRAPHIC:
+        break;
 #if defined(CONFIG_CURSES)
 #if defined(CONFIG_CURSES)
-            if (curses) {
-                /* At the moment curses cannot be used with other displays */
-                curses_display_init(ds, full_screen);
-            } else
+    case DT_CURSES:
+        curses_display_init(ds, full_screen);
+        break;
 #endif
 #endif
-            {
-                if (vnc_display != NULL) {
-                    vnc_display_init(ds);
-                    if (vnc_display_open(ds, vnc_display) < 0)
-                        exit(1);
-                }
 #if defined(CONFIG_SDL)
 #if defined(CONFIG_SDL)
-                if (sdl || !vnc_display)
-                    sdl_display_init(ds, full_screen, no_frame);
+    case DT_SDL:
+        sdl_display_init(ds, full_screen, no_frame);
+        break;
 #elif defined(CONFIG_COCOA)
 #elif defined(CONFIG_COCOA)
-                if (sdl || !vnc_display)
-                    cocoa_display_init(ds, full_screen);
+    case DT_SDL:
+        cocoa_display_init(ds, full_screen);
+        break;
 #endif
 #endif
-            }
+    case DT_VNC:
+        vnc_display_init(ds);
+        if (vnc_display_open(ds, vnc_display) < 0)
+            exit(1);
+
+        if (show_vnc_port) {
+            printf("VNC server running on `%s'\n", vnc_display_local_addr(ds));
+        }
+        break;
+    default:
+        break;
     }
     dpy_resize(ds);
 
     }
     dpy_resize(ds);
 
@@ -5980,7 +6134,7 @@ int main(int argc, char **argv, char **envp)
         dcl = dcl->next;
     }
 
         dcl = dcl->next;
     }
 
-    if (nographic || (vnc_display && !sdl)) {
+    if (display_type == DT_NOGRAPHIC || display_type == DT_VNC) {
         nographic_timer = qemu_new_timer(rt_clock, nographic_update, NULL);
         qemu_mod_timer(nographic_timer, qemu_get_clock(rt_clock));
     }
         nographic_timer = qemu_new_timer(rt_clock, nographic_update, NULL);
         qemu_mod_timer(nographic_timer, qemu_get_clock(rt_clock));
     }
@@ -5994,8 +6148,6 @@ int main(int argc, char **argv, char **envp)
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         const char *devname = serial_devices[i];
         if (devname && strcmp(devname, "none")) {
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         const char *devname = serial_devices[i];
         if (devname && strcmp(devname, "none")) {
-            char label[32];
-            snprintf(label, sizeof(label), "serial%d", i);
             if (strstart(devname, "vc", 0))
                 qemu_chr_printf(serial_hds[i], "serial%d console\r\n", i);
         }
             if (strstart(devname, "vc", 0))
                 qemu_chr_printf(serial_hds[i], "serial%d console\r\n", i);
         }
@@ -6004,8 +6156,6 @@ int main(int argc, char **argv, char **envp)
     for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
         const char *devname = parallel_devices[i];
         if (devname && strcmp(devname, "none")) {
     for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
         const char *devname = parallel_devices[i];
         if (devname && strcmp(devname, "none")) {
-            char label[32];
-            snprintf(label, sizeof(label), "parallel%d", i);
             if (strstart(devname, "vc", 0))
                 qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i);
         }
             if (strstart(devname, "vc", 0))
                 qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i);
         }
@@ -6014,20 +6164,16 @@ int main(int argc, char **argv, char **envp)
     for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
         const char *devname = virtio_consoles[i];
         if (virtcon_hds[i] && devname) {
     for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
         const char *devname = virtio_consoles[i];
         if (virtcon_hds[i] && devname) {
-            char label[32];
-            snprintf(label, sizeof(label), "virtcon%d", i);
             if (strstart(devname, "vc", 0))
                 qemu_chr_printf(virtcon_hds[i], "virtio console%d\r\n", i);
         }
     }
 
             if (strstart(devname, "vc", 0))
                 qemu_chr_printf(virtcon_hds[i], "virtio console%d\r\n", i);
         }
     }
 
-#ifdef CONFIG_GDBSTUB
     if (gdbstub_dev && gdbserver_start(gdbstub_dev) < 0) {
         fprintf(stderr, "qemu: could not open gdbserver on device '%s'\n",
                 gdbstub_dev);
         exit(1);
     }
     if (gdbstub_dev && gdbserver_start(gdbstub_dev) < 0) {
         fprintf(stderr, "qemu: could not open gdbserver on device '%s'\n",
                 gdbstub_dev);
         exit(1);
     }
-#endif
 
     if (loadvm)
         do_loadvm(cur_mon, loadvm);
 
     if (loadvm)
         do_loadvm(cur_mon, loadvm);
This page took 0.055848 seconds and 4 git commands to generate.