]> git.proxmox.com Git - mirror_qemu.git/blobdiff - vl.c
Bail out if -append or -initrd is specified without -kernel, by
[mirror_qemu.git] / vl.c
diff --git a/vl.c b/vl.c
index 86761ef3d9735647352ec0ecb7a78f3b6e700278..c8db57983b146ffb138896e554fd4771b569899a 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -239,6 +239,14 @@ struct drive_opt {
 static CPUState *cur_cpu;
 static CPUState *next_cpu;
 static int event_pending = 1;
+/* Conversion factor from emulated instructions to virtual clock ticks.  */
+static int icount_time_shift;
+/* Arbitrarily pick 1MIPS as the minimum allowable speed.  */
+#define MAX_ICOUNT_SHIFT 10
+/* Compensate for varying guest execution speed.  */
+static int64_t qemu_icount_bias;
+QEMUTimer *icount_rt_timer;
+QEMUTimer *icount_vm_timer;
 
 #define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
 
@@ -733,9 +741,22 @@ static int64_t get_clock(void)
         return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000);
     }
 }
-
 #endif
 
+/* Return the virtual CPU time, based on the instruction counter.  */
+static int64_t cpu_get_icount(void)
+{
+    int64_t icount;
+    CPUState *env = cpu_single_env;;
+    icount = qemu_icount;
+    if (env) {
+        if (!can_do_io(env))
+            fprintf(stderr, "Bad clock read\n");
+        icount -= (env->icount_decr.u16.low + env->icount_extra);
+    }
+    return qemu_icount_bias + (icount << icount_time_shift);
+}
+
 /***********************************************************/
 /* guest cycle counter */
 
@@ -747,6 +768,9 @@ static int cpu_ticks_enabled;
 /* return the host CPU cycle counter and handle stop/restart */
 int64_t cpu_get_ticks(void)
 {
+    if (use_icount) {
+        return cpu_get_icount();
+    }
     if (!cpu_ticks_enabled) {
         return cpu_ticks_offset;
     } else {
@@ -878,6 +902,71 @@ static void rtc_stop_timer(struct qemu_alarm_timer *t);
 
 #endif /* _WIN32 */
 
+/* Correlation between real and virtual time is always going to be
+   fairly approximate, so ignore small variation.
+   When the guest is idle real and virtual time will be aligned in
+   the IO wait loop.  */
+#define ICOUNT_WOBBLE (QEMU_TIMER_BASE / 10)
+
+static void icount_adjust(void)
+{
+    int64_t cur_time;
+    int64_t cur_icount;
+    int64_t delta;
+    static int64_t last_delta;
+    /* If the VM is not running, then do nothing.  */
+    if (!vm_running)
+        return;
+
+    cur_time = cpu_get_clock();
+    cur_icount = qemu_get_clock(vm_clock);
+    delta = cur_icount - cur_time;
+    /* FIXME: This is a very crude algorithm, somewhat prone to oscillation.  */
+    if (delta > 0
+        && last_delta + ICOUNT_WOBBLE < delta * 2
+        && icount_time_shift > 0) {
+        /* The guest is getting too far ahead.  Slow time down.  */
+        icount_time_shift--;
+    }
+    if (delta < 0
+        && last_delta - ICOUNT_WOBBLE > delta * 2
+        && icount_time_shift < MAX_ICOUNT_SHIFT) {
+        /* The guest is getting too far behind.  Speed time up.  */
+        icount_time_shift++;
+    }
+    last_delta = delta;
+    qemu_icount_bias = cur_icount - (qemu_icount << icount_time_shift);
+}
+
+static void icount_adjust_rt(void * opaque)
+{
+    qemu_mod_timer(icount_rt_timer,
+                   qemu_get_clock(rt_clock) + 1000);
+    icount_adjust();
+}
+
+static void icount_adjust_vm(void * opaque)
+{
+    qemu_mod_timer(icount_vm_timer,
+                   qemu_get_clock(vm_clock) + QEMU_TIMER_BASE / 10);
+    icount_adjust();
+}
+
+static void init_icount_adjust(void)
+{
+    /* Have both realtime and virtual time triggers for speed adjustment.
+       The realtime trigger catches emulated time passing too slowly,
+       the virtual time trigger catches emulated time passing too fast.
+       Realtime triggers occur even when idle, so use them less frequently
+       than VM triggers.  */
+    icount_rt_timer = qemu_new_timer(rt_clock, icount_adjust_rt, NULL);
+    qemu_mod_timer(icount_rt_timer,
+                   qemu_get_clock(rt_clock) + 1000);
+    icount_vm_timer = qemu_new_timer(vm_clock, icount_adjust_vm, NULL);
+    qemu_mod_timer(icount_vm_timer,
+                   qemu_get_clock(vm_clock) + QEMU_TIMER_BASE / 10);
+}
+
 static struct qemu_alarm_timer alarm_timers[] = {
 #ifndef _WIN32
 #ifdef __linux__
@@ -914,6 +1003,7 @@ static void configure_alarms(char const *opt)
     int count = (sizeof(alarm_timers) / sizeof(*alarm_timers)) - 1;
     char *arg;
     char *name;
+    struct qemu_alarm_timer tmp;
 
     if (!strcmp(opt, "?")) {
         show_available_alarms();
@@ -925,8 +1015,6 @@ static void configure_alarms(char const *opt)
     /* Reorder the array */
     name = strtok(arg, ",");
     while (name) {
-        struct qemu_alarm_timer tmp;
-
         for (i = 0; i < count && alarm_timers[i].name; i++) {
             if (!strcmp(alarm_timers[i].name, name))
                 break;
@@ -954,7 +1042,7 @@ next:
     free(arg);
 
     if (cur) {
-       /* Disable remaining timers */
+        /* Disable remaining timers */
         for (i = cur; i < count; i++)
             alarm_timers[i].name = NULL;
     } else {
@@ -1039,9 +1127,15 @@ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
     *pt = ts;
 
     /* Rearm if necessary  */
-    if ((alarm_timer->flags & ALARM_FLAG_EXPIRED) == 0 &&
-        pt == &active_timers[ts->clock->type])
-        qemu_rearm_alarm_timer(alarm_timer);
+    if (pt == &active_timers[ts->clock->type]) {
+        if ((alarm_timer->flags & ALARM_FLAG_EXPIRED) == 0) {
+            qemu_rearm_alarm_timer(alarm_timer);
+        }
+        /* Interrupt execution to force deadline recalculation.  */
+        if (use_icount && cpu_single_env) {
+            cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
+        }
+    }
 }
 
 int qemu_timer_pending(QEMUTimer *ts)
@@ -1085,7 +1179,11 @@ int64_t qemu_get_clock(QEMUClock *clock)
         return get_clock() / 1000000;
     default:
     case QEMU_TIMER_VIRTUAL:
-        return cpu_get_clock();
+        if (use_icount) {
+            return cpu_get_icount();
+        } else {
+            return cpu_get_clock();
+        }
     }
 }
 
@@ -1184,8 +1282,9 @@ static void host_alarm_handler(int host_signum)
     }
 #endif
     if (alarm_has_dynticks(alarm_timer) ||
-        qemu_timer_expired(active_timers[QEMU_TIMER_VIRTUAL],
-                           qemu_get_clock(vm_clock)) ||
+        (!use_icount &&
+            qemu_timer_expired(active_timers[QEMU_TIMER_VIRTUAL],
+                               qemu_get_clock(vm_clock))) ||
         qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME],
                            qemu_get_clock(rt_clock))) {
 #ifdef _WIN32
@@ -1209,28 +1308,45 @@ static void host_alarm_handler(int host_signum)
     }
 }
 
-static uint64_t qemu_next_deadline(void)
+static int64_t qemu_next_deadline(void)
 {
-    int64_t nearest_delta_us = INT64_MAX;
-    int64_t vmdelta_us;
-
-    if (active_timers[QEMU_TIMER_REALTIME])
-        nearest_delta_us = (active_timers[QEMU_TIMER_REALTIME]->expire_time -
-                            qemu_get_clock(rt_clock))*1000;
+    int64_t delta;
 
     if (active_timers[QEMU_TIMER_VIRTUAL]) {
-        /* round up */
-        vmdelta_us = (active_timers[QEMU_TIMER_VIRTUAL]->expire_time -
-                      qemu_get_clock(vm_clock)+999)/1000;
-        if (vmdelta_us < nearest_delta_us)
-            nearest_delta_us = vmdelta_us;
+        delta = active_timers[QEMU_TIMER_VIRTUAL]->expire_time -
+                     qemu_get_clock(vm_clock);
+    } else {
+        /* To avoid problems with overflow limit this to 2^32.  */
+        delta = INT32_MAX;
     }
 
-    /* Avoid arming the timer to negative, zero, or too low values */
-    if (nearest_delta_us <= MIN_TIMER_REARM_US)
-        nearest_delta_us = MIN_TIMER_REARM_US;
+    if (delta < 0)
+        delta = 0;
 
-    return nearest_delta_us;
+    return delta;
+}
+
+static uint64_t qemu_next_deadline_dyntick(void)
+{
+    int64_t delta;
+    int64_t rtdelta;
+
+    if (use_icount)
+        delta = INT32_MAX;
+    else
+        delta = (qemu_next_deadline() + 999) / 1000;
+
+    if (active_timers[QEMU_TIMER_REALTIME]) {
+        rtdelta = (active_timers[QEMU_TIMER_REALTIME]->expire_time -
+                 qemu_get_clock(rt_clock))*1000;
+        if (rtdelta < delta)
+            delta = rtdelta;
+    }
+
+    if (delta < MIN_TIMER_REARM_US)
+        delta = MIN_TIMER_REARM_US;
+
+    return delta;
 }
 
 #ifndef _WIN32
@@ -1386,7 +1502,7 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
                 !active_timers[QEMU_TIMER_VIRTUAL])
         return;
 
-    nearest_delta_us = qemu_next_deadline();
+    nearest_delta_us = qemu_next_deadline_dyntick();
 
     /* check whether a timer is already running */
     if (timer_gettime(host_timer, &timeout)) {
@@ -1513,7 +1629,7 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t)
                 !active_timers[QEMU_TIMER_VIRTUAL])
         return;
 
-    nearest_delta_us = qemu_next_deadline();
+    nearest_delta_us = qemu_next_deadline_dyntick();
     nearest_delta_us /= 1000;
 
     timeKillEvent(data->timerId);
@@ -3394,8 +3510,7 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
 #ifndef _WIN32
        if (is_unix) {
            char path[109];
-           strncpy(path, uaddr.sun_path, 108);
-           path[108] = 0;
+           pstrcpy(path, sizeof(path), uaddr.sun_path);
            unlink(path);
        } else
 #endif
@@ -5075,7 +5190,7 @@ static int drive_init(struct drive_opt *arg, int snapshot,
     }
 
     if (get_param_value(buf, sizeof(buf), "if", str)) {
-        strncpy(devname, buf, sizeof(devname));
+        pstrcpy(devname, sizeof(devname), buf);
         if (!strcmp(buf, "ide")) {
            type = IF_IDE;
             max_devs = MAX_IDE_DEVS;
@@ -5945,6 +6060,8 @@ typedef struct SaveStateEntry {
 
 static SaveStateEntry *first_se;
 
+/* TODO: Individual devices generally have very little idea about the rest
+   of the system, so instance_id should be removed/replaced.  */
 int register_savevm(const char *idstr,
                     int instance_id,
                     int version_id,
@@ -5958,7 +6075,7 @@ int register_savevm(const char *idstr,
     if (!se)
         return -1;
     pstrcpy(se->idstr, sizeof(se->idstr), idstr);
-    se->instance_id = instance_id;
+    se->instance_id = (instance_id == -1) ? 0 : instance_id;
     se->version_id = version_id;
     se->save_state = save_state;
     se->load_state = load_state;
@@ -5967,8 +6084,13 @@ int register_savevm(const char *idstr,
 
     /* add at the end of list */
     pse = &first_se;
-    while (*pse != NULL)
+    while (*pse != NULL) {
+        if (instance_id == -1
+                && strcmp(se->idstr, (*pse)->idstr) == 0
+                && se->instance_id <= (*pse)->instance_id)
+            se->instance_id = (*pse)->instance_id + 1;
         pse = &(*pse)->next;
+    }
     *pse = se;
     return 0;
 }
@@ -5988,6 +6110,10 @@ static int qemu_savevm_state(QEMUFile *f)
     qemu_put_be64(f, 0); /* total size */
 
     for(se = first_se; se != NULL; se = se->next) {
+       if (se->save_state == NULL)
+           /* this one has a loader only, for backwards compatibility */
+           continue;
+
         /* ID string */
         len = strlen(se->idstr);
         qemu_put_byte(f, len);
@@ -6905,14 +7031,6 @@ void qemu_system_powerdown_request(void)
         cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
 }
 
-/* boot_set handler */
-QEMUBootSetHandler *qemu_boot_set_handler = NULL;
-
-void qemu_register_boot_set(QEMUBootSetHandler *func)
-{
-       qemu_boot_set_handler = func;
-}
-
 void main_loop_wait(int timeout)
 {
     IOHandlerRecord *ioh;
@@ -7032,6 +7150,7 @@ void main_loop_wait(int timeout)
     qemu_aio_poll();
 
     if (vm_running) {
+        if (likely(!(cur_cpu->singlestep_enabled & SSTEP_NOTIMER)))
         qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL],
                         qemu_get_clock(vm_clock));
         /* run dma transfers, if any */
@@ -7072,10 +7191,33 @@ static int main_loop(void)
 #ifdef CONFIG_PROFILER
                 ti = profile_getclock();
 #endif
+                if (use_icount) {
+                    int64_t count;
+                    int decr;
+                    qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
+                    env->icount_decr.u16.low = 0;
+                    env->icount_extra = 0;
+                    count = qemu_next_deadline();
+                    count = (count + (1 << icount_time_shift) - 1)
+                            >> icount_time_shift;
+                    qemu_icount += count;
+                    decr = (count > 0xffff) ? 0xffff : count;
+                    count -= decr;
+                    env->icount_decr.u16.low = decr;
+                    env->icount_extra = count;
+                }
                 ret = cpu_exec(env);
 #ifdef CONFIG_PROFILER
                 qemu_time += profile_getclock() - ti;
 #endif
+                if (use_icount) {
+                    /* Fold pending instructions back into the
+                       instruction counter, and clear the interrupt flag.  */
+                    qemu_icount -= (env->icount_decr.u16.low
+                                    + env->icount_extra);
+                    env->icount_decr.u32 = 0;
+                    env->icount_extra = 0;
+                }
                 next_cpu = env->next_cpu ?: first_cpu;
                 if (event_pending && likely(ret != EXCP_DEBUG)) {
                     ret = EXCP_INTERRUPT;
@@ -7119,10 +7261,46 @@ static int main_loop(void)
             }
             /* If all cpus are halted then wait until the next IRQ */
             /* XXX: use timeout computed from timers */
-            if (ret == EXCP_HALTED)
-                timeout = 10;
-            else
+            if (ret == EXCP_HALTED) {
+                if (use_icount) {
+                    int64_t add;
+                    int64_t delta;
+                    /* Advance virtual time to the next event.  */
+                    if (use_icount == 1) {
+                        /* When not using an adaptive execution frequency
+                           we tend to get badly out of sync with real time,
+                           so just delay for a reasonable amount of time.  */
+                        delta = 0;
+                    } else {
+                        delta = cpu_get_icount() - cpu_get_clock();
+                    }
+                    if (delta > 0) {
+                        /* If virtual time is ahead of real time then just
+                           wait for IO.  */
+                        timeout = (delta / 1000000) + 1;
+                    } else {
+                        /* Wait for either IO to occur or the next
+                           timer event.  */
+                        add = qemu_next_deadline();
+                        /* We advance the timer before checking for IO.
+                           Limit the amount we advance so that early IO
+                           activity won't get the guest too far ahead.  */
+                        if (add > 10000000)
+                            add = 10000000;
+                        delta += add;
+                        add = (add + (1 << icount_time_shift) - 1)
+                              >> icount_time_shift;
+                        qemu_icount += add;
+                        timeout = delta / 1000000;
+                        if (timeout < 0)
+                            timeout = 0;
+                    }
+                } else {
+                    timeout = 10;
+                }
+            } else {
                 timeout = 0;
+            }
         } else {
             timeout = 10;
         }
@@ -7274,6 +7452,8 @@ static void help(int exitcode)
            "-clock          force the use of the given methods for timer alarm.\n"
            "                To see what timers are available use -clock ?\n"
            "-startdate      select initial date of the clock\n"
+           "-icount [N|auto]\n"
+           "                Enable virtual instruction counter with 2^N clock ticks per instruction\n"
            "\n"
            "During emulation, the following keys are useful:\n"
            "ctrl-alt-f      toggle full screen\n"
@@ -7341,7 +7521,6 @@ enum {
     QEMU_OPTION_hdachs,
     QEMU_OPTION_L,
     QEMU_OPTION_bios,
-    QEMU_OPTION_no_code_copy,
     QEMU_OPTION_k,
     QEMU_OPTION_localtime,
     QEMU_OPTION_cirrusvga,
@@ -7378,6 +7557,8 @@ enum {
     QEMU_OPTION_old_param,
     QEMU_OPTION_clock,
     QEMU_OPTION_startdate,
+    QEMU_OPTION_tb_size,
+    QEMU_OPTION_icount,
 };
 
 typedef struct QEMUOption {
@@ -7438,7 +7619,6 @@ const QEMUOption qemu_options[] = {
     { "hdachs", HAS_ARG, QEMU_OPTION_hdachs },
     { "L", HAS_ARG, QEMU_OPTION_L },
     { "bios", HAS_ARG, QEMU_OPTION_bios },
-    { "no-code-copy", 0, QEMU_OPTION_no_code_copy },
 #ifdef USE_KQEMU
     { "no-kqemu", 0, QEMU_OPTION_no_kqemu },
     { "kernel-kqemu", 0, QEMU_OPTION_kernel_kqemu },
@@ -7490,6 +7670,8 @@ const QEMUOption qemu_options[] = {
 #endif
     { "clock", HAS_ARG, QEMU_OPTION_clock },
     { "startdate", HAS_ARG, QEMU_OPTION_startdate },
+    { "tb-size", HAS_ARG, QEMU_OPTION_tb_size },
+    { "icount", HAS_ARG, QEMU_OPTION_icount },
     { NULL },
 };
 
@@ -7552,6 +7734,16 @@ struct soundhw soundhw[] = {
         { .init_isa = SB16_init }
     },
 
+#ifdef CONFIG_CS4231A
+    {
+        "cs4231a",
+        "CS4231A",
+        0,
+        1,
+        { .init_isa = cs4231a_init }
+    },
+#endif
+
 #ifdef CONFIG_ADLIB
     {
         "adlib",
@@ -7698,6 +7890,7 @@ int main(int argc, char **argv)
     const char *usb_devices[MAX_USB_CMDLINE];
     int usb_devices_index;
     int fds[2];
+    int tb_size;
     const char *pid_file = NULL;
     VLANState *vlan;
 
@@ -7749,7 +7942,7 @@ int main(int argc, char **argv)
     kernel_cmdline = "";
     cyls = heads = secs = 0;
     translation = BIOS_ATA_TRANSLATION_AUTO;
-    monitor_device = "vc:800x600";
+    monitor_device = "vc";
 
     serial_devices[0] = "vc:80Cx24C";
     for(i = 1; i < MAX_SERIAL_PORTS; i++)
@@ -7769,8 +7962,9 @@ int main(int argc, char **argv)
     hda_index = -1;
 
     nb_nics = 0;
-    /* default mac address of the first network interface */
 
+    tb_size = 0;
+    
     optind = 1;
     for(;;) {
         if (optind >= argc)
@@ -7976,9 +8170,6 @@ int main(int argc, char **argv)
                 fd_bootchk = 0;
                 break;
 #endif
-            case QEMU_OPTION_no_code_copy:
-                code_copy_enabled = 0;
-                break;
             case QEMU_OPTION_net:
                 if (nb_net_clients >= MAX_NET_CLIENTS) {
                     fprintf(stderr, "qemu: too many network clients\n");
@@ -8300,6 +8491,19 @@ int main(int argc, char **argv)
                     }
                 }
                 break;
+            case QEMU_OPTION_tb_size:
+                tb_size = strtol(optarg, NULL, 0);
+                if (tb_size < 0)
+                    tb_size = 0;
+                break;
+            case QEMU_OPTION_icount:
+                use_icount = 1;
+                if (strcmp(optarg, "auto") == 0) {
+                    icount_time_shift = -1;
+                } else {
+                    icount_time_shift = strtol(optarg, NULL, 0);
+                }
+                break;
             }
         }
     }
@@ -8376,6 +8580,16 @@ int main(int argc, char **argv)
         nb_drives_opt == 0)
         help(1);
 
+    if (!linux_boot && *kernel_cmdline != '\0') {
+        fprintf(stderr, "-append only allowed with -kernel option\n");
+        exit(1);
+    }
+
+    if (!linux_boot && initrd_filename != NULL) {
+        fprintf(stderr, "-initrd only allowed with -kernel option\n");
+        exit(1);
+    }
+
     /* boot to floppy or the default cd if no hard disk defined yet */
     if (!boot_devices[0]) {
         boot_devices = "cad";
@@ -8385,6 +8599,13 @@ int main(int argc, char **argv)
     init_timers();
     init_timer_alarm();
     qemu_aio_init();
+    if (use_icount && icount_time_shift < 0) {
+        use_icount = 2;
+        /* 125MIPS seems a reasonable initial guess at the guest speed.
+           It will be corrected fairly quickly anyway.  */
+        icount_time_shift = 3;
+        init_icount_adjust();
+    }
 
 #ifdef _WIN32
     socket_init();
@@ -8471,6 +8692,9 @@ int main(int argc, char **argv)
         exit(1);
     }
 
+    /* init the dynamic translator */
+    cpu_exec_init_all(tb_size * 1024 * 1024);
+
     bdrv_init();
 
     /* we always create the cdrom drive, even if no disk is there */