2010-03-29 23:23:50 +04:00
|
|
|
/*
|
|
|
|
* QEMU System Emulator
|
|
|
|
*
|
|
|
|
* Copyright (c) 2003-2008 Fabrice Bellard
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
* THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Needed early for CONFIG_BSD etc. */
|
2016-01-26 21:16:56 +03:00
|
|
|
#include "qemu/osdep.h"
|
2016-03-15 18:58:45 +03:00
|
|
|
#include "qemu-common.h"
|
|
|
|
#include "cpu.h"
|
2012-12-17 21:19:49 +04:00
|
|
|
#include "monitor/monitor.h"
|
2014-06-18 10:43:36 +04:00
|
|
|
#include "qapi/qmp/qerror.h"
|
2015-03-17 20:29:20 +03:00
|
|
|
#include "qemu/error-report.h"
|
2012-12-17 21:20:04 +04:00
|
|
|
#include "sysemu/sysemu.h"
|
2016-03-16 21:54:32 +03:00
|
|
|
#include "sysemu/block-backend.h"
|
2012-12-17 21:19:49 +04:00
|
|
|
#include "exec/gdbstub.h"
|
2012-12-17 21:20:04 +04:00
|
|
|
#include "sysemu/dma.h"
|
|
|
|
#include "sysemu/kvm.h"
|
2011-09-21 23:38:35 +04:00
|
|
|
#include "qmp-commands.h"
|
2016-03-15 15:18:37 +03:00
|
|
|
#include "exec/exec-all.h"
|
2010-03-29 23:23:50 +04:00
|
|
|
|
2012-12-17 21:20:00 +04:00
|
|
|
#include "qemu/thread.h"
|
2012-12-17 21:20:04 +04:00
|
|
|
#include "sysemu/cpus.h"
|
|
|
|
#include "sysemu/qtest.h"
|
2012-12-17 21:20:00 +04:00
|
|
|
#include "qemu/main-loop.h"
|
|
|
|
#include "qemu/bitmap.h"
|
2013-09-25 10:20:58 +04:00
|
|
|
#include "qemu/seqlock.h"
|
2014-06-18 10:43:36 +04:00
|
|
|
#include "qapi-event.h"
|
2014-08-20 16:16:33 +04:00
|
|
|
#include "hw/nmi.h"
|
2015-09-17 19:24:05 +03:00
|
|
|
#include "sysemu/replay.h"
|
2011-06-23 12:15:55 +04:00
|
|
|
|
|
|
|
#ifndef _WIN32
|
2012-12-17 21:20:00 +04:00
|
|
|
#include "qemu/compatfd.h"
|
2011-06-23 12:15:55 +04:00
|
|
|
#endif
|
2010-03-29 23:23:50 +04:00
|
|
|
|
2011-02-02 00:15:58 +03:00
|
|
|
#ifdef CONFIG_LINUX
|
|
|
|
|
|
|
|
#include <sys/prctl.h>
|
|
|
|
|
2010-10-11 22:31:21 +04:00
|
|
|
#ifndef PR_MCE_KILL
|
|
|
|
#define PR_MCE_KILL 33
|
|
|
|
#endif
|
|
|
|
|
2011-02-02 00:15:58 +03:00
|
|
|
#ifndef PR_MCE_KILL_SET
|
|
|
|
#define PR_MCE_KILL_SET 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef PR_MCE_KILL_EARLY
|
|
|
|
#define PR_MCE_KILL_EARLY 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* CONFIG_LINUX */
|
|
|
|
|
2013-05-30 00:29:20 +04:00
|
|
|
static CPUState *next_cpu;
|
2014-07-25 13:56:33 +04:00
|
|
|
int64_t max_delay;
|
|
|
|
int64_t max_advance;
|
2010-03-29 23:23:50 +04:00
|
|
|
|
2015-09-08 20:12:33 +03:00
|
|
|
/* vcpu throttling controls */
|
|
|
|
static QEMUTimer *throttle_timer;
|
|
|
|
static unsigned int throttle_percentage;
|
|
|
|
|
|
|
|
#define CPU_THROTTLE_PCT_MIN 1
|
|
|
|
#define CPU_THROTTLE_PCT_MAX 99
|
|
|
|
#define CPU_THROTTLE_TIMESLICE_NS 10000000
|
|
|
|
|
2013-08-02 05:43:09 +04:00
|
|
|
bool cpu_is_stopped(CPUState *cpu)
|
|
|
|
{
|
|
|
|
return cpu->stopped || !runstate_is_running();
|
|
|
|
}
|
|
|
|
|
2013-05-27 01:21:08 +04:00
|
|
|
static bool cpu_thread_is_idle(CPUState *cpu)
|
2012-07-19 19:52:27 +04:00
|
|
|
{
|
2012-05-03 04:11:45 +04:00
|
|
|
if (cpu->stop || cpu->queued_work_first) {
|
2012-07-19 19:52:27 +04:00
|
|
|
return false;
|
|
|
|
}
|
2013-08-02 05:43:09 +04:00
|
|
|
if (cpu_is_stopped(cpu)) {
|
2012-07-19 19:52:27 +04:00
|
|
|
return true;
|
|
|
|
}
|
2013-08-25 20:53:55 +04:00
|
|
|
if (!cpu->halted || cpu_has_work(cpu) ||
|
2013-04-25 00:24:12 +04:00
|
|
|
kvm_halt_in_kernel()) {
|
2012-07-19 19:52:27 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool all_cpu_threads_idle(void)
|
|
|
|
{
|
2013-05-30 00:29:20 +04:00
|
|
|
CPUState *cpu;
|
2012-07-19 19:52:27 +04:00
|
|
|
|
2013-06-25 01:50:24 +04:00
|
|
|
CPU_FOREACH(cpu) {
|
2013-05-30 00:29:20 +04:00
|
|
|
if (!cpu_thread_is_idle(cpu)) {
|
2012-07-19 19:52:27 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-09-12 15:57:37 +04:00
|
|
|
/***********************************************************/
|
|
|
|
/* guest cycle counter */
|
|
|
|
|
2013-10-07 19:18:15 +04:00
|
|
|
/* Protected by TimersState seqlock */
|
|
|
|
|
2015-05-29 18:14:04 +03:00
|
|
|
static bool icount_sleep = true;
|
2014-07-23 13:47:50 +04:00
|
|
|
static int64_t vm_clock_warp_start = -1;
|
2011-09-12 15:57:37 +04:00
|
|
|
/* 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
|
2013-10-07 19:18:15 +04:00
|
|
|
|
2011-09-12 15:57:37 +04:00
|
|
|
static QEMUTimer *icount_rt_timer;
|
|
|
|
static QEMUTimer *icount_vm_timer;
|
|
|
|
static QEMUTimer *icount_warp_timer;
|
|
|
|
|
|
|
|
typedef struct TimersState {
|
2013-09-25 10:20:58 +04:00
|
|
|
/* Protected by BQL. */
|
2011-09-12 15:57:37 +04:00
|
|
|
int64_t cpu_ticks_prev;
|
|
|
|
int64_t cpu_ticks_offset;
|
2013-09-25 10:20:58 +04:00
|
|
|
|
|
|
|
/* cpu_clock_offset can be read out of BQL, so protect it with
|
|
|
|
* this lock.
|
|
|
|
*/
|
|
|
|
QemuSeqLock vm_clock_seqlock;
|
2011-09-12 15:57:37 +04:00
|
|
|
int64_t cpu_clock_offset;
|
|
|
|
int32_t cpu_ticks_enabled;
|
|
|
|
int64_t dummy;
|
2014-08-01 03:37:09 +04:00
|
|
|
|
|
|
|
/* Compensate for varying guest execution speed. */
|
|
|
|
int64_t qemu_icount_bias;
|
|
|
|
/* Only written by TCG thread */
|
|
|
|
int64_t qemu_icount;
|
2011-09-12 15:57:37 +04:00
|
|
|
} TimersState;
|
|
|
|
|
2013-07-21 12:43:00 +04:00
|
|
|
static TimersState timers_state;
|
2011-09-12 15:57:37 +04:00
|
|
|
|
2014-12-08 10:53:45 +03:00
|
|
|
int64_t cpu_get_icount_raw(void)
|
2011-09-12 15:57:37 +04:00
|
|
|
{
|
|
|
|
int64_t icount;
|
2013-05-27 07:17:50 +04:00
|
|
|
CPUState *cpu = current_cpu;
|
2011-09-12 15:57:37 +04:00
|
|
|
|
2014-08-01 03:37:09 +04:00
|
|
|
icount = timers_state.qemu_icount;
|
2013-05-27 07:17:50 +04:00
|
|
|
if (cpu) {
|
2015-06-24 15:16:26 +03:00
|
|
|
if (!cpu->can_do_io) {
|
2014-12-08 10:53:45 +03:00
|
|
|
fprintf(stderr, "Bad icount read\n");
|
|
|
|
exit(1);
|
2011-09-12 15:57:37 +04:00
|
|
|
}
|
2013-08-26 07:51:49 +04:00
|
|
|
icount -= (cpu->icount_decr.u16.low + cpu->icount_extra);
|
2011-09-12 15:57:37 +04:00
|
|
|
}
|
2014-12-08 10:53:45 +03:00
|
|
|
return icount;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the virtual CPU time, based on the instruction counter. */
|
|
|
|
static int64_t cpu_get_icount_locked(void)
|
|
|
|
{
|
|
|
|
int64_t icount = cpu_get_icount_raw();
|
2014-08-01 03:37:15 +04:00
|
|
|
return timers_state.qemu_icount_bias + cpu_icount_to_ns(icount);
|
2011-09-12 15:57:37 +04:00
|
|
|
}
|
|
|
|
|
2013-10-03 17:17:25 +04:00
|
|
|
int64_t cpu_get_icount(void)
|
|
|
|
{
|
|
|
|
int64_t icount;
|
|
|
|
unsigned start;
|
|
|
|
|
|
|
|
do {
|
|
|
|
start = seqlock_read_begin(&timers_state.vm_clock_seqlock);
|
|
|
|
icount = cpu_get_icount_locked();
|
|
|
|
} while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start));
|
|
|
|
|
|
|
|
return icount;
|
|
|
|
}
|
|
|
|
|
2014-08-01 03:37:15 +04:00
|
|
|
int64_t cpu_icount_to_ns(int64_t icount)
|
|
|
|
{
|
|
|
|
return icount << icount_time_shift;
|
|
|
|
}
|
|
|
|
|
2016-07-29 14:05:38 +03:00
|
|
|
/* return the time elapsed in VM between vm_start and vm_stop. Unless
|
|
|
|
* icount is active, cpu_get_ticks() uses units of the host CPU cycle
|
|
|
|
* counter.
|
|
|
|
*
|
|
|
|
* Caller must hold the BQL
|
|
|
|
*/
|
2011-09-12 15:57:37 +04:00
|
|
|
int64_t cpu_get_ticks(void)
|
|
|
|
{
|
2013-10-28 20:32:18 +04:00
|
|
|
int64_t ticks;
|
|
|
|
|
2011-09-12 15:57:37 +04:00
|
|
|
if (use_icount) {
|
|
|
|
return cpu_get_icount();
|
|
|
|
}
|
2013-10-28 20:32:18 +04:00
|
|
|
|
|
|
|
ticks = timers_state.cpu_ticks_offset;
|
|
|
|
if (timers_state.cpu_ticks_enabled) {
|
2015-09-25 17:42:21 +03:00
|
|
|
ticks += cpu_get_host_ticks();
|
2013-10-28 20:32:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (timers_state.cpu_ticks_prev > ticks) {
|
|
|
|
/* Note: non increasing ticks may happen if the host uses
|
|
|
|
software suspend */
|
|
|
|
timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks;
|
|
|
|
ticks = timers_state.cpu_ticks_prev;
|
2011-09-12 15:57:37 +04:00
|
|
|
}
|
2013-10-28 20:32:18 +04:00
|
|
|
|
|
|
|
timers_state.cpu_ticks_prev = ticks;
|
|
|
|
return ticks;
|
2011-09-12 15:57:37 +04:00
|
|
|
}
|
|
|
|
|
2013-09-25 10:20:58 +04:00
|
|
|
static int64_t cpu_get_clock_locked(void)
|
2011-09-12 15:57:37 +04:00
|
|
|
{
|
2016-07-29 14:05:37 +03:00
|
|
|
int64_t time;
|
2013-09-25 10:20:58 +04:00
|
|
|
|
2016-07-29 14:05:37 +03:00
|
|
|
time = timers_state.cpu_clock_offset;
|
2013-10-28 20:32:18 +04:00
|
|
|
if (timers_state.cpu_ticks_enabled) {
|
2016-07-29 14:05:37 +03:00
|
|
|
time += get_clock();
|
2011-09-12 15:57:37 +04:00
|
|
|
}
|
2013-09-25 10:20:58 +04:00
|
|
|
|
2016-07-29 14:05:37 +03:00
|
|
|
return time;
|
2013-09-25 10:20:58 +04:00
|
|
|
}
|
|
|
|
|
2016-07-29 14:05:38 +03:00
|
|
|
/* Return the monotonic time elapsed in VM, i.e.,
|
2016-09-15 12:24:22 +03:00
|
|
|
* the time between vm_start and vm_stop
|
|
|
|
*/
|
2013-09-25 10:20:58 +04:00
|
|
|
int64_t cpu_get_clock(void)
|
|
|
|
{
|
|
|
|
int64_t ti;
|
|
|
|
unsigned start;
|
|
|
|
|
|
|
|
do {
|
|
|
|
start = seqlock_read_begin(&timers_state.vm_clock_seqlock);
|
|
|
|
ti = cpu_get_clock_locked();
|
|
|
|
} while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start));
|
|
|
|
|
|
|
|
return ti;
|
2011-09-12 15:57:37 +04:00
|
|
|
}
|
|
|
|
|
2013-09-25 10:20:58 +04:00
|
|
|
/* enable cpu_get_ticks()
|
2016-07-08 13:31:37 +03:00
|
|
|
* Caller must hold BQL which serves as mutex for vm_clock_seqlock.
|
2013-09-25 10:20:58 +04:00
|
|
|
*/
|
2011-09-12 15:57:37 +04:00
|
|
|
void cpu_enable_ticks(void)
|
|
|
|
{
|
2013-09-25 10:20:58 +04:00
|
|
|
/* Here, the really thing protected by seqlock is cpu_clock_offset. */
|
2016-06-08 21:55:21 +03:00
|
|
|
seqlock_write_begin(&timers_state.vm_clock_seqlock);
|
2011-09-12 15:57:37 +04:00
|
|
|
if (!timers_state.cpu_ticks_enabled) {
|
2015-09-25 17:42:21 +03:00
|
|
|
timers_state.cpu_ticks_offset -= cpu_get_host_ticks();
|
2011-09-12 15:57:37 +04:00
|
|
|
timers_state.cpu_clock_offset -= get_clock();
|
|
|
|
timers_state.cpu_ticks_enabled = 1;
|
|
|
|
}
|
2016-06-08 21:55:21 +03:00
|
|
|
seqlock_write_end(&timers_state.vm_clock_seqlock);
|
2011-09-12 15:57:37 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* disable cpu_get_ticks() : the clock is stopped. You must not call
|
2013-09-25 10:20:58 +04:00
|
|
|
* cpu_get_ticks() after that.
|
2016-07-08 13:31:37 +03:00
|
|
|
* Caller must hold BQL which serves as mutex for vm_clock_seqlock.
|
2013-09-25 10:20:58 +04:00
|
|
|
*/
|
2011-09-12 15:57:37 +04:00
|
|
|
void cpu_disable_ticks(void)
|
|
|
|
{
|
2013-09-25 10:20:58 +04:00
|
|
|
/* Here, the really thing protected by seqlock is cpu_clock_offset. */
|
2016-06-08 21:55:21 +03:00
|
|
|
seqlock_write_begin(&timers_state.vm_clock_seqlock);
|
2011-09-12 15:57:37 +04:00
|
|
|
if (timers_state.cpu_ticks_enabled) {
|
2015-09-25 17:42:21 +03:00
|
|
|
timers_state.cpu_ticks_offset += cpu_get_host_ticks();
|
2013-09-25 10:20:58 +04:00
|
|
|
timers_state.cpu_clock_offset = cpu_get_clock_locked();
|
2011-09-12 15:57:37 +04:00
|
|
|
timers_state.cpu_ticks_enabled = 0;
|
|
|
|
}
|
2016-06-08 21:55:21 +03:00
|
|
|
seqlock_write_end(&timers_state.vm_clock_seqlock);
|
2011-09-12 15:57:37 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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. */
|
2016-03-21 19:02:30 +03:00
|
|
|
#define ICOUNT_WOBBLE (NANOSECONDS_PER_SECOND / 10)
|
2011-09-12 15:57:37 +04:00
|
|
|
|
|
|
|
static void icount_adjust(void)
|
|
|
|
{
|
|
|
|
int64_t cur_time;
|
|
|
|
int64_t cur_icount;
|
|
|
|
int64_t delta;
|
2013-10-07 19:18:15 +04:00
|
|
|
|
|
|
|
/* Protected by TimersState mutex. */
|
2011-09-12 15:57:37 +04:00
|
|
|
static int64_t last_delta;
|
2013-10-07 19:21:51 +04:00
|
|
|
|
2011-09-12 15:57:37 +04:00
|
|
|
/* If the VM is not running, then do nothing. */
|
|
|
|
if (!runstate_is_running()) {
|
|
|
|
return;
|
|
|
|
}
|
2013-10-07 19:21:51 +04:00
|
|
|
|
2016-06-08 21:55:21 +03:00
|
|
|
seqlock_write_begin(&timers_state.vm_clock_seqlock);
|
2013-10-03 17:17:25 +04:00
|
|
|
cur_time = cpu_get_clock_locked();
|
|
|
|
cur_icount = cpu_get_icount_locked();
|
2013-10-07 19:21:51 +04:00
|
|
|
|
2011-09-12 15:57:37 +04:00
|
|
|
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;
|
2014-08-01 03:37:09 +04:00
|
|
|
timers_state.qemu_icount_bias = cur_icount
|
|
|
|
- (timers_state.qemu_icount << icount_time_shift);
|
2016-06-08 21:55:21 +03:00
|
|
|
seqlock_write_end(&timers_state.vm_clock_seqlock);
|
2011-09-12 15:57:37 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void icount_adjust_rt(void *opaque)
|
|
|
|
{
|
2013-08-21 19:03:02 +04:00
|
|
|
timer_mod(icount_rt_timer,
|
2015-01-12 15:00:43 +03:00
|
|
|
qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) + 1000);
|
2011-09-12 15:57:37 +04:00
|
|
|
icount_adjust();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void icount_adjust_vm(void *opaque)
|
|
|
|
{
|
2013-08-21 19:03:02 +04:00
|
|
|
timer_mod(icount_vm_timer,
|
|
|
|
qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
|
2016-03-21 19:02:30 +03:00
|
|
|
NANOSECONDS_PER_SECOND / 10);
|
2011-09-12 15:57:37 +04:00
|
|
|
icount_adjust();
|
|
|
|
}
|
|
|
|
|
|
|
|
static int64_t qemu_icount_round(int64_t count)
|
|
|
|
{
|
|
|
|
return (count + (1 << icount_time_shift) - 1) >> icount_time_shift;
|
|
|
|
}
|
|
|
|
|
2015-09-17 19:24:39 +03:00
|
|
|
static void icount_warp_rt(void)
|
2011-09-12 15:57:37 +04:00
|
|
|
{
|
2016-04-04 17:35:48 +03:00
|
|
|
unsigned seq;
|
|
|
|
int64_t warp_start;
|
|
|
|
|
2013-10-03 17:17:25 +04:00
|
|
|
/* The icount_warp_timer is rescheduled soon after vm_clock_warp_start
|
|
|
|
* changes from -1 to another value, so the race here is okay.
|
|
|
|
*/
|
2016-04-04 17:35:48 +03:00
|
|
|
do {
|
|
|
|
seq = seqlock_read_begin(&timers_state.vm_clock_seqlock);
|
|
|
|
warp_start = vm_clock_warp_start;
|
|
|
|
} while (seqlock_read_retry(&timers_state.vm_clock_seqlock, seq));
|
|
|
|
|
|
|
|
if (warp_start == -1) {
|
2011-09-12 15:57:37 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-06-08 21:55:21 +03:00
|
|
|
seqlock_write_begin(&timers_state.vm_clock_seqlock);
|
2011-09-12 15:57:37 +04:00
|
|
|
if (runstate_is_running()) {
|
2015-09-17 19:24:28 +03:00
|
|
|
int64_t clock = REPLAY_CLOCK(REPLAY_CLOCK_VIRTUAL_RT,
|
|
|
|
cpu_get_clock_locked());
|
2013-10-07 19:26:07 +04:00
|
|
|
int64_t warp_delta;
|
|
|
|
|
|
|
|
warp_delta = clock - vm_clock_warp_start;
|
|
|
|
if (use_icount == 2) {
|
2011-09-12 15:57:37 +04:00
|
|
|
/*
|
2013-08-21 19:03:02 +04:00
|
|
|
* In adaptive mode, do not let QEMU_CLOCK_VIRTUAL run too
|
2011-09-12 15:57:37 +04:00
|
|
|
* far ahead of real time.
|
|
|
|
*/
|
2013-10-03 17:17:25 +04:00
|
|
|
int64_t cur_icount = cpu_get_icount_locked();
|
2014-11-26 13:40:55 +03:00
|
|
|
int64_t delta = clock - cur_icount;
|
2013-10-07 19:26:07 +04:00
|
|
|
warp_delta = MIN(warp_delta, delta);
|
2011-09-12 15:57:37 +04:00
|
|
|
}
|
2014-08-01 03:37:09 +04:00
|
|
|
timers_state.qemu_icount_bias += warp_delta;
|
2011-09-12 15:57:37 +04:00
|
|
|
}
|
|
|
|
vm_clock_warp_start = -1;
|
2016-06-08 21:55:21 +03:00
|
|
|
seqlock_write_end(&timers_state.vm_clock_seqlock);
|
2013-10-07 19:26:07 +04:00
|
|
|
|
|
|
|
if (qemu_clock_expired(QEMU_CLOCK_VIRTUAL)) {
|
|
|
|
qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
|
|
|
|
}
|
2011-09-12 15:57:37 +04:00
|
|
|
}
|
|
|
|
|
2016-03-10 14:56:09 +03:00
|
|
|
static void icount_timer_cb(void *opaque)
|
2015-09-17 19:24:39 +03:00
|
|
|
{
|
2016-03-10 14:56:09 +03:00
|
|
|
/* No need for a checkpoint because the timer already synchronizes
|
|
|
|
* with CHECKPOINT_CLOCK_VIRTUAL_RT.
|
|
|
|
*/
|
|
|
|
icount_warp_rt();
|
2015-09-17 19:24:39 +03:00
|
|
|
}
|
|
|
|
|
2012-03-28 17:42:04 +04:00
|
|
|
void qtest_clock_warp(int64_t dest)
|
|
|
|
{
|
2013-08-21 19:03:02 +04:00
|
|
|
int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
2015-01-19 12:51:43 +03:00
|
|
|
AioContext *aio_context;
|
2012-03-28 17:42:04 +04:00
|
|
|
assert(qtest_enabled());
|
2015-01-19 12:51:43 +03:00
|
|
|
aio_context = qemu_get_aio_context();
|
2012-03-28 17:42:04 +04:00
|
|
|
while (clock < dest) {
|
2013-08-21 19:03:02 +04:00
|
|
|
int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
|
2014-06-10 13:10:28 +04:00
|
|
|
int64_t warp = qemu_soonest_timeout(dest - clock, deadline);
|
2015-01-19 12:51:43 +03:00
|
|
|
|
2016-06-08 21:55:21 +03:00
|
|
|
seqlock_write_begin(&timers_state.vm_clock_seqlock);
|
2014-08-01 03:37:09 +04:00
|
|
|
timers_state.qemu_icount_bias += warp;
|
2016-06-08 21:55:21 +03:00
|
|
|
seqlock_write_end(&timers_state.vm_clock_seqlock);
|
2013-10-03 17:17:25 +04:00
|
|
|
|
2013-08-21 19:03:02 +04:00
|
|
|
qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL);
|
2015-01-19 12:51:43 +03:00
|
|
|
timerlist_run_timers(aio_context->tlg.tl[QEMU_CLOCK_VIRTUAL]);
|
2013-08-21 19:03:02 +04:00
|
|
|
clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
2012-03-28 17:42:04 +04:00
|
|
|
}
|
2013-08-21 19:03:02 +04:00
|
|
|
qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
|
2012-03-28 17:42:04 +04:00
|
|
|
}
|
|
|
|
|
2016-03-10 14:56:09 +03:00
|
|
|
void qemu_start_warp_timer(void)
|
2011-09-12 15:57:37 +04:00
|
|
|
{
|
2013-10-07 19:30:02 +04:00
|
|
|
int64_t clock;
|
2011-09-12 15:57:37 +04:00
|
|
|
int64_t deadline;
|
|
|
|
|
2016-03-10 14:56:09 +03:00
|
|
|
if (!use_icount) {
|
2011-09-12 15:57:37 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-09-17 19:24:44 +03:00
|
|
|
/* Nothing to do if the VM is stopped: QEMU_CLOCK_VIRTUAL timers
|
|
|
|
* do not fire, so computing the deadline does not make sense.
|
|
|
|
*/
|
|
|
|
if (!runstate_is_running()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* warp clock deterministically in record/replay mode */
|
2016-03-10 14:56:09 +03:00
|
|
|
if (!replay_checkpoint(CHECKPOINT_CLOCK_WARP_START)) {
|
2015-09-17 19:24:44 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-10-07 19:30:02 +04:00
|
|
|
if (!all_cpu_threads_idle()) {
|
2011-09-12 15:57:37 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-03-28 17:42:04 +04:00
|
|
|
if (qtest_enabled()) {
|
|
|
|
/* When testing, qtest commands advance icount. */
|
2016-03-10 14:56:09 +03:00
|
|
|
return;
|
2012-03-28 17:42:04 +04:00
|
|
|
}
|
|
|
|
|
2013-08-21 19:02:57 +04:00
|
|
|
/* We want to use the earliest deadline from ALL vm_clocks */
|
2014-11-26 13:40:55 +03:00
|
|
|
clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT);
|
2013-08-21 19:03:02 +04:00
|
|
|
deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
|
2013-10-07 19:30:02 +04:00
|
|
|
if (deadline < 0) {
|
2015-05-29 18:14:06 +03:00
|
|
|
static bool notified;
|
|
|
|
if (!icount_sleep && !notified) {
|
|
|
|
error_report("WARNING: icount sleep disabled and no active timers");
|
|
|
|
notified = true;
|
|
|
|
}
|
2013-10-07 19:30:02 +04:00
|
|
|
return;
|
2013-08-21 19:02:57 +04:00
|
|
|
}
|
|
|
|
|
2011-09-12 15:57:37 +04:00
|
|
|
if (deadline > 0) {
|
|
|
|
/*
|
2013-08-21 19:03:02 +04:00
|
|
|
* Ensure QEMU_CLOCK_VIRTUAL proceeds even when the virtual CPU goes to
|
2011-09-12 15:57:37 +04:00
|
|
|
* sleep. Otherwise, the CPU might be waiting for a future timer
|
|
|
|
* interrupt to wake it up, but the interrupt never comes because
|
|
|
|
* the vCPU isn't running any insns and thus doesn't advance the
|
2013-08-21 19:03:02 +04:00
|
|
|
* QEMU_CLOCK_VIRTUAL.
|
2011-09-12 15:57:37 +04:00
|
|
|
*/
|
2015-05-29 18:14:04 +03:00
|
|
|
if (!icount_sleep) {
|
|
|
|
/*
|
|
|
|
* We never let VCPUs sleep in no sleep icount mode.
|
|
|
|
* If there is a pending QEMU_CLOCK_VIRTUAL timer we just advance
|
|
|
|
* to the next QEMU_CLOCK_VIRTUAL event and notify it.
|
|
|
|
* It is useful when we want a deterministic execution time,
|
|
|
|
* isolated from host latencies.
|
|
|
|
*/
|
2016-06-08 21:55:21 +03:00
|
|
|
seqlock_write_begin(&timers_state.vm_clock_seqlock);
|
2015-05-29 18:14:04 +03:00
|
|
|
timers_state.qemu_icount_bias += deadline;
|
2016-06-08 21:55:21 +03:00
|
|
|
seqlock_write_end(&timers_state.vm_clock_seqlock);
|
2015-05-29 18:14:04 +03:00
|
|
|
qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* We do stop VCPUs and only advance QEMU_CLOCK_VIRTUAL after some
|
|
|
|
* "real" time, (related to the time left until the next event) has
|
|
|
|
* passed. The QEMU_CLOCK_VIRTUAL_RT clock will do this.
|
|
|
|
* This avoids that the warps are visible externally; for example,
|
|
|
|
* you will not be sending network packets continuously instead of
|
|
|
|
* every 100ms.
|
|
|
|
*/
|
2016-06-08 21:55:21 +03:00
|
|
|
seqlock_write_begin(&timers_state.vm_clock_seqlock);
|
2015-05-29 18:14:04 +03:00
|
|
|
if (vm_clock_warp_start == -1 || vm_clock_warp_start > clock) {
|
|
|
|
vm_clock_warp_start = clock;
|
|
|
|
}
|
2016-06-08 21:55:21 +03:00
|
|
|
seqlock_write_end(&timers_state.vm_clock_seqlock);
|
2015-05-29 18:14:04 +03:00
|
|
|
timer_mod_anticipate(icount_warp_timer, clock + deadline);
|
2013-10-07 19:30:02 +04:00
|
|
|
}
|
2013-08-21 19:02:57 +04:00
|
|
|
} else if (deadline == 0) {
|
2013-08-21 19:03:02 +04:00
|
|
|
qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
|
2011-09-12 15:57:37 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-10 14:56:09 +03:00
|
|
|
static void qemu_account_warp_timer(void)
|
|
|
|
{
|
|
|
|
if (!use_icount || !icount_sleep) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Nothing to do if the VM is stopped: QEMU_CLOCK_VIRTUAL timers
|
|
|
|
* do not fire, so computing the deadline does not make sense.
|
|
|
|
*/
|
|
|
|
if (!runstate_is_running()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* warp clock deterministically in record/replay mode */
|
|
|
|
if (!replay_checkpoint(CHECKPOINT_CLOCK_WARP_ACCOUNT)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
timer_del(icount_warp_timer);
|
|
|
|
icount_warp_rt();
|
|
|
|
}
|
|
|
|
|
2014-08-01 03:37:10 +04:00
|
|
|
static bool icount_state_needed(void *opaque)
|
|
|
|
{
|
|
|
|
return use_icount;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is a subsection for icount migration.
|
|
|
|
*/
|
|
|
|
static const VMStateDescription icount_vmstate_timers = {
|
|
|
|
.name = "timer/icount",
|
|
|
|
.version_id = 1,
|
|
|
|
.minimum_version_id = 1,
|
2014-09-23 16:09:54 +04:00
|
|
|
.needed = icount_state_needed,
|
2014-08-01 03:37:10 +04:00
|
|
|
.fields = (VMStateField[]) {
|
|
|
|
VMSTATE_INT64(qemu_icount_bias, TimersState),
|
|
|
|
VMSTATE_INT64(qemu_icount, TimersState),
|
|
|
|
VMSTATE_END_OF_LIST()
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-09-12 15:57:37 +04:00
|
|
|
static const VMStateDescription vmstate_timers = {
|
|
|
|
.name = "timer",
|
|
|
|
.version_id = 2,
|
|
|
|
.minimum_version_id = 1,
|
2014-04-16 18:01:33 +04:00
|
|
|
.fields = (VMStateField[]) {
|
2011-09-12 15:57:37 +04:00
|
|
|
VMSTATE_INT64(cpu_ticks_offset, TimersState),
|
|
|
|
VMSTATE_INT64(dummy, TimersState),
|
|
|
|
VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2),
|
|
|
|
VMSTATE_END_OF_LIST()
|
2014-08-01 03:37:10 +04:00
|
|
|
},
|
2014-09-23 16:09:54 +04:00
|
|
|
.subsections = (const VMStateDescription*[]) {
|
|
|
|
&icount_vmstate_timers,
|
|
|
|
NULL
|
2011-09-12 15:57:37 +04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-08-02 20:27:33 +03:00
|
|
|
static void cpu_throttle_thread(CPUState *cpu, void *opaque)
|
2015-09-08 20:12:33 +03:00
|
|
|
{
|
|
|
|
double pct;
|
|
|
|
double throttle_ratio;
|
|
|
|
long sleeptime_ns;
|
|
|
|
|
|
|
|
if (!cpu_throttle_get_percentage()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pct = (double)cpu_throttle_get_percentage()/100;
|
|
|
|
throttle_ratio = pct / (1 - pct);
|
|
|
|
sleeptime_ns = (long)(throttle_ratio * CPU_THROTTLE_TIMESLICE_NS);
|
|
|
|
|
|
|
|
qemu_mutex_unlock_iothread();
|
|
|
|
atomic_set(&cpu->throttle_thread_scheduled, 0);
|
|
|
|
g_usleep(sleeptime_ns / 1000); /* Convert ns to us for usleep call */
|
|
|
|
qemu_mutex_lock_iothread();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void cpu_throttle_timer_tick(void *opaque)
|
|
|
|
{
|
|
|
|
CPUState *cpu;
|
|
|
|
double pct;
|
|
|
|
|
|
|
|
/* Stop the timer if needed */
|
|
|
|
if (!cpu_throttle_get_percentage()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
CPU_FOREACH(cpu) {
|
|
|
|
if (!atomic_xchg(&cpu->throttle_thread_scheduled, 1)) {
|
2016-08-02 20:27:33 +03:00
|
|
|
async_run_on_cpu(cpu, cpu_throttle_thread, NULL);
|
2015-09-08 20:12:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pct = (double)cpu_throttle_get_percentage()/100;
|
|
|
|
timer_mod(throttle_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT) +
|
|
|
|
CPU_THROTTLE_TIMESLICE_NS / (1-pct));
|
|
|
|
}
|
|
|
|
|
|
|
|
void cpu_throttle_set(int new_throttle_pct)
|
|
|
|
{
|
|
|
|
/* Ensure throttle percentage is within valid range */
|
|
|
|
new_throttle_pct = MIN(new_throttle_pct, CPU_THROTTLE_PCT_MAX);
|
|
|
|
new_throttle_pct = MAX(new_throttle_pct, CPU_THROTTLE_PCT_MIN);
|
|
|
|
|
|
|
|
atomic_set(&throttle_percentage, new_throttle_pct);
|
|
|
|
|
|
|
|
timer_mod(throttle_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT) +
|
|
|
|
CPU_THROTTLE_TIMESLICE_NS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cpu_throttle_stop(void)
|
|
|
|
{
|
|
|
|
atomic_set(&throttle_percentage, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cpu_throttle_active(void)
|
|
|
|
{
|
|
|
|
return (cpu_throttle_get_percentage() != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int cpu_throttle_get_percentage(void)
|
|
|
|
{
|
|
|
|
return atomic_read(&throttle_percentage);
|
|
|
|
}
|
|
|
|
|
2014-09-01 09:34:49 +04:00
|
|
|
void cpu_ticks_init(void)
|
|
|
|
{
|
2016-06-08 21:55:20 +03:00
|
|
|
seqlock_init(&timers_state.vm_clock_seqlock);
|
2014-09-01 09:34:49 +04:00
|
|
|
vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
|
2015-09-08 20:12:33 +03:00
|
|
|
throttle_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT,
|
|
|
|
cpu_throttle_timer_tick, NULL);
|
2014-09-01 09:34:49 +04:00
|
|
|
}
|
|
|
|
|
2014-07-25 13:56:28 +04:00
|
|
|
void configure_icount(QemuOpts *opts, Error **errp)
|
2011-09-12 15:57:37 +04:00
|
|
|
{
|
2014-07-25 13:56:28 +04:00
|
|
|
const char *option;
|
2014-07-25 13:56:29 +04:00
|
|
|
char *rem_str = NULL;
|
2014-07-25 13:56:28 +04:00
|
|
|
|
|
|
|
option = qemu_opt_get(opts, "shift");
|
2011-09-12 15:57:37 +04:00
|
|
|
if (!option) {
|
2014-07-25 13:56:29 +04:00
|
|
|
if (qemu_opt_get(opts, "align") != NULL) {
|
|
|
|
error_setg(errp, "Please specify shift option when using align");
|
|
|
|
}
|
2011-09-12 15:57:37 +04:00
|
|
|
return;
|
|
|
|
}
|
2015-05-29 18:14:05 +03:00
|
|
|
|
|
|
|
icount_sleep = qemu_opt_get_bool(opts, "sleep", true);
|
2015-05-29 18:14:04 +03:00
|
|
|
if (icount_sleep) {
|
|
|
|
icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT,
|
2016-03-10 14:56:09 +03:00
|
|
|
icount_timer_cb, NULL);
|
2015-05-29 18:14:04 +03:00
|
|
|
}
|
2015-05-29 18:14:05 +03:00
|
|
|
|
2014-07-25 13:56:29 +04:00
|
|
|
icount_align_option = qemu_opt_get_bool(opts, "align", false);
|
2015-05-29 18:14:05 +03:00
|
|
|
|
|
|
|
if (icount_align_option && !icount_sleep) {
|
2016-02-26 18:16:51 +03:00
|
|
|
error_setg(errp, "align=on and sleep=off are incompatible");
|
2015-05-29 18:14:05 +03:00
|
|
|
}
|
2011-09-12 15:57:37 +04:00
|
|
|
if (strcmp(option, "auto") != 0) {
|
2014-07-25 13:56:29 +04:00
|
|
|
errno = 0;
|
|
|
|
icount_time_shift = strtol(option, &rem_str, 0);
|
|
|
|
if (errno != 0 || *rem_str != '\0' || !strlen(option)) {
|
|
|
|
error_setg(errp, "icount: Invalid shift value");
|
|
|
|
}
|
2011-09-12 15:57:37 +04:00
|
|
|
use_icount = 1;
|
|
|
|
return;
|
2014-07-25 13:56:29 +04:00
|
|
|
} else if (icount_align_option) {
|
|
|
|
error_setg(errp, "shift=auto and align=on are incompatible");
|
2015-05-29 18:14:05 +03:00
|
|
|
} else if (!icount_sleep) {
|
2016-02-26 18:16:51 +03:00
|
|
|
error_setg(errp, "shift=auto and sleep=off are incompatible");
|
2011-09-12 15:57:37 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
use_icount = 2;
|
|
|
|
|
|
|
|
/* 125MIPS seems a reasonable initial guess at the guest speed.
|
|
|
|
It will be corrected fairly quickly anyway. */
|
|
|
|
icount_time_shift = 3;
|
|
|
|
|
|
|
|
/* 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. */
|
2014-11-26 13:40:55 +03:00
|
|
|
icount_rt_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL_RT,
|
|
|
|
icount_adjust_rt, NULL);
|
2013-08-21 19:03:02 +04:00
|
|
|
timer_mod(icount_rt_timer,
|
2014-11-26 13:40:55 +03:00
|
|
|
qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) + 1000);
|
2013-08-21 19:03:02 +04:00
|
|
|
icount_vm_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
|
|
|
|
icount_adjust_vm, NULL);
|
|
|
|
timer_mod(icount_vm_timer,
|
|
|
|
qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
|
2016-03-21 19:02:30 +03:00
|
|
|
NANOSECONDS_PER_SECOND / 10);
|
2011-09-12 15:57:37 +04:00
|
|
|
}
|
|
|
|
|
2010-03-29 23:23:50 +04:00
|
|
|
/***********************************************************/
|
|
|
|
void hw_error(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
2012-12-17 09:18:02 +04:00
|
|
|
CPUState *cpu;
|
2010-03-29 23:23:50 +04:00
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
fprintf(stderr, "qemu: hardware error: ");
|
|
|
|
vfprintf(stderr, fmt, ap);
|
|
|
|
fprintf(stderr, "\n");
|
2013-06-25 01:50:24 +04:00
|
|
|
CPU_FOREACH(cpu) {
|
2012-12-17 09:18:02 +04:00
|
|
|
fprintf(stderr, "CPU #%d:\n", cpu->cpu_index);
|
2013-05-27 03:33:50 +04:00
|
|
|
cpu_dump_state(cpu, stderr, fprintf, CPU_DUMP_FPU);
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
va_end(ap);
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
void cpu_synchronize_all_states(void)
|
|
|
|
{
|
2013-05-30 00:29:20 +04:00
|
|
|
CPUState *cpu;
|
2010-03-29 23:23:50 +04:00
|
|
|
|
2013-06-25 01:50:24 +04:00
|
|
|
CPU_FOREACH(cpu) {
|
2013-05-30 00:29:20 +04:00
|
|
|
cpu_synchronize_state(cpu);
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cpu_synchronize_all_post_reset(void)
|
|
|
|
{
|
2013-05-30 00:29:20 +04:00
|
|
|
CPUState *cpu;
|
2010-03-29 23:23:50 +04:00
|
|
|
|
2013-06-25 01:50:24 +04:00
|
|
|
CPU_FOREACH(cpu) {
|
2013-05-30 00:29:20 +04:00
|
|
|
cpu_synchronize_post_reset(cpu);
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cpu_synchronize_all_post_init(void)
|
|
|
|
{
|
2013-05-30 00:29:20 +04:00
|
|
|
CPUState *cpu;
|
2010-03-29 23:23:50 +04:00
|
|
|
|
2013-06-25 01:50:24 +04:00
|
|
|
CPU_FOREACH(cpu) {
|
2013-05-30 00:29:20 +04:00
|
|
|
cpu_synchronize_post_init(cpu);
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-05 15:49:54 +04:00
|
|
|
static int do_vm_stop(RunState state)
|
2010-03-29 23:23:50 +04:00
|
|
|
{
|
2013-07-05 15:49:54 +04:00
|
|
|
int ret = 0;
|
|
|
|
|
2011-07-29 22:36:43 +04:00
|
|
|
if (runstate_is_running()) {
|
2010-03-29 23:23:50 +04:00
|
|
|
cpu_disable_ticks();
|
|
|
|
pause_all_vcpus();
|
2011-07-29 22:04:45 +04:00
|
|
|
runstate_set(state);
|
2011-07-29 21:26:33 +04:00
|
|
|
vm_state_notify(0, state);
|
2014-06-18 10:43:36 +04:00
|
|
|
qapi_event_send_stop(&error_abort);
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
2013-07-05 15:49:54 +04:00
|
|
|
|
2013-07-18 16:52:19 +04:00
|
|
|
bdrv_drain_all();
|
2016-09-26 11:08:16 +03:00
|
|
|
replay_disable_events();
|
2016-09-23 04:45:51 +03:00
|
|
|
ret = bdrv_flush_all();
|
2013-07-18 16:52:19 +04:00
|
|
|
|
2013-07-05 15:49:54 +04:00
|
|
|
return ret;
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
|
2012-05-03 01:42:26 +04:00
|
|
|
static bool cpu_can_run(CPUState *cpu)
|
2010-03-29 23:23:50 +04:00
|
|
|
{
|
2012-05-03 01:10:09 +04:00
|
|
|
if (cpu->stop) {
|
2012-05-03 01:42:26 +04:00
|
|
|
return false;
|
2011-02-07 14:19:14 +03:00
|
|
|
}
|
2013-08-02 05:43:09 +04:00
|
|
|
if (cpu_is_stopped(cpu)) {
|
2012-05-03 01:42:26 +04:00
|
|
|
return false;
|
2011-02-07 14:19:14 +03:00
|
|
|
}
|
2012-05-03 01:42:26 +04:00
|
|
|
return true;
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
|
2013-05-27 04:07:49 +04:00
|
|
|
static void cpu_handle_guest_debug(CPUState *cpu)
|
2011-02-07 14:19:17 +03:00
|
|
|
{
|
2013-05-27 04:06:09 +04:00
|
|
|
gdb_set_stop_cpu(cpu);
|
2011-02-07 14:19:16 +03:00
|
|
|
qemu_system_debug_request();
|
2012-05-03 01:26:21 +04:00
|
|
|
cpu->stopped = true;
|
2010-06-25 18:56:56 +04:00
|
|
|
}
|
|
|
|
|
2011-02-02 00:15:58 +03:00
|
|
|
#ifdef CONFIG_LINUX
|
|
|
|
static void sigbus_reraise(void)
|
|
|
|
{
|
|
|
|
sigset_t set;
|
|
|
|
struct sigaction action;
|
|
|
|
|
|
|
|
memset(&action, 0, sizeof(action));
|
|
|
|
action.sa_handler = SIG_DFL;
|
|
|
|
if (!sigaction(SIGBUS, &action, NULL)) {
|
|
|
|
raise(SIGBUS);
|
|
|
|
sigemptyset(&set);
|
|
|
|
sigaddset(&set, SIGBUS);
|
2016-05-16 20:33:59 +03:00
|
|
|
pthread_sigmask(SIG_UNBLOCK, &set, NULL);
|
2011-02-02 00:15:58 +03:00
|
|
|
}
|
|
|
|
perror("Failed to re-raise SIGBUS!\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sigbus_handler(int n, struct qemu_signalfd_siginfo *siginfo,
|
|
|
|
void *ctx)
|
|
|
|
{
|
|
|
|
if (kvm_on_sigbus(siginfo->ssi_code,
|
|
|
|
(void *)(intptr_t)siginfo->ssi_addr)) {
|
|
|
|
sigbus_reraise();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void qemu_init_sigbus(void)
|
|
|
|
{
|
|
|
|
struct sigaction action;
|
|
|
|
|
|
|
|
memset(&action, 0, sizeof(action));
|
|
|
|
action.sa_flags = SA_SIGINFO;
|
|
|
|
action.sa_sigaction = (void (*)(int, siginfo_t*, void*))sigbus_handler;
|
|
|
|
sigaction(SIGBUS, &action, NULL);
|
|
|
|
|
|
|
|
prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY, 0, 0);
|
|
|
|
}
|
|
|
|
|
2013-01-17 12:30:27 +04:00
|
|
|
static void qemu_kvm_eat_signals(CPUState *cpu)
|
2011-03-15 14:26:12 +03:00
|
|
|
{
|
|
|
|
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:
|
2013-01-17 12:30:27 +04:00
|
|
|
if (kvm_on_sigbus_vcpu(cpu, siginfo.si_code, siginfo.si_addr)) {
|
2011-03-15 14:26:12 +03:00
|
|
|
sigbus_reraise();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = sigpending(&chkset);
|
|
|
|
if (r == -1) {
|
|
|
|
perror("sigpending");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
} while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS));
|
|
|
|
}
|
|
|
|
|
2011-02-02 00:15:58 +03:00
|
|
|
#else /* !CONFIG_LINUX */
|
|
|
|
|
|
|
|
static void qemu_init_sigbus(void)
|
|
|
|
{
|
|
|
|
}
|
2011-03-15 14:26:12 +03:00
|
|
|
|
2013-01-17 12:30:27 +04:00
|
|
|
static void qemu_kvm_eat_signals(CPUState *cpu)
|
2011-03-15 14:26:12 +03:00
|
|
|
{
|
|
|
|
}
|
2011-02-02 00:15:58 +03:00
|
|
|
#endif /* !CONFIG_LINUX */
|
|
|
|
|
2010-03-29 23:23:50 +04:00
|
|
|
#ifndef _WIN32
|
2011-02-02 00:15:52 +03:00
|
|
|
static void dummy_signal(int sig)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-05-27 01:41:00 +04:00
|
|
|
static void qemu_kvm_init_cpu_signals(CPUState *cpu)
|
2011-03-12 19:44:06 +03:00
|
|
|
{
|
|
|
|
int r;
|
|
|
|
sigset_t set;
|
|
|
|
struct sigaction sigact;
|
|
|
|
|
|
|
|
memset(&sigact, 0, sizeof(sigact));
|
|
|
|
sigact.sa_handler = dummy_signal;
|
|
|
|
sigaction(SIG_IPI, &sigact, NULL);
|
|
|
|
|
|
|
|
pthread_sigmask(SIG_BLOCK, NULL, &set);
|
|
|
|
sigdelset(&set, SIG_IPI);
|
|
|
|
sigdelset(&set, SIGBUS);
|
2013-05-27 01:38:10 +04:00
|
|
|
r = kvm_set_signal_mask(cpu, &set);
|
2011-03-12 19:44:06 +03:00
|
|
|
if (r) {
|
|
|
|
fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r));
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-02 00:15:52 +03:00
|
|
|
#else /* _WIN32 */
|
2013-05-27 01:41:00 +04:00
|
|
|
static void qemu_kvm_init_cpu_signals(CPUState *cpu)
|
2011-02-02 00:15:53 +03:00
|
|
|
{
|
2011-03-12 19:44:06 +03:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
#endif /* _WIN32 */
|
2011-02-02 00:15:53 +03:00
|
|
|
|
2012-09-27 09:41:42 +04:00
|
|
|
static QemuMutex qemu_global_mutex;
|
2011-06-09 15:10:24 +04:00
|
|
|
static QemuCond qemu_io_proceeded_cond;
|
2015-02-27 21:58:23 +03:00
|
|
|
static unsigned iothread_requesting_mutex;
|
2010-03-29 23:23:50 +04:00
|
|
|
|
|
|
|
static QemuThread io_thread;
|
|
|
|
|
|
|
|
/* cpu creation */
|
|
|
|
static QemuCond qemu_cpu_cond;
|
|
|
|
/* system init */
|
|
|
|
static QemuCond qemu_pause_cond;
|
|
|
|
|
2011-09-13 12:30:52 +04:00
|
|
|
void qemu_init_cpu_loop(void)
|
2010-03-29 23:23:50 +04:00
|
|
|
{
|
2011-02-02 00:15:58 +03:00
|
|
|
qemu_init_sigbus();
|
2011-02-08 20:18:18 +03:00
|
|
|
qemu_cond_init(&qemu_cpu_cond);
|
|
|
|
qemu_cond_init(&qemu_pause_cond);
|
2011-06-09 15:10:24 +04:00
|
|
|
qemu_cond_init(&qemu_io_proceeded_cond);
|
2010-03-29 23:23:50 +04:00
|
|
|
qemu_mutex_init(&qemu_global_mutex);
|
|
|
|
|
2011-03-12 19:43:51 +03:00
|
|
|
qemu_thread_get_self(&io_thread);
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
|
2016-08-02 20:27:33 +03:00
|
|
|
void run_on_cpu(CPUState *cpu, run_on_cpu_func func, void *data)
|
2010-05-04 16:45:22 +04:00
|
|
|
{
|
2016-08-29 10:51:00 +03:00
|
|
|
do_run_on_cpu(cpu, func, data, &qemu_global_mutex);
|
2013-06-24 13:49:41 +04:00
|
|
|
}
|
|
|
|
|
2016-05-12 06:48:13 +03:00
|
|
|
static void qemu_kvm_destroy_vcpu(CPUState *cpu)
|
|
|
|
{
|
|
|
|
if (kvm_destroy_vcpu(cpu) < 0) {
|
|
|
|
error_report("kvm_destroy_vcpu failed");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void qemu_tcg_destroy_vcpu(CPUState *cpu)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-05-03 04:18:09 +04:00
|
|
|
static void qemu_wait_io_event_common(CPUState *cpu)
|
2010-03-29 23:23:50 +04:00
|
|
|
{
|
2012-05-03 01:10:09 +04:00
|
|
|
if (cpu->stop) {
|
|
|
|
cpu->stop = false;
|
2012-05-03 01:26:21 +04:00
|
|
|
cpu->stopped = true;
|
2016-01-25 13:08:18 +03:00
|
|
|
qemu_cond_broadcast(&qemu_pause_cond);
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
2016-08-02 20:27:36 +03:00
|
|
|
process_queued_cpu_work(cpu);
|
2012-05-02 19:49:49 +04:00
|
|
|
cpu->thread_kicked = false;
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
|
2015-08-10 18:27:06 +03:00
|
|
|
static void qemu_tcg_wait_io_event(CPUState *cpu)
|
2010-03-29 23:23:50 +04:00
|
|
|
{
|
2011-02-09 18:29:37 +03:00
|
|
|
while (all_cpu_threads_idle()) {
|
2015-08-10 18:27:06 +03:00
|
|
|
qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex);
|
2011-02-09 18:29:37 +03:00
|
|
|
}
|
2010-03-29 23:23:50 +04:00
|
|
|
|
2011-06-09 15:10:24 +04:00
|
|
|
while (iothread_requesting_mutex) {
|
|
|
|
qemu_cond_wait(&qemu_io_proceeded_cond, &qemu_global_mutex);
|
|
|
|
}
|
2010-06-25 18:56:53 +04:00
|
|
|
|
2013-06-25 01:50:24 +04:00
|
|
|
CPU_FOREACH(cpu) {
|
2013-05-30 00:29:20 +04:00
|
|
|
qemu_wait_io_event_common(cpu);
|
2010-06-25 18:56:53 +04:00
|
|
|
}
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
|
2013-05-27 01:24:55 +04:00
|
|
|
static void qemu_kvm_wait_io_event(CPUState *cpu)
|
2010-03-29 23:23:50 +04:00
|
|
|
{
|
2013-05-27 01:21:08 +04:00
|
|
|
while (cpu_thread_is_idle(cpu)) {
|
2012-05-03 03:22:49 +04:00
|
|
|
qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex);
|
2011-02-09 18:29:37 +03:00
|
|
|
}
|
2010-03-29 23:23:50 +04:00
|
|
|
|
2013-01-17 12:30:27 +04:00
|
|
|
qemu_kvm_eat_signals(cpu);
|
2012-05-03 04:18:09 +04:00
|
|
|
qemu_wait_io_event_common(cpu);
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
|
2011-02-07 14:19:12 +03:00
|
|
|
static void *qemu_kvm_cpu_thread_fn(void *arg)
|
2010-03-29 23:23:50 +04:00
|
|
|
{
|
2013-05-27 04:20:39 +04:00
|
|
|
CPUState *cpu = arg;
|
2011-02-02 00:15:50 +03:00
|
|
|
int r;
|
2010-03-29 23:23:50 +04:00
|
|
|
|
2015-07-09 09:55:38 +03:00
|
|
|
rcu_register_thread();
|
|
|
|
|
2015-06-18 19:47:18 +03:00
|
|
|
qemu_mutex_lock_iothread();
|
2012-05-02 19:00:37 +04:00
|
|
|
qemu_thread_get_self(cpu->thread);
|
2012-05-03 08:59:07 +04:00
|
|
|
cpu->thread_id = qemu_get_thread_id();
|
2014-12-08 10:53:17 +03:00
|
|
|
cpu->can_do_io = 1;
|
2013-05-27 07:17:50 +04:00
|
|
|
current_cpu = cpu;
|
2010-03-29 23:23:50 +04:00
|
|
|
|
2012-12-17 09:38:45 +04:00
|
|
|
r = kvm_init_vcpu(cpu);
|
2011-02-02 00:15:50 +03:00
|
|
|
if (r < 0) {
|
|
|
|
fprintf(stderr, "kvm_init_vcpu failed: %s\n", strerror(-r));
|
|
|
|
exit(1);
|
|
|
|
}
|
2010-03-29 23:23:50 +04:00
|
|
|
|
2013-05-27 01:41:00 +04:00
|
|
|
qemu_kvm_init_cpu_signals(cpu);
|
2010-03-29 23:23:50 +04:00
|
|
|
|
|
|
|
/* signal CPU creation */
|
2012-05-03 00:49:36 +04:00
|
|
|
cpu->created = true;
|
2010-03-29 23:23:50 +04:00
|
|
|
qemu_cond_signal(&qemu_cpu_cond);
|
|
|
|
|
2016-05-12 06:48:13 +03:00
|
|
|
do {
|
2012-05-03 01:42:26 +04:00
|
|
|
if (cpu_can_run(cpu)) {
|
2013-05-27 01:46:55 +04:00
|
|
|
r = kvm_cpu_exec(cpu);
|
2011-02-07 14:19:17 +03:00
|
|
|
if (r == EXCP_DEBUG) {
|
2013-05-27 04:07:49 +04:00
|
|
|
cpu_handle_guest_debug(cpu);
|
2011-02-07 14:19:17 +03:00
|
|
|
}
|
2011-02-07 14:19:14 +03:00
|
|
|
}
|
2013-05-27 01:24:55 +04:00
|
|
|
qemu_kvm_wait_io_event(cpu);
|
2016-05-12 06:48:13 +03:00
|
|
|
} while (!cpu->unplug || cpu_can_run(cpu));
|
2010-03-29 23:23:50 +04:00
|
|
|
|
2016-05-12 06:48:13 +03:00
|
|
|
qemu_kvm_destroy_vcpu(cpu);
|
2016-05-12 06:48:14 +03:00
|
|
|
cpu->created = false;
|
|
|
|
qemu_cond_signal(&qemu_cpu_cond);
|
2016-05-12 06:48:13 +03:00
|
|
|
qemu_mutex_unlock_iothread();
|
2010-03-29 23:23:50 +04:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-03-28 17:42:02 +04:00
|
|
|
static void *qemu_dummy_cpu_thread_fn(void *arg)
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
fprintf(stderr, "qtest is not supported under Windows\n");
|
|
|
|
exit(1);
|
|
|
|
#else
|
2013-05-27 04:24:35 +04:00
|
|
|
CPUState *cpu = arg;
|
2012-03-28 17:42:02 +04:00
|
|
|
sigset_t waitset;
|
|
|
|
int r;
|
|
|
|
|
2015-07-09 09:55:38 +03:00
|
|
|
rcu_register_thread();
|
|
|
|
|
2012-03-28 17:42:02 +04:00
|
|
|
qemu_mutex_lock_iothread();
|
2012-05-02 19:00:37 +04:00
|
|
|
qemu_thread_get_self(cpu->thread);
|
2012-05-03 08:59:07 +04:00
|
|
|
cpu->thread_id = qemu_get_thread_id();
|
2014-12-08 10:53:17 +03:00
|
|
|
cpu->can_do_io = 1;
|
2012-03-28 17:42:02 +04:00
|
|
|
|
|
|
|
sigemptyset(&waitset);
|
|
|
|
sigaddset(&waitset, SIG_IPI);
|
|
|
|
|
|
|
|
/* signal CPU creation */
|
2012-05-03 00:49:36 +04:00
|
|
|
cpu->created = true;
|
2012-03-28 17:42:02 +04:00
|
|
|
qemu_cond_signal(&qemu_cpu_cond);
|
|
|
|
|
2013-05-27 07:17:50 +04:00
|
|
|
current_cpu = cpu;
|
2012-03-28 17:42:02 +04:00
|
|
|
while (1) {
|
2013-05-27 07:17:50 +04:00
|
|
|
current_cpu = NULL;
|
2012-03-28 17:42:02 +04:00
|
|
|
qemu_mutex_unlock_iothread();
|
|
|
|
do {
|
|
|
|
int sig;
|
|
|
|
r = sigwait(&waitset, &sig);
|
|
|
|
} while (r == -1 && (errno == EAGAIN || errno == EINTR));
|
|
|
|
if (r == -1) {
|
|
|
|
perror("sigwait");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
qemu_mutex_lock_iothread();
|
2013-05-27 07:17:50 +04:00
|
|
|
current_cpu = cpu;
|
2012-05-03 04:18:09 +04:00
|
|
|
qemu_wait_io_event_common(cpu);
|
2012-03-28 17:42:02 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2011-09-26 11:40:39 +04:00
|
|
|
static void tcg_exec_all(void);
|
|
|
|
|
2011-02-07 14:19:12 +03:00
|
|
|
static void *qemu_tcg_cpu_thread_fn(void *arg)
|
2010-03-29 23:23:50 +04:00
|
|
|
{
|
2012-05-03 03:41:24 +04:00
|
|
|
CPUState *cpu = arg;
|
2016-05-12 06:48:13 +03:00
|
|
|
CPUState *remove_cpu = NULL;
|
2010-03-29 23:23:50 +04:00
|
|
|
|
2015-07-09 09:55:38 +03:00
|
|
|
rcu_register_thread();
|
|
|
|
|
2015-06-18 19:47:18 +03:00
|
|
|
qemu_mutex_lock_iothread();
|
2012-05-02 19:00:37 +04:00
|
|
|
qemu_thread_get_self(cpu->thread);
|
2010-03-29 23:23:50 +04:00
|
|
|
|
2013-07-07 21:50:23 +04:00
|
|
|
CPU_FOREACH(cpu) {
|
|
|
|
cpu->thread_id = qemu_get_thread_id();
|
|
|
|
cpu->created = true;
|
2014-12-08 10:53:17 +03:00
|
|
|
cpu->can_do_io = 1;
|
2013-07-07 21:50:23 +04:00
|
|
|
}
|
2010-03-29 23:23:50 +04:00
|
|
|
qemu_cond_signal(&qemu_cpu_cond);
|
|
|
|
|
2011-08-22 20:35:25 +04:00
|
|
|
/* wait for initial kick-off after machine start */
|
2015-04-27 19:45:28 +03:00
|
|
|
while (first_cpu->stopped) {
|
2015-08-10 18:27:06 +03:00
|
|
|
qemu_cond_wait(first_cpu->halt_cond, &qemu_global_mutex);
|
2012-02-17 21:31:15 +04:00
|
|
|
|
|
|
|
/* process any pending work */
|
2013-06-25 01:50:24 +04:00
|
|
|
CPU_FOREACH(cpu) {
|
2013-05-30 00:29:20 +04:00
|
|
|
qemu_wait_io_event_common(cpu);
|
2012-02-17 21:31:15 +04:00
|
|
|
}
|
2011-02-07 14:19:14 +03:00
|
|
|
}
|
2010-03-29 23:23:50 +04:00
|
|
|
|
2015-02-27 22:01:03 +03:00
|
|
|
/* process any pending work */
|
2015-08-18 16:43:15 +03:00
|
|
|
atomic_mb_set(&exit_request, 1);
|
2015-02-27 22:01:03 +03:00
|
|
|
|
2010-03-29 23:23:50 +04:00
|
|
|
while (1) {
|
2011-09-26 11:40:39 +04:00
|
|
|
tcg_exec_all();
|
2013-08-21 19:02:57 +04:00
|
|
|
|
|
|
|
if (use_icount) {
|
2013-08-21 19:03:02 +04:00
|
|
|
int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
|
2013-08-21 19:02:57 +04:00
|
|
|
|
|
|
|
if (deadline == 0) {
|
2013-08-21 19:03:02 +04:00
|
|
|
qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
|
2013-08-21 19:02:57 +04:00
|
|
|
}
|
2011-04-13 12:03:43 +04:00
|
|
|
}
|
2015-08-10 18:27:06 +03:00
|
|
|
qemu_tcg_wait_io_event(QTAILQ_FIRST(&cpus));
|
2016-05-12 06:48:13 +03:00
|
|
|
CPU_FOREACH(cpu) {
|
|
|
|
if (cpu->unplug && !cpu_can_run(cpu)) {
|
|
|
|
remove_cpu = cpu;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (remove_cpu) {
|
|
|
|
qemu_tcg_destroy_vcpu(remove_cpu);
|
2016-05-12 06:48:14 +03:00
|
|
|
cpu->created = false;
|
|
|
|
qemu_cond_signal(&qemu_cpu_cond);
|
2016-05-12 06:48:13 +03:00
|
|
|
remove_cpu = NULL;
|
|
|
|
}
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-05-03 02:23:30 +04:00
|
|
|
static void qemu_cpu_kick_thread(CPUState *cpu)
|
2011-03-12 19:44:08 +03:00
|
|
|
{
|
|
|
|
#ifndef _WIN32
|
|
|
|
int err;
|
|
|
|
|
2015-08-26 01:19:19 +03:00
|
|
|
if (cpu->thread_kicked) {
|
|
|
|
return;
|
2015-08-18 16:52:09 +03:00
|
|
|
}
|
2015-08-26 01:19:19 +03:00
|
|
|
cpu->thread_kicked = true;
|
2012-05-02 19:00:37 +04:00
|
|
|
err = pthread_kill(cpu->thread->thread, SIG_IPI);
|
2011-03-12 19:44:08 +03:00
|
|
|
if (err) {
|
|
|
|
fprintf(stderr, "qemu:%s: %s", __func__, strerror(err));
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
#else /* _WIN32 */
|
2015-08-26 01:19:19 +03:00
|
|
|
abort();
|
|
|
|
#endif
|
|
|
|
}
|
2013-04-09 20:06:53 +04:00
|
|
|
|
2015-08-26 01:19:19 +03:00
|
|
|
static void qemu_cpu_kick_no_halt(void)
|
|
|
|
{
|
|
|
|
CPUState *cpu;
|
|
|
|
/* Ensure whatever caused the exit has reached the CPU threads before
|
|
|
|
* writing exit_request.
|
|
|
|
*/
|
|
|
|
atomic_mb_set(&exit_request, 1);
|
|
|
|
cpu = atomic_mb_read(&tcg_current_cpu);
|
|
|
|
if (cpu) {
|
|
|
|
cpu_exit(cpu);
|
2011-03-12 19:44:08 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-03 06:34:15 +04:00
|
|
|
void qemu_cpu_kick(CPUState *cpu)
|
2010-03-29 23:23:50 +04:00
|
|
|
{
|
2012-05-03 03:22:49 +04:00
|
|
|
qemu_cond_broadcast(cpu->halt_cond);
|
2015-08-26 01:19:19 +03:00
|
|
|
if (tcg_enabled()) {
|
|
|
|
qemu_cpu_kick_no_halt();
|
|
|
|
} else {
|
|
|
|
qemu_cpu_kick_thread(cpu);
|
|
|
|
}
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
|
2011-02-02 00:15:59 +03:00
|
|
|
void qemu_cpu_kick_self(void)
|
2010-03-29 23:23:50 +04:00
|
|
|
{
|
2013-05-27 07:17:50 +04:00
|
|
|
assert(current_cpu);
|
2015-08-18 16:52:09 +03:00
|
|
|
qemu_cpu_kick_thread(current_cpu);
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
|
2012-05-03 00:23:49 +04:00
|
|
|
bool qemu_cpu_is_self(CPUState *cpu)
|
2010-03-29 23:23:50 +04:00
|
|
|
{
|
2012-05-02 19:00:37 +04:00
|
|
|
return qemu_thread_is_self(cpu->thread);
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
|
2015-01-21 14:09:14 +03:00
|
|
|
bool qemu_in_vcpu_thread(void)
|
2012-09-18 18:30:11 +04:00
|
|
|
{
|
2013-05-27 07:17:50 +04:00
|
|
|
return current_cpu && qemu_cpu_is_self(current_cpu);
|
2012-09-18 18:30:11 +04:00
|
|
|
}
|
|
|
|
|
2015-06-18 19:47:19 +03:00
|
|
|
static __thread bool iothread_locked = false;
|
|
|
|
|
|
|
|
bool qemu_mutex_iothread_locked(void)
|
|
|
|
{
|
|
|
|
return iothread_locked;
|
|
|
|
}
|
|
|
|
|
2010-03-29 23:23:50 +04:00
|
|
|
void qemu_mutex_lock_iothread(void)
|
|
|
|
{
|
2015-02-27 22:01:03 +03:00
|
|
|
atomic_inc(&iothread_requesting_mutex);
|
2015-06-18 19:47:18 +03:00
|
|
|
/* In the simple case there is no need to bump the VCPU thread out of
|
|
|
|
* TCG code execution.
|
|
|
|
*/
|
|
|
|
if (!tcg_enabled() || qemu_in_vcpu_thread() ||
|
2015-09-03 23:48:33 +03:00
|
|
|
!first_cpu || !first_cpu->created) {
|
2010-03-29 23:23:50 +04:00
|
|
|
qemu_mutex_lock(&qemu_global_mutex);
|
2015-02-27 22:01:03 +03:00
|
|
|
atomic_dec(&iothread_requesting_mutex);
|
2010-05-04 16:45:20 +04:00
|
|
|
} else {
|
|
|
|
if (qemu_mutex_trylock(&qemu_global_mutex)) {
|
2015-08-26 01:19:19 +03:00
|
|
|
qemu_cpu_kick_no_halt();
|
2010-05-04 16:45:20 +04:00
|
|
|
qemu_mutex_lock(&qemu_global_mutex);
|
|
|
|
}
|
2015-02-27 21:58:23 +03:00
|
|
|
atomic_dec(&iothread_requesting_mutex);
|
2011-06-09 15:10:24 +04:00
|
|
|
qemu_cond_broadcast(&qemu_io_proceeded_cond);
|
2010-05-04 16:45:20 +04:00
|
|
|
}
|
2015-06-18 19:47:19 +03:00
|
|
|
iothread_locked = true;
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void qemu_mutex_unlock_iothread(void)
|
|
|
|
{
|
2015-06-18 19:47:19 +03:00
|
|
|
iothread_locked = false;
|
2010-03-29 23:23:50 +04:00
|
|
|
qemu_mutex_unlock(&qemu_global_mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int all_vcpus_paused(void)
|
|
|
|
{
|
2013-06-25 01:50:24 +04:00
|
|
|
CPUState *cpu;
|
2010-03-29 23:23:50 +04:00
|
|
|
|
2013-06-25 01:50:24 +04:00
|
|
|
CPU_FOREACH(cpu) {
|
2013-05-30 00:29:20 +04:00
|
|
|
if (!cpu->stopped) {
|
2010-03-29 23:23:50 +04:00
|
|
|
return 0;
|
2011-02-07 14:19:14 +03:00
|
|
|
}
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void pause_all_vcpus(void)
|
|
|
|
{
|
2013-06-25 01:50:24 +04:00
|
|
|
CPUState *cpu;
|
2010-03-29 23:23:50 +04:00
|
|
|
|
2013-08-21 19:03:02 +04:00
|
|
|
qemu_clock_enable(QEMU_CLOCK_VIRTUAL, false);
|
2013-06-25 01:50:24 +04:00
|
|
|
CPU_FOREACH(cpu) {
|
2013-05-30 00:29:20 +04:00
|
|
|
cpu->stop = true;
|
|
|
|
qemu_cpu_kick(cpu);
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
|
2012-09-18 18:30:11 +04:00
|
|
|
if (qemu_in_vcpu_thread()) {
|
2012-02-17 21:31:16 +04:00
|
|
|
cpu_stop_current();
|
|
|
|
if (!kvm_enabled()) {
|
2013-06-25 01:50:24 +04:00
|
|
|
CPU_FOREACH(cpu) {
|
2013-05-30 00:29:20 +04:00
|
|
|
cpu->stop = false;
|
|
|
|
cpu->stopped = true;
|
2012-02-17 21:31:16 +04:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-29 23:23:50 +04:00
|
|
|
while (!all_vcpus_paused()) {
|
2011-03-12 19:44:02 +03:00
|
|
|
qemu_cond_wait(&qemu_pause_cond, &qemu_global_mutex);
|
2013-06-25 01:50:24 +04:00
|
|
|
CPU_FOREACH(cpu) {
|
2013-05-30 00:29:20 +04:00
|
|
|
qemu_cpu_kick(cpu);
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-23 12:29:37 +04:00
|
|
|
void cpu_resume(CPUState *cpu)
|
|
|
|
{
|
|
|
|
cpu->stop = false;
|
|
|
|
cpu->stopped = false;
|
|
|
|
qemu_cpu_kick(cpu);
|
|
|
|
}
|
|
|
|
|
2010-03-29 23:23:50 +04:00
|
|
|
void resume_all_vcpus(void)
|
|
|
|
{
|
2013-06-25 01:50:24 +04:00
|
|
|
CPUState *cpu;
|
2010-03-29 23:23:50 +04:00
|
|
|
|
2013-08-21 19:03:02 +04:00
|
|
|
qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
|
2013-06-25 01:50:24 +04:00
|
|
|
CPU_FOREACH(cpu) {
|
2013-05-30 00:29:20 +04:00
|
|
|
cpu_resume(cpu);
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-12 06:48:13 +03:00
|
|
|
void cpu_remove(CPUState *cpu)
|
|
|
|
{
|
|
|
|
cpu->stop = true;
|
|
|
|
cpu->unplug = true;
|
|
|
|
qemu_cpu_kick(cpu);
|
|
|
|
}
|
|
|
|
|
2016-05-12 06:48:14 +03:00
|
|
|
void cpu_remove_sync(CPUState *cpu)
|
|
|
|
{
|
|
|
|
cpu_remove(cpu);
|
|
|
|
while (cpu->created) {
|
|
|
|
qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-30 14:20:32 +04:00
|
|
|
/* For temporary buffers for forming a name */
|
|
|
|
#define VCPU_THREAD_NAME_SIZE 16
|
|
|
|
|
2012-05-03 03:50:44 +04:00
|
|
|
static void qemu_tcg_init_vcpu(CPUState *cpu)
|
2010-03-29 23:23:50 +04:00
|
|
|
{
|
2014-01-30 14:20:32 +04:00
|
|
|
char thread_name[VCPU_THREAD_NAME_SIZE];
|
2015-08-10 18:27:06 +03:00
|
|
|
static QemuCond *tcg_halt_cond;
|
|
|
|
static QemuThread *tcg_cpu_thread;
|
2014-01-30 14:20:32 +04:00
|
|
|
|
2010-03-29 23:23:50 +04:00
|
|
|
/* share a single thread for all cpus with TCG */
|
|
|
|
if (!tcg_cpu_thread) {
|
2012-05-02 19:00:37 +04:00
|
|
|
cpu->thread = g_malloc0(sizeof(QemuThread));
|
2012-05-03 03:22:49 +04:00
|
|
|
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
|
|
|
qemu_cond_init(cpu->halt_cond);
|
|
|
|
tcg_halt_cond = cpu->halt_cond;
|
2014-01-30 14:20:32 +04:00
|
|
|
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/TCG",
|
|
|
|
cpu->cpu_index);
|
|
|
|
qemu_thread_create(cpu->thread, thread_name, qemu_tcg_cpu_thread_fn,
|
|
|
|
cpu, QEMU_THREAD_JOINABLE);
|
2011-12-13 16:43:52 +04:00
|
|
|
#ifdef _WIN32
|
2012-05-02 19:00:37 +04:00
|
|
|
cpu->hThread = qemu_thread_get_handle(cpu->thread);
|
2011-12-13 16:43:52 +04:00
|
|
|
#endif
|
2012-05-03 00:49:36 +04:00
|
|
|
while (!cpu->created) {
|
2011-03-12 19:44:03 +03:00
|
|
|
qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
|
2011-02-07 14:19:14 +03:00
|
|
|
}
|
2012-05-02 19:00:37 +04:00
|
|
|
tcg_cpu_thread = cpu->thread;
|
2010-03-29 23:23:50 +04:00
|
|
|
} else {
|
2012-05-02 19:00:37 +04:00
|
|
|
cpu->thread = tcg_cpu_thread;
|
2012-05-03 03:22:49 +04:00
|
|
|
cpu->halt_cond = tcg_halt_cond;
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-27 04:20:39 +04:00
|
|
|
static void qemu_kvm_start_vcpu(CPUState *cpu)
|
2010-03-29 23:23:50 +04:00
|
|
|
{
|
2014-01-30 14:20:32 +04:00
|
|
|
char thread_name[VCPU_THREAD_NAME_SIZE];
|
|
|
|
|
2012-05-02 19:00:37 +04:00
|
|
|
cpu->thread = g_malloc0(sizeof(QemuThread));
|
2012-05-03 03:22:49 +04:00
|
|
|
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
|
|
|
qemu_cond_init(cpu->halt_cond);
|
2014-01-30 14:20:32 +04:00
|
|
|
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/KVM",
|
|
|
|
cpu->cpu_index);
|
|
|
|
qemu_thread_create(cpu->thread, thread_name, qemu_kvm_cpu_thread_fn,
|
|
|
|
cpu, QEMU_THREAD_JOINABLE);
|
2012-05-03 00:49:36 +04:00
|
|
|
while (!cpu->created) {
|
2011-03-12 19:44:03 +03:00
|
|
|
qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
|
2011-02-07 14:19:14 +03:00
|
|
|
}
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
|
2013-05-27 04:24:35 +04:00
|
|
|
static void qemu_dummy_start_vcpu(CPUState *cpu)
|
2012-03-28 17:42:02 +04:00
|
|
|
{
|
2014-01-30 14:20:32 +04:00
|
|
|
char thread_name[VCPU_THREAD_NAME_SIZE];
|
|
|
|
|
2012-05-02 19:00:37 +04:00
|
|
|
cpu->thread = g_malloc0(sizeof(QemuThread));
|
2012-05-03 03:22:49 +04:00
|
|
|
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
|
|
|
qemu_cond_init(cpu->halt_cond);
|
2014-01-30 14:20:32 +04:00
|
|
|
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/DUMMY",
|
|
|
|
cpu->cpu_index);
|
|
|
|
qemu_thread_create(cpu->thread, thread_name, qemu_dummy_cpu_thread_fn, cpu,
|
2012-03-28 17:42:02 +04:00
|
|
|
QEMU_THREAD_JOINABLE);
|
2012-05-03 00:49:36 +04:00
|
|
|
while (!cpu->created) {
|
2012-03-28 17:42:02 +04:00
|
|
|
qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-27 05:23:24 +04:00
|
|
|
void qemu_init_vcpu(CPUState *cpu)
|
2010-03-29 23:23:50 +04:00
|
|
|
{
|
2012-12-17 06:27:07 +04:00
|
|
|
cpu->nr_cores = smp_cores;
|
|
|
|
cpu->nr_threads = smp_threads;
|
2012-05-03 01:26:21 +04:00
|
|
|
cpu->stopped = true;
|
2016-01-21 17:15:04 +03:00
|
|
|
|
|
|
|
if (!cpu->as) {
|
|
|
|
/* If the target cpu hasn't set up any address spaces itself,
|
|
|
|
* give it the default one.
|
|
|
|
*/
|
2016-01-21 17:15:06 +03:00
|
|
|
AddressSpace *as = address_space_init_shareable(cpu->memory,
|
|
|
|
"cpu-memory");
|
2016-01-21 17:15:04 +03:00
|
|
|
cpu->num_ases = 1;
|
2016-01-21 17:15:06 +03:00
|
|
|
cpu_address_space_init(cpu, as, 0);
|
2016-01-21 17:15:04 +03:00
|
|
|
}
|
|
|
|
|
2011-02-07 14:19:14 +03:00
|
|
|
if (kvm_enabled()) {
|
2013-05-27 04:20:39 +04:00
|
|
|
qemu_kvm_start_vcpu(cpu);
|
2012-03-28 17:42:02 +04:00
|
|
|
} else if (tcg_enabled()) {
|
2012-05-03 03:50:44 +04:00
|
|
|
qemu_tcg_init_vcpu(cpu);
|
2012-03-28 17:42:02 +04:00
|
|
|
} else {
|
2013-05-27 04:24:35 +04:00
|
|
|
qemu_dummy_start_vcpu(cpu);
|
2011-02-07 14:19:14 +03:00
|
|
|
}
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
|
2011-02-02 00:15:43 +03:00
|
|
|
void cpu_stop_current(void)
|
2010-03-29 23:23:50 +04:00
|
|
|
{
|
2013-05-27 07:17:50 +04:00
|
|
|
if (current_cpu) {
|
|
|
|
current_cpu->stop = false;
|
|
|
|
current_cpu->stopped = true;
|
|
|
|
cpu_exit(current_cpu);
|
2016-01-25 13:08:18 +03:00
|
|
|
qemu_cond_broadcast(&qemu_pause_cond);
|
2011-02-02 00:15:43 +03:00
|
|
|
}
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
|
2013-07-05 15:49:54 +04:00
|
|
|
int vm_stop(RunState state)
|
2010-03-29 23:23:50 +04:00
|
|
|
{
|
2012-09-18 18:30:11 +04:00
|
|
|
if (qemu_in_vcpu_thread()) {
|
2014-06-05 16:53:58 +04:00
|
|
|
qemu_system_vmstop_request_prepare();
|
2011-07-29 21:26:33 +04:00
|
|
|
qemu_system_vmstop_request(state);
|
2010-03-29 23:23:50 +04:00
|
|
|
/*
|
|
|
|
* FIXME: should not return to device code in case
|
|
|
|
* vm_stop() has been requested.
|
|
|
|
*/
|
2011-02-02 00:15:43 +03:00
|
|
|
cpu_stop_current();
|
2013-07-05 15:49:54 +04:00
|
|
|
return 0;
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
2013-07-05 15:49:54 +04:00
|
|
|
|
|
|
|
return do_vm_stop(state);
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
|
2011-10-14 18:18:09 +04:00
|
|
|
/* does a state transition even if the VM is already stopped,
|
|
|
|
current state is forgotten forever */
|
2013-07-05 15:49:54 +04:00
|
|
|
int vm_stop_force_state(RunState state)
|
2011-10-14 18:18:09 +04:00
|
|
|
{
|
|
|
|
if (runstate_is_running()) {
|
2013-07-05 15:49:54 +04:00
|
|
|
return vm_stop(state);
|
2011-10-14 18:18:09 +04:00
|
|
|
} else {
|
|
|
|
runstate_set(state);
|
2015-11-20 12:34:38 +03:00
|
|
|
|
|
|
|
bdrv_drain_all();
|
2013-07-18 16:52:19 +04:00
|
|
|
/* Make sure to return an error if the flush in a previous vm_stop()
|
|
|
|
* failed. */
|
2016-09-23 04:45:51 +03:00
|
|
|
return bdrv_flush_all();
|
2011-10-14 18:18:09 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-17 19:24:05 +03:00
|
|
|
static int64_t tcg_get_icount_limit(void)
|
|
|
|
{
|
|
|
|
int64_t deadline;
|
|
|
|
|
|
|
|
if (replay_mode != REPLAY_MODE_PLAY) {
|
|
|
|
deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
|
|
|
|
|
|
|
|
/* Maintain prior (possibly buggy) behaviour where if no deadline
|
|
|
|
* was set (as there is no QEMU_CLOCK_VIRTUAL timer) or it is more than
|
|
|
|
* INT32_MAX nanoseconds ahead, we still use INT32_MAX
|
|
|
|
* nanoseconds.
|
|
|
|
*/
|
|
|
|
if ((deadline < 0) || (deadline > INT32_MAX)) {
|
|
|
|
deadline = INT32_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
return qemu_icount_round(deadline);
|
|
|
|
} else {
|
|
|
|
return replay_get_instructions();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-24 05:31:17 +03:00
|
|
|
static int tcg_cpu_exec(CPUState *cpu)
|
2010-03-29 23:23:50 +04:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
#ifdef CONFIG_PROFILER
|
|
|
|
int64_t ti;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef CONFIG_PROFILER
|
|
|
|
ti = profile_getclock();
|
|
|
|
#endif
|
|
|
|
if (use_icount) {
|
|
|
|
int64_t count;
|
|
|
|
int decr;
|
2014-08-01 03:37:09 +04:00
|
|
|
timers_state.qemu_icount -= (cpu->icount_decr.u16.low
|
|
|
|
+ cpu->icount_extra);
|
2013-08-26 07:51:49 +04:00
|
|
|
cpu->icount_decr.u16.low = 0;
|
2013-08-26 07:39:29 +04:00
|
|
|
cpu->icount_extra = 0;
|
2015-09-17 19:24:05 +03:00
|
|
|
count = tcg_get_icount_limit();
|
2014-08-01 03:37:09 +04:00
|
|
|
timers_state.qemu_icount += count;
|
2010-03-29 23:23:50 +04:00
|
|
|
decr = (count > 0xffff) ? 0xffff : count;
|
|
|
|
count -= decr;
|
2013-08-26 07:51:49 +04:00
|
|
|
cpu->icount_decr.u16.low = decr;
|
2013-08-26 07:39:29 +04:00
|
|
|
cpu->icount_extra = count;
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
2016-08-31 17:56:04 +03:00
|
|
|
cpu_exec_start(cpu);
|
2015-06-18 20:24:55 +03:00
|
|
|
ret = cpu_exec(cpu);
|
2016-08-31 17:56:04 +03:00
|
|
|
cpu_exec_end(cpu);
|
2010-03-29 23:23:50 +04:00
|
|
|
#ifdef CONFIG_PROFILER
|
2015-03-16 06:57:38 +03:00
|
|
|
tcg_time += profile_getclock() - ti;
|
2010-03-29 23:23:50 +04:00
|
|
|
#endif
|
|
|
|
if (use_icount) {
|
|
|
|
/* Fold pending instructions back into the
|
|
|
|
instruction counter, and clear the interrupt flag. */
|
2014-08-01 03:37:09 +04:00
|
|
|
timers_state.qemu_icount -= (cpu->icount_decr.u16.low
|
|
|
|
+ cpu->icount_extra);
|
2013-08-26 07:51:49 +04:00
|
|
|
cpu->icount_decr.u32 = 0;
|
2013-08-26 07:39:29 +04:00
|
|
|
cpu->icount_extra = 0;
|
2015-09-17 19:24:05 +03:00
|
|
|
replay_account_executed_instructions();
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-09-26 11:40:39 +04:00
|
|
|
static void tcg_exec_all(void)
|
2010-03-29 23:23:50 +04:00
|
|
|
{
|
2011-02-02 00:15:55 +03:00
|
|
|
int r;
|
|
|
|
|
2013-08-21 19:03:02 +04:00
|
|
|
/* Account partial waits to QEMU_CLOCK_VIRTUAL. */
|
2016-03-10 14:56:09 +03:00
|
|
|
qemu_account_warp_timer();
|
enable vm_clock to "warp" in the iothread+icount case
The previous patch however is not enough, because if the virtual CPU
goes to sleep waiting for a future timer interrupt to wake it up, qemu
deadlocks. The timer interrupt never comes because time is driven by
icount, but the vCPU doesn't run any insns.
You could say that VCPUs should never go to sleep in icount
mode if there is a pending vm_clock timer; rather time should
just warp to the next vm_clock event with no sleep ever taking place.
Even better, you can sleep for some time related to the
time left until the next event, to avoid that the warps are too visible
externally; for example, you could be sending network packets continously
instead of every 100ms.
This is what this patch implements. qemu_clock_warp is called: 1)
whenever a vm_clock timer is adjusted, to ensure the warp_timer is
synchronized; 2) at strategic points in the CPU thread, to make sure
the insn counter is synchronized before the CPU starts running.
In any case, the warp_timer is disabled while the CPU is running,
because the insn counter will then be making progress on its own.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Tested-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
2011-04-13 12:03:44 +04:00
|
|
|
|
2011-02-07 14:19:14 +03:00
|
|
|
if (next_cpu == NULL) {
|
2010-03-29 23:23:50 +04:00
|
|
|
next_cpu = first_cpu;
|
2011-02-07 14:19:14 +03:00
|
|
|
}
|
2013-06-25 01:50:24 +04:00
|
|
|
for (; next_cpu != NULL && !exit_request; next_cpu = CPU_NEXT(next_cpu)) {
|
2013-05-30 00:29:20 +04:00
|
|
|
CPUState *cpu = next_cpu;
|
2010-03-29 23:23:50 +04:00
|
|
|
|
2013-08-21 19:03:02 +04:00
|
|
|
qemu_clock_enable(QEMU_CLOCK_VIRTUAL,
|
2013-06-21 22:20:45 +04:00
|
|
|
(cpu->singlestep_enabled & SSTEP_NOTIMER) == 0);
|
2010-03-29 23:23:50 +04:00
|
|
|
|
2012-05-03 01:42:26 +04:00
|
|
|
if (cpu_can_run(cpu)) {
|
2015-06-24 05:31:17 +03:00
|
|
|
r = tcg_cpu_exec(cpu);
|
2011-02-02 00:15:55 +03:00
|
|
|
if (r == EXCP_DEBUG) {
|
2013-05-27 04:07:49 +04:00
|
|
|
cpu_handle_guest_debug(cpu);
|
2010-06-25 18:56:56 +04:00
|
|
|
break;
|
|
|
|
}
|
2012-05-03 01:26:21 +04:00
|
|
|
} else if (cpu->stop || cpu->stopped) {
|
2016-05-12 06:48:13 +03:00
|
|
|
if (cpu->unplug) {
|
|
|
|
next_cpu = CPU_NEXT(cpu);
|
|
|
|
}
|
2010-03-29 23:23:50 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-08-18 16:43:15 +03:00
|
|
|
|
|
|
|
/* Pairs with smp_wmb in qemu_cpu_kick. */
|
|
|
|
atomic_mb_set(&exit_request, 0);
|
2010-03-29 23:23:50 +04:00
|
|
|
}
|
|
|
|
|
2010-10-23 01:03:33 +04:00
|
|
|
void list_cpus(FILE *f, fprintf_function cpu_fprintf, const char *optarg)
|
2010-05-04 23:55:35 +04:00
|
|
|
{
|
|
|
|
/* XXX: implement xxx_cpu_list for targets that still miss it */
|
2012-09-06 00:41:08 +04:00
|
|
|
#if defined(cpu_list)
|
|
|
|
cpu_list(f, cpu_fprintf);
|
2010-05-04 23:55:35 +04:00
|
|
|
#endif
|
|
|
|
}
|
2011-09-21 23:38:35 +04:00
|
|
|
|
|
|
|
CpuInfoList *qmp_query_cpus(Error **errp)
|
|
|
|
{
|
|
|
|
CpuInfoList *head = NULL, *cur_item = NULL;
|
2013-05-30 00:29:20 +04:00
|
|
|
CPUState *cpu;
|
2011-09-21 23:38:35 +04:00
|
|
|
|
2013-06-25 01:50:24 +04:00
|
|
|
CPU_FOREACH(cpu) {
|
2011-09-21 23:38:35 +04:00
|
|
|
CpuInfoList *info;
|
2013-05-30 00:29:20 +04:00
|
|
|
#if defined(TARGET_I386)
|
|
|
|
X86CPU *x86_cpu = X86_CPU(cpu);
|
|
|
|
CPUX86State *env = &x86_cpu->env;
|
|
|
|
#elif defined(TARGET_PPC)
|
|
|
|
PowerPCCPU *ppc_cpu = POWERPC_CPU(cpu);
|
|
|
|
CPUPPCState *env = &ppc_cpu->env;
|
|
|
|
#elif defined(TARGET_SPARC)
|
|
|
|
SPARCCPU *sparc_cpu = SPARC_CPU(cpu);
|
|
|
|
CPUSPARCState *env = &sparc_cpu->env;
|
|
|
|
#elif defined(TARGET_MIPS)
|
|
|
|
MIPSCPU *mips_cpu = MIPS_CPU(cpu);
|
|
|
|
CPUMIPSState *env = &mips_cpu->env;
|
2014-09-01 15:59:46 +04:00
|
|
|
#elif defined(TARGET_TRICORE)
|
|
|
|
TriCoreCPU *tricore_cpu = TRICORE_CPU(cpu);
|
|
|
|
CPUTriCoreState *env = &tricore_cpu->env;
|
2013-05-30 00:29:20 +04:00
|
|
|
#endif
|
2011-09-21 23:38:35 +04:00
|
|
|
|
2013-05-01 16:24:52 +04:00
|
|
|
cpu_synchronize_state(cpu);
|
2011-09-21 23:38:35 +04:00
|
|
|
|
|
|
|
info = g_malloc0(sizeof(*info));
|
|
|
|
info->value = g_malloc0(sizeof(*info->value));
|
2012-12-17 09:18:02 +04:00
|
|
|
info->value->CPU = cpu->cpu_index;
|
2013-05-30 00:29:20 +04:00
|
|
|
info->value->current = (cpu == first_cpu);
|
2013-01-17 21:51:17 +04:00
|
|
|
info->value->halted = cpu->halted;
|
2015-05-08 22:04:22 +03:00
|
|
|
info->value->qom_path = object_get_canonical_path(OBJECT(cpu));
|
2012-05-03 08:59:07 +04:00
|
|
|
info->value->thread_id = cpu->thread_id;
|
2011-09-21 23:38:35 +04:00
|
|
|
#if defined(TARGET_I386)
|
cpu: Convert CpuInfo into flat union
The CpuInfo struct is used only by the 'query-cpus' output
command, so we are free to modify it by adding fields (clients
are already supposed to ignore unknown output fields), or by
changing optional members to mandatory, while still keeping
QMP wire compatibility with older versions of qemu.
When qapi type CpuInfo was originally created for 0.14, we had
no notion of a flat union, and instead just listed a bunch of
optional fields with documentation about the mutually-exclusive
choice of which instruction pointer field(s) would be provided
for a given architecture. But now that we have flat unions and
introspection, it is better to segregate off which fields will
be provided according to the actual architecture. With this in
place, we no longer need the fields to be optional, because the
choice of the new 'arch' discriminator serves that role.
This has an additional benefit: the old all-in-one struct was
the only place in the code base that had a case-sensitive
naming of members 'pc' vs. 'PC'. Separating these spellings
into different branches of the flat union will allow us to add
restrictions against future case-insensitive collisions, since
that is generally a poor interface practice.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-25-git-send-email-eblake@redhat.com>
[Spelling of CPUInfo{SPARC,PPC,MIPS} fixed]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 11:52:59 +03:00
|
|
|
info->value->arch = CPU_INFO_ARCH_X86;
|
qapi: Don't box branches of flat unions
There's no reason to do two malloc's for a flat union; let's just
inline the branch struct directly into the C union branch of the
flat union.
Surprisingly, fewer clients were actually using explicit references
to the branch types in comparison to the number of flat unions
thus modified.
This lets us reduce the hack in qapi-types:gen_variants() added in
the previous patch; we no longer need to distinguish between
alternates and flat unions.
The change to unboxed structs means that u.data (added in commit
cee2dedb) is now coincident with random fields of each branch of
the flat union, whereas beforehand it was only coincident with
pointers (since all branches of a flat union have to be objects).
Note that this was already the case for simple unions - but there
we got lucky. Remember, visit_start_union() blindly returns true
for all visitors except for the dealloc visitor, where it returns
the value !!obj->u.data, and that this result then controls
whether to proceed with the visit to the variant. Pre-patch,
this meant that flat unions were testing whether the boxed pointer
was still NULL, and thereby skipping visit_end_implicit_struct()
and avoiding a NULL dereference if the pointer had not been
allocated. The same was true for simple unions where the current
branch had pointer type, except there we bypassed visit_type_FOO().
But for simple unions where the current branch had scalar type, the
contents of that scalar meant that the decision to call
visit_type_FOO() was data-dependent - the reason we got lucky there
is that visit_type_FOO() for all scalar types in the dealloc visitor
is a no-op (only the pointer variants had anything to free), so it
did not matter whether the dealloc visit was skipped. But with this
patch, we would risk leaking memory if we could skip a call to
visit_type_FOO_fields() based solely on a data-dependent decision.
But notice: in the dealloc visitor, visit_type_FOO() already handles
a NULL obj - it was only the visit_type_implicit_FOO() that was
failing to check for NULL. And now that we have refactored things to
have the branch be part of the parent struct, we no longer have a
separate pointer that can be NULL in the first place. So we can just
delete the call to visit_start_union() altogether, and blindly visit
the branch type; there is no change in behavior except to the dealloc
visitor, where we now unconditionally visit the branch, but where that
visit is now always safe (for a flat union, we can no longer
dereference NULL, and for a simple union, visit_type_FOO() was already
safely handling NULL on pointer types).
Unfortunately, simple unions are not as easy to switch to unboxed
layout; because we are special-casing the hidden implicit type with
a single 'data' member, we really DO need to keep calling another
layer of visit_start_struct(), with a second malloc; although there
are some cleanups planned for simple unions in later patches.
visit_start_union() and gen_visit_implicit_struct() are now unused.
Drop them.
Note that after this patch, the only remaining use of
visit_start_implicit_struct() is for alternate types; the next patch
will do further cleanup based on that fact.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1455778109-6278-14-git-send-email-eblake@redhat.com>
[Dead code deletion squashed in, commit message updated accordingly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-02-18 09:48:27 +03:00
|
|
|
info->value->u.x86.pc = env->eip + env->segs[R_CS].base;
|
2011-09-21 23:38:35 +04:00
|
|
|
#elif defined(TARGET_PPC)
|
cpu: Convert CpuInfo into flat union
The CpuInfo struct is used only by the 'query-cpus' output
command, so we are free to modify it by adding fields (clients
are already supposed to ignore unknown output fields), or by
changing optional members to mandatory, while still keeping
QMP wire compatibility with older versions of qemu.
When qapi type CpuInfo was originally created for 0.14, we had
no notion of a flat union, and instead just listed a bunch of
optional fields with documentation about the mutually-exclusive
choice of which instruction pointer field(s) would be provided
for a given architecture. But now that we have flat unions and
introspection, it is better to segregate off which fields will
be provided according to the actual architecture. With this in
place, we no longer need the fields to be optional, because the
choice of the new 'arch' discriminator serves that role.
This has an additional benefit: the old all-in-one struct was
the only place in the code base that had a case-sensitive
naming of members 'pc' vs. 'PC'. Separating these spellings
into different branches of the flat union will allow us to add
restrictions against future case-insensitive collisions, since
that is generally a poor interface practice.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-25-git-send-email-eblake@redhat.com>
[Spelling of CPUInfo{SPARC,PPC,MIPS} fixed]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 11:52:59 +03:00
|
|
|
info->value->arch = CPU_INFO_ARCH_PPC;
|
qapi: Don't box branches of flat unions
There's no reason to do two malloc's for a flat union; let's just
inline the branch struct directly into the C union branch of the
flat union.
Surprisingly, fewer clients were actually using explicit references
to the branch types in comparison to the number of flat unions
thus modified.
This lets us reduce the hack in qapi-types:gen_variants() added in
the previous patch; we no longer need to distinguish between
alternates and flat unions.
The change to unboxed structs means that u.data (added in commit
cee2dedb) is now coincident with random fields of each branch of
the flat union, whereas beforehand it was only coincident with
pointers (since all branches of a flat union have to be objects).
Note that this was already the case for simple unions - but there
we got lucky. Remember, visit_start_union() blindly returns true
for all visitors except for the dealloc visitor, where it returns
the value !!obj->u.data, and that this result then controls
whether to proceed with the visit to the variant. Pre-patch,
this meant that flat unions were testing whether the boxed pointer
was still NULL, and thereby skipping visit_end_implicit_struct()
and avoiding a NULL dereference if the pointer had not been
allocated. The same was true for simple unions where the current
branch had pointer type, except there we bypassed visit_type_FOO().
But for simple unions where the current branch had scalar type, the
contents of that scalar meant that the decision to call
visit_type_FOO() was data-dependent - the reason we got lucky there
is that visit_type_FOO() for all scalar types in the dealloc visitor
is a no-op (only the pointer variants had anything to free), so it
did not matter whether the dealloc visit was skipped. But with this
patch, we would risk leaking memory if we could skip a call to
visit_type_FOO_fields() based solely on a data-dependent decision.
But notice: in the dealloc visitor, visit_type_FOO() already handles
a NULL obj - it was only the visit_type_implicit_FOO() that was
failing to check for NULL. And now that we have refactored things to
have the branch be part of the parent struct, we no longer have a
separate pointer that can be NULL in the first place. So we can just
delete the call to visit_start_union() altogether, and blindly visit
the branch type; there is no change in behavior except to the dealloc
visitor, where we now unconditionally visit the branch, but where that
visit is now always safe (for a flat union, we can no longer
dereference NULL, and for a simple union, visit_type_FOO() was already
safely handling NULL on pointer types).
Unfortunately, simple unions are not as easy to switch to unboxed
layout; because we are special-casing the hidden implicit type with
a single 'data' member, we really DO need to keep calling another
layer of visit_start_struct(), with a second malloc; although there
are some cleanups planned for simple unions in later patches.
visit_start_union() and gen_visit_implicit_struct() are now unused.
Drop them.
Note that after this patch, the only remaining use of
visit_start_implicit_struct() is for alternate types; the next patch
will do further cleanup based on that fact.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1455778109-6278-14-git-send-email-eblake@redhat.com>
[Dead code deletion squashed in, commit message updated accordingly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-02-18 09:48:27 +03:00
|
|
|
info->value->u.ppc.nip = env->nip;
|
2011-09-21 23:38:35 +04:00
|
|
|
#elif defined(TARGET_SPARC)
|
cpu: Convert CpuInfo into flat union
The CpuInfo struct is used only by the 'query-cpus' output
command, so we are free to modify it by adding fields (clients
are already supposed to ignore unknown output fields), or by
changing optional members to mandatory, while still keeping
QMP wire compatibility with older versions of qemu.
When qapi type CpuInfo was originally created for 0.14, we had
no notion of a flat union, and instead just listed a bunch of
optional fields with documentation about the mutually-exclusive
choice of which instruction pointer field(s) would be provided
for a given architecture. But now that we have flat unions and
introspection, it is better to segregate off which fields will
be provided according to the actual architecture. With this in
place, we no longer need the fields to be optional, because the
choice of the new 'arch' discriminator serves that role.
This has an additional benefit: the old all-in-one struct was
the only place in the code base that had a case-sensitive
naming of members 'pc' vs. 'PC'. Separating these spellings
into different branches of the flat union will allow us to add
restrictions against future case-insensitive collisions, since
that is generally a poor interface practice.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-25-git-send-email-eblake@redhat.com>
[Spelling of CPUInfo{SPARC,PPC,MIPS} fixed]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 11:52:59 +03:00
|
|
|
info->value->arch = CPU_INFO_ARCH_SPARC;
|
qapi: Don't box branches of flat unions
There's no reason to do two malloc's for a flat union; let's just
inline the branch struct directly into the C union branch of the
flat union.
Surprisingly, fewer clients were actually using explicit references
to the branch types in comparison to the number of flat unions
thus modified.
This lets us reduce the hack in qapi-types:gen_variants() added in
the previous patch; we no longer need to distinguish between
alternates and flat unions.
The change to unboxed structs means that u.data (added in commit
cee2dedb) is now coincident with random fields of each branch of
the flat union, whereas beforehand it was only coincident with
pointers (since all branches of a flat union have to be objects).
Note that this was already the case for simple unions - but there
we got lucky. Remember, visit_start_union() blindly returns true
for all visitors except for the dealloc visitor, where it returns
the value !!obj->u.data, and that this result then controls
whether to proceed with the visit to the variant. Pre-patch,
this meant that flat unions were testing whether the boxed pointer
was still NULL, and thereby skipping visit_end_implicit_struct()
and avoiding a NULL dereference if the pointer had not been
allocated. The same was true for simple unions where the current
branch had pointer type, except there we bypassed visit_type_FOO().
But for simple unions where the current branch had scalar type, the
contents of that scalar meant that the decision to call
visit_type_FOO() was data-dependent - the reason we got lucky there
is that visit_type_FOO() for all scalar types in the dealloc visitor
is a no-op (only the pointer variants had anything to free), so it
did not matter whether the dealloc visit was skipped. But with this
patch, we would risk leaking memory if we could skip a call to
visit_type_FOO_fields() based solely on a data-dependent decision.
But notice: in the dealloc visitor, visit_type_FOO() already handles
a NULL obj - it was only the visit_type_implicit_FOO() that was
failing to check for NULL. And now that we have refactored things to
have the branch be part of the parent struct, we no longer have a
separate pointer that can be NULL in the first place. So we can just
delete the call to visit_start_union() altogether, and blindly visit
the branch type; there is no change in behavior except to the dealloc
visitor, where we now unconditionally visit the branch, but where that
visit is now always safe (for a flat union, we can no longer
dereference NULL, and for a simple union, visit_type_FOO() was already
safely handling NULL on pointer types).
Unfortunately, simple unions are not as easy to switch to unboxed
layout; because we are special-casing the hidden implicit type with
a single 'data' member, we really DO need to keep calling another
layer of visit_start_struct(), with a second malloc; although there
are some cleanups planned for simple unions in later patches.
visit_start_union() and gen_visit_implicit_struct() are now unused.
Drop them.
Note that after this patch, the only remaining use of
visit_start_implicit_struct() is for alternate types; the next patch
will do further cleanup based on that fact.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1455778109-6278-14-git-send-email-eblake@redhat.com>
[Dead code deletion squashed in, commit message updated accordingly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-02-18 09:48:27 +03:00
|
|
|
info->value->u.q_sparc.pc = env->pc;
|
|
|
|
info->value->u.q_sparc.npc = env->npc;
|
2011-09-21 23:38:35 +04:00
|
|
|
#elif defined(TARGET_MIPS)
|
cpu: Convert CpuInfo into flat union
The CpuInfo struct is used only by the 'query-cpus' output
command, so we are free to modify it by adding fields (clients
are already supposed to ignore unknown output fields), or by
changing optional members to mandatory, while still keeping
QMP wire compatibility with older versions of qemu.
When qapi type CpuInfo was originally created for 0.14, we had
no notion of a flat union, and instead just listed a bunch of
optional fields with documentation about the mutually-exclusive
choice of which instruction pointer field(s) would be provided
for a given architecture. But now that we have flat unions and
introspection, it is better to segregate off which fields will
be provided according to the actual architecture. With this in
place, we no longer need the fields to be optional, because the
choice of the new 'arch' discriminator serves that role.
This has an additional benefit: the old all-in-one struct was
the only place in the code base that had a case-sensitive
naming of members 'pc' vs. 'PC'. Separating these spellings
into different branches of the flat union will allow us to add
restrictions against future case-insensitive collisions, since
that is generally a poor interface practice.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-25-git-send-email-eblake@redhat.com>
[Spelling of CPUInfo{SPARC,PPC,MIPS} fixed]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 11:52:59 +03:00
|
|
|
info->value->arch = CPU_INFO_ARCH_MIPS;
|
qapi: Don't box branches of flat unions
There's no reason to do two malloc's for a flat union; let's just
inline the branch struct directly into the C union branch of the
flat union.
Surprisingly, fewer clients were actually using explicit references
to the branch types in comparison to the number of flat unions
thus modified.
This lets us reduce the hack in qapi-types:gen_variants() added in
the previous patch; we no longer need to distinguish between
alternates and flat unions.
The change to unboxed structs means that u.data (added in commit
cee2dedb) is now coincident with random fields of each branch of
the flat union, whereas beforehand it was only coincident with
pointers (since all branches of a flat union have to be objects).
Note that this was already the case for simple unions - but there
we got lucky. Remember, visit_start_union() blindly returns true
for all visitors except for the dealloc visitor, where it returns
the value !!obj->u.data, and that this result then controls
whether to proceed with the visit to the variant. Pre-patch,
this meant that flat unions were testing whether the boxed pointer
was still NULL, and thereby skipping visit_end_implicit_struct()
and avoiding a NULL dereference if the pointer had not been
allocated. The same was true for simple unions where the current
branch had pointer type, except there we bypassed visit_type_FOO().
But for simple unions where the current branch had scalar type, the
contents of that scalar meant that the decision to call
visit_type_FOO() was data-dependent - the reason we got lucky there
is that visit_type_FOO() for all scalar types in the dealloc visitor
is a no-op (only the pointer variants had anything to free), so it
did not matter whether the dealloc visit was skipped. But with this
patch, we would risk leaking memory if we could skip a call to
visit_type_FOO_fields() based solely on a data-dependent decision.
But notice: in the dealloc visitor, visit_type_FOO() already handles
a NULL obj - it was only the visit_type_implicit_FOO() that was
failing to check for NULL. And now that we have refactored things to
have the branch be part of the parent struct, we no longer have a
separate pointer that can be NULL in the first place. So we can just
delete the call to visit_start_union() altogether, and blindly visit
the branch type; there is no change in behavior except to the dealloc
visitor, where we now unconditionally visit the branch, but where that
visit is now always safe (for a flat union, we can no longer
dereference NULL, and for a simple union, visit_type_FOO() was already
safely handling NULL on pointer types).
Unfortunately, simple unions are not as easy to switch to unboxed
layout; because we are special-casing the hidden implicit type with
a single 'data' member, we really DO need to keep calling another
layer of visit_start_struct(), with a second malloc; although there
are some cleanups planned for simple unions in later patches.
visit_start_union() and gen_visit_implicit_struct() are now unused.
Drop them.
Note that after this patch, the only remaining use of
visit_start_implicit_struct() is for alternate types; the next patch
will do further cleanup based on that fact.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1455778109-6278-14-git-send-email-eblake@redhat.com>
[Dead code deletion squashed in, commit message updated accordingly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-02-18 09:48:27 +03:00
|
|
|
info->value->u.q_mips.PC = env->active_tc.PC;
|
2014-09-01 15:59:46 +04:00
|
|
|
#elif defined(TARGET_TRICORE)
|
cpu: Convert CpuInfo into flat union
The CpuInfo struct is used only by the 'query-cpus' output
command, so we are free to modify it by adding fields (clients
are already supposed to ignore unknown output fields), or by
changing optional members to mandatory, while still keeping
QMP wire compatibility with older versions of qemu.
When qapi type CpuInfo was originally created for 0.14, we had
no notion of a flat union, and instead just listed a bunch of
optional fields with documentation about the mutually-exclusive
choice of which instruction pointer field(s) would be provided
for a given architecture. But now that we have flat unions and
introspection, it is better to segregate off which fields will
be provided according to the actual architecture. With this in
place, we no longer need the fields to be optional, because the
choice of the new 'arch' discriminator serves that role.
This has an additional benefit: the old all-in-one struct was
the only place in the code base that had a case-sensitive
naming of members 'pc' vs. 'PC'. Separating these spellings
into different branches of the flat union will allow us to add
restrictions against future case-insensitive collisions, since
that is generally a poor interface practice.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-25-git-send-email-eblake@redhat.com>
[Spelling of CPUInfo{SPARC,PPC,MIPS} fixed]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 11:52:59 +03:00
|
|
|
info->value->arch = CPU_INFO_ARCH_TRICORE;
|
qapi: Don't box branches of flat unions
There's no reason to do two malloc's for a flat union; let's just
inline the branch struct directly into the C union branch of the
flat union.
Surprisingly, fewer clients were actually using explicit references
to the branch types in comparison to the number of flat unions
thus modified.
This lets us reduce the hack in qapi-types:gen_variants() added in
the previous patch; we no longer need to distinguish between
alternates and flat unions.
The change to unboxed structs means that u.data (added in commit
cee2dedb) is now coincident with random fields of each branch of
the flat union, whereas beforehand it was only coincident with
pointers (since all branches of a flat union have to be objects).
Note that this was already the case for simple unions - but there
we got lucky. Remember, visit_start_union() blindly returns true
for all visitors except for the dealloc visitor, where it returns
the value !!obj->u.data, and that this result then controls
whether to proceed with the visit to the variant. Pre-patch,
this meant that flat unions were testing whether the boxed pointer
was still NULL, and thereby skipping visit_end_implicit_struct()
and avoiding a NULL dereference if the pointer had not been
allocated. The same was true for simple unions where the current
branch had pointer type, except there we bypassed visit_type_FOO().
But for simple unions where the current branch had scalar type, the
contents of that scalar meant that the decision to call
visit_type_FOO() was data-dependent - the reason we got lucky there
is that visit_type_FOO() for all scalar types in the dealloc visitor
is a no-op (only the pointer variants had anything to free), so it
did not matter whether the dealloc visit was skipped. But with this
patch, we would risk leaking memory if we could skip a call to
visit_type_FOO_fields() based solely on a data-dependent decision.
But notice: in the dealloc visitor, visit_type_FOO() already handles
a NULL obj - it was only the visit_type_implicit_FOO() that was
failing to check for NULL. And now that we have refactored things to
have the branch be part of the parent struct, we no longer have a
separate pointer that can be NULL in the first place. So we can just
delete the call to visit_start_union() altogether, and blindly visit
the branch type; there is no change in behavior except to the dealloc
visitor, where we now unconditionally visit the branch, but where that
visit is now always safe (for a flat union, we can no longer
dereference NULL, and for a simple union, visit_type_FOO() was already
safely handling NULL on pointer types).
Unfortunately, simple unions are not as easy to switch to unboxed
layout; because we are special-casing the hidden implicit type with
a single 'data' member, we really DO need to keep calling another
layer of visit_start_struct(), with a second malloc; although there
are some cleanups planned for simple unions in later patches.
visit_start_union() and gen_visit_implicit_struct() are now unused.
Drop them.
Note that after this patch, the only remaining use of
visit_start_implicit_struct() is for alternate types; the next patch
will do further cleanup based on that fact.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1455778109-6278-14-git-send-email-eblake@redhat.com>
[Dead code deletion squashed in, commit message updated accordingly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-02-18 09:48:27 +03:00
|
|
|
info->value->u.tricore.PC = env->PC;
|
cpu: Convert CpuInfo into flat union
The CpuInfo struct is used only by the 'query-cpus' output
command, so we are free to modify it by adding fields (clients
are already supposed to ignore unknown output fields), or by
changing optional members to mandatory, while still keeping
QMP wire compatibility with older versions of qemu.
When qapi type CpuInfo was originally created for 0.14, we had
no notion of a flat union, and instead just listed a bunch of
optional fields with documentation about the mutually-exclusive
choice of which instruction pointer field(s) would be provided
for a given architecture. But now that we have flat unions and
introspection, it is better to segregate off which fields will
be provided according to the actual architecture. With this in
place, we no longer need the fields to be optional, because the
choice of the new 'arch' discriminator serves that role.
This has an additional benefit: the old all-in-one struct was
the only place in the code base that had a case-sensitive
naming of members 'pc' vs. 'PC'. Separating these spellings
into different branches of the flat union will allow us to add
restrictions against future case-insensitive collisions, since
that is generally a poor interface practice.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1447836791-369-25-git-send-email-eblake@redhat.com>
[Spelling of CPUInfo{SPARC,PPC,MIPS} fixed]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-18 11:52:59 +03:00
|
|
|
#else
|
|
|
|
info->value->arch = CPU_INFO_ARCH_OTHER;
|
2011-09-21 23:38:35 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/* XXX: waiting for the qapi to support GSList */
|
|
|
|
if (!cur_item) {
|
|
|
|
head = cur_item = info;
|
|
|
|
} else {
|
|
|
|
cur_item->next = info;
|
|
|
|
cur_item = info;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return head;
|
|
|
|
}
|
2011-11-22 22:32:37 +04:00
|
|
|
|
|
|
|
void qmp_memsave(int64_t addr, int64_t size, const char *filename,
|
|
|
|
bool has_cpu, int64_t cpu_index, Error **errp)
|
|
|
|
{
|
|
|
|
FILE *f;
|
|
|
|
uint32_t l;
|
2012-12-17 09:18:02 +04:00
|
|
|
CPUState *cpu;
|
2011-11-22 22:32:37 +04:00
|
|
|
uint8_t buf[1024];
|
2015-02-08 15:14:38 +03:00
|
|
|
int64_t orig_addr = addr, orig_size = size;
|
2011-11-22 22:32:37 +04:00
|
|
|
|
|
|
|
if (!has_cpu) {
|
|
|
|
cpu_index = 0;
|
|
|
|
}
|
|
|
|
|
2013-02-15 18:41:49 +04:00
|
|
|
cpu = qemu_get_cpu(cpu_index);
|
|
|
|
if (cpu == NULL) {
|
2015-03-17 13:54:50 +03:00
|
|
|
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index",
|
|
|
|
"a CPU number");
|
2011-11-22 22:32:37 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
f = fopen(filename, "wb");
|
|
|
|
if (!f) {
|
2013-06-07 22:35:06 +04:00
|
|
|
error_setg_file_open(errp, errno, filename);
|
2011-11-22 22:32:37 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (size != 0) {
|
|
|
|
l = sizeof(buf);
|
|
|
|
if (l > size)
|
|
|
|
l = size;
|
2013-10-01 20:19:30 +04:00
|
|
|
if (cpu_memory_rw_debug(cpu, addr, buf, l, 0) != 0) {
|
2015-02-08 15:14:38 +03:00
|
|
|
error_setg(errp, "Invalid addr 0x%016" PRIx64 "/size %" PRId64
|
|
|
|
" specified", orig_addr, orig_size);
|
2013-10-01 20:19:30 +04:00
|
|
|
goto exit;
|
|
|
|
}
|
2011-11-22 22:32:37 +04:00
|
|
|
if (fwrite(buf, 1, l, f) != l) {
|
2015-03-17 13:54:50 +03:00
|
|
|
error_setg(errp, QERR_IO_ERROR);
|
2011-11-22 22:32:37 +04:00
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
addr += l;
|
|
|
|
size -= l;
|
|
|
|
}
|
|
|
|
|
|
|
|
exit:
|
|
|
|
fclose(f);
|
|
|
|
}
|
2011-11-22 23:26:46 +04:00
|
|
|
|
|
|
|
void qmp_pmemsave(int64_t addr, int64_t size, const char *filename,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
FILE *f;
|
|
|
|
uint32_t l;
|
|
|
|
uint8_t buf[1024];
|
|
|
|
|
|
|
|
f = fopen(filename, "wb");
|
|
|
|
if (!f) {
|
2013-06-07 22:35:06 +04:00
|
|
|
error_setg_file_open(errp, errno, filename);
|
2011-11-22 23:26:46 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (size != 0) {
|
|
|
|
l = sizeof(buf);
|
|
|
|
if (l > size)
|
|
|
|
l = size;
|
2014-04-07 22:28:23 +04:00
|
|
|
cpu_physical_memory_read(addr, buf, l);
|
2011-11-22 23:26:46 +04:00
|
|
|
if (fwrite(buf, 1, l, f) != l) {
|
2015-03-17 13:54:50 +03:00
|
|
|
error_setg(errp, QERR_IO_ERROR);
|
2011-11-22 23:26:46 +04:00
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
addr += l;
|
|
|
|
size -= l;
|
|
|
|
}
|
|
|
|
|
|
|
|
exit:
|
|
|
|
fclose(f);
|
|
|
|
}
|
2011-11-23 18:55:53 +04:00
|
|
|
|
|
|
|
void qmp_inject_nmi(Error **errp)
|
|
|
|
{
|
2014-08-20 16:16:33 +04:00
|
|
|
nmi_monitor_handle(monitor_get_cpu_index(), errp);
|
2011-11-23 18:55:53 +04:00
|
|
|
}
|
2014-07-25 13:56:33 +04:00
|
|
|
|
|
|
|
void dump_drift_info(FILE *f, fprintf_function cpu_fprintf)
|
|
|
|
{
|
|
|
|
if (!use_icount) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cpu_fprintf(f, "Host - Guest clock %"PRIi64" ms\n",
|
|
|
|
(cpu_get_clock() - cpu_get_icount())/SCALE_MS);
|
|
|
|
if (icount_align_option) {
|
|
|
|
cpu_fprintf(f, "Max guest delay %"PRIi64" ms\n", -max_delay/SCALE_MS);
|
|
|
|
cpu_fprintf(f, "Max guest advance %"PRIi64" ms\n", max_advance/SCALE_MS);
|
|
|
|
} else {
|
|
|
|
cpu_fprintf(f, "Max guest delay NA\n");
|
|
|
|
cpu_fprintf(f, "Max guest advance NA\n");
|
|
|
|
}
|
|
|
|
}
|