mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 15:23:53 -06:00
* 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:
commit
3788c7b6e5
117 changed files with 1952 additions and 728 deletions
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue