diff options
author | David 'Digit' Turner <digit@android.com> | 2010-05-10 23:50:54 -0700 |
---|---|---|
committer | David 'Digit' Turner <digit@android.com> | 2010-05-11 18:01:32 -0700 |
commit | a7fb77d6eca56e61e94f62e7deb4120b60b1e919 (patch) | |
tree | 94f818fc4c89a5b5a361e3c78b9c308ccfb94064 | |
parent | fd3b1a0e32964436a5259e073857e0c4e2110122 (diff) | |
download | external_qemu-a7fb77d6eca56e61e94f62e7deb4120b60b1e919.zip external_qemu-a7fb77d6eca56e61e94f62e7deb4120b60b1e919.tar.gz external_qemu-a7fb77d6eca56e61e94f62e7deb4120b60b1e919.tar.bz2 |
Upstream: integrate timer/clock management changes.
Change-Id: I24acbdebe58d207352548f54dda1abf5be01e7d4
-rw-r--r-- | audio/audio.c | 3 | ||||
-rw-r--r-- | audio/noaudio.c | 5 | ||||
-rw-r--r-- | audio/wavaudio.c | 5 | ||||
-rw-r--r-- | hw/bt-hci.c | 8 | ||||
-rw-r--r-- | hw/goldfish_timer.c | 7 | ||||
-rw-r--r-- | hw/usb-ohci.c | 13 | ||||
-rw-r--r-- | monitor.c | 2 | ||||
-rw-r--r-- | net-android.c | 2 | ||||
-rw-r--r-- | net.c | 2 | ||||
-rw-r--r-- | qemu-timer.h | 16 | ||||
-rw-r--r-- | telephony/sysdeps_qemu.c | 1 | ||||
-rw-r--r-- | vl-android.c | 217 | ||||
-rw-r--r-- | vl.c | 284 |
13 files changed, 343 insertions, 222 deletions
diff --git a/audio/audio.c b/audio/audio.c index 2d77f14..1980450 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1990,7 +1990,8 @@ static void audio_init (void) } conf.period.ticks = 1; } else { - conf.period.ticks = ticks_per_sec / conf.period.hertz; + conf.period.ticks = + muldiv64 (1, get_ticks_per_sec (), conf.period.hertz); } e = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s); diff --git a/audio/noaudio.c b/audio/noaudio.c index 7451653..0209edb 100644 --- a/audio/noaudio.c +++ b/audio/noaudio.c @@ -53,7 +53,7 @@ static int no_run_out (HWVoiceOut *hw) now = qemu_get_clock (vm_clock); ticks = now - no->old_ticks; - bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec; + bytes = muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ()); bytes = audio_MIN (bytes, INT_MAX); samples = bytes >> hw->info.shift; @@ -109,7 +109,8 @@ static int no_run_in (HWVoiceIn *hw) if (dead) { int64_t now = qemu_get_clock (vm_clock); int64_t ticks = now - no->old_ticks; - int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec; + int64_t bytes = + muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ()); no->old_ticks = now; bytes = audio_MIN (bytes, INT_MAX); diff --git a/audio/wavaudio.c b/audio/wavaudio.c index 6f2cc54..a82997e 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -63,7 +63,8 @@ static int wav_out_run (HWVoiceOut *hw) struct st_sample *src; int64_t now = qemu_get_clock (vm_clock); int64_t ticks = now - wav->old_ticks; - int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec; + int64_t bytes = + muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ()); if (bytes > INT_MAX) { samples = INT_MAX >> hw->info.shift; @@ -355,7 +356,7 @@ static int wav_in_run (HWVoiceIn *hw) int64_t now = qemu_get_clock (vm_clock); int64_t ticks = now - wav->old_ticks; - int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec; + int64_t bytes = muldiv64(ticks, hw->info.bytes_per_second, get_ticks_per_sec()); if (bytes > INT_MAX) { samples = INT_MAX >> hw->info.shift; diff --git a/hw/bt-hci.c b/hw/bt-hci.c index 7837d9e..669866a 100644 --- a/hw/bt-hci.c +++ b/hw/bt-hci.c @@ -15,9 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA + * along with this program; if not, see <http://www.gnu.org/licenses/>. */ #include "qemu-common.h" @@ -579,7 +577,7 @@ static void bt_hci_inquiry_result(struct bt_hci_s *hci, static void bt_hci_mod_timer_1280ms(QEMUTimer *timer, int period) { qemu_mod_timer(timer, qemu_get_clock(vm_clock) + - muldiv64(period << 7, ticks_per_sec, 100)); + muldiv64(period << 7, get_ticks_per_sec(), 100)); } static void bt_hci_inquiry_start(struct bt_hci_s *hci, int length) @@ -1088,7 +1086,7 @@ static int bt_hci_mode_change(struct bt_hci_s *hci, uint16_t handle, bt_hci_event_status(hci, HCI_SUCCESS); qemu_mod_timer(link->acl_mode_timer, qemu_get_clock(vm_clock) + - muldiv64(interval * 625, ticks_per_sec, 1000000)); + muldiv64(interval * 625, get_ticks_per_sec(), 1000000)); bt_hci_lmp_mode_change_master(hci, link->link, mode, interval); return 0; diff --git a/hw/goldfish_timer.c b/hw/goldfish_timer.c index 8a84895..d5c9a33 100644 --- a/hw/goldfish_timer.c +++ b/hw/goldfish_timer.c @@ -9,6 +9,7 @@ ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. */ +#include "qemu-common.h" #include "qemu-timer.h" #include "cpu.h" #include "arm_pic.h" @@ -42,7 +43,7 @@ static void goldfish_timer_save(QEMUFile* f, void* opaque) qemu_put_byte(f, s->armed); if (s->armed) { int64_t now = qemu_get_clock(vm_clock); - int64_t alarm = muldiv64(s->alarm_low | (int64_t)s->alarm_high << 32, ticks_per_sec, 1000000000); + int64_t alarm = muldiv64(s->alarm_low | (int64_t)s->alarm_high << 32, get_ticks_per_sec(), 1000000000); qemu_put_be64(f, alarm-now); } } @@ -76,7 +77,7 @@ static uint32_t goldfish_timer_read(void *opaque, target_phys_addr_t offset) struct timer_state *s = (struct timer_state *)opaque; switch(offset) { case TIMER_TIME_LOW: - s->now = muldiv64(qemu_get_clock(vm_clock), 1000000000, ticks_per_sec); + s->now = muldiv64(qemu_get_clock(vm_clock), 1000000000, get_ticks_per_sec()); return s->now; case TIMER_TIME_HIGH: return s->now >> 32; @@ -93,7 +94,7 @@ static void goldfish_timer_write(void *opaque, target_phys_addr_t offset, uint32 switch(offset) { case TIMER_ALARM_LOW: s->alarm_low = value; - alarm = muldiv64(s->alarm_low | (int64_t)s->alarm_high << 32, ticks_per_sec, 1000000000); + alarm = muldiv64(s->alarm_low | (int64_t)s->alarm_high << 32, get_ticks_per_sec(), 1000000000); now = qemu_get_clock(vm_clock); if (alarm <= now) { goldfish_device_set_irq(&s->dev, 0, 1); diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c index c575480..7dd8ed3 100644 --- a/hw/usb-ohci.c +++ b/hw/usb-ohci.c @@ -15,8 +15,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA + * License along with this library; if not, see <http://www.gnu.org/licenses/>. * * TODO: * o Isochronous transfers @@ -1668,12 +1667,12 @@ static void usb_ohci_init(OHCIState *ohci, int num_ports, int devfn, if (usb_frame_time == 0) { #ifdef OHCI_TIME_WARP - usb_frame_time = ticks_per_sec; - usb_bit_time = muldiv64(1, ticks_per_sec, USB_HZ/1000); + usb_frame_time = get_ticks_per_sec(); + usb_bit_time = muldiv64(1, get_ticks_per_sec(), USB_HZ/1000); #else - usb_frame_time = muldiv64(1, ticks_per_sec, 1000); - if (ticks_per_sec >= USB_HZ) { - usb_bit_time = muldiv64(1, ticks_per_sec, USB_HZ); + usb_frame_time = muldiv64(1, get_ticks_per_sec(), 1000); + if (get_ticks_per_sec() >= USB_HZ) { + usb_bit_time = muldiv64(1, get_ticks_per_sec(), USB_HZ); } else { usb_bit_time = 1; } @@ -1131,7 +1131,7 @@ static void do_sendkey(Monitor *mon, const char *string, int has_hold_time, } /* delayed key up events */ qemu_mod_timer(key_timer, qemu_get_clock(vm_clock) + - muldiv64(ticks_per_sec, hold_time, 1000)); + muldiv64(get_ticks_per_sec(), hold_time, 1000)); } static int mouse_button_state; diff --git a/net-android.c b/net-android.c index e656f1e..d208cd6 100644 --- a/net-android.c +++ b/net-android.c @@ -2018,7 +2018,7 @@ static ssize_t dump_receive(VLANClientState *vc, const uint8_t *buf, size_t size return size; } - ts = muldiv64(qemu_get_clock(vm_clock), 1000000, ticks_per_sec); + ts = muldiv64(qemu_get_clock(vm_clock), 1000000, get_ticks_per_sec()); caplen = size > s->pcap_caplen ? s->pcap_caplen : size; hdr.ts.tv_sec = ts / 1000000; @@ -1957,7 +1957,7 @@ static ssize_t dump_receive(VLANClientState *vc, const uint8_t *buf, size_t size return size; } - ts = muldiv64(qemu_get_clock(vm_clock), 1000000, ticks_per_sec); + ts = muldiv64(qemu_get_clock(vm_clock), 1000000, get_ticks_per_sec()); caplen = size > s->pcap_caplen ? s->pcap_caplen : size; hdr.ts.tv_sec = ts / 1000000; diff --git a/qemu-timer.h b/qemu-timer.h index 8264f3e..c17b4e6 100644 --- a/qemu-timer.h +++ b/qemu-timer.h @@ -1,8 +1,6 @@ #ifndef QEMU_TIMER_H #define QEMU_TIMER_H -#include "qemu-common.h" - /* timers */ typedef struct QEMUClock QEMUClock; @@ -19,15 +17,27 @@ extern QEMUClock *rt_clock; precision clock, usually cpu cycles (use ticks_per_sec). */ extern QEMUClock *vm_clock; +/* The host clock should be use for device models that emulate accurate + real time sources. It will continue to run when the virtual machine + is suspended, and it will reflect system time changes the host may + undergo (e.g. due to NTP). The host clock has the same precision as + the virtual clock. */ +extern QEMUClock *host_clock; + int64_t qemu_get_clock(QEMUClock *clock); +int64_t qemu_get_clock_ns(QEMUClock *clock); QEMUTimer *qemu_new_timer(QEMUClock *clock, QEMUTimerCB *cb, void *opaque); void qemu_free_timer(QEMUTimer *ts); void qemu_del_timer(QEMUTimer *ts); void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time); int qemu_timer_pending(QEMUTimer *ts); +int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time); -extern int64_t ticks_per_sec; +static inline int64_t get_ticks_per_sec(void) +{ + return 1000000000LL; +} void qemu_get_timer(QEMUFile *f, QEMUTimer *ts); void qemu_put_timer(QEMUFile *f, QEMUTimer *ts); diff --git a/telephony/sysdeps_qemu.c b/telephony/sysdeps_qemu.c index 48cd81c..e464597 100644 --- a/telephony/sysdeps_qemu.c +++ b/telephony/sysdeps_qemu.c @@ -11,6 +11,7 @@ */ #include "sockets.h" #include "sysdeps.h" +#include "qemu-common.h" #include "qemu-timer.h" #include "qemu-char.h" #ifdef _WIN32 diff --git a/vl-android.c b/vl-android.c index fc32d77..7be2eae 100644 --- a/vl-android.c +++ b/vl-android.c @@ -249,6 +249,7 @@ int cirrus_vga_enabled = 1; int std_vga_enabled = 0; int vmsvga_enabled = 0; int xenfb_enabled = 0; +QEMUClock *rtc_clock; #ifdef TARGET_SPARC int graphic_width = 1024; int graphic_height = 768; @@ -433,6 +434,20 @@ void hw_error(const char *fmt, ...) abort(); } +static void set_proc_name(const char *s) +{ +#if defined(__linux__) && defined(PR_SET_NAME) + char name[16]; + if (!s) + return; + name[sizeof(name) - 1] = 0; + strncpy(name, s, sizeof(name)); + /* Could rewrite argv[0] too, but that's a bit more complicated. + This simple way is enough for `top'. */ + prctl(PR_SET_NAME, name); +#endif +} + /***************/ /* ballooning */ @@ -699,10 +714,13 @@ uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) return res.ll; } -/***********************************************************/ -/* real time host monotonic timer */ +static int64_t get_clock_realtime(void) +{ + struct timeval tv; -#define QEMU_TIMER_BASE 1000000000LL + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000); +} #ifdef WIN32 @@ -724,7 +742,7 @@ static int64_t get_clock(void) { LARGE_INTEGER ti; QueryPerformanceCounter(&ti); - return muldiv64(ti.QuadPart, QEMU_TIMER_BASE, clock_freq); + return muldiv64(ti.QuadPart, get_ticks_per_sec(), clock_freq); } #else @@ -735,7 +753,7 @@ static void init_get_clock(void) { use_rt_clock = 0; #if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 500000) \ - || defined(__DragonFly__) + || defined(__DragonFly__) || defined(__FreeBSD_kernel__) { struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { @@ -748,7 +766,7 @@ static void init_get_clock(void) static int64_t get_clock(void) { #if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 500000) \ - || defined(__DragonFly__) + || defined(__DragonFly__) || defined(__FreeBSD_kernel__) if (use_rt_clock) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); @@ -782,10 +800,15 @@ static int64_t cpu_get_icount(void) /***********************************************************/ /* guest cycle counter */ -static int64_t cpu_ticks_prev; -static int64_t cpu_ticks_offset; -static int64_t cpu_clock_offset; -static int cpu_ticks_enabled; +typedef struct TimersState { + int64_t cpu_ticks_prev; + int64_t cpu_ticks_offset; + int64_t cpu_clock_offset; + int32_t cpu_ticks_enabled; + int64_t dummy; +} TimersState; + +TimersState timers_state; /* return the host CPU cycle counter and handle stop/restart */ int64_t cpu_get_ticks(void) @@ -793,18 +816,18 @@ int64_t cpu_get_ticks(void) if (use_icount) { return cpu_get_icount(); } - if (!cpu_ticks_enabled) { - return cpu_ticks_offset; + if (!timers_state.cpu_ticks_enabled) { + return timers_state.cpu_ticks_offset; } else { int64_t ticks; ticks = cpu_get_real_ticks(); - if (cpu_ticks_prev > ticks) { + if (timers_state.cpu_ticks_prev > ticks) { /* Note: non increasing ticks may happen if the host uses software suspend */ - cpu_ticks_offset += cpu_ticks_prev - ticks; + timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks; } - cpu_ticks_prev = ticks; - return ticks + cpu_ticks_offset; + timers_state.cpu_ticks_prev = ticks; + return ticks + timers_state.cpu_ticks_offset; } } @@ -812,21 +835,21 @@ int64_t cpu_get_ticks(void) static int64_t cpu_get_clock(void) { int64_t ti; - if (!cpu_ticks_enabled) { - return cpu_clock_offset; + if (!timers_state.cpu_ticks_enabled) { + return timers_state.cpu_clock_offset; } else { ti = get_clock(); - return ti + cpu_clock_offset; + return ti + timers_state.cpu_clock_offset; } } /* enable cpu_get_ticks() */ void cpu_enable_ticks(void) { - if (!cpu_ticks_enabled) { - cpu_ticks_offset -= cpu_get_real_ticks(); - cpu_clock_offset -= get_clock(); - cpu_ticks_enabled = 1; + if (!timers_state.cpu_ticks_enabled) { + timers_state.cpu_ticks_offset -= cpu_get_real_ticks(); + timers_state.cpu_clock_offset -= get_clock(); + timers_state.cpu_ticks_enabled = 1; } } @@ -834,18 +857,19 @@ void cpu_enable_ticks(void) cpu_get_ticks() after that. */ void cpu_disable_ticks(void) { - if (cpu_ticks_enabled) { - cpu_ticks_offset = cpu_get_ticks(); - cpu_clock_offset = cpu_get_clock(); - cpu_ticks_enabled = 0; + if (timers_state.cpu_ticks_enabled) { + timers_state.cpu_ticks_offset = cpu_get_ticks(); + timers_state.cpu_clock_offset = cpu_get_clock(); + timers_state.cpu_ticks_enabled = 0; } } /***********************************************************/ /* timers */ -#define QEMU_TIMER_REALTIME 0 -#define QEMU_TIMER_VIRTUAL 1 +#define QEMU_CLOCK_REALTIME 0 +#define QEMU_CLOCK_VIRTUAL 1 +#define QEMU_CLOCK_HOST 2 struct QEMUClock { int type; @@ -927,7 +951,7 @@ static void rtc_stop_timer(struct qemu_alarm_timer *t); 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) +#define ICOUNT_WOBBLE (get_ticks_per_sec() / 10) static void icount_adjust(void) { @@ -969,7 +993,7 @@ static void icount_adjust_rt(void * opaque) static void icount_adjust_vm(void * opaque) { qemu_mod_timer(icount_vm_timer, - qemu_get_clock(vm_clock) + QEMU_TIMER_BASE / 10); + qemu_get_clock(vm_clock) + get_ticks_per_sec() / 10); icount_adjust(); } @@ -985,7 +1009,7 @@ static void init_icount_adjust(void) 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); + qemu_get_clock(vm_clock) + get_ticks_per_sec() / 10); } static struct qemu_alarm_timer alarm_timers[] = { @@ -1060,7 +1084,7 @@ next: name = strtok(NULL, ","); } - free(arg); + qemu_free(arg); if (cur) { /* Disable remaining timers */ @@ -1072,10 +1096,13 @@ next: } } +#define QEMU_NUM_CLOCKS 3 + QEMUClock *rt_clock; QEMUClock *vm_clock; +QEMUClock *host_clock; -static QEMUTimer *active_timers[2]; +static QEMUTimer *active_timers[QEMU_NUM_CLOCKS]; static QEMUClock *qemu_new_clock(int type) { @@ -1166,7 +1193,7 @@ int qemu_timer_pending(QEMUTimer *ts) return 0; } -static inline int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time) +int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time) { if (!timer_head) return 0; @@ -1193,24 +1220,45 @@ static void qemu_run_timers(QEMUTimer **ptimer_head, int64_t current_time) int64_t qemu_get_clock(QEMUClock *clock) { switch(clock->type) { - case QEMU_TIMER_REALTIME: + case QEMU_CLOCK_REALTIME: return get_clock() / 1000000; default: - case QEMU_TIMER_VIRTUAL: + case QEMU_CLOCK_VIRTUAL: + if (use_icount) { + return cpu_get_icount(); + } else { + return cpu_get_clock(); + } + case QEMU_CLOCK_HOST: + return get_clock_realtime(); + } +} + +int64_t qemu_get_clock_ns(QEMUClock *clock) +{ + switch(clock->type) { + case QEMU_CLOCK_REALTIME: + return get_clock(); + default: + case QEMU_CLOCK_VIRTUAL: if (use_icount) { return cpu_get_icount(); } else { return cpu_get_clock(); } + case QEMU_CLOCK_HOST: + return get_clock_realtime(); } } -static void init_timers(void) +static void init_clocks(void) { init_get_clock(); - ticks_per_sec = QEMU_TIMER_BASE; - rt_clock = qemu_new_clock(QEMU_TIMER_REALTIME); - vm_clock = qemu_new_clock(QEMU_TIMER_VIRTUAL); + rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME); + vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL); + host_clock = qemu_new_clock(QEMU_CLOCK_HOST); + + rtc_clock = host_clock; } /* save a timer */ @@ -1240,16 +1288,19 @@ void qemu_get_timer(QEMUFile *f, QEMUTimer *ts) static void timer_save(QEMUFile *f, void *opaque) { +#if 0 if (cpu_ticks_enabled) { hw_error("cannot save state if virtual timers are running"); } qemu_put_be64(f, cpu_ticks_offset); qemu_put_be64(f, ticks_per_sec); qemu_put_be64(f, cpu_clock_offset); +#endif } static int timer_load(QEMUFile *f, void *opaque, int version_id) { +#if 0 if (version_id != 1 && version_id != 2) return -EINVAL; if (cpu_ticks_enabled) { @@ -1260,6 +1311,7 @@ static int timer_load(QEMUFile *f, void *opaque, int version_id) if (version_id == 2) { cpu_clock_offset=qemu_get_be64(f); } +#endif return 0; } @@ -1289,10 +1341,10 @@ static void host_alarm_handler(int host_signum) delta_cum += delta; if (++count == DISP_FREQ) { printf("timer: min=%" PRId64 " us max=%" PRId64 " us avg=%" PRId64 " us avg_freq=%0.3f Hz\n", - muldiv64(delta_min, 1000000, ticks_per_sec), - muldiv64(delta_max, 1000000, ticks_per_sec), - muldiv64(delta_cum, 1000000 / DISP_FREQ, ticks_per_sec), - (double)ticks_per_sec / ((double)delta_cum / DISP_FREQ)); + muldiv64(delta_min, 1000000, get_ticks_per_sec()), + muldiv64(delta_max, 1000000, get_ticks_per_sec()), + muldiv64(delta_cum, 1000000 / DISP_FREQ, get_ticks_per_sec()), + (double)get_ticks_per_sec() / ((double)delta_cum / DISP_FREQ)); count = 0; delta_min = INT64_MAX; delta_max = 0; @@ -1304,10 +1356,12 @@ static void host_alarm_handler(int host_signum) #endif if (alarm_has_dynticks(alarm_timer) || (!use_icount && - qemu_timer_expired(active_timers[QEMU_TIMER_VIRTUAL], + qemu_timer_expired(active_timers[QEMU_CLOCK_VIRTUAL], qemu_get_clock(vm_clock))) || - qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME], - qemu_get_clock(rt_clock))) { + qemu_timer_expired(active_timers[QEMU_CLOCK_REALTIME], + qemu_get_clock(rt_clock)) || + qemu_timer_expired(active_timers[QEMU_CLOCK_HOST], + qemu_get_clock(host_clock))) { qemu_event_increment(); if (alarm_timer) alarm_timer->flags |= ALARM_FLAG_EXPIRED; @@ -1315,11 +1369,6 @@ static void host_alarm_handler(int host_signum) if (next_cpu) { /* stop the currently executing cpu because a timer occured */ cpu_exit(next_cpu); -#ifdef CONFIG_KQEMU - if (next_cpu->kqemu_enabled) { - kqemu_cpu_interrupt(next_cpu); - } -#endif } #endif timer_alarm_pending = 1; @@ -1329,14 +1378,18 @@ static void host_alarm_handler(int host_signum) static int64_t qemu_next_deadline(void) { - int64_t delta; + /* To avoid problems with overflow limit this to 2^32. */ + int64_t delta = INT32_MAX; - if (active_timers[QEMU_TIMER_VIRTUAL]) { - delta = active_timers[QEMU_TIMER_VIRTUAL]->expire_time - + if (active_timers[QEMU_CLOCK_VIRTUAL]) { + delta = active_timers[QEMU_CLOCK_VIRTUAL]->expire_time - qemu_get_clock(vm_clock); - } else { - /* To avoid problems with overflow limit this to 2^32. */ - delta = INT32_MAX; + } + if (active_timers[QEMU_CLOCK_HOST]) { + int64_t hdelta = active_timers[QEMU_CLOCK_HOST]->expire_time - + qemu_get_clock(host_clock); + if (hdelta < delta) + delta = hdelta; } if (delta < 0) @@ -1345,7 +1398,7 @@ static int64_t qemu_next_deadline(void) return delta; } -#if defined(__linux__) || defined(_WIN32) +#if defined(__linux__) static uint64_t qemu_next_deadline_dyntick(void) { int64_t delta; @@ -1356,8 +1409,8 @@ static uint64_t qemu_next_deadline_dyntick(void) else delta = (qemu_next_deadline() + 999) / 1000; - if (active_timers[QEMU_TIMER_REALTIME]) { - rtdelta = (active_timers[QEMU_TIMER_REALTIME]->expire_time - + if (active_timers[QEMU_CLOCK_REALTIME]) { + rtdelta = (active_timers[QEMU_CLOCK_REALTIME]->expire_time - qemu_get_clock(rt_clock))*1000; if (rtdelta < delta) delta = rtdelta; @@ -1539,8 +1592,9 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t) int64_t nearest_delta_us = INT64_MAX; int64_t current_us; - if (!active_timers[QEMU_TIMER_REALTIME] && - !active_timers[QEMU_TIMER_VIRTUAL]) + if (!active_timers[QEMU_CLOCK_REALTIME] && + !active_timers[QEMU_CLOCK_VIRTUAL] && + !active_timers[QEMU_CLOCK_HOST]) return; nearest_delta_us = qemu_next_deadline_dyntick(); @@ -1634,7 +1688,8 @@ static int win32_start_timer(struct qemu_alarm_timer *t) flags); if (!data->timerId) { - perror("Failed to initialize win32 alarm timer"); + fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n", + GetLastError()); timeEndPeriod(data->period); return -1; } @@ -1653,15 +1708,12 @@ static void win32_stop_timer(struct qemu_alarm_timer *t) static void win32_rearm_timer(struct qemu_alarm_timer *t) { struct qemu_alarm_win32 *data = t->priv; - uint64_t nearest_delta_us; - if (!active_timers[QEMU_TIMER_REALTIME] && - !active_timers[QEMU_TIMER_VIRTUAL]) + if (!active_timers[QEMU_CLOCK_REALTIME] && + !active_timers[QEMU_CLOCK_VIRTUAL] && + !active_timers[QEMU_CLOCK_HOST]) return; - nearest_delta_us = qemu_next_deadline_dyntick(); - nearest_delta_us /= 1000; - timeKillEvent(data->timerId); data->timerId = timeSetEvent(1, @@ -1671,7 +1723,8 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t) TIME_ONESHOT | TIME_PERIODIC); if (!data->timerId) { - perror("Failed to re-arm win32 alarm timer"); + fprintf(stderr, "Failed to re-arm win32 alarm timer %ld\n", + GetLastError()); timeEndPeriod(data->period); exit(1); @@ -4233,14 +4286,17 @@ void main_loop_wait(int timeout) /* vm time timers */ if (vm_running) { if (!cur_cpu || likely(!(cur_cpu->singlestep_enabled & SSTEP_NOTIMER))) - qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL], + qemu_run_timers(&active_timers[QEMU_CLOCK_VIRTUAL], qemu_get_clock(vm_clock)); } /* real time timers */ - qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME], + qemu_run_timers(&active_timers[QEMU_CLOCK_REALTIME], qemu_get_clock(rt_clock)); + qemu_run_timers(&active_timers[QEMU_CLOCK_HOST], + qemu_get_clock(host_clock)); + /* Check bottom-halves last in case any of the earlier events triggered them. */ qemu_bh_poll(); @@ -4934,6 +4990,8 @@ int main(int argc, char **argv, char **envp) CPUState *env; int show_vnc_port = 0; + init_clocks(); + qemu_cache_utils_init(envp); QLIST_INIT (&vm_change_state_head); @@ -5820,7 +5878,6 @@ int main(int argc, char **argv, char **envp) } setvbuf(stdout, NULL, _IOLBF, 0); - init_timers(); if (init_timer_alarm() < 0) { fprintf(stderr, "could not initialize alarm timer\n"); exit(1); @@ -6235,7 +6292,10 @@ int main(int argc, char **argv, char **envp) if (len != 1) exit(1); - chdir("/"); + if (chdir("/")) { + perror("not able to chdir to /"); + exit(1); + } TFR(fd = open("/dev/null", O_RDWR)); if (fd == -1) exit(1); @@ -6254,7 +6314,10 @@ int main(int argc, char **argv, char **envp) fprintf(stderr, "chroot failed\n"); exit(1); } - chdir("/"); + if (chdir("/")) { + perror("not able to chdir to /"); + exit(1); + } } if (run_as) { @@ -205,7 +205,6 @@ enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; static DisplayState *display_state; DisplayType display_type = DT_DEFAULT; const char* keyboard_layout = NULL; -int64_t ticks_per_sec; ram_addr_t ram_size; int nb_nics; NICInfo nd_table[MAX_NICS]; @@ -217,6 +216,7 @@ int cirrus_vga_enabled = 1; int std_vga_enabled = 0; int vmsvga_enabled = 0; int xenfb_enabled = 0; +QEMUClock *rtc_clock; #ifdef TARGET_SPARC int graphic_width = 1024; int graphic_height = 768; @@ -528,6 +528,20 @@ void hw_error(const char *fmt, ...) abort(); } +static void set_proc_name(const char *s) +{ +#if defined(__linux__) && defined(PR_SET_NAME) + char name[16]; + if (!s) + return; + name[sizeof(name) - 1] = 0; + strncpy(name, s, sizeof(name)); + /* Could rewrite argv[0] too, but that's a bit more complicated. + This simple way is enough for `top'. */ + prctl(PR_SET_NAME, name); +#endif +} + /***************/ /* ballooning */ @@ -716,6 +730,9 @@ void do_mouse_set(Monitor *mon, int index) monitor_printf(mon, "Mouse at given index not found\n"); } +/***********************************************************/ +/* real time host monotonic timer */ + /* compute with 96 bit intermediate result: (a*b)/c */ uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) { @@ -740,10 +757,13 @@ uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) return res.ll; } -/***********************************************************/ -/* real time host monotonic timer */ +static int64_t get_clock_realtime(void) +{ + struct timeval tv; -#define QEMU_TIMER_BASE 1000000000LL + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000); +} #ifdef WIN32 @@ -765,7 +785,7 @@ static int64_t get_clock(void) { LARGE_INTEGER ti; QueryPerformanceCounter(&ti); - return muldiv64(ti.QuadPart, QEMU_TIMER_BASE, clock_freq); + return muldiv64(ti.QuadPart, get_ticks_per_sec(), clock_freq); } #else @@ -776,7 +796,7 @@ static void init_get_clock(void) { use_rt_clock = 0; #if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 500000) \ - || defined(__DragonFly__) + || defined(__DragonFly__) || defined(__FreeBSD_kernel__) { struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { @@ -789,7 +809,7 @@ static void init_get_clock(void) static int64_t get_clock(void) { #if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 500000) \ - || defined(__DragonFly__) + || defined(__DragonFly__) || defined(__FreeBSD_kernel__) if (use_rt_clock) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); @@ -799,9 +819,7 @@ static int64_t get_clock(void) { /* XXX: using gettimeofday leads to problems if the date changes, so it should be avoided. */ - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000); + return get_clock_realtime(); } } #endif @@ -823,10 +841,15 @@ static int64_t cpu_get_icount(void) /***********************************************************/ /* guest cycle counter */ -static int64_t cpu_ticks_prev; -static int64_t cpu_ticks_offset; -static int64_t cpu_clock_offset; -static int cpu_ticks_enabled; +typedef struct TimersState { + int64_t cpu_ticks_prev; + int64_t cpu_ticks_offset; + int64_t cpu_clock_offset; + int32_t cpu_ticks_enabled; + int64_t dummy; +} TimersState; + +TimersState timers_state; /* return the host CPU cycle counter and handle stop/restart */ int64_t cpu_get_ticks(void) @@ -834,18 +857,18 @@ int64_t cpu_get_ticks(void) if (use_icount) { return cpu_get_icount(); } - if (!cpu_ticks_enabled) { - return cpu_ticks_offset; + if (!timers_state.cpu_ticks_enabled) { + return timers_state.cpu_ticks_offset; } else { int64_t ticks; ticks = cpu_get_real_ticks(); - if (cpu_ticks_prev > ticks) { + if (timers_state.cpu_ticks_prev > ticks) { /* Note: non increasing ticks may happen if the host uses software suspend */ - cpu_ticks_offset += cpu_ticks_prev - ticks; + timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks; } - cpu_ticks_prev = ticks; - return ticks + cpu_ticks_offset; + timers_state.cpu_ticks_prev = ticks; + return ticks + timers_state.cpu_ticks_offset; } } @@ -853,21 +876,21 @@ int64_t cpu_get_ticks(void) static int64_t cpu_get_clock(void) { int64_t ti; - if (!cpu_ticks_enabled) { - return cpu_clock_offset; + if (!timers_state.cpu_ticks_enabled) { + return timers_state.cpu_clock_offset; } else { ti = get_clock(); - return ti + cpu_clock_offset; + return ti + timers_state.cpu_clock_offset; } } /* enable cpu_get_ticks() */ void cpu_enable_ticks(void) { - if (!cpu_ticks_enabled) { - cpu_ticks_offset -= cpu_get_real_ticks(); - cpu_clock_offset -= get_clock(); - cpu_ticks_enabled = 1; + if (!timers_state.cpu_ticks_enabled) { + timers_state.cpu_ticks_offset -= cpu_get_real_ticks(); + timers_state.cpu_clock_offset -= get_clock(); + timers_state.cpu_ticks_enabled = 1; } } @@ -875,18 +898,19 @@ void cpu_enable_ticks(void) cpu_get_ticks() after that. */ void cpu_disable_ticks(void) { - if (cpu_ticks_enabled) { - cpu_ticks_offset = cpu_get_ticks(); - cpu_clock_offset = cpu_get_clock(); - cpu_ticks_enabled = 0; + if (timers_state.cpu_ticks_enabled) { + timers_state.cpu_ticks_offset = cpu_get_ticks(); + timers_state.cpu_clock_offset = cpu_get_clock(); + timers_state.cpu_ticks_enabled = 0; } } /***********************************************************/ /* timers */ -#define QEMU_TIMER_REALTIME 0 -#define QEMU_TIMER_VIRTUAL 1 +#define QEMU_CLOCK_REALTIME 0 +#define QEMU_CLOCK_VIRTUAL 1 +#define QEMU_CLOCK_HOST 2 struct QEMUClock { int type; @@ -968,7 +992,7 @@ static void rtc_stop_timer(struct qemu_alarm_timer *t); 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) +#define ICOUNT_WOBBLE (get_ticks_per_sec() / 10) static void icount_adjust(void) { @@ -1010,7 +1034,7 @@ static void icount_adjust_rt(void * opaque) static void icount_adjust_vm(void * opaque) { qemu_mod_timer(icount_vm_timer, - qemu_get_clock(vm_clock) + QEMU_TIMER_BASE / 10); + qemu_get_clock(vm_clock) + get_ticks_per_sec() / 10); icount_adjust(); } @@ -1026,7 +1050,7 @@ static void init_icount_adjust(void) 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); + qemu_get_clock(vm_clock) + get_ticks_per_sec() / 10); } static struct qemu_alarm_timer alarm_timers[] = { @@ -1072,7 +1096,7 @@ static void configure_alarms(char const *opt) exit(0); } - arg = strdup(opt); + arg = qemu_strdup(opt); /* Reorder the array */ name = strtok(arg, ","); @@ -1101,7 +1125,7 @@ next: name = strtok(NULL, ","); } - free(arg); + qemu_free(arg); if (cur) { /* Disable remaining timers */ @@ -1113,10 +1137,13 @@ next: } } +#define QEMU_NUM_CLOCKS 3 + QEMUClock *rt_clock; QEMUClock *vm_clock; +QEMUClock *host_clock; -static QEMUTimer *active_timers[2]; +static QEMUTimer *active_timers[QEMU_NUM_CLOCKS]; static QEMUClock *qemu_new_clock(int type) { @@ -1207,7 +1234,7 @@ int qemu_timer_pending(QEMUTimer *ts) return 0; } -static inline int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time) +int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time) { if (!timer_head) return 0; @@ -1234,24 +1261,45 @@ static void qemu_run_timers(QEMUTimer **ptimer_head, int64_t current_time) int64_t qemu_get_clock(QEMUClock *clock) { switch(clock->type) { - case QEMU_TIMER_REALTIME: + case QEMU_CLOCK_REALTIME: return get_clock() / 1000000; default: - case QEMU_TIMER_VIRTUAL: + case QEMU_CLOCK_VIRTUAL: + if (use_icount) { + return cpu_get_icount(); + } else { + return cpu_get_clock(); + } + case QEMU_CLOCK_HOST: + return get_clock_realtime(); + } +} + +int64_t qemu_get_clock_ns(QEMUClock *clock) +{ + switch(clock->type) { + case QEMU_CLOCK_REALTIME: + return get_clock(); + default: + case QEMU_CLOCK_VIRTUAL: if (use_icount) { return cpu_get_icount(); } else { return cpu_get_clock(); } + case QEMU_CLOCK_HOST: + return get_clock_realtime(); } } -static void init_timers(void) +static void init_clocks(void) { init_get_clock(); - ticks_per_sec = QEMU_TIMER_BASE; - rt_clock = qemu_new_clock(QEMU_TIMER_REALTIME); - vm_clock = qemu_new_clock(QEMU_TIMER_VIRTUAL); + rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME); + vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL); + host_clock = qemu_new_clock(QEMU_CLOCK_HOST); + + rtc_clock = host_clock; } /* save a timer */ @@ -1279,30 +1327,18 @@ void qemu_get_timer(QEMUFile *f, QEMUTimer *ts) } } -static void timer_save(QEMUFile *f, void *opaque) -{ - if (cpu_ticks_enabled) { - hw_error("cannot save state if virtual timers are running"); +static const VMStateDescription vmstate_timers = { + .name = "timer", + .version_id = 2, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField []) { + VMSTATE_INT64(cpu_ticks_offset, TimersState), + VMSTATE_INT64(dummy, TimersState), + VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2), + VMSTATE_END_OF_LIST() } - qemu_put_be64(f, cpu_ticks_offset); - qemu_put_be64(f, ticks_per_sec); - qemu_put_be64(f, cpu_clock_offset); -} - -static int timer_load(QEMUFile *f, void *opaque, int version_id) -{ - if (version_id != 1 && version_id != 2) - return -EINVAL; - if (cpu_ticks_enabled) { - return -EINVAL; - } - cpu_ticks_offset=qemu_get_be64(f); - ticks_per_sec=qemu_get_be64(f); - if (version_id == 2) { - cpu_clock_offset=qemu_get_be64(f); - } - return 0; -} +}; static void qemu_event_increment(void); @@ -1330,10 +1366,10 @@ static void host_alarm_handler(int host_signum) delta_cum += delta; if (++count == DISP_FREQ) { printf("timer: min=%" PRId64 " us max=%" PRId64 " us avg=%" PRId64 " us avg_freq=%0.3f Hz\n", - muldiv64(delta_min, 1000000, ticks_per_sec), - muldiv64(delta_max, 1000000, ticks_per_sec), - muldiv64(delta_cum, 1000000 / DISP_FREQ, ticks_per_sec), - (double)ticks_per_sec / ((double)delta_cum / DISP_FREQ)); + muldiv64(delta_min, 1000000, get_ticks_per_sec()), + muldiv64(delta_max, 1000000, get_ticks_per_sec()), + muldiv64(delta_cum, 1000000 / DISP_FREQ, get_ticks_per_sec()), + (double)get_ticks_per_sec() / ((double)delta_cum / DISP_FREQ)); count = 0; delta_min = INT64_MAX; delta_max = 0; @@ -1345,10 +1381,12 @@ static void host_alarm_handler(int host_signum) #endif if (alarm_has_dynticks(alarm_timer) || (!use_icount && - qemu_timer_expired(active_timers[QEMU_TIMER_VIRTUAL], + qemu_timer_expired(active_timers[QEMU_CLOCK_VIRTUAL], qemu_get_clock(vm_clock))) || - qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME], - qemu_get_clock(rt_clock))) { + qemu_timer_expired(active_timers[QEMU_CLOCK_REALTIME], + qemu_get_clock(rt_clock)) || + qemu_timer_expired(active_timers[QEMU_CLOCK_HOST], + qemu_get_clock(host_clock))) { qemu_event_increment(); if (alarm_timer) alarm_timer->flags |= ALARM_FLAG_EXPIRED; @@ -1356,11 +1394,6 @@ static void host_alarm_handler(int host_signum) if (next_cpu) { /* stop the currently executing cpu because a timer occured */ cpu_exit(next_cpu); -#ifdef CONFIG_KQEMU - if (next_cpu->kqemu_enabled) { - kqemu_cpu_interrupt(next_cpu); - } -#endif } #endif timer_alarm_pending = 1; @@ -1370,14 +1403,18 @@ static void host_alarm_handler(int host_signum) static int64_t qemu_next_deadline(void) { - int64_t delta; + /* To avoid problems with overflow limit this to 2^32. */ + int64_t delta = INT32_MAX; - if (active_timers[QEMU_TIMER_VIRTUAL]) { - delta = active_timers[QEMU_TIMER_VIRTUAL]->expire_time - + if (active_timers[QEMU_CLOCK_VIRTUAL]) { + delta = active_timers[QEMU_CLOCK_VIRTUAL]->expire_time - qemu_get_clock(vm_clock); - } else { - /* To avoid problems with overflow limit this to 2^32. */ - delta = INT32_MAX; + } + if (active_timers[QEMU_CLOCK_HOST]) { + int64_t hdelta = active_timers[QEMU_CLOCK_HOST]->expire_time - + qemu_get_clock(host_clock); + if (hdelta < delta) + delta = hdelta; } if (delta < 0) @@ -1386,7 +1423,7 @@ static int64_t qemu_next_deadline(void) return delta; } -#if defined(__linux__) || defined(_WIN32) +#if defined(__linux__) static uint64_t qemu_next_deadline_dyntick(void) { int64_t delta; @@ -1397,8 +1434,8 @@ static uint64_t qemu_next_deadline_dyntick(void) else delta = (qemu_next_deadline() + 999) / 1000; - if (active_timers[QEMU_TIMER_REALTIME]) { - rtdelta = (active_timers[QEMU_TIMER_REALTIME]->expire_time - + if (active_timers[QEMU_CLOCK_REALTIME]) { + rtdelta = (active_timers[QEMU_CLOCK_REALTIME]->expire_time - qemu_get_clock(rt_clock))*1000; if (rtdelta < delta) delta = rtdelta; @@ -1451,7 +1488,7 @@ static int hpet_start_timer(struct qemu_alarm_timer *t) struct hpet_info info; int r, fd; - fd = open("/dev/hpet", O_RDONLY); + fd = qemu_open("/dev/hpet", O_RDONLY); if (fd < 0) return -1; @@ -1500,7 +1537,7 @@ static int rtc_start_timer(struct qemu_alarm_timer *t) int rtc_fd; unsigned long current_rtc_freq = 0; - TFR(rtc_fd = open("/dev/rtc", O_RDONLY)); + TFR(rtc_fd = qemu_open("/dev/rtc", O_RDONLY)); if (rtc_fd < 0) return -1; ioctl(rtc_fd, RTC_IRQP_READ, ¤t_rtc_freq); @@ -1580,8 +1617,9 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t) int64_t nearest_delta_us = INT64_MAX; int64_t current_us; - if (!active_timers[QEMU_TIMER_REALTIME] && - !active_timers[QEMU_TIMER_VIRTUAL]) + if (!active_timers[QEMU_CLOCK_REALTIME] && + !active_timers[QEMU_CLOCK_VIRTUAL] && + !active_timers[QEMU_CLOCK_HOST]) return; nearest_delta_us = qemu_next_deadline_dyntick(); @@ -1675,7 +1713,8 @@ static int win32_start_timer(struct qemu_alarm_timer *t) flags); if (!data->timerId) { - perror("Failed to initialize win32 alarm timer"); + fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n", + GetLastError()); timeEndPeriod(data->period); return -1; } @@ -1694,15 +1733,12 @@ static void win32_stop_timer(struct qemu_alarm_timer *t) static void win32_rearm_timer(struct qemu_alarm_timer *t) { struct qemu_alarm_win32 *data = t->priv; - uint64_t nearest_delta_us; - if (!active_timers[QEMU_TIMER_REALTIME] && - !active_timers[QEMU_TIMER_VIRTUAL]) + if (!active_timers[QEMU_CLOCK_REALTIME] && + !active_timers[QEMU_CLOCK_VIRTUAL] && + !active_timers[QEMU_CLOCK_HOST]) return; - nearest_delta_us = qemu_next_deadline_dyntick(); - nearest_delta_us /= 1000; - timeKillEvent(data->timerId); data->timerId = timeSetEvent(1, @@ -1712,7 +1748,8 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t) TIME_ONESHOT | TIME_PERIODIC); if (!data->timerId) { - perror("Failed to re-arm win32 alarm timer"); + fprintf(stderr, "Failed to re-arm win32 alarm timer %ld\n", + GetLastError()); timeEndPeriod(data->period); exit(1); @@ -3188,7 +3225,7 @@ static int ram_save_block(QEMUFile *f) return found; } -static uint64_t bytes_transferred = 0; +static uint64_t bytes_transferred; static ram_addr_t ram_save_remaining(void) { @@ -3231,6 +3268,8 @@ static int ram_save_live(QEMUFile *f, int stage, void *opaque) } if (stage == 1) { + bytes_transferred = 0; + /* Make sure all dirty bits are set */ for (addr = 0; addr < last_ram_offset; addr += TARGET_PAGE_SIZE) { if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) @@ -3244,7 +3283,7 @@ static int ram_save_live(QEMUFile *f, int stage, void *opaque) } bytes_transferred_last = bytes_transferred; - bwidth = get_clock(); + bwidth = qemu_get_clock_ns(rt_clock); while (!qemu_file_rate_limit(f)) { int ret; @@ -3255,7 +3294,7 @@ static int ram_save_live(QEMUFile *f, int stage, void *opaque) break; } - bwidth = get_clock() - bwidth; + bwidth = qemu_get_clock_ns(rt_clock) - bwidth; bwidth = (bytes_transferred - bytes_transferred_last) / bwidth; /* if we haven't transferred anything this round, force expected_time to a @@ -3264,9 +3303,7 @@ static int ram_save_live(QEMUFile *f, int stage, void *opaque) bwidth = 0.000001; /* try transferring iterative blocks of memory */ - if (stage == 3) { - /* flush all remaining blocks regardless of rate limiting */ while (ram_save_block(f) != 0) { bytes_transferred += TARGET_PAGE_SIZE; @@ -3780,6 +3817,8 @@ static int cpu_can_run(CPUState *env) return 0; if (env->stopped) return 0; + if (!vm_running) + return 0; return 1; } @@ -3822,10 +3861,6 @@ void qemu_notify_event(void) if (env) { cpu_exit(env); -#ifdef USE_KQEMU - if (env->kqemu_enabled) - kqemu_cpu_interrupt(env); -#endif } } @@ -4290,14 +4325,17 @@ void main_loop_wait(int timeout) /* vm time timers */ if (vm_running) { if (!cur_cpu || likely(!(cur_cpu->singlestep_enabled & SSTEP_NOTIMER))) - qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL], + qemu_run_timers(&active_timers[QEMU_CLOCK_VIRTUAL], qemu_get_clock(vm_clock)); } /* real time timers */ - qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME], + qemu_run_timers(&active_timers[QEMU_CLOCK_REALTIME], qemu_get_clock(rt_clock)); + qemu_run_timers(&active_timers[QEMU_CLOCK_HOST], + qemu_get_clock(host_clock)); + /* Check bottom-halves last in case any of the earlier events triggered them. */ qemu_bh_poll(); @@ -4353,14 +4391,15 @@ static void tcg_cpu_exec(void) for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) { CPUState *env = cur_cpu = next_cpu; - if (!vm_running) - break; if (timer_alarm_pending) { timer_alarm_pending = 0; break; } if (cpu_can_run(env)) ret = qemu_cpu_exec(env); + else if (env->stop) + break; + if (ret == EXCP_DEBUG) { gdb_set_stop_cpu(env); debug_requested = 1; @@ -4982,6 +5021,8 @@ int main(int argc, char **argv, char **envp) CPUState *env; int show_vnc_port = 0; + init_clocks(); + qemu_cache_utils_init(envp); QLIST_INIT (&vm_change_state_head); @@ -5819,7 +5860,6 @@ int main(int argc, char **argv, char **envp) } setvbuf(stdout, NULL, _IOLBF, 0); - init_timers(); if (init_timer_alarm() < 0) { fprintf(stderr, "could not initialize alarm timer\n"); exit(1); @@ -6216,8 +6256,11 @@ int main(int argc, char **argv, char **envp) if (len != 1) exit(1); - chdir("/"); - TFR(fd = open("/dev/null", O_RDWR)); + if (chdir("/")) { + perror("not able to chdir to /"); + exit(1); + } + TFR(fd = qemu_open("/dev/null", O_RDWR)); if (fd == -1) exit(1); } @@ -6235,7 +6278,10 @@ int main(int argc, char **argv, char **envp) fprintf(stderr, "chroot failed\n"); exit(1); } - chdir("/"); + if (chdir("/")) { + perror("not able to chdir to /"); + exit(1); + } } if (run_as) { |