diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2018-03-01 18:46:41 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-03-01 18:46:41 +0000 |
commit | 427cbc7e4136a061628cb4315cc8182ea36d772f (patch) | |
tree | ccbdf5985d6e2b20f6e7310a8b776824362fc9cf /hw | |
parent | 0dc8ae5e8e693737dfe65ba02d0c6eccb58a9c67 (diff) | |
parent | 0a9b9be9eb40055d2d1bb5b8fc4d4faefecb22c3 (diff) |
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
virtio,vhost,pci,pc: features, fixes and cleanups
- documentation updates
- vhost fixes
- new crypto vhost device
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
# gpg: Signature made Thu 01 Mar 2018 16:27:25 GMT
# gpg: using RSA key 281F0DB8D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg: aka "Michael S. Tsirkin <mst@redhat.com>"
# Primary key fingerprint: 0270 606B 6F3C DF3D 0B17 0970 C350 3912 AFBE 8E67
# Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA 8A0D 281F 0DB8 D28D 5469
* remotes/mst/tags/for_upstream:
cryptodev-vhost-user: set the key length
cryptodev-vhost-user: add crypto session handler
cryptodev: add vhost support
cryptodev: add vhost-user as a new cryptodev backend
docs/vmcoreinfo: detail unsupported host format behaviour
vhost: fix incorrect check in vhost_verify_ring_mappings
vhost: avoid to start/stop virtqueue which is not ready
vhost: fix memslot limit check
docs: pcie: Spell out machine type needs for PCIe features
docs: document virtio-balloon stats
intel-iommu: Accept 64-bit writes to FEADDR
virtio-pci: trivial fixes in error message
vhost-user: fix memory leak
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/i386/intel_iommu.c | 11 | ||||
-rw-r--r-- | hw/virtio/vhost-user.c | 104 | ||||
-rw-r--r-- | hw/virtio/vhost.c | 41 | ||||
-rw-r--r-- | hw/virtio/virtio-crypto.c | 70 | ||||
-rw-r--r-- | hw/virtio/virtio-pci.c | 2 |
5 files changed, 215 insertions, 13 deletions
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 2e841cde27..fb31de9416 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -2129,8 +2129,15 @@ static void vtd_mem_write(void *opaque, hwaddr addr, /* Fault Event Address Register, 32-bit */ case DMAR_FEADDR_REG: - assert(size == 4); - vtd_set_long(s, addr, val); + if (size == 4) { + vtd_set_long(s, addr, val); + } else { + /* + * While the register is 32-bit only, some guests (Xen...) write to + * it with 64-bit. + */ + vtd_set_quad(s, addr, val); + } break; /* Fault Event Upper Address Register, 32-bit */ diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index 6eb97980ad..41ff5cff41 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -17,6 +17,7 @@ #include "sysemu/kvm.h" #include "qemu/error-report.h" #include "qemu/sockets.h" +#include "sysemu/cryptodev.h" #include <sys/ioctl.h> #include <sys/socket.h> @@ -39,6 +40,7 @@ enum VhostUserProtocolFeature { VHOST_USER_PROTOCOL_F_NET_MTU = 4, VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5, VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6, + VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7, VHOST_USER_PROTOCOL_F_MAX }; @@ -72,6 +74,8 @@ typedef enum VhostUserRequest { VHOST_USER_SET_VRING_ENDIAN = 23, VHOST_USER_GET_CONFIG = 24, VHOST_USER_SET_CONFIG = 25, + VHOST_USER_CREATE_CRYPTO_SESSION = 26, + VHOST_USER_CLOSE_CRYPTO_SESSION = 27, VHOST_USER_MAX } VhostUserRequest; @@ -107,6 +111,17 @@ typedef struct VhostUserConfig { uint8_t region[VHOST_USER_MAX_CONFIG_SIZE]; } VhostUserConfig; +#define VHOST_CRYPTO_SYM_HMAC_MAX_KEY_LEN 512 +#define VHOST_CRYPTO_SYM_CIPHER_MAX_KEY_LEN 64 + +typedef struct VhostUserCryptoSession { + /* session id for success, -1 on errors */ + int64_t session_id; + CryptoDevBackendSymSessionInfo session_setup_data; + uint8_t key[VHOST_CRYPTO_SYM_CIPHER_MAX_KEY_LEN]; + uint8_t auth_key[VHOST_CRYPTO_SYM_HMAC_MAX_KEY_LEN]; +} VhostUserCryptoSession; + static VhostUserConfig c __attribute__ ((unused)); #define VHOST_USER_CONFIG_HDR_SIZE (sizeof(c.offset) \ + sizeof(c.size) \ @@ -132,6 +147,7 @@ typedef union { VhostUserLog log; struct vhost_iotlb_msg iotlb; VhostUserConfig config; + VhostUserCryptoSession session; } VhostUserPayload; typedef struct VhostUserMsg { @@ -1054,6 +1070,92 @@ static int vhost_user_set_config(struct vhost_dev *dev, const uint8_t *data, return 0; } +static int vhost_user_crypto_create_session(struct vhost_dev *dev, + void *session_info, + uint64_t *session_id) +{ + bool crypto_session = virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_CRYPTO_SESSION); + CryptoDevBackendSymSessionInfo *sess_info = session_info; + VhostUserMsg msg = { + .hdr.request = VHOST_USER_CREATE_CRYPTO_SESSION, + .hdr.flags = VHOST_USER_VERSION, + .hdr.size = sizeof(msg.payload.session), + }; + + assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER); + + if (!crypto_session) { + error_report("vhost-user trying to send unhandled ioctl"); + return -1; + } + + memcpy(&msg.payload.session.session_setup_data, sess_info, + sizeof(CryptoDevBackendSymSessionInfo)); + if (sess_info->key_len) { + memcpy(&msg.payload.session.key, sess_info->cipher_key, + sess_info->key_len); + } + if (sess_info->auth_key_len > 0) { + memcpy(&msg.payload.session.auth_key, sess_info->auth_key, + sess_info->auth_key_len); + } + if (vhost_user_write(dev, &msg, NULL, 0) < 0) { + error_report("vhost_user_write() return -1, create session failed"); + return -1; + } + + if (vhost_user_read(dev, &msg) < 0) { + error_report("vhost_user_read() return -1, create session failed"); + return -1; + } + + if (msg.hdr.request != VHOST_USER_CREATE_CRYPTO_SESSION) { + error_report("Received unexpected msg type. Expected %d received %d", + VHOST_USER_CREATE_CRYPTO_SESSION, msg.hdr.request); + return -1; + } + + if (msg.hdr.size != sizeof(msg.payload.session)) { + error_report("Received bad msg size."); + return -1; + } + + if (msg.payload.session.session_id < 0) { + error_report("Bad session id: %" PRId64 "", + msg.payload.session.session_id); + return -1; + } + *session_id = msg.payload.session.session_id; + + return 0; +} + +static int +vhost_user_crypto_close_session(struct vhost_dev *dev, uint64_t session_id) +{ + bool crypto_session = virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_CRYPTO_SESSION); + VhostUserMsg msg = { + .hdr.request = VHOST_USER_CLOSE_CRYPTO_SESSION, + .hdr.flags = VHOST_USER_VERSION, + .hdr.size = sizeof(msg.payload.u64), + }; + msg.payload.u64 = session_id; + + if (!crypto_session) { + error_report("vhost-user trying to send unhandled ioctl"); + return -1; + } + + if (vhost_user_write(dev, &msg, NULL, 0) < 0) { + error_report("vhost_user_write() return -1, close session failed"); + return -1; + } + + return 0; +} + const VhostOps user_ops = { .backend_type = VHOST_BACKEND_TYPE_USER, .vhost_backend_init = vhost_user_init, @@ -1082,4 +1184,6 @@ const VhostOps user_ops = { .vhost_send_device_iotlb_msg = vhost_user_send_device_iotlb_msg, .vhost_get_config = vhost_user_get_config, .vhost_set_config = vhost_user_set_config, + .vhost_crypto_create_session = vhost_user_crypto_create_session, + .vhost_crypto_close_session = vhost_user_crypto_close_session, }; diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 4a44e6e6bf..d8d0ef92e1 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -345,6 +345,10 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev, for (i = 0; i < dev->nvqs; ++i) { struct vhost_virtqueue *vq = dev->vqs + i; + if (vq->desc_phys == 0) { + continue; + } + j = 0; r = vhost_verify_ring_part_mapping( vq->desc, vq->desc_phys, vq->desc_size, @@ -355,7 +359,7 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev, j++; r = vhost_verify_ring_part_mapping( - vq->desc, vq->desc_phys, vq->desc_size, + vq->avail, vq->avail_phys, vq->avail_size, reg_hva, reg_gpa, reg_size); if (r) { break; @@ -363,7 +367,7 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev, j++; r = vhost_verify_ring_part_mapping( - vq->desc, vq->desc_phys, vq->desc_size, + vq->used, vq->used_phys, vq->used_size, reg_hva, reg_gpa, reg_size); if (r) { break; @@ -881,6 +885,11 @@ static int vhost_virtqueue_start(struct vhost_dev *dev, }; struct VirtQueue *vvq = virtio_get_queue(vdev, idx); + a = virtio_queue_get_desc_addr(vdev, idx); + if (a == 0) { + /* Queue might not be ready for start */ + return 0; + } vq->num = state.num = virtio_queue_get_num(vdev, idx); r = dev->vhost_ops->vhost_set_vring_num(dev, &state); @@ -906,7 +915,7 @@ static int vhost_virtqueue_start(struct vhost_dev *dev, } vq->desc_size = s = l = virtio_queue_get_desc_size(vdev, idx); - vq->desc_phys = a = virtio_queue_get_desc_addr(vdev, idx); + vq->desc_phys = a; vq->desc = vhost_memory_map(dev, a, &l, 0); if (!vq->desc || l != s) { r = -ENOMEM; @@ -989,6 +998,13 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev, .index = vhost_vq_index, }; int r; + int a; + + a = virtio_queue_get_desc_addr(vdev, idx); + if (a == 0) { + /* Don't stop the virtqueue which might have not been started */ + return; + } r = dev->vhost_ops->vhost_get_vring_base(dev, &state); if (r < 0) { @@ -1106,13 +1122,6 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, goto fail; } - if (used_memslots > hdev->vhost_ops->vhost_backend_memslots_limit(hdev)) { - error_report("vhost backend memory slots limit is less" - " than current number of present memory slots"); - r = -1; - goto fail; - } - r = hdev->vhost_ops->vhost_set_owner(hdev); if (r < 0) { VHOST_OPS_DEBUG("vhost_set_owner failed"); @@ -1192,6 +1201,18 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, hdev->started = false; memory_listener_register(&hdev->memory_listener, &address_space_memory); QLIST_INSERT_HEAD(&vhost_devices, hdev, entry); + + if (used_memslots > hdev->vhost_ops->vhost_backend_memslots_limit(hdev)) { + error_report("vhost backend memory slots limit is less" + " than current number of present memory slots"); + r = -1; + if (busyloop_timeout) { + goto fail_busyloop; + } else { + goto fail; + } + } + return 0; fail_busyloop: diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c index 19c82e0432..9a9fa495d2 100644 --- a/hw/virtio/virtio-crypto.c +++ b/hw/virtio/virtio-crypto.c @@ -20,6 +20,7 @@ #include "hw/virtio/virtio-crypto.h" #include "hw/virtio/virtio-access.h" #include "standard-headers/linux/virtio_ids.h" +#include "sysemu/cryptodev-vhost.h" #define VIRTIO_CRYPTO_VM_VERSION 1 @@ -880,6 +881,72 @@ static void virtio_crypto_get_config(VirtIODevice *vdev, uint8_t *config) memcpy(config, &crypto_cfg, c->config_size); } +static bool virtio_crypto_started(VirtIOCrypto *c, uint8_t status) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(c); + return (status & VIRTIO_CONFIG_S_DRIVER_OK) && + (c->status & VIRTIO_CRYPTO_S_HW_READY) && vdev->vm_running; +} + +static void virtio_crypto_vhost_status(VirtIOCrypto *c, uint8_t status) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(c); + int queues = c->multiqueue ? c->max_queues : 1; + CryptoDevBackend *b = c->cryptodev; + CryptoDevBackendClient *cc = b->conf.peers.ccs[0]; + + if (!cryptodev_get_vhost(cc, b, 0)) { + return; + } + + if ((virtio_crypto_started(c, status)) == !!c->vhost_started) { + return; + } + + if (!c->vhost_started) { + int r; + + c->vhost_started = 1; + r = cryptodev_vhost_start(vdev, queues); + if (r < 0) { + error_report("unable to start vhost crypto: %d: " + "falling back on userspace virtio", -r); + c->vhost_started = 0; + } + } else { + cryptodev_vhost_stop(vdev, queues); + c->vhost_started = 0; + } +} + +static void virtio_crypto_set_status(VirtIODevice *vdev, uint8_t status) +{ + VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev); + + virtio_crypto_vhost_status(vcrypto, status); +} + +static void virtio_crypto_guest_notifier_mask(VirtIODevice *vdev, int idx, + bool mask) +{ + VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev); + int queue = virtio_crypto_vq2q(idx); + + assert(vcrypto->vhost_started); + + cryptodev_vhost_virtqueue_mask(vdev, queue, idx, mask); +} + +static bool virtio_crypto_guest_notifier_pending(VirtIODevice *vdev, int idx) +{ + VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev); + int queue = virtio_crypto_vq2q(idx); + + assert(vcrypto->vhost_started); + + return cryptodev_vhost_virtqueue_pending(vdev, queue, idx); +} + static void virtio_crypto_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -893,6 +960,9 @@ static void virtio_crypto_class_init(ObjectClass *klass, void *data) vdc->get_config = virtio_crypto_get_config; vdc->get_features = virtio_crypto_get_features; vdc->reset = virtio_crypto_reset; + vdc->set_status = virtio_crypto_set_status; + vdc->guest_notifier_mask = virtio_crypto_guest_notifier_mask; + vdc->guest_notifier_pending = virtio_crypto_guest_notifier_pending; } static void virtio_crypto_instance_init(Object *obj) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index b55dfcf05c..1e8ab7bbc5 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1585,7 +1585,7 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) if (legacy) { if (virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM)) { error_setg(errp, "VIRTIO_F_IOMMU_PLATFORM was supported by" - "neither legacy nor transitional device."); + " neither legacy nor transitional device"); return ; } /* |