* 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)
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQEcBAABAgAGBQJaXgkRAAoJEL/70l94x66DA3EIAI8z8Y+1NAmbLqiHhrrN9Ji/
 b8EHQ8wf0pwwrHuRVKYZvKUU8yvp/CRIoVWZwfeGjRbZC+l7l+BAwdOx42Bj/dUW
 VopNzcJMu3s5SNwoYLvs01OjhciBYNXWTXBkIiErwurF0Ow7oYR7trkLwOw0veSO
 L4qFAGoIBI/7b6BZ3YRQXshhzdSQ6dvHrDness2V1c0crLG+yhvjKJ8PJ2tJyNZO
 DbsrCd7hS6e6liSUqdLj9XgRySFj9R5kgjaLjckjg1SC6kmhLN9hyke8iXgH7uvz
 WGnRPmKjKexFHVYgR0rRFlazcQclAczHuIi/OZe0HLi6trg2YKBkolMaQLQdgfk=
 =HTyS
 -----END PGP SIGNATURE-----

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:
Peter Maydell 2018-01-16 15:45:15 +00:00
commit c1d5b9add7
90 changed files with 900 additions and 415 deletions

View File

@ -8,9 +8,12 @@ SRC_PATH=.
UNCHECKED_GOALS := %clean TAGS cscope ctags dist \ UNCHECKED_GOALS := %clean TAGS cscope ctags dist \
html info pdf txt \ html info pdf txt \
help check-help \ help check-help print-% \
docker docker-% vm-test vm-build-% docker docker-% vm-test vm-build-%
print-%:
@echo '$*=$($*)'
# All following code might depend on configuration variables # All following code might depend on configuration variables
ifneq ($(wildcard config-host.mak),) ifneq ($(wildcard config-host.mak),)
# Put the all: rule here so that config-host.mak can contain dependencies. # Put the all: rule here so that config-host.mak can contain dependencies.
@ -277,7 +280,7 @@ else
DOCS= DOCS=
endif 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=$(patsubst %, %/config-devices.mak, $(TARGET_DIRS))
SUBDIR_DEVICES_MAK_DEP=$(patsubst %, %-config-devices.mak.d, $(TARGET_DIRS)) SUBDIR_DEVICES_MAK_DEP=$(patsubst %, %-config-devices.mak.d, $(TARGET_DIRS))

View File

@ -89,7 +89,7 @@ static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x)
} \ } \
goto label; \ goto label; \
} \ } \
} while (0); } while (0)
#define CHECK_DEAD_GOTO(c, stream, rerror, label) \ #define CHECK_DEAD_GOTO(c, stream, rerror, label) \
do { \ do { \
@ -107,7 +107,7 @@ static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x)
} \ } \
goto label; \ goto label; \
} \ } \
} while (0); } while (0)
static int qpa_simple_read (PAVoiceIn *p, void *data, size_t length, int *rerror) static int qpa_simple_read (PAVoiceIn *p, void *data, size_t length, int *rerror)
{ {

View File

@ -658,6 +658,8 @@ static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs,
uint64_t lba; uint64_t lba;
int64_t ret; int64_t ret;
iscsi_co_init_iscsitask(iscsilun, &iTask);
if (!is_sector_request_lun_aligned(sector_num, nb_sectors, iscsilun)) { if (!is_sector_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
@ -675,7 +677,6 @@ static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs,
lba = sector_qemu2lun(sector_num, iscsilun); lba = sector_qemu2lun(sector_num, iscsilun);
iscsi_co_init_iscsitask(iscsilun, &iTask);
qemu_mutex_lock(&iscsilun->mutex); qemu_mutex_lock(&iscsilun->mutex);
retry: retry:
if (iscsi_get_lba_status_task(iscsilun->iscsi, iscsilun->lun, if (iscsi_get_lba_status_task(iscsilun->iscsi, iscsilun->lun,

View File

@ -356,7 +356,7 @@ guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond,
} }
g_source_set_callback(src, (GSourceFunc)func, user_data, NULL); 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); g_source_unref(src);
return tag; return tag;

View File

@ -42,8 +42,8 @@ typedef struct {
/* Protected by the Chardev chr_write_lock. */ /* Protected by the Chardev chr_write_lock. */
int connected; int connected;
guint timer_tag; GSource *timer_src;
guint open_tag; GSource *open_source;
} PtyChardev; } PtyChardev;
#define PTY_CHARDEV(obj) OBJECT_CHECK(PtyChardev, (obj), TYPE_CHARDEV_PTY) #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); PtyChardev *s = PTY_CHARDEV(opaque);
qemu_mutex_lock(&chr->chr_write_lock); qemu_mutex_lock(&chr->chr_write_lock);
s->timer_tag = 0; s->timer_src = NULL;
s->open_tag = 0; g_source_unref(s->open_source);
s->open_source = NULL;
if (!s->connected) { if (!s->connected) {
/* Next poll ... */ /* Next poll ... */
pty_chr_update_read_handler_locked(chr); pty_chr_update_read_handler_locked(chr);
@ -67,25 +68,25 @@ static gboolean pty_chr_timer(gpointer opaque)
return FALSE; 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. */ /* Called with chr_write_lock held. */
static void pty_chr_rearm_timer(Chardev *chr, int ms) static void pty_chr_rearm_timer(Chardev *chr, int ms)
{ {
PtyChardev *s = PTY_CHARDEV(chr); PtyChardev *s = PTY_CHARDEV(chr);
char *name; char *name;
if (s->timer_tag) { pty_chr_timer_cancel(s);
g_source_remove(s->timer_tag); name = g_strdup_printf("pty-timer-%s", chr->label);
s->timer_tag = 0; s->timer_src = qemu_chr_timeout_add_ms(chr, ms, pty_chr_timer, chr);
} g_source_set_name(s->timer_src, name);
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);
g_free(name); g_free(name);
} }
@ -183,7 +184,7 @@ static gboolean qemu_chr_be_generic_open_func(gpointer opaque)
Chardev *chr = CHARDEV(opaque); Chardev *chr = CHARDEV(opaque);
PtyChardev *s = PTY_CHARDEV(opaque); PtyChardev *s = PTY_CHARDEV(opaque);
s->open_tag = 0; s->open_source = NULL;
qemu_chr_be_event(chr, CHR_EVENT_OPENED); qemu_chr_be_event(chr, CHR_EVENT_OPENED);
return FALSE; return FALSE;
} }
@ -194,9 +195,10 @@ static void pty_chr_state(Chardev *chr, int connected)
PtyChardev *s = PTY_CHARDEV(chr); PtyChardev *s = PTY_CHARDEV(chr);
if (!connected) { if (!connected) {
if (s->open_tag) { if (s->open_source) {
g_source_remove(s->open_tag); g_source_destroy(s->open_source);
s->open_tag = 0; g_source_unref(s->open_source);
s->open_source = NULL;
} }
remove_fd_in_watch(chr); remove_fd_in_watch(chr);
s->connected = 0; s->connected = 0;
@ -205,14 +207,15 @@ static void pty_chr_state(Chardev *chr, int connected)
* the virtual device linked to our pty. */ * the virtual device linked to our pty. */
pty_chr_rearm_timer(chr, 1000); pty_chr_rearm_timer(chr, 1000);
} else { } else {
if (s->timer_tag) { pty_chr_timer_cancel(s);
g_source_remove(s->timer_tag);
s->timer_tag = 0;
}
if (!s->connected) { 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->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) { if (!chr->gsource) {
chr->gsource = io_add_watch_poll(chr, s->ioc, 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); qemu_mutex_lock(&chr->chr_write_lock);
pty_chr_state(chr, 0); pty_chr_state(chr, 0);
object_unref(OBJECT(s->ioc)); object_unref(OBJECT(s->ioc));
if (s->timer_tag) { pty_chr_timer_cancel(s);
g_source_remove(s->timer_tag);
s->timer_tag = 0;
}
qemu_mutex_unlock(&chr->chr_write_lock); qemu_mutex_unlock(&chr->chr_write_lock);
qemu_chr_be_event(chr, CHR_EVENT_CLOSED); 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); name = g_strdup_printf("chardev-pty-%s", chr->label);
qio_channel_set_name(QIO_CHANNEL(s->ioc), name); qio_channel_set_name(QIO_CHANNEL(s->ioc), name);
g_free(name); g_free(name);
s->timer_tag = 0; s->timer_src = NULL;
*be_opened = false; *be_opened = false;
} }

View File

@ -64,69 +64,74 @@ static void tty_serial_init(int fd, int speed,
#endif #endif
tcgetattr(fd, &tty); 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; speed = speed * 10 / 11;
do { check_speed(50);
check_speed(50); check_speed(75);
check_speed(75); check_speed(110);
check_speed(110); check_speed(134);
check_speed(134); check_speed(150);
check_speed(150); check_speed(200);
check_speed(200); check_speed(300);
check_speed(300); check_speed(600);
check_speed(600); check_speed(1200);
check_speed(1200); check_speed(1800);
check_speed(1800); check_speed(2400);
check_speed(2400); check_speed(4800);
check_speed(4800); check_speed(9600);
check_speed(9600); check_speed(19200);
check_speed(19200); check_speed(38400);
check_speed(38400); /* Non-Posix values follow. They may be unsupported on some systems. */
/* Non-Posix values follow. They may be unsupported on some systems. */ check_speed(57600);
check_speed(57600); check_speed(115200);
check_speed(115200);
#ifdef B230400 #ifdef B230400
check_speed(230400); check_speed(230400);
#endif #endif
#ifdef B460800 #ifdef B460800
check_speed(460800); check_speed(460800);
#endif #endif
#ifdef B500000 #ifdef B500000
check_speed(500000); check_speed(500000);
#endif #endif
#ifdef B576000 #ifdef B576000
check_speed(576000); check_speed(576000);
#endif #endif
#ifdef B921600 #ifdef B921600
check_speed(921600); check_speed(921600);
#endif #endif
#ifdef B1000000 #ifdef B1000000
check_speed(1000000); check_speed(1000000);
#endif #endif
#ifdef B1152000 #ifdef B1152000
check_speed(1152000); check_speed(1152000);
#endif #endif
#ifdef B1500000 #ifdef B1500000
check_speed(1500000); check_speed(1500000);
#endif #endif
#ifdef B2000000 #ifdef B2000000
check_speed(2000000); check_speed(2000000);
#endif #endif
#ifdef B2500000 #ifdef B2500000
check_speed(2500000); check_speed(2500000);
#endif #endif
#ifdef B3000000 #ifdef B3000000
check_speed(3000000); check_speed(3000000);
#endif #endif
#ifdef B3500000 #ifdef B3500000
check_speed(3500000); check_speed(3500000);
#endif #endif
#ifdef B4000000 #ifdef B4000000
check_speed(4000000); check_speed(4000000);
#endif #endif
spd = B115200; spd = B115200;
} while (0);
#undef check_speed
done:
cfsetispeed(&tty, spd); cfsetispeed(&tty, spd);
cfsetospeed(&tty, spd); cfsetospeed(&tty, spd);

View File

@ -57,7 +57,7 @@ typedef struct {
bool is_telnet; bool is_telnet;
bool is_tn3270; bool is_tn3270;
guint reconnect_timer; GSource *reconnect_timer;
int64_t reconnect_time; int64_t reconnect_time;
bool connect_err_reported; bool connect_err_reported;
} SocketChardev; } SocketChardev;
@ -67,16 +67,27 @@ typedef struct {
static gboolean socket_reconnect_timeout(gpointer opaque); 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) static void qemu_chr_socket_restart_timer(Chardev *chr)
{ {
SocketChardev *s = SOCKET_CHARDEV(chr); SocketChardev *s = SOCKET_CHARDEV(chr);
char *name; char *name;
assert(s->connected == 0); 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); 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); g_free(name);
} }
@ -781,11 +792,7 @@ static void char_socket_finalize(Object *obj)
SocketChardev *s = SOCKET_CHARDEV(obj); SocketChardev *s = SOCKET_CHARDEV(obj);
tcp_chr_free_connection(chr); tcp_chr_free_connection(chr);
tcp_chr_reconn_timer_cancel(s);
if (s->reconnect_timer) {
g_source_remove(s->reconnect_timer);
s->reconnect_timer = 0;
}
qapi_free_SocketAddress(s->addr); qapi_free_SocketAddress(s->addr);
if (s->listener) { if (s->listener) {
qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL); 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); SocketChardev *s = SOCKET_CHARDEV(opaque);
QIOChannelSocket *sioc; QIOChannelSocket *sioc;
s->reconnect_timer = 0; g_source_unref(s->reconnect_timer);
s->reconnect_timer = NULL;
if (chr->be_open) { if (chr->be_open) {
return false; return false;

View File

@ -1084,6 +1084,24 @@ void qmp_chardev_send_break(const char *id, Error **errp)
qemu_chr_be_event(chr, CHR_EVENT_BREAK); 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) void qemu_chr_cleanup(void)
{ {
object_unparent(get_chardevs_root()); object_unparent(get_chardevs_root());

16
configure vendored
View File

@ -3464,6 +3464,7 @@ else
done done
if test "$found" = "no"; then if test "$found" = "no"; then
LIBS="$pthread_lib $LIBS" LIBS="$pthread_lib $LIBS"
libs_qga="$pthread_lib $libs_qga"
fi fi
PTHREAD_LIB="$pthread_lib" PTHREAD_LIB="$pthread_lib"
break break
@ -5193,8 +5194,19 @@ if test "$gcov" = "yes" ; then
LDFLAGS="-fprofile-arcs -ftest-coverage $LDFLAGS" LDFLAGS="-fprofile-arcs -ftest-coverage $LDFLAGS"
elif test "$fortify_source" = "yes" ; then elif test "$fortify_source" = "yes" ; then
CFLAGS="-O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 $CFLAGS" CFLAGS="-O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 $CFLAGS"
elif test "$debug" = "no"; then elif test "$debug" = "yes"; then
CFLAGS="-O2 $CFLAGS" 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 fi
########################################## ##########################################

134
cpus.c
View File

@ -120,16 +120,11 @@ static bool all_cpu_threads_idle(void)
/* Protected by TimersState seqlock */ /* Protected by TimersState seqlock */
static bool icount_sleep = true; static bool icount_sleep = true;
static int64_t vm_clock_warp_start = -1;
/* Conversion factor from emulated instructions to virtual clock ticks. */ /* Conversion factor from emulated instructions to virtual clock ticks. */
static int icount_time_shift; static int icount_time_shift;
/* Arbitrarily pick 1MIPS as the minimum allowable speed. */ /* Arbitrarily pick 1MIPS as the minimum allowable speed. */
#define MAX_ICOUNT_SHIFT 10 #define MAX_ICOUNT_SHIFT 10
static QEMUTimer *icount_rt_timer;
static QEMUTimer *icount_vm_timer;
static QEMUTimer *icount_warp_timer;
typedef struct TimersState { typedef struct TimersState {
/* Protected by BQL. */ /* Protected by BQL. */
int64_t cpu_ticks_prev; int64_t cpu_ticks_prev;
@ -147,6 +142,11 @@ typedef struct TimersState {
int64_t qemu_icount_bias; int64_t qemu_icount_bias;
/* Only written by TCG thread */ /* Only written by TCG thread */
int64_t qemu_icount; 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; } TimersState;
static TimersState timers_state; static TimersState timers_state;
@ -432,14 +432,14 @@ static void icount_adjust(void)
static void icount_adjust_rt(void *opaque) 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); qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) + 1000);
icount_adjust(); icount_adjust();
} }
static void icount_adjust_vm(void *opaque) 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) + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
NANOSECONDS_PER_SECOND / 10); NANOSECONDS_PER_SECOND / 10);
icount_adjust(); icount_adjust();
@ -460,7 +460,7 @@ static void icount_warp_rt(void)
*/ */
do { do {
seq = seqlock_read_begin(&timers_state.vm_clock_seqlock); 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)); } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, seq));
if (warp_start == -1) { if (warp_start == -1) {
@ -473,7 +473,7 @@ static void icount_warp_rt(void)
cpu_get_clock_locked()); cpu_get_clock_locked());
int64_t warp_delta; int64_t warp_delta;
warp_delta = clock - vm_clock_warp_start; warp_delta = clock - timers_state.vm_clock_warp_start;
if (use_icount == 2) { if (use_icount == 2) {
/* /*
* In adaptive mode, do not let QEMU_CLOCK_VIRTUAL run too * 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; 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); seqlock_write_end(&timers_state.vm_clock_seqlock);
if (qemu_clock_expired(QEMU_CLOCK_VIRTUAL)) { if (qemu_clock_expired(QEMU_CLOCK_VIRTUAL)) {
@ -594,11 +594,13 @@ void qemu_start_warp_timer(void)
* every 100ms. * every 100ms.
*/ */
seqlock_write_begin(&timers_state.vm_clock_seqlock); seqlock_write_begin(&timers_state.vm_clock_seqlock);
if (vm_clock_warp_start == -1 || vm_clock_warp_start > clock) { if (timers_state.vm_clock_warp_start == -1
vm_clock_warp_start = clock; || timers_state.vm_clock_warp_start > clock) {
timers_state.vm_clock_warp_start = clock;
} }
seqlock_write_end(&timers_state.vm_clock_seqlock); 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) { } else if (deadline == 0) {
qemu_clock_notify(QEMU_CLOCK_VIRTUAL); qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
@ -623,7 +625,7 @@ static void qemu_account_warp_timer(void)
return; return;
} }
timer_del(icount_warp_timer); timer_del(timers_state.icount_warp_timer);
icount_warp_rt(); icount_warp_rt();
} }
@ -632,6 +634,45 @@ static bool icount_state_needed(void *opaque)
return use_icount; 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. * 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_bias, TimersState),
VMSTATE_INT64(qemu_icount, TimersState), VMSTATE_INT64(qemu_icount, TimersState),
VMSTATE_END_OF_LIST() 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); icount_sleep = qemu_opt_get_bool(opts, "sleep", true);
if (icount_sleep) { 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); 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. the virtual time trigger catches emulated time passing too fast.
Realtime triggers occur even when idle, so use them less frequently Realtime triggers occur even when idle, so use them less frequently
than VM triggers. */ 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); 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); 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); icount_adjust_vm, NULL);
timer_mod(icount_vm_timer, timer_mod(timers_state.icount_vm_timer,
qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
NANOSECONDS_PER_SECOND / 10); NANOSECONDS_PER_SECOND / 10);
} }
@ -862,7 +909,8 @@ static void kick_tcg_thread(void *opaque)
static void start_tcg_kick_timer(void) 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, tcg_kick_vcpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
kick_tcg_thread, NULL); kick_tcg_thread, NULL);
timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick()); 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) static void stop_tcg_kick_timer(void)
{ {
assert(!mttcg_enabled);
if (tcg_kick_vcpu_timer) { if (tcg_kick_vcpu_timer) {
timer_del(tcg_kick_vcpu_timer); timer_del(tcg_kick_vcpu_timer);
tcg_kick_vcpu_timer = NULL; tcg_kick_vcpu_timer = NULL;
@ -1090,18 +1139,9 @@ static void qemu_wait_io_event_common(CPUState *cpu)
process_queued_cpu_work(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) { while (all_cpu_threads_idle()) {
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)) {
stop_tcg_kick_timer(); stop_tcg_kick_timer();
qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex); 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); 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)) { while (cpu_thread_is_idle(cpu)) {
qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex); qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex);
} }
qemu_wait_io_event_common(cpu); #ifdef _WIN32
} /* Eat dummy APC queued by qemu_cpu_kick_thread. */
if (!tcg_enabled()) {
static void qemu_hvf_wait_io_event(CPUState *cpu) SleepEx(0, TRUE);
{
while (cpu_thread_is_idle(cpu)) {
qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex);
} }
#endif
qemu_wait_io_event_common(cpu); qemu_wait_io_event_common(cpu);
} }
@ -1160,7 +1198,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
cpu_handle_guest_debug(cpu); cpu_handle_guest_debug(cpu);
} }
} }
qemu_kvm_wait_io_event(cpu); qemu_wait_io_event(cpu);
} while (!cpu->unplug || cpu_can_run(cpu)); } while (!cpu->unplug || cpu_can_run(cpu));
qemu_kvm_destroy_vcpu(cpu); qemu_kvm_destroy_vcpu(cpu);
@ -1206,7 +1244,7 @@ static void *qemu_dummy_cpu_thread_fn(void *arg)
exit(1); exit(1);
} }
qemu_mutex_lock_iothread(); qemu_mutex_lock_iothread();
qemu_wait_io_event_common(cpu); qemu_wait_io_event(cpu);
} }
return NULL; return NULL;
@ -1423,7 +1461,7 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg)
atomic_mb_set(&cpu->exit_request, 0); 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(); deal_with_unplugged_cpus();
} }
@ -1454,13 +1492,7 @@ static void *qemu_hax_cpu_thread_fn(void *arg)
} }
} }
while (cpu_thread_is_idle(cpu)) { qemu_wait_io_event(cpu);
qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex);
}
#ifdef _WIN32
SleepEx(0, TRUE);
#endif
qemu_wait_io_event_common(cpu);
} }
return NULL; return NULL;
} }
@ -1497,7 +1529,7 @@ static void *qemu_hvf_cpu_thread_fn(void *arg)
cpu_handle_guest_debug(cpu); cpu_handle_guest_debug(cpu);
} }
} }
qemu_hvf_wait_io_event(cpu); qemu_wait_io_event(cpu);
} while (!cpu->unplug || cpu_can_run(cpu)); } while (!cpu->unplug || cpu_can_run(cpu));
hvf_vcpu_destroy(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); atomic_mb_set(&cpu->exit_request, 0);
qemu_tcg_wait_io_event(cpu); qemu_wait_io_event(cpu);
} }
return NULL; return NULL;

View File

@ -79,7 +79,7 @@ static int qcrypto_ivgen_essiv_calculate(QCryptoIVGen *ivgen,
uint8_t *data = g_new(uint8_t, ndata); uint8_t *data = g_new(uint8_t, ndata);
sector = cpu_to_le64(sector); sector = cpu_to_le64(sector);
memcpy(data, (uint8_t *)&sector, ndata); memcpy(data, (uint8_t *)&sector, MIN(sizeof(sector), ndata));
if (sizeof(sector) < ndata) { if (sizeof(sector) < ndata) {
memset(data + sizeof(sector), 0, ndata - sizeof(sector)); memset(data + sizeof(sector), 0, ndata - sizeof(sector));
} }

View File

@ -207,18 +207,14 @@ static int opc_index[256];
static void static void
init_disasm (struct disassemble_info *info) init_disasm (struct disassemble_info *info)
{ {
const struct s390_opcode *opcode; int i;
const struct s390_opcode *opcode_end;
memset (opc_index, 0, sizeof (opc_index)); memset (opc_index, 0, sizeof (opc_index));
opcode_end = s390_opcodes + s390_num_opcodes;
for (opcode = s390_opcodes; opcode < opcode_end; opcode++) /* Reverse order, such that each opc_index ends up pointing to the
{ first matching entry instead of the last. */
opc_index[(int) opcode->opcode[0]] = opcode - s390_opcodes; for (i = s390_num_opcodes; i--; )
while ((opcode < opcode_end) && opc_index[s390_opcodes[i].opcode[0]] = i;
(opcode[1].opcode[0] == opcode->opcode[0]))
opcode++;
}
#ifdef QEMU_DISABLE #ifdef QEMU_DISABLE
switch (info->mach) switch (info->mach)

View File

@ -510,3 +510,16 @@ default-configs/$TARGET-NAME file as input.
This is the entrypoint used when make recurses to build a single system 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 or userspace emulator target. It is merely a symlink back to the
Makefile.target in the top level. 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.

40
exec.c
View File

@ -623,6 +623,13 @@ static int cpu_common_post_load(void *opaque, int version_id)
cpu->interrupt_request &= ~0x01; cpu->interrupt_request &= ~0x01;
tlb_flush(cpu); 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; return 0;
} }
@ -1660,7 +1667,10 @@ static void *file_ram_alloc(RAMBlock *block,
} }
#endif #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) static ram_addr_t find_ram_offset(ram_addr_t size)
{ {
RAMBlock *block, *next_block; RAMBlock *block, *next_block;
@ -1673,19 +1683,33 @@ static ram_addr_t find_ram_offset(ram_addr_t size)
} }
RAMBLOCK_FOREACH(block) { 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) { RAMBLOCK_FOREACH(next_block) {
if (next_block->offset >= end) { if (next_block->offset >= candidate) {
next = MIN(next, next_block->offset); next = MIN(next, next_block->offset);
} }
} }
if (next - end >= size && next - end < mingap) {
offset = end; /* If it fits remember our place and remember the size
mingap = next - end; * 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) { if (offset == RAM_ADDR_MAX) {
@ -1694,6 +1718,8 @@ static ram_addr_t find_ram_offset(ram_addr_t size)
abort(); abort();
} }
trace_find_ram_offset(size, offset);
return offset; return offset;
} }

View File

@ -37,7 +37,7 @@
if (STM_ADC_ERR_DEBUG >= lvl) { \ if (STM_ADC_ERR_DEBUG >= lvl) { \
qemu_log("%s: " fmt, __func__, ## args); \ qemu_log("%s: " fmt, __func__, ## args); \
} \ } \
} while (0); } while (0)
#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args) #define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)

View File

@ -40,7 +40,7 @@
fprintf(stderr, ": %s: ", __func__); \ fprintf(stderr, ": %s: ", __func__); \
fprintf(stderr, ## __VA_ARGS__); \ fprintf(stderr, ## __VA_ARGS__); \
} \ } \
} while (0); } while (0)
/* Fields for FlashPartInfo->flags */ /* Fields for FlashPartInfo->flags */

View File

@ -33,7 +33,7 @@
#define DB_PRINT(...) do { \ #define DB_PRINT(...) do { \
fprintf(stderr, ": %s: ", __func__); \ fprintf(stderr, ": %s: ", __func__); \
fprintf(stderr, ## __VA_ARGS__); \ fprintf(stderr, ## __VA_ARGS__); \
} while (0); } while (0)
#else #else
#define DB_PRINT(...) #define DB_PRINT(...)
#endif #endif

View File

@ -34,7 +34,7 @@
if (STM_USART_ERR_DEBUG >= lvl) { \ if (STM_USART_ERR_DEBUG >= lvl) { \
qemu_log("%s: " fmt, __func__, ## args); \ qemu_log("%s: " fmt, __func__, ## args); \
} \ } \
} while (0); } while (0)
#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args) #define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)

View File

@ -31,7 +31,7 @@ typedef struct Terminal3270 {
uint8_t outv[OUTPUT_BUFFER_SIZE]; uint8_t outv[OUTPUT_BUFFER_SIZE];
int in_len; int in_len;
bool handshake_done; bool handshake_done;
guint timer_tag; GSource *timer_src;
} Terminal3270; } Terminal3270;
#define TYPE_TERMINAL_3270 "x-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; 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, * Protocol handshake done,
* signal guest by an unsolicited DE irq. * 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)); assert(size <= (INPUT_BUFFER_SIZE - t->in_len));
if (t->timer_tag) { terminal_timer_cancel(t);
g_source_remove(t->timer_tag); t->timer_src = qemu_chr_timeout_add_ms(t->chr.chr, 600 * 1000,
t->timer_tag = 0; send_timing_mark_cb, t);
}
t->timer_tag = g_timeout_add_seconds(600, send_timing_mark_cb, t);
memcpy(&t->inv[t->in_len], buf, size); memcpy(&t->inv[t->in_len], buf, size);
t->in_len += size; t->in_len += size;
if (t->in_len < 2) { 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. */ /* Ensure the initial status correct, always reset them. */
t->in_len = 0; t->in_len = 0;
t->handshake_done = false; t->handshake_done = false;
if (t->timer_tag) { terminal_timer_cancel(t);
g_source_remove(t->timer_tag);
t->timer_tag = 0;
}
switch (event) { switch (event) {
case CHR_EVENT_OPENED: 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 * char-socket.c. Once qemu receives the terminal-type of the
* client, mark handshake done and trigger everything rolling again. * 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; break;
case CHR_EVENT_CLOSED: case CHR_EVENT_CLOSED:
sch->curr_status.scsw.dstat = SCSW_DSTAT_DEVICE_END; sch->curr_status.scsw.dstat = SCSW_DSTAT_DEVICE_END;

View File

@ -63,7 +63,7 @@
if (DEBUG_CG3) { \ if (DEBUG_CG3) { \
printf("CG3: " fmt , ## __VA_ARGS__); \ printf("CG3: " fmt , ## __VA_ARGS__); \
} \ } \
} while (0); } while (0)
#define TYPE_CG3 "cgthree" #define TYPE_CG3 "cgthree"
#define CG3(obj) OBJECT_CHECK(CG3State, (obj), TYPE_CG3) #define CG3(obj) OBJECT_CHECK(CG3State, (obj), TYPE_CG3)

View File

@ -39,7 +39,7 @@
if (DEBUG_DPCD) { \ if (DEBUG_DPCD) { \
qemu_log("dpcd: " fmt, ## __VA_ARGS__); \ qemu_log("dpcd: " fmt, ## __VA_ARGS__); \
} \ } \
} while (0); } while (0)
#define DPCD_READABLE_AREA 0x600 #define DPCD_READABLE_AREA 0x600

View File

@ -34,7 +34,7 @@
if (DEBUG_DP) { \ if (DEBUG_DP) { \
qemu_log("xlnx_dp: " fmt , ## __VA_ARGS__); \ qemu_log("xlnx_dp: " fmt , ## __VA_ARGS__); \
} \ } \
} while (0); } while (0)
/* /*
* Register offset for DP. * Register offset for DP.

View File

@ -29,7 +29,7 @@
if (PL330_ERR_DEBUG >= lvl) {\ if (PL330_ERR_DEBUG >= lvl) {\
fprintf(stderr, "PL330: %s:" fmt, __func__, ## args);\ fprintf(stderr, "PL330: %s:" fmt, __func__, ## args);\
} \ } \
} while (0); } while (0)
#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args) #define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)

View File

@ -43,7 +43,7 @@
if (XLNX_ZYNQ_DEVCFG_ERR_DEBUG) { \ if (XLNX_ZYNQ_DEVCFG_ERR_DEBUG) { \
qemu_log("%s: " fmt, __func__, ## args); \ qemu_log("%s: " fmt, __func__, ## args); \
} \ } \
} while (0); } while (0)
REG32(CTRL, 0x00) REG32(CTRL, 0x00)
FIELD(CTRL, FORCE_RST, 31, 1) /* Not supported, wr ignored */ FIELD(CTRL, FORCE_RST, 31, 1) /* Not supported, wr ignored */

View File

@ -34,7 +34,7 @@
if (DEBUG_DPDMA) { \ if (DEBUG_DPDMA) { \
qemu_log("xlnx_dpdma: " fmt , ## __VA_ARGS__); \ qemu_log("xlnx_dpdma: " fmt , ## __VA_ARGS__); \
} \ } \
} while (0); } while (0)
/* /*
* Registers offset for DPDMA. * Registers offset for DPDMA.

View File

@ -30,7 +30,7 @@
if (DEBUG_I2CDDC) { \ if (DEBUG_I2CDDC) { \
qemu_log("i2c-ddc: " fmt , ## __VA_ARGS__); \ qemu_log("i2c-ddc: " fmt , ## __VA_ARGS__); \
} \ } \
} while (0); } while (0)
/* Structure defining a monitor's characteristics in a /* Structure defining a monitor's characteristics in a
* readable format: this should be passed to build_edid_blob() * readable format: this should be passed to build_edid_blob()

View File

@ -1695,9 +1695,14 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev,
align = memory_region_get_alignment(mr); align = memory_region_get_alignment(mr);
} }
if (!pcms->acpi_dev) { /*
* When -no-acpi is used with Q35 machine type, no ACPI is built,
* but pcms->acpi_dev is still created. Check !acpi_enabled in
* addition to cover this case.
*/
if (!pcms->acpi_dev || !acpi_enabled) {
error_setg(&local_err, error_setg(&local_err,
"memory hotplug is not enabled: missing acpi device"); "memory hotplug is not enabled: missing acpi device or acpi disabled");
goto out; goto out;
} }
@ -1729,9 +1734,14 @@ static void pc_dimm_unplug_request(HotplugHandler *hotplug_dev,
Error *local_err = NULL; Error *local_err = NULL;
PCMachineState *pcms = PC_MACHINE(hotplug_dev); PCMachineState *pcms = PC_MACHINE(hotplug_dev);
if (!pcms->acpi_dev) { /*
* When -no-acpi is used with Q35 machine type, no ACPI is built,
* but pcms->acpi_dev is still created. Check !acpi_enabled in
* addition to cover this case.
*/
if (!pcms->acpi_dev || !acpi_enabled) {
error_setg(&local_err, error_setg(&local_err,
"memory hotplug is not enabled: missing acpi device"); "memory hotplug is not enabled: missing acpi device or acpi disabled");
goto out; goto out;
} }

View File

@ -40,7 +40,7 @@
if (DEBUG_AUX) { \ if (DEBUG_AUX) { \
qemu_log("aux: " fmt , ## __VA_ARGS__); \ qemu_log("aux: " fmt , ## __VA_ARGS__); \
} \ } \
} while (0); } while (0)
#define TYPE_AUXTOI2C "aux-to-i2c-bridge" #define TYPE_AUXTOI2C "aux-to-i2c-bridge"
#define AUXTOI2C(obj) OBJECT_CHECK(AUXTOI2CState, (obj), TYPE_AUXTOI2C) #define AUXTOI2C(obj) OBJECT_CHECK(AUXTOI2CState, (obj), TYPE_AUXTOI2C)

View File

@ -52,7 +52,7 @@
if (DEBUG_DBDMA) { \ if (DEBUG_DBDMA) { \
printf("DBDMA: " fmt , ## __VA_ARGS__); \ printf("DBDMA: " fmt , ## __VA_ARGS__); \
} \ } \
} while (0); } while (0)
#define DBDMA_DPRINTFCH(ch, fmt, ...) do { \ #define DBDMA_DPRINTFCH(ch, fmt, ...) do { \
if (DEBUG_DBDMA) { \ if (DEBUG_DBDMA) { \
@ -60,7 +60,7 @@
printf("DBDMA[%02x]: " fmt , (ch)->channel, ## __VA_ARGS__); \ printf("DBDMA[%02x]: " fmt , (ch)->channel, ## __VA_ARGS__); \
} \ } \
} \ } \
} while (0); } while (0)
/* /*
*/ */

View File

@ -39,7 +39,7 @@ static uint64_t mmio_interface_counter;
if (DEBUG_MMIO_INTERFACE) { \ if (DEBUG_MMIO_INTERFACE) { \
qemu_log("mmio_interface: 0x%" PRIX64 ": " fmt, s->id, ## __VA_ARGS__);\ qemu_log("mmio_interface: 0x%" PRIX64 ": " fmt, s->id, ## __VA_ARGS__);\
} \ } \
} while (0); } while (0)
static void mmio_interface_init(Object *obj) static void mmio_interface_init(Object *obj)
{ {

View File

@ -34,7 +34,7 @@
if (STM_SYSCFG_ERR_DEBUG >= lvl) { \ if (STM_SYSCFG_ERR_DEBUG >= lvl) { \
qemu_log("%s: " fmt, __func__, ## args); \ qemu_log("%s: " fmt, __func__, ## args); \
} \ } \
} while (0); } while (0)
#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args) #define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)

View File

@ -30,7 +30,7 @@
fprintf(stderr, ": %s: ", __func__); \ fprintf(stderr, ": %s: ", __func__); \
fprintf(stderr, ## __VA_ARGS__); \ fprintf(stderr, ## __VA_ARGS__); \
} \ } \
} while (0); } while (0)
#define XILINX_LOCK_KEY 0x767b #define XILINX_LOCK_KEY 0x767b
#define XILINX_UNLOCK_KEY 0xdf0d #define XILINX_UNLOCK_KEY 0xdf0d

View File

@ -34,7 +34,7 @@
#define DB_PRINT(...) do { \ #define DB_PRINT(...) do { \
fprintf(stderr, ": %s: ", __func__); \ fprintf(stderr, ": %s: ", __func__); \
fprintf(stderr, ## __VA_ARGS__); \ fprintf(stderr, ## __VA_ARGS__); \
} while (0); } while (0)
#else #else
#define DB_PRINT(...) #define DB_PRINT(...)
#endif #endif

View File

@ -456,32 +456,32 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd,
#define CHECK_RMD(ADDR,RES) do { \ #define CHECK_RMD(ADDR,RES) do { \
switch (BCR_SWSTYLE(s)) { \ switch (BCR_SWSTYLE(s)) { \
case 0x00: \ case 0x00: \
do { \ { \
uint16_t rda[4]; \ uint16_t rda[4]; \
s->phys_mem_read(s->dma_opaque, (ADDR), \ s->phys_mem_read(s->dma_opaque, (ADDR), \
(void *)&rda[0], sizeof(rda), 0); \ (void *)&rda[0], sizeof(rda), 0); \
(RES) |= (rda[2] & 0xf000)!=0xf000; \ (RES) |= (rda[2] & 0xf000)!=0xf000; \
(RES) |= (rda[3] & 0xf000)!=0x0000; \ (RES) |= (rda[3] & 0xf000)!=0x0000; \
} while (0); \ } \
break; \ break; \
case 0x01: \ case 0x01: \
case 0x02: \ case 0x02: \
do { \ { \
uint32_t rda[4]; \ uint32_t rda[4]; \
s->phys_mem_read(s->dma_opaque, (ADDR), \ s->phys_mem_read(s->dma_opaque, (ADDR), \
(void *)&rda[0], sizeof(rda), 0); \ (void *)&rda[0], sizeof(rda), 0); \
(RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \ (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
(RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \ (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \
} while (0); \ } \
break; \ break; \
case 0x03: \ case 0x03: \
do { \ { \
uint32_t rda[4]; \ uint32_t rda[4]; \
s->phys_mem_read(s->dma_opaque, (ADDR), \ s->phys_mem_read(s->dma_opaque, (ADDR), \
(void *)&rda[0], sizeof(rda), 0); \ (void *)&rda[0], sizeof(rda), 0); \
(RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \ (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \
(RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \ (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
} while (0); \ } \
break; \ break; \
} \ } \
} while (0) } while (0)
@ -489,22 +489,22 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd,
#define CHECK_TMD(ADDR,RES) do { \ #define CHECK_TMD(ADDR,RES) do { \
switch (BCR_SWSTYLE(s)) { \ switch (BCR_SWSTYLE(s)) { \
case 0x00: \ case 0x00: \
do { \ { \
uint16_t xda[4]; \ uint16_t xda[4]; \
s->phys_mem_read(s->dma_opaque, (ADDR), \ s->phys_mem_read(s->dma_opaque, (ADDR), \
(void *)&xda[0], sizeof(xda), 0); \ (void *)&xda[0], sizeof(xda), 0); \
(RES) |= (xda[2] & 0xf000)!=0xf000; \ (RES) |= (xda[2] & 0xf000)!=0xf000; \
} while (0); \ } \
break; \ break; \
case 0x01: \ case 0x01: \
case 0x02: \ case 0x02: \
case 0x03: \ case 0x03: \
do { \ { \
uint32_t xda[4]; \ uint32_t xda[4]; \
s->phys_mem_read(s->dma_opaque, (ADDR), \ s->phys_mem_read(s->dma_opaque, (ADDR), \
(void *)&xda[0], sizeof(xda), 0); \ (void *)&xda[0], sizeof(xda), 0); \
(RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \ (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \
} while (0); \ } \
break; \ break; \
} \ } \
} while (0) } while (0)

View File

@ -80,7 +80,7 @@ static int nvram_post_load(void *opaque, int version_id)
} }
/* Write back nvram contents */ /* Write back nvram contents */
s->file = fopen(s->filename, "wb"); s->file = s->filename ? fopen(s->filename, "wb") : NULL;
if (s->file) { if (s->file) {
/* Write back contents, as 'wb' mode cleaned the file */ /* Write back contents, as 'wb' mode cleaned the file */
if (fwrite(s->contents, s->chip_size, 1, s->file) != 1) { if (fwrite(s->contents, s->chip_size, 1, s->file) != 1) {
@ -126,7 +126,7 @@ static int nvram_sysbus_initfn(SysBusDevice *dev)
sysbus_init_mmio(dev, &s->iomem); sysbus_init_mmio(dev, &s->iomem);
/* Read current file */ /* Read current file */
file = fopen(s->filename, "rb"); file = s->filename ? fopen(s->filename, "rb") : NULL;
if (file) { if (file) {
/* Read nvram contents */ /* Read nvram contents */
if (fread(s->contents, s->chip_size, 1, file) != 1) { if (fread(s->contents, s->chip_size, 1, file) != 1) {

View File

@ -1755,6 +1755,7 @@ static void scsi_write_same_complete(void *opaque, int ret)
data->sector << BDRV_SECTOR_BITS, data->sector << BDRV_SECTOR_BITS,
&data->qiov, 0, &data->qiov, 0,
scsi_write_same_complete, data); scsi_write_same_complete, data);
aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
return; return;
} }

View File

@ -482,6 +482,7 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp)
int rc; int rc;
int sg_version; int sg_version;
struct sg_scsi_id scsiid; struct sg_scsi_id scsiid;
Error *local_err = NULL;
if (!s->conf.blk) { if (!s->conf.blk) {
error_setg(errp, "drive property not set"); error_setg(errp, "drive property not set");
@ -515,6 +516,13 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp)
error_setg(errp, "SG_GET_SCSI_ID ioctl failed"); error_setg(errp, "SG_GET_SCSI_ID ioctl failed");
return; return;
} }
blkconf_apply_backend_options(&s->conf,
blk_is_read_only(s->conf.blk),
true, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
/* define device state */ /* define device state */
s->type = scsiid.scsi_type; s->type = scsiid.scsi_type;
@ -565,6 +573,7 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
static Property scsi_generic_properties[] = { static Property scsi_generic_properties[] = {
DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.blk), DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.blk),
DEFINE_PROP_BOOL("share-rw", SCSIDevice, conf.share_rw, false),
DEFINE_PROP_END_OF_LIST(), DEFINE_PROP_END_OF_LIST(),
}; };

View File

@ -35,7 +35,7 @@
if (MSS_SPI_ERR_DEBUG >= lvl) { \ if (MSS_SPI_ERR_DEBUG >= lvl) { \
qemu_log("%s: " fmt "\n", __func__, ## args); \ qemu_log("%s: " fmt "\n", __func__, ## args); \
} \ } \
} while (0); } while (0)
#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args) #define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)

View File

@ -35,7 +35,7 @@
if (STM_SPI_ERR_DEBUG >= lvl) { \ if (STM_SPI_ERR_DEBUG >= lvl) { \
qemu_log("%s: " fmt, __func__, ## args); \ qemu_log("%s: " fmt, __func__, ## args); \
} \ } \
} while (0); } while (0)
#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args) #define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)

View File

@ -36,7 +36,7 @@
#define DB_PRINT(...) do { \ #define DB_PRINT(...) do { \
fprintf(stderr, ": %s: ", __func__); \ fprintf(stderr, ": %s: ", __func__); \
fprintf(stderr, ## __VA_ARGS__); \ fprintf(stderr, ## __VA_ARGS__); \
} while (0); } while (0)
#else #else
#define DB_PRINT(...) #define DB_PRINT(...)
#endif #endif

View File

@ -43,7 +43,7 @@
fprintf(stderr, ": %s: ", __func__); \ fprintf(stderr, ": %s: ", __func__); \
fprintf(stderr, ## __VA_ARGS__); \ fprintf(stderr, ## __VA_ARGS__); \
} \ } \
} while (0); } while (0)
/* config register */ /* config register */
#define R_CONFIG (0x00 / 4) #define R_CONFIG (0x00 / 4)

View File

@ -37,7 +37,7 @@
fprintf(stderr, ": %s: ", __func__); \ fprintf(stderr, ": %s: ", __func__); \
fprintf(stderr, ## __VA_ARGS__); \ fprintf(stderr, ## __VA_ARGS__); \
} \ } \
} while (0); } while (0)
#define DB_PRINT(...) DB_PRINT_L(0, ## __VA_ARGS__) #define DB_PRINT(...) DB_PRINT_L(0, ## __VA_ARGS__)

View File

@ -24,7 +24,7 @@
#define DB_PRINT(...) do { \ #define DB_PRINT(...) do { \
fprintf(stderr, ": %s: ", __func__); \ fprintf(stderr, ": %s: ", __func__); \
fprintf(stderr, ## __VA_ARGS__); \ fprintf(stderr, ## __VA_ARGS__); \
} while (0); } while (0)
#else #else
#define DB_PRINT(...) #define DB_PRINT(...)
#endif #endif

View File

@ -70,6 +70,7 @@ typedef struct HPETState {
MemoryRegion iomem; MemoryRegion iomem;
uint64_t hpet_offset; uint64_t hpet_offset;
bool hpet_offset_saved;
qemu_irq irqs[HPET_NUM_IRQ_ROUTES]; qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
uint32_t flags; uint32_t flags;
uint8_t rtc_irq_level; uint8_t rtc_irq_level;
@ -221,7 +222,9 @@ static int hpet_pre_save(void *opaque)
HPETState *s = opaque; HPETState *s = opaque;
/* save current counter value */ /* save current counter value */
s->hpet_counter = hpet_get_ticks(s); if (hpet_enabled(s)) {
s->hpet_counter = hpet_get_ticks(s);
}
return 0; return 0;
} }
@ -252,7 +255,10 @@ static int hpet_post_load(void *opaque, int version_id)
HPETState *s = opaque; HPETState *s = opaque;
/* Recalculate the offset between the main counter and guest time */ /* Recalculate the offset between the main counter and guest time */
s->hpet_offset = ticks_to_ns(s->hpet_counter) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); if (!s->hpet_offset_saved) {
s->hpet_offset = ticks_to_ns(s->hpet_counter)
- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
/* Push number of timers into capability returned via HPET_ID */ /* Push number of timers into capability returned via HPET_ID */
s->capability &= ~HPET_ID_NUM_TIM_MASK; s->capability &= ~HPET_ID_NUM_TIM_MASK;
@ -267,6 +273,13 @@ static int hpet_post_load(void *opaque, int version_id)
return 0; return 0;
} }
static bool hpet_offset_needed(void *opaque)
{
HPETState *s = opaque;
return hpet_enabled(s) && s->hpet_offset_saved;
}
static bool hpet_rtc_irq_level_needed(void *opaque) static bool hpet_rtc_irq_level_needed(void *opaque)
{ {
HPETState *s = opaque; HPETState *s = opaque;
@ -285,6 +298,17 @@ static const VMStateDescription vmstate_hpet_rtc_irq_level = {
} }
}; };
static const VMStateDescription vmstate_hpet_offset = {
.name = "hpet/offset",
.version_id = 1,
.minimum_version_id = 1,
.needed = hpet_offset_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT64(hpet_offset, HPETState),
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription vmstate_hpet_timer = { static const VMStateDescription vmstate_hpet_timer = {
.name = "hpet_timer", .name = "hpet_timer",
.version_id = 1, .version_id = 1,
@ -320,6 +344,7 @@ static const VMStateDescription vmstate_hpet = {
}, },
.subsections = (const VMStateDescription*[]) { .subsections = (const VMStateDescription*[]) {
&vmstate_hpet_rtc_irq_level, &vmstate_hpet_rtc_irq_level,
&vmstate_hpet_offset,
NULL NULL
} }
}; };
@ -762,6 +787,7 @@ static Property hpet_device_properties[] = {
DEFINE_PROP_UINT8("timers", HPETState, num_timers, HPET_MIN_TIMERS), DEFINE_PROP_UINT8("timers", HPETState, num_timers, HPET_MIN_TIMERS),
DEFINE_PROP_BIT("msi", HPETState, flags, HPET_MSI_SUPPORT, false), DEFINE_PROP_BIT("msi", HPETState, flags, HPET_MSI_SUPPORT, false),
DEFINE_PROP_UINT32(HPET_INTCAP, HPETState, intcap, 0), DEFINE_PROP_UINT32(HPET_INTCAP, HPETState, intcap, 0),
DEFINE_PROP_BOOL("hpet-offset-saved", HPETState, hpet_offset_saved, true),
DEFINE_PROP_END_OF_LIST(), DEFINE_PROP_END_OF_LIST(),
}; };

View File

@ -36,7 +36,7 @@
if (MSS_TIMER_ERR_DEBUG >= lvl) { \ if (MSS_TIMER_ERR_DEBUG >= lvl) { \
qemu_log("%s: " fmt "\n", __func__, ## args); \ qemu_log("%s: " fmt "\n", __func__, ## args); \
} \ } \
} while (0); } while (0)
#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args) #define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)

View File

@ -34,7 +34,7 @@
if (STM_TIMER_ERR_DEBUG >= lvl) { \ if (STM_TIMER_ERR_DEBUG >= lvl) { \
qemu_log("%s: " fmt, __func__, ## args); \ qemu_log("%s: " fmt, __func__, ## args); \
} \ } \
} while (0); } while (0)
#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args) #define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)

View File

@ -38,7 +38,7 @@
if (DEBUG_TPM) { \ if (DEBUG_TPM) { \
fprintf(stderr, fmt, ## __VA_ARGS__); \ fprintf(stderr, fmt, ## __VA_ARGS__); \
} \ } \
} while (0); } while (0)
#define TYPE_TPM_PASSTHROUGH "tpm-passthrough" #define TYPE_TPM_PASSTHROUGH "tpm-passthrough"
#define TPM_PASSTHROUGH(obj) \ #define TPM_PASSTHROUGH(obj) \

View File

@ -90,7 +90,7 @@ typedef struct TPMState {
if (DEBUG_TIS) { \ if (DEBUG_TIS) { \
printf(fmt, ## __VA_ARGS__); \ printf(fmt, ## __VA_ARGS__); \
} \ } \
} while (0); } while (0)
/* tis registers */ /* tis registers */
#define TPM_TIS_REG_ACCESS 0x00 #define TPM_TIS_REG_ACCESS 0x00

View File

@ -256,6 +256,9 @@ Chardev *qemu_chardev_new(const char *id, const char *typename,
extern int term_escape_char; extern int term_escape_char;
GSource *qemu_chr_timeout_add_ms(Chardev *chr, guint ms,
GSourceFunc func, void *private);
/* console.c */ /* console.c */
void qemu_chr_parse_vc(QemuOpts *opts, ChardevBackend *backend, Error **errp); void qemu_chr_parse_vc(QemuOpts *opts, ChardevBackend *backend, Error **errp);

View File

@ -391,9 +391,10 @@ uint64_t cpu_physical_memory_sync_dirty_bitmap(RAMBlock *rb,
uint64_t num_dirty = 0; uint64_t num_dirty = 0;
unsigned long *dest = rb->bmap; unsigned long *dest = rb->bmap;
/* start address is aligned at the start of a word? */ /* start address and length is aligned at the start of a word? */
if (((word * BITS_PER_LONG) << TARGET_PAGE_BITS) == if (((word * BITS_PER_LONG) << TARGET_PAGE_BITS) ==
(start + rb->offset)) { (start + rb->offset) &&
!(length & ((BITS_PER_LONG << TARGET_PAGE_BITS) - 1))) {
int k; int k;
int nr = BITS_TO_LONGS(length >> TARGET_PAGE_BITS); int nr = BITS_TO_LONGS(length >> TARGET_PAGE_BITS);
unsigned long * const *src; unsigned long * const *src;

View File

@ -2,7 +2,11 @@
#define HW_COMPAT_H #define HW_COMPAT_H
#define HW_COMPAT_2_11 \ #define HW_COMPAT_2_11 \
/* empty */ {\
.driver = "hpet",\
.property = "hpet-offset-saved",\
.value = "false",\
},
#define HW_COMPAT_2_10 \ #define HW_COMPAT_2_10 \
{\ {\

View File

@ -59,5 +59,6 @@ ReadLineState *readline_init(ReadLinePrintfFunc *printf_func,
ReadLineFlushFunc *flush_func, ReadLineFlushFunc *flush_func,
void *opaque, void *opaque,
ReadLineCompletionFunc *completion_finder); ReadLineCompletionFunc *completion_finder);
void readline_free(ReadLineState *rs);
#endif /* READLINE_H */ #endif /* READLINE_H */

View File

@ -22,9 +22,31 @@ typedef struct QemuThread QemuThread;
void qemu_mutex_init(QemuMutex *mutex); void qemu_mutex_init(QemuMutex *mutex);
void qemu_mutex_destroy(QemuMutex *mutex); void qemu_mutex_destroy(QemuMutex *mutex);
void qemu_mutex_lock(QemuMutex *mutex); int qemu_mutex_trylock_impl(QemuMutex *mutex, const char *file, const int line);
int qemu_mutex_trylock(QemuMutex *mutex); void qemu_mutex_lock_impl(QemuMutex *mutex, const char *file, const int line);
void qemu_mutex_unlock(QemuMutex *mutex); void qemu_mutex_unlock_impl(QemuMutex *mutex, const char *file, const int line);
#define qemu_mutex_lock(mutex) \
qemu_mutex_lock_impl(mutex, __FILE__, __LINE__)
#define qemu_mutex_trylock(mutex) \
qemu_mutex_trylock_impl(mutex, __FILE__, __LINE__)
#define qemu_mutex_unlock(mutex) \
qemu_mutex_unlock_impl(mutex, __FILE__, __LINE__)
static inline void (qemu_mutex_lock)(QemuMutex *mutex)
{
qemu_mutex_lock(mutex);
}
static inline int (qemu_mutex_trylock)(QemuMutex *mutex)
{
return qemu_mutex_trylock(mutex);
}
static inline void (qemu_mutex_unlock)(QemuMutex *mutex)
{
qemu_mutex_unlock(mutex);
}
/* Prototypes for other functions are in thread-posix.h/thread-win32.h. */ /* Prototypes for other functions are in thread-posix.h/thread-win32.h. */
void qemu_rec_mutex_init(QemuRecMutex *mutex); void qemu_rec_mutex_init(QemuRecMutex *mutex);
@ -39,7 +61,16 @@ void qemu_cond_destroy(QemuCond *cond);
*/ */
void qemu_cond_signal(QemuCond *cond); void qemu_cond_signal(QemuCond *cond);
void qemu_cond_broadcast(QemuCond *cond); void qemu_cond_broadcast(QemuCond *cond);
void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex); void qemu_cond_wait_impl(QemuCond *cond, QemuMutex *mutex,
const char *file, const int line);
#define qemu_cond_wait(cond, mutex) \
qemu_cond_wait_impl(cond, mutex, __FILE__, __LINE__)
static inline void (qemu_cond_wait)(QemuCond *cond, QemuMutex *mutex)
{
qemu_cond_wait(cond, mutex);
}
void qemu_sem_init(QemuSemaphore *sem, int init); void qemu_sem_init(QemuSemaphore *sem, int init);
void qemu_sem_post(QemuSemaphore *sem); void qemu_sem_post(QemuSemaphore *sem);

View File

@ -88,7 +88,7 @@ static uint32_t known_capabilities = RDMA_CAPABILITY_PIN_ALL;
} \ } \
return rdma->error_state; \ return rdma->error_state; \
} \ } \
} while (0); } while (0)
/* /*
* A work request ID is 64-bits and we split up these bits * A work request ID is 64-bits and we split up these bits

View File

@ -583,7 +583,7 @@ static void monitor_data_destroy(Monitor *mon)
if (monitor_is_qmp(mon)) { if (monitor_is_qmp(mon)) {
json_message_parser_destroy(&mon->qmp.parser); json_message_parser_destroy(&mon->qmp.parser);
} }
g_free(mon->rs); readline_free(mon->rs);
QDECREF(mon->outbuf); QDECREF(mon->outbuf);
qemu_mutex_destroy(&mon->out_lock); qemu_mutex_destroy(&mon->out_lock);
} }

View File

@ -131,6 +131,8 @@ modules:
# If called with only a single argument, will print nothing in quiet mode. # If called with only a single argument, will print nothing in quiet mode.
quiet-command = $(if $(V),$1,$(if $(2),@printf " %-7s %s\n" $2 $3 && $1, @$1)) quiet-command = $(if $(V),$1,$(if $(2),@printf " %-7s %s\n" $2 $3 && $1, @$1))
MAKEFLAGS += $(if $(V),,--no-print-directory --quiet)
# cc-option # cc-option
# Usage: CFLAGS+=$(call cc-option, -falign-functions=0, -malign-functions=0) # Usage: CFLAGS+=$(call cc-option, -falign-functions=0, -malign-functions=0)

View File

@ -0,0 +1,99 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Analyse lock events and compute statistics
#
# Author: Alex Bennée <alex.bennee@linaro.org>
#
import os
import simpletrace
import argparse
import numpy as np
class MutexAnalyser(simpletrace.Analyzer):
"A simpletrace Analyser for checking locks."
def __init__(self):
self.locks = 0
self.locked = 0
self.unlocks = 0
self.mutex_records = {}
def _get_mutex(self, mutex):
if not mutex in self.mutex_records:
self.mutex_records[mutex] = {"locks": 0,
"lock_time": 0,
"acquire_times": [],
"locked": 0,
"locked_time": 0,
"held_times": [],
"unlocked": 0}
return self.mutex_records[mutex]
def qemu_mutex_lock(self, timestamp, mutex, filename, line):
self.locks += 1
rec = self._get_mutex(mutex)
rec["locks"] += 1
rec["lock_time"] = timestamp[0]
rec["lock_loc"] = (filename, line)
def qemu_mutex_locked(self, timestamp, mutex, filename, line):
self.locked += 1
rec = self._get_mutex(mutex)
rec["locked"] += 1
rec["locked_time"] = timestamp[0]
acquire_time = rec["locked_time"] - rec["lock_time"]
rec["locked_loc"] = (filename, line)
rec["acquire_times"].append(acquire_time)
def qemu_mutex_unlock(self, timestamp, mutex, filename, line):
self.unlocks += 1
rec = self._get_mutex(mutex)
rec["unlocked"] += 1
held_time = timestamp[0] - rec["locked_time"]
rec["held_times"].append(held_time)
rec["unlock_loc"] = (filename, line)
def get_args():
"Grab options"
parser = argparse.ArgumentParser()
parser.add_argument("--output", "-o", type=str, help="Render plot to file")
parser.add_argument("events", type=str, help='trace file read from')
parser.add_argument("tracefile", type=str, help='trace file read from')
return parser.parse_args()
if __name__ == '__main__':
args = get_args()
# Gather data from the trace
analyser = MutexAnalyser()
simpletrace.process(args.events, args.tracefile, analyser)
print ("Total locks: %d, locked: %d, unlocked: %d" %
(analyser.locks, analyser.locked, analyser.unlocks))
# Now dump the individual lock stats
for key, val in sorted(analyser.mutex_records.iteritems(),
key=lambda (k,v): v["locks"]):
print ("Lock: %#x locks: %d, locked: %d, unlocked: %d" %
(key, val["locks"], val["locked"], val["unlocked"]))
acquire_times = np.array(val["acquire_times"])
if len(acquire_times) > 0:
print (" Acquire Time: min:%d median:%d avg:%.2f max:%d" %
(acquire_times.min(), np.median(acquire_times),
acquire_times.mean(), acquire_times.max()))
held_times = np.array(val["held_times"])
if len(held_times) > 0:
print (" Held Time: min:%d median:%d avg:%.2f max:%d" %
(held_times.min(), np.median(held_times),
held_times.mean(), held_times.max()))
# Check if any locks still held
if val["locks"] > val["locked"]:
print (" LOCK HELD (%s:%s)" % (val["locked_loc"]))
print (" BLOCKED (%s:%s)" % (val["lock_loc"]))

View File

@ -1622,6 +1622,11 @@ sub process {
} }
} }
# 'do ... while (0/false)' only makes sense in macros, without trailing ';'
if ($line =~ /while\s*\((0|false)\);/) {
ERROR("suspicious ; after while (0)\n" . $herecurr);
}
# Check relative indent for conditionals and blocks. # Check relative indent for conditionals and blocks.
if ($line =~ /\b(?:(?:if|while|for)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) { if ($line =~ /\b(?:(?:if|while|for)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) {
my ($s, $c) = ($stat, $cond); my ($s, $c) = ($stat, $cond);

View File

@ -26,7 +26,7 @@ import os, sys
sys.path.append(os.path.dirname(__file__)) sys.path.append(os.path.dirname(__file__))
from qemugdb import aio, mtree, coroutine from qemugdb import aio, mtree, coroutine, tcg, timers
class QemuCommand(gdb.Command): class QemuCommand(gdb.Command):
'''Prefix for QEMU debug support commands''' '''Prefix for QEMU debug support commands'''
@ -38,6 +38,8 @@ QemuCommand()
coroutine.CoroutineCommand() coroutine.CoroutineCommand()
mtree.MtreeCommand() mtree.MtreeCommand()
aio.HandlersCommand() aio.HandlersCommand()
tcg.TCGLockStatusCommand()
timers.TimersCommand()
coroutine.CoroutineSPFunction() coroutine.CoroutineSPFunction()
coroutine.CoroutinePCFunction() coroutine.CoroutinePCFunction()

46
scripts/qemugdb/tcg.py Normal file
View File

@ -0,0 +1,46 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# GDB debugging support, TCG status
#
# Copyright 2016 Linaro Ltd
#
# Authors:
# Alex Bennée <alex.bennee@linaro.org>
#
# This work is licensed under the terms of the GNU GPL, version 2. See
# the COPYING file in the top-level directory.
#
# Contributions after 2012-01-13 are licensed under the terms of the
# GNU GPL, version 2 or (at your option) any later version.
# 'qemu tcg-lock-status' -- display the TCG lock status across threads
import gdb
class TCGLockStatusCommand(gdb.Command):
'''Display TCG Execution Status'''
def __init__(self):
gdb.Command.__init__(self, 'qemu tcg-lock-status', gdb.COMMAND_DATA,
gdb.COMPLETE_NONE)
def invoke(self, arg, from_tty):
gdb.write("Thread, BQL (iothread_mutex), Replay, Blocked?\n")
for thread in gdb.inferiors()[0].threads():
thread.switch()
iothread = gdb.parse_and_eval("iothread_locked")
replay = gdb.parse_and_eval("replay_locked")
frame = gdb.selected_frame()
if frame.name() == "__lll_lock_wait":
frame.older().select()
mutex = gdb.parse_and_eval("mutex")
owner = gdb.parse_and_eval("mutex->__data.__owner")
blocked = ("__lll_lock_wait waiting on %s from %d" %
(mutex, owner))
else:
blocked = "not blocked"
gdb.write("%d/%d, %s, %s, %s\n" % (thread.num, thread.ptid[1],
iothread, replay, blocked))

54
scripts/qemugdb/timers.py Normal file
View File

@ -0,0 +1,54 @@
#!/usr/bin/python
# GDB debugging support
#
# Copyright 2017 Linaro Ltd
#
# Author: Alex Bennée <alex.bennee@linaro.org>
#
# This work is licensed under the terms of the GNU GPL, version 2. See
# the COPYING file in the top-level directory.
# 'qemu timers' -- display the current timerlists
import gdb
class TimersCommand(gdb.Command):
'''Display the current QEMU timers'''
def __init__(self):
'Register the class as a gdb command'
gdb.Command.__init__(self, 'qemu timers', gdb.COMMAND_DATA,
gdb.COMPLETE_NONE)
def dump_timers(self, timer):
"Follow a timer and recursively dump each one in the list."
# timer should be of type QemuTimer
gdb.write(" timer %s/%s (cb:%s,opq:%s)\n" % (
timer['expire_time'],
timer['scale'],
timer['cb'],
timer['opaque']))
if int(timer['next']) > 0:
self.dump_timers(timer['next'])
def process_timerlist(self, tlist, ttype):
gdb.write("Processing %s timers\n" % (ttype))
gdb.write(" clock %s is enabled:%s, last:%s\n" % (
tlist['clock']['type'],
tlist['clock']['enabled'],
tlist['clock']['last']))
if int(tlist['active_timers']) > 0:
self.dump_timers(tlist['active_timers'])
def invoke(self, arg, from_tty):
'Run the command'
main_timers = gdb.parse_and_eval("main_loop_tlg")
# This will break if QEMUClockType in timer.h is redfined
self.process_timerlist(main_timers['tl'][0], "Realtime")
self.process_timerlist(main_timers['tl'][1], "Virtual")
self.process_timerlist(main_timers['tl'][2], "Host")
self.process_timerlist(main_timers['tl'][3], "Virtual RT")

View File

@ -322,18 +322,18 @@ int scsi_convert_sense(uint8_t *in_buf, int in_len,
SCSISense sense; SCSISense sense;
bool fixed_in; bool fixed_in;
fixed_in = (in_buf[0] & 2) == 0; if (in_len == 0) {
if (in_len && fixed == fixed_in) { return scsi_build_sense_buf(buf, len, SENSE_CODE(NO_SENSE), fixed);
memcpy(buf, in_buf, MIN(len, in_len));
return MIN(len, in_len);
} }
if (in_len == 0) { fixed_in = (in_buf[0] & 2) == 0;
sense = SENSE_CODE(NO_SENSE); if (fixed == fixed_in) {
memcpy(buf, in_buf, MIN(len, in_len));
return MIN(len, in_len);
} else { } else {
sense = scsi_parse_sense_buf(in_buf, in_len); sense = scsi_parse_sense_buf(in_buf, in_len);
return scsi_build_sense_buf(buf, len, sense, fixed);
} }
return scsi_build_sense_buf(buf, len, sense, fixed);
} }
int scsi_sense_to_errno(int key, int asc, int ascq) int scsi_sense_to_errno(int key, int asc, int ascq)

View File

@ -400,7 +400,7 @@ static void unallocated_encoding(DisasContext *s)
"at pc=%016" PRIx64 "\n", \ "at pc=%016" PRIx64 "\n", \
__FILE__, __LINE__, insn, s->pc - 4); \ __FILE__, __LINE__, insn, s->pc - 4); \
unallocated_encoding(s); \ unallocated_encoding(s); \
} while (0); } while (0)
static void init_tmp_a64_array(DisasContext *s) static void init_tmp_a64_array(DisasContext *s)
{ {

View File

@ -4147,6 +4147,48 @@ static void x86_disas_set_info(CPUState *cs, disassemble_info *info)
info->cap_insn_split = 8; info->cap_insn_split = 8;
} }
void x86_update_hflags(CPUX86State *env)
{
uint32_t hflags;
#define HFLAG_COPY_MASK \
~( HF_CPL_MASK | HF_PE_MASK | HF_MP_MASK | HF_EM_MASK | \
HF_TS_MASK | HF_TF_MASK | HF_VM_MASK | HF_IOPL_MASK | \
HF_OSFXSR_MASK | HF_LMA_MASK | HF_CS32_MASK | \
HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)
hflags = env->hflags & HFLAG_COPY_MASK;
hflags |= (env->segs[R_SS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK;
hflags |= (env->cr[0] & CR0_PE_MASK) << (HF_PE_SHIFT - CR0_PE_SHIFT);
hflags |= (env->cr[0] << (HF_MP_SHIFT - CR0_MP_SHIFT)) &
(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK);
hflags |= (env->eflags & (HF_TF_MASK | HF_VM_MASK | HF_IOPL_MASK));
if (env->cr[4] & CR4_OSFXSR_MASK) {
hflags |= HF_OSFXSR_MASK;
}
if (env->efer & MSR_EFER_LMA) {
hflags |= HF_LMA_MASK;
}
if ((hflags & HF_LMA_MASK) && (env->segs[R_CS].flags & DESC_L_MASK)) {
hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
} else {
hflags |= (env->segs[R_CS].flags & DESC_B_MASK) >>
(DESC_B_SHIFT - HF_CS32_SHIFT);
hflags |= (env->segs[R_SS].flags & DESC_B_MASK) >>
(DESC_B_SHIFT - HF_SS32_SHIFT);
if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK) ||
!(hflags & HF_CS32_MASK)) {
hflags |= HF_ADDSEG_MASK;
} else {
hflags |= ((env->segs[R_DS].base | env->segs[R_ES].base |
env->segs[R_SS].base) != 0) << HF_ADDSEG_SHIFT;
}
}
env->hflags = hflags;
}
static Property x86_cpu_properties[] = { static Property x86_cpu_properties[] = {
#ifdef CONFIG_USER_ONLY #ifdef CONFIG_USER_ONLY
/* apic_id = 0 by default for *-user, see commit 9886e834 */ /* apic_id = 0 by default for *-user, see commit 9886e834 */

View File

@ -1778,4 +1778,6 @@ bool cpu_is_bsp(X86CPU *cpu);
void x86_cpu_xrstor_all_areas(X86CPU *cpu, const X86XSaveArea *buf); void x86_cpu_xrstor_all_areas(X86CPU *cpu, const X86XSaveArea *buf);
void x86_cpu_xsave_all_areas(X86CPU *cpu, X86XSaveArea *buf); void x86_cpu_xsave_all_areas(X86CPU *cpu, X86XSaveArea *buf);
void x86_update_hflags(CPUX86State* env);
#endif /* I386_CPU_H */ #endif /* I386_CPU_H */

View File

@ -782,56 +782,6 @@ static int hax_set_segments(CPUArchState *env, struct vcpu_state_t *sregs)
return 0; return 0;
} }
/*
* After get the state from the kernel module, some
* qemu emulator state need be updated also
*/
static int hax_setup_qemu_emulator(CPUArchState *env)
{
#define HFLAG_COPY_MASK (~( \
HF_CPL_MASK | HF_PE_MASK | HF_MP_MASK | HF_EM_MASK | \
HF_TS_MASK | HF_TF_MASK | HF_VM_MASK | HF_IOPL_MASK | \
HF_OSFXSR_MASK | HF_LMA_MASK | HF_CS32_MASK | \
HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK))
uint32_t hflags;
hflags = (env->segs[R_CS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK;
hflags |= (env->cr[0] & CR0_PE_MASK) << (HF_PE_SHIFT - CR0_PE_SHIFT);
hflags |= (env->cr[0] << (HF_MP_SHIFT - CR0_MP_SHIFT)) &
(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK);
hflags |= (env->eflags & (HF_TF_MASK | HF_VM_MASK | HF_IOPL_MASK));
hflags |= (env->cr[4] & CR4_OSFXSR_MASK) <<
(HF_OSFXSR_SHIFT - CR4_OSFXSR_SHIFT);
if (env->efer & MSR_EFER_LMA) {
hflags |= HF_LMA_MASK;
}
if ((hflags & HF_LMA_MASK) && (env->segs[R_CS].flags & DESC_L_MASK)) {
hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
} else {
hflags |= (env->segs[R_CS].flags & DESC_B_MASK) >>
(DESC_B_SHIFT - HF_CS32_SHIFT);
hflags |= (env->segs[R_SS].flags & DESC_B_MASK) >>
(DESC_B_SHIFT - HF_SS32_SHIFT);
if (!(env->cr[0] & CR0_PE_MASK) ||
(env->eflags & VM_MASK) || !(hflags & HF_CS32_MASK)) {
hflags |= HF_ADDSEG_MASK;
} else {
hflags |= ((env->segs[R_DS].base |
env->segs[R_ES].base |
env->segs[R_SS].base) != 0) << HF_ADDSEG_SHIFT;
}
}
hflags &= ~HF_SMM_MASK;
env->hflags = (env->hflags & HFLAG_COPY_MASK) | hflags;
return 0;
}
static int hax_sync_vcpu_register(CPUArchState *env, int set) static int hax_sync_vcpu_register(CPUArchState *env, int set)
{ {
struct vcpu_state_t regs; struct vcpu_state_t regs;
@ -887,9 +837,6 @@ static int hax_sync_vcpu_register(CPUArchState *env, int set)
return -1; return -1;
} }
} }
if (!set) {
hax_setup_qemu_emulator(env);
}
return 0; return 0;
} }
@ -1070,6 +1017,7 @@ static int hax_arch_get_registers(CPUArchState *env)
return ret; return ret;
} }
x86_update_hflags(env);
return 0; return 0;
} }

View File

@ -297,7 +297,6 @@ int hvf_get_registers(CPUState *cpu_state)
X86CPU *x86cpu = X86_CPU(cpu_state); X86CPU *x86cpu = X86_CPU(cpu_state);
CPUX86State *env = &x86cpu->env; CPUX86State *env = &x86cpu->env;
env->regs[R_EAX] = rreg(cpu_state->hvf_fd, HV_X86_RAX); env->regs[R_EAX] = rreg(cpu_state->hvf_fd, HV_X86_RAX);
env->regs[R_EBX] = rreg(cpu_state->hvf_fd, HV_X86_RBX); env->regs[R_EBX] = rreg(cpu_state->hvf_fd, HV_X86_RBX);
env->regs[R_ECX] = rreg(cpu_state->hvf_fd, HV_X86_RCX); env->regs[R_ECX] = rreg(cpu_state->hvf_fd, HV_X86_RCX);
@ -333,6 +332,7 @@ int hvf_get_registers(CPUState *cpu_state)
env->dr[6] = rreg(cpu_state->hvf_fd, HV_X86_DR6); env->dr[6] = rreg(cpu_state->hvf_fd, HV_X86_DR6);
env->dr[7] = rreg(cpu_state->hvf_fd, HV_X86_DR7); env->dr[7] = rreg(cpu_state->hvf_fd, HV_X86_DR7);
x86_update_hflags(env);
return 0; return 0;
} }

View File

@ -92,8 +92,9 @@ static bool has_msr_hv_stimer;
static bool has_msr_hv_frequencies; static bool has_msr_hv_frequencies;
static bool has_msr_xss; static bool has_msr_xss;
static bool has_msr_architectural_pmu; static uint32_t has_architectural_pmu_version;
static uint32_t num_architectural_pmu_counters; static uint32_t num_architectural_pmu_gp_counters;
static uint32_t num_architectural_pmu_fixed_counters;
static int has_xsave; static int has_xsave;
static int has_xcrs; static int has_xcrs;
@ -872,19 +873,28 @@ int kvm_arch_init_vcpu(CPUState *cs)
} }
if (limit >= 0x0a) { if (limit >= 0x0a) {
uint32_t ver; uint32_t eax, edx;
cpu_x86_cpuid(env, 0x0a, 0, &ver, &unused, &unused, &unused); cpu_x86_cpuid(env, 0x0a, 0, &eax, &unused, &unused, &edx);
if ((ver & 0xff) > 0) {
has_msr_architectural_pmu = true; has_architectural_pmu_version = eax & 0xff;
num_architectural_pmu_counters = (ver & 0xff00) >> 8; if (has_architectural_pmu_version > 0) {
num_architectural_pmu_gp_counters = (eax & 0xff00) >> 8;
/* Shouldn't be more than 32, since that's the number of bits /* Shouldn't be more than 32, since that's the number of bits
* available in EBX to tell us _which_ counters are available. * available in EBX to tell us _which_ counters are available.
* Play it safe. * Play it safe.
*/ */
if (num_architectural_pmu_counters > MAX_GP_COUNTERS) { if (num_architectural_pmu_gp_counters > MAX_GP_COUNTERS) {
num_architectural_pmu_counters = MAX_GP_COUNTERS; num_architectural_pmu_gp_counters = MAX_GP_COUNTERS;
}
if (has_architectural_pmu_version > 1) {
num_architectural_pmu_fixed_counters = edx & 0x1f;
if (num_architectural_pmu_fixed_counters > MAX_FIXED_COUNTERS) {
num_architectural_pmu_fixed_counters = MAX_FIXED_COUNTERS;
}
} }
} }
} }
@ -1650,32 +1660,36 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_STEAL_TIME)) { if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_STEAL_TIME)) {
kvm_msr_entry_add(cpu, MSR_KVM_STEAL_TIME, env->steal_time_msr); kvm_msr_entry_add(cpu, MSR_KVM_STEAL_TIME, env->steal_time_msr);
} }
if (has_msr_architectural_pmu) { if (has_architectural_pmu_version > 0) {
/* Stop the counter. */ if (has_architectural_pmu_version > 1) {
kvm_msr_entry_add(cpu, MSR_CORE_PERF_FIXED_CTR_CTRL, 0); /* Stop the counter. */
kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_CTRL, 0); kvm_msr_entry_add(cpu, MSR_CORE_PERF_FIXED_CTR_CTRL, 0);
kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_CTRL, 0);
}
/* Set the counter values. */ /* Set the counter values. */
for (i = 0; i < MAX_FIXED_COUNTERS; i++) { for (i = 0; i < num_architectural_pmu_fixed_counters; i++) {
kvm_msr_entry_add(cpu, MSR_CORE_PERF_FIXED_CTR0 + i, kvm_msr_entry_add(cpu, MSR_CORE_PERF_FIXED_CTR0 + i,
env->msr_fixed_counters[i]); env->msr_fixed_counters[i]);
} }
for (i = 0; i < num_architectural_pmu_counters; i++) { for (i = 0; i < num_architectural_pmu_gp_counters; i++) {
kvm_msr_entry_add(cpu, MSR_P6_PERFCTR0 + i, kvm_msr_entry_add(cpu, MSR_P6_PERFCTR0 + i,
env->msr_gp_counters[i]); env->msr_gp_counters[i]);
kvm_msr_entry_add(cpu, MSR_P6_EVNTSEL0 + i, kvm_msr_entry_add(cpu, MSR_P6_EVNTSEL0 + i,
env->msr_gp_evtsel[i]); env->msr_gp_evtsel[i]);
} }
kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_STATUS, if (has_architectural_pmu_version > 1) {
env->msr_global_status); kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_STATUS,
kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_OVF_CTRL, env->msr_global_status);
env->msr_global_ovf_ctrl); kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_OVF_CTRL,
env->msr_global_ovf_ctrl);
/* Now start the PMU. */ /* Now start the PMU. */
kvm_msr_entry_add(cpu, MSR_CORE_PERF_FIXED_CTR_CTRL, kvm_msr_entry_add(cpu, MSR_CORE_PERF_FIXED_CTR_CTRL,
env->msr_fixed_ctr_ctrl); env->msr_fixed_ctr_ctrl);
kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_CTRL, kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_CTRL,
env->msr_global_ctrl); env->msr_global_ctrl);
}
} }
/* /*
* Hyper-V partition-wide MSRs: to avoid clearing them on cpu hot-add, * Hyper-V partition-wide MSRs: to avoid clearing them on cpu hot-add,
@ -1877,7 +1891,6 @@ static int kvm_get_sregs(X86CPU *cpu)
{ {
CPUX86State *env = &cpu->env; CPUX86State *env = &cpu->env;
struct kvm_sregs sregs; struct kvm_sregs sregs;
uint32_t hflags;
int bit, i, ret; int bit, i, ret;
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_SREGS, &sregs); ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_SREGS, &sregs);
@ -1919,44 +1932,7 @@ static int kvm_get_sregs(X86CPU *cpu)
env->efer = sregs.efer; env->efer = sregs.efer;
/* changes to apic base and cr8/tpr are read back via kvm_arch_post_run */ /* changes to apic base and cr8/tpr are read back via kvm_arch_post_run */
x86_update_hflags(env);
#define HFLAG_COPY_MASK \
~( HF_CPL_MASK | HF_PE_MASK | HF_MP_MASK | HF_EM_MASK | \
HF_TS_MASK | HF_TF_MASK | HF_VM_MASK | HF_IOPL_MASK | \
HF_OSFXSR_MASK | HF_LMA_MASK | HF_CS32_MASK | \
HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)
hflags = env->hflags & HFLAG_COPY_MASK;
hflags |= (env->segs[R_SS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK;
hflags |= (env->cr[0] & CR0_PE_MASK) << (HF_PE_SHIFT - CR0_PE_SHIFT);
hflags |= (env->cr[0] << (HF_MP_SHIFT - CR0_MP_SHIFT)) &
(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK);
hflags |= (env->eflags & (HF_TF_MASK | HF_VM_MASK | HF_IOPL_MASK));
if (env->cr[4] & CR4_OSFXSR_MASK) {
hflags |= HF_OSFXSR_MASK;
}
if (env->efer & MSR_EFER_LMA) {
hflags |= HF_LMA_MASK;
}
if ((hflags & HF_LMA_MASK) && (env->segs[R_CS].flags & DESC_L_MASK)) {
hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
} else {
hflags |= (env->segs[R_CS].flags & DESC_B_MASK) >>
(DESC_B_SHIFT - HF_CS32_SHIFT);
hflags |= (env->segs[R_SS].flags & DESC_B_MASK) >>
(DESC_B_SHIFT - HF_SS32_SHIFT);
if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK) ||
!(hflags & HF_CS32_MASK)) {
hflags |= HF_ADDSEG_MASK;
} else {
hflags |= ((env->segs[R_DS].base | env->segs[R_ES].base |
env->segs[R_SS].base) != 0) << HF_ADDSEG_SHIFT;
}
}
env->hflags = hflags;
return 0; return 0;
} }
@ -2030,15 +2006,17 @@ static int kvm_get_msrs(X86CPU *cpu)
if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_STEAL_TIME)) { if (env->features[FEAT_KVM] & (1 << KVM_FEATURE_STEAL_TIME)) {
kvm_msr_entry_add(cpu, MSR_KVM_STEAL_TIME, 0); kvm_msr_entry_add(cpu, MSR_KVM_STEAL_TIME, 0);
} }
if (has_msr_architectural_pmu) { if (has_architectural_pmu_version > 0) {
kvm_msr_entry_add(cpu, MSR_CORE_PERF_FIXED_CTR_CTRL, 0); if (has_architectural_pmu_version > 1) {
kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_CTRL, 0); kvm_msr_entry_add(cpu, MSR_CORE_PERF_FIXED_CTR_CTRL, 0);
kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_STATUS, 0); kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_CTRL, 0);
kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_OVF_CTRL, 0); kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_STATUS, 0);
for (i = 0; i < MAX_FIXED_COUNTERS; i++) { kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_OVF_CTRL, 0);
}
for (i = 0; i < num_architectural_pmu_fixed_counters; i++) {
kvm_msr_entry_add(cpu, MSR_CORE_PERF_FIXED_CTR0 + i, 0); kvm_msr_entry_add(cpu, MSR_CORE_PERF_FIXED_CTR0 + i, 0);
} }
for (i = 0; i < num_architectural_pmu_counters; i++) { for (i = 0; i < num_architectural_pmu_gp_counters; i++) {
kvm_msr_entry_add(cpu, MSR_P6_PERFCTR0 + i, 0); kvm_msr_entry_add(cpu, MSR_P6_PERFCTR0 + i, 0);
kvm_msr_entry_add(cpu, MSR_P6_EVNTSEL0 + i, 0); kvm_msr_entry_add(cpu, MSR_P6_EVNTSEL0 + i, 0);
} }
@ -3492,6 +3470,7 @@ int kvm_arch_release_virq_post(int virq)
if (entry->virq == virq) { if (entry->virq == virq) {
trace_kvm_x86_remove_msi_route(virq); trace_kvm_x86_remove_msi_route(virq);
QLIST_REMOVE(entry, list); QLIST_REMOVE(entry, list);
g_free(entry);
break; break;
} }
} }

View File

@ -682,13 +682,13 @@ static inline int64_t msa_mod_u_df(uint32_t df, int64_t arg1, int64_t arg2)
do { \ do { \
e = SIGNED_EVEN(a, df); \ e = SIGNED_EVEN(a, df); \
o = SIGNED_ODD(a, df); \ o = SIGNED_ODD(a, df); \
} while (0); } while (0)
#define UNSIGNED_EXTRACT(e, o, a, df) \ #define UNSIGNED_EXTRACT(e, o, a, df) \
do { \ do { \
e = UNSIGNED_EVEN(a, df); \ e = UNSIGNED_EVEN(a, df); \
o = UNSIGNED_ODD(a, df); \ o = UNSIGNED_ODD(a, df); \
} while (0); } while (0)
static inline int64_t msa_dotp_s_df(uint32_t df, int64_t arg1, int64_t arg2) static inline int64_t msa_dotp_s_df(uint32_t df, int64_t arg1, int64_t arg2)
{ {
@ -1120,9 +1120,11 @@ void helper_msa_splat_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
#define MSA_LOOP_COND_D MSA_LOOP_COND(DF_DOUBLE) #define MSA_LOOP_COND_D MSA_LOOP_COND(DF_DOUBLE)
#define MSA_LOOP(DF) \ #define MSA_LOOP(DF) \
do { \
for (i = 0; i < (MSA_LOOP_COND_ ## DF) ; i++) { \ for (i = 0; i < (MSA_LOOP_COND_ ## DF) ; i++) { \
MSA_DO_ ## DF \ MSA_DO_ ## DF; \
} } \
} while (0)
#define MSA_FN_DF(FUNC) \ #define MSA_FN_DF(FUNC) \
void helper_msa_##FUNC(CPUMIPSState *env, uint32_t df, uint32_t wd, \ void helper_msa_##FUNC(CPUMIPSState *env, uint32_t df, uint32_t wd, \
@ -1135,17 +1137,17 @@ void helper_msa_##FUNC(CPUMIPSState *env, uint32_t df, uint32_t wd, \
uint32_t i; \ uint32_t i; \
switch (df) { \ switch (df) { \
case DF_BYTE: \ case DF_BYTE: \
MSA_LOOP_B \ MSA_LOOP_B; \
break; \ break; \
case DF_HALF: \ case DF_HALF: \
MSA_LOOP_H \ MSA_LOOP_H; \
break; \ break; \
case DF_WORD: \ case DF_WORD: \
MSA_LOOP_W \ MSA_LOOP_W; \
break; \ break; \
case DF_DOUBLE: \ case DF_DOUBLE: \
MSA_LOOP_D \ MSA_LOOP_D; \
break; \ break; \
default: \ default: \
assert(0); \ assert(0); \
} \ } \
@ -1168,7 +1170,7 @@ void helper_msa_##FUNC(CPUMIPSState *env, uint32_t df, uint32_t wd, \
do { \ do { \
R##DF(pwx, i) = pwt->DF[2*i]; \ R##DF(pwx, i) = pwt->DF[2*i]; \
L##DF(pwx, i) = pws->DF[2*i]; \ L##DF(pwx, i) = pws->DF[2*i]; \
} while (0); } while (0)
MSA_FN_DF(pckev_df) MSA_FN_DF(pckev_df)
#undef MSA_DO #undef MSA_DO
@ -1176,7 +1178,7 @@ MSA_FN_DF(pckev_df)
do { \ do { \
R##DF(pwx, i) = pwt->DF[2*i+1]; \ R##DF(pwx, i) = pwt->DF[2*i+1]; \
L##DF(pwx, i) = pws->DF[2*i+1]; \ L##DF(pwx, i) = pws->DF[2*i+1]; \
} while (0); } while (0)
MSA_FN_DF(pckod_df) MSA_FN_DF(pckod_df)
#undef MSA_DO #undef MSA_DO
@ -1184,7 +1186,7 @@ MSA_FN_DF(pckod_df)
do { \ do { \
pwx->DF[2*i] = L##DF(pwt, i); \ pwx->DF[2*i] = L##DF(pwt, i); \
pwx->DF[2*i+1] = L##DF(pws, i); \ pwx->DF[2*i+1] = L##DF(pws, i); \
} while (0); } while (0)
MSA_FN_DF(ilvl_df) MSA_FN_DF(ilvl_df)
#undef MSA_DO #undef MSA_DO
@ -1192,7 +1194,7 @@ MSA_FN_DF(ilvl_df)
do { \ do { \
pwx->DF[2*i] = R##DF(pwt, i); \ pwx->DF[2*i] = R##DF(pwt, i); \
pwx->DF[2*i+1] = R##DF(pws, i); \ pwx->DF[2*i+1] = R##DF(pws, i); \
} while (0); } while (0)
MSA_FN_DF(ilvr_df) MSA_FN_DF(ilvr_df)
#undef MSA_DO #undef MSA_DO
@ -1200,7 +1202,7 @@ MSA_FN_DF(ilvr_df)
do { \ do { \
pwx->DF[2*i] = pwt->DF[2*i]; \ pwx->DF[2*i] = pwt->DF[2*i]; \
pwx->DF[2*i+1] = pws->DF[2*i]; \ pwx->DF[2*i+1] = pws->DF[2*i]; \
} while (0); } while (0)
MSA_FN_DF(ilvev_df) MSA_FN_DF(ilvev_df)
#undef MSA_DO #undef MSA_DO
@ -1208,7 +1210,7 @@ MSA_FN_DF(ilvev_df)
do { \ do { \
pwx->DF[2*i] = pwt->DF[2*i+1]; \ pwx->DF[2*i] = pwt->DF[2*i+1]; \
pwx->DF[2*i+1] = pws->DF[2*i+1]; \ pwx->DF[2*i+1] = pws->DF[2*i+1]; \
} while (0); } while (0)
MSA_FN_DF(ilvod_df) MSA_FN_DF(ilvod_df)
#undef MSA_DO #undef MSA_DO
#undef MSA_LOOP_COND #undef MSA_LOOP_COND
@ -1222,7 +1224,7 @@ MSA_FN_DF(ilvod_df)
uint32_t k = (pwd->DF[i] & 0x3f) % (2 * n); \ uint32_t k = (pwd->DF[i] & 0x3f) % (2 * n); \
pwx->DF[i] = \ pwx->DF[i] = \
(pwd->DF[i] & 0xc0) ? 0 : k < n ? pwt->DF[k] : pws->DF[k - n]; \ (pwd->DF[i] & 0xc0) ? 0 : k < n ? pwt->DF[k] : pws->DF[k - n]; \
} while (0); } while (0)
MSA_FN_DF(vshf_df) MSA_FN_DF(vshf_df)
#undef MSA_DO #undef MSA_DO
#undef MSA_LOOP_COND #undef MSA_LOOP_COND

View File

@ -58,7 +58,7 @@
if (DEBUG_KVM) { \ if (DEBUG_KVM) { \
fprintf(stderr, fmt, ## __VA_ARGS__); \ fprintf(stderr, fmt, ## __VA_ARGS__); \
} \ } \
} while (0); } while (0)
#define kvm_vm_check_mem_attr(s, attr) \ #define kvm_vm_check_mem_attr(s, attr) \
kvm_vm_check_attr(s, KVM_S390_VM_MEM_CTRL, attr) kvm_vm_check_attr(s, KVM_S390_VM_MEM_CTRL, attr)

View File

@ -300,12 +300,16 @@ check-qtest-alpha-y = tests/boot-serial-test$(EXESUF)
check-qtest-m68k-y = tests/boot-serial-test$(EXESUF) check-qtest-m68k-y = tests/boot-serial-test$(EXESUF)
check-qtest-microblaze-y = tests/boot-serial-test$(EXESUF)
check-qtest-mips-y = tests/endianness-test$(EXESUF) check-qtest-mips-y = tests/endianness-test$(EXESUF)
check-qtest-mips64-y = tests/endianness-test$(EXESUF) check-qtest-mips64-y = tests/endianness-test$(EXESUF)
check-qtest-mips64el-y = tests/endianness-test$(EXESUF) check-qtest-mips64el-y = tests/endianness-test$(EXESUF)
check-qtest-moxie-y = tests/boot-serial-test$(EXESUF)
check-qtest-ppc-y = tests/endianness-test$(EXESUF) check-qtest-ppc-y = tests/endianness-test$(EXESUF)
check-qtest-ppc-y += tests/boot-order-test$(EXESUF) check-qtest-ppc-y += tests/boot-order-test$(EXESUF)
check-qtest-ppc-y += tests/prom-env-test$(EXESUF) check-qtest-ppc-y += tests/prom-env-test$(EXESUF)
@ -358,6 +362,7 @@ check-qtest-arm-y += tests/virtio-blk-test$(EXESUF)
gcov-files-arm-y += arm-softmmu/hw/block/virtio-blk.c gcov-files-arm-y += arm-softmmu/hw/block/virtio-blk.c
check-qtest-arm-y += tests/test-arm-mptimer$(EXESUF) check-qtest-arm-y += tests/test-arm-mptimer$(EXESUF)
gcov-files-arm-y += hw/timer/arm_mptimer.c gcov-files-arm-y += hw/timer/arm_mptimer.c
check-qtest-arm-y += tests/boot-serial-test$(EXESUF)
check-qtest-aarch64-y = tests/numa-test$(EXESUF) check-qtest-aarch64-y = tests/numa-test$(EXESUF)

View File

@ -32,7 +32,7 @@ typedef struct {
do { \ do { \
memread(addr, &field, sizeof(field)); \ memread(addr, &field, sizeof(field)); \
addr += sizeof(field); \ addr += sizeof(field); \
} while (0); } while (0)
#define ACPI_READ_ARRAY_PTR(arr, length, addr) \ #define ACPI_READ_ARRAY_PTR(arr, length, addr) \
do { \ do { \
@ -40,7 +40,7 @@ typedef struct {
for (idx = 0; idx < length; ++idx) { \ for (idx = 0; idx < length; ++idx) { \
ACPI_READ_FIELD(arr[idx], addr); \ ACPI_READ_FIELD(arr[idx], addr); \
} \ } \
} while (0); } while (0)
#define ACPI_READ_ARRAY(arr, addr) \ #define ACPI_READ_ARRAY(arr, addr) \
ACPI_READ_ARRAY_PTR(arr, sizeof(arr) / sizeof(arr[0]), addr) ACPI_READ_ARRAY_PTR(arr, sizeof(arr) / sizeof(arr[0]), addr)
@ -56,7 +56,7 @@ typedef struct {
ACPI_READ_FIELD((table)->oem_revision, addr); \ ACPI_READ_FIELD((table)->oem_revision, addr); \
ACPI_READ_ARRAY((table)->asl_compiler_id, addr); \ ACPI_READ_ARRAY((table)->asl_compiler_id, addr); \
ACPI_READ_FIELD((table)->asl_compiler_revision, addr); \ ACPI_READ_FIELD((table)->asl_compiler_revision, addr); \
} while (0); } while (0)
#define ACPI_ASSERT_CMP(actual, expected) do { \ #define ACPI_ASSERT_CMP(actual, expected) do { \
char ACPI_ASSERT_CMP_str[5] = {}; \ char ACPI_ASSERT_CMP_str[5] = {}; \
@ -77,7 +77,7 @@ typedef struct {
ACPI_READ_FIELD((field).bit_offset, addr); \ ACPI_READ_FIELD((field).bit_offset, addr); \
ACPI_READ_FIELD((field).access_width, addr); \ ACPI_READ_FIELD((field).access_width, addr); \
ACPI_READ_FIELD((field).address, addr); \ ACPI_READ_FIELD((field).address, addr); \
} while (0); } while (0)
uint8_t acpi_calc_checksum(const uint8_t *data, int len); uint8_t acpi_calc_checksum(const uint8_t *data, int len);

View File

@ -24,6 +24,37 @@ static const uint8_t kernel_mcf5208[] = {
0x60, 0xfa /* bra.s loop */ 0x60, 0xfa /* bra.s loop */
}; };
static const uint8_t kernel_pls3adsp1800[] = {
0xb0, 0x00, 0x84, 0x00, /* imm 0x8400 */
0x30, 0x60, 0x00, 0x04, /* addik r3,r0,4 */
0x30, 0x80, 0x00, 0x54, /* addik r4,r0,'T' */
0xf0, 0x83, 0x00, 0x00, /* sbi r4,r3,0 */
0xb8, 0x00, 0xff, 0xfc /* bri -4 loop */
};
static const uint8_t kernel_plml605[] = {
0xe0, 0x83, 0x00, 0xb0, /* imm 0x83e0 */
0x00, 0x10, 0x60, 0x30, /* addik r3,r0,0x1000 */
0x54, 0x00, 0x80, 0x30, /* addik r4,r0,'T' */
0x00, 0x00, 0x83, 0xf0, /* sbi r4,r3,0 */
0xfc, 0xff, 0x00, 0xb8 /* bri -4 loop */
};
static const uint8_t bios_moxiesim[] = {
0x20, 0x10, 0x00, 0x00, 0x03, 0xf8, /* ldi.s r1,0x3f8 */
0x1b, 0x20, 0x00, 0x00, 0x00, 0x54, /* ldi.b r2,'T' */
0x1e, 0x12, /* st.b r1,r2 */
0x1a, 0x00, 0x00, 0x00, 0x10, 0x00 /* jmpa 0x1000 */
};
static const uint8_t bios_raspi2[] = {
0x08, 0x30, 0x9f, 0xe5, /* ldr r3,[pc,#8] Get base */
0x54, 0x20, 0xa0, 0xe3, /* mov r2,#'T' */
0x00, 0x20, 0xc3, 0xe5, /* strb r2,[r3] */
0xfb, 0xff, 0xff, 0xea, /* b loop */
0x00, 0x10, 0x20, 0x3f, /* 0x3f201000 = UART0 base addr */
};
typedef struct testdef { typedef struct testdef {
const char *arch; /* Target architecture */ const char *arch; /* Target architecture */
const char *machine; /* Name of the machine */ const char *machine; /* Name of the machine */
@ -50,6 +81,12 @@ static testdef_t tests[] = {
{ "s390x", "s390-ccw-virtio", { "s390x", "s390-ccw-virtio",
"-nodefaults -device sclpconsole,chardev=serial0", "virtio device" }, "-nodefaults -device sclpconsole,chardev=serial0", "virtio device" },
{ "m68k", "mcf5208evb", "", "TT", sizeof(kernel_mcf5208), kernel_mcf5208 }, { "m68k", "mcf5208evb", "", "TT", sizeof(kernel_mcf5208), kernel_mcf5208 },
{ "microblaze", "petalogix-s3adsp1800", "", "TT",
sizeof(kernel_pls3adsp1800), kernel_pls3adsp1800 },
{ "microblazeel", "petalogix-ml605", "", "TT",
sizeof(kernel_plml605), kernel_plml605 },
{ "moxie", "moxiesim", "", "TT", sizeof(bios_moxiesim), 0, bios_moxiesim },
{ "arm", "raspi2", "", "TT", sizeof(bios_raspi2), 0, bios_raspi2 },
{ NULL } { NULL }
}; };

View File

@ -59,6 +59,8 @@ static void do_test_equality(bool expected, int _, ...)
g_assert(qobject_is_equal(args[i], args[j]) == expected); g_assert(qobject_is_equal(args[i], args[j]) == expected);
} }
} }
g_free(args);
} }
#define check_equal(...) \ #define check_equal(...) \

View File

@ -3,7 +3,7 @@ ENV PACKAGES \
ccache gettext git tar PyYAML sparse flex bison python2 bzip2 hostname \ ccache gettext git tar PyYAML sparse flex bison python2 bzip2 hostname \
glib2-devel pixman-devel zlib-devel SDL-devel libfdt-devel \ glib2-devel pixman-devel zlib-devel SDL-devel libfdt-devel \
gcc gcc-c++ clang make perl which bc findutils libaio-devel \ gcc gcc-c++ clang make perl which bc findutils libaio-devel \
nettle-devel \ nettle-devel libasan libubsan \
mingw32-pixman mingw32-glib2 mingw32-gmp mingw32-SDL mingw32-pkg-config \ mingw32-pixman mingw32-glib2 mingw32-gmp mingw32-SDL mingw32-pkg-config \
mingw32-gtk2 mingw32-gtk3 mingw32-gnutls mingw32-nettle mingw32-libtasn1 \ mingw32-gtk2 mingw32-gtk3 mingw32-gnutls mingw32-nettle mingw32-libtasn1 \
mingw32-libjpeg-turbo mingw32-libpng mingw32-curl mingw32-libssh2 \ mingw32-libjpeg-turbo mingw32-libpng mingw32-curl mingw32-libssh2 \
@ -15,4 +15,4 @@ ENV PACKAGES \
RUN dnf install -y $PACKAGES RUN dnf install -y $PACKAGES
RUN rpm -q $PACKAGES | sort > /packages.txt RUN rpm -q $PACKAGES | sort > /packages.txt
ENV FEATURES mingw clang pyyaml ENV FEATURES mingw clang pyyaml asan

View File

@ -17,7 +17,7 @@ requires clang
cd "$BUILD_DIR" cd "$BUILD_DIR"
OPTS="--enable-debug --cxx=clang++ --cc=clang --host-cc=clang" OPTS="--cxx=clang++ --cc=clang --host-cc=clang"
# -fsanitize=undefined is broken on Fedora 23, skip it for now # -fsanitize=undefined is broken on Fedora 23, skip it for now
# See also: https://bugzilla.redhat.com/show_bug.cgi?id=1263834 # See also: https://bugzilla.redhat.com/show_bug.cgi?id=1263834
#OPTS="$OPTS --extra-cflags=-fsanitize=undefined \ #OPTS="$OPTS --extra-cflags=-fsanitize=undefined \

26
tests/docker/test-debug Executable file
View File

@ -0,0 +1,26 @@
#!/bin/bash -e
#
# Compile and check with clang & --enable-debug.
#
# Copyright (c) 2016-2018 Red Hat Inc.
#
# Authors:
# Fam Zheng <famz@redhat.com>
# Marc-André Lureau <marcandre.lureau@redhat.com>
#
# This work is licensed under the terms of the GNU GPL, version 2
# or (at your option) any later version. See the COPYING file in
# the top-level directory.
. common.rc
requires clang asan
cd "$BUILD_DIR"
OPTS="--cxx=clang++ --cc=clang --host-cc=clang"
OPTS="--enable-debug $OPTS"
build_qemu $OPTS
make $MAKEFLAGS check
install_qemu

View File

@ -22,7 +22,6 @@ for prefix in x86_64-w64-mingw32- i686-w64-mingw32-; do
TARGET_LIST=${TARGET_LIST:-$DEF_TARGET_LIST} \ TARGET_LIST=${TARGET_LIST:-$DEF_TARGET_LIST} \
build_qemu --cross-prefix=$prefix \ build_qemu --cross-prefix=$prefix \
--enable-trace-backends=simple \ --enable-trace-backends=simple \
--enable-debug \
--enable-gnutls \ --enable-gnutls \
--enable-nettle \ --enable-nettle \
--enable-curl \ --enable-curl \
@ -35,4 +34,3 @@ for prefix in x86_64-w64-mingw32- i686-w64-mingw32-; do
make clean make clean
done done

View File

@ -271,7 +271,7 @@ static void add_query_tests(QmpSchema *schema)
{ {
SchemaInfoList *tail; SchemaInfoList *tail;
SchemaInfo *si, *arg_type, *ret_type; SchemaInfo *si, *arg_type, *ret_type;
const char *test_name; char *test_name;
/* Test the query-like commands */ /* Test the query-like commands */
for (tail = schema->list; tail; tail = tail->next) { for (tail = schema->list; tail; tail = tail->next) {
@ -297,6 +297,7 @@ static void add_query_tests(QmpSchema *schema)
test_name = g_strdup_printf("qmp/%s", si->name); test_name = g_strdup_printf("qmp/%s", si->name);
qtest_add_data_func(test_name, si->name, test_query); qtest_add_data_func(test_name, si->name, test_query);
g_free(test_name);
} }
} }

View File

@ -39,7 +39,7 @@ do \
fprintf (stderr, "FAILED at %s:%d\n", __FILE__, __LINE__); \ fprintf (stderr, "FAILED at %s:%d\n", __FILE__, __LINE__); \
exit (EXIT_FAILURE); \ exit (EXIT_FAILURE); \
} \ } \
} while (0); } while (0)
unsigned char *dummybuf; unsigned char *dummybuf;
static unsigned int pagesize; static unsigned int pagesize;

View File

@ -67,7 +67,6 @@ static void coroutine_fn verify_entered_step_2(void *opaque)
/* Once more to check it still works after yielding */ /* Once more to check it still works after yielding */
g_assert(qemu_coroutine_entered(caller)); g_assert(qemu_coroutine_entered(caller));
g_assert(qemu_coroutine_entered(qemu_coroutine_self())); g_assert(qemu_coroutine_entered(qemu_coroutine_self()));
qemu_coroutine_yield();
} }
static void coroutine_fn verify_entered_step_1(void *opaque) static void coroutine_fn verify_entered_step_1(void *opaque)

View File

@ -283,7 +283,7 @@ vubr_backend_recv_cb(int sock, void *ctx)
return; return;
} }
do { while (1) {
struct iovec *sg; struct iovec *sg;
ssize_t ret, total = 0; ssize_t ret, total = 0;
unsigned int num; unsigned int num;
@ -343,7 +343,9 @@ vubr_backend_recv_cb(int sock, void *ctx)
free(elem); free(elem);
elem = NULL; elem = NULL;
} while (false); /* could loop if DONTWAIT worked? */
break; /* could loop if DONTWAIT worked? */
}
if (mhdr_cnt) { if (mhdr_cnt) {
mhdr.num_buffers = i; mhdr.num_buffers = i;

View File

@ -55,6 +55,10 @@ dma_complete(void *dbs, int ret, void *cb) "dbs=%p ret=%d cb=%p"
dma_blk_cb(void *dbs, int ret) "dbs=%p ret=%d" dma_blk_cb(void *dbs, int ret) "dbs=%p ret=%d"
dma_map_wait(void *dbs) "dbs=%p" dma_map_wait(void *dbs) "dbs=%p"
# # exec.c
find_ram_offset(uint64_t size, uint64_t offset) "size: 0x%" PRIx64 " @ 0x%" PRIx64
find_ram_offset_loop(uint64_t size, uint64_t candidate, uint64_t offset, uint64_t next, uint64_t mingap) "trying size: 0x%" PRIx64 " @ 0x%" PRIx64 ", offset: 0x%" PRIx64" next: 0x%" PRIx64 " mingap: 0x%" PRIx64
# memory.c # memory.c
memory_region_ops_read(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u" memory_region_ops_read(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
memory_region_ops_write(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u" memory_region_ops_write(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"

View File

@ -34,22 +34,22 @@
#define setRed(r, pcolor) do { \ #define setRed(r, pcolor) do { \
*pcolor = ((*pcolor) & (~(dpf->Rmask))) + \ *pcolor = ((*pcolor) & (~(dpf->Rmask))) + \
(((r) & (dpf->Rmask >> dpf->Rshift)) << dpf->Rshift); \ (((r) & (dpf->Rmask >> dpf->Rshift)) << dpf->Rshift); \
} while (0); } while (0)
#define setGreen(g, pcolor) do { \ #define setGreen(g, pcolor) do { \
*pcolor = ((*pcolor) & (~(dpf->Gmask))) + \ *pcolor = ((*pcolor) & (~(dpf->Gmask))) + \
(((g) & (dpf->Gmask >> dpf->Gshift)) << dpf->Gshift); \ (((g) & (dpf->Gmask >> dpf->Gshift)) << dpf->Gshift); \
} while (0); } while (0)
#define setBlue(b, pcolor) do { \ #define setBlue(b, pcolor) do { \
*pcolor = ((*pcolor) & (~(dpf->Bmask))) + \ *pcolor = ((*pcolor) & (~(dpf->Bmask))) + \
(((b) & (dpf->Bmask >> dpf->Bshift)) << dpf->Bshift); \ (((b) & (dpf->Bmask >> dpf->Bshift)) << dpf->Bshift); \
} while (0); } while (0)
#define setAlpha(a, pcolor) do { \ #define setAlpha(a, pcolor) do { \
*pcolor = ((*pcolor) & (~(dpf->Amask))) + \ *pcolor = ((*pcolor) & (~(dpf->Amask))) + \
(((a) & (dpf->Amask >> dpf->Ashift)) << dpf->Ashift); \ (((a) & (dpf->Amask >> dpf->Ashift)) << dpf->Ashift); \
} while (0); } while (0)
static void glue(sdl_zoom_rgb, BPP)(SDL_Surface *src, SDL_Surface *dst, int smooth, static void glue(sdl_zoom_rgb, BPP)(SDL_Surface *src, SDL_Surface *dst, int smooth,
SDL_Rect *dst_rect) SDL_Rect *dst_rect)

View File

@ -105,7 +105,8 @@ static void cleanup_infolist(CommandLineParameterInfoList *head)
if (!strcmp(pre_entry->value->name, cur->next->value->name)) { if (!strcmp(pre_entry->value->name, cur->next->value->name)) {
del_entry = cur->next; del_entry = cur->next;
cur->next = cur->next->next; cur->next = cur->next->next;
g_free(del_entry); del_entry->next = NULL;
qapi_free_CommandLineParameterInfoList(del_entry);
break; break;
} }
pre_entry = pre_entry->next; pre_entry = pre_entry->next;

View File

@ -57,26 +57,28 @@ void qemu_mutex_destroy(QemuMutex *mutex)
error_exit(err, __func__); error_exit(err, __func__);
} }
void qemu_mutex_lock(QemuMutex *mutex) void qemu_mutex_lock_impl(QemuMutex *mutex, const char *file, const int line)
{ {
int err; int err;
assert(mutex->initialized); assert(mutex->initialized);
trace_qemu_mutex_lock(mutex, file, line);
err = pthread_mutex_lock(&mutex->lock); err = pthread_mutex_lock(&mutex->lock);
if (err) if (err)
error_exit(err, __func__); error_exit(err, __func__);
trace_qemu_mutex_locked(mutex); trace_qemu_mutex_locked(mutex, file, line);
} }
int qemu_mutex_trylock(QemuMutex *mutex) int qemu_mutex_trylock_impl(QemuMutex *mutex, const char *file, const int line)
{ {
int err; int err;
assert(mutex->initialized); assert(mutex->initialized);
err = pthread_mutex_trylock(&mutex->lock); err = pthread_mutex_trylock(&mutex->lock);
if (err == 0) { if (err == 0) {
trace_qemu_mutex_locked(mutex); trace_qemu_mutex_locked(mutex, file, line);
return 0; return 0;
} }
if (err != EBUSY) { if (err != EBUSY) {
@ -85,15 +87,16 @@ int qemu_mutex_trylock(QemuMutex *mutex)
return -EBUSY; return -EBUSY;
} }
void qemu_mutex_unlock(QemuMutex *mutex) void qemu_mutex_unlock_impl(QemuMutex *mutex, const char *file, const int line)
{ {
int err; int err;
assert(mutex->initialized); assert(mutex->initialized);
trace_qemu_mutex_unlocked(mutex);
err = pthread_mutex_unlock(&mutex->lock); err = pthread_mutex_unlock(&mutex->lock);
if (err) if (err)
error_exit(err, __func__); error_exit(err, __func__);
trace_qemu_mutex_unlock(mutex, file, line);
} }
void qemu_rec_mutex_init(QemuRecMutex *mutex) void qemu_rec_mutex_init(QemuRecMutex *mutex)
@ -152,14 +155,14 @@ void qemu_cond_broadcast(QemuCond *cond)
error_exit(err, __func__); error_exit(err, __func__);
} }
void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex) void qemu_cond_wait_impl(QemuCond *cond, QemuMutex *mutex, const char *file, const int line)
{ {
int err; int err;
assert(cond->initialized); assert(cond->initialized);
trace_qemu_mutex_unlocked(mutex); trace_qemu_mutex_unlock(mutex, file, line);
err = pthread_cond_wait(&cond->cond, &mutex->lock); err = pthread_cond_wait(&cond->cond, &mutex->lock);
trace_qemu_mutex_locked(mutex); trace_qemu_mutex_locked(mutex, file, line);
if (err) if (err)
error_exit(err, __func__); error_exit(err, __func__);
} }

View File

@ -56,30 +56,32 @@ void qemu_mutex_destroy(QemuMutex *mutex)
InitializeSRWLock(&mutex->lock); InitializeSRWLock(&mutex->lock);
} }
void qemu_mutex_lock(QemuMutex *mutex) void qemu_mutex_lock_impl(QemuMutex *mutex, const char *file, const int line)
{ {
assert(mutex->initialized); assert(mutex->initialized);
trace_qemu_mutex_lock(mutex, file, line);
AcquireSRWLockExclusive(&mutex->lock); AcquireSRWLockExclusive(&mutex->lock);
trace_qemu_mutex_locked(mutex); trace_qemu_mutex_locked(mutex, file, line);
} }
int qemu_mutex_trylock(QemuMutex *mutex) int qemu_mutex_trylock_impl(QemuMutex *mutex, const char *file, const int line)
{ {
int owned; int owned;
assert(mutex->initialized); assert(mutex->initialized);
owned = TryAcquireSRWLockExclusive(&mutex->lock); owned = TryAcquireSRWLockExclusive(&mutex->lock);
if (owned) { if (owned) {
trace_qemu_mutex_locked(mutex); trace_qemu_mutex_locked(mutex, file, line);
return 0; return 0;
} }
return -EBUSY; return -EBUSY;
} }
void qemu_mutex_unlock(QemuMutex *mutex) void qemu_mutex_unlock_impl(QemuMutex *mutex, const char *file, const int line)
{ {
assert(mutex->initialized); assert(mutex->initialized);
trace_qemu_mutex_unlocked(mutex); trace_qemu_mutex_unlock(mutex, file, line);
ReleaseSRWLockExclusive(&mutex->lock); ReleaseSRWLockExclusive(&mutex->lock);
} }
@ -140,12 +142,12 @@ void qemu_cond_broadcast(QemuCond *cond)
WakeAllConditionVariable(&cond->var); WakeAllConditionVariable(&cond->var);
} }
void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex) void qemu_cond_wait_impl(QemuCond *cond, QemuMutex *mutex, const char *file, const int line)
{ {
assert(cond->initialized); assert(cond->initialized);
trace_qemu_mutex_unlocked(mutex); trace_qemu_mutex_unlock(mutex, file, line);
SleepConditionVariableSRW(&cond->var, &mutex->lock, INFINITE, 0); SleepConditionVariableSRW(&cond->var, &mutex->lock, INFINITE, 0);
trace_qemu_mutex_locked(mutex); trace_qemu_mutex_locked(mutex, file, line);
} }
void qemu_sem_init(QemuSemaphore *sem, int init) void qemu_sem_init(QemuSemaphore *sem, int init)

View File

@ -500,12 +500,28 @@ const char *readline_get_history(ReadLineState *rs, unsigned int index)
return rs->history[index]; return rs->history[index];
} }
void readline_free(ReadLineState *rs)
{
int i;
if (!rs) {
return;
}
for (i = 0; i < READLINE_MAX_CMDS; i++) {
g_free(rs->history[i]);
}
for (i = 0; i < READLINE_MAX_COMPLETIONS; i++) {
g_free(rs->completions[i]);
}
g_free(rs);
}
ReadLineState *readline_init(ReadLinePrintfFunc *printf_func, ReadLineState *readline_init(ReadLinePrintfFunc *printf_func,
ReadLineFlushFunc *flush_func, ReadLineFlushFunc *flush_func,
void *opaque, void *opaque,
ReadLineCompletionFunc *completion_finder) ReadLineCompletionFunc *completion_finder)
{ {
ReadLineState *rs = g_malloc0(sizeof(*rs)); ReadLineState *rs = g_new0(ReadLineState, 1);
rs->hist_entry = -1; rs->hist_entry = -1;
rs->opaque = opaque; rs->opaque = opaque;

View File

@ -56,6 +56,7 @@ lockcnt_futex_wait(const void *lockcnt, int val) "lockcnt %p waiting on %d"
lockcnt_futex_wait_resume(const void *lockcnt, int new) "lockcnt %p after wait: %d" lockcnt_futex_wait_resume(const void *lockcnt, int new) "lockcnt %p after wait: %d"
lockcnt_futex_wake(const void *lockcnt) "lockcnt %p waking up one waiter" lockcnt_futex_wake(const void *lockcnt) "lockcnt %p waking up one waiter"
# util/qemu-thread-posix.c # util/qemu-thread.c
qemu_mutex_locked(void *lock) "locked mutex %p" qemu_mutex_lock(void *mutex, const char *file, const int line) "waiting on mutex %p (%s:%d)"
qemu_mutex_unlocked(void *lock) "unlocked mutex %p" qemu_mutex_locked(void *mutex, const char *file, const int line) "taken mutex %p (%s:%d)"
qemu_mutex_unlock(void *mutex, const char *file, const int line) "released mutex %p (%s:%d)"

9
vl.c
View File

@ -2318,7 +2318,7 @@ static void qemu_add_data_dir(const char *path)
return; /* duplicate */ return; /* duplicate */
} }
} }
data_dir[data_dir_idx++] = path; data_dir[data_dir_idx++] = g_strdup(path);
} }
static inline bool nonempty_str(const char *str) static inline bool nonempty_str(const char *str)
@ -3078,7 +3078,7 @@ int main(int argc, char **argv, char **envp)
Error *main_loop_err = NULL; Error *main_loop_err = NULL;
Error *err = NULL; Error *err = NULL;
bool list_data_dirs = false; bool list_data_dirs = false;
char **dirs; char *dir, **dirs;
typedef struct BlockdevOptions_queue { typedef struct BlockdevOptions_queue {
BlockdevOptions *bdo; BlockdevOptions *bdo;
Location loc; Location loc;
@ -4181,9 +4181,12 @@ int main(int argc, char **argv, char **envp)
for (i = 0; dirs[i] != NULL; i++) { for (i = 0; dirs[i] != NULL; i++) {
qemu_add_data_dir(dirs[i]); qemu_add_data_dir(dirs[i]);
} }
g_strfreev(dirs);
/* try to find datadir relative to the executable path */ /* try to find datadir relative to the executable path */
qemu_add_data_dir(os_find_datadir()); dir = os_find_datadir();
qemu_add_data_dir(dir);
g_free(dir);
/* add the datadir specified when building */ /* add the datadir specified when building */
qemu_add_data_dir(CONFIG_QEMU_DATADIR); qemu_add_data_dir(CONFIG_QEMU_DATADIR);