aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rwxr-xr-xconfigure16
-rw-r--r--docs/spice-port-fqdn.txt19
-rw-r--r--hw/arm_gic.c2
-rw-r--r--hw/pflash_cfi01.c14
-rw-r--r--hw/pflash_cfi02.c6
-rw-r--r--hw/qxl-render.c11
-rw-r--r--hw/virtio-serial-bus.c195
-rw-r--r--hw/vmmouse.c1
-rw-r--r--hw/xen_console.c28
-rw-r--r--hw/xen_pt.c5
-rw-r--r--hw/xen_pt_msi.c2
-rw-r--r--hw/zynq_slcr.c7
-rw-r--r--include/ui/qemu-spice.h4
-rw-r--r--linux-user/syscall.c2
-rw-r--r--net/hub.c2
-rw-r--r--qemu-char.c3
-rw-r--r--qemu-options.hx13
-rw-r--r--spice-qemu-char.c107
-rw-r--r--trace-events1
-rw-r--r--ui/spice-core.c6
-rw-r--r--user-exec.c2
-rw-r--r--xen-all.c83
23 files changed, 356 insertions, 174 deletions
diff --git a/.gitignore b/.gitignore
index ca52f01ab2..3a417656e2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -48,6 +48,7 @@ test-qmp-output-visitor
test-string-input-visitor
test-string-output-visitor
test-visitor-serialization
+fsdev/virtfs-proxy-helper
fsdev/virtfs-proxy-helper.1
fsdev/virtfs-proxy-helper.pod
.gdbinit
diff --git a/configure b/configure
index c989fece9a..b101d5c1b7 100755
--- a/configure
+++ b/configure
@@ -1360,6 +1360,14 @@ esac
fi
##########################################
+# pkg-config probe
+
+if ! has "$pkg_config_exe"; then
+ echo "Error: pkg-config binary '$pkg_config_exe' not found"
+ exit 1
+fi
+
+##########################################
# NPTL probe
if test "$nptl" != "no" ; then
@@ -1590,14 +1598,6 @@ if test "$xen_pci_passthrough" != "no"; then
fi
##########################################
-# pkg-config probe
-
-if ! has "$pkg_config_exe"; then
- echo "Error: pkg-config binary '$pkg_config_exe' not found"
- exit 1
-fi
-
-##########################################
# libtool probe
if ! has $libtool; then
diff --git a/docs/spice-port-fqdn.txt b/docs/spice-port-fqdn.txt
new file mode 100644
index 0000000000..50778952e5
--- /dev/null
+++ b/docs/spice-port-fqdn.txt
@@ -0,0 +1,19 @@
+A Spice port channel is an arbitrary communication between the Spice
+server host side and the client side.
+
+Thanks to the associated reverse fully qualified domain name (fqdn),
+a Spice client can handle the various ports appropriately.
+
+The following fqdn names are reserved by the QEMU project:
+
+org.qemu.monitor.hmp.0
+ QEMU human monitor
+
+org.qemu.monitor.qmp.0:
+ QEMU control monitor
+
+org.qemu.console.serial.0
+ QEMU virtual serial port
+
+org.qemu.console.debug.0
+ QEMU debug console
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 8d769de4f5..b6062c4241 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -76,7 +76,7 @@ void gic_update(GICState *s)
if (best_prio < s->priority_mask[cpu]) {
s->current_pending[cpu] = best_irq;
if (best_prio < s->running_priority[cpu]) {
- DPRINTF("Raised pending IRQ %d\n", best_irq);
+ DPRINTF("Raised pending IRQ %d (cpu %d)\n", best_irq, cpu);
level = 1;
}
}
diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c
index 59982dcd6f..95e07e7cdb 100644
--- a/hw/pflash_cfi01.c
+++ b/hw/pflash_cfi01.c
@@ -46,15 +46,15 @@
#define PFLASH_BUG(fmt, ...) \
do { \
- printf("PFLASH: Possible BUG - " fmt, ## __VA_ARGS__); \
+ fprintf(stderr, "PFLASH: Possible BUG - " fmt, ## __VA_ARGS__); \
exit(1); \
} while(0)
/* #define PFLASH_DEBUG */
#ifdef PFLASH_DEBUG
-#define DPRINTF(fmt, ...) \
-do { \
- printf("PFLASH: " fmt , ## __VA_ARGS__); \
+#define DPRINTF(fmt, ...) \
+do { \
+ fprintf(stderr, "PFLASH: " fmt , ## __VA_ARGS__); \
} while (0)
#else
#define DPRINTF(fmt, ...) do { } while (0)
@@ -438,9 +438,9 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
return;
error_flash:
- printf("%s: Unimplemented flash cmd sequence "
- "(offset " TARGET_FMT_plx ", wcycle 0x%x cmd 0x%x value 0x%x)\n",
- __func__, offset, pfl->wcycle, pfl->cmd, value);
+ qemu_log_mask(LOG_UNIMP, "%s: Unimplemented flash cmd sequence "
+ "(offset " TARGET_FMT_plx ", wcycle 0x%x cmd 0x%x value 0x%x)"
+ "\n", __func__, offset, pfl->wcycle, pfl->cmd, value);
reset_flash:
memory_region_rom_device_set_readable(&pfl->mem, true);
diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c
index 6924f064c2..cfb91cb143 100644
--- a/hw/pflash_cfi02.c
+++ b/hw/pflash_cfi02.c
@@ -45,9 +45,9 @@
//#define PFLASH_DEBUG
#ifdef PFLASH_DEBUG
-#define DPRINTF(fmt, ...) \
-do { \
- printf("PFLASH: " fmt , ## __VA_ARGS__); \
+#define DPRINTF(fmt, ...) \
+do { \
+ fprintf(stderr "PFLASH: " fmt , ## __VA_ARGS__); \
} while (0)
#else
#define DPRINTF(fmt, ...) do { } while (0)
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index 98ecb21405..88e63f8085 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -113,11 +113,12 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
qxl->guest_primary.bits_pp);
if (qxl->guest_primary.qxl_stride > 0) {
qemu_free_displaysurface(vga->ds);
- qemu_create_displaysurface_from(qxl->guest_primary.surface.width,
- qxl->guest_primary.surface.height,
- qxl->guest_primary.bits_pp,
- qxl->guest_primary.abs_stride,
- qxl->guest_primary.data);
+ vga->ds->surface = qemu_create_displaysurface_from
+ (qxl->guest_primary.surface.width,
+ qxl->guest_primary.surface.height,
+ qxl->guest_primary.bits_pp,
+ qxl->guest_primary.abs_stride,
+ qxl->guest_primary.data);
} else {
qemu_resize_displaysurface(vga->ds,
qxl->guest_primary.surface.width,
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index fc5cb32277..7272bfd5fe 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -36,6 +36,15 @@ struct VirtIOSerialBus {
uint32_t max_nr_ports;
};
+typedef struct VirtIOSerialPostLoad {
+ QEMUTimer *timer;
+ uint32_t nr_active_ports;
+ struct {
+ VirtIOSerialPort *port;
+ uint8_t host_connected;
+ } *connected;
+} VirtIOSerialPostLoad;
+
struct VirtIOSerial {
VirtIODevice vdev;
@@ -54,14 +63,7 @@ struct VirtIOSerial {
struct virtio_console_config config;
- struct {
- QEMUTimer *timer;
- int nr_active_ports;
- struct {
- VirtIOSerialPort *port;
- uint8_t host_connected;
- } *connected;
- } post_load;
+ struct VirtIOSerialPostLoad *post_load;
};
static VirtIOSerialPort *find_port_by_id(VirtIOSerial *vser, uint32_t id)
@@ -215,13 +217,12 @@ static void flush_queued_data(VirtIOSerialPort *port)
do_flush_queued_data(port, port->ovq, &port->vser->vdev);
}
-static size_t send_control_msg(VirtIOSerialPort *port, void *buf, size_t len)
+static size_t send_control_msg(VirtIOSerial *vser, void *buf, size_t len)
{
VirtQueueElement elem;
VirtQueue *vq;
- struct virtio_console_control *cpkt;
- vq = port->vser->c_ivq;
+ vq = vser->c_ivq;
if (!virtio_queue_ready(vq)) {
return 0;
}
@@ -229,25 +230,24 @@ static size_t send_control_msg(VirtIOSerialPort *port, void *buf, size_t len)
return 0;
}
- cpkt = (struct virtio_console_control *)buf;
- stl_p(&cpkt->id, port->id);
memcpy(elem.in_sg[0].iov_base, buf, len);
virtqueue_push(vq, &elem, len);
- virtio_notify(&port->vser->vdev, vq);
+ virtio_notify(&vser->vdev, vq);
return len;
}
-static size_t send_control_event(VirtIOSerialPort *port, uint16_t event,
- uint16_t value)
+static size_t send_control_event(VirtIOSerial *vser, uint32_t port_id,
+ uint16_t event, uint16_t value)
{
struct virtio_console_control cpkt;
+ stl_p(&cpkt.id, port_id);
stw_p(&cpkt.event, event);
stw_p(&cpkt.value, value);
- trace_virtio_serial_send_control_event(port->id, event, value);
- return send_control_msg(port, &cpkt, sizeof(cpkt));
+ trace_virtio_serial_send_control_event(port_id, event, value);
+ return send_control_msg(vser, &cpkt, sizeof(cpkt));
}
/* Functions for use inside qemu to open and read from/write to ports */
@@ -259,7 +259,7 @@ int virtio_serial_open(VirtIOSerialPort *port)
}
/* Send port open notification to the guest */
port->host_connected = true;
- send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN, 1);
+ send_control_event(port->vser, port->id, VIRTIO_CONSOLE_PORT_OPEN, 1);
return 0;
}
@@ -274,7 +274,7 @@ int virtio_serial_close(VirtIOSerialPort *port)
port->throttled = false;
discard_vq_data(port->ovq, &port->vser->vdev);
- send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
+ send_control_event(port->vser, port->id, VIRTIO_CONSOLE_PORT_OPEN, 0);
return 0;
}
@@ -363,7 +363,7 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
* ports we have here.
*/
QTAILQ_FOREACH(port, &vser->ports, next) {
- send_control_event(port, VIRTIO_CONSOLE_PORT_ADD, 1);
+ send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_ADD, 1);
}
return;
}
@@ -394,10 +394,11 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
* up to hvc.
*/
if (vsc->is_console) {
- send_control_event(port, VIRTIO_CONSOLE_CONSOLE_PORT, 1);
+ send_control_event(vser, port->id, VIRTIO_CONSOLE_CONSOLE_PORT, 1);
}
if (port->name) {
+ stl_p(&cpkt.id, port->id);
stw_p(&cpkt.event, VIRTIO_CONSOLE_PORT_NAME);
stw_p(&cpkt.value, 1);
@@ -408,12 +409,12 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
memcpy(buffer + sizeof(cpkt), port->name, strlen(port->name));
buffer[buffer_len - 1] = 0;
- send_control_msg(port, buffer, buffer_len);
+ send_control_msg(vser, buffer, buffer_len);
g_free(buffer);
}
if (port->host_connected) {
- send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN, 1);
+ send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_OPEN, 1);
}
/*
@@ -637,31 +638,91 @@ static void virtio_serial_save(QEMUFile *f, void *opaque)
static void virtio_serial_post_load_timer_cb(void *opaque)
{
- int i;
+ uint32_t i;
VirtIOSerial *s = opaque;
VirtIOSerialPort *port;
uint8_t host_connected;
- for (i = 0 ; i < s->post_load.nr_active_ports; ++i) {
- port = s->post_load.connected[i].port;
- host_connected = s->post_load.connected[i].host_connected;
+ if (!s->post_load) {
+ return;
+ }
+ for (i = 0 ; i < s->post_load->nr_active_ports; ++i) {
+ port = s->post_load->connected[i].port;
+ host_connected = s->post_load->connected[i].host_connected;
if (host_connected != port->host_connected) {
/*
* We have to let the guest know of the host connection
* status change
*/
- send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN,
+ send_control_event(s, port->id, VIRTIO_CONSOLE_PORT_OPEN,
port->host_connected);
}
}
- g_free(s->post_load.connected);
- s->post_load.connected = NULL;
+ g_free(s->post_load->connected);
+ qemu_free_timer(s->post_load->timer);
+ g_free(s->post_load);
+ s->post_load = NULL;
+}
+
+static int fetch_active_ports_list(QEMUFile *f, int version_id,
+ VirtIOSerial *s, uint32_t nr_active_ports)
+{
+ uint32_t i;
+
+ s->post_load = g_malloc0(sizeof(*s->post_load));
+ s->post_load->nr_active_ports = nr_active_ports;
+ s->post_load->connected =
+ g_malloc0(sizeof(*s->post_load->connected) * nr_active_ports);
+
+ s->post_load->timer = qemu_new_timer_ns(vm_clock,
+ virtio_serial_post_load_timer_cb,
+ s);
+
+ /* Items in struct VirtIOSerialPort */
+ for (i = 0; i < nr_active_ports; i++) {
+ VirtIOSerialPort *port;
+ uint32_t id;
+
+ id = qemu_get_be32(f);
+ port = find_port_by_id(s, id);
+ if (!port) {
+ return -EINVAL;
+ }
+
+ port->guest_connected = qemu_get_byte(f);
+ s->post_load->connected[i].port = port;
+ s->post_load->connected[i].host_connected = qemu_get_byte(f);
+
+ if (version_id > 2) {
+ uint32_t elem_popped;
+
+ qemu_get_be32s(f, &elem_popped);
+ if (elem_popped) {
+ qemu_get_be32s(f, &port->iov_idx);
+ qemu_get_be64s(f, &port->iov_offset);
+
+ qemu_get_buffer(f, (unsigned char *)&port->elem,
+ sizeof(port->elem));
+ virtqueue_map_sg(port->elem.in_sg, port->elem.in_addr,
+ port->elem.in_num, 1);
+ virtqueue_map_sg(port->elem.out_sg, port->elem.out_addr,
+ port->elem.out_num, 1);
+
+ /*
+ * Port was throttled on source machine. Let's
+ * unthrottle it here so data starts flowing again.
+ */
+ virtio_serial_throttle_port(port, false);
+ }
+ }
+ }
+ qemu_mod_timer(s->post_load->timer, 1);
+ return 0;
}
static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
{
VirtIOSerial *s = opaque;
- VirtIOSerialPort *port;
uint32_t max_nr_ports, nr_active_ports, ports_map;
unsigned int i;
int ret;
@@ -705,48 +766,12 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
qemu_get_be32s(f, &nr_active_ports);
- s->post_load.nr_active_ports = nr_active_ports;
- s->post_load.connected =
- g_malloc0(sizeof(*s->post_load.connected) * nr_active_ports);
-
- /* Items in struct VirtIOSerialPort */
- for (i = 0; i < nr_active_ports; i++) {
- uint32_t id;
-
- id = qemu_get_be32(f);
- port = find_port_by_id(s, id);
- if (!port) {
- return -EINVAL;
- }
-
- port->guest_connected = qemu_get_byte(f);
- s->post_load.connected[i].port = port;
- s->post_load.connected[i].host_connected = qemu_get_byte(f);
-
- if (version_id > 2) {
- uint32_t elem_popped;
-
- qemu_get_be32s(f, &elem_popped);
- if (elem_popped) {
- qemu_get_be32s(f, &port->iov_idx);
- qemu_get_be64s(f, &port->iov_offset);
-
- qemu_get_buffer(f, (unsigned char *)&port->elem,
- sizeof(port->elem));
- virtqueue_map_sg(port->elem.in_sg, port->elem.in_addr,
- port->elem.in_num, 1);
- virtqueue_map_sg(port->elem.out_sg, port->elem.out_addr,
- port->elem.out_num, 1);
-
- /*
- * Port was throttled on source machine. Let's
- * unthrottle it here so data starts flowing again.
- */
- virtio_serial_throttle_port(port, false);
- }
+ if (nr_active_ports) {
+ ret = fetch_active_ports_list(f, version_id, s, nr_active_ports);
+ if (ret) {
+ return ret;
}
}
- qemu_mod_timer(s->post_load.timer, 1);
return 0;
}
@@ -815,9 +840,7 @@ static void mark_port_added(VirtIOSerial *vser, uint32_t port_id)
static void add_port(VirtIOSerial *vser, uint32_t port_id)
{
mark_port_added(vser, port_id);
-
- send_control_event(find_port_by_id(vser, port_id),
- VIRTIO_CONSOLE_PORT_ADD, 1);
+ send_control_event(vser, port_id, VIRTIO_CONSOLE_PORT_ADD, 1);
}
static void remove_port(VirtIOSerial *vser, uint32_t port_id)
@@ -829,10 +852,16 @@ static void remove_port(VirtIOSerial *vser, uint32_t port_id)
vser->ports_map[i] &= ~(1U << (port_id % 32));
port = find_port_by_id(vser, port_id);
+ /*
+ * This function is only called from qdev's unplug callback; if we
+ * get a NULL port here, we're in trouble.
+ */
+ assert(port);
+
/* Flush out any unconsumed buffers first */
discard_vq_data(port->ovq, &port->vser->vdev);
- send_control_event(port, VIRTIO_CONSOLE_PORT_REMOVE, 1);
+ send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_REMOVE, 1);
}
static int virtser_port_qdev_init(DeviceState *qdev)
@@ -989,6 +1018,8 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf)
vser->qdev = dev;
+ vser->post_load = NULL;
+
/*
* Register for the savevm section with the virtio-console name
* to preserve backward compat
@@ -996,9 +1027,6 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf)
register_savevm(dev, "virtio-console", -1, 3, virtio_serial_save,
virtio_serial_load, vser);
- vser->post_load.timer = qemu_new_timer_ns(vm_clock,
- virtio_serial_post_load_timer_cb, vser);
-
return vdev;
}
@@ -1011,9 +1039,12 @@ void virtio_serial_exit(VirtIODevice *vdev)
g_free(vser->ivqs);
g_free(vser->ovqs);
g_free(vser->ports_map);
- g_free(vser->post_load.connected);
- qemu_free_timer(vser->post_load.timer);
-
+ if (vser->post_load) {
+ g_free(vser->post_load->connected);
+ qemu_del_timer(vser->post_load->timer);
+ qemu_free_timer(vser->post_load->timer);
+ g_free(vser->post_load);
+ }
virtio_cleanup(vdev);
}
diff --git a/hw/vmmouse.c b/hw/vmmouse.c
index d052f33f56..004d09851c 100644
--- a/hw/vmmouse.c
+++ b/hw/vmmouse.c
@@ -252,7 +252,6 @@ static void vmmouse_reset(DeviceState *d)
{
VMMouseState *s = container_of(d, VMMouseState, dev.qdev);
- s->status = 0xffff;
s->queue_size = VMMOUSE_QUEUE_SIZE;
vmmouse_disable(s);
diff --git a/hw/xen_console.c b/hw/xen_console.c
index ac36ceb47c..44141f8692 100644
--- a/hw/xen_console.c
+++ b/hw/xen_console.c
@@ -184,7 +184,11 @@ static int con_init(struct XenDevice *xendev)
/* setup */
dom = xs_get_domain_path(xenstore, con->xendev.dom);
- snprintf(con->console, sizeof(con->console), "%s/console", dom);
+ if (!xendev->dev) {
+ snprintf(con->console, sizeof(con->console), "%s/console", dom);
+ } else {
+ snprintf(con->console, sizeof(con->console), "%s/device/console/%d", dom, xendev->dev);
+ }
free(dom);
type = xenstore_read_str(con->console, "type");
@@ -223,10 +227,16 @@ static int con_initialise(struct XenDevice *xendev)
if (xenstore_read_int(con->console, "limit", &limit) == 0)
con->buffer.max_capacity = limit;
- con->sring = xc_map_foreign_range(xen_xc, con->xendev.dom,
- XC_PAGE_SIZE,
- PROT_READ|PROT_WRITE,
- con->ring_ref);
+ if (!xendev->dev) {
+ con->sring = xc_map_foreign_range(xen_xc, con->xendev.dom,
+ XC_PAGE_SIZE,
+ PROT_READ|PROT_WRITE,
+ con->ring_ref);
+ } else {
+ con->sring = xc_gnttab_map_grant_ref(xendev->gnttabdev, con->xendev.dom,
+ con->ring_ref,
+ PROT_READ|PROT_WRITE);
+ }
if (!con->sring)
return -1;
@@ -255,7 +265,11 @@ static void con_disconnect(struct XenDevice *xendev)
xen_be_unbind_evtchn(&con->xendev);
if (con->sring) {
- munmap(con->sring, XC_PAGE_SIZE);
+ if (!xendev->gnttabdev) {
+ munmap(con->sring, XC_PAGE_SIZE);
+ } else {
+ xc_gnttab_munmap(xendev->gnttabdev, con->sring, 1);
+ }
con->sring = NULL;
}
}
@@ -273,7 +287,7 @@ static void con_event(struct XenDevice *xendev)
struct XenDevOps xen_console_ops = {
.size = sizeof(struct XenConsole),
- .flags = DEVOPS_FLAG_IGNORE_STATE,
+ .flags = DEVOPS_FLAG_IGNORE_STATE|DEVOPS_FLAG_NEED_GNTDEV,
.init = con_init,
.initialise = con_initialise,
.event = con_event,
diff --git a/hw/xen_pt.c b/hw/xen_pt.c
index 9ebd028f2e..6fd8433a2d 100644
--- a/hw/xen_pt.c
+++ b/hw/xen_pt.c
@@ -671,7 +671,8 @@ static int xen_pt_initfn(PCIDevice *d)
s->is_virtfn = s->real_device.is_virtfn;
if (s->is_virtfn) {
XEN_PT_LOG(d, "%04x:%02x:%02x.%d is a SR-IOV Virtual Function\n",
- s->real_device.domain, bus, slot, func);
+ s->real_device.domain, s->real_device.bus,
+ s->real_device.dev, s->real_device.func);
}
/* Initialize virtualized PCI configuration (Extended 256 Bytes) */
@@ -752,7 +753,7 @@ out:
memory_listener_register(&s->memory_listener, &address_space_memory);
memory_listener_register(&s->io_listener, &address_space_io);
XEN_PT_LOG(d, "Real physical device %02x:%02x.%d registered successfuly!\n",
- bus, slot, func);
+ s->hostaddr.bus, s->hostaddr.slot, s->hostaddr.function);
return 0;
}
diff --git a/hw/xen_pt_msi.c b/hw/xen_pt_msi.c
index 680767229b..db757cd1f1 100644
--- a/hw/xen_pt_msi.c
+++ b/hw/xen_pt_msi.c
@@ -321,7 +321,7 @@ static int xen_pt_msix_update_one(XenPCIPassthroughState *s, int entry_nr)
pirq = entry->pirq;
- rc = msi_msix_setup(s, entry->data, entry->data, &pirq, true, entry_nr,
+ rc = msi_msix_setup(s, entry->addr, entry->data, &pirq, true, entry_nr,
entry->pirq == XEN_PT_UNASSIGNED_PIRQ);
if (rc) {
return rc;
diff --git a/hw/zynq_slcr.c b/hw/zynq_slcr.c
index 97ec578262..143a7cf436 100644
--- a/hw/zynq_slcr.c
+++ b/hw/zynq_slcr.c
@@ -334,7 +334,7 @@ static uint64_t zynq_slcr_read(void *opaque, hwaddr offset,
{
uint32_t ret = zynq_slcr_read_imp(opaque, offset);
- DB_PRINT("addr: %08x data: %08x\n", offset, ret);
+ DB_PRINT("addr: %08x data: %08x\n", (unsigned)offset, (unsigned)ret);
return ret;
}
@@ -343,7 +343,7 @@ static void zynq_slcr_write(void *opaque, hwaddr offset,
{
ZynqSLCRState *s = (ZynqSLCRState *)opaque;
- DB_PRINT("offset: %08x data: %08x\n", offset, (unsigned)val);
+ DB_PRINT("offset: %08x data: %08x\n", (unsigned)offset, (unsigned)val);
switch (offset) {
case 0x00: /* SCL */
@@ -476,7 +476,8 @@ static void zynq_slcr_write(void *opaque, hwaddr offset,
break;
default:
bad_reg:
- DB_PRINT("Bad register write %x <= %08x\n", (int)offset, val);
+ DB_PRINT("Bad register write %x <= %08x\n", (int)offset,
+ (unsigned)val);
}
} else {
DB_PRINT("SCLR registers are locked. Unlock them first\n");
diff --git a/include/ui/qemu-spice.h b/include/ui/qemu-spice.h
index 73422adeee..5a78fd764d 100644
--- a/include/ui/qemu-spice.h
+++ b/include/ui/qemu-spice.h
@@ -45,6 +45,10 @@ void do_info_spice_print(Monitor *mon, const QObject *data);
void do_info_spice(Monitor *mon, QObject **ret_data);
CharDriverState *qemu_chr_open_spice(QemuOpts *opts);
+#if SPICE_SERVER_VERSION >= 0x000c02
+CharDriverState *qemu_chr_open_spice_port(QemuOpts *opts);
+void qemu_spice_register_ports(void);
+#endif
#else /* CONFIG_SPICE */
#include "monitor/monitor.h"
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 7c304e92de..e99adab492 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -28,6 +28,7 @@
#include <fcntl.h>
#include <time.h>
#include <limits.h>
+#include <grp.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
@@ -584,7 +585,6 @@ extern int personality(int);
extern int flock(int, int);
extern int setfsuid(int);
extern int setfsgid(int);
-extern int setgroups(int, gid_t *);
/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
#ifdef TARGET_ARM
diff --git a/net/hub.c b/net/hub.c
index 5adfce444b..a24c9d17f7 100644
--- a/net/hub.c
+++ b/net/hub.c
@@ -256,7 +256,7 @@ void net_hub_info(Monitor *mon)
/**
* Get the hub id that a client is connected to
*
- * @id Pointer for hub id output, may be NULL
+ * @id: Pointer for hub id output, may be NULL
*/
int net_hub_id_for_client(NetClientState *nc, int *id)
{
diff --git a/qemu-char.c b/qemu-char.c
index e39e6f168c..6113d0ab60 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2761,6 +2761,9 @@ static const struct {
#endif
#ifdef CONFIG_SPICE
{ .name = "spicevmc", .open = qemu_chr_open_spice },
+#if SPICE_SERVER_VERSION >= 0x000c02
+ { .name = "spiceport", .open = qemu_chr_open_spice_port },
+#endif
#endif
};
diff --git a/qemu-options.hx b/qemu-options.hx
index 231cc4f55f..9df0cde64c 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1749,6 +1749,7 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
#endif
#if defined(CONFIG_SPICE)
"-chardev spicevmc,id=id,name=name[,debug=debug]\n"
+ "-chardev spiceport,id=id,name=name[,debug=debug]\n"
#endif
, QEMU_ARCH_ALL
)
@@ -1776,6 +1777,7 @@ Backend is one of:
@option{tty},
@option{parport},
@option{spicevmc}.
+@option{spiceport}.
The specific backend will determine the applicable options.
All devices must have an id, which can be any string up to 127 characters long.
@@ -1961,6 +1963,17 @@ required.
Connect to a spice virtual machine channel, such as vdiport.
+@item -chardev spiceport ,id=@var{id} ,debug=@var{debug}, name=@var{name}
+
+@option{spiceport} is only available when spice support is built in.
+
+@option{debug} debug level for spicevmc
+
+@option{name} name of spice port to connect to
+
+Connect to a spice port, allowing a Spice client to handle the traffic
+identified by a name (preferably a fqdn).
+
@end table
ETEXI
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index 4b03143f68..a4d7de8c4f 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -4,6 +4,7 @@
#include "char/char.h"
#include <spice.h>
#include <spice-experimental.h>
+#include <spice/protocol.h>
#include "qemu/osdep.h"
@@ -15,8 +16,6 @@
} \
} while (0)
-#define VMC_MAX_HOST_WRITE 2048
-
typedef struct SpiceCharDriver {
CharDriverState* chr;
SpiceCharDeviceInstance sin;
@@ -26,8 +25,12 @@ typedef struct SpiceCharDriver {
uint8_t *datapos;
ssize_t bufsize, datalen;
uint32_t debug;
+ QLIST_ENTRY(SpiceCharDriver) next;
} SpiceCharDriver;
+static QLIST_HEAD(, SpiceCharDriver) spice_chars =
+ QLIST_HEAD_INITIALIZER(spice_chars);
+
static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
{
SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
@@ -36,8 +39,8 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
uint8_t* p = (uint8_t*)buf;
while (len > 0) {
- last_out = MIN(len, VMC_MAX_HOST_WRITE);
- if (qemu_chr_be_can_write(scd->chr) < last_out) {
+ last_out = MIN(len, qemu_chr_be_can_write(scd->chr));
+ if (last_out <= 0) {
break;
}
qemu_chr_be_write(scd->chr, p, last_out);
@@ -70,6 +73,27 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
return bytes;
}
+#if SPICE_SERVER_VERSION >= 0x000c02
+static void vmc_event(SpiceCharDeviceInstance *sin, uint8_t event)
+{
+ SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
+ int chr_event;
+
+ switch (event) {
+ case SPICE_PORT_EVENT_BREAK:
+ chr_event = CHR_EVENT_BREAK;
+ break;
+ default:
+ dprintf(scd, 2, "%s: unknown %d\n", __func__, event);
+ return;
+ }
+
+ dprintf(scd, 2, "%s: %d\n", __func__, event);
+ trace_spice_vmc_event(chr_event);
+ qemu_chr_be_event(scd->chr, chr_event);
+}
+#endif
+
static void vmc_state(SpiceCharDeviceInstance *sin, int connected)
{
SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
@@ -106,6 +130,9 @@ static SpiceCharDeviceInterface vmc_interface = {
.state = vmc_state,
.write = vmc_write,
.read = vmc_read,
+#if SPICE_SERVER_VERSION >= 0x000c02
+ .event = vmc_event,
+#endif
};
@@ -157,6 +184,7 @@ static void spice_chr_close(struct CharDriverState *chr)
printf("%s\n", __func__);
vmc_unregister_interface(s);
+ QLIST_REMOVE(s, next);
g_free(s);
}
@@ -189,13 +217,34 @@ static void print_allowed_subtypes(void)
fprintf(stderr, "\n");
}
-CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
+static CharDriverState *chr_open(QemuOpts *opts, const char *subtype)
{
CharDriverState *chr;
SpiceCharDriver *s;
- const char* name = qemu_opt_get(opts, "name");
uint32_t debug = qemu_opt_get_number(opts, "debug", 0);
- const char** psubtype = spice_server_char_device_recognized_subtypes();
+
+ chr = g_malloc0(sizeof(CharDriverState));
+ s = g_malloc0(sizeof(SpiceCharDriver));
+ s->chr = chr;
+ s->debug = debug;
+ s->active = false;
+ s->sin.subtype = subtype;
+ chr->opaque = s;
+ chr->chr_write = spice_chr_write;
+ chr->chr_close = spice_chr_close;
+ chr->chr_guest_open = spice_chr_guest_open;
+ chr->chr_guest_close = spice_chr_guest_close;
+
+ QLIST_INSERT_HEAD(&spice_chars, s, next);
+
+ return chr;
+}
+
+CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
+{
+ CharDriverState *chr;
+ const char *name = qemu_opt_get(opts, "name");
+ const char **psubtype = spice_server_char_device_recognized_subtypes();
const char *subtype = NULL;
if (name == NULL) {
@@ -215,17 +264,7 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
return NULL;
}
- chr = g_malloc0(sizeof(CharDriverState));
- s = g_malloc0(sizeof(SpiceCharDriver));
- s->chr = chr;
- s->debug = debug;
- s->active = false;
- s->sin.subtype = subtype;
- chr->opaque = s;
- chr->chr_write = spice_chr_write;
- chr->chr_close = spice_chr_close;
- chr->chr_guest_open = spice_chr_guest_open;
- chr->chr_guest_close = spice_chr_guest_close;
+ chr = chr_open(opts, subtype);
#if SPICE_SERVER_VERSION < 0x000901
/* See comment in vmc_state() */
@@ -236,3 +275,35 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
return chr;
}
+
+#if SPICE_SERVER_VERSION >= 0x000c02
+CharDriverState *qemu_chr_open_spice_port(QemuOpts *opts)
+{
+ CharDriverState *chr;
+ SpiceCharDriver *s;
+ const char *name = qemu_opt_get(opts, "name");
+
+ if (name == NULL) {
+ fprintf(stderr, "spice-qemu-char: missing name parameter\n");
+ return NULL;
+ }
+
+ chr = chr_open(opts, "port");
+ s = chr->opaque;
+ s->sin.portname = name;
+
+ return chr;
+}
+
+void qemu_spice_register_ports(void)
+{
+ SpiceCharDriver *s;
+
+ QLIST_FOREACH(s, &spice_chars, next) {
+ if (s->sin.portname == NULL) {
+ continue;
+ }
+ vmc_register_interface(s);
+ }
+}
+#endif
diff --git a/trace-events b/trace-events
index 6cb450a993..bb7621eeb6 100644
--- a/trace-events
+++ b/trace-events
@@ -535,6 +535,7 @@ spice_vmc_write(ssize_t out, int len) "spice wrottn %zd of requested %d"
spice_vmc_read(int bytes, int len) "spice read %d of requested %d"
spice_vmc_register_interface(void *scd) "spice vmc registered interface %p"
spice_vmc_unregister_interface(void *scd) "spice vmc unregistered interface %p"
+spice_vmc_event(int event) "spice vmc event %d"
# hw/lm32_pic.c
lm32_pic_raise_irq(void) "Raise CPU interrupt"
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 5fe3e0e4cf..3e44779107 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -714,6 +714,10 @@ void qemu_spice_init(void)
g_free(x509_key_file);
g_free(x509_cert_file);
g_free(x509_cacert_file);
+
+#if SPICE_SERVER_VERSION >= 0x000c02
+ qemu_spice_register_ports();
+#endif
}
int qemu_spice_add_interface(SpiceBaseInstance *sin)
@@ -732,6 +736,8 @@ int qemu_spice_add_interface(SpiceBaseInstance *sin)
*/
spice_server = spice_server_new();
spice_server_init(spice_server, &core_interface);
+ qemu_add_vm_change_state_handler(vm_change_state_handler,
+ &spice_server);
}
return spice_server_add_interface(spice_server, sin);
diff --git a/user-exec.c b/user-exec.c
index 63fb05384f..c71acbc503 100644
--- a/user-exec.c
+++ b/user-exec.c
@@ -436,7 +436,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
unsigned long pc;
int is_write;
-#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
+#if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
pc = uc->uc_mcontext.gregs[R15];
#else
pc = uc->uc_mcontext.arm_pc;
diff --git a/xen-all.c b/xen-all.c
index b659321184..50edaecbf1 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -292,7 +292,8 @@ static int xen_add_to_physmap(XenIOState *state,
return -1;
go_physmap:
- DPRINTF("mapping vram to %llx - %llx\n", start_addr, start_addr + size);
+ DPRINTF("mapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx"\n",
+ start_addr, start_addr + size);
pfn = phys_offset >> TARGET_PAGE_BITS;
start_gpfn = start_addr >> TARGET_PAGE_BITS;
@@ -365,8 +366,8 @@ static int xen_remove_from_physmap(XenIOState *state,
phys_offset = physmap->phys_offset;
size = physmap->size;
- DPRINTF("unmapping vram to %llx - %llx, from %llx\n",
- phys_offset, phys_offset + size, start_addr);
+ DPRINTF("unmapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx", from ",
+ "%"HWADDR_PRIx"\n", phys_offset, phys_offset + size, start_addr);
size >>= TARGET_PAGE_BITS;
start_addr >>= TARGET_PAGE_BITS;
@@ -682,11 +683,45 @@ static void do_outp(pio_addr_t addr,
}
}
-static void cpu_ioreq_pio(ioreq_t *req)
+/*
+ * Helper functions which read/write an object from/to physical guest
+ * memory, as part of the implementation of an ioreq.
+ *
+ * Equivalent to
+ * cpu_physical_memory_rw(addr + (req->df ? -1 : +1) * req->size * i,
+ * val, req->size, 0/1)
+ * except without the integer overflow problems.
+ */
+static void rw_phys_req_item(hwaddr addr,
+ ioreq_t *req, uint32_t i, void *val, int rw)
+{
+ /* Do everything unsigned so overflow just results in a truncated result
+ * and accesses to undesired parts of guest memory, which is up
+ * to the guest */
+ hwaddr offset = (hwaddr)req->size * i;
+ if (req->df) {
+ addr -= offset;
+ } else {
+ addr += offset;
+ }
+ cpu_physical_memory_rw(addr, val, req->size, rw);
+}
+
+static inline void read_phys_req_item(hwaddr addr,
+ ioreq_t *req, uint32_t i, void *val)
+{
+ rw_phys_req_item(addr, req, i, val, 0);
+}
+static inline void write_phys_req_item(hwaddr addr,
+ ioreq_t *req, uint32_t i, void *val)
{
- int i, sign;
+ rw_phys_req_item(addr, req, i, val, 1);
+}
- sign = req->df ? -1 : 1;
+
+static void cpu_ioreq_pio(ioreq_t *req)
+{
+ uint32_t i;
if (req->dir == IOREQ_READ) {
if (!req->data_is_ptr) {
@@ -696,9 +731,7 @@ static void cpu_ioreq_pio(ioreq_t *req)
for (i = 0; i < req->count; i++) {
tmp = do_inp(req->addr, req->size);
- cpu_physical_memory_write(
- req->data + (sign * i * (int64_t)req->size),
- (uint8_t *) &tmp, req->size);
+ write_phys_req_item(req->data, req, i, &tmp);
}
}
} else if (req->dir == IOREQ_WRITE) {
@@ -708,9 +741,7 @@ static void cpu_ioreq_pio(ioreq_t *req)
for (i = 0; i < req->count; i++) {
uint32_t tmp = 0;
- cpu_physical_memory_read(
- req->data + (sign * i * (int64_t)req->size),
- (uint8_t*) &tmp, req->size);
+ read_phys_req_item(req->data, req, i, &tmp);
do_outp(req->addr, req->size, tmp);
}
}
@@ -719,22 +750,16 @@ static void cpu_ioreq_pio(ioreq_t *req)
static void cpu_ioreq_move(ioreq_t *req)
{
- int i, sign;
-
- sign = req->df ? -1 : 1;
+ uint32_t i;
if (!req->data_is_ptr) {
if (req->dir == IOREQ_READ) {
for (i = 0; i < req->count; i++) {
- cpu_physical_memory_read(
- req->addr + (sign * i * (int64_t)req->size),
- (uint8_t *) &req->data, req->size);
+ read_phys_req_item(req->addr, req, i, &req->data);
}
} else if (req->dir == IOREQ_WRITE) {
for (i = 0; i < req->count; i++) {
- cpu_physical_memory_write(
- req->addr + (sign * i * (int64_t)req->size),
- (uint8_t *) &req->data, req->size);
+ write_phys_req_item(req->addr, req, i, &req->data);
}
}
} else {
@@ -742,21 +767,13 @@ static void cpu_ioreq_move(ioreq_t *req)
if (req->dir == IOREQ_READ) {
for (i = 0; i < req->count; i++) {
- cpu_physical_memory_read(
- req->addr + (sign * i * (int64_t)req->size),
- (uint8_t*) &tmp, req->size);
- cpu_physical_memory_write(
- req->data + (sign * i * (int64_t)req->size),
- (uint8_t*) &tmp, req->size);
+ read_phys_req_item(req->addr, req, i, &tmp);
+ write_phys_req_item(req->data, req, i, &tmp);
}
} else if (req->dir == IOREQ_WRITE) {
for (i = 0; i < req->count; i++) {
- cpu_physical_memory_read(
- req->data + (sign * i * (int64_t)req->size),
- (uint8_t*) &tmp, req->size);
- cpu_physical_memory_write(
- req->addr + (sign * i * (int64_t)req->size),
- (uint8_t*) &tmp, req->size);
+ read_phys_req_item(req->data, req, i, &tmp);
+ write_phys_req_item(req->addr, req, i, &tmp);
}
}
}