mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* QemuMutex tracing improvements (Alex)
* ram_addr_t optimization (David)
* SCSI fixes (Fam, Stefan, me)
* do {} while (0) fixes (Eric)
* KVM fix for PMU (Jan)
* memory leak fixes from ASAN (Marc-André)
* migration fix for HPET, icount, loadvm (Maria, Pavel)
* hflags fixes (me, Tao)
* block/iscsi uninitialized variable (Peter L.)
* full support for GMainContexts in character devices (Peter Xu)
* more boot-serial-test (Thomas)
* Memory leak fix (Zhecheng)
# gpg: Signature made Tue 16 Jan 2018 14:15:45 GMT
# gpg: using RSA key 0xBFFBD25F78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg: aka "Paolo Bonzini <pbonzini@redhat.com>"
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1
# Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83
* remotes/bonzini/tags/for-upstream: (51 commits)
scripts/analyse-locks-simpletrace.py: script to analyse lock times
util/qemu-thread-*: add qemu_lock, locked and unlock trace events
cpu: flush TB cache when loading VMState
block/iscsi: fix initialization of iTask in iscsi_co_get_block_status
find_ram_offset: Align ram_addr_t allocation on long boundaries
find_ram_offset: Add comments and tracing
cpu_physical_memory_sync_dirty_bitmap: Another alignment fix
checkpatch: Enforce proper do/while (0) style
maint: Fix macros with broken 'do/while(0); ' usage
tests: Avoid 'do/while(false); ' in vhost-user-bridge
chardev: Clean up previous patch indentation
chardev: Use goto/label instead of do/break/while(0)
mips: Tweak location of ';' in macros
net: Drop unusual use of do { } while (0);
irq: fix memory leak
cpus: unify qemu_*_wait_io_event
icount: fixed saving/restoring of icount warp timers
scripts/qemu-gdb/timers.py: new helper to dump timer state
scripts/qemu-gdb: add simple tcg lock status helper
target-i386: update hflags on Hypervisor.framework
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -8,9 +8,12 @@ SRC_PATH=.
|
||||
|
||||
UNCHECKED_GOALS := %clean TAGS cscope ctags dist \
|
||||
html info pdf txt \
|
||||
help check-help \
|
||||
help check-help print-% \
|
||||
docker docker-% vm-test vm-build-%
|
||||
|
||||
print-%:
|
||||
@echo '$*=$($*)'
|
||||
|
||||
# All following code might depend on configuration variables
|
||||
ifneq ($(wildcard config-host.mak),)
|
||||
# Put the all: rule here so that config-host.mak can contain dependencies.
|
||||
@@ -277,7 +280,7 @@ else
|
||||
DOCS=
|
||||
endif
|
||||
|
||||
SUBDIR_MAKEFLAGS=$(if $(V),,--no-print-directory) BUILD_DIR=$(BUILD_DIR)
|
||||
SUBDIR_MAKEFLAGS=BUILD_DIR=$(BUILD_DIR)
|
||||
SUBDIR_DEVICES_MAK=$(patsubst %, %/config-devices.mak, $(TARGET_DIRS))
|
||||
SUBDIR_DEVICES_MAK_DEP=$(patsubst %, %-config-devices.mak.d, $(TARGET_DIRS))
|
||||
|
||||
|
||||
+2
-2
@@ -89,7 +89,7 @@ static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x)
|
||||
} \
|
||||
goto label; \
|
||||
} \
|
||||
} while (0);
|
||||
} while (0)
|
||||
|
||||
#define CHECK_DEAD_GOTO(c, stream, rerror, label) \
|
||||
do { \
|
||||
@@ -107,7 +107,7 @@ static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x)
|
||||
} \
|
||||
goto label; \
|
||||
} \
|
||||
} while (0);
|
||||
} while (0)
|
||||
|
||||
static int qpa_simple_read (PAVoiceIn *p, void *data, size_t length, int *rerror)
|
||||
{
|
||||
|
||||
+2
-1
@@ -658,6 +658,8 @@ static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs,
|
||||
uint64_t lba;
|
||||
int64_t ret;
|
||||
|
||||
iscsi_co_init_iscsitask(iscsilun, &iTask);
|
||||
|
||||
if (!is_sector_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
@@ -675,7 +677,6 @@ static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs,
|
||||
|
||||
lba = sector_qemu2lun(sector_num, iscsilun);
|
||||
|
||||
iscsi_co_init_iscsitask(iscsilun, &iTask);
|
||||
qemu_mutex_lock(&iscsilun->mutex);
|
||||
retry:
|
||||
if (iscsi_get_lba_status_task(iscsilun->iscsi, iscsilun->lun,
|
||||
|
||||
+1
-1
@@ -356,7 +356,7 @@ guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond,
|
||||
}
|
||||
|
||||
g_source_set_callback(src, (GSourceFunc)func, user_data, NULL);
|
||||
tag = g_source_attach(src, NULL);
|
||||
tag = g_source_attach(src, s->gcontext);
|
||||
g_source_unref(src);
|
||||
|
||||
return tag;
|
||||
|
||||
+32
-32
@@ -42,8 +42,8 @@ typedef struct {
|
||||
|
||||
/* Protected by the Chardev chr_write_lock. */
|
||||
int connected;
|
||||
guint timer_tag;
|
||||
guint open_tag;
|
||||
GSource *timer_src;
|
||||
GSource *open_source;
|
||||
} PtyChardev;
|
||||
|
||||
#define PTY_CHARDEV(obj) OBJECT_CHECK(PtyChardev, (obj), TYPE_CHARDEV_PTY)
|
||||
@@ -57,8 +57,9 @@ static gboolean pty_chr_timer(gpointer opaque)
|
||||
PtyChardev *s = PTY_CHARDEV(opaque);
|
||||
|
||||
qemu_mutex_lock(&chr->chr_write_lock);
|
||||
s->timer_tag = 0;
|
||||
s->open_tag = 0;
|
||||
s->timer_src = NULL;
|
||||
g_source_unref(s->open_source);
|
||||
s->open_source = NULL;
|
||||
if (!s->connected) {
|
||||
/* Next poll ... */
|
||||
pty_chr_update_read_handler_locked(chr);
|
||||
@@ -67,25 +68,25 @@ static gboolean pty_chr_timer(gpointer opaque)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void pty_chr_timer_cancel(PtyChardev *s)
|
||||
{
|
||||
if (s->timer_src) {
|
||||
g_source_destroy(s->timer_src);
|
||||
g_source_unref(s->timer_src);
|
||||
s->timer_src = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Called with chr_write_lock held. */
|
||||
static void pty_chr_rearm_timer(Chardev *chr, int ms)
|
||||
{
|
||||
PtyChardev *s = PTY_CHARDEV(chr);
|
||||
char *name;
|
||||
|
||||
if (s->timer_tag) {
|
||||
g_source_remove(s->timer_tag);
|
||||
s->timer_tag = 0;
|
||||
}
|
||||
|
||||
if (ms == 1000) {
|
||||
name = g_strdup_printf("pty-timer-secs-%s", chr->label);
|
||||
s->timer_tag = g_timeout_add_seconds(1, pty_chr_timer, chr);
|
||||
} else {
|
||||
name = g_strdup_printf("pty-timer-ms-%s", chr->label);
|
||||
s->timer_tag = g_timeout_add(ms, pty_chr_timer, chr);
|
||||
}
|
||||
g_source_set_name_by_id(s->timer_tag, name);
|
||||
pty_chr_timer_cancel(s);
|
||||
name = g_strdup_printf("pty-timer-%s", chr->label);
|
||||
s->timer_src = qemu_chr_timeout_add_ms(chr, ms, pty_chr_timer, chr);
|
||||
g_source_set_name(s->timer_src, name);
|
||||
g_free(name);
|
||||
}
|
||||
|
||||
@@ -183,7 +184,7 @@ static gboolean qemu_chr_be_generic_open_func(gpointer opaque)
|
||||
Chardev *chr = CHARDEV(opaque);
|
||||
PtyChardev *s = PTY_CHARDEV(opaque);
|
||||
|
||||
s->open_tag = 0;
|
||||
s->open_source = NULL;
|
||||
qemu_chr_be_event(chr, CHR_EVENT_OPENED);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -194,9 +195,10 @@ static void pty_chr_state(Chardev *chr, int connected)
|
||||
PtyChardev *s = PTY_CHARDEV(chr);
|
||||
|
||||
if (!connected) {
|
||||
if (s->open_tag) {
|
||||
g_source_remove(s->open_tag);
|
||||
s->open_tag = 0;
|
||||
if (s->open_source) {
|
||||
g_source_destroy(s->open_source);
|
||||
g_source_unref(s->open_source);
|
||||
s->open_source = NULL;
|
||||
}
|
||||
remove_fd_in_watch(chr);
|
||||
s->connected = 0;
|
||||
@@ -205,14 +207,15 @@ static void pty_chr_state(Chardev *chr, int connected)
|
||||
* the virtual device linked to our pty. */
|
||||
pty_chr_rearm_timer(chr, 1000);
|
||||
} else {
|
||||
if (s->timer_tag) {
|
||||
g_source_remove(s->timer_tag);
|
||||
s->timer_tag = 0;
|
||||
}
|
||||
pty_chr_timer_cancel(s);
|
||||
if (!s->connected) {
|
||||
g_assert(s->open_tag == 0);
|
||||
g_assert(s->open_source == NULL);
|
||||
s->open_source = g_idle_source_new();
|
||||
s->connected = 1;
|
||||
s->open_tag = g_idle_add(qemu_chr_be_generic_open_func, chr);
|
||||
g_source_set_callback(s->open_source,
|
||||
qemu_chr_be_generic_open_func,
|
||||
chr, NULL);
|
||||
g_source_attach(s->open_source, chr->gcontext);
|
||||
}
|
||||
if (!chr->gsource) {
|
||||
chr->gsource = io_add_watch_poll(chr, s->ioc,
|
||||
@@ -231,10 +234,7 @@ static void char_pty_finalize(Object *obj)
|
||||
qemu_mutex_lock(&chr->chr_write_lock);
|
||||
pty_chr_state(chr, 0);
|
||||
object_unref(OBJECT(s->ioc));
|
||||
if (s->timer_tag) {
|
||||
g_source_remove(s->timer_tag);
|
||||
s->timer_tag = 0;
|
||||
}
|
||||
pty_chr_timer_cancel(s);
|
||||
qemu_mutex_unlock(&chr->chr_write_lock);
|
||||
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
|
||||
}
|
||||
@@ -267,7 +267,7 @@ static void char_pty_open(Chardev *chr,
|
||||
name = g_strdup_printf("chardev-pty-%s", chr->label);
|
||||
qio_channel_set_name(QIO_CHANNEL(s->ioc), name);
|
||||
g_free(name);
|
||||
s->timer_tag = 0;
|
||||
s->timer_src = NULL;
|
||||
*be_opened = false;
|
||||
}
|
||||
|
||||
|
||||
+40
-35
@@ -64,69 +64,74 @@ static void tty_serial_init(int fd, int speed,
|
||||
#endif
|
||||
tcgetattr(fd, &tty);
|
||||
|
||||
#define check_speed(val) if (speed <= val) { spd = B##val; break; }
|
||||
#define check_speed(val) \
|
||||
if (speed <= val) { \
|
||||
spd = B##val; \
|
||||
goto done; \
|
||||
}
|
||||
|
||||
speed = speed * 10 / 11;
|
||||
do {
|
||||
check_speed(50);
|
||||
check_speed(75);
|
||||
check_speed(110);
|
||||
check_speed(134);
|
||||
check_speed(150);
|
||||
check_speed(200);
|
||||
check_speed(300);
|
||||
check_speed(600);
|
||||
check_speed(1200);
|
||||
check_speed(1800);
|
||||
check_speed(2400);
|
||||
check_speed(4800);
|
||||
check_speed(9600);
|
||||
check_speed(19200);
|
||||
check_speed(38400);
|
||||
/* Non-Posix values follow. They may be unsupported on some systems. */
|
||||
check_speed(57600);
|
||||
check_speed(115200);
|
||||
check_speed(50);
|
||||
check_speed(75);
|
||||
check_speed(110);
|
||||
check_speed(134);
|
||||
check_speed(150);
|
||||
check_speed(200);
|
||||
check_speed(300);
|
||||
check_speed(600);
|
||||
check_speed(1200);
|
||||
check_speed(1800);
|
||||
check_speed(2400);
|
||||
check_speed(4800);
|
||||
check_speed(9600);
|
||||
check_speed(19200);
|
||||
check_speed(38400);
|
||||
/* Non-Posix values follow. They may be unsupported on some systems. */
|
||||
check_speed(57600);
|
||||
check_speed(115200);
|
||||
#ifdef B230400
|
||||
check_speed(230400);
|
||||
check_speed(230400);
|
||||
#endif
|
||||
#ifdef B460800
|
||||
check_speed(460800);
|
||||
check_speed(460800);
|
||||
#endif
|
||||
#ifdef B500000
|
||||
check_speed(500000);
|
||||
check_speed(500000);
|
||||
#endif
|
||||
#ifdef B576000
|
||||
check_speed(576000);
|
||||
check_speed(576000);
|
||||
#endif
|
||||
#ifdef B921600
|
||||
check_speed(921600);
|
||||
check_speed(921600);
|
||||
#endif
|
||||
#ifdef B1000000
|
||||
check_speed(1000000);
|
||||
check_speed(1000000);
|
||||
#endif
|
||||
#ifdef B1152000
|
||||
check_speed(1152000);
|
||||
check_speed(1152000);
|
||||
#endif
|
||||
#ifdef B1500000
|
||||
check_speed(1500000);
|
||||
check_speed(1500000);
|
||||
#endif
|
||||
#ifdef B2000000
|
||||
check_speed(2000000);
|
||||
check_speed(2000000);
|
||||
#endif
|
||||
#ifdef B2500000
|
||||
check_speed(2500000);
|
||||
check_speed(2500000);
|
||||
#endif
|
||||
#ifdef B3000000
|
||||
check_speed(3000000);
|
||||
check_speed(3000000);
|
||||
#endif
|
||||
#ifdef B3500000
|
||||
check_speed(3500000);
|
||||
check_speed(3500000);
|
||||
#endif
|
||||
#ifdef B4000000
|
||||
check_speed(4000000);
|
||||
check_speed(4000000);
|
||||
#endif
|
||||
spd = B115200;
|
||||
} while (0);
|
||||
spd = B115200;
|
||||
|
||||
#undef check_speed
|
||||
done:
|
||||
cfsetispeed(&tty, spd);
|
||||
cfsetospeed(&tty, spd);
|
||||
|
||||
|
||||
+18
-10
@@ -57,7 +57,7 @@ typedef struct {
|
||||
bool is_telnet;
|
||||
bool is_tn3270;
|
||||
|
||||
guint reconnect_timer;
|
||||
GSource *reconnect_timer;
|
||||
int64_t reconnect_time;
|
||||
bool connect_err_reported;
|
||||
} SocketChardev;
|
||||
@@ -67,16 +67,27 @@ typedef struct {
|
||||
|
||||
static gboolean socket_reconnect_timeout(gpointer opaque);
|
||||
|
||||
static void tcp_chr_reconn_timer_cancel(SocketChardev *s)
|
||||
{
|
||||
if (s->reconnect_timer) {
|
||||
g_source_destroy(s->reconnect_timer);
|
||||
g_source_unref(s->reconnect_timer);
|
||||
s->reconnect_timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void qemu_chr_socket_restart_timer(Chardev *chr)
|
||||
{
|
||||
SocketChardev *s = SOCKET_CHARDEV(chr);
|
||||
char *name;
|
||||
|
||||
assert(s->connected == 0);
|
||||
s->reconnect_timer = g_timeout_add_seconds(s->reconnect_time,
|
||||
socket_reconnect_timeout, chr);
|
||||
name = g_strdup_printf("chardev-socket-reconnect-%s", chr->label);
|
||||
g_source_set_name_by_id(s->reconnect_timer, name);
|
||||
s->reconnect_timer = qemu_chr_timeout_add_ms(chr,
|
||||
s->reconnect_time * 1000,
|
||||
socket_reconnect_timeout,
|
||||
chr);
|
||||
g_source_set_name(s->reconnect_timer, name);
|
||||
g_free(name);
|
||||
}
|
||||
|
||||
@@ -781,11 +792,7 @@ static void char_socket_finalize(Object *obj)
|
||||
SocketChardev *s = SOCKET_CHARDEV(obj);
|
||||
|
||||
tcp_chr_free_connection(chr);
|
||||
|
||||
if (s->reconnect_timer) {
|
||||
g_source_remove(s->reconnect_timer);
|
||||
s->reconnect_timer = 0;
|
||||
}
|
||||
tcp_chr_reconn_timer_cancel(s);
|
||||
qapi_free_SocketAddress(s->addr);
|
||||
if (s->listener) {
|
||||
qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL);
|
||||
@@ -824,7 +831,8 @@ static gboolean socket_reconnect_timeout(gpointer opaque)
|
||||
SocketChardev *s = SOCKET_CHARDEV(opaque);
|
||||
QIOChannelSocket *sioc;
|
||||
|
||||
s->reconnect_timer = 0;
|
||||
g_source_unref(s->reconnect_timer);
|
||||
s->reconnect_timer = NULL;
|
||||
|
||||
if (chr->be_open) {
|
||||
return false;
|
||||
|
||||
@@ -1084,6 +1084,24 @@ void qmp_chardev_send_break(const char *id, Error **errp)
|
||||
qemu_chr_be_event(chr, CHR_EVENT_BREAK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a timeout callback for the chardev (in milliseconds), return
|
||||
* the GSource object created. Please use this to add timeout hook for
|
||||
* chardev instead of g_timeout_add() and g_timeout_add_seconds(), to
|
||||
* make sure the gcontext that the task bound to is correct.
|
||||
*/
|
||||
GSource *qemu_chr_timeout_add_ms(Chardev *chr, guint ms,
|
||||
GSourceFunc func, void *private)
|
||||
{
|
||||
GSource *source = g_timeout_source_new(ms);
|
||||
|
||||
assert(func);
|
||||
g_source_set_callback(source, func, private, NULL);
|
||||
g_source_attach(source, chr->gcontext);
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
void qemu_chr_cleanup(void)
|
||||
{
|
||||
object_unparent(get_chardevs_root());
|
||||
|
||||
@@ -3464,6 +3464,7 @@ else
|
||||
done
|
||||
if test "$found" = "no"; then
|
||||
LIBS="$pthread_lib $LIBS"
|
||||
libs_qga="$pthread_lib $libs_qga"
|
||||
fi
|
||||
PTHREAD_LIB="$pthread_lib"
|
||||
break
|
||||
@@ -5193,8 +5194,19 @@ if test "$gcov" = "yes" ; then
|
||||
LDFLAGS="-fprofile-arcs -ftest-coverage $LDFLAGS"
|
||||
elif test "$fortify_source" = "yes" ; then
|
||||
CFLAGS="-O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 $CFLAGS"
|
||||
elif test "$debug" = "no"; then
|
||||
CFLAGS="-O2 $CFLAGS"
|
||||
elif test "$debug" = "yes"; then
|
||||
if compile_prog "-Og" ""; then
|
||||
CFLAGS="-Og $CFLAGS"
|
||||
elif compile_prog "-O1" ""; then
|
||||
CFLAGS="-O1 $CFLAGS"
|
||||
fi
|
||||
# Workaround GCC false-positive Wuninitialized bugs with Og or O1:
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=24639
|
||||
if cc_has_warning_flag "-Wno-maybe-uninitialized"; then
|
||||
CFLAGS="-Wno-maybe-uninitialized $CFLAGS"
|
||||
fi
|
||||
else
|
||||
CFLAGS="-O2 $CFLAGS"
|
||||
fi
|
||||
|
||||
##########################################
|
||||
|
||||
@@ -120,16 +120,11 @@ static bool all_cpu_threads_idle(void)
|
||||
/* Protected by TimersState seqlock */
|
||||
|
||||
static bool icount_sleep = true;
|
||||
static int64_t vm_clock_warp_start = -1;
|
||||
/* Conversion factor from emulated instructions to virtual clock ticks. */
|
||||
static int icount_time_shift;
|
||||
/* Arbitrarily pick 1MIPS as the minimum allowable speed. */
|
||||
#define MAX_ICOUNT_SHIFT 10
|
||||
|
||||
static QEMUTimer *icount_rt_timer;
|
||||
static QEMUTimer *icount_vm_timer;
|
||||
static QEMUTimer *icount_warp_timer;
|
||||
|
||||
typedef struct TimersState {
|
||||
/* Protected by BQL. */
|
||||
int64_t cpu_ticks_prev;
|
||||
@@ -147,6 +142,11 @@ typedef struct TimersState {
|
||||
int64_t qemu_icount_bias;
|
||||
/* Only written by TCG thread */
|
||||
int64_t qemu_icount;
|
||||
/* for adjusting icount */
|
||||
int64_t vm_clock_warp_start;
|
||||
QEMUTimer *icount_rt_timer;
|
||||
QEMUTimer *icount_vm_timer;
|
||||
QEMUTimer *icount_warp_timer;
|
||||
} TimersState;
|
||||
|
||||
static TimersState timers_state;
|
||||
@@ -432,14 +432,14 @@ static void icount_adjust(void)
|
||||
|
||||
static void icount_adjust_rt(void *opaque)
|
||||
{
|
||||
timer_mod(icount_rt_timer,
|
||||
timer_mod(timers_state.icount_rt_timer,
|
||||
qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) + 1000);
|
||||
icount_adjust();
|
||||
}
|
||||
|
||||
static void icount_adjust_vm(void *opaque)
|
||||
{
|
||||
timer_mod(icount_vm_timer,
|
||||
timer_mod(timers_state.icount_vm_timer,
|
||||
qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
|
||||
NANOSECONDS_PER_SECOND / 10);
|
||||
icount_adjust();
|
||||
@@ -460,7 +460,7 @@ static void icount_warp_rt(void)
|
||||
*/
|
||||
do {
|
||||
seq = seqlock_read_begin(&timers_state.vm_clock_seqlock);
|
||||
warp_start = vm_clock_warp_start;
|
||||
warp_start = timers_state.vm_clock_warp_start;
|
||||
} while (seqlock_read_retry(&timers_state.vm_clock_seqlock, seq));
|
||||
|
||||
if (warp_start == -1) {
|
||||
@@ -473,7 +473,7 @@ static void icount_warp_rt(void)
|
||||
cpu_get_clock_locked());
|
||||
int64_t warp_delta;
|
||||
|
||||
warp_delta = clock - vm_clock_warp_start;
|
||||
warp_delta = clock - timers_state.vm_clock_warp_start;
|
||||
if (use_icount == 2) {
|
||||
/*
|
||||
* In adaptive mode, do not let QEMU_CLOCK_VIRTUAL run too
|
||||
@@ -485,7 +485,7 @@ static void icount_warp_rt(void)
|
||||
}
|
||||
timers_state.qemu_icount_bias += warp_delta;
|
||||
}
|
||||
vm_clock_warp_start = -1;
|
||||
timers_state.vm_clock_warp_start = -1;
|
||||
seqlock_write_end(&timers_state.vm_clock_seqlock);
|
||||
|
||||
if (qemu_clock_expired(QEMU_CLOCK_VIRTUAL)) {
|
||||
@@ -594,11 +594,13 @@ void qemu_start_warp_timer(void)
|
||||
* every 100ms.
|
||||
*/
|
||||
seqlock_write_begin(&timers_state.vm_clock_seqlock);
|
||||
if (vm_clock_warp_start == -1 || vm_clock_warp_start > clock) {
|
||||
vm_clock_warp_start = clock;
|
||||
if (timers_state.vm_clock_warp_start == -1
|
||||
|| timers_state.vm_clock_warp_start > clock) {
|
||||
timers_state.vm_clock_warp_start = clock;
|
||||
}
|
||||
seqlock_write_end(&timers_state.vm_clock_seqlock);
|
||||
timer_mod_anticipate(icount_warp_timer, clock + deadline);
|
||||
timer_mod_anticipate(timers_state.icount_warp_timer,
|
||||
clock + deadline);
|
||||
}
|
||||
} else if (deadline == 0) {
|
||||
qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
|
||||
@@ -623,7 +625,7 @@ static void qemu_account_warp_timer(void)
|
||||
return;
|
||||
}
|
||||
|
||||
timer_del(icount_warp_timer);
|
||||
timer_del(timers_state.icount_warp_timer);
|
||||
icount_warp_rt();
|
||||
}
|
||||
|
||||
@@ -632,6 +634,45 @@ static bool icount_state_needed(void *opaque)
|
||||
return use_icount;
|
||||
}
|
||||
|
||||
static bool warp_timer_state_needed(void *opaque)
|
||||
{
|
||||
TimersState *s = opaque;
|
||||
return s->icount_warp_timer != NULL;
|
||||
}
|
||||
|
||||
static bool adjust_timers_state_needed(void *opaque)
|
||||
{
|
||||
TimersState *s = opaque;
|
||||
return s->icount_rt_timer != NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Subsection for warp timer migration is optional, because may not be created
|
||||
*/
|
||||
static const VMStateDescription icount_vmstate_warp_timer = {
|
||||
.name = "timer/icount/warp_timer",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = warp_timer_state_needed,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_INT64(vm_clock_warp_start, TimersState),
|
||||
VMSTATE_TIMER_PTR(icount_warp_timer, TimersState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription icount_vmstate_adjust_timers = {
|
||||
.name = "timer/icount/timers",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = adjust_timers_state_needed,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_TIMER_PTR(icount_rt_timer, TimersState),
|
||||
VMSTATE_TIMER_PTR(icount_vm_timer, TimersState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* This is a subsection for icount migration.
|
||||
*/
|
||||
@@ -644,6 +685,11 @@ static const VMStateDescription icount_vmstate_timers = {
|
||||
VMSTATE_INT64(qemu_icount_bias, TimersState),
|
||||
VMSTATE_INT64(qemu_icount, TimersState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
.subsections = (const VMStateDescription*[]) {
|
||||
&icount_vmstate_warp_timer,
|
||||
&icount_vmstate_adjust_timers,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
@@ -754,7 +800,7 @@ void configure_icount(QemuOpts *opts, Error **errp)
|
||||
|
||||
icount_sleep = qemu_opt_get_bool(opts, "sleep", true);
|
||||
if (icount_sleep) {
|
||||
icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT,
|
||||
timers_state.icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT,
|
||||
icount_timer_cb, NULL);
|
||||
}
|
||||
|
||||
@@ -788,13 +834,14 @@ void configure_icount(QemuOpts *opts, Error **errp)
|
||||
the virtual time trigger catches emulated time passing too fast.
|
||||
Realtime triggers occur even when idle, so use them less frequently
|
||||
than VM triggers. */
|
||||
icount_rt_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL_RT,
|
||||
timers_state.vm_clock_warp_start = -1;
|
||||
timers_state.icount_rt_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL_RT,
|
||||
icount_adjust_rt, NULL);
|
||||
timer_mod(icount_rt_timer,
|
||||
timer_mod(timers_state.icount_rt_timer,
|
||||
qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) + 1000);
|
||||
icount_vm_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
|
||||
timers_state.icount_vm_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
|
||||
icount_adjust_vm, NULL);
|
||||
timer_mod(icount_vm_timer,
|
||||
timer_mod(timers_state.icount_vm_timer,
|
||||
qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
|
||||
NANOSECONDS_PER_SECOND / 10);
|
||||
}
|
||||
@@ -862,7 +909,8 @@ static void kick_tcg_thread(void *opaque)
|
||||
|
||||
static void start_tcg_kick_timer(void)
|
||||
{
|
||||
if (!mttcg_enabled && !tcg_kick_vcpu_timer && CPU_NEXT(first_cpu)) {
|
||||
assert(!mttcg_enabled);
|
||||
if (!tcg_kick_vcpu_timer && CPU_NEXT(first_cpu)) {
|
||||
tcg_kick_vcpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
|
||||
kick_tcg_thread, NULL);
|
||||
timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick());
|
||||
@@ -871,6 +919,7 @@ static void start_tcg_kick_timer(void)
|
||||
|
||||
static void stop_tcg_kick_timer(void)
|
||||
{
|
||||
assert(!mttcg_enabled);
|
||||
if (tcg_kick_vcpu_timer) {
|
||||
timer_del(tcg_kick_vcpu_timer);
|
||||
tcg_kick_vcpu_timer = NULL;
|
||||
@@ -1090,18 +1139,9 @@ static void qemu_wait_io_event_common(CPUState *cpu)
|
||||
process_queued_cpu_work(cpu);
|
||||
}
|
||||
|
||||
static bool qemu_tcg_should_sleep(CPUState *cpu)
|
||||
static void qemu_tcg_rr_wait_io_event(CPUState *cpu)
|
||||
{
|
||||
if (mttcg_enabled) {
|
||||
return cpu_thread_is_idle(cpu);
|
||||
} else {
|
||||
return all_cpu_threads_idle();
|
||||
}
|
||||
}
|
||||
|
||||
static void qemu_tcg_wait_io_event(CPUState *cpu)
|
||||
{
|
||||
while (qemu_tcg_should_sleep(cpu)) {
|
||||
while (all_cpu_threads_idle()) {
|
||||
stop_tcg_kick_timer();
|
||||
qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex);
|
||||
}
|
||||
@@ -1111,20 +1151,18 @@ static void qemu_tcg_wait_io_event(CPUState *cpu)
|
||||
qemu_wait_io_event_common(cpu);
|
||||
}
|
||||
|
||||
static void qemu_kvm_wait_io_event(CPUState *cpu)
|
||||
static void qemu_wait_io_event(CPUState *cpu)
|
||||
{
|
||||
while (cpu_thread_is_idle(cpu)) {
|
||||
qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex);
|
||||
}
|
||||
|
||||
qemu_wait_io_event_common(cpu);
|
||||
}
|
||||
|
||||
static void qemu_hvf_wait_io_event(CPUState *cpu)
|
||||
{
|
||||
while (cpu_thread_is_idle(cpu)) {
|
||||
qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex);
|
||||
#ifdef _WIN32
|
||||
/* Eat dummy APC queued by qemu_cpu_kick_thread. */
|
||||
if (!tcg_enabled()) {
|
||||
SleepEx(0, TRUE);
|
||||
}
|
||||
#endif
|
||||
qemu_wait_io_event_common(cpu);
|
||||
}
|
||||
|
||||
@@ -1160,7 +1198,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
|
||||
cpu_handle_guest_debug(cpu);
|
||||
}
|
||||
}
|
||||
qemu_kvm_wait_io_event(cpu);
|
||||
qemu_wait_io_event(cpu);
|
||||
} while (!cpu->unplug || cpu_can_run(cpu));
|
||||
|
||||
qemu_kvm_destroy_vcpu(cpu);
|
||||
@@ -1206,7 +1244,7 @@ static void *qemu_dummy_cpu_thread_fn(void *arg)
|
||||
exit(1);
|
||||
}
|
||||
qemu_mutex_lock_iothread();
|
||||
qemu_wait_io_event_common(cpu);
|
||||
qemu_wait_io_event(cpu);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -1423,7 +1461,7 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg)
|
||||
atomic_mb_set(&cpu->exit_request, 0);
|
||||
}
|
||||
|
||||
qemu_tcg_wait_io_event(cpu ? cpu : QTAILQ_FIRST(&cpus));
|
||||
qemu_tcg_rr_wait_io_event(cpu ? cpu : QTAILQ_FIRST(&cpus));
|
||||
deal_with_unplugged_cpus();
|
||||
}
|
||||
|
||||
@@ -1454,13 +1492,7 @@ static void *qemu_hax_cpu_thread_fn(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
while (cpu_thread_is_idle(cpu)) {
|
||||
qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
SleepEx(0, TRUE);
|
||||
#endif
|
||||
qemu_wait_io_event_common(cpu);
|
||||
qemu_wait_io_event(cpu);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -1497,7 +1529,7 @@ static void *qemu_hvf_cpu_thread_fn(void *arg)
|
||||
cpu_handle_guest_debug(cpu);
|
||||
}
|
||||
}
|
||||
qemu_hvf_wait_io_event(cpu);
|
||||
qemu_wait_io_event(cpu);
|
||||
} while (!cpu->unplug || cpu_can_run(cpu));
|
||||
|
||||
hvf_vcpu_destroy(cpu);
|
||||
@@ -1576,7 +1608,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
|
||||
}
|
||||
|
||||
atomic_mb_set(&cpu->exit_request, 0);
|
||||
qemu_tcg_wait_io_event(cpu);
|
||||
qemu_wait_io_event(cpu);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -79,7 +79,7 @@ static int qcrypto_ivgen_essiv_calculate(QCryptoIVGen *ivgen,
|
||||
uint8_t *data = g_new(uint8_t, ndata);
|
||||
|
||||
sector = cpu_to_le64(sector);
|
||||
memcpy(data, (uint8_t *)§or, ndata);
|
||||
memcpy(data, (uint8_t *)§or, MIN(sizeof(sector), ndata));
|
||||
if (sizeof(sector) < ndata) {
|
||||
memset(data + sizeof(sector), 0, ndata - sizeof(sector));
|
||||
}
|
||||
|
||||
+6
-10
@@ -207,18 +207,14 @@ static int opc_index[256];
|
||||
static void
|
||||
init_disasm (struct disassemble_info *info)
|
||||
{
|
||||
const struct s390_opcode *opcode;
|
||||
const struct s390_opcode *opcode_end;
|
||||
int i;
|
||||
|
||||
memset (opc_index, 0, sizeof (opc_index));
|
||||
opcode_end = s390_opcodes + s390_num_opcodes;
|
||||
for (opcode = s390_opcodes; opcode < opcode_end; opcode++)
|
||||
{
|
||||
opc_index[(int) opcode->opcode[0]] = opcode - s390_opcodes;
|
||||
while ((opcode < opcode_end) &&
|
||||
(opcode[1].opcode[0] == opcode->opcode[0]))
|
||||
opcode++;
|
||||
}
|
||||
|
||||
/* Reverse order, such that each opc_index ends up pointing to the
|
||||
first matching entry instead of the last. */
|
||||
for (i = s390_num_opcodes; i--; )
|
||||
opc_index[s390_opcodes[i].opcode[0]] = i;
|
||||
|
||||
#ifdef QEMU_DISABLE
|
||||
switch (info->mach)
|
||||
|
||||
@@ -510,3 +510,16 @@ default-configs/$TARGET-NAME file as input.
|
||||
This is the entrypoint used when make recurses to build a single system
|
||||
or userspace emulator target. It is merely a symlink back to the
|
||||
Makefile.target in the top level.
|
||||
|
||||
|
||||
Useful make targets
|
||||
===================
|
||||
|
||||
- help
|
||||
|
||||
Print a help message for the most common build targets.
|
||||
|
||||
- print-VAR
|
||||
|
||||
Print the value of the variable VAR. Useful for debugging the build
|
||||
system.
|
||||
|
||||
@@ -623,6 +623,13 @@ static int cpu_common_post_load(void *opaque, int version_id)
|
||||
cpu->interrupt_request &= ~0x01;
|
||||
tlb_flush(cpu);
|
||||
|
||||
/* loadvm has just updated the content of RAM, bypassing the
|
||||
* usual mechanisms that ensure we flush TBs for writes to
|
||||
* memory we've translated code from. So we must flush all TBs,
|
||||
* which will now be stale.
|
||||
*/
|
||||
tb_flush(cpu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1660,7 +1667,10 @@ static void *file_ram_alloc(RAMBlock *block,
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Called with the ramlist lock held. */
|
||||
/* Allocate space within the ram_addr_t space that governs the
|
||||
* dirty bitmaps.
|
||||
* Called with the ramlist lock held.
|
||||
*/
|
||||
static ram_addr_t find_ram_offset(ram_addr_t size)
|
||||
{
|
||||
RAMBlock *block, *next_block;
|
||||
@@ -1673,19 +1683,33 @@ static ram_addr_t find_ram_offset(ram_addr_t size)
|
||||
}
|
||||
|
||||
RAMBLOCK_FOREACH(block) {
|
||||
ram_addr_t end, next = RAM_ADDR_MAX;
|
||||
ram_addr_t candidate, next = RAM_ADDR_MAX;
|
||||
|
||||
end = block->offset + block->max_length;
|
||||
/* Align blocks to start on a 'long' in the bitmap
|
||||
* which makes the bitmap sync'ing take the fast path.
|
||||
*/
|
||||
candidate = block->offset + block->max_length;
|
||||
candidate = ROUND_UP(candidate, BITS_PER_LONG << TARGET_PAGE_BITS);
|
||||
|
||||
/* Search for the closest following block
|
||||
* and find the gap.
|
||||
*/
|
||||
RAMBLOCK_FOREACH(next_block) {
|
||||
if (next_block->offset >= end) {
|
||||
if (next_block->offset >= candidate) {
|
||||
next = MIN(next, next_block->offset);
|
||||
}
|
||||
}
|
||||
if (next - end >= size && next - end < mingap) {
|
||||
offset = end;
|
||||
mingap = next - end;
|
||||
|
||||
/* If it fits remember our place and remember the size
|
||||
* of gap, but keep going so that we might find a smaller
|
||||
* gap to fill so avoiding fragmentation.
|
||||
*/
|
||||
if (next - candidate >= size && next - candidate < mingap) {
|
||||
offset = candidate;
|
||||
mingap = next - candidate;
|
||||
}
|
||||
|
||||
trace_find_ram_offset_loop(size, candidate, offset, next, mingap);
|
||||
}
|
||||
|
||||
if (offset == RAM_ADDR_MAX) {
|
||||
@@ -1694,6 +1718,8 @@ static ram_addr_t find_ram_offset(ram_addr_t size)
|
||||
abort();
|
||||
}
|
||||
|
||||
trace_find_ram_offset(size, offset);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
if (STM_ADC_ERR_DEBUG >= lvl) { \
|
||||
qemu_log("%s: " fmt, __func__, ## args); \
|
||||
} \
|
||||
} while (0);
|
||||
} while (0)
|
||||
|
||||
#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
|
||||
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@
|
||||
fprintf(stderr, ": %s: ", __func__); \
|
||||
fprintf(stderr, ## __VA_ARGS__); \
|
||||
} \
|
||||
} while (0);
|
||||
} while (0)
|
||||
|
||||
/* Fields for FlashPartInfo->flags */
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#define DB_PRINT(...) do { \
|
||||
fprintf(stderr, ": %s: ", __func__); \
|
||||
fprintf(stderr, ## __VA_ARGS__); \
|
||||
} while (0);
|
||||
} while (0)
|
||||
#else
|
||||
#define DB_PRINT(...)
|
||||
#endif
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
if (STM_USART_ERR_DEBUG >= lvl) { \
|
||||
qemu_log("%s: " fmt, __func__, ## args); \
|
||||
} \
|
||||
} while (0);
|
||||
} while (0)
|
||||
|
||||
#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
|
||||
|
||||
|
||||
+16
-12
@@ -31,7 +31,7 @@ typedef struct Terminal3270 {
|
||||
uint8_t outv[OUTPUT_BUFFER_SIZE];
|
||||
int in_len;
|
||||
bool handshake_done;
|
||||
guint timer_tag;
|
||||
GSource *timer_src;
|
||||
} Terminal3270;
|
||||
|
||||
#define TYPE_TERMINAL_3270 "x-terminal3270"
|
||||
@@ -45,6 +45,15 @@ static int terminal_can_read(void *opaque)
|
||||
return INPUT_BUFFER_SIZE - t->in_len;
|
||||
}
|
||||
|
||||
static void terminal_timer_cancel(Terminal3270 *t)
|
||||
{
|
||||
if (t->timer_src) {
|
||||
g_source_destroy(t->timer_src);
|
||||
g_source_unref(t->timer_src);
|
||||
t->timer_src = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Protocol handshake done,
|
||||
* signal guest by an unsolicited DE irq.
|
||||
@@ -90,12 +99,9 @@ static void terminal_read(void *opaque, const uint8_t *buf, int size)
|
||||
|
||||
assert(size <= (INPUT_BUFFER_SIZE - t->in_len));
|
||||
|
||||
if (t->timer_tag) {
|
||||
g_source_remove(t->timer_tag);
|
||||
t->timer_tag = 0;
|
||||
}
|
||||
t->timer_tag = g_timeout_add_seconds(600, send_timing_mark_cb, t);
|
||||
|
||||
terminal_timer_cancel(t);
|
||||
t->timer_src = qemu_chr_timeout_add_ms(t->chr.chr, 600 * 1000,
|
||||
send_timing_mark_cb, t);
|
||||
memcpy(&t->inv[t->in_len], buf, size);
|
||||
t->in_len += size;
|
||||
if (t->in_len < 2) {
|
||||
@@ -145,10 +151,7 @@ static void chr_event(void *opaque, int event)
|
||||
/* Ensure the initial status correct, always reset them. */
|
||||
t->in_len = 0;
|
||||
t->handshake_done = false;
|
||||
if (t->timer_tag) {
|
||||
g_source_remove(t->timer_tag);
|
||||
t->timer_tag = 0;
|
||||
}
|
||||
terminal_timer_cancel(t);
|
||||
|
||||
switch (event) {
|
||||
case CHR_EVENT_OPENED:
|
||||
@@ -157,7 +160,8 @@ static void chr_event(void *opaque, int event)
|
||||
* char-socket.c. Once qemu receives the terminal-type of the
|
||||
* client, mark handshake done and trigger everything rolling again.
|
||||
*/
|
||||
t->timer_tag = g_timeout_add_seconds(600, send_timing_mark_cb, t);
|
||||
t->timer_src = qemu_chr_timeout_add_ms(t->chr.chr, 600 * 1000,
|
||||
send_timing_mark_cb, t);
|
||||
break;
|
||||
case CHR_EVENT_CLOSED:
|
||||
sch->curr_status.scsw.dstat = SCSW_DSTAT_DEVICE_END;
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@
|
||||
if (DEBUG_CG3) { \
|
||||
printf("CG3: " fmt , ## __VA_ARGS__); \
|
||||
} \
|
||||
} while (0);
|
||||
} while (0)
|
||||
|
||||
#define TYPE_CG3 "cgthree"
|
||||
#define CG3(obj) OBJECT_CHECK(CG3State, (obj), TYPE_CG3)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user