mirror of https://github.com/xemu-project/xemu.git
Merge remote branch 'amit/for-anthony' into staging
This commit is contained in:
commit
56d7a964a5
|
@ -351,8 +351,13 @@ static int parse_chr(DeviceState *dev, Property *prop, const char *str)
|
||||||
CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
|
CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||||
|
|
||||||
*ptr = qemu_chr_find(str);
|
*ptr = qemu_chr_find(str);
|
||||||
if (*ptr == NULL)
|
if (*ptr == NULL) {
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
if ((*ptr)->assigned) {
|
||||||
|
return -EEXIST;
|
||||||
|
}
|
||||||
|
(*ptr)->assigned = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu-char.h"
|
#include "qemu-char.h"
|
||||||
|
#include "qemu-error.h"
|
||||||
#include "virtio-serial.h"
|
#include "virtio-serial.h"
|
||||||
|
|
||||||
typedef struct VirtConsole {
|
typedef struct VirtConsole {
|
||||||
|
@ -81,8 +82,11 @@ static int virtconsole_exitfn(VirtIOSerialPort *port)
|
||||||
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
|
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
|
||||||
|
|
||||||
if (vcon->chr) {
|
if (vcon->chr) {
|
||||||
port->info->have_data = NULL;
|
/*
|
||||||
qemu_chr_close(vcon->chr);
|
* Instead of closing the chardev, free it so it can be used
|
||||||
|
* for other purposes.
|
||||||
|
*/
|
||||||
|
qemu_chr_add_handlers(vcon->chr, NULL, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -113,6 +117,14 @@ static int virtserialport_initfn(VirtIOSerialPort *port)
|
||||||
{
|
{
|
||||||
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
|
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
|
||||||
|
|
||||||
|
if (port->id == 0) {
|
||||||
|
/*
|
||||||
|
* Disallow a generic port at id 0, that's reserved for
|
||||||
|
* console ports.
|
||||||
|
*/
|
||||||
|
error_report("Port number 0 on virtio-serial devices reserved for virtconsole devices for backward compatibility.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return generic_port_init(vcon, port);
|
return generic_port_init(vcon, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "virtio.h"
|
#include "virtio.h"
|
||||||
#include "virtio-blk.h"
|
#include "virtio-blk.h"
|
||||||
#include "virtio-net.h"
|
#include "virtio-net.h"
|
||||||
|
#include "virtio-serial.h"
|
||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
#include "qemu-error.h"
|
#include "qemu-error.h"
|
||||||
#include "msix.h"
|
#include "msix.h"
|
||||||
|
@ -109,8 +110,7 @@ typedef struct {
|
||||||
#ifdef CONFIG_LINUX
|
#ifdef CONFIG_LINUX
|
||||||
V9fsConf fsconf;
|
V9fsConf fsconf;
|
||||||
#endif
|
#endif
|
||||||
/* Max. number of ports we can have for a the virtio-serial device */
|
virtio_serial_conf serial;
|
||||||
uint32_t max_virtserial_ports;
|
|
||||||
virtio_net_conf net;
|
virtio_net_conf net;
|
||||||
bool ioeventfd_disabled;
|
bool ioeventfd_disabled;
|
||||||
bool ioeventfd_started;
|
bool ioeventfd_started;
|
||||||
|
@ -770,12 +770,12 @@ static int virtio_serial_init_pci(PCIDevice *pci_dev)
|
||||||
proxy->class_code != PCI_CLASS_OTHERS) /* qemu-kvm */
|
proxy->class_code != PCI_CLASS_OTHERS) /* qemu-kvm */
|
||||||
proxy->class_code = PCI_CLASS_COMMUNICATION_OTHER;
|
proxy->class_code = PCI_CLASS_COMMUNICATION_OTHER;
|
||||||
|
|
||||||
vdev = virtio_serial_init(&pci_dev->qdev, proxy->max_virtserial_ports);
|
vdev = virtio_serial_init(&pci_dev->qdev, &proxy->serial);
|
||||||
if (!vdev) {
|
if (!vdev) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
vdev->nvectors = proxy->nvectors == DEV_NVECTORS_UNSPECIFIED
|
vdev->nvectors = proxy->nvectors == DEV_NVECTORS_UNSPECIFIED
|
||||||
? proxy->max_virtserial_ports + 1
|
? proxy->serial.max_virtserial_ports + 1
|
||||||
: proxy->nvectors;
|
: proxy->nvectors;
|
||||||
virtio_init_pci(proxy, vdev,
|
virtio_init_pci(proxy, vdev,
|
||||||
PCI_VENDOR_ID_REDHAT_QUMRANET,
|
PCI_VENDOR_ID_REDHAT_QUMRANET,
|
||||||
|
@ -789,6 +789,7 @@ static int virtio_serial_exit_pci(PCIDevice *pci_dev)
|
||||||
{
|
{
|
||||||
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
|
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
|
||||||
|
|
||||||
|
virtio_pci_stop_ioeventfd(proxy);
|
||||||
virtio_serial_exit(proxy->vdev);
|
virtio_serial_exit(proxy->vdev);
|
||||||
return virtio_exit_pci(pci_dev);
|
return virtio_exit_pci(pci_dev);
|
||||||
}
|
}
|
||||||
|
@ -898,12 +899,14 @@ static PCIDeviceInfo virtio_info[] = {
|
||||||
.init = virtio_serial_init_pci,
|
.init = virtio_serial_init_pci,
|
||||||
.exit = virtio_serial_exit_pci,
|
.exit = virtio_serial_exit_pci,
|
||||||
.qdev.props = (Property[]) {
|
.qdev.props = (Property[]) {
|
||||||
|
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
|
||||||
|
VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
|
||||||
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
|
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
|
||||||
DEV_NVECTORS_UNSPECIFIED),
|
DEV_NVECTORS_UNSPECIFIED),
|
||||||
DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
|
DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
|
||||||
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
|
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
|
||||||
DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy, max_virtserial_ports,
|
DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy,
|
||||||
31),
|
serial.max_virtserial_ports, 31),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
},
|
},
|
||||||
.qdev.reset = virtio_pci_reset,
|
.qdev.reset = virtio_pci_reset,
|
||||||
|
|
|
@ -442,25 +442,19 @@ static void handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||||
{
|
{
|
||||||
VirtIOSerial *vser;
|
VirtIOSerial *vser;
|
||||||
VirtIOSerialPort *port;
|
VirtIOSerialPort *port;
|
||||||
bool discard;
|
|
||||||
|
|
||||||
vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
|
vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
|
||||||
port = find_port_by_vq(vser, vq);
|
port = find_port_by_vq(vser, vq);
|
||||||
|
|
||||||
discard = false;
|
|
||||||
if (!port || !port->host_connected || !port->info->have_data) {
|
if (!port || !port->host_connected || !port->info->have_data) {
|
||||||
discard = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (discard) {
|
|
||||||
discard_vq_data(vq, vdev);
|
discard_vq_data(vq, vdev);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (port->throttled) {
|
|
||||||
|
if (!port->throttled) {
|
||||||
|
do_flush_queued_data(port, vq, vdev);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
do_flush_queued_data(port, vq, vdev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
|
static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
|
||||||
|
@ -811,19 +805,19 @@ void virtio_serial_port_qdev_register(VirtIOSerialPortInfo *info)
|
||||||
qdev_register(&info->qdev);
|
qdev_register(&info->qdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
|
VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf)
|
||||||
{
|
{
|
||||||
VirtIOSerial *vser;
|
VirtIOSerial *vser;
|
||||||
VirtIODevice *vdev;
|
VirtIODevice *vdev;
|
||||||
uint32_t i, max_supported_ports;
|
uint32_t i, max_supported_ports;
|
||||||
|
|
||||||
if (!max_nr_ports)
|
if (!conf->max_virtserial_ports)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Each port takes 2 queues, and one pair is for the control queue */
|
/* Each port takes 2 queues, and one pair is for the control queue */
|
||||||
max_supported_ports = VIRTIO_PCI_QUEUE_MAX / 2 - 1;
|
max_supported_ports = VIRTIO_PCI_QUEUE_MAX / 2 - 1;
|
||||||
|
|
||||||
if (max_nr_ports > max_supported_ports) {
|
if (conf->max_virtserial_ports > max_supported_ports) {
|
||||||
error_report("maximum ports supported: %u", max_supported_ports);
|
error_report("maximum ports supported: %u", max_supported_ports);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -839,9 +833,9 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
|
||||||
vser->bus->vser = vser;
|
vser->bus->vser = vser;
|
||||||
QTAILQ_INIT(&vser->ports);
|
QTAILQ_INIT(&vser->ports);
|
||||||
|
|
||||||
vser->bus->max_nr_ports = max_nr_ports;
|
vser->bus->max_nr_ports = conf->max_virtserial_ports;
|
||||||
vser->ivqs = qemu_malloc(max_nr_ports * sizeof(VirtQueue *));
|
vser->ivqs = qemu_malloc(conf->max_virtserial_ports * sizeof(VirtQueue *));
|
||||||
vser->ovqs = qemu_malloc(max_nr_ports * sizeof(VirtQueue *));
|
vser->ovqs = qemu_malloc(conf->max_virtserial_ports * sizeof(VirtQueue *));
|
||||||
|
|
||||||
/* Add a queue for host to guest transfers for port 0 (backward compat) */
|
/* Add a queue for host to guest transfers for port 0 (backward compat) */
|
||||||
vser->ivqs[0] = virtio_add_queue(vdev, 128, handle_input);
|
vser->ivqs[0] = virtio_add_queue(vdev, 128, handle_input);
|
||||||
|
@ -866,8 +860,8 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
|
||||||
vser->ovqs[i] = virtio_add_queue(vdev, 128, handle_output);
|
vser->ovqs[i] = virtio_add_queue(vdev, 128, handle_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
vser->config.max_nr_ports = max_nr_ports;
|
vser->config.max_nr_ports = conf->max_virtserial_ports;
|
||||||
vser->ports_map = qemu_mallocz(((max_nr_ports + 31) / 32)
|
vser->ports_map = qemu_mallocz(((conf->max_virtserial_ports + 31) / 32)
|
||||||
* sizeof(vser->ports_map[0]));
|
* sizeof(vser->ports_map[0]));
|
||||||
/*
|
/*
|
||||||
* Reserve location 0 for a console port for backward compat
|
* Reserve location 0 for a console port for backward compat
|
||||||
|
|
|
@ -45,6 +45,11 @@ struct virtio_console_control {
|
||||||
uint16_t value; /* Extra information for the key */
|
uint16_t value; /* Extra information for the key */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct virtio_serial_conf {
|
||||||
|
/* Max. number of ports we can have for a virtio-serial device */
|
||||||
|
uint32_t max_virtserial_ports;
|
||||||
|
};
|
||||||
|
|
||||||
/* Some events for the internal messages (control packets) */
|
/* Some events for the internal messages (control packets) */
|
||||||
#define VIRTIO_CONSOLE_DEVICE_READY 0
|
#define VIRTIO_CONSOLE_DEVICE_READY 0
|
||||||
#define VIRTIO_CONSOLE_PORT_ADD 1
|
#define VIRTIO_CONSOLE_PORT_ADD 1
|
||||||
|
|
|
@ -195,7 +195,8 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf);
|
||||||
struct virtio_net_conf;
|
struct virtio_net_conf;
|
||||||
VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
|
VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
|
||||||
struct virtio_net_conf *net);
|
struct virtio_net_conf *net);
|
||||||
VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports);
|
typedef struct virtio_serial_conf virtio_serial_conf;
|
||||||
|
VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *serial);
|
||||||
VirtIODevice *virtio_balloon_init(DeviceState *dev);
|
VirtIODevice *virtio_balloon_init(DeviceState *dev);
|
||||||
#ifdef CONFIG_LINUX
|
#ifdef CONFIG_LINUX
|
||||||
VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
|
VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
|
||||||
|
|
|
@ -197,6 +197,10 @@ void qemu_chr_add_handlers(CharDriverState *s,
|
||||||
IOEventHandler *fd_event,
|
IOEventHandler *fd_event,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
|
if (!opaque) {
|
||||||
|
/* chr driver being released. */
|
||||||
|
s->assigned = 0;
|
||||||
|
}
|
||||||
s->chr_can_read = fd_can_read;
|
s->chr_can_read = fd_can_read;
|
||||||
s->chr_read = fd_read;
|
s->chr_read = fd_read;
|
||||||
s->chr_event = fd_event;
|
s->chr_event = fd_event;
|
||||||
|
|
|
@ -70,6 +70,7 @@ struct CharDriverState {
|
||||||
char *label;
|
char *label;
|
||||||
char *filename;
|
char *filename;
|
||||||
int opened;
|
int opened;
|
||||||
|
int assigned; /* chardev assigned to a device */
|
||||||
QTAILQ_ENTRY(CharDriverState) next;
|
QTAILQ_ENTRY(CharDriverState) next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue