acpi, vhost, misc: fixes, features
vDPA support, fix to vhost blk RO bit handling, some include path cleanups, NFIT ACPI table. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- iQEcBAABAgAGBQJbEXNvAAoJECgfDbjSjVRpc8gH/R8xrcFrV+k9wwbgYcOcGb6Y LWjseE31pqJcxRV80vLOdzYEuLStZQKQQY7xBDMlA5vdyvZxIA6FLO2IsiJSbFAk EK8pclwhpwQAahr8BfzenabohBv2UO7zu5+dqSvuJCiMWF3jGtPAIMxInfjXaOZY odc1zY2D2EgsC7wZZ1hfraRbISBOiRaez9BoGDKPOyBY9G1ASEgxJgleFgoBLfsK a1XU+fDM6hAVdxftfkTm0nibyf7PWPDyzqghLqjR9WXLvZP3Cqud4p8N29mY51pR KSTjA4FYk6Z9EVMltyBHfdJs6RQzglKjxcNGdlrvacDfyFi79fGdiosVllrjfJM= =3+V0 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging acpi, vhost, misc: fixes, features vDPA support, fix to vhost blk RO bit handling, some include path cleanups, NFIT ACPI table. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Fri 01 Jun 2018 17:25:19 BST # 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: (31 commits) vhost-blk: turn on pre-defined RO feature bit ACPI testing: test NFIT platform capabilities nvdimm, acpi: support NFIT platform capabilities tests/.gitignore: add entry for generated file arch_init: sort architectures ui: use local path for local headers qga: use local path for local headers colo: use local path for local headers migration: use local path for local headers usb: use local path for local headers sd: fix up include vhost-scsi: drop an unused include ppc: use local path for local headers rocker: drop an unused include e1000e: use local path for local headers ioapic: fix up includes ide: use local path for local headers display: use local path for local headers trace: use local path for local headers migration: drop an unused include ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
						commit
						f67c9b693a
					
				
							
								
								
									
										16
									
								
								arch_init.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								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; | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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 */ | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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" | ||||
| 
 | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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: | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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 { | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -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: | ||||
|  | ||||
| @ -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); | ||||
| 
 | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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 { | ||||
|  | ||||
| @ -18,7 +18,7 @@ | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include "crypto/ivgenpriv.h" | ||||
| #include "ivgenpriv.h" | ||||
| 
 | ||||
| #ifndef QCRYPTO_IVGEN_ESSIV_H__ | ||||
| #define QCRYPTO_IVGEN_ESSIV_H__ | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -18,7 +18,7 @@ | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include "crypto/ivgenpriv.h" | ||||
| #include "ivgenpriv.h" | ||||
| 
 | ||||
| #ifndef QCRYPTO_IVGEN_PLAIN_H__ | ||||
| #define QCRYPTO_IVGEN_PLAIN_H__ | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -18,7 +18,7 @@ | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include "crypto/ivgenpriv.h" | ||||
| #include "ivgenpriv.h" | ||||
| 
 | ||||
| #ifndef QCRYPTO_IVGEN_PLAIN64_H__ | ||||
| #define QCRYPTO_IVGEN_PLAIN64_H__ | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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. | ||||
|  | ||||
| @ -169,6 +169,21 @@ struct NvdimmNfitControlRegion { | ||||
| } QEMU_PACKED; | ||||
| 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 | ||||
| @ -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, | ||||
|  | ||||
| @ -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(), | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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 *); | ||||
| 
 | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
							
								
								
									
										31
									
								
								hw/i386/pc.c
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								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); | ||||
| 
 | ||||
|  | ||||
| @ -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" | ||||
| 
 | ||||
|  | ||||
| @ -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" | ||||
| 
 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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 */ | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| #include "qemu/osdep.h" | ||||
| #include "hw/usb.h" | ||||
| #include "hw/usb/desc.h" | ||||
| #include "desc.h" | ||||
| 
 | ||||
| /*
 | ||||
|  * Microsoft OS Descriptors | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| #include "qemu/osdep.h" | ||||
| 
 | ||||
| #include "hw/usb.h" | ||||
| #include "hw/usb/desc.h" | ||||
| #include "desc.h" | ||||
| #include "trace.h" | ||||
| 
 | ||||
| /* ------------------------------------------------------------------ */ | ||||
|  | ||||
| @ -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" | ||||
| 
 | ||||
|  | ||||
| @ -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" | ||||
| 
 | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -24,7 +24,7 @@ | ||||
| #include "qemu/iov.h" | ||||
| #include "trace.h" | ||||
| #include "hw/usb.h" | ||||
| #include "hw/usb/desc.h" | ||||
| #include "desc.h" | ||||
| 
 | ||||
| /* ----------------------------------------------------------------------- */ | ||||
| 
 | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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" | ||||
| 
 | ||||
|  | ||||
| @ -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" | ||||
| 
 | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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" | ||||
| 
 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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) | ||||
| { | ||||
| } | ||||
|  | ||||
| @ -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, | ||||
| }; | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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 */ | ||||
|  | ||||
							
								
								
									
										28
									
								
								include/hw/virtio/vhost-user.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								include/hw/virtio/vhost-user.h
									
									
									
									
									
										Normal file
									
								
							| @ -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 | ||||
| @ -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; | ||||
|  | ||||
| @ -107,6 +107,16 @@ extern int daemon(int, int); | ||||
| #include "glib-compat.h" | ||||
| #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 | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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, ...) \ | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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) | ||||
| { | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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( | ||||
|  | ||||
| @ -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> | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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" | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										1
									
								
								tests/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								tests/.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -21,6 +21,7 @@ test-base64 | ||||
| test-bdrv-drain | ||||
| test-bitops | ||||
| test-bitcnt | ||||
| test-block-backend | ||||
| test-blockjob | ||||
| test-blockjob-txn | ||||
| test-bufferiszero | ||||
|  | ||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -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" | ||||
|  | ||||
| @ -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)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
| } | ||||
|  | ||||
| @ -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 */ | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Peter Maydell
						Peter Maydell