diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libvirtio/virtio-blk.c | 2 | ||||
-rw-r--r-- | lib/libvirtio/virtio.c | 42 | ||||
-rw-r--r-- | lib/libvirtio/virtio.h | 4 |
3 files changed, 41 insertions, 7 deletions
diff --git a/lib/libvirtio/virtio-blk.c b/lib/libvirtio/virtio-blk.c index 26c9685..7ced1c7 100644 --- a/lib/libvirtio/virtio-blk.c +++ b/lib/libvirtio/virtio-blk.c @@ -57,7 +57,7 @@ virtioblk_init(struct virtio_device *dev) status |= VIRTIO_STAT_DRIVER_OK; virtio_set_status(dev, status); - virtio_get_host_features(dev, &features); + features = virtio_get_host_features(dev); if (features & VIRTIO_BLK_F_BLK_SIZE) { blk_size = virtio_get_config(dev, offset_of(struct virtio_blk_cfg, blk_size), diff --git a/lib/libvirtio/virtio.c b/lib/libvirtio/virtio.c index 24d3bb8..ba7aced 100644 --- a/lib/libvirtio/virtio.c +++ b/lib/libvirtio/virtio.c @@ -301,19 +301,53 @@ void virtio_set_status(struct virtio_device *dev, int status) /** * Set guest feature bits */ -void virtio_set_guest_features(struct virtio_device *dev, int features) +void virtio_set_guest_features(struct virtio_device *dev, uint64_t features) { - ci_write_32(dev->base+VIRTIOHDR_GUEST_FEATURES, bswap_32(features)); + if (dev->is_modern) { + uint32_t f1 = (features >> 32) & 0xFFFFFFFF; + uint32_t f0 = features & 0xFFFFFFFF; + void *addr = dev->common.addr; + + ci_write_32(addr + offset_of(struct virtio_dev_common, drv_features_sel), + cpu_to_le32(1)); + ci_write_32(addr + offset_of(struct virtio_dev_common, drv_features), + cpu_to_le32(f1)); + + ci_write_32(addr + offset_of(struct virtio_dev_common, drv_features_sel), + cpu_to_le32(0)); + ci_write_32(addr + offset_of(struct virtio_dev_common, drv_features), + cpu_to_le32(f0)); + } else { + ci_write_32(dev->base+VIRTIOHDR_GUEST_FEATURES, cpu_to_le32(features)); + } } /** * Get host feature bits */ -void virtio_get_host_features(struct virtio_device *dev, int *features) +uint64_t virtio_get_host_features(struct virtio_device *dev) { - *features = bswap_32(ci_read_32(dev->base+VIRTIOHDR_DEVICE_FEATURES)); + uint64_t features = 0; + if (dev->is_modern) { + uint32_t f0 = 0, f1 = 0; + void *addr = dev->common.addr; + + ci_write_32(addr + offset_of(struct virtio_dev_common, dev_features_sel), + cpu_to_le32(1)); + f1 = ci_read_32(addr + + offset_of(struct virtio_dev_common, dev_features)); + ci_write_32(addr + offset_of(struct virtio_dev_common, dev_features_sel), + cpu_to_le32(0)); + f0 = ci_read_32(addr + + offset_of(struct virtio_dev_common, dev_features)); + + features = ((uint64_t)le32_to_cpu(f1) << 32) | le32_to_cpu(f0); + } else { + features = le32_to_cpu(ci_read_32(dev->base+VIRTIOHDR_DEVICE_FEATURES)); + } + return features; } diff --git a/lib/libvirtio/virtio.h b/lib/libvirtio/virtio.h index e2543a1..bf8ea28 100644 --- a/lib/libvirtio/virtio.h +++ b/lib/libvirtio/virtio.h @@ -117,8 +117,8 @@ extern void virtio_reset_device(struct virtio_device *dev); extern void virtio_queue_notify(struct virtio_device *dev, int queue); extern void virtio_set_status(struct virtio_device *dev, int status); extern void virtio_set_qaddr(struct virtio_device *dev, int queue, unsigned long qaddr); -extern void virtio_set_guest_features(struct virtio_device *dev, int features); -extern void virtio_get_host_features(struct virtio_device *dev, int *features); +extern void virtio_set_guest_features(struct virtio_device *dev, uint64_t features); +extern uint64_t virtio_get_host_features(struct virtio_device *dev); extern uint64_t virtio_get_config(struct virtio_device *dev, int offset, int size); extern int __virtio_read_config(struct virtio_device *dev, void *dst, int offset, int len); |