mirror of https://github.com/xemu-project/xemu.git
virtio-ccw: use ccw data stream
Replace direct access which implicitly assumes no IDA or MIDA with the new ccw data stream interface which should cope with these transparently in the future. Note that checking the return code for ccw_dstream_* will be done in a follow-on patch. Signed-off-by: Halil Pasic <pasic@linux.vnet.ibm.com> Reviewed-by: Pierre Morel <pmorel@linux.vnet.ibm.com> Reviewed-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com> Message-Id: <20170921180841.24490-4-pasic@linux.vnet.ibm.com> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
This commit is contained in:
parent
0a22eac5aa
commit
f57ba05823
|
@ -289,49 +289,19 @@ static int virtio_ccw_handle_set_vq(SubchDev *sch, CCW1 ccw, bool check_len,
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
if (is_legacy) {
|
if (is_legacy) {
|
||||||
linfo.queue = address_space_ldq_be(&address_space_memory, ccw.cda,
|
ccw_dstream_read(&sch->cds, linfo);
|
||||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
be64_to_cpus(&linfo.queue);
|
||||||
linfo.align = address_space_ldl_be(&address_space_memory,
|
be32_to_cpus(&linfo.align);
|
||||||
ccw.cda + sizeof(linfo.queue),
|
be16_to_cpus(&linfo.index);
|
||||||
MEMTXATTRS_UNSPECIFIED,
|
be16_to_cpus(&linfo.num);
|
||||||
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);
|
ret = virtio_ccw_set_vqs(sch, NULL, &linfo);
|
||||||
} else {
|
} else {
|
||||||
info.desc = address_space_ldq_be(&address_space_memory, ccw.cda,
|
ccw_dstream_read(&sch->cds, info);
|
||||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
be64_to_cpus(&info.desc);
|
||||||
info.index = address_space_lduw_be(&address_space_memory,
|
be16_to_cpus(&info.index);
|
||||||
ccw.cda + sizeof(info.desc)
|
be16_to_cpus(&info.num);
|
||||||
+ sizeof(info.res0),
|
be64_to_cpus(&info.avail);
|
||||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
be64_to_cpus(&info.used);
|
||||||
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);
|
ret = virtio_ccw_set_vqs(sch, &info, NULL);
|
||||||
}
|
}
|
||||||
sch->curr_status.scsw.count = 0;
|
sch->curr_status.scsw.count = 0;
|
||||||
|
@ -344,15 +314,13 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||||
VirtioRevInfo revinfo;
|
VirtioRevInfo revinfo;
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
VirtioFeatDesc features;
|
VirtioFeatDesc features;
|
||||||
void *config;
|
|
||||||
hwaddr indicators;
|
hwaddr indicators;
|
||||||
VqConfigBlock vq_config;
|
VqConfigBlock vq_config;
|
||||||
VirtioCcwDevice *dev = sch->driver_data;
|
VirtioCcwDevice *dev = sch->driver_data;
|
||||||
VirtIODevice *vdev = virtio_ccw_get_vdev(sch);
|
VirtIODevice *vdev = virtio_ccw_get_vdev(sch);
|
||||||
bool check_len;
|
bool check_len;
|
||||||
int len;
|
int len;
|
||||||
hwaddr hw_len;
|
VirtioThinintInfo thinint;
|
||||||
VirtioThinintInfo *thinint;
|
|
||||||
|
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -396,11 +364,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||||
} else {
|
} else {
|
||||||
VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
|
VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
|
||||||
|
|
||||||
features.index = address_space_ldub(&address_space_memory,
|
ccw_dstream_advance(&sch->cds, sizeof(features.features));
|
||||||
ccw.cda
|
ccw_dstream_read(&sch->cds, features.index);
|
||||||
+ sizeof(features.features),
|
|
||||||
MEMTXATTRS_UNSPECIFIED,
|
|
||||||
NULL);
|
|
||||||
if (features.index == 0) {
|
if (features.index == 0) {
|
||||||
if (dev->revision >= 1) {
|
if (dev->revision >= 1) {
|
||||||
/* Don't offer legacy features for modern devices. */
|
/* Don't offer legacy features for modern devices. */
|
||||||
|
@ -419,9 +384,9 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||||
/* Return zeroes if the guest supports more feature bits. */
|
/* Return zeroes if the guest supports more feature bits. */
|
||||||
features.features = 0;
|
features.features = 0;
|
||||||
}
|
}
|
||||||
address_space_stl_le(&address_space_memory, ccw.cda,
|
ccw_dstream_rewind(&sch->cds);
|
||||||
features.features, MEMTXATTRS_UNSPECIFIED,
|
cpu_to_le32s(&features.features);
|
||||||
NULL);
|
ccw_dstream_write(&sch->cds, features.features);
|
||||||
sch->curr_status.scsw.count = ccw.count - sizeof(features);
|
sch->curr_status.scsw.count = ccw.count - sizeof(features);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
@ -440,15 +405,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||||
if (!ccw.cda) {
|
if (!ccw.cda) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
} else {
|
} else {
|
||||||
features.index = address_space_ldub(&address_space_memory,
|
ccw_dstream_read(&sch->cds, features);
|
||||||
ccw.cda
|
le32_to_cpus(&features.features);
|
||||||
+ sizeof(features.features),
|
|
||||||
MEMTXATTRS_UNSPECIFIED,
|
|
||||||
NULL);
|
|
||||||
features.features = address_space_ldl_le(&address_space_memory,
|
|
||||||
ccw.cda,
|
|
||||||
MEMTXATTRS_UNSPECIFIED,
|
|
||||||
NULL);
|
|
||||||
if (features.index == 0) {
|
if (features.index == 0) {
|
||||||
virtio_set_features(vdev,
|
virtio_set_features(vdev,
|
||||||
(vdev->guest_features & 0xffffffff00000000ULL) |
|
(vdev->guest_features & 0xffffffff00000000ULL) |
|
||||||
|
@ -489,7 +447,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
} else {
|
} else {
|
||||||
virtio_bus_get_vdev_config(&dev->bus, vdev->config);
|
virtio_bus_get_vdev_config(&dev->bus, vdev->config);
|
||||||
cpu_physical_memory_write(ccw.cda, vdev->config, len);
|
ccw_dstream_write_buf(&sch->cds, vdev->config, len);
|
||||||
sch->curr_status.scsw.count = ccw.count - len;
|
sch->curr_status.scsw.count = ccw.count - len;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
@ -502,20 +460,13 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
len = MIN(ccw.count, vdev->config_len);
|
len = MIN(ccw.count, vdev->config_len);
|
||||||
hw_len = len;
|
|
||||||
if (!ccw.cda) {
|
if (!ccw.cda) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
} else {
|
} else {
|
||||||
config = cpu_physical_memory_map(ccw.cda, &hw_len, 0);
|
ret = ccw_dstream_read_buf(&sch->cds, vdev->config, len);
|
||||||
if (!config) {
|
if (!ret) {
|
||||||
ret = -EFAULT;
|
|
||||||
} else {
|
|
||||||
len = hw_len;
|
|
||||||
memcpy(vdev->config, config, len);
|
|
||||||
cpu_physical_memory_unmap(config, hw_len, 0, hw_len);
|
|
||||||
virtio_bus_set_vdev_config(&dev->bus, vdev->config);
|
virtio_bus_set_vdev_config(&dev->bus, vdev->config);
|
||||||
sch->curr_status.scsw.count = ccw.count - len;
|
sch->curr_status.scsw.count = ccw.count - len;
|
||||||
ret = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -553,8 +504,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||||
if (!ccw.cda) {
|
if (!ccw.cda) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
} else {
|
} else {
|
||||||
status = address_space_ldub(&address_space_memory, ccw.cda,
|
ccw_dstream_read(&sch->cds, status);
|
||||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
|
if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
|
||||||
virtio_ccw_stop_ioeventfd(dev);
|
virtio_ccw_stop_ioeventfd(dev);
|
||||||
}
|
}
|
||||||
|
@ -597,8 +547,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||||
if (!ccw.cda) {
|
if (!ccw.cda) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
} else {
|
} else {
|
||||||
indicators = address_space_ldq_be(&address_space_memory, ccw.cda,
|
ccw_dstream_read(&sch->cds, indicators);
|
||||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
be64_to_cpus(&indicators);
|
||||||
dev->indicators = get_indicator(indicators, sizeof(uint64_t));
|
dev->indicators = get_indicator(indicators, sizeof(uint64_t));
|
||||||
sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
|
sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
@ -618,8 +568,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||||
if (!ccw.cda) {
|
if (!ccw.cda) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
} else {
|
} else {
|
||||||
indicators = address_space_ldq_be(&address_space_memory, ccw.cda,
|
ccw_dstream_read(&sch->cds, indicators);
|
||||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
be64_to_cpus(&indicators);
|
||||||
dev->indicators2 = get_indicator(indicators, sizeof(uint64_t));
|
dev->indicators2 = get_indicator(indicators, sizeof(uint64_t));
|
||||||
sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
|
sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
@ -639,67 +589,58 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||||
if (!ccw.cda) {
|
if (!ccw.cda) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
} else {
|
} else {
|
||||||
vq_config.index = address_space_lduw_be(&address_space_memory,
|
ccw_dstream_read(&sch->cds, vq_config.index);
|
||||||
ccw.cda,
|
be16_to_cpus(&vq_config.index);
|
||||||
MEMTXATTRS_UNSPECIFIED,
|
|
||||||
NULL);
|
|
||||||
if (vq_config.index >= VIRTIO_QUEUE_MAX) {
|
if (vq_config.index >= VIRTIO_QUEUE_MAX) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
vq_config.num_max = virtio_queue_get_num(vdev,
|
vq_config.num_max = virtio_queue_get_num(vdev,
|
||||||
vq_config.index);
|
vq_config.index);
|
||||||
address_space_stw_be(&address_space_memory,
|
cpu_to_be16s(&vq_config.num_max);
|
||||||
ccw.cda + sizeof(vq_config.index),
|
ccw_dstream_write(&sch->cds, vq_config.num_max);
|
||||||
vq_config.num_max,
|
|
||||||
MEMTXATTRS_UNSPECIFIED,
|
|
||||||
NULL);
|
|
||||||
sch->curr_status.scsw.count = ccw.count - sizeof(vq_config);
|
sch->curr_status.scsw.count = ccw.count - sizeof(vq_config);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CCW_CMD_SET_IND_ADAPTER:
|
case CCW_CMD_SET_IND_ADAPTER:
|
||||||
if (check_len) {
|
if (check_len) {
|
||||||
if (ccw.count != sizeof(*thinint)) {
|
if (ccw.count != sizeof(thinint)) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (ccw.count < sizeof(*thinint)) {
|
} else if (ccw.count < sizeof(thinint)) {
|
||||||
/* Can't execute command. */
|
/* Can't execute command. */
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
len = sizeof(*thinint);
|
|
||||||
hw_len = len;
|
|
||||||
if (!ccw.cda) {
|
if (!ccw.cda) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
} else if (dev->indicators && !sch->thinint_active) {
|
} else if (dev->indicators && !sch->thinint_active) {
|
||||||
/* Trigger a command reject. */
|
/* Trigger a command reject. */
|
||||||
ret = -ENOSYS;
|
ret = -ENOSYS;
|
||||||
} else {
|
} else {
|
||||||
thinint = cpu_physical_memory_map(ccw.cda, &hw_len, 0);
|
if (ccw_dstream_read(&sch->cds, thinint)) {
|
||||||
if (!thinint) {
|
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
} else {
|
} else {
|
||||||
uint64_t ind_bit = ldq_be_p(&thinint->ind_bit);
|
be64_to_cpus(&thinint.ind_bit);
|
||||||
|
be64_to_cpus(&thinint.summary_indicator);
|
||||||
|
be64_to_cpus(&thinint.device_indicator);
|
||||||
|
|
||||||
len = hw_len;
|
|
||||||
dev->summary_indicator =
|
dev->summary_indicator =
|
||||||
get_indicator(ldq_be_p(&thinint->summary_indicator),
|
get_indicator(thinint.summary_indicator, sizeof(uint8_t));
|
||||||
sizeof(uint8_t));
|
|
||||||
dev->indicators =
|
dev->indicators =
|
||||||
get_indicator(ldq_be_p(&thinint->device_indicator),
|
get_indicator(thinint.device_indicator,
|
||||||
ind_bit / 8 + 1);
|
thinint.ind_bit / 8 + 1);
|
||||||
dev->thinint_isc = thinint->isc;
|
dev->thinint_isc = thinint.isc;
|
||||||
dev->routes.adapter.ind_offset = ind_bit;
|
dev->routes.adapter.ind_offset = thinint.ind_bit;
|
||||||
dev->routes.adapter.summary_offset = 7;
|
dev->routes.adapter.summary_offset = 7;
|
||||||
cpu_physical_memory_unmap(thinint, hw_len, 0, hw_len);
|
|
||||||
dev->routes.adapter.adapter_id = css_get_adapter_id(
|
dev->routes.adapter.adapter_id = css_get_adapter_id(
|
||||||
CSS_IO_ADAPTER_VIRTIO,
|
CSS_IO_ADAPTER_VIRTIO,
|
||||||
dev->thinint_isc);
|
dev->thinint_isc);
|
||||||
sch->thinint_active = ((dev->indicators != NULL) &&
|
sch->thinint_active = ((dev->indicators != NULL) &&
|
||||||
(dev->summary_indicator != NULL));
|
(dev->summary_indicator != NULL));
|
||||||
sch->curr_status.scsw.count = ccw.count - len;
|
sch->curr_status.scsw.count = ccw.count - sizeof(thinint);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -714,13 +655,9 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
revinfo.revision =
|
ccw_dstream_read_buf(&sch->cds, &revinfo, 4);
|
||||||
address_space_lduw_be(&address_space_memory, ccw.cda,
|
be16_to_cpus(&revinfo.revision);
|
||||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
be16_to_cpus(&revinfo.length);
|
||||||
revinfo.length =
|
|
||||||
address_space_lduw_be(&address_space_memory,
|
|
||||||
ccw.cda + sizeof(revinfo.revision),
|
|
||||||
MEMTXATTRS_UNSPECIFIED, NULL);
|
|
||||||
if (ccw.count < len + revinfo.length ||
|
if (ccw.count < len + revinfo.length ||
|
||||||
(check_len && ccw.count > len + revinfo.length)) {
|
(check_len && ccw.count > len + revinfo.length)) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
|
Loading…
Reference in New Issue