diff options
104 files changed, 807 insertions, 166 deletions
diff --git a/arch_init.c b/arch_init.c index 9597218..f4f3f61 100644 --- a/arch_init.c +++ b/arch_init.c @@ -52,14 +52,14 @@ int graphic_depth = 32; #define QEMU_ARCH QEMU_ARCH_ARM #elif defined(TARGET_CRIS) #define QEMU_ARCH QEMU_ARCH_CRIS -#elif defined(TARGET_I386) -#define QEMU_ARCH QEMU_ARCH_I386 #elif defined(TARGET_HPPA) #define QEMU_ARCH QEMU_ARCH_HPPA -#elif defined(TARGET_M68K) -#define QEMU_ARCH QEMU_ARCH_M68K +#elif defined(TARGET_I386) +#define QEMU_ARCH QEMU_ARCH_I386 #elif defined(TARGET_LM32) #define QEMU_ARCH QEMU_ARCH_LM32 +#elif defined(TARGET_M68K) +#define QEMU_ARCH QEMU_ARCH_M68K #elif defined(TARGET_MICROBLAZE) #define QEMU_ARCH QEMU_ARCH_MICROBLAZE #elif defined(TARGET_MIPS) @@ -80,12 +80,12 @@ int graphic_depth = 32; #define QEMU_ARCH QEMU_ARCH_SH4 #elif defined(TARGET_SPARC) #define QEMU_ARCH QEMU_ARCH_SPARC -#elif defined(TARGET_XTENSA) -#define QEMU_ARCH QEMU_ARCH_XTENSA -#elif defined(TARGET_UNICORE32) -#define QEMU_ARCH QEMU_ARCH_UNICORE32 #elif defined(TARGET_TRICORE) #define QEMU_ARCH QEMU_ARCH_TRICORE +#elif defined(TARGET_UNICORE32) +#define QEMU_ARCH QEMU_ARCH_UNICORE32 +#elif defined(TARGET_XTENSA) +#define QEMU_ARCH QEMU_ARCH_XTENSA #endif const uint32_t arch_type = QEMU_ARCH; diff --git a/backends/cryptodev-vhost-user.c b/backends/cryptodev-vhost-user.c index 862d4f2..d52dacc 100644 --- a/backends/cryptodev-vhost-user.c +++ b/backends/cryptodev-vhost-user.c @@ -26,6 +26,7 @@ #include "qapi/error.h" #include "qapi/qmp/qerror.h" #include "qemu/error-report.h" +#include "hw/virtio/vhost-user.h" #include "standard-headers/linux/virtio_crypto.h" #include "sysemu/cryptodev-vhost.h" #include "chardev/char-fe.h" @@ -46,6 +47,7 @@ typedef struct CryptoDevBackendVhostUser { CryptoDevBackend parent_obj; + VhostUserState *vhost_user; CharBackend chr; char *chr_name; bool opened; @@ -102,7 +104,7 @@ cryptodev_vhost_user_start(int queues, continue; } - options.opaque = &s->chr; + options.opaque = s->vhost_user; options.backend_type = VHOST_BACKEND_TYPE_USER; options.cc = b->conf.peers.ccs[i]; s->vhost_crypto[i] = cryptodev_vhost_init(&options); @@ -185,6 +187,7 @@ static void cryptodev_vhost_user_init( size_t i; Error *local_err = NULL; Chardev *chr; + VhostUserState *user; CryptoDevBackendClient *cc; CryptoDevBackendVhostUser *s = CRYPTODEV_BACKEND_VHOST_USER(backend); @@ -215,6 +218,15 @@ static void cryptodev_vhost_user_init( } } + user = vhost_user_init(); + if (!user) { + error_setg(errp, "Failed to init vhost_user"); + return; + } + + user->chr = &s->chr; + s->vhost_user = user; + qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, cryptodev_vhost_user_event, NULL, s, NULL, true); @@ -299,6 +311,12 @@ static void cryptodev_vhost_user_cleanup( backend->conf.peers.ccs[i] = NULL; } } + + if (s->vhost_user) { + vhost_user_cleanup(s->vhost_user); + g_free(s->vhost_user); + s->vhost_user = NULL; + } } static void cryptodev_vhost_user_set_chardev(Object *obj, diff --git a/block/crypto.c b/block/crypto.c index 7e7ad2d..bc322b5 100644 --- a/block/crypto.c +++ b/block/crypto.c @@ -29,7 +29,7 @@ #include "qapi/qobject-input-visitor.h" #include "qapi/error.h" #include "qemu/option.h" -#include "block/crypto.h" +#include "crypto.h" typedef struct BlockCrypto BlockCrypto; diff --git a/block/nbd.c b/block/nbd.c index 3e1693c..ff8333e 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -27,7 +27,7 @@ */ #include "qemu/osdep.h" -#include "block/nbd-client.h" +#include "nbd-client.h" #include "qapi/error.h" #include "qemu/uri.h" #include "block/block_int.h" diff --git a/block/qcow.c b/block/qcow.c index 3ba2ca2..1f866af 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -37,7 +37,7 @@ #include "qapi/qapi-visit-block-core.h" #include "crypto/block.h" #include "migration/blocker.h" -#include "block/crypto.h" +#include "crypto.h" /**************************************************************/ /* QEMU COW block driver with compression and encryption support */ diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c index 6e93ec4..60d5290 100644 --- a/block/qcow2-bitmap.c +++ b/block/qcow2-bitmap.c @@ -30,7 +30,7 @@ #include "qemu/cutils.h" #include "block/block_int.h" -#include "block/qcow2.h" +#include "qcow2.h" /* NOTICE: BME here means Bitmaps Extension and used as a namespace for * _internal_ constants. Please do not use this _internal_ abbreviation for diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 1aee726..0d74584 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -28,7 +28,7 @@ #include "qapi/error.h" #include "qemu-common.h" #include "block/block_int.h" -#include "block/qcow2.h" +#include "qcow2.h" #include "qemu/bswap.h" #include "trace.h" diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 2dc2300..4032362 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -26,7 +26,7 @@ #include "qapi/error.h" #include "qemu-common.h" #include "block/block_int.h" -#include "block/qcow2.h" +#include "qcow2.h" #include "qemu/range.h" #include "qemu/bswap.h" #include "qemu/cutils.h" diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index 74293be..bb6a5b7 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -25,7 +25,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "block/block_int.h" -#include "block/qcow2.h" +#include "qcow2.h" #include "qemu/bswap.h" #include "qemu/error-report.h" #include "qemu/cutils.h" diff --git a/block/qcow2.c b/block/qcow2.c index a007dc4..c87c593 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -27,7 +27,7 @@ #include "sysemu/block-backend.h" #include "qemu/module.h" #include <zlib.h> -#include "block/qcow2.h" +#include "qcow2.h" #include "qemu/error-report.h" #include "qapi/error.h" #include "qapi/qapi-events-block-core.h" @@ -39,7 +39,7 @@ #include "qemu/bswap.h" #include "qapi/qobject-input-visitor.h" #include "qapi/qapi-visit-block-core.h" -#include "block/crypto.h" +#include "crypto.h" /* Differences with QCOW: diff --git a/block/vhdx-endian.c b/block/vhdx-endian.c index 429d755..41fbdd2 100644 --- a/block/vhdx-endian.c +++ b/block/vhdx-endian.c @@ -19,7 +19,7 @@ #include "qemu-common.h" #include "block/block_int.h" #include "qemu/bswap.h" -#include "block/vhdx.h" +#include "vhdx.h" /* * All the VHDX formats on disk are little endian - the following diff --git a/block/vhdx-log.c b/block/vhdx-log.c index 0ac4863..d2f1b98 100644 --- a/block/vhdx-log.c +++ b/block/vhdx-log.c @@ -24,7 +24,7 @@ #include "qemu/error-report.h" #include "qemu/module.h" #include "qemu/bswap.h" -#include "block/vhdx.h" +#include "vhdx.h" typedef struct VHDXLogSequence { diff --git a/block/vhdx.c b/block/vhdx.c index b1ba121..0831c5c 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -23,7 +23,7 @@ #include "qemu/option.h" #include "qemu/crc32c.h" #include "qemu/bswap.h" -#include "block/vhdx.h" +#include "vhdx.h" #include "migration/blocker.h" #include "qemu/uuid.h" #include "qapi/qmp/qdict.h" diff --git a/contrib/libvhost-user/libvhost-user.c b/contrib/libvhost-user/libvhost-user.c index 54e643d..a6b46cd 100644 --- a/contrib/libvhost-user/libvhost-user.c +++ b/contrib/libvhost-user/libvhost-user.c @@ -314,11 +314,6 @@ vu_message_write(VuDev *dev, int conn_fd, VhostUserMsg *vmsg) msg.msg_controllen = 0; } - /* Set the version in the flags when sending the reply */ - vmsg->flags &= ~VHOST_USER_VERSION_MASK; - vmsg->flags |= VHOST_USER_VERSION; - vmsg->flags |= VHOST_USER_REPLY_MASK; - do { rc = sendmsg(conn_fd, &msg, 0); } while (rc < 0 && (errno == EINTR || errno == EAGAIN)); @@ -341,6 +336,39 @@ vu_message_write(VuDev *dev, int conn_fd, VhostUserMsg *vmsg) return true; } +static bool +vu_send_reply(VuDev *dev, int conn_fd, VhostUserMsg *vmsg) +{ + /* Set the version in the flags when sending the reply */ + vmsg->flags &= ~VHOST_USER_VERSION_MASK; + vmsg->flags |= VHOST_USER_VERSION; + vmsg->flags |= VHOST_USER_REPLY_MASK; + + return vu_message_write(dev, conn_fd, vmsg); +} + +static bool +vu_process_message_reply(VuDev *dev, const VhostUserMsg *vmsg) +{ + VhostUserMsg msg_reply; + + if ((vmsg->flags & VHOST_USER_NEED_REPLY_MASK) == 0) { + return true; + } + + if (!vu_message_read(dev, dev->slave_fd, &msg_reply)) { + return false; + } + + if (msg_reply.request != vmsg->request) { + DPRINT("Received unexpected msg type. Expected %d received %d", + vmsg->request, msg_reply.request); + return false; + } + + return msg_reply.payload.u64 == 0; +} + /* Kick the log_call_fd if required. */ static void vu_log_kick(VuDev *dev) @@ -536,7 +564,7 @@ vu_set_mem_table_exec_postcopy(VuDev *dev, VhostUserMsg *vmsg) /* Send the message back to qemu with the addresses filled in */ vmsg->fd_num = 0; - if (!vu_message_write(dev, dev->sock, vmsg)) { + if (!vu_send_reply(dev, dev->sock, vmsg)) { vu_panic(dev, "failed to respond to set-mem-table for postcopy"); return false; } @@ -916,6 +944,41 @@ void vu_set_queue_handler(VuDev *dev, VuVirtq *vq, } } +bool vu_set_queue_host_notifier(VuDev *dev, VuVirtq *vq, int fd, + int size, int offset) +{ + int qidx = vq - dev->vq; + int fd_num = 0; + VhostUserMsg vmsg = { + .request = VHOST_USER_SLAVE_VRING_HOST_NOTIFIER_MSG, + .flags = VHOST_USER_VERSION | VHOST_USER_NEED_REPLY_MASK, + .size = sizeof(vmsg.payload.area), + .payload.area = { + .u64 = qidx & VHOST_USER_VRING_IDX_MASK, + .size = size, + .offset = offset, + }, + }; + + if (fd == -1) { + vmsg.payload.area.u64 |= VHOST_USER_VRING_NOFD_MASK; + } else { + vmsg.fds[fd_num++] = fd; + } + + vmsg.fd_num = fd_num; + + if ((dev->protocol_features & VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD) == 0) { + return false; + } + + if (!vu_message_write(dev, dev->slave_fd, &vmsg)) { + return false; + } + + return vu_process_message_reply(dev, &vmsg); +} + static bool vu_set_vring_call_exec(VuDev *dev, VhostUserMsg *vmsg) { @@ -968,7 +1031,9 @@ static bool vu_get_protocol_features_exec(VuDev *dev, VhostUserMsg *vmsg) { uint64_t features = 1ULL << VHOST_USER_PROTOCOL_F_LOG_SHMFD | - 1ULL << VHOST_USER_PROTOCOL_F_SLAVE_REQ; + 1ULL << VHOST_USER_PROTOCOL_F_SLAVE_REQ | + 1ULL << VHOST_USER_PROTOCOL_F_HOST_NOTIFIER | + 1ULL << VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD; if (have_userfault()) { features |= 1ULL << VHOST_USER_PROTOCOL_F_PAGEFAULT; @@ -1252,7 +1317,7 @@ vu_dispatch(VuDev *dev) goto end; } - if (!vu_message_write(dev, dev->sock, &vmsg)) { + if (!vu_send_reply(dev, dev->sock, &vmsg)) { goto end; } diff --git a/contrib/libvhost-user/libvhost-user.h b/contrib/libvhost-user/libvhost-user.h index b27075e..4aa55b4 100644 --- a/contrib/libvhost-user/libvhost-user.h +++ b/contrib/libvhost-user/libvhost-user.h @@ -51,6 +51,8 @@ enum VhostUserProtocolFeature { VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7, VHOST_USER_PROTOCOL_F_PAGEFAULT = 8, VHOST_USER_PROTOCOL_F_CONFIG = 9, + VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD = 10, + VHOST_USER_PROTOCOL_F_HOST_NOTIFIER = 11, VHOST_USER_PROTOCOL_F_MAX }; @@ -92,6 +94,14 @@ typedef enum VhostUserRequest { VHOST_USER_MAX } VhostUserRequest; +typedef enum VhostUserSlaveRequest { + VHOST_USER_SLAVE_NONE = 0, + VHOST_USER_SLAVE_IOTLB_MSG = 1, + VHOST_USER_SLAVE_CONFIG_CHANGE_MSG = 2, + VHOST_USER_SLAVE_VRING_HOST_NOTIFIER_MSG = 3, + VHOST_USER_SLAVE_MAX +} VhostUserSlaveRequest; + typedef struct VhostUserMemoryRegion { uint64_t guest_phys_addr; uint64_t memory_size; @@ -122,6 +132,12 @@ static VhostUserConfig c __attribute__ ((unused)); + sizeof(c.size) \ + sizeof(c.flags)) +typedef struct VhostUserVringArea { + uint64_t u64; + uint64_t size; + uint64_t offset; +} VhostUserVringArea; + #if defined(_WIN32) # define VU_PACKED __attribute__((gcc_struct, packed)) #else @@ -133,6 +149,7 @@ typedef struct VhostUserMsg { #define VHOST_USER_VERSION_MASK (0x3) #define VHOST_USER_REPLY_MASK (0x1 << 2) +#define VHOST_USER_NEED_REPLY_MASK (0x1 << 3) uint32_t flags; uint32_t size; /* the following payload size */ @@ -145,6 +162,7 @@ typedef struct VhostUserMsg { VhostUserMemory memory; VhostUserLog log; VhostUserConfig config; + VhostUserVringArea area; } payload; int fds[VHOST_MEMORY_MAX_NREGIONS]; @@ -368,6 +386,20 @@ VuVirtq *vu_get_queue(VuDev *dev, int qidx); void vu_set_queue_handler(VuDev *dev, VuVirtq *vq, vu_queue_handler_cb handler); +/** + * vu_set_queue_host_notifier: + * @dev: a VuDev context + * @vq: a VuVirtq queue + * @fd: a file descriptor + * @size: host page size + * @offset: notifier offset in @fd file + * + * Set queue's host notifier. This function may be called several + * times for the same queue. If called with -1 @fd, the notifier + * is removed. + */ +bool vu_set_queue_host_notifier(VuDev *dev, VuVirtq *vq, int fd, + int size, int offset); /** * vu_queue_set_notification: diff --git a/contrib/vhost-user-blk/vhost-user-blk.c b/contrib/vhost-user-blk/vhost-user-blk.c index a6a132a..571f114 100644 --- a/contrib/vhost-user-blk/vhost-user-blk.c +++ b/contrib/vhost-user-blk/vhost-user-blk.c @@ -31,6 +31,7 @@ typedef struct VubDev { VugDev parent; int blk_fd; struct virtio_blk_config blkcfg; + bool enable_ro; char *blk_name; GMainLoop *loop; } VubDev; @@ -301,14 +302,27 @@ static void vub_queue_set_started(VuDev *vu_dev, int idx, bool started) static uint64_t vub_get_features(VuDev *dev) { - return 1ull << VIRTIO_BLK_F_SIZE_MAX | - 1ull << VIRTIO_BLK_F_SEG_MAX | - 1ull << VIRTIO_BLK_F_TOPOLOGY | - 1ull << VIRTIO_BLK_F_BLK_SIZE | - 1ull << VIRTIO_BLK_F_FLUSH | - 1ull << VIRTIO_BLK_F_CONFIG_WCE | - 1ull << VIRTIO_F_VERSION_1 | - 1ull << VHOST_USER_F_PROTOCOL_FEATURES; + uint64_t features; + VugDev *gdev; + VubDev *vdev_blk; + + gdev = container_of(dev, VugDev, parent); + vdev_blk = container_of(gdev, VubDev, parent); + + features = 1ull << VIRTIO_BLK_F_SIZE_MAX | + 1ull << VIRTIO_BLK_F_SEG_MAX | + 1ull << VIRTIO_BLK_F_TOPOLOGY | + 1ull << VIRTIO_BLK_F_BLK_SIZE | + 1ull << VIRTIO_BLK_F_FLUSH | + 1ull << VIRTIO_BLK_F_CONFIG_WCE | + 1ull << VIRTIO_F_VERSION_1 | + 1ull << VHOST_USER_F_PROTOCOL_FEATURES; + + if (vdev_blk->enable_ro) { + features |= 1ull << VIRTIO_BLK_F_RO; + } + + return features; } static uint64_t @@ -476,6 +490,7 @@ vub_new(char *blk_file) vub_free(vdev_blk); return NULL; } + vdev_blk->enable_ro = false; vdev_blk->blkcfg.wce = 0; vdev_blk->blk_name = blk_file; @@ -490,10 +505,11 @@ int main(int argc, char **argv) int opt; char *unix_socket = NULL; char *blk_file = NULL; + bool enable_ro = false; int lsock = -1, csock = -1; VubDev *vdev_blk = NULL; - while ((opt = getopt(argc, argv, "b:s:h")) != -1) { + while ((opt = getopt(argc, argv, "b:rs:h")) != -1) { switch (opt) { case 'b': blk_file = g_strdup(optarg); @@ -501,17 +517,20 @@ int main(int argc, char **argv) case 's': unix_socket = g_strdup(optarg); break; + case 'r': + enable_ro = true; + break; case 'h': default: - printf("Usage: %s [-b block device or file, -s UNIX domain socket]" - " | [ -h ]\n", argv[0]); + printf("Usage: %s [ -b block device or file, -s UNIX domain socket" + " | -r Enable read-only ] | [ -h ]\n", argv[0]); return 0; } } if (!unix_socket || !blk_file) { - printf("Usage: %s [-b block device or file, -s UNIX domain socket] |" - " [ -h ]\n", argv[0]); + printf("Usage: %s [ -b block device or file, -s UNIX domain socket" + " | -r Enable read-only ] | [ -h ]\n", argv[0]); return -1; } @@ -530,6 +549,9 @@ int main(int argc, char **argv) if (!vdev_blk) { goto err; } + if (enable_ro) { + vdev_blk->enable_ro = true; + } vug_init(&vdev_blk->parent, csock, vub_panic_cb, &vub_iface); diff --git a/crypto/block-luks.c b/crypto/block-luks.c index d418ac3..5738124 100644 --- a/crypto/block-luks.c +++ b/crypto/block-luks.c @@ -22,7 +22,7 @@ #include "qapi/error.h" #include "qemu/bswap.h" -#include "crypto/block-luks.h" +#include "block-luks.h" #include "crypto/hash.h" #include "crypto/afsplit.h" diff --git a/crypto/block-luks.h b/crypto/block-luks.h index b2d8a35..befd8b2 100644 --- a/crypto/block-luks.h +++ b/crypto/block-luks.h @@ -21,7 +21,7 @@ #ifndef QCRYPTO_BLOCK_LUKS_H #define QCRYPTO_BLOCK_LUKS_H -#include "crypto/blockpriv.h" +#include "blockpriv.h" extern const QCryptoBlockDriver qcrypto_block_driver_luks; diff --git a/crypto/block-qcow.c b/crypto/block-qcow.c index 8817d6a..4284e05 100644 --- a/crypto/block-qcow.c +++ b/crypto/block-qcow.c @@ -27,7 +27,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" -#include "crypto/block-qcow.h" +#include "block-qcow.h" #include "crypto/secret.h" #define QCRYPTO_BLOCK_QCOW_SECTOR_SIZE 512 diff --git a/crypto/block-qcow.h b/crypto/block-qcow.h index 3e2c0a8..6988fb2 100644 --- a/crypto/block-qcow.h +++ b/crypto/block-qcow.h @@ -21,7 +21,7 @@ #ifndef QCRYPTO_BLOCK_QCOW_H #define QCRYPTO_BLOCK_QCOW_H -#include "crypto/blockpriv.h" +#include "blockpriv.h" extern const QCryptoBlockDriver qcrypto_block_driver_qcow; diff --git a/crypto/block.c b/crypto/block.c index f206d5e..e59d114 100644 --- a/crypto/block.c +++ b/crypto/block.c @@ -20,9 +20,9 @@ #include "qemu/osdep.h" #include "qapi/error.h" -#include "crypto/blockpriv.h" -#include "crypto/block-qcow.h" -#include "crypto/block-luks.h" +#include "blockpriv.h" +#include "block-qcow.h" +#include "block-luks.h" static const QCryptoBlockDriver *qcrypto_block_drivers[] = { [Q_CRYPTO_BLOCK_FORMAT_QCOW] = &qcrypto_block_driver_qcow, diff --git a/crypto/cipher.c b/crypto/cipher.c index bcbfb3d..b3af579 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c @@ -150,11 +150,11 @@ qcrypto_cipher_munge_des_rfb_key(const uint8_t *key, #endif /* CONFIG_GCRYPT || CONFIG_NETTLE */ #ifdef CONFIG_GCRYPT -#include "crypto/cipher-gcrypt.c" +#include "cipher-gcrypt.c" #elif defined CONFIG_NETTLE -#include "crypto/cipher-nettle.c" +#include "cipher-nettle.c" #else -#include "crypto/cipher-builtin.c" +#include "cipher-builtin.c" #endif QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg, diff --git a/crypto/ivgen-essiv.c b/crypto/ivgen-essiv.c index aeaa8fc..43e258c 100644 --- a/crypto/ivgen-essiv.c +++ b/crypto/ivgen-essiv.c @@ -20,7 +20,7 @@ #include "qemu/osdep.h" #include "qemu/bswap.h" -#include "crypto/ivgen-essiv.h" +#include "ivgen-essiv.h" typedef struct QCryptoIVGenESSIV QCryptoIVGenESSIV; struct QCryptoIVGenESSIV { diff --git a/crypto/ivgen-essiv.h b/crypto/ivgen-essiv.h index 4a00af8..f34dbab 100644 --- a/crypto/ivgen-essiv.h +++ b/crypto/ivgen-essiv.h @@ -18,7 +18,7 @@ * */ -#include "crypto/ivgenpriv.h" +#include "ivgenpriv.h" #ifndef QCRYPTO_IVGEN_ESSIV_H__ #define QCRYPTO_IVGEN_ESSIV_H__ diff --git a/crypto/ivgen-plain.c b/crypto/ivgen-plain.c index bf2fb7a..06f4145 100644 --- a/crypto/ivgen-plain.c +++ b/crypto/ivgen-plain.c @@ -20,7 +20,7 @@ #include "qemu/osdep.h" #include "qemu/bswap.h" -#include "crypto/ivgen-plain.h" +#include "ivgen-plain.h" static int qcrypto_ivgen_plain_init(QCryptoIVGen *ivgen, const uint8_t *key, size_t nkey, diff --git a/crypto/ivgen-plain.h b/crypto/ivgen-plain.h index 0fe8835..16e1ae5 100644 --- a/crypto/ivgen-plain.h +++ b/crypto/ivgen-plain.h @@ -18,7 +18,7 @@ * */ -#include "crypto/ivgenpriv.h" +#include "ivgenpriv.h" #ifndef QCRYPTO_IVGEN_PLAIN_H__ #define QCRYPTO_IVGEN_PLAIN_H__ diff --git a/crypto/ivgen-plain64.c b/crypto/ivgen-plain64.c index e4679a1..fbb7724 100644 --- a/crypto/ivgen-plain64.c +++ b/crypto/ivgen-plain64.c @@ -20,7 +20,7 @@ #include "qemu/osdep.h" #include "qemu/bswap.h" -#include "crypto/ivgen-plain.h" +#include "ivgen-plain.h" static int qcrypto_ivgen_plain_init(QCryptoIVGen *ivgen, const uint8_t *key, size_t nkey, diff --git a/crypto/ivgen-plain64.h b/crypto/ivgen-plain64.h index c410445..f8611bd 100644 --- a/crypto/ivgen-plain64.h +++ b/crypto/ivgen-plain64.h @@ -18,7 +18,7 @@ * */ -#include "crypto/ivgenpriv.h" +#include "ivgenpriv.h" #ifndef QCRYPTO_IVGEN_PLAIN64_H__ #define QCRYPTO_IVGEN_PLAIN64_H__ diff --git a/crypto/ivgen.c b/crypto/ivgen.c index f664351..6a2b3ad 100644 --- a/crypto/ivgen.c +++ b/crypto/ivgen.c @@ -21,10 +21,10 @@ #include "qemu/osdep.h" #include "qapi/error.h" -#include "crypto/ivgenpriv.h" -#include "crypto/ivgen-plain.h" -#include "crypto/ivgen-plain64.h" -#include "crypto/ivgen-essiv.h" +#include "ivgenpriv.h" +#include "ivgen-plain.h" +#include "ivgen-plain64.h" +#include "ivgen-essiv.h" QCryptoIVGen *qcrypto_ivgen_new(QCryptoIVGenAlgorithm alg, diff --git a/crypto/tlscreds.c b/crypto/tlscreds.c index 3cd4103..02255a6 100644 --- a/crypto/tlscreds.c +++ b/crypto/tlscreds.c @@ -20,7 +20,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" -#include "crypto/tlscredspriv.h" +#include "tlscredspriv.h" #include "trace.h" #define DH_BITS 2048 diff --git a/crypto/tlscredsanon.c b/crypto/tlscredsanon.c index 1464220..7ad66d1 100644 --- a/crypto/tlscredsanon.c +++ b/crypto/tlscredsanon.c @@ -20,7 +20,7 @@ #include "qemu/osdep.h" #include "crypto/tlscredsanon.h" -#include "crypto/tlscredspriv.h" +#include "tlscredspriv.h" #include "qapi/error.h" #include "qom/object_interfaces.h" #include "trace.h" diff --git a/crypto/tlscredsx509.c b/crypto/tlscredsx509.c index 50eb54f..98ee042 100644 --- a/crypto/tlscredsx509.c +++ b/crypto/tlscredsx509.c @@ -20,7 +20,7 @@ #include "qemu/osdep.h" #include "crypto/tlscredsx509.h" -#include "crypto/tlscredspriv.h" +#include "tlscredspriv.h" #include "crypto/secret.h" #include "qapi/error.h" #include "qom/object_interfaces.h" diff --git a/docs/interop/vhost-user.txt b/docs/interop/vhost-user.txt index 534caab..d51fd58 100644 --- a/docs/interop/vhost-user.txt +++ b/docs/interop/vhost-user.txt @@ -132,6 +132,16 @@ Depending on the request type, payload can be: Payload: Size bytes array holding the contents of the virtio device's configuration space + * Vring area description + ----------------------- + | u64 | size | offset | + ----------------------- + + u64: a 64-bit integer contains vring index and flags + Size: a 64-bit size of this area + Offset: a 64-bit offset of this area from the start of the + supplied file descriptor + In QEMU the vhost-user message is implemented with the following struct: typedef struct VhostUserMsg { @@ -146,6 +156,7 @@ typedef struct VhostUserMsg { VhostUserLog log; struct vhost_iotlb_msg iotlb; VhostUserConfig config; + VhostUserVringArea area; }; } QEMU_PACKED VhostUserMsg; @@ -367,6 +378,10 @@ The fd is provided via VHOST_USER_SET_SLAVE_REQ_FD ancillary data. A slave may then send VHOST_USER_SLAVE_* messages to the master using this fd communication channel. +If VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD protocol feature is negotiated, +slave can send file descriptors (at most 8 descriptors in each message) +to master via ancillary data using this fd communication channel. + Protocol features ----------------- @@ -380,6 +395,8 @@ Protocol features #define VHOST_USER_PROTOCOL_F_CRYPTO_SESSION 7 #define VHOST_USER_PROTOCOL_F_PAGEFAULT 8 #define VHOST_USER_PROTOCOL_F_CONFIG 9 +#define VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD 10 +#define VHOST_USER_PROTOCOL_F_HOST_NOTIFIER 11 Master message types -------------------- @@ -777,6 +794,27 @@ Slave message types the VHOST_USER_NEED_REPLY flag, master must respond with zero when operation is successfully completed, or non-zero otherwise. + * VHOST_USER_SLAVE_VRING_HOST_NOTIFIER_MSG + + Id: 3 + Equivalent ioctl: N/A + Slave payload: vring area description + Master payload: N/A + + Sets host notifier for a specified queue. The queue index is contained + in the u64 field of the vring area description. The host notifier is + described by the file descriptor (typically it's a VFIO device fd) which + is passed as ancillary data and the size (which is mmap size and should + be the same as host page size) and offset (which is mmap offset) carried + in the vring area description. QEMU can mmap the file descriptor based + on the size and offset to get a memory range. Registering a host notifier + means mapping this memory range to the VM as the specified queue's notify + MMIO region. Slave sends this request to tell QEMU to de-register the + existing notifier if any and register the new notifier if the request is + sent with a file descriptor. + This request should be sent only when VHOST_USER_PROTOCOL_F_HOST_NOTIFIER + protocol feature has been successfully negotiated. + VHOST_USER_PROTOCOL_F_REPLY_ACK: ------------------------------- The original vhost-user specification only demands replies for certain diff --git a/docs/nvdimm.txt b/docs/nvdimm.txt index e903d8b..8b48fb4 100644 --- a/docs/nvdimm.txt +++ b/docs/nvdimm.txt @@ -153,3 +153,30 @@ guest NVDIMM region mapping structure. This unarmed flag indicates guest software that this vNVDIMM device contains a region that cannot accept persistent writes. In result, for example, the guest Linux NVDIMM driver, marks such vNVDIMM device as read-only. + +Platform Capabilities +--------------------- + +ACPI 6.2 Errata A added support for a new Platform Capabilities Structure +which allows the platform to communicate what features it supports related to +NVDIMM data durability. Users can provide a capabilities value to a guest via +the optional "nvdimm-cap" machine command line option: + + -machine pc,accel=kvm,nvdimm,nvdimm-cap=2 + +This "nvdimm-cap" field is an integer, and is the combined value of the +various capability bits defined in table 5-137 of the ACPI 6.2 Errata A spec. + +Here is a quick summary of the three bits that are defined as of that spec: + +Bit[0] - CPU Cache Flush to NVDIMM Durability on Power Loss Capable. +Bit[1] - Memory Controller Flush to NVDIMM Durability on Power Loss Capable. + Note: If bit 0 is set to 1 then this bit shall be set to 1 as well. +Bit[2] - Byte Addressable Persistent Memory Hardware Mirroring Capable. + +So, a "nvdimm-cap" value of 2 would mean that the platform supports Memory +Controller Flush on Power Loss, a value of 3 would mean that the platform +supports CPU Cache Flush and Memory Controller Flush on Power Loss, etc. + +For a complete list of the flags available and for more detailed descriptions, +please consult the ACPI spec. diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c index 59d6e42..87e4280 100644 --- a/hw/acpi/nvdimm.c +++ b/hw/acpi/nvdimm.c @@ -170,6 +170,21 @@ struct NvdimmNfitControlRegion { typedef struct NvdimmNfitControlRegion NvdimmNfitControlRegion; /* + * NVDIMM Platform Capabilities Structure + * + * Defined in section 5.2.25.9 of ACPI 6.2 Errata A, September 2017 + */ +struct NvdimmNfitPlatformCaps { + uint16_t type; + uint16_t length; + uint8_t highest_cap; + uint8_t reserved[3]; + uint32_t capabilities; + uint8_t reserved2[4]; +} QEMU_PACKED; +typedef struct NvdimmNfitPlatformCaps NvdimmNfitPlatformCaps; + +/* * Module serial number is a unique number for each device. We use the * slot id of NVDIMM device to generate this number so that each device * associates with a different number. @@ -351,7 +366,23 @@ static void nvdimm_build_structure_dcr(GArray *structures, DeviceState *dev) JEDEC Annex L Release 3. */); } -static GArray *nvdimm_build_device_structure(void) +/* + * ACPI 6.2 Errata A: 5.2.25.9 NVDIMM Platform Capabilities Structure + */ +static void +nvdimm_build_structure_caps(GArray *structures, uint32_t capabilities) +{ + NvdimmNfitPlatformCaps *nfit_caps; + + nfit_caps = acpi_data_push(structures, sizeof(*nfit_caps)); + + nfit_caps->type = cpu_to_le16(7 /* NVDIMM Platform Capabilities */); + nfit_caps->length = cpu_to_le16(sizeof(*nfit_caps)); + nfit_caps->highest_cap = 31 - clz32(capabilities); + nfit_caps->capabilities = cpu_to_le32(capabilities); +} + +static GArray *nvdimm_build_device_structure(AcpiNVDIMMState *state) { GSList *device_list = nvdimm_get_device_list(); GArray *structures = g_array_new(false, true /* clear */, 1); @@ -373,6 +404,10 @@ static GArray *nvdimm_build_device_structure(void) } g_slist_free(device_list); + if (state->capabilities) { + nvdimm_build_structure_caps(structures, state->capabilities); + } + return structures; } @@ -381,16 +416,18 @@ static void nvdimm_init_fit_buffer(NvdimmFitBuffer *fit_buf) fit_buf->fit = g_array_new(false, true /* clear */, 1); } -static void nvdimm_build_fit_buffer(NvdimmFitBuffer *fit_buf) +static void nvdimm_build_fit_buffer(AcpiNVDIMMState *state) { + NvdimmFitBuffer *fit_buf = &state->fit_buf; + g_array_free(fit_buf->fit, true); - fit_buf->fit = nvdimm_build_device_structure(); + fit_buf->fit = nvdimm_build_device_structure(state); fit_buf->dirty = true; } void nvdimm_plug(AcpiNVDIMMState *state) { - nvdimm_build_fit_buffer(&state->fit_buf); + nvdimm_build_fit_buffer(state); } static void nvdimm_build_nfit(AcpiNVDIMMState *state, GArray *table_offsets, diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c index 975eae6..d755223 100644 --- a/hw/block/vhost-user-blk.c +++ b/hw/block/vhost-user-blk.c @@ -203,13 +203,11 @@ static uint64_t vhost_user_blk_get_features(VirtIODevice *vdev, virtio_add_feature(&features, VIRTIO_BLK_F_TOPOLOGY); virtio_add_feature(&features, VIRTIO_BLK_F_BLK_SIZE); virtio_add_feature(&features, VIRTIO_BLK_F_FLUSH); + virtio_add_feature(&features, VIRTIO_BLK_F_RO); if (s->config_wce) { virtio_add_feature(&features, VIRTIO_BLK_F_CONFIG_WCE); } - if (s->config_ro) { - virtio_add_feature(&features, VIRTIO_BLK_F_RO); - } if (s->num_queues > 1) { virtio_add_feature(&features, VIRTIO_BLK_F_MQ); } @@ -226,6 +224,7 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); VHostUserBlk *s = VHOST_USER_BLK(vdev); + VhostUserState *user; int i, ret; if (!s->chardev.chr) { @@ -243,6 +242,15 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp) return; } + user = vhost_user_init(); + if (!user) { + error_setg(errp, "vhost-user-blk: failed to init vhost_user"); + return; + } + + user->chr = &s->chardev; + s->vhost_user = user; + virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK, sizeof(struct virtio_blk_config)); @@ -258,7 +266,7 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp) vhost_dev_set_config_notifier(&s->dev, &blk_ops); - ret = vhost_dev_init(&s->dev, &s->chardev, VHOST_BACKEND_TYPE_USER, 0); + ret = vhost_dev_init(&s->dev, s->vhost_user, VHOST_BACKEND_TYPE_USER, 0); if (ret < 0) { error_setg(errp, "vhost-user-blk: vhost initialization failed: %s", strerror(-ret)); @@ -283,6 +291,10 @@ vhost_err: virtio_err: g_free(s->dev.vqs); virtio_cleanup(vdev); + + vhost_user_cleanup(user); + g_free(user); + s->vhost_user = NULL; } static void vhost_user_blk_device_unrealize(DeviceState *dev, Error **errp) @@ -294,6 +306,12 @@ static void vhost_user_blk_device_unrealize(DeviceState *dev, Error **errp) vhost_dev_cleanup(&s->dev); g_free(s->dev.vqs); virtio_cleanup(vdev); + + if (s->vhost_user) { + vhost_user_cleanup(s->vhost_user); + g_free(s->vhost_user); + s->vhost_user = NULL; + } } static void vhost_user_blk_instance_init(Object *obj) @@ -319,7 +337,6 @@ static Property vhost_user_blk_properties[] = { DEFINE_PROP_UINT16("num-queues", VHostUserBlk, num_queues, 1), DEFINE_PROP_UINT32("queue-size", VHostUserBlk, queue_size, 128), DEFINE_PROP_BIT("config-wce", VHostUserBlk, config_wce, 0, true), - DEFINE_PROP_BIT("config-ro", VHostUserBlk, config_ro, 0, false), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c index 7eab927..3355f4c 100644 --- a/hw/display/bcm2835_fb.c +++ b/hw/display/bcm2835_fb.c @@ -26,7 +26,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/display/bcm2835_fb.h" -#include "hw/display/framebuffer.h" +#include "framebuffer.h" #include "ui/pixel_ops.h" #include "hw/misc/bcm2835_mbox_defs.h" #include "qemu/log.h" diff --git a/hw/hppa/hppa_sys.h b/hw/hppa/hppa_sys.h index 3f6c145..f5f983b 100644 --- a/hw/hppa/hppa_sys.h +++ b/hw/hppa/hppa_sys.h @@ -9,7 +9,7 @@ #include "hw/i386/pc.h" #include "hw/irq.h" -#include "hw/hppa/hppa_hardware.h" +#include "hppa_hardware.h" PCIBus *dino_init(MemoryRegion *, qemu_irq *, qemu_irq *); diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index a1d6b0e..aba269b 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -16,7 +16,7 @@ #include "hw/ide.h" #include "hw/timer/i8254.h" #include "hw/char/serial.h" -#include "hw/hppa/hppa_sys.h" +#include "hppa_sys.h" #include "qemu/cutils.h" #include "qapi/error.h" #include "qemu/log.h" diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 8b0803c..f3befe6 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -2181,6 +2181,33 @@ static void pc_machine_set_nvdimm(Object *obj, bool value, Error **errp) pcms->acpi_nvdimm_state.is_enabled = value; } +static void pc_machine_get_nvdimm_capabilities(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + PCMachineState *pcms = PC_MACHINE(obj); + uint32_t value = pcms->acpi_nvdimm_state.capabilities; + + visit_type_uint32(v, name, &value, errp); +} + +static void pc_machine_set_nvdimm_capabilities(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + PCMachineState *pcms = PC_MACHINE(obj); + Error *error = NULL; + uint32_t value; + + visit_type_uint32(v, name, &value, &error); + if (error) { + error_propagate(errp, error); + return; + } + + pcms->acpi_nvdimm_state.capabilities = value; +} + static bool pc_machine_get_smbus(Object *obj, Error **errp) { PCMachineState *pcms = PC_MACHINE(obj); @@ -2394,6 +2421,10 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) object_class_property_add_bool(oc, PC_MACHINE_NVDIMM, pc_machine_get_nvdimm, pc_machine_set_nvdimm, &error_abort); + object_class_property_add(oc, PC_MACHINE_NVDIMM_CAP, "uint32", + pc_machine_get_nvdimm_capabilities, + pc_machine_set_nvdimm_capabilities, NULL, NULL, &error_abort); + object_class_property_add_bool(oc, PC_MACHINE_SMBUS, pc_machine_get_smbus, pc_machine_set_smbus, &error_abort); diff --git a/hw/ide/ahci-allwinner.c b/hw/ide/ahci-allwinner.c index 2fd9507..f98e6cb 100644 --- a/hw/ide/ahci-allwinner.c +++ b/hw/ide/ahci-allwinner.c @@ -20,7 +20,7 @@ #include "qemu/error-report.h" #include "sysemu/dma.h" #include "hw/ide/internal.h" -#include "hw/ide/ahci_internal.h" +#include "ahci_internal.h" #include "trace.h" diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index e22d7be..24dbad5 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -31,7 +31,7 @@ #include "sysemu/dma.h" #include "hw/ide/internal.h" #include "hw/ide/pci.h" -#include "hw/ide/ahci_internal.h" +#include "ahci_internal.h" #include "trace.h" diff --git a/hw/ide/ich.c b/hw/ide/ich.c index 134478e..51c935a 100644 --- a/hw/ide/ich.c +++ b/hw/ide/ich.c @@ -67,7 +67,7 @@ #include "hw/isa/isa.h" #include "sysemu/dma.h" #include "hw/ide/pci.h" -#include "hw/ide/ahci_internal.h" +#include "ahci_internal.h" #define ICH9_MSI_CAP_OFFSET 0x80 #define ICH9_SATA_CAP_OFFSET 0xA8 diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c index 36139a4..c45f073 100644 --- a/hw/intc/ioapic.c +++ b/hw/intc/ioapic.c @@ -28,9 +28,8 @@ #include "hw/i386/apic.h" #include "hw/i386/ioapic.h" #include "hw/i386/ioapic_internal.h" -#include "include/hw/pci/msi.h" +#include "hw/pci/msi.h" #include "sysemu/kvm.h" -#include "target/i386/cpu.h" #include "hw/i386/apic-msidef.h" #include "hw/i386/x86-iommu.h" #include "trace.h" diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c index 16a9417..cda8d48 100644 --- a/hw/net/e1000e.c +++ b/hw/net/e1000e.c @@ -41,7 +41,7 @@ #include "hw/pci/msi.h" #include "hw/pci/msix.h" -#include "hw/net/e1000_regs.h" +#include "e1000_regs.h" #include "e1000x_common.h" #include "e1000e_core.h" diff --git a/hw/net/rocker/rocker_fp.c b/hw/net/rocker/rocker_fp.c index 27b17c8..4aa7da7 100644 --- a/hw/net/rocker/rocker_fp.c +++ b/hw/net/rocker/rocker_fp.c @@ -15,7 +15,6 @@ */ #include "qemu/osdep.h" -#include "net/clients.h" #include "qapi/qapi-types-rocker.h" #include "rocker.h" #include "rocker_hw.h" diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c index e312fdb..123f4ac 100644 --- a/hw/ppc/ppc440_uc.c +++ b/hw/ppc/ppc440_uc.c @@ -20,7 +20,7 @@ #include "hw/ppc/ppc.h" #include "hw/pci/pci.h" #include "sysemu/block-backend.h" -#include "hw/ppc/ppc440.h" +#include "ppc440.h" /*****************************************************************************/ /* L2 Cache as SRAM */ diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index 3dd23de..bdc53d2 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -26,8 +26,8 @@ #include "elf.h" #include "exec/address-spaces.h" #include "exec/memory.h" -#include "hw/ppc/ppc440.h" -#include "hw/ppc/ppc405.h" +#include "ppc440.h" +#include "ppc405.h" #include "hw/block/flash.h" #include "sysemu/sysemu.h" #include "sysemu/qtest.h" diff --git a/hw/scsi/vhost-scsi-common.c b/hw/scsi/vhost-scsi-common.c index 77e9897..e2a5828 100644 --- a/hw/scsi/vhost-scsi-common.c +++ b/hw/scsi/vhost-scsi-common.c @@ -17,7 +17,6 @@ #include "qemu/osdep.h" #include "qemu/error-report.h" -#include "migration/migration.h" #include "hw/virtio/vhost.h" #include "hw/virtio/vhost-scsi-common.h" #include "hw/virtio/virtio-scsi.h" diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c index 9389ed4..9355cfd 100644 --- a/hw/scsi/vhost-user-scsi.c +++ b/hw/scsi/vhost-user-scsi.c @@ -69,6 +69,7 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp) VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev); VHostUserSCSI *s = VHOST_USER_SCSI(dev); VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s); + VhostUserState *user; Error *err = NULL; int ret; @@ -85,19 +86,30 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp) return; } + user = vhost_user_init(); + if (!user) { + error_setg(errp, "vhost-user-scsi: failed to init vhost_user"); + return; + } + user->chr = &vs->conf.chardev; + vsc->dev.nvqs = 2 + vs->conf.num_queues; vsc->dev.vqs = g_new(struct vhost_virtqueue, vsc->dev.nvqs); vsc->dev.vq_index = 0; vsc->dev.backend_features = 0; - ret = vhost_dev_init(&vsc->dev, (void *)&vs->conf.chardev, + ret = vhost_dev_init(&vsc->dev, user, VHOST_BACKEND_TYPE_USER, 0); if (ret < 0) { error_setg(errp, "vhost-user-scsi: vhost initialization failed: %s", strerror(-ret)); + vhost_user_cleanup(user); + g_free(user); return; } + s->vhost_user = user; + /* Channel and lun both are 0 for bootable vhost-user-scsi disk */ vsc->channel = 0; vsc->lun = 0; @@ -117,6 +129,12 @@ static void vhost_user_scsi_unrealize(DeviceState *dev, Error **errp) g_free(vsc->dev.vqs); virtio_scsi_common_unrealize(dev, errp); + + if (s->vhost_user) { + vhost_user_cleanup(s->vhost_user); + g_free(s->vhost_user); + s->vhost_user = NULL; + } } static uint64_t vhost_user_scsi_get_features(VirtIODevice *vdev, diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c index 5570c1e..fe1cccc 100644 --- a/hw/sd/milkymist-memcard.c +++ b/hw/sd/milkymist-memcard.c @@ -27,7 +27,7 @@ #include "hw/sysbus.h" #include "sysemu/sysemu.h" #include "trace.h" -#include "include/qapi/error.h" +#include "qapi/error.h" #include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "hw/sd/sd.h" diff --git a/hw/usb/desc-msos.c b/hw/usb/desc-msos.c index 3652919..3a5ad7c 100644 --- a/hw/usb/desc-msos.c +++ b/hw/usb/desc-msos.c @@ -1,6 +1,6 @@ #include "qemu/osdep.h" #include "hw/usb.h" -#include "hw/usb/desc.h" +#include "desc.h" /* * Microsoft OS Descriptors diff --git a/hw/usb/desc.c b/hw/usb/desc.c index 85c15ad..8b6eaea 100644 --- a/hw/usb/desc.c +++ b/hw/usb/desc.c @@ -1,7 +1,7 @@ #include "qemu/osdep.h" #include "hw/usb.h" -#include "hw/usb/desc.h" +#include "desc.h" #include "trace.h" /* ------------------------------------------------------------------ */ diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index 3433452..ee43e49 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -32,7 +32,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" #include "hw/usb.h" -#include "hw/usb/desc.h" +#include "desc.h" #include "hw/hw.h" #include "audio/audio.h" diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c index 0bbceae..eac7365 100644 --- a/hw/usb/dev-bluetooth.c +++ b/hw/usb/dev-bluetooth.c @@ -22,7 +22,7 @@ #include "qemu-common.h" #include "qemu/error-report.h" #include "hw/usb.h" -#include "hw/usb/desc.h" +#include "desc.h" #include "sysemu/bt.h" #include "hw/bt.h" diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c index c40019d..62d1829 100644 --- a/hw/usb/dev-hid.c +++ b/hw/usb/dev-hid.c @@ -26,7 +26,7 @@ #include "hw/hw.h" #include "ui/console.h" #include "hw/usb.h" -#include "hw/usb/desc.h" +#include "desc.h" #include "qapi/error.h" #include "qemu/timer.h" #include "hw/input/hid.h" diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c index 752e30c..5d9743ef 100644 --- a/hw/usb/dev-hub.c +++ b/hw/usb/dev-hub.c @@ -26,7 +26,7 @@ #include "qemu-common.h" #include "trace.h" #include "hw/usb.h" -#include "hw/usb/desc.h" +#include "desc.h" #include "qemu/error-report.h" #define NUM_PORTS 8 diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c index 3d59fe4..560c61c 100644 --- a/hw/usb/dev-mtp.c +++ b/hw/usb/dev-mtp.c @@ -24,7 +24,7 @@ #include "qemu/iov.h" #include "trace.h" #include "hw/usb.h" -#include "hw/usb/desc.h" +#include "desc.h" /* ----------------------------------------------------------------------- */ diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index aea7edc..385e090 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -27,7 +27,7 @@ #include "qapi/error.h" #include "qemu-common.h" #include "hw/usb.h" -#include "hw/usb/desc.h" +#include "desc.h" #include "net/net.h" #include "qemu/error-report.h" #include "qemu/queue.h" diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index 2829dda..98d1ca3 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -14,7 +14,7 @@ #include "qemu/cutils.h" #include "qemu/error-report.h" #include "hw/usb.h" -#include "hw/usb/desc.h" +#include "desc.h" #include "chardev/char-serial.h" #include "chardev/char-fe.h" diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index f745192..2131e33 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -39,7 +39,7 @@ #include "qemu-common.h" #include "qemu/error-report.h" #include "hw/usb.h" -#include "hw/usb/desc.h" +#include "desc.h" #include "ccid.h" diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index d02acda..481694a 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -14,7 +14,7 @@ #include "qemu/option.h" #include "qemu/config-file.h" #include "hw/usb.h" -#include "hw/usb/desc.h" +#include "desc.h" #include "hw/scsi/scsi.h" #include "ui/console.h" #include "monitor/monitor.h" diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c index c218b53..aaf5a88 100644 --- a/hw/usb/dev-uas.c +++ b/hw/usb/dev-uas.c @@ -17,7 +17,7 @@ #include "qemu/error-report.h" #include "hw/usb.h" -#include "hw/usb/desc.h" +#include "desc.h" #include "hw/scsi/scsi.h" #include "scsi/constants.h" diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c index bf70013..ac0bc83 100644 --- a/hw/usb/dev-wacom.c +++ b/hw/usb/dev-wacom.c @@ -29,7 +29,7 @@ #include "hw/hw.h" #include "ui/console.h" #include "hw/usb.h" -#include "hw/usb/desc.h" +#include "desc.h" /* Interface requests */ #define WACOM_GET_REPORT 0x2101 diff --git a/hw/virtio/vhost-stub.c b/hw/virtio/vhost-stub.c index 2d76cde..049089b 100644 --- a/hw/virtio/vhost-stub.c +++ b/hw/virtio/vhost-stub.c @@ -1,7 +1,17 @@ #include "qemu/osdep.h" #include "hw/virtio/vhost.h" +#include "hw/virtio/vhost-user.h" bool vhost_has_free_slot(void) { return true; } + +VhostUserState *vhost_user_init(void) +{ + return NULL; +} + +void vhost_user_cleanup(VhostUserState *user) +{ +} diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index ca554d4..b041343 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -11,7 +11,9 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/virtio/vhost.h" +#include "hw/virtio/vhost-user.h" #include "hw/virtio/vhost-backend.h" +#include "hw/virtio/virtio.h" #include "hw/virtio/virtio-net.h" #include "chardev/char-fe.h" #include "sysemu/kvm.h" @@ -30,6 +32,7 @@ #define VHOST_MEMORY_MAX_NREGIONS 8 #define VHOST_USER_F_PROTOCOL_FEATURES 30 +#define VHOST_USER_SLAVE_MAX_FDS 8 /* * Maximum size of virtio device config space @@ -47,6 +50,8 @@ enum VhostUserProtocolFeature { VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7, VHOST_USER_PROTOCOL_F_PAGEFAULT = 8, VHOST_USER_PROTOCOL_F_CONFIG = 9, + VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD = 10, + VHOST_USER_PROTOCOL_F_HOST_NOTIFIER = 11, VHOST_USER_PROTOCOL_F_MAX }; @@ -91,6 +96,7 @@ typedef enum VhostUserSlaveRequest { VHOST_USER_SLAVE_NONE = 0, VHOST_USER_SLAVE_IOTLB_MSG = 1, VHOST_USER_SLAVE_CONFIG_CHANGE_MSG = 2, + VHOST_USER_SLAVE_VRING_HOST_NOTIFIER_MSG = 3, VHOST_USER_SLAVE_MAX } VhostUserSlaveRequest; @@ -135,6 +141,12 @@ static VhostUserConfig c __attribute__ ((unused)); + sizeof(c.size) \ + sizeof(c.flags)) +typedef struct VhostUserVringArea { + uint64_t u64; + uint64_t size; + uint64_t offset; +} VhostUserVringArea; + typedef struct { VhostUserRequest request; @@ -156,6 +168,7 @@ typedef union { struct vhost_iotlb_msg iotlb; VhostUserConfig config; VhostUserCryptoSession session; + VhostUserVringArea area; } VhostUserPayload; typedef struct VhostUserMsg { @@ -173,7 +186,8 @@ static VhostUserMsg m __attribute__ ((unused)); struct vhost_user { struct vhost_dev *dev; - CharBackend *chr; + /* Shared between vhost devs of the same virtio device */ + VhostUserState *user; int slave_fd; NotifierWithReturn postcopy_notifier; struct PostCopyFD postcopy_fd; @@ -199,7 +213,7 @@ static bool ioeventfd_enabled(void) static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg) { struct vhost_user *u = dev->opaque; - CharBackend *chr = u->chr; + CharBackend *chr = u->user->chr; uint8_t *p = (uint8_t *) msg; int r, size = VHOST_USER_HDR_SIZE; @@ -285,7 +299,7 @@ static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg, int *fds, int fd_num) { struct vhost_user *u = dev->opaque; - CharBackend *chr = u->chr; + CharBackend *chr = u->user->chr; int ret, size = VHOST_USER_HDR_SIZE + msg->hdr.size; /* @@ -636,9 +650,37 @@ static int vhost_user_set_vring_num(struct vhost_dev *dev, return vhost_set_vring(dev, VHOST_USER_SET_VRING_NUM, ring); } +static void vhost_user_host_notifier_restore(struct vhost_dev *dev, + int queue_idx) +{ + struct vhost_user *u = dev->opaque; + VhostUserHostNotifier *n = &u->user->notifier[queue_idx]; + VirtIODevice *vdev = dev->vdev; + + if (n->addr && !n->set) { + virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, true); + n->set = true; + } +} + +static void vhost_user_host_notifier_remove(struct vhost_dev *dev, + int queue_idx) +{ + struct vhost_user *u = dev->opaque; + VhostUserHostNotifier *n = &u->user->notifier[queue_idx]; + VirtIODevice *vdev = dev->vdev; + + if (n->addr && n->set) { + virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, false); + n->set = false; + } +} + static int vhost_user_set_vring_base(struct vhost_dev *dev, struct vhost_vring_state *ring) { + vhost_user_host_notifier_restore(dev, ring->index); + return vhost_set_vring(dev, VHOST_USER_SET_VRING_BASE, ring); } @@ -672,6 +714,8 @@ static int vhost_user_get_vring_base(struct vhost_dev *dev, .hdr.size = sizeof(msg.payload.state), }; + vhost_user_host_notifier_remove(dev, ring->index); + if (vhost_user_write(dev, &msg, NULL, 0) < 0) { return -1; } @@ -845,6 +889,66 @@ static int vhost_user_slave_handle_config_change(struct vhost_dev *dev) return ret; } +static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev, + VhostUserVringArea *area, + int fd) +{ + int queue_idx = area->u64 & VHOST_USER_VRING_IDX_MASK; + size_t page_size = qemu_real_host_page_size; + struct vhost_user *u = dev->opaque; + VhostUserState *user = u->user; + VirtIODevice *vdev = dev->vdev; + VhostUserHostNotifier *n; + void *addr; + char *name; + + if (!virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_HOST_NOTIFIER) || + vdev == NULL || queue_idx >= virtio_get_num_queues(vdev)) { + return -1; + } + + n = &user->notifier[queue_idx]; + + if (n->addr) { + virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, false); + object_unparent(OBJECT(&n->mr)); + munmap(n->addr, page_size); + n->addr = NULL; + } + + if (area->u64 & VHOST_USER_VRING_NOFD_MASK) { + return 0; + } + + /* Sanity check. */ + if (area->size != page_size) { + return -1; + } + + addr = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, + fd, area->offset); + if (addr == MAP_FAILED) { + return -1; + } + + name = g_strdup_printf("vhost-user/host-notifier@%p mmaps[%d]", + user, queue_idx); + memory_region_init_ram_device_ptr(&n->mr, OBJECT(vdev), name, + page_size, addr); + g_free(name); + + if (virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, true)) { + munmap(addr, page_size); + return -1; + } + + n->addr = addr; + n->set = true; + + return 0; +} + static void slave_read(void *opaque) { struct vhost_dev *dev = opaque; @@ -854,10 +958,10 @@ static void slave_read(void *opaque) int size, ret = 0; struct iovec iov; struct msghdr msgh; - int fd = -1; + int fd[VHOST_USER_SLAVE_MAX_FDS]; char control[CMSG_SPACE(sizeof(fd))]; struct cmsghdr *cmsg; - size_t fdsize; + int i, fdsize = 0; memset(&msgh, 0, sizeof(msgh)); msgh.msg_iov = &iov; @@ -865,6 +969,8 @@ static void slave_read(void *opaque) msgh.msg_control = control; msgh.msg_controllen = sizeof(control); + memset(fd, -1, sizeof(fd)); + /* Read header */ iov.iov_base = &hdr; iov.iov_len = VHOST_USER_HDR_SIZE; @@ -885,7 +991,7 @@ static void slave_read(void *opaque) if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { fdsize = cmsg->cmsg_len - CMSG_LEN(0); - memcpy(&fd, CMSG_DATA(cmsg), fdsize); + memcpy(fd, CMSG_DATA(cmsg), fdsize); break; } } @@ -911,16 +1017,21 @@ static void slave_read(void *opaque) case VHOST_USER_SLAVE_CONFIG_CHANGE_MSG : ret = vhost_user_slave_handle_config_change(dev); break; + case VHOST_USER_SLAVE_VRING_HOST_NOTIFIER_MSG: + ret = vhost_user_slave_handle_vring_host_notifier(dev, &payload.area, + fd[0]); + break; default: error_report("Received unexpected msg type."); - if (fd != -1) { - close(fd); - } ret = -EINVAL; } - /* Message handlers need to make sure that fd will be consumed. */ - fd = -1; + /* Close the remaining file descriptors. */ + for (i = 0; i < fdsize; i++) { + if (fd[i] != -1) { + close(fd[i]); + } + } /* * REPLY_ACK feature handling. Other reply types has to be managed @@ -954,8 +1065,10 @@ err: qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL); close(u->slave_fd); u->slave_fd = -1; - if (fd != -1) { - close(fd); + for (i = 0; i < fdsize; i++) { + if (fd[i] != -1) { + close(fd[i]); + } } return; } @@ -1083,7 +1196,7 @@ static int vhost_user_postcopy_waker(struct PostCopyFD *pcfd, RAMBlock *rb, static int vhost_user_postcopy_advise(struct vhost_dev *dev, Error **errp) { struct vhost_user *u = dev->opaque; - CharBackend *chr = u->chr; + CharBackend *chr = u->user->chr; int ufd; VhostUserMsg msg = { .hdr.request = VHOST_USER_POSTCOPY_ADVISE, @@ -1221,7 +1334,7 @@ static int vhost_user_postcopy_notifier(NotifierWithReturn *notifier, return 0; } -static int vhost_user_init(struct vhost_dev *dev, void *opaque) +static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque) { uint64_t features, protocol_features; struct vhost_user *u; @@ -1230,7 +1343,7 @@ static int vhost_user_init(struct vhost_dev *dev, void *opaque) assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER); u = g_new0(struct vhost_user, 1); - u->chr = opaque; + u->user = opaque; u->slave_fd = -1; u->dev = dev; dev->opaque = u; @@ -1306,7 +1419,7 @@ static int vhost_user_init(struct vhost_dev *dev, void *opaque) return 0; } -static int vhost_user_cleanup(struct vhost_dev *dev) +static int vhost_user_backend_cleanup(struct vhost_dev *dev) { struct vhost_user *u; @@ -1620,10 +1733,40 @@ vhost_user_crypto_close_session(struct vhost_dev *dev, uint64_t session_id) return 0; } +static bool vhost_user_mem_section_filter(struct vhost_dev *dev, + MemoryRegionSection *section) +{ + bool result; + + result = memory_region_get_fd(section->mr) >= 0; + + return result; +} + +VhostUserState *vhost_user_init(void) +{ + VhostUserState *user = g_new0(struct VhostUserState, 1); + + return user; +} + +void vhost_user_cleanup(VhostUserState *user) +{ + int i; + + for (i = 0; i < VIRTIO_QUEUE_MAX; i++) { + if (user->notifier[i].addr) { + object_unparent(OBJECT(&user->notifier[i].mr)); + munmap(user->notifier[i].addr, qemu_real_host_page_size); + user->notifier[i].addr = NULL; + } + } +} + const VhostOps user_ops = { .backend_type = VHOST_BACKEND_TYPE_USER, - .vhost_backend_init = vhost_user_init, - .vhost_backend_cleanup = vhost_user_cleanup, + .vhost_backend_init = vhost_user_backend_init, + .vhost_backend_cleanup = vhost_user_backend_cleanup, .vhost_backend_memslots_limit = vhost_user_memslots_limit, .vhost_set_log_base = vhost_user_set_log_base, .vhost_set_mem_table = vhost_user_set_mem_table, @@ -1650,4 +1793,5 @@ const VhostOps user_ops = { .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, + .vhost_backend_mem_section_filter = vhost_user_mem_section_filter, }; diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 4565b69..96175b2 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -386,7 +386,7 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev, return r; } -static bool vhost_section(MemoryRegionSection *section) +static bool vhost_section(struct vhost_dev *dev, MemoryRegionSection *section) { bool result; bool log_dirty = memory_region_get_dirty_log_mask(section->mr) & @@ -399,6 +399,11 @@ static bool vhost_section(MemoryRegionSection *section) */ result &= !log_dirty; + if (result && dev->vhost_ops->vhost_backend_mem_section_filter) { + result &= + dev->vhost_ops->vhost_backend_mem_section_filter(dev, section); + } + trace_vhost_section(section->mr->name, result); return result; } @@ -632,7 +637,7 @@ static void vhost_region_addnop(MemoryListener *listener, struct vhost_dev *dev = container_of(listener, struct vhost_dev, memory_listener); - if (!vhost_section(section)) { + if (!vhost_section(dev, section)) { return; } vhost_region_add_section(dev, section); diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index a0c269f..04d1f8c 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -76,6 +76,7 @@ struct PCMachineState { #define PC_MACHINE_VMPORT "vmport" #define PC_MACHINE_SMM "smm" #define PC_MACHINE_NVDIMM "nvdimm" +#define PC_MACHINE_NVDIMM_CAP "nvdimm-cap" #define PC_MACHINE_SMBUS "smbus" #define PC_MACHINE_SATA "sata" #define PC_MACHINE_PIT "pit" diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h index 74c6033..3c82751 100644 --- a/include/hw/mem/nvdimm.h +++ b/include/hw/mem/nvdimm.h @@ -134,6 +134,11 @@ struct AcpiNVDIMMState { /* the IO region used by OSPM to transfer control to QEMU. */ MemoryRegion io_mr; + + /* + * Platform capabilities, section 5.2.25.9 of ACPI 6.2 Errata A + */ + int32_t capabilities; }; typedef struct AcpiNVDIMMState AcpiNVDIMMState; diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h index 5dac61f..81283ec 100644 --- a/include/hw/virtio/vhost-backend.h +++ b/include/hw/virtio/vhost-backend.h @@ -101,6 +101,9 @@ typedef int (*vhost_crypto_create_session_op)(struct vhost_dev *dev, typedef int (*vhost_crypto_close_session_op)(struct vhost_dev *dev, uint64_t session_id); +typedef bool (*vhost_backend_mem_section_filter_op)(struct vhost_dev *dev, + MemoryRegionSection *section); + typedef struct VhostOps { VhostBackendType backend_type; vhost_backend_init vhost_backend_init; @@ -138,6 +141,7 @@ typedef struct VhostOps { vhost_set_config_op vhost_set_config; vhost_crypto_create_session_op vhost_crypto_create_session; vhost_crypto_close_session_op vhost_crypto_close_session; + vhost_backend_mem_section_filter_op vhost_backend_mem_section_filter; } VhostOps; extern const VhostOps user_ops; diff --git a/include/hw/virtio/vhost-user-blk.h b/include/hw/virtio/vhost-user-blk.h index 5804cc9..d52944a 100644 --- a/include/hw/virtio/vhost-user-blk.h +++ b/include/hw/virtio/vhost-user-blk.h @@ -21,6 +21,7 @@ #include "hw/block/block.h" #include "chardev/char-fe.h" #include "hw/virtio/vhost.h" +#include "hw/virtio/vhost-user.h" #define TYPE_VHOST_USER_BLK "vhost-user-blk" #define VHOST_USER_BLK(obj) \ @@ -34,8 +35,8 @@ typedef struct VHostUserBlk { uint16_t num_queues; uint32_t queue_size; uint32_t config_wce; - uint32_t config_ro; struct vhost_dev dev; + VhostUserState *vhost_user; } VHostUserBlk; #endif diff --git a/include/hw/virtio/vhost-user-scsi.h b/include/hw/virtio/vhost-user-scsi.h index 01861f7..3ec34ae 100644 --- a/include/hw/virtio/vhost-user-scsi.h +++ b/include/hw/virtio/vhost-user-scsi.h @@ -21,6 +21,7 @@ #include "hw/qdev.h" #include "hw/virtio/virtio-scsi.h" #include "hw/virtio/vhost.h" +#include "hw/virtio/vhost-user.h" #include "hw/virtio/vhost-scsi-common.h" #define TYPE_VHOST_USER_SCSI "vhost-user-scsi" @@ -30,6 +31,7 @@ typedef struct VHostUserSCSI { VHostSCSICommon parent_obj; uint64_t host_features; + VhostUserState *vhost_user; } VHostUserSCSI; #endif /* VHOST_USER_SCSI_H */ diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h new file mode 100644 index 0000000..fd66039 --- /dev/null +++ b/include/hw/virtio/vhost-user.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017-2018 Intel Corporation + * + * This work is licensed under the terms of the GNU GPL, version 2. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_VIRTIO_VHOST_USER_H +#define HW_VIRTIO_VHOST_USER_H + +#include "chardev/char-fe.h" +#include "hw/virtio/virtio.h" + +typedef struct VhostUserHostNotifier { + MemoryRegion mr; + void *addr; + bool set; +} VhostUserHostNotifier; + +typedef struct VhostUserState { + CharBackend *chr; + VhostUserHostNotifier notifier[VIRTIO_QUEUE_MAX]; +} VhostUserState; + +VhostUserState *vhost_user_init(void); +void vhost_user_cleanup(VhostUserState *user); + +#endif diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index f65852f..3747110 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -27,7 +27,7 @@ #ifndef QEMU_VMSTATE_H #define QEMU_VMSTATE_H -#include "migration/qjson.h" +typedef struct QJSON QJSON; typedef struct VMStateInfo VMStateInfo; typedef struct VMStateDescription VMStateDescription; diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index 4165806..afc28e5 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -108,6 +108,16 @@ extern int daemon(int, int); #include "qemu/typedefs.h" /* + * According to waitpid man page: + * WCOREDUMP + * This macro is not specified in POSIX.1-2001 and is not + * available on some UNIX implementations (e.g., AIX, SunOS). + * Therefore, enclose its use inside #ifdef WCOREDUMP ... #endif. + */ +#ifndef WCOREDUMP +#define WCOREDUMP(status) 0 +#endif +/* * We have a lot of unaudited code that may fail in strange ways, or * even be a security risk during migration, if you disable assertions * at compile-time. You may comment out these safety checks if you diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c index 8819aab..eeccaff 100644 --- a/migration/block-dirty-bitmap.c +++ b/migration/block-dirty-bitmap.c @@ -66,7 +66,7 @@ #include "qemu/error-report.h" #include "migration/misc.h" #include "migration/migration.h" -#include "migration/qemu-file.h" +#include "qemu-file.h" #include "migration/vmstate.h" #include "migration/register.h" #include "qemu/hbitmap.h" diff --git a/migration/page_cache.c b/migration/page_cache.c index 96268c3..acc252b 100644 --- a/migration/page_cache.c +++ b/migration/page_cache.c @@ -18,7 +18,7 @@ #include "qapi/error.h" #include "qemu-common.h" #include "qemu/host-utils.h" -#include "migration/page_cache.h" +#include "page_cache.h" #ifdef DEBUG_CACHE #define DPRINTF(fmt, ...) \ diff --git a/migration/ram.c b/migration/ram.c index c53e836..f4e29ca 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -41,7 +41,7 @@ #include "migration/misc.h" #include "qemu-file.h" #include "postcopy-ram.h" -#include "migration/page_cache.h" +#include "page_cache.h" #include "qemu/error-report.h" #include "qapi/error.h" #include "qapi/qapi-events-migration.h" @@ -51,7 +51,7 @@ #include "exec/target_page.h" #include "qemu/rcu_queue.h" #include "migration/colo.h" -#include "migration/block.h" +#include "block.h" #include "sysemu/sysemu.h" #include "qemu/uuid.h" #include "savevm.h" diff --git a/migration/savevm.c b/migration/savevm.c index 4251125..da724c5 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -55,6 +55,7 @@ #include "io/channel-buffer.h" #include "io/channel-file.h" #include "sysemu/replay.h" +#include "qjson.h" #ifndef ETH_P_RARP #define ETH_P_RARP 0x8035 diff --git a/migration/vmstate.c b/migration/vmstate.c index f0b07f4..6b9079b 100644 --- a/migration/vmstate.c +++ b/migration/vmstate.c @@ -14,7 +14,7 @@ #include "qemu-common.h" #include "migration.h" #include "migration/vmstate.h" -#include "migration/savevm.h" +#include "savevm.h" #include "qemu-file.h" #include "qemu/bitops.h" #include "qemu/error-report.h" diff --git a/net/colo-compare.c b/net/colo-compare.c index 23b2d2c..c3a2be4 100644 --- a/net/colo-compare.c +++ b/net/colo-compare.c @@ -25,7 +25,7 @@ #include "net/queue.h" #include "chardev/char-fe.h" #include "qemu/sockets.h" -#include "net/colo.h" +#include "colo.h" #include "sysemu/iothread.h" #define TYPE_COLO_COMPARE "colo-compare" @@ -14,7 +14,7 @@ #include "qemu/osdep.h" #include "trace.h" -#include "net/colo.h" +#include "colo.h" uint32_t connection_key_hash(const void *opaque) { diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c index 62dad2d..f584e4e 100644 --- a/net/filter-rewriter.c +++ b/net/filter-rewriter.c @@ -11,7 +11,7 @@ #include "qemu/osdep.h" #include "trace.h" -#include "net/colo.h" +#include "colo.h" #include "net/filter.h" #include "net/net.h" #include "qemu-common.h" diff --git a/net/vhost-user.c b/net/vhost-user.c index fa28aad..608b837 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -12,6 +12,7 @@ #include "clients.h" #include "net/vhost_net.h" #include "net/vhost-user.h" +#include "hw/virtio/vhost-user.h" #include "chardev/char-fe.h" #include "qapi/error.h" #include "qapi/qapi-commands-net.h" @@ -23,6 +24,7 @@ typedef struct NetVhostUserState { NetClientState nc; CharBackend chr; /* only queue index 0 */ + VhostUserState *vhost_user; VHostNetState *vhost_net; guint watch; uint64_t acked_features; @@ -64,7 +66,8 @@ static void vhost_user_stop(int queues, NetClientState *ncs[]) } } -static int vhost_user_start(int queues, NetClientState *ncs[], CharBackend *be) +static int vhost_user_start(int queues, NetClientState *ncs[], + VhostUserState *be) { VhostNetOptions options; struct vhost_net *net = NULL; @@ -144,7 +147,7 @@ static ssize_t vhost_user_receive(NetClientState *nc, const uint8_t *buf, return size; } -static void vhost_user_cleanup(NetClientState *nc) +static void net_vhost_user_cleanup(NetClientState *nc) { NetVhostUserState *s = DO_UPCAST(NetVhostUserState, nc, nc); @@ -159,6 +162,11 @@ static void vhost_user_cleanup(NetClientState *nc) s->watch = 0; } qemu_chr_fe_deinit(&s->chr, true); + if (s->vhost_user) { + vhost_user_cleanup(s->vhost_user); + g_free(s->vhost_user); + s->vhost_user = NULL; + } } qemu_purge_queued_packets(nc); @@ -182,7 +190,7 @@ static NetClientInfo net_vhost_user_info = { .type = NET_CLIENT_DRIVER_VHOST_USER, .size = sizeof(NetVhostUserState), .receive = vhost_user_receive, - .cleanup = vhost_user_cleanup, + .cleanup = net_vhost_user_cleanup, .has_vnet_hdr = vhost_user_has_vnet_hdr, .has_ufo = vhost_user_has_ufo, }; @@ -244,7 +252,7 @@ static void net_vhost_user_event(void *opaque, int event) trace_vhost_user_event(chr->label, event); switch (event) { case CHR_EVENT_OPENED: - if (vhost_user_start(queues, ncs, &s->chr) < 0) { + if (vhost_user_start(queues, ncs, s->vhost_user) < 0) { qemu_chr_fe_disconnect(&s->chr); return; } @@ -283,12 +291,19 @@ static int net_vhost_user_init(NetClientState *peer, const char *device, { Error *err = NULL; NetClientState *nc, *nc0 = NULL; - NetVhostUserState *s; + VhostUserState *user = NULL; + NetVhostUserState *s = NULL; int i; assert(name); assert(queues > 0); + user = vhost_user_init(); + if (!user) { + error_report("failed to init vhost_user"); + goto err; + } + for (i = 0; i < queues; i++) { nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name); snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s", @@ -299,17 +314,19 @@ static int net_vhost_user_init(NetClientState *peer, const char *device, s = DO_UPCAST(NetVhostUserState, nc, nc); if (!qemu_chr_fe_init(&s->chr, chr, &err)) { error_report_err(err); - return -1; + goto err; } + user->chr = &s->chr; } - + s = DO_UPCAST(NetVhostUserState, nc, nc); + s->vhost_user = user; } s = DO_UPCAST(NetVhostUserState, nc, nc0); do { if (qemu_chr_fe_wait_connected(&s->chr, &err) < 0) { error_report_err(err); - return -1; + goto err; } qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, net_vhost_user_event, NULL, nc0->name, NULL, @@ -319,6 +336,17 @@ static int net_vhost_user_init(NetClientState *peer, const char *device, assert(s->vhost_net); return 0; + +err: + if (user) { + vhost_user_cleanup(user); + g_free(user); + if (s) { + s->vhost_user = NULL; + } + } + + return -1; } static Chardev *net_vhost_claim_chardev( diff --git a/qga/channel-posix.c b/qga/channel-posix.c index b812bf4..5a925a9 100644 --- a/qga/channel-posix.c +++ b/qga/channel-posix.c @@ -2,7 +2,7 @@ #include <termios.h> #include "qapi/error.h" #include "qemu/sockets.h" -#include "qga/channel.h" +#include "channel.h" #ifdef CONFIG_SOLARIS #include <stropts.h> diff --git a/qga/channel-win32.c b/qga/channel-win32.c index 7e6dc4d..b3597a8 100644 --- a/qga/channel-win32.c +++ b/qga/channel-win32.c @@ -1,8 +1,8 @@ #include "qemu/osdep.h" #include <windows.h> #include <io.h> -#include "qga/guest-agent-core.h" -#include "qga/channel.h" +#include "guest-agent-core.h" +#include "channel.h" typedef struct GAChannelReadState { guint thread_id; diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 0dc219d..eae8171 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -16,7 +16,7 @@ #include <sys/utsname.h> #include <sys/wait.h> #include <dirent.h> -#include "qga/guest-agent-core.h" +#include "guest-agent-core.h" #include "qga-qapi-commands.h" #include "qapi/error.h" #include "qapi/qmp/qerror.h" diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 2d48394..70ee537 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -32,8 +32,8 @@ #include <wtsapi32.h> #include <wininet.h> -#include "qga/guest-agent-core.h" -#include "qga/vss-win32.h" +#include "guest-agent-core.h" +#include "vss-win32.h" #include "qga-qapi-commands.h" #include "qapi/error.h" #include "qapi/qmp/qerror.h" diff --git a/qga/commands.c b/qga/commands.c index a64b34c..cce3010 100644 --- a/qga/commands.c +++ b/qga/commands.c @@ -11,7 +11,7 @@ */ #include "qemu/osdep.h" -#include "qga/guest-agent-core.h" +#include "guest-agent-core.h" #include "qga-qapi-commands.h" #include "qapi/error.h" #include "qapi/qmp/qerror.h" diff --git a/qga/guest-agent-command-state.c b/qga/guest-agent-command-state.c index e609d32..18bcb59 100644 --- a/qga/guest-agent-command-state.c +++ b/qga/guest-agent-command-state.c @@ -10,7 +10,7 @@ * See the COPYING file in the top-level directory. */ #include "qemu/osdep.h" -#include "qga/guest-agent-core.h" +#include "guest-agent-core.h" struct GACommandState { GSList *groups; @@ -23,12 +23,12 @@ #include "qapi/qmp/qdict.h" #include "qapi/qmp/qjson.h" #include "qapi/qmp/qstring.h" -#include "qga/guest-agent-core.h" +#include "guest-agent-core.h" #include "qemu/module.h" #include "qga-qapi-commands.h" #include "qapi/qmp/qerror.h" #include "qapi/error.h" -#include "qga/channel.h" +#include "channel.h" #include "qemu/bswap.h" #include "qemu/help_option.h" #include "qemu/sockets.h" diff --git a/qga/vss-win32.c b/qga/vss-win32.c index 0199c2a..a541f3a 100644 --- a/qga/vss-win32.c +++ b/qga/vss-win32.c @@ -14,9 +14,9 @@ #include <windows.h> #include "qapi/error.h" #include "qemu/error-report.h" -#include "qga/guest-agent-core.h" -#include "qga/vss-win32.h" -#include "qga/vss-win32/requester.h" +#include "guest-agent-core.h" +#include "vss-win32.h" +#include "vss-win32/requester.h" #define QGA_VSS_DLL "qga-vss.dll" diff --git a/tests/.gitignore b/tests/.gitignore index fb62d22..2bc61a9 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -21,6 +21,7 @@ test-base64 test-bdrv-drain test-bitops test-bitcnt +test-block-backend test-blockjob test-blockjob-txn test-bufferiszero diff --git a/tests/acpi-test-data/pc/NFIT.dimmpxm b/tests/acpi-test-data/pc/NFIT.dimmpxm Binary files differindex 2bfc6c5..598d331 100644 --- a/tests/acpi-test-data/pc/NFIT.dimmpxm +++ b/tests/acpi-test-data/pc/NFIT.dimmpxm diff --git a/tests/acpi-test-data/q35/NFIT.dimmpxm b/tests/acpi-test-data/q35/NFIT.dimmpxm Binary files differindex 2bfc6c5..598d331 100644 --- a/tests/acpi-test-data/q35/NFIT.dimmpxm +++ b/tests/acpi-test-data/q35/NFIT.dimmpxm diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c index bf3e193..256d463 100644 --- a/tests/bios-tables-test.c +++ b/tests/bios-tables-test.c @@ -830,7 +830,7 @@ static void test_acpi_tcg_dimm_pxm(const char *machine) memset(&data, 0, sizeof(data)); data.machine = machine; data.variant = ".dimmpxm"; - test_acpi_one(" -machine nvdimm=on" + test_acpi_one(" -machine nvdimm=on,nvdimm-cap=3" " -smp 4,sockets=4" " -m 128M,slots=3,maxmem=1G" " -numa node,mem=32M,nodeid=0" diff --git a/tests/libqtest.c b/tests/libqtest.c index e0ca19d..098af6a 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -103,8 +103,15 @@ static int socket_accept(int sock) static void kill_qemu(QTestState *s) { if (s->qemu_pid != -1) { + int wstatus = 0; + pid_t pid; + kill(s->qemu_pid, SIGTERM); - waitpid(s->qemu_pid, NULL, 0); + pid = waitpid(s->qemu_pid, &wstatus, 0); + + if (pid == s->qemu_pid && WIFSIGNALED(wstatus)) { + assert(!WCOREDUMP(wstatus)); + } } } diff --git a/tests/vhost-user-bridge.c b/tests/vhost-user-bridge.c index e0605a5..0884294 100644 --- a/tests/vhost-user-bridge.c +++ b/tests/vhost-user-bridge.c @@ -29,6 +29,7 @@ #define _FILE_OFFSET_BITS 64 +#include "qemu/atomic.h" #include "qemu/osdep.h" #include "qemu/iov.h" #include "standard-headers/linux/virtio_net.h" @@ -65,6 +66,11 @@ typedef struct VubrDev { int sock; int ready; int quit; + struct { + int fd; + void *addr; + pthread_t thread; + } notifier; } VubrDev; static void @@ -445,14 +451,22 @@ static uint64_t vubr_get_features(VuDev *dev) { return 1ULL << VIRTIO_NET_F_GUEST_ANNOUNCE | - 1ULL << VIRTIO_NET_F_MRG_RXBUF; + 1ULL << VIRTIO_NET_F_MRG_RXBUF | + 1ULL << VIRTIO_F_VERSION_1; } static void vubr_queue_set_started(VuDev *dev, int qidx, bool started) { + VubrDev *vubr = container_of(dev, VubrDev, vudev); VuVirtq *vq = vu_get_queue(dev, qidx); + if (started && vubr->notifier.fd >= 0) { + vu_set_queue_host_notifier(dev, vq, vubr->notifier.fd, + getpagesize(), + qidx * getpagesize()); + } + if (qidx % 2 == 1) { vu_set_queue_handler(dev, vq, started ? vubr_handle_tx : NULL); } @@ -522,6 +536,8 @@ vubr_new(const char *path, bool client) vubr_die("socket"); } + dev->notifier.fd = -1; + un.sun_family = AF_UNIX; strcpy(un.sun_path, path); len = sizeof(un.sun_family) + strlen(path); @@ -559,6 +575,73 @@ vubr_new(const char *path, bool client) return dev; } +static void *notifier_thread(void *arg) +{ + VuDev *dev = (VuDev *)arg; + VubrDev *vubr = container_of(dev, VubrDev, vudev); + int pagesize = getpagesize(); + int qidx; + + while (true) { + for (qidx = 0; qidx < VHOST_MAX_NR_VIRTQUEUE; qidx++) { + uint16_t *n = vubr->notifier.addr + pagesize * qidx; + + if (*n == qidx) { + *n = 0xffff; + /* We won't miss notifications if we reset + * the memory first. */ + smp_mb(); + + DPRINT("Got a notification for queue%d via host notifier.\n", + qidx); + + if (qidx % 2 == 1) { + vubr_handle_tx(dev, qidx); + } + } + usleep(1000); + } + } + + return NULL; +} + +static void +vubr_host_notifier_setup(VubrDev *dev) +{ + char template[] = "/tmp/vubr-XXXXXX"; + pthread_t thread; + size_t length; + void *addr; + int fd; + + length = getpagesize() * VHOST_MAX_NR_VIRTQUEUE; + + fd = mkstemp(template); + if (fd < 0) { + vubr_die("mkstemp()"); + } + + if (posix_fallocate(fd, 0, length) != 0) { + vubr_die("posix_fallocate()"); + } + + addr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (addr == MAP_FAILED) { + vubr_die("mmap()"); + } + + memset(addr, 0xff, length); + + if (pthread_create(&thread, NULL, notifier_thread, &dev->vudev) != 0) { + vubr_die("pthread_create()"); + } + + dev->notifier.fd = fd; + dev->notifier.addr = addr; + dev->notifier.thread = thread; +} + static void vubr_set_host(struct sockaddr_in *saddr, const char *host) { @@ -673,8 +756,9 @@ main(int argc, char *argv[]) VubrDev *dev; int opt; bool client = false; + bool host_notifier = false; - while ((opt = getopt(argc, argv, "l:r:u:c")) != -1) { + while ((opt = getopt(argc, argv, "l:r:u:cH")) != -1) { switch (opt) { case 'l': @@ -693,6 +777,9 @@ main(int argc, char *argv[]) case 'c': client = true; break; + case 'H': + host_notifier = true; + break; default: goto out; } @@ -708,6 +795,10 @@ main(int argc, char *argv[]) return 1; } + if (host_notifier) { + vubr_host_notifier_setup(dev); + } + vubr_backend_udp_setup(dev, lhost, lport, rhost, rport); vubr_run(dev); @@ -717,7 +808,7 @@ main(int argc, char *argv[]) out: fprintf(stderr, "Usage: %s ", argv[0]); - fprintf(stderr, "[-c] [-u ud_socket_path] [-l lhost:lport] [-r rhost:rport]\n"); + fprintf(stderr, "[-c] [-H] [-u ud_socket_path] [-l lhost:lport] [-r rhost:rport]\n"); fprintf(stderr, "\t-u path to unix doman socket. default: %s\n", DEFAULT_UD_SOCKET); fprintf(stderr, "\t-l local host and port. default: %s:%s\n", @@ -725,6 +816,7 @@ out: fprintf(stderr, "\t-r remote host and port. default: %s:%s\n", DEFAULT_RHOST, DEFAULT_RPORT); fprintf(stderr, "\t-c client mode\n"); + fprintf(stderr, "\t-H use host notifier\n"); return 1; } diff --git a/trace/control.h b/trace/control.h index 1903e22..eb65c8e 100644 --- a/trace/control.h +++ b/trace/control.h @@ -267,6 +267,6 @@ char *trace_opt_parse(const char *optarg); uint32_t trace_get_vcpu_event_count(void); -#include "trace/control-internal.h" +#include "control-internal.h" #endif /* TRACE__CONTROL_H */ diff --git a/trace/qmp.c b/trace/qmp.c index 756086c..ea99b00 100644 --- a/trace/qmp.c +++ b/trace/qmp.c @@ -10,7 +10,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qapi/qapi-commands-trace.h" -#include "trace/control.h" +#include "control.h" static CPUState *get_cpu(bool has_vcpu, int vcpu, Error **errp) @@ -66,7 +66,7 @@ #define VC_SCALE_STEP 0.25 #ifdef GDK_WINDOWING_X11 -#include "ui/x_keymap.h" +#include "x_keymap.h" /* Gtk2 compat */ #ifndef GDK_IS_X11_DISPLAY diff --git a/ui/input-keymap.c b/ui/input-keymap.c index 3d4e66b..87cc301 100644 --- a/ui/input-keymap.c +++ b/ui/input-keymap.c @@ -1,6 +1,6 @@ #include "qemu/osdep.h" #include "sysemu/sysemu.h" -#include "ui/keymaps.h" +#include "keymaps.h" #include "ui/input.h" #include "standard-headers/linux/input.h" diff --git a/ui/input-legacy.c b/ui/input-legacy.c index e5d4db1..549654e 100644 --- a/ui/input-legacy.c +++ b/ui/input-legacy.c @@ -26,7 +26,7 @@ #include "qapi/qapi-commands-ui.h" #include "sysemu/sysemu.h" #include "ui/console.h" -#include "ui/keymaps.h" +#include "keymaps.h" #include "ui/input.h" struct QEMUPutMouseEntry { diff --git a/ui/spice-input.c b/ui/spice-input.c index 3d41aa1..a426c03 100644 --- a/ui/spice-input.c +++ b/ui/spice-input.c @@ -23,7 +23,7 @@ #include "qemu-common.h" #include "ui/qemu-spice.h" #include "ui/console.h" -#include "ui/keymaps.h" +#include "keymaps.h" #include "ui/input.h" /* keyboard bits */ |