if (env->stopped || !vm_running) {
return true;
}
- if (!env->halted || qemu_cpu_has_work(env)) {
+ if (!env->halted || qemu_cpu_has_work(env) ||
+ (kvm_enabled() && kvm_irqchip_in_kernel())) {
return false;
}
return true;
}
-static bool all_cpu_threads_idle(void)
+bool all_cpu_threads_idle(void)
{
CPUState *env;
return true;
}
-static CPUDebugExcpHandler *debug_excp_handler;
-
-CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
+static void cpu_handle_guest_debug(CPUState *env)
{
- CPUDebugExcpHandler *old_handler = debug_excp_handler;
-
- debug_excp_handler = handler;
- return old_handler;
-}
-
-static void cpu_handle_debug_exception(CPUState *env)
-{
- CPUWatchpoint *wp;
-
- if (!env->watchpoint_hit) {
- QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
- wp->flags &= ~BP_WATCHPOINT_HIT;
- }
- }
- if (debug_excp_handler) {
- debug_excp_handler(env);
- }
-
gdb_set_stop_cpu(env);
qemu_system_debug_request();
#ifdef CONFIG_IOTHREAD
prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY, 0, 0);
}
+static void qemu_kvm_eat_signals(CPUState *env)
+{
+ struct timespec ts = { 0, 0 };
+ siginfo_t siginfo;
+ sigset_t waitset;
+ sigset_t chkset;
+ int r;
+
+ sigemptyset(&waitset);
+ sigaddset(&waitset, SIG_IPI);
+ sigaddset(&waitset, SIGBUS);
+
+ do {
+ r = sigtimedwait(&waitset, &siginfo, &ts);
+ if (r == -1 && !(errno == EAGAIN || errno == EINTR)) {
+ perror("sigtimedwait");
+ exit(1);
+ }
+
+ switch (r) {
+ case SIGBUS:
+ if (kvm_on_sigbus_vcpu(env, siginfo.si_code, siginfo.si_addr)) {
+ sigbus_reraise();
+ }
+ break;
+ default:
+ break;
+ }
+
+ r = sigpending(&chkset);
+ if (r == -1) {
+ perror("sigpending");
+ exit(1);
+ }
+ } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS));
+
+#ifndef CONFIG_IOTHREAD
+ if (sigismember(&chkset, SIGIO) || sigismember(&chkset, SIGALRM)) {
+ qemu_notify_event();
+ }
+#endif
+}
+
#else /* !CONFIG_LINUX */
static void qemu_init_sigbus(void)
{
}
+
+static void qemu_kvm_eat_signals(CPUState *env)
+{
+}
#endif /* !CONFIG_LINUX */
#ifndef _WIN32
#endif
}
-static void qemu_kvm_eat_signals(CPUState *env)
-{
- struct timespec ts = { 0, 0 };
- siginfo_t siginfo;
- sigset_t waitset;
- sigset_t chkset;
- int r;
-
- sigemptyset(&waitset);
- sigaddset(&waitset, SIG_IPI);
- sigaddset(&waitset, SIGBUS);
-
- do {
- r = sigtimedwait(&waitset, &siginfo, &ts);
- if (r == -1 && !(errno == EAGAIN || errno == EINTR)) {
- perror("sigtimedwait");
- exit(1);
- }
-
- switch (r) {
- case SIGBUS:
- if (kvm_on_sigbus_vcpu(env, siginfo.si_code, siginfo.si_addr)) {
- sigbus_reraise();
- }
- break;
- default:
- break;
- }
-
- r = sigpending(&chkset);
- if (r == -1) {
- perror("sigpending");
- exit(1);
- }
- } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS));
-
-#ifndef CONFIG_IOTHREAD
- if (sigismember(&chkset, SIGIO) || sigismember(&chkset, SIGALRM)) {
- qemu_notify_event();
- }
-#endif
-}
-
#else /* _WIN32 */
HANDLE qemu_event_handle;
}
}
-static void qemu_kvm_eat_signals(CPUState *env)
-{
-}
-
static int qemu_signal_init(void)
{
return 0;
CPUState *env;
while (all_cpu_threads_idle()) {
+ /* Start accounting real time to the virtual clock if the CPUs
+ are idle. */
+ qemu_clock_warp(vm_clock);
qemu_cond_wait(tcg_halt_cond, &qemu_global_mutex);
}
qemu_mutex_lock(&qemu_global_mutex);
qemu_thread_get_self(env->thread);
+ env->thread_id = qemu_get_thread_id();
r = kvm_init_vcpu(env);
if (r < 0) {
if (cpu_can_run(env)) {
r = kvm_cpu_exec(env);
if (r == EXCP_DEBUG) {
- cpu_handle_debug_exception(env);
+ cpu_handle_guest_debug(env);
}
}
qemu_kvm_wait_io_event(env);
/* signal CPU creation */
qemu_mutex_lock(&qemu_global_mutex);
for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ env->thread_id = qemu_get_thread_id();
env->created = 1;
}
qemu_cond_signal(&qemu_cpu_cond);
while (1) {
cpu_exec_all();
+ if (use_icount && qemu_next_icount_deadline() <= 0) {
+ qemu_notify_event();
+ }
qemu_tcg_wait_io_event();
}
qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
env->icount_decr.u16.low = 0;
env->icount_extra = 0;
- count = qemu_icount_round (qemu_next_deadline());
+ count = qemu_icount_round(qemu_next_icount_deadline());
qemu_icount += count;
decr = (count > 0xffff) ? 0xffff : count;
count -= decr;
{
int r;
+ /* Account partial waits to the vm_clock. */
+ qemu_clock_warp(vm_clock);
+
if (next_cpu == NULL) {
next_cpu = first_cpu;
}
r = tcg_cpu_exec(env);
}
if (r == EXCP_DEBUG) {
- cpu_handle_debug_exception(env);
+ cpu_handle_guest_debug(env);
break;
}
} else if (env->stop || env->stopped) {