2007-11-17 20:14:51 +03:00
|
|
|
#ifndef QEMU_CHAR_H
|
|
|
|
#define QEMU_CHAR_H
|
|
|
|
|
2009-03-06 02:01:23 +03:00
|
|
|
#include "qemu-common.h"
|
2012-12-17 21:20:00 +04:00
|
|
|
#include "qemu/option.h"
|
|
|
|
#include "qemu/main-loop.h"
|
net: don't poke at chardev internal QemuOpts
The vhost-user & colo code is poking at the QemuOpts instance
in the CharDriverState struct, not realizing that it is valid
for this to be NULL. e.g. the following crash shows a codepath
where it will be NULL:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x000055baf6ab4adc in qemu_opt_foreach (opts=0x0, func=0x55baf696b650 <net_vhost_chardev_opts>, opaque=0x7ffc51368c00, errp=0x7ffc51368e48) at util/qemu-option.c:617
617 QTAILQ_FOREACH(opt, &opts->head, next) {
[Current thread is 1 (Thread 0x7f1d4970bb40 (LWP 6603))]
(gdb) bt
#0 0x000055baf6ab4adc in qemu_opt_foreach (opts=0x0, func=0x55baf696b650 <net_vhost_chardev_opts>, opaque=0x7ffc51368c00, errp=0x7ffc51368e48) at util/qemu-option.c:617
#1 0x000055baf696b7da in net_vhost_parse_chardev (opts=0x55baf8ff9260, errp=0x7ffc51368e48) at net/vhost-user.c:314
#2 0x000055baf696b985 in net_init_vhost_user (netdev=0x55baf8ff9250, name=0x55baf879d270 "hostnet2", peer=0x0, errp=0x7ffc51368e48) at net/vhost-user.c:360
#3 0x000055baf6960216 in net_client_init1 (object=0x55baf8ff9250, is_netdev=true, errp=0x7ffc51368e48) at net/net.c:1051
#4 0x000055baf6960518 in net_client_init (opts=0x55baf776e7e0, is_netdev=true, errp=0x7ffc51368f00) at net/net.c:1108
#5 0x000055baf696083f in netdev_add (opts=0x55baf776e7e0, errp=0x7ffc51368f00) at net/net.c:1186
#6 0x000055baf69608c7 in qmp_netdev_add (qdict=0x55baf7afaf60, ret=0x7ffc51368f50, errp=0x7ffc51368f48) at net/net.c:1205
#7 0x000055baf6622135 in handle_qmp_command (parser=0x55baf77fb590, tokens=0x7f1d24011960) at /path/to/qemu.git/monitor.c:3978
#8 0x000055baf6a9d099 in json_message_process_token (lexer=0x55baf77fb598, input=0x55baf75acd20, type=JSON_RCURLY, x=113, y=19) at qobject/json-streamer.c:105
#9 0x000055baf6abf7aa in json_lexer_feed_char (lexer=0x55baf77fb598, ch=125 '}', flush=false) at qobject/json-lexer.c:319
#10 0x000055baf6abf8f2 in json_lexer_feed (lexer=0x55baf77fb598, buffer=0x7ffc51369170 "}R\204\367\272U", size=1) at qobject/json-lexer.c:369
#11 0x000055baf6a9d13c in json_message_parser_feed (parser=0x55baf77fb590, buffer=0x7ffc51369170 "}R\204\367\272U", size=1) at qobject/json-streamer.c:124
#12 0x000055baf66221f7 in monitor_qmp_read (opaque=0x55baf77fb530, buf=0x7ffc51369170 "}R\204\367\272U", size=1) at /path/to/qemu.git/monitor.c:3994
#13 0x000055baf6757014 in qemu_chr_be_write_impl (s=0x55baf7610a40, buf=0x7ffc51369170 "}R\204\367\272U", len=1) at qemu-char.c:387
#14 0x000055baf6757076 in qemu_chr_be_write (s=0x55baf7610a40, buf=0x7ffc51369170 "}R\204\367\272U", len=1) at qemu-char.c:399
#15 0x000055baf675b3b0 in tcp_chr_read (chan=0x55baf90244b0, cond=G_IO_IN, opaque=0x55baf7610a40) at qemu-char.c:2927
#16 0x000055baf6a5d655 in qio_channel_fd_source_dispatch (source=0x55baf7610df0, callback=0x55baf675b25a <tcp_chr_read>, user_data=0x55baf7610a40) at io/channel-watch.c:84
#17 0x00007f1d3e80cbbd in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0
#18 0x000055baf69d3720 in glib_pollfds_poll () at main-loop.c:213
#19 0x000055baf69d37fd in os_host_main_loop_wait (timeout=126000000) at main-loop.c:258
#20 0x000055baf69d38ad in main_loop_wait (nonblocking=0) at main-loop.c:506
#21 0x000055baf676587b in main_loop () at vl.c:1908
#22 0x000055baf676d3bf in main (argc=101, argv=0x7ffc5136a6c8, envp=0x7ffc5136a9f8) at vl.c:4604
(gdb) p opts
$1 = (QemuOpts *) 0x0
The crash occurred when attaching vhost-user net via QMP:
{
"execute": "chardev-add",
"arguments": {
"id": "charnet2",
"backend": {
"type": "socket",
"data": {
"addr": {
"type": "unix",
"data": {
"path": "/var/run/openvswitch/vhost-user1"
}
},
"wait": false,
"server": false
}
}
},
"id": "libvirt-19"
}
{
"return": {
},
"id": "libvirt-19"
}
{
"execute": "netdev_add",
"arguments": {
"type": "vhost-user",
"chardev": "charnet2",
"id": "hostnet2"
},
"id": "libvirt-20"
}
Code using chardevs should not be poking at the internals of the
CharDriverState struct. What vhost-user wants is a chardev that is
operating as reconnectable network service, along with the ability
to do FD passing over the connection. The colo code simply wants
a network service. Add a feature concept to the char drivers so
that chardev users can query the actual features they wish to have
supported. The QemuOpts member is removed to prevent future mistakes
in this area.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2016-10-07 15:18:34 +03:00
|
|
|
#include "qemu/bitmap.h"
|
2016-12-07 18:39:10 +03:00
|
|
|
#include "qom/object.h"
|
2009-03-06 02:01:23 +03:00
|
|
|
|
2007-11-17 20:14:51 +03:00
|
|
|
/* character device */
|
|
|
|
|
2016-10-22 13:09:39 +03:00
|
|
|
typedef enum {
|
|
|
|
CHR_EVENT_BREAK, /* serial break char */
|
|
|
|
CHR_EVENT_OPENED, /* new connection established */
|
|
|
|
CHR_EVENT_MUX_IN, /* mux-focus was set to this terminal */
|
|
|
|
CHR_EVENT_MUX_OUT, /* mux-focus will move on */
|
|
|
|
CHR_EVENT_CLOSED /* connection closed */
|
|
|
|
} QEMUChrEvent;
|
2007-11-17 20:14:51 +03:00
|
|
|
|
2016-12-12 16:39:35 +03:00
|
|
|
#define CHR_READ_BUF_LEN 4096
|
2007-11-17 20:14:51 +03:00
|
|
|
|
|
|
|
#define CHR_IOCTL_SERIAL_SET_PARAMS 1
|
|
|
|
typedef struct {
|
|
|
|
int speed;
|
|
|
|
int parity;
|
|
|
|
int data_bits;
|
|
|
|
int stop_bits;
|
|
|
|
} QEMUSerialSetParams;
|
|
|
|
|
|
|
|
#define CHR_IOCTL_SERIAL_SET_BREAK 2
|
|
|
|
|
|
|
|
#define CHR_IOCTL_PP_READ_DATA 3
|
|
|
|
#define CHR_IOCTL_PP_WRITE_DATA 4
|
|
|
|
#define CHR_IOCTL_PP_READ_CONTROL 5
|
|
|
|
#define CHR_IOCTL_PP_WRITE_CONTROL 6
|
|
|
|
#define CHR_IOCTL_PP_READ_STATUS 7
|
|
|
|
#define CHR_IOCTL_PP_EPP_READ_ADDR 8
|
|
|
|
#define CHR_IOCTL_PP_EPP_READ 9
|
|
|
|
#define CHR_IOCTL_PP_EPP_WRITE_ADDR 10
|
|
|
|
#define CHR_IOCTL_PP_EPP_WRITE 11
|
2008-08-22 12:57:09 +04:00
|
|
|
#define CHR_IOCTL_PP_DATA_DIR 12
|
2007-11-17 20:14:51 +03:00
|
|
|
|
2016-03-09 14:21:49 +03:00
|
|
|
struct ParallelIOArg {
|
|
|
|
void *buffer;
|
|
|
|
int count;
|
|
|
|
};
|
|
|
|
|
2008-08-23 01:25:00 +04:00
|
|
|
#define CHR_IOCTL_SERIAL_SET_TIOCM 13
|
|
|
|
#define CHR_IOCTL_SERIAL_GET_TIOCM 14
|
2008-08-11 18:17:04 +04:00
|
|
|
|
|
|
|
#define CHR_TIOCM_CTS 0x020
|
|
|
|
#define CHR_TIOCM_CAR 0x040
|
|
|
|
#define CHR_TIOCM_DSR 0x100
|
|
|
|
#define CHR_TIOCM_RI 0x080
|
|
|
|
#define CHR_TIOCM_DTR 0x002
|
|
|
|
#define CHR_TIOCM_RTS 0x004
|
|
|
|
|
2007-11-17 20:14:51 +03:00
|
|
|
typedef void IOEventHandler(void *opaque, int event);
|
|
|
|
|
net: don't poke at chardev internal QemuOpts
The vhost-user & colo code is poking at the QemuOpts instance
in the CharDriverState struct, not realizing that it is valid
for this to be NULL. e.g. the following crash shows a codepath
where it will be NULL:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x000055baf6ab4adc in qemu_opt_foreach (opts=0x0, func=0x55baf696b650 <net_vhost_chardev_opts>, opaque=0x7ffc51368c00, errp=0x7ffc51368e48) at util/qemu-option.c:617
617 QTAILQ_FOREACH(opt, &opts->head, next) {
[Current thread is 1 (Thread 0x7f1d4970bb40 (LWP 6603))]
(gdb) bt
#0 0x000055baf6ab4adc in qemu_opt_foreach (opts=0x0, func=0x55baf696b650 <net_vhost_chardev_opts>, opaque=0x7ffc51368c00, errp=0x7ffc51368e48) at util/qemu-option.c:617
#1 0x000055baf696b7da in net_vhost_parse_chardev (opts=0x55baf8ff9260, errp=0x7ffc51368e48) at net/vhost-user.c:314
#2 0x000055baf696b985 in net_init_vhost_user (netdev=0x55baf8ff9250, name=0x55baf879d270 "hostnet2", peer=0x0, errp=0x7ffc51368e48) at net/vhost-user.c:360
#3 0x000055baf6960216 in net_client_init1 (object=0x55baf8ff9250, is_netdev=true, errp=0x7ffc51368e48) at net/net.c:1051
#4 0x000055baf6960518 in net_client_init (opts=0x55baf776e7e0, is_netdev=true, errp=0x7ffc51368f00) at net/net.c:1108
#5 0x000055baf696083f in netdev_add (opts=0x55baf776e7e0, errp=0x7ffc51368f00) at net/net.c:1186
#6 0x000055baf69608c7 in qmp_netdev_add (qdict=0x55baf7afaf60, ret=0x7ffc51368f50, errp=0x7ffc51368f48) at net/net.c:1205
#7 0x000055baf6622135 in handle_qmp_command (parser=0x55baf77fb590, tokens=0x7f1d24011960) at /path/to/qemu.git/monitor.c:3978
#8 0x000055baf6a9d099 in json_message_process_token (lexer=0x55baf77fb598, input=0x55baf75acd20, type=JSON_RCURLY, x=113, y=19) at qobject/json-streamer.c:105
#9 0x000055baf6abf7aa in json_lexer_feed_char (lexer=0x55baf77fb598, ch=125 '}', flush=false) at qobject/json-lexer.c:319
#10 0x000055baf6abf8f2 in json_lexer_feed (lexer=0x55baf77fb598, buffer=0x7ffc51369170 "}R\204\367\272U", size=1) at qobject/json-lexer.c:369
#11 0x000055baf6a9d13c in json_message_parser_feed (parser=0x55baf77fb590, buffer=0x7ffc51369170 "}R\204\367\272U", size=1) at qobject/json-streamer.c:124
#12 0x000055baf66221f7 in monitor_qmp_read (opaque=0x55baf77fb530, buf=0x7ffc51369170 "}R\204\367\272U", size=1) at /path/to/qemu.git/monitor.c:3994
#13 0x000055baf6757014 in qemu_chr_be_write_impl (s=0x55baf7610a40, buf=0x7ffc51369170 "}R\204\367\272U", len=1) at qemu-char.c:387
#14 0x000055baf6757076 in qemu_chr_be_write (s=0x55baf7610a40, buf=0x7ffc51369170 "}R\204\367\272U", len=1) at qemu-char.c:399
#15 0x000055baf675b3b0 in tcp_chr_read (chan=0x55baf90244b0, cond=G_IO_IN, opaque=0x55baf7610a40) at qemu-char.c:2927
#16 0x000055baf6a5d655 in qio_channel_fd_source_dispatch (source=0x55baf7610df0, callback=0x55baf675b25a <tcp_chr_read>, user_data=0x55baf7610a40) at io/channel-watch.c:84
#17 0x00007f1d3e80cbbd in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0
#18 0x000055baf69d3720 in glib_pollfds_poll () at main-loop.c:213
#19 0x000055baf69d37fd in os_host_main_loop_wait (timeout=126000000) at main-loop.c:258
#20 0x000055baf69d38ad in main_loop_wait (nonblocking=0) at main-loop.c:506
#21 0x000055baf676587b in main_loop () at vl.c:1908
#22 0x000055baf676d3bf in main (argc=101, argv=0x7ffc5136a6c8, envp=0x7ffc5136a9f8) at vl.c:4604
(gdb) p opts
$1 = (QemuOpts *) 0x0
The crash occurred when attaching vhost-user net via QMP:
{
"execute": "chardev-add",
"arguments": {
"id": "charnet2",
"backend": {
"type": "socket",
"data": {
"addr": {
"type": "unix",
"data": {
"path": "/var/run/openvswitch/vhost-user1"
}
},
"wait": false,
"server": false
}
}
},
"id": "libvirt-19"
}
{
"return": {
},
"id": "libvirt-19"
}
{
"execute": "netdev_add",
"arguments": {
"type": "vhost-user",
"chardev": "charnet2",
"id": "hostnet2"
},
"id": "libvirt-20"
}
Code using chardevs should not be poking at the internals of the
CharDriverState struct. What vhost-user wants is a chardev that is
operating as reconnectable network service, along with the ability
to do FD passing over the connection. The colo code simply wants
a network service. Add a feature concept to the char drivers so
that chardev users can query the actual features they wish to have
supported. The QemuOpts member is removed to prevent future mistakes
in this area.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2016-10-07 15:18:34 +03:00
|
|
|
typedef enum {
|
|
|
|
/* Whether the chardev peer is able to close and
|
|
|
|
* reopen the data channel, thus requiring support
|
|
|
|
* for qemu_chr_wait_connected() to wait for a
|
|
|
|
* valid connection */
|
|
|
|
QEMU_CHAR_FEATURE_RECONNECTABLE,
|
|
|
|
/* Whether it is possible to send/recv file descriptors
|
|
|
|
* over the data channel */
|
|
|
|
QEMU_CHAR_FEATURE_FD_PASS,
|
2016-10-21 22:58:45 +03:00
|
|
|
/* Whether replay or record mode is enabled */
|
|
|
|
QEMU_CHAR_FEATURE_REPLAY,
|
net: don't poke at chardev internal QemuOpts
The vhost-user & colo code is poking at the QemuOpts instance
in the CharDriverState struct, not realizing that it is valid
for this to be NULL. e.g. the following crash shows a codepath
where it will be NULL:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x000055baf6ab4adc in qemu_opt_foreach (opts=0x0, func=0x55baf696b650 <net_vhost_chardev_opts>, opaque=0x7ffc51368c00, errp=0x7ffc51368e48) at util/qemu-option.c:617
617 QTAILQ_FOREACH(opt, &opts->head, next) {
[Current thread is 1 (Thread 0x7f1d4970bb40 (LWP 6603))]
(gdb) bt
#0 0x000055baf6ab4adc in qemu_opt_foreach (opts=0x0, func=0x55baf696b650 <net_vhost_chardev_opts>, opaque=0x7ffc51368c00, errp=0x7ffc51368e48) at util/qemu-option.c:617
#1 0x000055baf696b7da in net_vhost_parse_chardev (opts=0x55baf8ff9260, errp=0x7ffc51368e48) at net/vhost-user.c:314
#2 0x000055baf696b985 in net_init_vhost_user (netdev=0x55baf8ff9250, name=0x55baf879d270 "hostnet2", peer=0x0, errp=0x7ffc51368e48) at net/vhost-user.c:360
#3 0x000055baf6960216 in net_client_init1 (object=0x55baf8ff9250, is_netdev=true, errp=0x7ffc51368e48) at net/net.c:1051
#4 0x000055baf6960518 in net_client_init (opts=0x55baf776e7e0, is_netdev=true, errp=0x7ffc51368f00) at net/net.c:1108
#5 0x000055baf696083f in netdev_add (opts=0x55baf776e7e0, errp=0x7ffc51368f00) at net/net.c:1186
#6 0x000055baf69608c7 in qmp_netdev_add (qdict=0x55baf7afaf60, ret=0x7ffc51368f50, errp=0x7ffc51368f48) at net/net.c:1205
#7 0x000055baf6622135 in handle_qmp_command (parser=0x55baf77fb590, tokens=0x7f1d24011960) at /path/to/qemu.git/monitor.c:3978
#8 0x000055baf6a9d099 in json_message_process_token (lexer=0x55baf77fb598, input=0x55baf75acd20, type=JSON_RCURLY, x=113, y=19) at qobject/json-streamer.c:105
#9 0x000055baf6abf7aa in json_lexer_feed_char (lexer=0x55baf77fb598, ch=125 '}', flush=false) at qobject/json-lexer.c:319
#10 0x000055baf6abf8f2 in json_lexer_feed (lexer=0x55baf77fb598, buffer=0x7ffc51369170 "}R\204\367\272U", size=1) at qobject/json-lexer.c:369
#11 0x000055baf6a9d13c in json_message_parser_feed (parser=0x55baf77fb590, buffer=0x7ffc51369170 "}R\204\367\272U", size=1) at qobject/json-streamer.c:124
#12 0x000055baf66221f7 in monitor_qmp_read (opaque=0x55baf77fb530, buf=0x7ffc51369170 "}R\204\367\272U", size=1) at /path/to/qemu.git/monitor.c:3994
#13 0x000055baf6757014 in qemu_chr_be_write_impl (s=0x55baf7610a40, buf=0x7ffc51369170 "}R\204\367\272U", len=1) at qemu-char.c:387
#14 0x000055baf6757076 in qemu_chr_be_write (s=0x55baf7610a40, buf=0x7ffc51369170 "}R\204\367\272U", len=1) at qemu-char.c:399
#15 0x000055baf675b3b0 in tcp_chr_read (chan=0x55baf90244b0, cond=G_IO_IN, opaque=0x55baf7610a40) at qemu-char.c:2927
#16 0x000055baf6a5d655 in qio_channel_fd_source_dispatch (source=0x55baf7610df0, callback=0x55baf675b25a <tcp_chr_read>, user_data=0x55baf7610a40) at io/channel-watch.c:84
#17 0x00007f1d3e80cbbd in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0
#18 0x000055baf69d3720 in glib_pollfds_poll () at main-loop.c:213
#19 0x000055baf69d37fd in os_host_main_loop_wait (timeout=126000000) at main-loop.c:258
#20 0x000055baf69d38ad in main_loop_wait (nonblocking=0) at main-loop.c:506
#21 0x000055baf676587b in main_loop () at vl.c:1908
#22 0x000055baf676d3bf in main (argc=101, argv=0x7ffc5136a6c8, envp=0x7ffc5136a9f8) at vl.c:4604
(gdb) p opts
$1 = (QemuOpts *) 0x0
The crash occurred when attaching vhost-user net via QMP:
{
"execute": "chardev-add",
"arguments": {
"id": "charnet2",
"backend": {
"type": "socket",
"data": {
"addr": {
"type": "unix",
"data": {
"path": "/var/run/openvswitch/vhost-user1"
}
},
"wait": false,
"server": false
}
}
},
"id": "libvirt-19"
}
{
"return": {
},
"id": "libvirt-19"
}
{
"execute": "netdev_add",
"arguments": {
"type": "vhost-user",
"chardev": "charnet2",
"id": "hostnet2"
},
"id": "libvirt-20"
}
Code using chardevs should not be poking at the internals of the
CharDriverState struct. What vhost-user wants is a chardev that is
operating as reconnectable network service, along with the ability
to do FD passing over the connection. The colo code simply wants
a network service. Add a feature concept to the char drivers so
that chardev users can query the actual features they wish to have
supported. The QemuOpts member is removed to prevent future mistakes
in this area.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2016-10-07 15:18:34 +03:00
|
|
|
|
|
|
|
QEMU_CHAR_FEATURE_LAST,
|
2016-12-14 13:27:58 +03:00
|
|
|
} ChardevFeature;
|
net: don't poke at chardev internal QemuOpts
The vhost-user & colo code is poking at the QemuOpts instance
in the CharDriverState struct, not realizing that it is valid
for this to be NULL. e.g. the following crash shows a codepath
where it will be NULL:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x000055baf6ab4adc in qemu_opt_foreach (opts=0x0, func=0x55baf696b650 <net_vhost_chardev_opts>, opaque=0x7ffc51368c00, errp=0x7ffc51368e48) at util/qemu-option.c:617
617 QTAILQ_FOREACH(opt, &opts->head, next) {
[Current thread is 1 (Thread 0x7f1d4970bb40 (LWP 6603))]
(gdb) bt
#0 0x000055baf6ab4adc in qemu_opt_foreach (opts=0x0, func=0x55baf696b650 <net_vhost_chardev_opts>, opaque=0x7ffc51368c00, errp=0x7ffc51368e48) at util/qemu-option.c:617
#1 0x000055baf696b7da in net_vhost_parse_chardev (opts=0x55baf8ff9260, errp=0x7ffc51368e48) at net/vhost-user.c:314
#2 0x000055baf696b985 in net_init_vhost_user (netdev=0x55baf8ff9250, name=0x55baf879d270 "hostnet2", peer=0x0, errp=0x7ffc51368e48) at net/vhost-user.c:360
#3 0x000055baf6960216 in net_client_init1 (object=0x55baf8ff9250, is_netdev=true, errp=0x7ffc51368e48) at net/net.c:1051
#4 0x000055baf6960518 in net_client_init (opts=0x55baf776e7e0, is_netdev=true, errp=0x7ffc51368f00) at net/net.c:1108
#5 0x000055baf696083f in netdev_add (opts=0x55baf776e7e0, errp=0x7ffc51368f00) at net/net.c:1186
#6 0x000055baf69608c7 in qmp_netdev_add (qdict=0x55baf7afaf60, ret=0x7ffc51368f50, errp=0x7ffc51368f48) at net/net.c:1205
#7 0x000055baf6622135 in handle_qmp_command (parser=0x55baf77fb590, tokens=0x7f1d24011960) at /path/to/qemu.git/monitor.c:3978
#8 0x000055baf6a9d099 in json_message_process_token (lexer=0x55baf77fb598, input=0x55baf75acd20, type=JSON_RCURLY, x=113, y=19) at qobject/json-streamer.c:105
#9 0x000055baf6abf7aa in json_lexer_feed_char (lexer=0x55baf77fb598, ch=125 '}', flush=false) at qobject/json-lexer.c:319
#10 0x000055baf6abf8f2 in json_lexer_feed (lexer=0x55baf77fb598, buffer=0x7ffc51369170 "}R\204\367\272U", size=1) at qobject/json-lexer.c:369
#11 0x000055baf6a9d13c in json_message_parser_feed (parser=0x55baf77fb590, buffer=0x7ffc51369170 "}R\204\367\272U", size=1) at qobject/json-streamer.c:124
#12 0x000055baf66221f7 in monitor_qmp_read (opaque=0x55baf77fb530, buf=0x7ffc51369170 "}R\204\367\272U", size=1) at /path/to/qemu.git/monitor.c:3994
#13 0x000055baf6757014 in qemu_chr_be_write_impl (s=0x55baf7610a40, buf=0x7ffc51369170 "}R\204\367\272U", len=1) at qemu-char.c:387
#14 0x000055baf6757076 in qemu_chr_be_write (s=0x55baf7610a40, buf=0x7ffc51369170 "}R\204\367\272U", len=1) at qemu-char.c:399
#15 0x000055baf675b3b0 in tcp_chr_read (chan=0x55baf90244b0, cond=G_IO_IN, opaque=0x55baf7610a40) at qemu-char.c:2927
#16 0x000055baf6a5d655 in qio_channel_fd_source_dispatch (source=0x55baf7610df0, callback=0x55baf675b25a <tcp_chr_read>, user_data=0x55baf7610a40) at io/channel-watch.c:84
#17 0x00007f1d3e80cbbd in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0
#18 0x000055baf69d3720 in glib_pollfds_poll () at main-loop.c:213
#19 0x000055baf69d37fd in os_host_main_loop_wait (timeout=126000000) at main-loop.c:258
#20 0x000055baf69d38ad in main_loop_wait (nonblocking=0) at main-loop.c:506
#21 0x000055baf676587b in main_loop () at vl.c:1908
#22 0x000055baf676d3bf in main (argc=101, argv=0x7ffc5136a6c8, envp=0x7ffc5136a9f8) at vl.c:4604
(gdb) p opts
$1 = (QemuOpts *) 0x0
The crash occurred when attaching vhost-user net via QMP:
{
"execute": "chardev-add",
"arguments": {
"id": "charnet2",
"backend": {
"type": "socket",
"data": {
"addr": {
"type": "unix",
"data": {
"path": "/var/run/openvswitch/vhost-user1"
}
},
"wait": false,
"server": false
}
}
},
"id": "libvirt-19"
}
{
"return": {
},
"id": "libvirt-19"
}
{
"execute": "netdev_add",
"arguments": {
"type": "vhost-user",
"chardev": "charnet2",
"id": "hostnet2"
},
"id": "libvirt-20"
}
Code using chardevs should not be poking at the internals of the
CharDriverState struct. What vhost-user wants is a chardev that is
operating as reconnectable network service, along with the ability
to do FD passing over the connection. The colo code simply wants
a network service. Add a feature concept to the char drivers so
that chardev users can query the actual features they wish to have
supported. The QemuOpts member is removed to prevent future mistakes
in this area.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2016-10-07 15:18:34 +03:00
|
|
|
|
2016-10-22 12:52:49 +03:00
|
|
|
/* This is the backend as seen by frontend, the actual backend is
|
2016-12-07 16:20:22 +03:00
|
|
|
* Chardev */
|
2016-10-22 12:52:49 +03:00
|
|
|
typedef struct CharBackend {
|
2016-12-07 16:20:22 +03:00
|
|
|
Chardev *chr;
|
2016-10-22 12:53:01 +03:00
|
|
|
IOEventHandler *chr_event;
|
|
|
|
IOCanReadHandler *chr_can_read;
|
|
|
|
IOReadHandler *chr_read;
|
|
|
|
void *opaque;
|
2016-10-22 12:52:49 +03:00
|
|
|
int tag;
|
2016-10-22 13:09:37 +03:00
|
|
|
int fe_open;
|
2016-10-22 12:52:49 +03:00
|
|
|
} CharBackend;
|
net: don't poke at chardev internal QemuOpts
The vhost-user & colo code is poking at the QemuOpts instance
in the CharDriverState struct, not realizing that it is valid
for this to be NULL. e.g. the following crash shows a codepath
where it will be NULL:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x000055baf6ab4adc in qemu_opt_foreach (opts=0x0, func=0x55baf696b650 <net_vhost_chardev_opts>, opaque=0x7ffc51368c00, errp=0x7ffc51368e48) at util/qemu-option.c:617
617 QTAILQ_FOREACH(opt, &opts->head, next) {
[Current thread is 1 (Thread 0x7f1d4970bb40 (LWP 6603))]
(gdb) bt
#0 0x000055baf6ab4adc in qemu_opt_foreach (opts=0x0, func=0x55baf696b650 <net_vhost_chardev_opts>, opaque=0x7ffc51368c00, errp=0x7ffc51368e48) at util/qemu-option.c:617
#1 0x000055baf696b7da in net_vhost_parse_chardev (opts=0x55baf8ff9260, errp=0x7ffc51368e48) at net/vhost-user.c:314
#2 0x000055baf696b985 in net_init_vhost_user (netdev=0x55baf8ff9250, name=0x55baf879d270 "hostnet2", peer=0x0, errp=0x7ffc51368e48) at net/vhost-user.c:360
#3 0x000055baf6960216 in net_client_init1 (object=0x55baf8ff9250, is_netdev=true, errp=0x7ffc51368e48) at net/net.c:1051
#4 0x000055baf6960518 in net_client_init (opts=0x55baf776e7e0, is_netdev=true, errp=0x7ffc51368f00) at net/net.c:1108
#5 0x000055baf696083f in netdev_add (opts=0x55baf776e7e0, errp=0x7ffc51368f00) at net/net.c:1186
#6 0x000055baf69608c7 in qmp_netdev_add (qdict=0x55baf7afaf60, ret=0x7ffc51368f50, errp=0x7ffc51368f48) at net/net.c:1205
#7 0x000055baf6622135 in handle_qmp_command (parser=0x55baf77fb590, tokens=0x7f1d24011960) at /path/to/qemu.git/monitor.c:3978
#8 0x000055baf6a9d099 in json_message_process_token (lexer=0x55baf77fb598, input=0x55baf75acd20, type=JSON_RCURLY, x=113, y=19) at qobject/json-streamer.c:105
#9 0x000055baf6abf7aa in json_lexer_feed_char (lexer=0x55baf77fb598, ch=125 '}', flush=false) at qobject/json-lexer.c:319
#10 0x000055baf6abf8f2 in json_lexer_feed (lexer=0x55baf77fb598, buffer=0x7ffc51369170 "}R\204\367\272U", size=1) at qobject/json-lexer.c:369
#11 0x000055baf6a9d13c in json_message_parser_feed (parser=0x55baf77fb590, buffer=0x7ffc51369170 "}R\204\367\272U", size=1) at qobject/json-streamer.c:124
#12 0x000055baf66221f7 in monitor_qmp_read (opaque=0x55baf77fb530, buf=0x7ffc51369170 "}R\204\367\272U", size=1) at /path/to/qemu.git/monitor.c:3994
#13 0x000055baf6757014 in qemu_chr_be_write_impl (s=0x55baf7610a40, buf=0x7ffc51369170 "}R\204\367\272U", len=1) at qemu-char.c:387
#14 0x000055baf6757076 in qemu_chr_be_write (s=0x55baf7610a40, buf=0x7ffc51369170 "}R\204\367\272U", len=1) at qemu-char.c:399
#15 0x000055baf675b3b0 in tcp_chr_read (chan=0x55baf90244b0, cond=G_IO_IN, opaque=0x55baf7610a40) at qemu-char.c:2927
#16 0x000055baf6a5d655 in qio_channel_fd_source_dispatch (source=0x55baf7610df0, callback=0x55baf675b25a <tcp_chr_read>, user_data=0x55baf7610a40) at io/channel-watch.c:84
#17 0x00007f1d3e80cbbd in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0
#18 0x000055baf69d3720 in glib_pollfds_poll () at main-loop.c:213
#19 0x000055baf69d37fd in os_host_main_loop_wait (timeout=126000000) at main-loop.c:258
#20 0x000055baf69d38ad in main_loop_wait (nonblocking=0) at main-loop.c:506
#21 0x000055baf676587b in main_loop () at vl.c:1908
#22 0x000055baf676d3bf in main (argc=101, argv=0x7ffc5136a6c8, envp=0x7ffc5136a9f8) at vl.c:4604
(gdb) p opts
$1 = (QemuOpts *) 0x0
The crash occurred when attaching vhost-user net via QMP:
{
"execute": "chardev-add",
"arguments": {
"id": "charnet2",
"backend": {
"type": "socket",
"data": {
"addr": {
"type": "unix",
"data": {
"path": "/var/run/openvswitch/vhost-user1"
}
},
"wait": false,
"server": false
}
}
},
"id": "libvirt-19"
}
{
"return": {
},
"id": "libvirt-19"
}
{
"execute": "netdev_add",
"arguments": {
"type": "vhost-user",
"chardev": "charnet2",
"id": "hostnet2"
},
"id": "libvirt-20"
}
Code using chardevs should not be poking at the internals of the
CharDriverState struct. What vhost-user wants is a chardev that is
operating as reconnectable network service, along with the ability
to do FD passing over the connection. The colo code simply wants
a network service. Add a feature concept to the char drivers so
that chardev users can query the actual features they wish to have
supported. The QemuOpts member is removed to prevent future mistakes
in this area.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2016-10-07 15:18:34 +03:00
|
|
|
|
2016-12-07 16:20:22 +03:00
|
|
|
struct Chardev {
|
2016-12-07 18:39:10 +03:00
|
|
|
Object parent_obj;
|
|
|
|
|
2014-06-18 10:43:58 +04:00
|
|
|
QemuMutex chr_write_lock;
|
2016-10-22 12:53:01 +03:00
|
|
|
CharBackend *be;
|
2008-10-31 20:31:29 +03:00
|
|
|
char *label;
|
|
|
|
char *filename;
|
qemu-char: add logfile facility to all chardev backends
Typically a UNIX guest OS will log boot messages to a serial
port in addition to any graphical console. An admin user
may also wish to use the serial port for an interactive
console. A virtualization management system may wish to
collect system boot messages by logging the serial port,
but also wish to allow admins interactive access.
Currently providing such a feature forces the mgmt app
to either provide 2 separate serial ports, one for
logging boot messages and one for interactive console
login, or to proxy all output via a separate service
that can multiplex the two needs onto one serial port.
While both are valid approaches, they each have their
own downsides. The former causes confusion and extra
setup work for VM admins creating disk images. The latter
places an extra burden to re-implement much of the QEMU
chardev backends logic in libvirt or even higher level
mgmt apps and adds extra hops in the data transfer path.
A simpler approach that is satisfactory for many use
cases is to allow the QEMU chardev backends to have a
"logfile" property associated with them.
$QEMU -chardev socket,host=localhost,port=9000,\
server=on,nowait,id-charserial0,\
logfile=/var/log/libvirt/qemu/test-serial0.log
-device isa-serial,chardev=charserial0,id=serial0
This patch introduces a 'ChardevCommon' struct which
is setup as a base for all the ChardevBackend types.
Ideally this would be registered directly as a base
against ChardevBackend, rather than each type, but
the QAPI generator doesn't allow that since the
ChardevBackend is a non-discriminated union. The
ChardevCommon struct provides the optional 'logfile'
parameter, as well as 'logappend' which controls
whether QEMU truncates or appends (default truncate).
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Message-Id: <1452516281-27519-1-git-send-email-berrange@redhat.com>
[Call qemu_chr_parse_common if cd->parse is NULL. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2016-01-11 15:44:41 +03:00
|
|
|
int logfd;
|
2013-03-26 14:07:53 +04:00
|
|
|
int be_open;
|
2013-08-28 13:48:29 +04:00
|
|
|
guint fd_in_tag;
|
net: don't poke at chardev internal QemuOpts
The vhost-user & colo code is poking at the QemuOpts instance
in the CharDriverState struct, not realizing that it is valid
for this to be NULL. e.g. the following crash shows a codepath
where it will be NULL:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x000055baf6ab4adc in qemu_opt_foreach (opts=0x0, func=0x55baf696b650 <net_vhost_chardev_opts>, opaque=0x7ffc51368c00, errp=0x7ffc51368e48) at util/qemu-option.c:617
617 QTAILQ_FOREACH(opt, &opts->head, next) {
[Current thread is 1 (Thread 0x7f1d4970bb40 (LWP 6603))]
(gdb) bt
#0 0x000055baf6ab4adc in qemu_opt_foreach (opts=0x0, func=0x55baf696b650 <net_vhost_chardev_opts>, opaque=0x7ffc51368c00, errp=0x7ffc51368e48) at util/qemu-option.c:617
#1 0x000055baf696b7da in net_vhost_parse_chardev (opts=0x55baf8ff9260, errp=0x7ffc51368e48) at net/vhost-user.c:314
#2 0x000055baf696b985 in net_init_vhost_user (netdev=0x55baf8ff9250, name=0x55baf879d270 "hostnet2", peer=0x0, errp=0x7ffc51368e48) at net/vhost-user.c:360
#3 0x000055baf6960216 in net_client_init1 (object=0x55baf8ff9250, is_netdev=true, errp=0x7ffc51368e48) at net/net.c:1051
#4 0x000055baf6960518 in net_client_init (opts=0x55baf776e7e0, is_netdev=true, errp=0x7ffc51368f00) at net/net.c:1108
#5 0x000055baf696083f in netdev_add (opts=0x55baf776e7e0, errp=0x7ffc51368f00) at net/net.c:1186
#6 0x000055baf69608c7 in qmp_netdev_add (qdict=0x55baf7afaf60, ret=0x7ffc51368f50, errp=0x7ffc51368f48) at net/net.c:1205
#7 0x000055baf6622135 in handle_qmp_command (parser=0x55baf77fb590, tokens=0x7f1d24011960) at /path/to/qemu.git/monitor.c:3978
#8 0x000055baf6a9d099 in json_message_process_token (lexer=0x55baf77fb598, input=0x55baf75acd20, type=JSON_RCURLY, x=113, y=19) at qobject/json-streamer.c:105
#9 0x000055baf6abf7aa in json_lexer_feed_char (lexer=0x55baf77fb598, ch=125 '}', flush=false) at qobject/json-lexer.c:319
#10 0x000055baf6abf8f2 in json_lexer_feed (lexer=0x55baf77fb598, buffer=0x7ffc51369170 "}R\204\367\272U", size=1) at qobject/json-lexer.c:369
#11 0x000055baf6a9d13c in json_message_parser_feed (parser=0x55baf77fb590, buffer=0x7ffc51369170 "}R\204\367\272U", size=1) at qobject/json-streamer.c:124
#12 0x000055baf66221f7 in monitor_qmp_read (opaque=0x55baf77fb530, buf=0x7ffc51369170 "}R\204\367\272U", size=1) at /path/to/qemu.git/monitor.c:3994
#13 0x000055baf6757014 in qemu_chr_be_write_impl (s=0x55baf7610a40, buf=0x7ffc51369170 "}R\204\367\272U", len=1) at qemu-char.c:387
#14 0x000055baf6757076 in qemu_chr_be_write (s=0x55baf7610a40, buf=0x7ffc51369170 "}R\204\367\272U", len=1) at qemu-char.c:399
#15 0x000055baf675b3b0 in tcp_chr_read (chan=0x55baf90244b0, cond=G_IO_IN, opaque=0x55baf7610a40) at qemu-char.c:2927
#16 0x000055baf6a5d655 in qio_channel_fd_source_dispatch (source=0x55baf7610df0, callback=0x55baf675b25a <tcp_chr_read>, user_data=0x55baf7610a40) at io/channel-watch.c:84
#17 0x00007f1d3e80cbbd in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0
#18 0x000055baf69d3720 in glib_pollfds_poll () at main-loop.c:213
#19 0x000055baf69d37fd in os_host_main_loop_wait (timeout=126000000) at main-loop.c:258
#20 0x000055baf69d38ad in main_loop_wait (nonblocking=0) at main-loop.c:506
#21 0x000055baf676587b in main_loop () at vl.c:1908
#22 0x000055baf676d3bf in main (argc=101, argv=0x7ffc5136a6c8, envp=0x7ffc5136a9f8) at vl.c:4604
(gdb) p opts
$1 = (QemuOpts *) 0x0
The crash occurred when attaching vhost-user net via QMP:
{
"execute": "chardev-add",
"arguments": {
"id": "charnet2",
"backend": {
"type": "socket",
"data": {
"addr": {
"type": "unix",
"data": {
"path": "/var/run/openvswitch/vhost-user1"
}
},
"wait": false,
"server": false
}
}
},
"id": "libvirt-19"
}
{
"return": {
},
"id": "libvirt-19"
}
{
"execute": "netdev_add",
"arguments": {
"type": "vhost-user",
"chardev": "charnet2",
"id": "hostnet2"
},
"id": "libvirt-20"
}
Code using chardevs should not be poking at the internals of the
CharDriverState struct. What vhost-user wants is a chardev that is
operating as reconnectable network service, along with the ability
to do FD passing over the connection. The colo code simply wants
a network service. Add a feature concept to the char drivers so
that chardev users can query the actual features they wish to have
supported. The QemuOpts member is removed to prevent future mistakes
in this area.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2016-10-07 15:18:34 +03:00
|
|
|
DECLARE_BITMAP(features, QEMU_CHAR_FEATURE_LAST);
|
2016-12-07 16:20:22 +03:00
|
|
|
QTAILQ_ENTRY(Chardev) next;
|
2007-11-17 20:14:51 +03:00
|
|
|
};
|
|
|
|
|
2011-08-15 20:17:41 +04:00
|
|
|
/**
|
|
|
|
* @qemu_chr_new_from_opts:
|
|
|
|
*
|
|
|
|
* Create a new character backend from a QemuOpts list.
|
|
|
|
*
|
|
|
|
* @opts see qemu-config.c for a list of valid options
|
|
|
|
*
|
|
|
|
* Returns: a new character backend
|
|
|
|
*/
|
2016-12-07 16:20:22 +03:00
|
|
|
Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
|
|
|
|
Error **errp);
|
2011-08-15 20:17:41 +04:00
|
|
|
|
2016-02-20 03:19:31 +03:00
|
|
|
/**
|
|
|
|
* @qemu_chr_parse_common:
|
|
|
|
*
|
|
|
|
* Parse the common options available to all character backends.
|
|
|
|
*
|
|
|
|
* @opts the options that still need parsing
|
|
|
|
* @backend a new backend
|
|
|
|
*/
|
|
|
|
void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend);
|
|
|
|
|
2011-08-15 20:17:41 +04:00
|
|
|
/**
|
|
|
|
* @qemu_chr_new:
|
|
|
|
*
|
|
|
|
* Create a new character backend from a URI.
|
|
|
|
*
|
|
|
|
* @label the name of the backend
|
|
|
|
* @filename the URI
|
|
|
|
*
|
|
|
|
* Returns: a new character backend
|
|
|
|
*/
|
2016-12-07 16:20:22 +03:00
|
|
|
Chardev *qemu_chr_new(const char *label, const char *filename);
|
2016-10-22 12:52:49 +03:00
|
|
|
|
|
|
|
|
2016-06-06 19:45:02 +03:00
|
|
|
/**
|
2016-10-22 12:52:53 +03:00
|
|
|
* @qemu_chr_fe_disconnect:
|
2016-06-06 19:45:02 +03:00
|
|
|
*
|
|
|
|
* Close a fd accpeted by character backend.
|
2016-12-14 13:27:58 +03:00
|
|
|
* Without associated Chardev, do nothing.
|
2016-06-06 19:45:02 +03:00
|
|
|
*/
|
2016-10-22 12:52:55 +03:00
|
|
|
void qemu_chr_fe_disconnect(CharBackend *be);
|
2011-08-15 20:17:41 +04:00
|
|
|
|
char: do not use atexit cleanup handler
It turns out qemu is calling exit() in various places from various
threads without taking much care of resources state. The atexit()
cleanup handlers cannot easily destroy resources that are in use (by
the same thread or other).
Since c1111a24a3, TCG arm guests run into the following abort() when
running tests, the chardev mutex is locked during the write, so
qemu_mutex_destroy() returns an error:
#0 0x00007fffdbb806f5 in raise () at /lib64/libc.so.6
#1 0x00007fffdbb822fa in abort () at /lib64/libc.so.6
#2 0x00005555557616fe in error_exit (err=<optimized out>, msg=msg@entry=0x555555c38c30 <__func__.14622> "qemu_mutex_destroy")
at /home/drjones/code/qemu/util/qemu-thread-posix.c:39
#3 0x0000555555b0be20 in qemu_mutex_destroy (mutex=mutex@entry=0x5555566aa0e0) at /home/drjones/code/qemu/util/qemu-thread-posix.c:57
#4 0x00005555558aab00 in qemu_chr_free_common (chr=0x5555566aa0e0) at /home/drjones/code/qemu/qemu-char.c:4029
#5 0x00005555558b05f9 in qemu_chr_delete (chr=<optimized out>) at /home/drjones/code/qemu/qemu-char.c:4038
#6 0x00005555558b05f9 in qemu_chr_delete (chr=<optimized out>) at /home/drjones/code/qemu/qemu-char.c:4044
#7 0x00005555558b062c in qemu_chr_cleanup () at /home/drjones/code/qemu/qemu-char.c:4557
#8 0x00007fffdbb851e8 in __run_exit_handlers () at /lib64/libc.so.6
#9 0x00007fffdbb85235 in () at /lib64/libc.so.6
#10 0x00005555558d1b39 in testdev_write (testdev=0x5555566aa0a0) at /home/drjones/code/qemu/backends/testdev.c:71
#11 0x00005555558d1b39 in testdev_write (chr=<optimized out>, buf=0x7fffc343fd9a "", len=0) at /home/drjones/code/qemu/backends/testdev.c:95
#12 0x00005555558adced in qemu_chr_fe_write (s=0x5555566aa0e0, buf=buf@entry=0x7fffc343fd98 "0q", len=len@entry=2) at /home/drjones/code/qemu/qemu-char.c:282
Instead of using a atexit() handler, only run the chardev cleanup as
initially proposed at the end of main(), where there are less chances
(hic) of conflicts or other races.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reported-by: Andrew Jones <drjones@redhat.com>
Message-Id: <20160704153823.16879-1-marcandre.lureau@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2016-07-04 18:38:23 +03:00
|
|
|
/**
|
|
|
|
* @qemu_chr_cleanup:
|
|
|
|
*
|
|
|
|
* Delete all chardevs (when leaving qemu)
|
|
|
|
*/
|
|
|
|
void qemu_chr_cleanup(void);
|
|
|
|
|
2016-07-27 00:15:17 +03:00
|
|
|
/**
|
2016-10-22 12:52:55 +03:00
|
|
|
* @qemu_chr_fe_wait_connected:
|
2016-07-27 00:15:17 +03:00
|
|
|
*
|
2016-10-22 12:52:59 +03:00
|
|
|
* Wait for characted backend to be connected, return < 0 on error or
|
2016-12-14 13:27:58 +03:00
|
|
|
* if no assicated Chardev.
|
2016-07-27 00:15:17 +03:00
|
|
|
*/
|
2016-10-22 12:52:55 +03:00
|
|
|
int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp);
|
2016-07-27 00:15:17 +03:00
|
|
|
|
2016-03-14 10:44:36 +03:00
|
|
|
/**
|
|
|
|
* @qemu_chr_new_noreplay:
|
|
|
|
*
|
|
|
|
* Create a new character backend from a URI.
|
|
|
|
* Character device communications are not written
|
|
|
|
* into the replay log.
|
|
|
|
*
|
|
|
|
* @label the name of the backend
|
|
|
|
* @filename the URI
|
|
|
|
*
|
|
|
|
* Returns: a new character backend
|
|
|
|
*/
|
2016-12-07 16:20:22 +03:00
|
|
|
Chardev *qemu_chr_new_noreplay(const char *label, const char *filename);
|
2016-03-14 10:44:36 +03:00
|
|
|
|
2011-08-15 20:17:41 +04:00
|
|
|
/**
|
|
|
|
* @qemu_chr_delete:
|
|
|
|
*
|
2015-06-22 19:20:18 +03:00
|
|
|
* Destroy a character backend and remove it from the list of
|
|
|
|
* identified character backends.
|
2011-08-15 20:17:41 +04:00
|
|
|
*/
|
2016-12-07 16:20:22 +03:00
|
|
|
void qemu_chr_delete(Chardev *chr);
|
2011-08-15 20:17:41 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @qemu_chr_fe_set_echo:
|
|
|
|
*
|
|
|
|
* Ask the backend to override its normal echo setting. This only really
|
|
|
|
* applies to the stdio backend and is used by the QMP server such that you
|
|
|
|
* can see what you type if you try to type QMP commands.
|
2016-12-14 13:27:58 +03:00
|
|
|
* Without associated Chardev, do nothing.
|
2011-08-15 20:17:41 +04:00
|
|
|
*
|
|
|
|
* @echo true to enable echo, false to disable echo
|
|
|
|
*/
|
2016-10-22 12:52:55 +03:00
|
|
|
void qemu_chr_fe_set_echo(CharBackend *be, bool echo);
|
2011-08-15 20:17:41 +04:00
|
|
|
|
|
|
|
/**
|
2013-03-26 14:07:57 +04:00
|
|
|
* @qemu_chr_fe_set_open:
|
2011-08-15 20:17:41 +04:00
|
|
|
*
|
2013-03-26 14:07:57 +04:00
|
|
|
* Set character frontend open status. This is an indication that the
|
|
|
|
* front end is ready (or not) to begin doing I/O.
|
2016-12-14 13:27:58 +03:00
|
|
|
* Without associated Chardev, do nothing.
|
2011-08-15 20:17:41 +04:00
|
|
|
*/
|
2016-10-22 12:52:55 +03:00
|
|
|
void qemu_chr_fe_set_open(CharBackend *be, int fe_open);
|
2011-08-15 20:17:41 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @qemu_chr_fe_printf:
|
|
|
|
*
|
2016-10-22 12:52:59 +03:00
|
|
|
* Write to a character backend using a printf style interface. This
|
|
|
|
* function is thread-safe. It does nothing without associated
|
2016-12-14 13:27:58 +03:00
|
|
|
* Chardev.
|
2011-08-15 20:17:41 +04:00
|
|
|
*
|
|
|
|
* @fmt see #printf
|
|
|
|
*/
|
2016-10-22 12:52:55 +03:00
|
|
|
void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...)
|
2010-09-23 23:28:05 +04:00
|
|
|
GCC_FMT_ATTR(2, 3);
|
2011-08-15 20:17:41 +04:00
|
|
|
|
2016-06-20 16:02:40 +03:00
|
|
|
/**
|
|
|
|
* @qemu_chr_fe_add_watch:
|
|
|
|
*
|
|
|
|
* If the backend is connected, create and add a #GSource that fires
|
|
|
|
* when the given condition (typically G_IO_OUT|G_IO_HUP or G_IO_HUP)
|
|
|
|
* is active; return the #GSource's tag. If it is disconnected,
|
2016-12-14 13:27:58 +03:00
|
|
|
* or without associated Chardev, return 0.
|
2016-06-20 16:02:40 +03:00
|
|
|
*
|
|
|
|
* @cond the condition to poll for
|
|
|
|
* @func the function to call when the condition happens
|
|
|
|
* @user_data the opaque pointer to pass to @func
|
2016-12-16 13:49:45 +03:00
|
|
|
*
|
|
|
|
* Returns: the source tag
|
2016-06-20 16:02:40 +03:00
|
|
|
*/
|
2016-10-22 12:52:55 +03:00
|
|
|
guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond,
|
2016-06-20 16:02:40 +03:00
|
|
|
GIOFunc func, void *user_data);
|
2013-03-05 21:51:23 +04:00
|
|
|
|
2011-08-15 20:17:41 +04:00
|
|
|
/**
|
|
|
|
* @qemu_chr_fe_write:
|
|
|
|
*
|
2014-06-18 10:43:58 +04:00
|
|
|
* Write data to a character backend from the front end. This function
|
|
|
|
* will send data from the front end to the back end. This function
|
|
|
|
* is thread-safe.
|
2011-08-15 20:17:41 +04:00
|
|
|
*
|
|
|
|
* @buf the data
|
|
|
|
* @len the number of bytes to send
|
|
|
|
*
|
2016-12-14 13:27:58 +03:00
|
|
|
* Returns: the number of bytes consumed (0 if no assicated Chardev)
|
2011-08-15 20:17:41 +04:00
|
|
|
*/
|
2016-10-22 12:52:55 +03:00
|
|
|
int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len);
|
2011-08-15 20:17:41 +04:00
|
|
|
|
2013-03-26 19:04:17 +04:00
|
|
|
/**
|
|
|
|
* @qemu_chr_fe_write_all:
|
|
|
|
*
|
|
|
|
* Write data to a character backend from the front end. This function will
|
|
|
|
* send data from the front end to the back end. Unlike @qemu_chr_fe_write,
|
|
|
|
* this function will block if the back end cannot consume all of the data
|
2014-06-18 10:43:58 +04:00
|
|
|
* attempted to be written. This function is thread-safe.
|
2013-03-26 19:04:17 +04:00
|
|
|
*
|
|
|
|
* @buf the data
|
|
|
|
* @len the number of bytes to send
|
|
|
|
*
|
2016-12-14 13:27:58 +03:00
|
|
|
* Returns: the number of bytes consumed (0 if no assicated Chardev)
|
2013-03-26 19:04:17 +04:00
|
|
|
*/
|
2016-10-22 12:52:55 +03:00
|
|
|
int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len);
|
2013-03-26 19:04:17 +04:00
|
|
|
|
2014-05-27 16:03:48 +04:00
|
|
|
/**
|
|
|
|
* @qemu_chr_fe_read_all:
|
|
|
|
*
|
|
|
|
* Read data to a buffer from the back end.
|
|
|
|
*
|
|
|
|
* @buf the data buffer
|
|
|
|
* @len the number of bytes to read
|
|
|
|
*
|
2016-12-14 13:27:58 +03:00
|
|
|
* Returns: the number of bytes read (0 if no assicated Chardev)
|
2014-05-27 16:03:48 +04:00
|
|
|
*/
|
2016-10-22 12:52:55 +03:00
|
|
|
int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len);
|
2014-05-27 16:03:48 +04:00
|
|
|
|
2011-08-15 20:17:41 +04:00
|
|
|
/**
|
|
|
|
* @qemu_chr_fe_ioctl:
|
|
|
|
*
|
2014-06-18 10:43:58 +04:00
|
|
|
* Issue a device specific ioctl to a backend. This function is thread-safe.
|
2011-08-15 20:17:41 +04:00
|
|
|
*
|
|
|
|
* @cmd see CHR_IOCTL_*
|
|
|
|
* @arg the data associated with @cmd
|
|
|
|
*
|
2016-10-22 12:52:59 +03:00
|
|
|
* Returns: if @cmd is not supported by the backend or there is no
|
2016-12-14 13:27:58 +03:00
|
|
|
* associated Chardev, -ENOTSUP, otherwise the return
|
2016-10-22 12:52:59 +03:00
|
|
|
* value depends on the semantics of @cmd
|
2011-08-15 20:17:41 +04:00
|
|
|
*/
|
2016-10-22 12:52:55 +03:00
|
|
|
int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg);
|
2011-08-15 20:17:41 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @qemu_chr_fe_get_msgfd:
|
|
|
|
*
|
|
|
|
* For backends capable of fd passing, return the latest file descriptor passed
|
|
|
|
* by a client.
|
|
|
|
*
|
|
|
|
* Returns: -1 if fd passing isn't supported or there is no pending file
|
|
|
|
* descriptor. If a file descriptor is returned, subsequent calls to
|
|
|
|
* this function will return -1 until a client sends a new file
|
|
|
|
* descriptor.
|
|
|
|
*/
|
2016-10-22 12:52:55 +03:00
|
|
|
int qemu_chr_fe_get_msgfd(CharBackend *be);
|
2011-08-15 20:17:41 +04:00
|
|
|
|
2014-05-27 16:04:15 +04:00
|
|
|
/**
|
|
|
|
* @qemu_chr_fe_get_msgfds:
|
|
|
|
*
|
|
|
|
* For backends capable of fd passing, return the number of file received
|
|
|
|
* descriptors and fills the fds array up to num elements
|
|
|
|
*
|
|
|
|
* Returns: -1 if fd passing isn't supported or there are no pending file
|
|
|
|
* descriptors. If file descriptors are returned, subsequent calls to
|
|
|
|
* this function will return -1 until a client sends a new set of file
|
|
|
|
* descriptors.
|
|
|
|
*/
|
2016-10-22 12:52:55 +03:00
|
|
|
int qemu_chr_fe_get_msgfds(CharBackend *be, int *fds, int num);
|
2014-05-27 16:04:15 +04:00
|
|
|
|
2014-05-27 16:04:02 +04:00
|
|
|
/**
|
|
|
|
* @qemu_chr_fe_set_msgfds:
|
|
|
|
*
|
|
|
|
* For backends capable of fd passing, set an array of fds to be passed with
|
|
|
|
* the next send operation.
|
|
|
|
* A subsequent call to this function before calling a write function will
|
|
|
|
* result in overwriting the fd array with the new value without being send.
|
|
|
|
* Upon writing the message the fd array is freed.
|
|
|
|
*
|
2016-12-14 13:27:58 +03:00
|
|
|
* Returns: -1 if fd passing isn't supported or no associated Chardev.
|
2014-05-27 16:04:02 +04:00
|
|
|
*/
|
2016-10-22 12:52:55 +03:00
|
|
|
int qemu_chr_fe_set_msgfds(CharBackend *be, int *fds, int num);
|
2014-05-27 16:04:02 +04:00
|
|
|
|
2011-08-15 20:17:41 +04:00
|
|
|
/**
|
|
|
|
* @qemu_chr_be_can_write:
|
|
|
|
*
|
|
|
|
* Determine how much data the front end can currently accept. This function
|
|
|
|
* returns the number of bytes the front end can accept. If it returns 0, the
|
|
|
|
* front end cannot receive data at the moment. The function must be polled
|
|
|
|
* to determine when data can be received.
|
|
|
|
*
|
|
|
|
* Returns: the number of bytes the front end can receive via @qemu_chr_be_write
|
|
|
|
*/
|
2016-12-07 16:20:22 +03:00
|
|
|
int qemu_chr_be_can_write(Chardev *s);
|
2011-08-15 20:17:41 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @qemu_chr_be_write:
|
|
|
|
*
|
|
|
|
* Write data from the back end to the front end. Before issuing this call,
|
|
|
|
* the caller should call @qemu_chr_be_can_write to determine how much data
|
|
|
|
* the front end can currently accept.
|
|
|
|
*
|
|
|
|
* @buf a buffer to receive data from the front end
|
|
|
|
* @len the number of bytes to receive from the front end
|
|
|
|
*/
|
2016-12-07 16:20:22 +03:00
|
|
|
void qemu_chr_be_write(Chardev *s, uint8_t *buf, int len);
|
2011-08-15 20:17:41 +04:00
|
|
|
|
2016-03-14 10:44:36 +03:00
|
|
|
/**
|
|
|
|
* @qemu_chr_be_write_impl:
|
|
|
|
*
|
|
|
|
* Implementation of back end writing. Used by replay module.
|
|
|
|
*
|
|
|
|
* @buf a buffer to receive data from the front end
|
|
|
|
* @len the number of bytes to receive from the front end
|
|
|
|
*/
|
2016-12-07 16:20:22 +03:00
|
|
|
void qemu_chr_be_write_impl(Chardev *s, uint8_t *buf, int len);
|
2011-11-19 13:22:43 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @qemu_chr_be_event:
|
|
|
|
*
|
|
|
|
* Send an event from the back end to the front end.
|
|
|
|
*
|
|
|
|
* @event the event to send
|
|
|
|
*/
|
2016-12-07 16:20:22 +03:00
|
|
|
void qemu_chr_be_event(Chardev *s, int event);
|
2011-11-19 13:22:43 +04:00
|
|
|
|
2016-10-22 12:52:49 +03:00
|
|
|
/**
|
|
|
|
* @qemu_chr_fe_init:
|
|
|
|
*
|
2016-10-22 12:52:55 +03:00
|
|
|
* Initializes a front end for the given CharBackend and
|
2016-12-14 13:27:58 +03:00
|
|
|
* Chardev. Call qemu_chr_fe_deinit() to remove the association and
|
2016-10-22 12:52:58 +03:00
|
|
|
* release the driver.
|
2016-10-22 12:52:49 +03:00
|
|
|
*
|
|
|
|
* Returns: false on error.
|
|
|
|
*/
|
2016-12-07 16:20:22 +03:00
|
|
|
bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp);
|
2016-10-22 12:52:49 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @qemu_chr_fe_get_driver:
|
|
|
|
*
|
2016-10-22 12:52:59 +03:00
|
|
|
* Returns the driver associated with a CharBackend or NULL if no
|
2016-12-14 13:27:58 +03:00
|
|
|
* associated Chardev.
|
2016-10-22 12:52:49 +03:00
|
|
|
*/
|
2016-12-07 16:20:22 +03:00
|
|
|
Chardev *qemu_chr_fe_get_driver(CharBackend *be);
|
2016-10-22 12:52:49 +03:00
|
|
|
|
2016-10-22 12:52:58 +03:00
|
|
|
/**
|
|
|
|
* @qemu_chr_fe_deinit:
|
|
|
|
*
|
2016-12-14 13:27:58 +03:00
|
|
|
* Dissociate the CharBackend from the Chardev.
|
2016-10-22 12:52:59 +03:00
|
|
|
*
|
2016-12-14 13:27:58 +03:00
|
|
|
* Safe to call without associated Chardev.
|
2016-10-22 12:52:58 +03:00
|
|
|
*/
|
|
|
|
void qemu_chr_fe_deinit(CharBackend *b);
|
|
|
|
|
2016-10-22 12:52:49 +03:00
|
|
|
/**
|
|
|
|
* @qemu_chr_fe_set_handlers:
|
|
|
|
* @b: a CharBackend
|
|
|
|
* @fd_can_read: callback to get the amount of data the frontend may
|
|
|
|
* receive
|
|
|
|
* @fd_read: callback to receive data from char
|
|
|
|
* @fd_event: event callback
|
|
|
|
* @opaque: an opaque pointer for the callbacks
|
|
|
|
* @context: a main loop context or NULL for the default
|
2016-10-22 12:53:03 +03:00
|
|
|
* @set_open: whether to call qemu_chr_fe_set_open() implicitely when
|
|
|
|
* any of the handler is non-NULL
|
2016-10-22 12:52:49 +03:00
|
|
|
*
|
2016-10-22 12:52:56 +03:00
|
|
|
* Set the front end char handlers. The front end takes the focus if
|
|
|
|
* any of the handler is non-NULL.
|
2016-10-22 12:52:59 +03:00
|
|
|
*
|
2016-12-14 13:27:58 +03:00
|
|
|
* Without associated Chardev, nothing is changed.
|
2016-10-22 12:52:49 +03:00
|
|
|
*/
|
|
|
|
void qemu_chr_fe_set_handlers(CharBackend *b,
|
|
|
|
IOCanReadHandler *fd_can_read,
|
|
|
|
IOReadHandler *fd_read,
|
|
|
|
IOEventHandler *fd_event,
|
|
|
|
void *opaque,
|
2016-10-22 12:53:03 +03:00
|
|
|
GMainContext *context,
|
|
|
|
bool set_open);
|
2016-10-22 12:52:49 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @qemu_chr_fe_take_focus:
|
|
|
|
*
|
2016-10-22 12:52:59 +03:00
|
|
|
* Take the focus (if the front end is muxed).
|
|
|
|
*
|
2016-12-14 13:27:58 +03:00
|
|
|
* Without associated Chardev, nothing is changed.
|
2016-10-22 12:52:49 +03:00
|
|
|
*/
|
|
|
|
void qemu_chr_fe_take_focus(CharBackend *b);
|
|
|
|
|
2016-12-07 16:20:22 +03:00
|
|
|
void qemu_chr_be_generic_open(Chardev *s);
|
2016-10-22 12:52:55 +03:00
|
|
|
void qemu_chr_fe_accept_input(CharBackend *be);
|
2016-12-07 16:20:22 +03:00
|
|
|
int qemu_chr_add_client(Chardev *s, int fd);
|
|
|
|
Chardev *qemu_chr_find(const char *name);
|
2016-10-21 22:38:41 +03:00
|
|
|
|
2016-12-07 16:20:22 +03:00
|
|
|
bool qemu_chr_has_feature(Chardev *chr,
|
2016-12-14 13:27:58 +03:00
|
|
|
ChardevFeature feature);
|
2016-12-07 16:20:22 +03:00
|
|
|
void qemu_chr_set_feature(Chardev *chr,
|
2016-12-14 13:27:58 +03:00
|
|
|
ChardevFeature feature);
|
2011-08-15 20:17:41 +04:00
|
|
|
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
|
2016-12-12 15:06:14 +03:00
|
|
|
int qemu_chr_write_all(Chardev *s, const uint8_t *buf, int len);
|
2016-12-12 18:41:00 +03:00
|
|
|
int qemu_chr_wait_connected(Chardev *chr, Error **errp);
|
2011-08-15 20:17:41 +04:00
|
|
|
|
2016-12-07 18:39:10 +03:00
|
|
|
#define TYPE_CHARDEV "chardev"
|
|
|
|
#define CHARDEV(obj) OBJECT_CHECK(Chardev, (obj), TYPE_CHARDEV)
|
|
|
|
#define CHARDEV_CLASS(klass) \
|
|
|
|
OBJECT_CLASS_CHECK(ChardevClass, (klass), TYPE_CHARDEV)
|
|
|
|
#define CHARDEV_GET_CLASS(obj) \
|
|
|
|
OBJECT_GET_CLASS(ChardevClass, (obj), TYPE_CHARDEV)
|
|
|
|
|
|
|
|
#define TYPE_CHARDEV_NULL "chardev-null"
|
|
|
|
#define TYPE_CHARDEV_MUX "chardev-mux"
|
|
|
|
#define TYPE_CHARDEV_RINGBUF "chardev-ringbuf"
|
|
|
|
#define TYPE_CHARDEV_PTY "chardev-pty"
|
|
|
|
#define TYPE_CHARDEV_CONSOLE "chardev-console"
|
|
|
|
#define TYPE_CHARDEV_STDIO "chardev-stdio"
|
|
|
|
#define TYPE_CHARDEV_PIPE "chardev-pipe"
|
|
|
|
#define TYPE_CHARDEV_MEMORY "chardev-memory"
|
|
|
|
#define TYPE_CHARDEV_PARALLEL "chardev-parallel"
|
|
|
|
#define TYPE_CHARDEV_FILE "chardev-file"
|
|
|
|
#define TYPE_CHARDEV_SERIAL "chardev-serial"
|
|
|
|
#define TYPE_CHARDEV_SOCKET "chardev-socket"
|
|
|
|
#define TYPE_CHARDEV_UDP "chardev-udp"
|
|
|
|
|
|
|
|
#define CHARDEV_IS_RINGBUF(chr) \
|
|
|
|
object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_RINGBUF)
|
|
|
|
#define CHARDEV_IS_PTY(chr) \
|
|
|
|
object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_PTY)
|
|
|
|
|
|
|
|
typedef struct ChardevClass {
|
|
|
|
ObjectClass parent_class;
|
|
|
|
|
|
|
|
bool internal; /* TODO: eventually use TYPE_USER_CREATABLE */
|
2016-12-09 00:50:12 +03:00
|
|
|
void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp);
|
2016-12-07 18:39:10 +03:00
|
|
|
|
|
|
|
void (*open)(Chardev *chr, ChardevBackend *backend,
|
|
|
|
bool *be_opened, Error **errp);
|
|
|
|
|
|
|
|
int (*chr_write)(Chardev *s, const uint8_t *buf, int len);
|
|
|
|
int (*chr_sync_read)(Chardev *s, const uint8_t *buf, int len);
|
|
|
|
GSource *(*chr_add_watch)(Chardev *s, GIOCondition cond);
|
|
|
|
void (*chr_update_read_handler)(Chardev *s, GMainContext *context);
|
|
|
|
int (*chr_ioctl)(Chardev *s, int cmd, void *arg);
|
|
|
|
int (*get_msgfds)(Chardev *s, int* fds, int num);
|
|
|
|
int (*set_msgfds)(Chardev *s, int *fds, int num);
|
|
|
|
int (*chr_add_client)(Chardev *chr, int fd);
|
|
|
|
int (*chr_wait_connected)(Chardev *chr, Error **errp);
|
|
|
|
void (*chr_disconnect)(Chardev *chr);
|
|
|
|
void (*chr_accept_input)(Chardev *chr);
|
|
|
|
void (*chr_set_echo)(Chardev *chr, bool echo);
|
|
|
|
void (*chr_set_fe_open)(Chardev *chr, int fe_open);
|
|
|
|
} ChardevClass;
|
|
|
|
|
|
|
|
Chardev *qemu_chardev_new(const char *id, const char *typename,
|
|
|
|
ChardevBackend *backend, Error **errp);
|
|
|
|
|
2008-10-31 21:44:40 +03:00
|
|
|
extern int term_escape_char;
|
|
|
|
|
2014-06-23 11:29:07 +04:00
|
|
|
/* console.c */
|
2016-12-07 15:13:50 +03:00
|
|
|
void qemu_chr_parse_vc(QemuOpts *opts, ChardevBackend *backend, Error **errp);
|
2015-09-29 16:49:06 +03:00
|
|
|
|
2007-11-17 20:14:51 +03:00
|
|
|
#endif
|