aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS9
-rw-r--r--hw/9pfs/9p-synth.c52
-rw-r--r--hw/9pfs/9p-synth.h13
-rw-r--r--hw/9pfs/9p.c25
-rw-r--r--hw/9pfs/9p.h10
-rw-r--r--hw/9pfs/trace-events1
-rw-r--r--hw/9pfs/virtio-9p-device.c8
-rw-r--r--hw/9pfs/xen-9p-backend.c3
-rw-r--r--hw/arm/musicpal.c3
-rw-r--r--hw/arm/spitz.c3
-rw-r--r--hw/arm/z2.c3
-rw-r--r--hw/audio/marvell_88w8618.c1
-rw-r--r--hw/audio/sb16.c79
-rw-r--r--hw/audio/wm8750.c6
-rw-r--r--hw/display/virtio-gpu-pci.c8
-rw-r--r--hw/display/virtio-gpu.c5
-rw-r--r--hw/ipmi/ipmi_bmc_extern.c5
-rw-r--r--hw/ipmi/ipmi_bmc_sim.c58
-rw-r--r--hw/ipmi/isa_ipmi_bt.c12
-rw-r--r--include/hw/audio/wm8750.h30
-rw-r--r--include/hw/i2c/i2c.h9
-rw-r--r--tests/libqos/virtio.c25
-rw-r--r--tests/libqos/virtio.h3
-rw-r--r--tests/virtio-9p-test.c294
-rw-r--r--tests/virtio-blk-test.c24
-rw-r--r--tests/virtio-net-test.c6
-rw-r--r--tests/virtio-scsi-test.c3
-rw-r--r--ui/sdl.c9
-rw-r--r--ui/vnc-auth-sasl.c2
-rw-r--r--ui/vnc.c195
-rw-r--r--ui/vnc.h9
31 files changed, 613 insertions, 300 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index d352d16fac..bbc3a617c2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -941,6 +941,15 @@ F: tests/ahci-test.c
F: tests/libqos/ahci*
T: git git://github.com/jnsnow/qemu.git ide
+IPMI
+M: Corey Minyard <minyard@acm.org>
+S: Maintained
+F: include/hw/ipmi/*
+F: hw/ipmi/*
+F: hw/smbios/smbios_type_38.c
+F: tests/ipmi*
+T: git git://github.com/cminyard/qemu.git master-ipmi-rebase
+
Floppy
M: John Snow <jsnow@redhat.com>
L: qemu-block@nongnu.org
diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c
index 8f255e91c0..18082dffe8 100644
--- a/hw/9pfs/9p-synth.c
+++ b/hw/9pfs/9p-synth.c
@@ -19,6 +19,7 @@
#include "qemu/rcu.h"
#include "qemu/rcu_queue.h"
#include "qemu/cutils.h"
+#include "sysemu/qtest.h"
/* Root node for synth file system */
static V9fsSynthNode synth_root = {
@@ -514,6 +515,26 @@ static int synth_unlinkat(FsContext *ctx, V9fsPath *dir,
return -1;
}
+static ssize_t v9fs_synth_qtest_write(void *buf, int len, off_t offset,
+ void *arg)
+{
+ return 1;
+}
+
+static ssize_t v9fs_synth_qtest_flush_write(void *buf, int len, off_t offset,
+ void *arg)
+{
+ bool should_block = !!*(uint8_t *)buf;
+
+ if (should_block) {
+ /* This will cause the server to call us again until we're cancelled */
+ errno = EINTR;
+ return -1;
+ }
+
+ return 1;
+}
+
static int synth_init(FsContext *ctx, Error **errp)
{
QLIST_INIT(&synth_root.child);
@@ -527,6 +548,37 @@ static int synth_init(FsContext *ctx, Error **errp)
/* Mark the subsystem is ready for use */
synth_fs = 1;
+
+ if (qtest_enabled()) {
+ V9fsSynthNode *node = NULL;
+ int i, ret;
+
+ /* Directory hierarchy for WALK test */
+ for (i = 0; i < P9_MAXWELEM; i++) {
+ char *name = g_strdup_printf(QTEST_V9FS_SYNTH_WALK_FILE, i);
+
+ ret = qemu_v9fs_synth_mkdir(node, 0700, name, &node);
+ assert(!ret);
+ g_free(name);
+ }
+
+ /* File for LOPEN test */
+ ret = qemu_v9fs_synth_add_file(NULL, 0, QTEST_V9FS_SYNTH_LOPEN_FILE,
+ NULL, NULL, ctx);
+ assert(!ret);
+
+ /* File for WRITE test */
+ ret = qemu_v9fs_synth_add_file(NULL, 0, QTEST_V9FS_SYNTH_WRITE_FILE,
+ NULL, v9fs_synth_qtest_write, ctx);
+ assert(!ret);
+
+ /* File for FLUSH test */
+ ret = qemu_v9fs_synth_add_file(NULL, 0, QTEST_V9FS_SYNTH_FLUSH_FILE,
+ NULL, v9fs_synth_qtest_flush_write,
+ ctx);
+ assert(!ret);
+ }
+
return 0;
}
diff --git a/hw/9pfs/9p-synth.h b/hw/9pfs/9p-synth.h
index 49c2fc7b27..af7a993a1e 100644
--- a/hw/9pfs/9p-synth.h
+++ b/hw/9pfs/9p-synth.h
@@ -49,4 +49,17 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode,
const char *name, v9fs_synth_read read,
v9fs_synth_write write, void *arg);
+/* qtest stuff */
+
+#define QTEST_V9FS_SYNTH_WALK_FILE "WALK%d"
+#define QTEST_V9FS_SYNTH_LOPEN_FILE "LOPEN"
+#define QTEST_V9FS_SYNTH_WRITE_FILE "WRITE"
+
+/* Any write to the "FLUSH" file is handled one byte at a time by the
+ * backend. If the byte is zero, the backend returns success (ie, 1),
+ * otherwise it forces the server to try again forever. Thus allowing
+ * the client to cancel the request.
+ */
+#define QTEST_V9FS_SYNTH_FLUSH_FILE "FLUSH"
+
#endif
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 909a611394..85a1ed8171 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -24,6 +24,7 @@
#include "coth.h"
#include "trace.h"
#include "migration/blocker.h"
+#include "sysemu/qtest.h"
int open_fd_hw;
int total_open_fd;
@@ -630,6 +631,24 @@ static void coroutine_fn pdu_complete(V9fsPDU *pdu, ssize_t len)
V9fsState *s = pdu->s;
int ret;
+ /*
+ * The 9p spec requires that successfully cancelled pdus receive no reply.
+ * Sending a reply would confuse clients because they would
+ * assume that any EINTR is the actual result of the operation,
+ * rather than a consequence of the cancellation. However, if
+ * the operation completed (succesfully or with an error other
+ * than caused be cancellation), we do send out that reply, both
+ * for efficiency and to avoid confusing the rest of the state machine
+ * that assumes passing a non-error here will mean a successful
+ * transmission of the reply.
+ */
+ bool discard = pdu->cancelled && len == -EINTR;
+ if (discard) {
+ trace_v9fs_rcancel(pdu->tag, pdu->id);
+ pdu->size = 0;
+ goto out_notify;
+ }
+
if (len < 0) {
int err = -len;
len = 7;
@@ -3485,7 +3504,8 @@ void pdu_submit(V9fsPDU *pdu, P9MsgHeader *hdr)
}
/* Returns 0 on success, 1 on failure. */
-int v9fs_device_realize_common(V9fsState *s, Error **errp)
+int v9fs_device_realize_common(V9fsState *s, const V9fsTransport *t,
+ Error **errp)
{
int i, len;
struct stat stat;
@@ -3493,6 +3513,9 @@ int v9fs_device_realize_common(V9fsState *s, Error **errp)
V9fsPath path;
int rc = 1;
+ assert(!s->transport);
+ s->transport = t;
+
/* initialize pdu allocator */
QLIST_INIT(&s->free_list);
QLIST_INIT(&s->active_list);
diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
index ffe658ab89..5ced427d86 100644
--- a/hw/9pfs/9p.h
+++ b/hw/9pfs/9p.h
@@ -346,7 +346,8 @@ void v9fs_path_sprintf(V9fsPath *path, const char *fmt, ...);
void v9fs_path_copy(V9fsPath *lhs, V9fsPath *rhs);
int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath,
const char *name, V9fsPath *path);
-int v9fs_device_realize_common(V9fsState *s, Error **errp);
+int v9fs_device_realize_common(V9fsState *s, const V9fsTransport *t,
+ Error **errp);
void v9fs_device_unrealize_common(V9fsState *s, Error **errp);
V9fsPDU *pdu_alloc(V9fsState *s);
@@ -366,11 +367,4 @@ struct V9fsTransport {
void (*push_and_notify)(V9fsPDU *pdu);
};
-static inline int v9fs_register_transport(V9fsState *s, const V9fsTransport *t)
-{
- assert(!s->transport);
- s->transport = t;
- return 0;
-}
-
#endif
diff --git a/hw/9pfs/trace-events b/hw/9pfs/trace-events
index 08a4abf22e..1aee350c42 100644
--- a/hw/9pfs/trace-events
+++ b/hw/9pfs/trace-events
@@ -1,6 +1,7 @@
# See docs/devel/tracing.txt for syntax documentation.
# hw/9pfs/virtio-9p.c
+v9fs_rcancel(uint16_t tag, uint8_t id) "tag %d id %d"
v9fs_rerror(uint16_t tag, uint8_t id, int err) "tag %d id %d err %d"
v9fs_version(uint16_t tag, uint8_t id, int32_t msize, char* version) "tag %d id %d msize %d version %s"
v9fs_version_return(uint16_t tag, uint8_t id, int32_t msize, char* version) "tag %d id %d msize %d version %s"
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 43f4e53f33..775e8ff766 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -198,17 +198,13 @@ static void virtio_9p_device_realize(DeviceState *dev, Error **errp)
V9fsVirtioState *v = VIRTIO_9P(dev);
V9fsState *s = &v->state;
- if (v9fs_device_realize_common(s, errp)) {
- goto out;
+ if (v9fs_device_realize_common(s, &virtio_9p_transport, errp)) {
+ return;
}
v->config_size = sizeof(struct virtio_9p_config) + strlen(s->fsconf.tag);
virtio_init(vdev, "virtio-9p", VIRTIO_ID_9P, v->config_size);
v->vq = virtio_add_queue(vdev, MAX_REQ, handle_9p_output);
- v9fs_register_transport(s, &virtio_9p_transport);
-
-out:
- return;
}
static void virtio_9p_device_unrealize(DeviceState *dev, Error **errp)
diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c
index df2a4100bf..14f0d6a50e 100644
--- a/hw/9pfs/xen-9p-backend.c
+++ b/hw/9pfs/xen-9p-backend.c
@@ -446,7 +446,6 @@ static int xen_9pfs_connect(struct XenDevice *xendev)
xen_9pdev->id = s->fsconf.fsdev_id =
g_strdup_printf("xen9p%d", xendev->dev);
xen_9pdev->tag = s->fsconf.tag = xenstore_read_fe_str(xendev, "tag");
- v9fs_register_transport(s, &xen_9p_transport);
fsdev = qemu_opts_create(qemu_find_opts("fsdev"),
s->fsconf.tag,
1, NULL);
@@ -455,7 +454,7 @@ static int xen_9pfs_connect(struct XenDevice *xendev)
qemu_opt_set(fsdev, "security_model", xen_9pdev->security_model, NULL);
qemu_opts_set_id(fsdev, s->fsconf.fsdev_id);
qemu_fsdev_add(fsdev);
- v9fs_device_realize_common(s, NULL);
+ v9fs_device_realize_common(s, &xen_9p_transport, NULL);
return 0;
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index b648770882..4172caf5db 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -25,6 +25,7 @@
#include "hw/block/flash.h"
#include "ui/console.h"
#include "hw/i2c/i2c.h"
+#include "hw/audio/wm8750.h"
#include "sysemu/block-backend.h"
#include "exec/address-spaces.h"
#include "ui/pixel_ops.h"
@@ -1691,7 +1692,7 @@ static void musicpal_init(MachineState *machine)
qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 15));
}
- wm8750_dev = i2c_create_slave(i2c, "wm8750", MP_WM_ADDR);
+ wm8750_dev = i2c_create_slave(i2c, TYPE_WM8750, MP_WM_ADDR);
dev = qdev_create(NULL, "mv88w8618_audio");
s = SYS_BUS_DEVICE(dev);
qdev_prop_set_ptr(dev, "wm8750", wm8750_dev);
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index ac1e15cbbc..e419e3c00e 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -24,6 +24,7 @@
#include "hw/devices.h"
#include "hw/arm/sharpsl.h"
#include "ui/console.h"
+#include "hw/audio/wm8750.h"
#include "audio/audio.h"
#include "hw/boards.h"
#include "sysemu/block-backend.h"
@@ -745,7 +746,7 @@ static void spitz_i2c_setup(PXA2xxState *cpu)
DeviceState *wm;
/* Attach a WM8750 to the bus */
- wm = i2c_create_slave(bus, "wm8750", 0);
+ wm = i2c_create_slave(bus, TYPE_WM8750, 0);
spitz_wm8750_addr(wm, 0, 0);
qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_WM,
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
index 60561c7b7c..300e933c82 100644
--- a/hw/arm/z2.c
+++ b/hw/arm/z2.c
@@ -23,6 +23,7 @@
#include "hw/block/flash.h"
#include "sysemu/block-backend.h"
#include "ui/console.h"
+#include "hw/audio/wm8750.h"
#include "audio/audio.h"
#include "exec/address-spaces.h"
#include "sysemu/qtest.h"
@@ -346,7 +347,7 @@ static void z2_init(MachineState *machine)
z2_lcd = ssi_create_slave(mpu->ssp[1], "zipit-lcd");
bus = pxa2xx_i2c_bus(mpu->i2c[0]);
i2c_create_slave(bus, TYPE_AER915, 0x55);
- wm = i2c_create_slave(bus, "wm8750", 0x1b);
+ wm = i2c_create_slave(bus, TYPE_WM8750, 0x1b);
mpu->i2s->opaque = wm;
mpu->i2s->codec_out = wm8750_dac_dat;
mpu->i2s->codec_in = wm8750_adc_dat;
diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c
index 4f65f8c199..e546892d3c 100644
--- a/hw/audio/marvell_88w8618.c
+++ b/hw/audio/marvell_88w8618.c
@@ -13,6 +13,7 @@
#include "hw/sysbus.h"
#include "hw/hw.h"
#include "hw/i2c/i2c.h"
+#include "hw/audio/wm8750.h"
#include "audio/audio.h"
#define MP_AUDIO_SIZE 0x00001000
diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c
index 6ab2f6f89a..31de264ab7 100644
--- a/hw/audio/sb16.c
+++ b/hw/audio/sb16.c
@@ -29,6 +29,8 @@
#include "hw/qdev.h"
#include "qemu/timer.h"
#include "qemu/host-utils.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
#define dolog(...) AUD_log ("sb16", __VA_ARGS__)
@@ -123,7 +125,7 @@ static int magic_of_irq (int irq)
case 10:
return 8;
default:
- dolog ("bad irq %d\n", irq);
+ qemu_log_mask(LOG_GUEST_ERROR, "bad irq %d\n", irq);
return 2;
}
}
@@ -140,7 +142,7 @@ static int irq_of_magic (int magic)
case 8:
return 10;
default:
- dolog ("bad irq magic %d\n", magic);
+ qemu_log_mask(LOG_GUEST_ERROR, "bad irq magic %d\n", magic);
return -1;
}
}
@@ -258,8 +260,8 @@ static void dma_cmd8 (SB16State *s, int mask, int dma_len)
s->align = (1 << s->fmt_stereo) - 1;
if (s->block_size & s->align) {
- dolog ("warning: misaligned block size %d, alignment %d\n",
- s->block_size, s->align + 1);
+ qemu_log_mask(LOG_GUEST_ERROR, "warning: misaligned block size %d,"
+ " alignment %d\n", s->block_size, s->align + 1);
}
ldebug ("freq %d, stereo %d, sign %d, bits %d, "
@@ -338,8 +340,8 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
s->highspeed = 0;
s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
if (s->block_size & s->align) {
- dolog ("warning: misaligned block size %d, alignment %d\n",
- s->block_size, s->align + 1);
+ qemu_log_mask(LOG_GUEST_ERROR, "warning: misaligned block size %d,"
+ " alignment %d\n", s->block_size, s->align + 1);
}
if (s->freq) {
@@ -391,7 +393,8 @@ static void command (SB16State *s, uint8_t cmd)
if (cmd > 0xaf && cmd < 0xd0) {
if (cmd & 8) {
- dolog ("ADC not yet supported (command %#x)\n", cmd);
+ qemu_log_mask(LOG_UNIMP, "ADC not yet supported (command %#x)\n",
+ cmd);
}
switch (cmd >> 4) {
@@ -399,7 +402,7 @@ static void command (SB16State *s, uint8_t cmd)
case 12:
break;
default:
- dolog ("%#x wrong bits\n", cmd);
+ qemu_log_mask(LOG_GUEST_ERROR, "%#x wrong bits\n", cmd);
}
s->needed_bytes = 3;
}
@@ -453,7 +456,7 @@ static void command (SB16State *s, uint8_t cmd)
goto warn;
case 0x35:
- dolog ("0x35 - MIDI command not implemented\n");
+ qemu_log_mask(LOG_UNIMP, "0x35 - MIDI command not implemented\n");
break;
case 0x40:
@@ -487,34 +490,38 @@ static void command (SB16State *s, uint8_t cmd)
case 0x74:
s->needed_bytes = 2; /* DMA DAC, 4-bit ADPCM */
- dolog ("0x75 - DMA DAC, 4-bit ADPCM not implemented\n");
+ qemu_log_mask(LOG_UNIMP, "0x75 - DMA DAC, 4-bit ADPCM not"
+ " implemented\n");
break;
case 0x75: /* DMA DAC, 4-bit ADPCM Reference */
s->needed_bytes = 2;
- dolog ("0x74 - DMA DAC, 4-bit ADPCM Reference not implemented\n");
+ qemu_log_mask(LOG_UNIMP, "0x74 - DMA DAC, 4-bit ADPCM Reference not"
+ " implemented\n");
break;
case 0x76: /* DMA DAC, 2.6-bit ADPCM */
s->needed_bytes = 2;
- dolog ("0x74 - DMA DAC, 2.6-bit ADPCM not implemented\n");
+ qemu_log_mask(LOG_UNIMP, "0x74 - DMA DAC, 2.6-bit ADPCM not"
+ " implemented\n");
break;
case 0x77: /* DMA DAC, 2.6-bit ADPCM Reference */
s->needed_bytes = 2;
- dolog ("0x74 - DMA DAC, 2.6-bit ADPCM Reference not implemented\n");
+ qemu_log_mask(LOG_UNIMP, "0x74 - DMA DAC, 2.6-bit ADPCM Reference"
+ " not implemented\n");
break;
case 0x7d:
- dolog ("0x7d - Autio-Initialize DMA DAC, 4-bit ADPCM Reference\n");
- dolog ("not implemented\n");
+ qemu_log_mask(LOG_UNIMP, "0x7d - Autio-Initialize DMA DAC, 4-bit"
+ " ADPCM Reference\n");
+ qemu_log_mask(LOG_UNIMP, "not implemented\n");
break;
case 0x7f:
- dolog (
- "0x7d - Autio-Initialize DMA DAC, 2.6-bit ADPCM Reference\n"
- );
- dolog ("not implemented\n");
+ qemu_log_mask(LOG_UNIMP, "0x7d - Autio-Initialize DMA DAC, 2.6-bit"
+ " ADPCM Reference\n");
+ qemu_log_mask(LOG_UNIMP, "not implemented\n");
break;
case 0x80:
@@ -586,7 +593,7 @@ static void command (SB16State *s, uint8_t cmd)
break;
case 0xe7:
- dolog ("Attempt to probe for ESS (0xe7)?\n");
+ qemu_log_mask(LOG_UNIMP, "Attempt to probe for ESS (0xe7)?\n");
break;
case 0xe8: /* read test reg */
@@ -613,7 +620,7 @@ static void command (SB16State *s, uint8_t cmd)
goto warn;
default:
- dolog ("Unrecognized command %#x\n", cmd);
+ qemu_log_mask(LOG_UNIMP, "Unrecognized command %#x\n", cmd);
break;
}
}
@@ -632,8 +639,8 @@ static void command (SB16State *s, uint8_t cmd)
return;
warn:
- dolog ("warning: command %#x,%d is not truly understood yet\n",
- cmd, s->needed_bytes);
+ qemu_log_mask(LOG_UNIMP, "warning: command %#x,%d is not truly understood"
+ " yet\n", cmd, s->needed_bytes);
goto exit;
}
@@ -735,9 +742,8 @@ static void complete (SB16State *s)
break;
case 0x42: /* FT2 sets output freq with this, go figure */
-#if 0
- dolog ("cmd 0x42 might not do what it think it should\n");
-#endif
+ qemu_log_mask(LOG_UNIMP, "cmd 0x42 might not do what it think it"
+ " should\n");
case 0x41:
s->freq = dsp_get_hilo (s);
ldebug ("set freq %d\n", s->freq);
@@ -820,7 +826,8 @@ static void complete (SB16State *s)
break;
default:
- dolog ("complete: unrecognized command %#x\n", s->cmd);
+ qemu_log_mask(LOG_UNIMP, "complete: unrecognized command %#x\n",
+ s->cmd);
return;
}
}
@@ -1095,10 +1102,9 @@ static void mixer_write_datab(void *opaque, uint32_t nport, uint32_t val)
dma = ctz32 (val & 0xf);
hdma = ctz32 (val & 0xf0);
if (dma != s->dma || hdma != s->hdma) {
- dolog (
- "attempt to change DMA "
- "8bit %d(%d), 16bit %d(%d) (val=%#x)\n",
- dma, s->dma, hdma, s->hdma, val);
+ qemu_log_mask(LOG_GUEST_ERROR, "attempt to change DMA 8bit"
+ " %d(%d), 16bit %d(%d) (val=%#x)\n", dma, s->dma,
+ hdma, s->hdma, val);
}
#if 0
s->dma = dma;
@@ -1108,8 +1114,8 @@ static void mixer_write_datab(void *opaque, uint32_t nport, uint32_t val)
break;
case 0x82:
- dolog ("attempt to write into IRQ status register (val=%#x)\n",
- val);
+ qemu_log_mask(LOG_GUEST_ERROR, "attempt to write into IRQ status"
+ " register (val=%#x)\n", val);
return;
default:
@@ -1181,8 +1187,9 @@ static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
int till, copy, written, free;
if (s->block_size <= 0) {
- dolog ("invalid block size=%d nchan=%d dma_pos=%d dma_len=%d\n",
- s->block_size, nchan, dma_pos, dma_len);
+ qemu_log_mask(LOG_GUEST_ERROR, "invalid block size=%d nchan=%d"
+ " dma_pos=%d dma_len=%d\n", s->block_size, nchan,
+ dma_pos, dma_len);
return dma_pos;
}
@@ -1376,7 +1383,7 @@ static void sb16_realizefn (DeviceState *dev, Error **errp)
reset_mixer (s);
s->aux_ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, aux_timer, s);
if (!s->aux_ts) {
- dolog ("warning: Could not create auxiliary timer\n");
+ error_setg(errp, "warning: Could not create auxiliary timer");
}
isa_register_portio_list(isadev, &s->portio_list, s->port,
diff --git a/hw/audio/wm8750.c b/hw/audio/wm8750.c
index 6d8b728923..416a78e869 100644
--- a/hw/audio/wm8750.c
+++ b/hw/audio/wm8750.c
@@ -8,8 +8,8 @@
*/
#include "qemu/osdep.h"
-#include "hw/hw.h"
#include "hw/i2c/i2c.h"
+#include "hw/audio/wm8750.h"
#include "audio/audio.h"
#define IN_PORT_N 3
@@ -24,7 +24,6 @@ typedef struct {
int dac_hz;
} WMRate;
-#define TYPE_WM8750 "wm8750"
#define WM8750(obj) OBJECT_CHECK(WM8750State, (obj), TYPE_WM8750)
typedef struct WM8750State {
@@ -639,8 +638,7 @@ static void wm8750_fini(I2CSlave *i2c)
}
#endif
-void wm8750_data_req_set(DeviceState *dev,
- void (*data_req)(void *, int, int), void *opaque)
+void wm8750_data_req_set(DeviceState *dev, data_req_cb *data_req, void *opaque)
{
WM8750State *s = WM8750(dev);
diff --git a/hw/display/virtio-gpu-pci.c b/hw/display/virtio-gpu-pci.c
index ef92c4ad6f..3519dc80b1 100644
--- a/hw/display/virtio-gpu-pci.c
+++ b/hw/display/virtio-gpu-pci.c
@@ -28,10 +28,16 @@ static void virtio_gpu_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
VirtIOGPU *g = &vgpu->vdev;
DeviceState *vdev = DEVICE(&vgpu->vdev);
int i;
+ Error *local_error = NULL;
qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
virtio_pci_force_virtio_1(vpci_dev);
- object_property_set_bool(OBJECT(vdev), true, "realized", errp);
+ object_property_set_bool(OBJECT(vdev), true, "realized", &local_error);
+
+ if (local_error) {
+ error_propagate(errp, local_error);
+ return;
+ }
for (i = 0; i < g->conf.max_outputs; i++) {
object_property_set_link(OBJECT(g->scanout[i].con),
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 274e365713..6658f6c6a6 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1173,6 +1173,11 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
Error *local_err = NULL;
int i;
+ if (virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM)) {
+ error_setg(errp, "virtio-gpu does not support vIOMMU yet");
+ return;
+ }
+
if (g->conf.max_outputs > VIRTIO_GPU_MAX_SCANOUTS) {
error_setg(errp, "invalid max_outputs > %d", VIRTIO_GPU_MAX_SCANOUTS);
return;
diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c
index 8c0535d3dd..bf0b7ee0f5 100644
--- a/hw/ipmi/ipmi_bmc_extern.c
+++ b/hw/ipmi/ipmi_bmc_extern.c
@@ -425,6 +425,11 @@ static void chr_event(void *opaque, int event)
return;
}
ibe->connected = false;
+ /*
+ * Don't hang the OS trying to handle the ATN bit, other end will
+ * resend on a reconnect.
+ */
+ k->set_atn(s, 0, 0);
if (ibe->waiting_rsp) {
ibe->waiting_rsp = false;
ibe->inbuf[1] = ibe->outbuf[1] | 0x04;
diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index 277c28cb40..9b509f829b 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -38,6 +38,7 @@
#define IPMI_NETFN_SENSOR_EVENT 0x04
+#define IPMI_CMD_PLATFORM_EVENT_MSG 0x02
#define IPMI_CMD_SET_SENSOR_EVT_ENABLE 0x28
#define IPMI_CMD_GET_SENSOR_EVT_ENABLE 0x29
#define IPMI_CMD_REARM_SENSOR_EVTS 0x2a
@@ -213,8 +214,8 @@ struct IPMIBmcSim {
uint8_t device_rev;
uint8_t fwrev1;
uint8_t fwrev2;
- uint8_t mfg_id[3];
- uint8_t product_id[2];
+ uint32_t mfg_id;
+ uint16_t product_id;
uint8_t restart_cause;
@@ -443,16 +444,21 @@ static void sel_inc_reservation(IPMISel *sel)
/* Returns 1 if the SEL is full and can't hold the event. */
static int sel_add_event(IPMIBmcSim *ibs, uint8_t *event)
{
+ uint8_t ts[4];
+
event[0] = 0xff;
event[1] = 0xff;
- set_timestamp(ibs, event + 3);
+ set_timestamp(ibs, ts);
+ if (event[2] < 0xe0) { /* Don't set timestamps for type 0xe0-0xff. */
+ memcpy(event + 3, ts, 4);
+ }
if (ibs->sel.next_free == MAX_SEL_SIZE) {
ibs->sel.overflow = 1;
return 1;
}
event[0] = ibs->sel.next_free & 0xff;
event[1] = (ibs->sel.next_free >> 8) & 0xff;
- memcpy(ibs->sel.last_addition, event + 3, 4);
+ memcpy(ibs->sel.last_addition, ts, 4);
memcpy(ibs->sel.sel[ibs->sel.next_free], event, 16);
ibs->sel.next_free++;
sel_inc_reservation(&ibs->sel);
@@ -861,11 +867,11 @@ static void get_device_id(IPMIBmcSim *ibs,
rsp_buffer_push(rsp, ibs->fwrev2);
rsp_buffer_push(rsp, ibs->ipmi_version);
rsp_buffer_push(rsp, 0x07); /* sensor, SDR, and SEL. */
- rsp_buffer_push(rsp, ibs->mfg_id[0]);
- rsp_buffer_push(rsp, ibs->mfg_id[1]);
- rsp_buffer_push(rsp, ibs->mfg_id[2]);
- rsp_buffer_push(rsp, ibs->product_id[0]);
- rsp_buffer_push(rsp, ibs->product_id[1]);
+ rsp_buffer_push(rsp, ibs->mfg_id & 0xff);
+ rsp_buffer_push(rsp, (ibs->mfg_id >> 8) & 0xff);
+ rsp_buffer_push(rsp, (ibs->mfg_id >> 16) & 0xff);
+ rsp_buffer_push(rsp, ibs->product_id & 0xff);
+ rsp_buffer_push(rsp, (ibs->product_id >> 8) & 0xff);
}
static void set_global_enables(IPMIBmcSim *ibs, uint8_t val)
@@ -1576,6 +1582,28 @@ static void set_sel_time(IPMIBmcSim *ibs,
ibs->sel.time_offset = now.tv_sec - ((long) val);
}
+static void platform_event_msg(IPMIBmcSim *ibs,
+ uint8_t *cmd, unsigned int cmd_len,
+ RspBuffer *rsp)
+{
+ uint8_t event[16];
+
+ event[2] = 2; /* System event record */
+ event[7] = cmd[2]; /* Generator ID */
+ event[8] = 0;
+ event[9] = cmd[3]; /* EvMRev */
+ event[10] = cmd[4]; /* Sensor type */
+ event[11] = cmd[5]; /* Sensor number */
+ event[12] = cmd[6]; /* Event dir / Event type */
+ event[13] = cmd[7]; /* Event data 1 */
+ event[14] = cmd[8]; /* Event data 2 */
+ event[15] = cmd[9]; /* Event data 3 */
+
+ if (sel_add_event(ibs, event)) {
+ rsp_buffer_set_error(rsp, IPMI_CC_OUT_OF_SPACE);
+ }
+}
+
static void set_sensor_evt_enable(IPMIBmcSim *ibs,
uint8_t *cmd, unsigned int cmd_len,
RspBuffer *rsp)
@@ -1752,6 +1780,7 @@ static const IPMINetfn chassis_netfn = {
};
static const IPMICmdHandler sensor_event_cmds[] = {
+ [IPMI_CMD_PLATFORM_EVENT_MSG] = { platform_event_msg, 10 },
[IPMI_CMD_SET_SENSOR_EVT_ENABLE] = { set_sensor_evt_enable, 4 },
[IPMI_CMD_GET_SENSOR_EVT_ENABLE] = { get_sensor_evt_enable, 3 },
[IPMI_CMD_REARM_SENSOR_EVTS] = { rearm_sensor_evts, 4 },
@@ -1802,8 +1831,8 @@ static const IPMICmdHandler storage_cmds[] = {
[IPMI_CMD_GET_SEL_ENTRY] = { get_sel_entry, 8 },
[IPMI_CMD_ADD_SEL_ENTRY] = { add_sel_entry, 18 },
[IPMI_CMD_CLEAR_SEL] = { clear_sel, 8 },
- [IPMI_CMD_GET_SEL_TIME] = { get_sel_time, 6 },
- [IPMI_CMD_SET_SEL_TIME] = { set_sel_time },
+ [IPMI_CMD_GET_SEL_TIME] = { get_sel_time },
+ [IPMI_CMD_SET_SEL_TIME] = { set_sel_time, 6 },
};
static const IPMINetfn storage_netfn = {
@@ -1968,6 +1997,13 @@ static Property ipmi_sim_properties[] = {
DEFINE_PROP_UINT16("fruareasize", IPMIBmcSim, fru.areasize, 1024),
DEFINE_PROP_STRING("frudatafile", IPMIBmcSim, fru.filename),
DEFINE_PROP_STRING("sdrfile", IPMIBmcSim, sdr_filename),
+ DEFINE_PROP_UINT8("device_id", IPMIBmcSim, device_id, 0x20),
+ DEFINE_PROP_UINT8("ipmi_version", IPMIBmcSim, ipmi_version, 0x02),
+ DEFINE_PROP_UINT8("device_rev", IPMIBmcSim, device_rev, 0),
+ DEFINE_PROP_UINT8("fwrev1", IPMIBmcSim, fwrev1, 0),
+ DEFINE_PROP_UINT8("fwrev2", IPMIBmcSim, fwrev2, 0),
+ DEFINE_PROP_UINT32("mfg_id", IPMIBmcSim, mfg_id, 0),
+ DEFINE_PROP_UINT16("product_id", IPMIBmcSim, product_id, 0),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/ipmi/isa_ipmi_bt.c b/hw/ipmi/isa_ipmi_bt.c
index e098fd5206..e946030e84 100644
--- a/hw/ipmi/isa_ipmi_bt.c
+++ b/hw/ipmi/isa_ipmi_bt.c
@@ -45,21 +45,21 @@
#define IPMI_BT_B2H_ATN_MASK (1 << IPMI_BT_B2H_ATN_BIT)
#define IPMI_BT_GET_B2H_ATN(d) (((d) >> IPMI_BT_B2H_ATN_BIT) & 0x1)
#define IPMI_BT_SET_B2H_ATN(d, v) ((d) = (((d) & ~IPMI_BT_B2H_ATN_MASK) | \
- (((v) & 1) << IPMI_BT_B2H_ATN_BIT)))
+ (!!(v) << IPMI_BT_B2H_ATN_BIT)))
#define IPMI_BT_SMS_ATN_MASK (1 << IPMI_BT_SMS_ATN_BIT)
#define IPMI_BT_GET_SMS_ATN(d) (((d) >> IPMI_BT_SMS_ATN_BIT) & 0x1)
#define IPMI_BT_SET_SMS_ATN(d, v) ((d) = (((d) & ~IPMI_BT_SMS_ATN_MASK) | \
- (((v) & 1) << IPMI_BT_SMS_ATN_BIT)))
+ (!!(v) << IPMI_BT_SMS_ATN_BIT)))
#define IPMI_BT_HBUSY_MASK (1 << IPMI_BT_HBUSY_BIT)
#define IPMI_BT_GET_HBUSY(d) (((d) >> IPMI_BT_HBUSY_BIT) & 0x1)
#define IPMI_BT_SET_HBUSY(d, v) ((d) = (((d) & ~IPMI_BT_HBUSY_MASK) | \
- (((v) & 1) << IPMI_BT_HBUSY_BIT)))
+ (!!(v) << IPMI_BT_HBUSY_BIT)))
#define IPMI_BT_BBUSY_MASK (1 << IPMI_BT_BBUSY_BIT)
#define IPMI_BT_SET_BBUSY(d, v) ((d) = (((d) & ~IPMI_BT_BBUSY_MASK) | \
- (((v) & 1) << IPMI_BT_BBUSY_BIT)))
+ (!!(v) << IPMI_BT_BBUSY_BIT)))
/* Mask register */
@@ -69,12 +69,12 @@
#define IPMI_BT_B2H_IRQ_EN_MASK (1 << IPMI_BT_B2H_IRQ_EN_BIT)
#define IPMI_BT_GET_B2H_IRQ_EN(d) (((d) >> IPMI_BT_B2H_IRQ_EN_BIT) & 0x1)
#define IPMI_BT_SET_B2H_IRQ_EN(d, v) ((d) = (((d) & ~IPMI_BT_B2H_IRQ_EN_MASK) |\
- (((v) & 1) << IPMI_BT_B2H_IRQ_EN_BIT)))
+ (!!(v) << IPMI_BT_B2H_IRQ_EN_BIT)))
#define IPMI_BT_B2H_IRQ_MASK (1 << IPMI_BT_B2H_IRQ_BIT)
#define IPMI_BT_GET_B2H_IRQ(d) (((d) >> IPMI_BT_B2H_IRQ_BIT) & 0x1)
#define IPMI_BT_SET_B2H_IRQ(d, v) ((d) = (((d) & ~IPMI_BT_B2H_IRQ_MASK) | \
- (((v) & 1) << IPMI_BT_B2H_IRQ_BIT)))
+ (!!(v) << IPMI_BT_B2H_IRQ_BIT)))
typedef struct IPMIBT {
IPMIBmc *bmc;
diff --git a/include/hw/audio/wm8750.h b/include/hw/audio/wm8750.h
new file mode 100644
index 0000000000..84e7a119bb
--- /dev/null
+++ b/include/hw/audio/wm8750.h
@@ -0,0 +1,30 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef HW_DAC_WM8750_H
+#define HW_DAC_WM8750_H
+
+#include "hw/hw.h"
+
+#define TYPE_WM8750 "wm8750"
+
+typedef void data_req_cb(void *opaque, int free_out, int free_in);
+
+void wm8750_data_req_set(DeviceState *dev, data_req_cb *data_req, void *opaque);
+void wm8750_dac_dat(void *opaque, uint32_t sample);
+uint32_t wm8750_adc_dat(void *opaque);
+void *wm8750_dac_buffer(void *opaque, int samples);
+void wm8750_dac_commit(void *opaque);
+void wm8750_set_bclk_in(void *opaque, int new_hz);
+
+#endif
diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h
index 2ce611d4c8..24e95d0155 100644
--- a/include/hw/i2c/i2c.h
+++ b/include/hw/i2c/i2c.h
@@ -70,15 +70,6 @@ int i2c_recv(I2CBus *bus);
DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr);
-/* wm8750.c */
-void wm8750_data_req_set(DeviceState *dev,
- void (*data_req)(void *, int, int), void *opaque);
-void wm8750_dac_dat(void *opaque, uint32_t sample);
-uint32_t wm8750_adc_dat(void *opaque);
-void *wm8750_dac_buffer(void *opaque, int samples);
-void wm8750_dac_commit(void *opaque);
-void wm8750_set_bclk_in(void *opaque, int new_hz);
-
/* lm832x.c */
void lm832x_key_event(DeviceState *dev, int key, int state);
diff --git a/tests/libqos/virtio.c b/tests/libqos/virtio.c
index 0879a621c8..0dad5c19ac 100644
--- a/tests/libqos/virtio.c
+++ b/tests/libqos/virtio.c
@@ -119,6 +119,8 @@ uint8_t qvirtio_wait_status_byte_no_isr(QVirtioDevice *d,
/*
* qvirtio_wait_used_elem:
* @desc_idx: The next expected vq->desc[] index in the used ring
+ * @len: A pointer that is filled with the length written into the buffer, may
+ * be NULL
* @timeout_us: How many microseconds to wait before failing
*
* This function waits for the next completed request on the used ring.
@@ -126,6 +128,7 @@ uint8_t qvirtio_wait_status_byte_no_isr(QVirtioDevice *d,
void qvirtio_wait_used_elem(QVirtioDevice *d,
QVirtQueue *vq,
uint32_t desc_idx,
+ uint32_t *len,
gint64 timeout_us)
{
gint64 start_time = g_get_monotonic_time();
@@ -136,7 +139,7 @@ void qvirtio_wait_used_elem(QVirtioDevice *d,
clock_step(100);
if (d->bus->get_queue_isr_status(d, vq) &&
- qvirtqueue_get_buf(vq, &got_desc_idx)) {
+ qvirtqueue_get_buf(vq, &got_desc_idx, len)) {
g_assert_cmpint(got_desc_idx, ==, desc_idx);
return;
}
@@ -304,30 +307,36 @@ void qvirtqueue_kick(QVirtioDevice *d, QVirtQueue *vq, uint32_t free_head)
/*
* qvirtqueue_get_buf:
* @desc_idx: A pointer that is filled with the vq->desc[] index, may be NULL
+ * @len: A pointer that is filled with the length written into the buffer, may
+ * be NULL
*
* This function gets the next used element if there is one ready.
*
* Returns: true if an element was ready, false otherwise
*/
-bool qvirtqueue_get_buf(QVirtQueue *vq, uint32_t *desc_idx)
+bool qvirtqueue_get_buf(QVirtQueue *vq, uint32_t *desc_idx, uint32_t *len)
{
uint16_t idx;
+ uint64_t elem_addr;
idx = readw(vq->used + offsetof(struct vring_used, idx));
if (idx == vq->last_used_idx) {
return false;
}
- if (desc_idx) {
- uint64_t elem_addr;
+ elem_addr = vq->used +
+ offsetof(struct vring_used, ring) +
+ (vq->last_used_idx % vq->size) *
+ sizeof(struct vring_used_elem);
- elem_addr = vq->used +
- offsetof(struct vring_used, ring) +
- (vq->last_used_idx % vq->size) *
- sizeof(struct vring_used_elem);
+ if (desc_idx) {
*desc_idx = readl(elem_addr + offsetof(struct vring_used_elem, id));
}
+ if (len) {
+ *len = readw(elem_addr + offsetof(struct vring_used_elem, len));
+ }
+
vq->last_used_idx++;
return true;
}
diff --git a/tests/libqos/virtio.h b/tests/libqos/virtio.h
index 0a04740adf..69b5b13840 100644
--- a/tests/libqos/virtio.h
+++ b/tests/libqos/virtio.h
@@ -124,6 +124,7 @@ uint8_t qvirtio_wait_status_byte_no_isr(QVirtioDevice *d,
void qvirtio_wait_used_elem(QVirtioDevice *d,
QVirtQueue *vq,
uint32_t desc_idx,
+ uint32_t *len,
gint64 timeout_us);
void qvirtio_wait_config_isr(QVirtioDevice *d, gint64 timeout_us);
QVirtQueue *qvirtqueue_setup(QVirtioDevice *d,
@@ -140,7 +141,7 @@ uint32_t qvirtqueue_add(QVirtQueue *vq, uint64_t data, uint32_t len, bool write,
bool next);
uint32_t qvirtqueue_add_indirect(QVirtQueue *vq, QVRingIndirectDesc *indirect);
void qvirtqueue_kick(QVirtioDevice *d, QVirtQueue *vq, uint32_t free_head);
-bool qvirtqueue_get_buf(QVirtQueue *vq, uint32_t *desc_idx);
+bool qvirtqueue_get_buf(QVirtQueue *vq, uint32_t *desc_idx, uint32_t *len);
void qvirtqueue_set_used_event(QVirtQueue *vq, uint16_t idx);
diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index 00f00f7246..54edcb9955 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -17,6 +17,7 @@
#include "standard-headers/linux/virtio_ids.h"
#include "standard-headers/linux/virtio_pci.h"
#include "hw/9pfs/9p.h"
+#include "hw/9pfs/9p-synth.h"
#define QVIRTIO_9P_TIMEOUT_US (10 * 1000 * 1000)
@@ -26,24 +27,19 @@ typedef struct {
QVirtioDevice *dev;
QOSState *qs;
QVirtQueue *vq;
- char *test_share;
- uint16_t p9_req_tag;
} QVirtIO9P;
static QVirtIO9P *qvirtio_9p_start(const char *driver)
{
const char *arch = qtest_get_arch();
- const char *cmd = "-fsdev local,id=fsdev0,security_model=none,path=%s "
+ const char *cmd = "-fsdev synth,id=fsdev0 "
"-device %s,fsdev=fsdev0,mount_tag=%s";
QVirtIO9P *v9p = g_new0(QVirtIO9P, 1);
- v9p->test_share = g_strdup("/tmp/qtest.XXXXXX");
- g_assert_nonnull(mkdtemp(v9p->test_share));
-
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
- v9p->qs = qtest_pc_boot(cmd, v9p->test_share, driver, mount_tag);
+ v9p->qs = qtest_pc_boot(cmd, driver, mount_tag);
} else if (strcmp(arch, "ppc64") == 0) {
- v9p->qs = qtest_spapr_boot(cmd, v9p->test_share, driver, mount_tag);
+ v9p->qs = qtest_spapr_boot(cmd, driver, mount_tag);
} else {
g_printerr("virtio-9p tests are only available on x86 or ppc64\n");
exit(EXIT_FAILURE);
@@ -55,8 +51,6 @@ static QVirtIO9P *qvirtio_9p_start(const char *driver)
static void qvirtio_9p_stop(QVirtIO9P *v9p)
{
qtest_shutdown(v9p->qs);
- rmdir(v9p->test_share);
- g_free(v9p->test_share);
g_free(v9p);
}
@@ -156,6 +150,13 @@ static void v9fs_uint32_write(P9Req *req, uint32_t val)
v9fs_memwrite(req, &le_val, 4);
}
+static void v9fs_uint64_write(P9Req *req, uint64_t val)
+{
+ uint64_t le_val = cpu_to_le64(val);
+
+ v9fs_memwrite(req, &le_val, 8);
+}
+
static void v9fs_uint32_read(P9Req *req, uint32_t *val)
{
v9fs_memread(req, val, 4);
@@ -167,7 +168,7 @@ static uint16_t v9fs_string_size(const char *string)
{
size_t len = strlen(string);
- g_assert_cmpint(len, <=, UINT16_MAX);
+ g_assert_cmpint(len, <=, UINT16_MAX - 2);
return 2 + len;
}
@@ -208,17 +209,20 @@ static P9Req *v9fs_req_init(QVirtIO9P *v9p, uint32_t size, uint8_t id,
uint16_t tag)
{
P9Req *req = g_new0(P9Req, 1);
- uint32_t t_size = 7 + size; /* 9P header has well-known size of 7 bytes */
+ uint32_t total_size = 7; /* 9P header has well-known size of 7 bytes */
P9Hdr hdr = {
- .size = cpu_to_le32(t_size),
.id = id,
.tag = cpu_to_le16(tag)
};
- g_assert_cmpint(t_size, <=, P9_MAX_SIZE);
+ g_assert_cmpint(total_size, <=, UINT32_MAX - size);
+ total_size += size;
+ hdr.size = cpu_to_le32(total_size);
+
+ g_assert_cmpint(total_size, <=, P9_MAX_SIZE);
req->v9p = v9p;
- req->t_size = t_size;
+ req->t_size = total_size;
req->t_msg = guest_alloc(v9p->qs->alloc, req->t_size);
v9fs_memwrite(req, &hdr, 7);
req->tag = tag;
@@ -244,16 +248,23 @@ static const char *rmessage_name(uint8_t id)
id == P9_RVERSION ? "RVERSION" :
id == P9_RATTACH ? "RATTACH" :
id == P9_RWALK ? "RWALK" :
+ id == P9_RLOPEN ? "RLOPEN" :
+ id == P9_RWRITE ? "RWRITE" :
+ id == P9_RFLUSH ? "RFLUSH" :
"<unknown>";
}
-static void v9fs_req_recv(P9Req *req, uint8_t id)
+static void v9fs_req_wait_for_reply(P9Req *req, uint32_t *len)
{
QVirtIO9P *v9p = req->v9p;
- P9Hdr hdr;
- qvirtio_wait_used_elem(v9p->dev, v9p->vq, req->free_head,
+ qvirtio_wait_used_elem(v9p->dev, v9p->vq, req->free_head, len,
QVIRTIO_9P_TIMEOUT_US);
+}
+
+static void v9fs_req_recv(P9Req *req, uint8_t id)
+{
+ P9Hdr hdr;
v9fs_memread(req, &hdr, 7);
hdr.size = ldl_le_p(&hdr.size);
@@ -294,10 +305,16 @@ static void v9fs_rlerror(P9Req *req, uint32_t *err)
}
/* size[4] Tversion tag[2] msize[4] version[s] */
-static P9Req *v9fs_tversion(QVirtIO9P *v9p, uint32_t msize, const char *version)
+static P9Req *v9fs_tversion(QVirtIO9P *v9p, uint32_t msize, const char *version,
+ uint16_t tag)
{
- P9Req *req = v9fs_req_init(v9p, 4 + v9fs_string_size(version), P9_TVERSION,
- P9_NOTAG);
+ P9Req *req;
+ uint32_t body_size = 4;
+ uint16_t string_size = v9fs_string_size(version);
+
+ g_assert_cmpint(body_size, <=, UINT32_MAX - string_size);
+ body_size += string_size;
+ req = v9fs_req_init(v9p, body_size, P9_TVERSION, tag);
v9fs_uint32_write(req, msize);
v9fs_string_write(req, version);
@@ -323,12 +340,12 @@ static void v9fs_rversion(P9Req *req, uint16_t *len, char **version)
}
/* size[4] Tattach tag[2] fid[4] afid[4] uname[s] aname[s] n_uname[4] */
-static P9Req *v9fs_tattach(QVirtIO9P *v9p, uint32_t fid, uint32_t n_uname)
+static P9Req *v9fs_tattach(QVirtIO9P *v9p, uint32_t fid, uint32_t n_uname,
+ uint16_t tag)
{
const char *uname = ""; /* ignored by QEMU */
const char *aname = ""; /* ignored by QEMU */
- P9Req *req = v9fs_req_init(v9p, 4 + 4 + 2 + 2 + 4, P9_TATTACH,
- ++(v9p->p9_req_tag));
+ P9Req *req = v9fs_req_init(v9p, 4 + 4 + 2 + 2 + 4, P9_TATTACH, tag);
v9fs_uint32_write(req, fid);
v9fs_uint32_write(req, P9_NOFID);
@@ -353,16 +370,19 @@ static void v9fs_rattach(P9Req *req, v9fs_qid *qid)
/* size[4] Twalk tag[2] fid[4] newfid[4] nwname[2] nwname*(wname[s]) */
static P9Req *v9fs_twalk(QVirtIO9P *v9p, uint32_t fid, uint32_t newfid,
- uint16_t nwname, char *const wnames[])
+ uint16_t nwname, char *const wnames[], uint16_t tag)
{
P9Req *req;
int i;
- uint32_t size = 4 + 4 + 2;
+ uint32_t body_size = 4 + 4 + 2;
for (i = 0; i < nwname; i++) {
- size += v9fs_string_size(wnames[i]);
+ uint16_t wname_size = v9fs_string_size(wnames[i]);
+
+ g_assert_cmpint(body_size, <=, UINT32_MAX - wname_size);
+ body_size += wname_size;
}
- req = v9fs_req_init(v9p, size, P9_TWALK, ++(v9p->p9_req_tag));
+ req = v9fs_req_init(v9p, body_size, P9_TWALK, tag);
v9fs_uint32_write(req, fid);
v9fs_uint32_write(req, newfid);
v9fs_uint16_write(req, nwname);
@@ -390,6 +410,80 @@ static void v9fs_rwalk(P9Req *req, uint16_t *nwqid, v9fs_qid **wqid)
v9fs_req_free(req);
}
+/* size[4] Tlopen tag[2] fid[4] flags[4] */
+static P9Req *v9fs_tlopen(QVirtIO9P *v9p, uint32_t fid, uint32_t flags,
+ uint16_t tag)
+{
+ P9Req *req;
+
+ req = v9fs_req_init(v9p, 4 + 4, P9_TLOPEN, tag);
+ v9fs_uint32_write(req, fid);
+ v9fs_uint32_write(req, flags);
+ v9fs_req_send(req);
+ return req;
+}
+
+/* size[4] Rlopen tag[2] qid[13] iounit[4] */
+static void v9fs_rlopen(P9Req *req, v9fs_qid *qid, uint32_t *iounit)
+{
+ v9fs_req_recv(req, P9_RLOPEN);
+ if (qid) {
+ v9fs_memread(req, qid, 13);
+ } else {
+ v9fs_memskip(req, 13);
+ }
+ if (iounit) {
+ v9fs_uint32_read(req, iounit);
+ }
+ v9fs_req_free(req);
+}
+
+/* size[4] Twrite tag[2] fid[4] offset[8] count[4] data[count] */
+static P9Req *v9fs_twrite(QVirtIO9P *v9p, uint32_t fid, uint64_t offset,
+ uint32_t count, const void *data, uint16_t tag)
+{
+ P9Req *req;
+ uint32_t body_size = 4 + 8 + 4;
+
+ g_assert_cmpint(body_size, <=, UINT32_MAX - count);
+ body_size += count;
+ req = v9fs_req_init(v9p, body_size, P9_TWRITE, tag);
+ v9fs_uint32_write(req, fid);
+ v9fs_uint64_write(req, offset);
+ v9fs_uint32_write(req, count);
+ v9fs_memwrite(req, data, count);
+ v9fs_req_send(req);
+ return req;
+}
+
+/* size[4] Rwrite tag[2] count[4] */
+static void v9fs_rwrite(P9Req *req, uint32_t *count)
+{
+ v9fs_req_recv(req, P9_RWRITE);
+ if (count) {
+ v9fs_uint32_read(req, count);
+ }
+ v9fs_req_free(req);
+}
+
+/* size[4] Tflush tag[2] oldtag[2] */
+static P9Req *v9fs_tflush(QVirtIO9P *v9p, uint16_t oldtag, uint16_t tag)
+{
+ P9Req *req;
+
+ req = v9fs_req_init(v9p, 2, P9_TFLUSH, tag);
+ v9fs_uint32_write(req, oldtag);
+ v9fs_req_send(req);
+ return req;
+}
+
+/* size[4] Rflush tag[2] */
+static void v9fs_rflush(P9Req *req)
+{
+ v9fs_req_recv(req, P9_RFLUSH);
+ v9fs_req_free(req);
+}
+
static void fs_version(QVirtIO9P *v9p)
{
const char *version = "9P2000.L";
@@ -397,7 +491,8 @@ static void fs_version(QVirtIO9P *v9p)
char *server_version;
P9Req *req;
- req = v9fs_tversion(v9p, P9_MAX_SIZE, version);
+ req = v9fs_tversion(v9p, P9_MAX_SIZE, version, P9_NOTAG);
+ v9fs_req_wait_for_reply(req, NULL);
v9fs_rversion(req, &server_len, &server_version);
g_assert_cmpmem(server_version, server_len, version, strlen(version));
@@ -410,34 +505,31 @@ static void fs_attach(QVirtIO9P *v9p)
P9Req *req;
fs_version(v9p);
- req = v9fs_tattach(v9p, 0, getuid());
+ req = v9fs_tattach(v9p, 0, getuid(), 0);
+ v9fs_req_wait_for_reply(req, NULL);
v9fs_rattach(req, NULL);
}
static void fs_walk(QVirtIO9P *v9p)
{
- char *wnames[P9_MAXWELEM], *paths[P9_MAXWELEM];
- char *last_path = v9p->test_share;
+ char *wnames[P9_MAXWELEM];
uint16_t nwqid;
v9fs_qid *wqid;
int i;
P9Req *req;
for (i = 0; i < P9_MAXWELEM; i++) {
- wnames[i] = g_strdup_printf("%s%d", __func__, i);
- last_path = paths[i] = g_strdup_printf("%s/%s", last_path, wnames[i]);
- g_assert(!mkdir(paths[i], 0700));
+ wnames[i] = g_strdup_printf(QTEST_V9FS_SYNTH_WALK_FILE, i);
}
fs_attach(v9p);
- req = v9fs_twalk(v9p, 0, 1, P9_MAXWELEM, wnames);
+ req = v9fs_twalk(v9p, 0, 1, P9_MAXWELEM, wnames, 0);
+ v9fs_req_wait_for_reply(req, NULL);
v9fs_rwalk(req, &nwqid, &wqid);
g_assert_cmpint(nwqid, ==, P9_MAXWELEM);
for (i = 0; i < P9_MAXWELEM; i++) {
- rmdir(paths[P9_MAXWELEM - i - 1]);
- g_free(paths[P9_MAXWELEM - i - 1]);
g_free(wnames[i]);
}
@@ -451,7 +543,8 @@ static void fs_walk_no_slash(QVirtIO9P *v9p)
uint32_t err;
fs_attach(v9p);
- req = v9fs_twalk(v9p, 0, 1, 1, wnames);
+ req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0);
+ v9fs_req_wait_for_reply(req, NULL);
v9fs_rlerror(req, &err);
g_assert_cmpint(err, ==, ENOENT);
@@ -466,10 +559,12 @@ static void fs_walk_dotdot(QVirtIO9P *v9p)
P9Req *req;
fs_version(v9p);
- req = v9fs_tattach(v9p, 0, getuid());
+ req = v9fs_tattach(v9p, 0, getuid(), 0);
+ v9fs_req_wait_for_reply(req, NULL);
v9fs_rattach(req, &root_qid);
- req = v9fs_twalk(v9p, 0, 1, 1, wnames);
+ req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0);
+ v9fs_req_wait_for_reply(req, NULL);
v9fs_rwalk(req, NULL, &wqid); /* We now we'll get one qid */
g_assert_cmpmem(&root_qid, 13, wqid[0], 13);
@@ -478,6 +573,119 @@ static void fs_walk_dotdot(QVirtIO9P *v9p)
g_free(wnames[0]);
}
+static void fs_lopen(QVirtIO9P *v9p)
+{
+ char *const wnames[] = { g_strdup(QTEST_V9FS_SYNTH_LOPEN_FILE) };
+ P9Req *req;
+
+ fs_attach(v9p);
+ req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0);
+ v9fs_req_wait_for_reply(req, NULL);
+ v9fs_rwalk(req, NULL, NULL);
+
+ req = v9fs_tlopen(v9p, 1, O_WRONLY, 0);
+ v9fs_req_wait_for_reply(req, NULL);
+ v9fs_rlopen(req, NULL, NULL);
+
+ g_free(wnames[0]);
+}
+
+static void fs_write(QVirtIO9P *v9p)
+{
+ static const uint32_t write_count = P9_MAX_SIZE / 2;
+ char *const wnames[] = { g_strdup(QTEST_V9FS_SYNTH_WRITE_FILE) };
+ char *buf = g_malloc0(write_count);
+ uint32_t count;
+ P9Req *req;
+
+ fs_attach(v9p);
+ req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0);
+ v9fs_req_wait_for_reply(req, NULL);
+ v9fs_rwalk(req, NULL, NULL);
+
+ req = v9fs_tlopen(v9p, 1, O_WRONLY, 0);
+ v9fs_req_wait_for_reply(req, NULL);
+ v9fs_rlopen(req, NULL, NULL);
+
+ req = v9fs_twrite(v9p, 1, 0, write_count, buf, 0);
+ v9fs_req_wait_for_reply(req, NULL);
+ v9fs_rwrite(req, &count);
+ g_assert_cmpint(count, ==, write_count);
+
+ g_free(buf);
+ g_free(wnames[0]);
+}
+
+static void fs_flush_success(QVirtIO9P *v9p)
+{
+ char *const wnames[] = { g_strdup(QTEST_V9FS_SYNTH_FLUSH_FILE) };
+ P9Req *req, *flush_req;
+ uint32_t reply_len;
+ uint8_t should_block;
+
+ fs_attach(v9p);
+ req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0);
+ v9fs_req_wait_for_reply(req, NULL);
+ v9fs_rwalk(req, NULL, NULL);
+
+ req = v9fs_tlopen(v9p, 1, O_WRONLY, 0);
+ v9fs_req_wait_for_reply(req, NULL);
+ v9fs_rlopen(req, NULL, NULL);
+
+ /* This will cause the 9p server to try to write data to the backend,
+ * until the write request gets cancelled.
+ */
+ should_block = 1;
+ req = v9fs_twrite(v9p, 1, 0, sizeof(should_block), &should_block, 0);
+
+ flush_req = v9fs_tflush(v9p, req->tag, 1);
+
+ /* The write request is supposed to be flushed: the server should just
+ * mark the write request as used and reply to the flush request.
+ */
+ v9fs_req_wait_for_reply(req, &reply_len);
+ g_assert_cmpint(reply_len, ==, 0);
+ v9fs_req_free(req);
+ v9fs_rflush(flush_req);
+
+ g_free(wnames[0]);
+}
+
+static void fs_flush_ignored(QVirtIO9P *v9p)
+{
+ char *const wnames[] = { g_strdup(QTEST_V9FS_SYNTH_FLUSH_FILE) };
+ P9Req *req, *flush_req;
+ uint32_t count;
+ uint8_t should_block;
+
+ fs_attach(v9p);
+ req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0);
+ v9fs_req_wait_for_reply(req, NULL);
+ v9fs_rwalk(req, NULL, NULL);
+
+ req = v9fs_tlopen(v9p, 1, O_WRONLY, 0);
+ v9fs_req_wait_for_reply(req, NULL);
+ v9fs_rlopen(req, NULL, NULL);
+
+ /* This will cause the write request to complete right away, before it
+ * could be actually cancelled.
+ */
+ should_block = 0;
+ req = v9fs_twrite(v9p, 1, 0, sizeof(should_block), &should_block, 0);
+
+ flush_req = v9fs_tflush(v9p, req->tag, 1);
+
+ /* The write request is supposed to complete. The server should
+ * reply to the write request and the flush request.
+ */
+ v9fs_req_wait_for_reply(req, NULL);
+ v9fs_rwrite(req, &count);
+ g_assert_cmpint(count, ==, sizeof(should_block));
+ v9fs_rflush(flush_req);
+
+ g_free(wnames[0]);
+}
+
typedef void (*v9fs_test_fn)(QVirtIO9P *v9p);
static void v9fs_run_pci_test(gconstpointer data)
@@ -507,6 +715,10 @@ int main(int argc, char **argv)
v9fs_qtest_pci_add("/virtio/9p/pci/fs/walk/no_slash", fs_walk_no_slash);
v9fs_qtest_pci_add("/virtio/9p/pci/fs/walk/dotdot_from_root",
fs_walk_dotdot);
+ v9fs_qtest_pci_add("/virtio/9p/pci/fs/lopen/basic", fs_lopen);
+ v9fs_qtest_pci_add("/virtio/9p/pci/fs/write/basic", fs_write);
+ v9fs_qtest_pci_add("/virtio/9p/pci/fs/flush/success", fs_flush_success);
+ v9fs_qtest_pci_add("/virtio/9p/pci/fs/flush/ignored", fs_flush_ignored);
return g_test_run();
}
diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c
index 45f368dcd9..2ac64e5e25 100644
--- a/tests/virtio-blk-test.c
+++ b/tests/virtio-blk-test.c
@@ -193,7 +193,7 @@ static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
qvirtqueue_kick(dev, vq, free_head);
- qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_BLK_TIMEOUT_US);
+ qvirtio_wait_used_elem(dev, vq, free_head, NULL, QVIRTIO_BLK_TIMEOUT_US);
status = readb(req_addr + 528);
g_assert_cmpint(status, ==, 0);
@@ -215,7 +215,7 @@ static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
qvirtqueue_kick(dev, vq, free_head);
- qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_BLK_TIMEOUT_US);
+ qvirtio_wait_used_elem(dev, vq, free_head, NULL, QVIRTIO_BLK_TIMEOUT_US);
status = readb(req_addr + 528);
g_assert_cmpint(status, ==, 0);
@@ -243,7 +243,8 @@ static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
qvirtqueue_add(vq, req_addr + 528, 1, true, false);
qvirtqueue_kick(dev, vq, free_head);
- qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_BLK_TIMEOUT_US);
+ qvirtio_wait_used_elem(dev, vq, free_head, NULL,
+ QVIRTIO_BLK_TIMEOUT_US);
status = readb(req_addr + 528);
g_assert_cmpint(status, ==, 0);
@@ -264,7 +265,8 @@ static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
qvirtqueue_kick(dev, vq, free_head);
- qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_BLK_TIMEOUT_US);
+ qvirtio_wait_used_elem(dev, vq, free_head, NULL,
+ QVIRTIO_BLK_TIMEOUT_US);
status = readb(req_addr + 528);
g_assert_cmpint(status, ==, 0);
@@ -345,7 +347,7 @@ static void pci_indirect(void)
free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
- qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head,
+ qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
QVIRTIO_BLK_TIMEOUT_US);
status = readb(req_addr + 528);
g_assert_cmpint(status, ==, 0);
@@ -370,7 +372,7 @@ static void pci_indirect(void)
free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
- qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head,
+ qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
QVIRTIO_BLK_TIMEOUT_US);
status = readb(req_addr + 528);
g_assert_cmpint(status, ==, 0);
@@ -481,7 +483,7 @@ static void pci_msix(void)
qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
- qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head,
+ qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
QVIRTIO_BLK_TIMEOUT_US);
status = readb(req_addr + 528);
@@ -506,7 +508,7 @@ static void pci_msix(void)
qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
- qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head,
+ qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
QVIRTIO_BLK_TIMEOUT_US);
status = readb(req_addr + 528);
@@ -580,7 +582,7 @@ static void pci_idx(void)
qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
- qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head,
+ qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
QVIRTIO_BLK_TIMEOUT_US);
/* Write request */
@@ -627,9 +629,9 @@ static void pci_idx(void)
qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
/* We get just one notification for both requests */
- qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, write_head,
+ qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, write_head, NULL,
QVIRTIO_BLK_TIMEOUT_US);
- g_assert(qvirtqueue_get_buf(&vqpci->vq, &desc_idx));
+ g_assert(qvirtqueue_get_buf(&vqpci->vq, &desc_idx, NULL));
g_assert_cmpint(desc_idx, ==, free_head);
status = readb(req_addr + 528);
diff --git a/tests/virtio-net-test.c b/tests/virtio-net-test.c
index 635b942c36..ea634dc05a 100644
--- a/tests/virtio-net-test.c
+++ b/tests/virtio-net-test.c
@@ -108,7 +108,7 @@ static void rx_test(QVirtioDevice *dev,
ret = iov_send(socket, iov, 2, 0, sizeof(len) + sizeof(test));
g_assert_cmpint(ret, ==, sizeof(test) + sizeof(len));
- qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_NET_TIMEOUT_US);
+ qvirtio_wait_used_elem(dev, vq, free_head, NULL, QVIRTIO_NET_TIMEOUT_US);
memread(req_addr + VNET_HDR_SIZE, buffer, sizeof(test));
g_assert_cmpstr(buffer, ==, "TEST");
@@ -131,7 +131,7 @@ static void tx_test(QVirtioDevice *dev,
free_head = qvirtqueue_add(vq, req_addr, 64, false, false);
qvirtqueue_kick(dev, vq, free_head);
- qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_NET_TIMEOUT_US);
+ qvirtio_wait_used_elem(dev, vq, free_head, NULL, QVIRTIO_NET_TIMEOUT_US);
guest_free(alloc, req_addr);
ret = qemu_recv(socket, &len, sizeof(len), 0);
@@ -182,7 +182,7 @@ static void rx_stop_cont_test(QVirtioDevice *dev,
rsp = qmp("{ 'execute' : 'cont'}");
QDECREF(rsp);
- qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_NET_TIMEOUT_US);
+ qvirtio_wait_used_elem(dev, vq, free_head, NULL, QVIRTIO_NET_TIMEOUT_US);
memread(req_addr + VNET_HDR_SIZE, buffer, sizeof(test));
g_assert_cmpstr(buffer, ==, "TEST");
diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c
index 2934305b2b..bcf408fbb6 100644
--- a/tests/virtio-scsi-test.c
+++ b/tests/virtio-scsi-test.c
@@ -121,7 +121,8 @@ static uint8_t virtio_scsi_do_command(QVirtIOSCSI *vs, const uint8_t *cdb,
}
qvirtqueue_kick(vs->dev, vq, free_head);
- qvirtio_wait_used_elem(vs->dev, vq, free_head, QVIRTIO_SCSI_TIMEOUT_US);
+ qvirtio_wait_used_elem(vs->dev, vq, free_head, NULL,
+ QVIRTIO_SCSI_TIMEOUT_US);
response = readb(resp_addr +
offsetof(struct virtio_scsi_cmd_resp, response));
diff --git a/ui/sdl.c b/ui/sdl.c
index c8f102bb9f..a6bff301eb 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -242,6 +242,7 @@ static const guint16 *sdl_get_keymap(size_t *maplen)
static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
{
+ int qcode;
if (!keycode_map) {
return 0;
}
@@ -249,7 +250,13 @@ static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
return 0;
}
- return keycode_map[ev->keysym.scancode];
+ qcode = keycode_map[ev->keysym.scancode];
+
+ if (qcode > qemu_input_map_qcode_to_qnum_len) {
+ return 0;
+ }
+
+ return qemu_input_map_qcode_to_qnum[qcode];
}
static void reset_keys(void)
diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c
index 74a5f513f2..fbccca8c8a 100644
--- a/ui/vnc-auth-sasl.c
+++ b/ui/vnc-auth-sasl.c
@@ -84,7 +84,7 @@ size_t vnc_client_write_sasl(VncState *vs)
} else {
vs->force_update_offset -= vs->sasl.encodedRawLength;
}
- vs->output.offset -= vs->sasl.encodedRawLength;
+ buffer_advance(&vs->output, vs->sasl.encodedRawLength);
vs->sasl.encoded = NULL;
vs->sasl.encodedOffset = vs->sasl.encodedLength = 0;
}
diff --git a/ui/vnc.c b/ui/vnc.c
index 33b087221f..93731accb6 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -228,12 +228,12 @@ static VncServerInfo *vnc_server_info_get(VncDisplay *vd)
VncServerInfo *info;
Error *err = NULL;
- if (!vd->nlsock) {
+ if (!vd->listener || !vd->listener->nsioc) {
return NULL;
}
info = g_malloc0(sizeof(*info));
- vnc_init_basic_info_from_server_addr(vd->lsock[0],
+ vnc_init_basic_info_from_server_addr(vd->listener->sioc[0],
qapi_VncServerInfo_base(info), &err);
info->has_auth = true;
info->auth = g_strdup(vnc_auth_name(vd));
@@ -379,7 +379,7 @@ VncInfo *qmp_query_vnc(Error **errp)
VncDisplay *vd = vnc_display_find(NULL);
SocketAddress *addr = NULL;
- if (vd == NULL || !vd->nlsock) {
+ if (vd == NULL || !vd->listener || !vd->listener->nsioc) {
info->enabled = false;
} else {
info->enabled = true;
@@ -388,11 +388,8 @@ VncInfo *qmp_query_vnc(Error **errp)
info->has_clients = true;
info->clients = qmp_query_client_list(vd);
- if (vd->lsock == NULL) {
- return info;
- }
-
- addr = qio_channel_socket_get_local_address(vd->lsock[0], errp);
+ addr = qio_channel_socket_get_local_address(vd->listener->sioc[0],
+ errp);
if (!addr) {
goto out_error;
}
@@ -572,13 +569,14 @@ VncInfo2List *qmp_query_vnc_servers(Error **errp)
info->has_display = true;
info->display = g_strdup(dev->id);
}
- for (i = 0; i < vd->nlsock; i++) {
+ for (i = 0; vd->listener != NULL && i < vd->listener->nsioc; i++) {
info->server = qmp_query_server_entry(
- vd->lsock[i], false, vd->auth, vd->subauth, info->server);
+ vd->listener->sioc[i], false, vd->auth, vd->subauth,
+ info->server);
}
- for (i = 0; i < vd->nlwebsock; i++) {
+ for (i = 0; vd->wslistener != NULL && i < vd->wslistener->nsioc; i++) {
info->server = qmp_query_server_entry(
- vd->lwebsock[i], true, vd->ws_auth,
+ vd->wslistener->sioc[i], true, vd->ws_auth,
vd->ws_subauth, info->server);
}
@@ -3143,36 +3141,18 @@ void vnc_start_protocol(VncState *vs)
qemu_add_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
}
-static gboolean vnc_listen_io(QIOChannel *ioc,
- GIOCondition condition,
- void *opaque)
+static void vnc_listen_io(QIONetListener *listener,
+ QIOChannelSocket *cioc,
+ void *opaque)
{
VncDisplay *vd = opaque;
- QIOChannelSocket *sioc = NULL;
- Error *err = NULL;
- bool isWebsock = false;
- size_t i;
-
- for (i = 0; i < vd->nlwebsock; i++) {
- if (ioc == QIO_CHANNEL(vd->lwebsock[i])) {
- isWebsock = true;
- break;
- }
- }
+ bool isWebsock = listener == vd->wslistener;
- sioc = qio_channel_socket_accept(QIO_CHANNEL_SOCKET(ioc), &err);
- if (sioc != NULL) {
- qio_channel_set_name(QIO_CHANNEL(sioc),
- isWebsock ? "vnc-ws-server" : "vnc-server");
- qio_channel_set_delay(QIO_CHANNEL(sioc), false);
- vnc_connect(vd, sioc, false, isWebsock);
- object_unref(OBJECT(sioc));
- } else {
- /* client probably closed connection before we got there */
- error_free(err);
- }
-
- return TRUE;
+ qio_channel_set_name(QIO_CHANNEL(cioc),
+ isWebsock ? "vnc-ws-server" : "vnc-server");
+ qio_channel_set_delay(QIO_CHANNEL(cioc), false);
+ vnc_connect(vd, cioc, false, isWebsock);
+ object_unref(OBJECT(cioc));
}
static const DisplayChangeListenerOps dcl_ops = {
@@ -3224,34 +3204,22 @@ void vnc_display_init(const char *id)
static void vnc_display_close(VncDisplay *vd)
{
- size_t i;
if (!vd) {
return;
}
vd->is_unix = false;
- for (i = 0; i < vd->nlsock; i++) {
- if (vd->lsock_tag[i]) {
- g_source_remove(vd->lsock_tag[i]);
- }
- object_unref(OBJECT(vd->lsock[i]));
+
+ if (vd->listener) {
+ qio_net_listener_disconnect(vd->listener);
+ object_unref(OBJECT(vd->listener));
}
- g_free(vd->lsock);
- g_free(vd->lsock_tag);
- vd->lsock = NULL;
- vd->lsock_tag = NULL;
- vd->nlsock = 0;
+ vd->listener = NULL;
- for (i = 0; i < vd->nlwebsock; i++) {
- if (vd->lwebsock_tag[i]) {
- g_source_remove(vd->lwebsock_tag[i]);
- }
- object_unref(OBJECT(vd->lwebsock[i]));
+ if (vd->wslistener) {
+ qio_net_listener_disconnect(vd->wslistener);
+ object_unref(OBJECT(vd->wslistener));
}
- g_free(vd->lwebsock);
- g_free(vd->lwebsock_tag);
- vd->lwebsock = NULL;
- vd->lwebsock_tag = NULL;
- vd->nlwebsock = 0;
+ vd->wslistener = NULL;
vd->auth = VNC_AUTH_INVALID;
vd->subauth = VNC_AUTH_INVALID;
@@ -3303,11 +3271,11 @@ static void vnc_display_print_local_addr(VncDisplay *vd)
SocketAddress *addr;
Error *err = NULL;
- if (!vd->nlsock) {
+ if (!vd->listener || !vd->listener->nsioc) {
return;
}
- addr = qio_channel_socket_get_local_address(vd->lsock[0], &err);
+ addr = qio_channel_socket_get_local_address(vd->listener->sioc[0], &err);
if (!addr) {
return;
}
@@ -3815,68 +3783,6 @@ static int vnc_display_connect(VncDisplay *vd,
}
-static int vnc_display_listen_addr(VncDisplay *vd,
- SocketAddress *addr,
- const char *name,
- QIOChannelSocket ***lsock,
- guint **lsock_tag,
- size_t *nlsock,
- Error **errp)
-{
- QIODNSResolver *resolver = qio_dns_resolver_get_instance();
- SocketAddress **rawaddrs = NULL;
- size_t nrawaddrs = 0;
- Error *listenerr = NULL;
- bool listening = false;
- size_t i;
-
- if (qio_dns_resolver_lookup_sync(resolver, addr, &nrawaddrs,
- &rawaddrs, errp) < 0) {
- return -1;
- }
-
- for (i = 0; i < nrawaddrs; i++) {
- QIOChannelSocket *sioc = qio_channel_socket_new();
-
- qio_channel_set_name(QIO_CHANNEL(sioc), name);
- if (qio_channel_socket_listen_sync(
- sioc, rawaddrs[i], listenerr == NULL ? &listenerr : NULL) < 0) {
- object_unref(OBJECT(sioc));
- continue;
- }
- listening = true;
- (*nlsock)++;
- *lsock = g_renew(QIOChannelSocket *, *lsock, *nlsock);
- *lsock_tag = g_renew(guint, *lsock_tag, *nlsock);
-
- (*lsock)[*nlsock - 1] = sioc;
- (*lsock_tag)[*nlsock - 1] = 0;
- }
-
- for (i = 0; i < nrawaddrs; i++) {
- qapi_free_SocketAddress(rawaddrs[i]);
- }
- g_free(rawaddrs);
-
- if (listenerr) {
- if (!listening) {
- error_propagate(errp, listenerr);
- return -1;
- } else {
- error_free(listenerr);
- }
- }
-
- for (i = 0; i < *nlsock; i++) {
- (*lsock_tag)[i] = qio_channel_add_watch(
- QIO_CHANNEL((*lsock)[i]),
- G_IO_IN, vnc_listen_io, vd, NULL);
- }
-
- return 0;
-}
-
-
static int vnc_display_listen(VncDisplay *vd,
SocketAddress **saddr,
size_t nsaddr,
@@ -3886,25 +3792,34 @@ static int vnc_display_listen(VncDisplay *vd,
{
size_t i;
- for (i = 0; i < nsaddr; i++) {
- if (vnc_display_listen_addr(vd, saddr[i],
- "vnc-listen",
- &vd->lsock,
- &vd->lsock_tag,
- &vd->nlsock,
- errp) < 0) {
- return -1;
+ if (nsaddr) {
+ vd->listener = qio_net_listener_new();
+ qio_net_listener_set_name(vd->listener, "vnc-listen");
+ for (i = 0; i < nsaddr; i++) {
+ if (qio_net_listener_open_sync(vd->listener,
+ saddr[i],
+ errp) < 0) {
+ return -1;
+ }
}
+
+ qio_net_listener_set_client_func(vd->listener,
+ vnc_listen_io, vd, NULL);
}
- for (i = 0; i < nwsaddr; i++) {
- if (vnc_display_listen_addr(vd, wsaddr[i],
- "vnc-ws-listen",
- &vd->lwebsock,
- &vd->lwebsock_tag,
- &vd->nlwebsock,
- errp) < 0) {
- return -1;
+
+ if (nwsaddr) {
+ vd->wslistener = qio_net_listener_new();
+ qio_net_listener_set_name(vd->wslistener, "vnc-ws-listen");
+ for (i = 0; i < nwsaddr; i++) {
+ if (qio_net_listener_open_sync(vd->wslistener,
+ wsaddr[i],
+ errp) < 0) {
+ return -1;
+ }
}
+
+ qio_net_listener_set_client_func(vd->wslistener,
+ vnc_listen_io, vd, NULL);
}
return 0;
diff --git a/ui/vnc.h b/ui/vnc.h
index bbda0540a7..23b4dbbe72 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -37,6 +37,7 @@
#include "qemu/buffer.h"
#include "io/channel-socket.h"
#include "io/channel-tls.h"
+#include "io/net-listener.h"
#include <zlib.h>
#include "keymaps.h"
@@ -146,12 +147,8 @@ struct VncDisplay
int num_exclusive;
int connections_limit;
VncSharePolicy share_policy;
- size_t nlsock;
- QIOChannelSocket **lsock;
- guint *lsock_tag;
- size_t nlwebsock;
- QIOChannelSocket **lwebsock;
- guint *lwebsock_tag;
+ QIONetListener *listener;
+ QIONetListener *wslistener;
DisplaySurface *ds;
DisplayChangeListener dcl;
kbd_layout_t *kbd_layout;