mirror of https://github.com/xqemu/xqemu.git
s390x/virtio-ccw: support virtio-1 set_vq format
Support the new CCW_CMD_SET_VQ format for virtio-1 devices. While we're at it, refactor the code a bit and enforce big endian fields (which had always been required, even for legacy). Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
c42767f2bb
commit
0db87e0d17
|
@ -238,11 +238,20 @@ VirtualCssBus *virtual_css_bus_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Communication blocks used by several channel commands. */
|
/* Communication blocks used by several channel commands. */
|
||||||
typedef struct VqInfoBlock {
|
typedef struct VqInfoBlockLegacy {
|
||||||
uint64_t queue;
|
uint64_t queue;
|
||||||
uint32_t align;
|
uint32_t align;
|
||||||
uint16_t index;
|
uint16_t index;
|
||||||
uint16_t num;
|
uint16_t num;
|
||||||
|
} QEMU_PACKED VqInfoBlockLegacy;
|
||||||
|
|
||||||
|
typedef struct VqInfoBlock {
|
||||||
|
uint64_t desc;
|
||||||
|
uint32_t res0;
|
||||||
|
uint16_t index;
|
||||||
|
uint16_t num;
|
||||||
|
uint64_t avail;
|
||||||
|
uint64_t used;
|
||||||
} QEMU_PACKED VqInfoBlock;
|
} QEMU_PACKED VqInfoBlock;
|
||||||
|
|
||||||
typedef struct VqConfigBlock {
|
typedef struct VqConfigBlock {
|
||||||
|
@ -269,17 +278,20 @@ typedef struct VirtioRevInfo {
|
||||||
} QEMU_PACKED VirtioRevInfo;
|
} QEMU_PACKED VirtioRevInfo;
|
||||||
|
|
||||||
/* Specify where the virtqueues for the subchannel are in guest memory. */
|
/* Specify where the virtqueues for the subchannel are in guest memory. */
|
||||||
static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align,
|
static int virtio_ccw_set_vqs(SubchDev *sch, VqInfoBlock *info,
|
||||||
uint16_t index, uint16_t num)
|
VqInfoBlockLegacy *linfo)
|
||||||
{
|
{
|
||||||
VirtIODevice *vdev = virtio_ccw_get_vdev(sch);
|
VirtIODevice *vdev = virtio_ccw_get_vdev(sch);
|
||||||
|
uint16_t index = info ? info->index : linfo->index;
|
||||||
|
uint16_t num = info ? info->num : linfo->num;
|
||||||
|
uint64_t desc = info ? info->desc : linfo->queue;
|
||||||
|
|
||||||
if (index >= VIRTIO_CCW_QUEUE_MAX) {
|
if (index >= VIRTIO_CCW_QUEUE_MAX) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Current code in virtio.c relies on 4K alignment. */
|
/* Current code in virtio.c relies on 4K alignment. */
|
||||||
if (addr && (align != 4096)) {
|
if (linfo && desc && (linfo->align != 4096)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,8 +299,12 @@ static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtio_queue_set_addr(vdev, index, addr);
|
if (info) {
|
||||||
if (!addr) {
|
virtio_queue_set_rings(vdev, index, desc, info->avail, info->used);
|
||||||
|
} else {
|
||||||
|
virtio_queue_set_addr(vdev, index, desc);
|
||||||
|
}
|
||||||
|
if (!desc) {
|
||||||
virtio_queue_set_vector(vdev, index, VIRTIO_NO_VECTOR);
|
virtio_queue_set_vector(vdev, index, VIRTIO_NO_VECTOR);
|
||||||
} else {
|
} else {
|
||||||
/* Fail if we don't have a big enough queue. */
|
/* Fail if we don't have a big enough queue. */
|
||||||
|
@ -322,10 +338,78 @@ static void virtio_ccw_reset_virtio(VirtioCcwDevice *dev, VirtIODevice *vdev)
|
||||||
dev->sch->thinint_active = false;
|
dev->sch->thinint_active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
static int virtio_ccw_handle_set_vq(SubchDev *sch, CCW1 ccw, bool check_len,
|
||||||
|
bool is_legacy)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
VqInfoBlock info;
|
VqInfoBlock info;
|
||||||
|
VqInfoBlockLegacy linfo;
|
||||||
|
size_t info_len = is_legacy ? sizeof(linfo) : sizeof(info);
|
||||||
|
|
||||||
|
if (check_len) {
|
||||||
|
if (ccw.count != info_len) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
} else if (ccw.count < info_len) {
|
||||||
|
/* Can't execute command. */
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (!ccw.cda) {
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
if (is_legacy) {
|
||||||
|
linfo.queue = address_space_ldq_be(&address_space_memory, ccw.cda,
|
||||||
|
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||||
|
linfo.align = address_space_ldl_be(&address_space_memory,
|
||||||
|
ccw.cda + sizeof(linfo.queue),
|
||||||
|
MEMTXATTRS_UNSPECIFIED,
|
||||||
|
NULL);
|
||||||
|
linfo.index = address_space_lduw_be(&address_space_memory,
|
||||||
|
ccw.cda + sizeof(linfo.queue)
|
||||||
|
+ sizeof(linfo.align),
|
||||||
|
MEMTXATTRS_UNSPECIFIED,
|
||||||
|
NULL);
|
||||||
|
linfo.num = address_space_lduw_be(&address_space_memory,
|
||||||
|
ccw.cda + sizeof(linfo.queue)
|
||||||
|
+ sizeof(linfo.align)
|
||||||
|
+ sizeof(linfo.index),
|
||||||
|
MEMTXATTRS_UNSPECIFIED,
|
||||||
|
NULL);
|
||||||
|
ret = virtio_ccw_set_vqs(sch, NULL, &linfo);
|
||||||
|
} else {
|
||||||
|
info.desc = address_space_ldq_be(&address_space_memory, ccw.cda,
|
||||||
|
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||||
|
info.index = address_space_lduw_be(&address_space_memory,
|
||||||
|
ccw.cda + sizeof(info.desc)
|
||||||
|
+ sizeof(info.res0),
|
||||||
|
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||||
|
info.num = address_space_lduw_be(&address_space_memory,
|
||||||
|
ccw.cda + sizeof(info.desc)
|
||||||
|
+ sizeof(info.res0)
|
||||||
|
+ sizeof(info.index),
|
||||||
|
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||||
|
info.avail = address_space_ldq_be(&address_space_memory,
|
||||||
|
ccw.cda + sizeof(info.desc)
|
||||||
|
+ sizeof(info.res0)
|
||||||
|
+ sizeof(info.index)
|
||||||
|
+ sizeof(info.num),
|
||||||
|
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||||
|
info.used = address_space_ldq_be(&address_space_memory,
|
||||||
|
ccw.cda + sizeof(info.desc)
|
||||||
|
+ sizeof(info.res0)
|
||||||
|
+ sizeof(info.index)
|
||||||
|
+ sizeof(info.num)
|
||||||
|
+ sizeof(info.avail),
|
||||||
|
MEMTXATTRS_UNSPECIFIED, NULL);
|
||||||
|
ret = virtio_ccw_set_vqs(sch, &info, NULL);
|
||||||
|
}
|
||||||
|
sch->curr_status.scsw.count = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
VirtioRevInfo revinfo;
|
VirtioRevInfo revinfo;
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
VirtioFeatDesc features;
|
VirtioFeatDesc features;
|
||||||
|
@ -350,40 +434,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||||
/* Look at the command. */
|
/* Look at the command. */
|
||||||
switch (ccw.cmd_code) {
|
switch (ccw.cmd_code) {
|
||||||
case CCW_CMD_SET_VQ:
|
case CCW_CMD_SET_VQ:
|
||||||
if (check_len) {
|
ret = virtio_ccw_handle_set_vq(sch, ccw, check_len, dev->revision < 1);
|
||||||
if (ccw.count != sizeof(info)) {
|
|
||||||
ret = -EINVAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (ccw.count < sizeof(info)) {
|
|
||||||
/* Can't execute command. */
|
|
||||||
ret = -EINVAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!ccw.cda) {
|
|
||||||
ret = -EFAULT;
|
|
||||||
} else {
|
|
||||||
info.queue = address_space_ldq(&address_space_memory, ccw.cda,
|
|
||||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
info.align = address_space_ldl(&address_space_memory,
|
|
||||||
ccw.cda + sizeof(info.queue),
|
|
||||||
MEMTXATTRS_UNSPECIFIED,
|
|
||||||
NULL);
|
|
||||||
info.index = address_space_lduw(&address_space_memory,
|
|
||||||
ccw.cda + sizeof(info.queue)
|
|
||||||
+ sizeof(info.align),
|
|
||||||
MEMTXATTRS_UNSPECIFIED,
|
|
||||||
NULL);
|
|
||||||
info.num = address_space_lduw(&address_space_memory,
|
|
||||||
ccw.cda + sizeof(info.queue)
|
|
||||||
+ sizeof(info.align)
|
|
||||||
+ sizeof(info.index),
|
|
||||||
MEMTXATTRS_UNSPECIFIED,
|
|
||||||
NULL);
|
|
||||||
ret = virtio_ccw_set_vqs(sch, info.queue, info.align, info.index,
|
|
||||||
info.num);
|
|
||||||
sch->curr_status.scsw.count = 0;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case CCW_CMD_VDEV_RESET:
|
case CCW_CMD_VDEV_RESET:
|
||||||
virtio_ccw_reset_virtio(dev, vdev);
|
virtio_ccw_reset_virtio(dev, vdev);
|
||||||
|
|
Loading…
Reference in New Issue