* Record-replay lockstep execution, log dumper and fixes (Alex, Pavel)

* SCSI fix to pass maximum transfer size (Daniel Barboza)
 * chardev fixes and improved iothread support (Daniel Berrangé, Peter)
 * checkpatch tweak (Eric)
 * make help tweak (Marc-André)
 * make more PCI NICs available with -net or -nic (myself)
 * change default q35 NIC to e1000e (myself)
 * SCSI support for NDOB bit (myself)
 * membarrier system call support (myself)
 * SuperIO refactoring (Philippe)
 * miscellaneous cleanups and fixes (Thomas)
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQEcBAABAgAGBQJapqaMAAoJEL/70l94x66DQoUH/Rvg+a8giz/SrEA4P8D3Cb2z
 4GNbNUUoy4oU0ltD5IAMskMwpOsvl1batE0D+pKIlfO9NV4+Cj2kpgo0p9TxoYqM
 VCby3wRtx27zb5nVytC6M++iIKXmeEMqXmFw61I6umddNPSl4IR3hiHEE0DM+7dV
 UPIOvJeEiazyQaw3Iw+ZctNn8dDBKc/+6oxP9xRcYTaZ6hB4G9RZkqGNNSLcJkk7
 R0UotdjzIZhyWMOkjIwlpTF4sWv8gsYUV4bPYKMYho5B0Obda2dBM3I1kpA8yDa/
 xZ5lheOaAVBZvM5aMIcaQPa65MO9hLyXFmhMOgyfpJhLBBz6Qpa4OLLI6DeTN+0=
 =UAgA
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging

* Record-replay lockstep execution, log dumper and fixes (Alex, Pavel)
* SCSI fix to pass maximum transfer size (Daniel Barboza)
* chardev fixes and improved iothread support (Daniel Berrangé, Peter)
* checkpatch tweak (Eric)
* make help tweak (Marc-André)
* make more PCI NICs available with -net or -nic (myself)
* change default q35 NIC to e1000e (myself)
* SCSI support for NDOB bit (myself)
* membarrier system call support (myself)
* SuperIO refactoring (Philippe)
* miscellaneous cleanups and fixes (Thomas)

# gpg: Signature made Mon 12 Mar 2018 16:10:52 GMT
# gpg:                using RSA key BFFBD25F78C7AE83
# 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: (69 commits)
  tcg: fix cpu_io_recompile
  replay: update documentation
  replay: save vmstate of the asynchronous events
  replay: don't process async events when warping the clock
  scripts/replay-dump.py: replay log dumper
  replay: avoid recursive call of checkpoints
  replay: check return values of fwrite
  replay: push replay_mutex_lock up the call tree
  replay: don't destroy mutex at exit
  replay: make locking visible outside replay code
  replay/replay-internal.c: track holding of replay_lock
  replay/replay.c: bump REPLAY_VERSION again
  replay: save prior value of the host clock
  replay: added replay log format description
  replay: fix save/load vm for non-empty queue
  replay: fixed replay_enable_events
  replay: fix processing async events
  cpu-exec: fix exception_index handling
  hw/i386/pc: Factor out the superio code
  hw/alpha/dp264: Use the TYPE_SMC37C669_SUPERIO
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

# Conflicts:
#	default-configs/i386-softmmu.mak
#	default-configs/x86_64-softmmu.mak
This commit is contained in:
Peter Maydell 2018-03-16 11:05:03 +00:00
commit 3788c7b6e5
117 changed files with 1952 additions and 728 deletions

View file

@ -40,6 +40,11 @@
#define TCP_MAX_FDS 16
typedef struct {
char buf[21];
size_t buflen;
} TCPChardevTelnetInit;
typedef struct {
Chardev parent;
QIOChannel *ioc; /* Client I/O channel */
@ -60,6 +65,8 @@ typedef struct {
bool is_listen;
bool is_telnet;
bool is_tn3270;
GSource *telnet_source;
TCPChardevTelnetInit *telnet_init;
GSource *reconnect_timer;
int64_t reconnect_time;
@ -70,6 +77,7 @@ typedef struct {
OBJECT_CHECK(SocketChardev, (obj), TYPE_CHARDEV_SOCKET)
static gboolean socket_reconnect_timeout(gpointer opaque);
static void tcp_chr_telnet_init(Chardev *chr);
static void tcp_chr_reconn_timer_cancel(SocketChardev *s)
{
@ -423,8 +431,8 @@ static void tcp_chr_disconnect(Chardev *chr)
tcp_chr_free_connection(chr);
if (s->listener) {
qio_net_listener_set_client_func(s->listener, tcp_chr_accept,
chr, NULL);
qio_net_listener_set_client_func_full(s->listener, tcp_chr_accept,
chr, NULL, chr->gcontext);
}
update_disconnected_filename(s);
if (emit_close) {
@ -450,7 +458,7 @@ static gboolean tcp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
len = s->max_size;
}
size = tcp_chr_recv(chr, (void *)buf, len);
if (size == 0 || size == -1) {
if (size == 0 || (size == -1 && errno != EAGAIN)) {
/* connection closed */
tcp_chr_disconnect(chr);
} else if (size > 0) {
@ -556,10 +564,33 @@ static void tcp_chr_connect(void *opaque)
qemu_chr_be_event(chr, CHR_EVENT_OPENED);
}
static void tcp_chr_telnet_destroy(SocketChardev *s)
{
if (s->telnet_source) {
g_source_destroy(s->telnet_source);
g_source_unref(s->telnet_source);
s->telnet_source = NULL;
}
}
static void tcp_chr_update_read_handler(Chardev *chr)
{
SocketChardev *s = SOCKET_CHARDEV(chr);
if (s->listener) {
/*
* It's possible that chardev context is changed in
* qemu_chr_be_update_read_handlers(). Reset it for QIO net
* listener if there is.
*/
qio_net_listener_set_client_func_full(s->listener, tcp_chr_accept,
chr, NULL, chr->gcontext);
}
if (s->telnet_source) {
tcp_chr_telnet_init(CHARDEV(s));
}
if (!s->connected) {
return;
}
@ -573,32 +604,30 @@ static void tcp_chr_update_read_handler(Chardev *chr)
}
}
typedef struct {
Chardev *chr;
char buf[21];
size_t buflen;
} TCPChardevTelnetInit;
static gboolean tcp_chr_telnet_init_io(QIOChannel *ioc,
GIOCondition cond G_GNUC_UNUSED,
gpointer user_data)
{
TCPChardevTelnetInit *init = user_data;
SocketChardev *s = user_data;
Chardev *chr = CHARDEV(s);
TCPChardevTelnetInit *init = s->telnet_init;
ssize_t ret;
assert(init);
ret = qio_channel_write(ioc, init->buf, init->buflen, NULL);
if (ret < 0) {
if (ret == QIO_CHANNEL_ERR_BLOCK) {
ret = 0;
} else {
tcp_chr_disconnect(init->chr);
tcp_chr_disconnect(chr);
goto end;
}
}
init->buflen -= ret;
if (init->buflen == 0) {
tcp_chr_connect(init->chr);
tcp_chr_connect(chr);
goto end;
}
@ -607,16 +636,30 @@ static gboolean tcp_chr_telnet_init_io(QIOChannel *ioc,
return G_SOURCE_CONTINUE;
end:
g_free(init);
g_free(s->telnet_init);
s->telnet_init = NULL;
g_source_unref(s->telnet_source);
s->telnet_source = NULL;
return G_SOURCE_REMOVE;
}
static void tcp_chr_telnet_init(Chardev *chr)
{
SocketChardev *s = SOCKET_CHARDEV(chr);
TCPChardevTelnetInit *init = g_new0(TCPChardevTelnetInit, 1);
TCPChardevTelnetInit *init;
size_t n = 0;
/* Destroy existing task */
tcp_chr_telnet_destroy(s);
if (s->telnet_init) {
/* We are possibly during a handshake already */
goto cont;
}
s->telnet_init = g_new0(TCPChardevTelnetInit, 1);
init = s->telnet_init;
#define IACSET(x, a, b, c) \
do { \
x[n++] = a; \
@ -624,7 +667,6 @@ static void tcp_chr_telnet_init(Chardev *chr)
x[n++] = c; \
} while (0)
init->chr = chr;
if (!s->is_tn3270) {
init->buflen = 12;
/* Prep the telnet negotion to put telnet in binary,
@ -647,10 +689,11 @@ static void tcp_chr_telnet_init(Chardev *chr)
#undef IACSET
qio_channel_add_watch(
s->ioc, G_IO_OUT,
tcp_chr_telnet_init_io,
init, NULL);
cont:
s->telnet_source = qio_channel_add_watch_source(s->ioc, G_IO_OUT,
tcp_chr_telnet_init_io,
s, NULL,
chr->gcontext);
}
@ -707,7 +750,7 @@ static void tcp_chr_tls_init(Chardev *chr)
tcp_chr_tls_handshake,
chr,
NULL,
NULL);
chr->gcontext);
}
@ -743,7 +786,8 @@ static int tcp_chr_new_client(Chardev *chr, QIOChannelSocket *sioc)
qio_channel_set_delay(s->ioc, false);
}
if (s->listener) {
qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL);
qio_net_listener_set_client_func_full(s->listener, NULL, NULL,
NULL, chr->gcontext);
}
if (s->tls_creds) {
@ -823,8 +867,11 @@ static void char_socket_finalize(Object *obj)
tcp_chr_free_connection(chr);
tcp_chr_reconn_timer_cancel(s);
qapi_free_SocketAddress(s->addr);
tcp_chr_telnet_destroy(s);
g_free(s->telnet_init);
if (s->listener) {
qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL);
qio_net_listener_set_client_func_full(s->listener, NULL, NULL,
NULL, chr->gcontext);
object_unref(OBJECT(s->listener));
}
if (s->tls_creds) {
@ -854,11 +901,22 @@ cleanup:
object_unref(OBJECT(sioc));
}
static void tcp_chr_connect_async(Chardev *chr)
{
SocketChardev *s = SOCKET_CHARDEV(chr);
QIOChannelSocket *sioc;
sioc = qio_channel_socket_new();
tcp_chr_set_client_ioc_name(chr, sioc);
qio_channel_socket_connect_async(sioc, s->addr,
qemu_chr_socket_connected,
chr, NULL, chr->gcontext);
}
static gboolean socket_reconnect_timeout(gpointer opaque)
{
Chardev *chr = CHARDEV(opaque);
SocketChardev *s = SOCKET_CHARDEV(opaque);
QIOChannelSocket *sioc;
g_source_unref(s->reconnect_timer);
s->reconnect_timer = NULL;
@ -867,11 +925,7 @@ static gboolean socket_reconnect_timeout(gpointer opaque)
return false;
}
sioc = qio_channel_socket_new();
tcp_chr_set_client_ioc_name(chr, sioc);
qio_channel_socket_connect_async(sioc, s->addr,
qemu_chr_socket_connected,
chr, NULL, NULL);
tcp_chr_connect_async(chr);
return false;
}
@ -950,13 +1004,8 @@ static void qmp_chardev_open_socket(Chardev *chr,
s->reconnect_time = reconnect;
}
if (s->reconnect_time) {
sioc = qio_channel_socket_new();
tcp_chr_set_client_ioc_name(chr, sioc);
qio_channel_socket_connect_async(sioc, s->addr,
qemu_chr_socket_connected,
chr, NULL, NULL);
} else {
/* If reconnect_time is set, will do that in chr_machine_done. */
if (!s->reconnect_time) {
if (s->is_listen) {
char *name;
s->listener = qio_net_listener_new();
@ -980,8 +1029,10 @@ static void qmp_chardev_open_socket(Chardev *chr,
return;
}
if (!s->ioc) {
qio_net_listener_set_client_func(s->listener, tcp_chr_accept,
chr, NULL);
qio_net_listener_set_client_func_full(s->listener,
tcp_chr_accept,
chr, NULL,
chr->gcontext);
}
} else if (qemu_chr_wait_connected(chr, errp) < 0) {
goto error;
@ -1103,6 +1154,17 @@ char_socket_get_connected(Object *obj, Error **errp)
return s->connected;
}
static int tcp_chr_machine_done_hook(Chardev *chr)
{
SocketChardev *s = SOCKET_CHARDEV(chr);
if (s->reconnect_time) {
tcp_chr_connect_async(chr);
}
return 0;
}
static void char_socket_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
@ -1118,6 +1180,7 @@ static void char_socket_class_init(ObjectClass *oc, void *data)
cc->chr_add_client = tcp_chr_add_client;
cc->chr_add_watch = tcp_chr_add_watch;
cc->chr_update_read_handler = tcp_chr_update_read_handler;
cc->chr_machine_done = tcp_chr_machine_done_hook;
object_class_property_add(oc, "addr", "SocketAddress",
char_socket_get_addr, NULL,