aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElie Kheirallah <khei@google.com>2023-10-23 19:10:37 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-10-23 19:10:37 +0000
commit4c88633a8cccd22a6cd9754c87b90337dcda7507 (patch)
treed559ec0e5fdd4a84b23978cd21635a10d39dad38
parentf7c85d76bd293788949b470db064c34e434998e1 (diff)
parent89da3783ed0748072d6c3187e2fa2d8a10b0766e (diff)
downloadwmediumd-4c88633a8cccd22a6cd9754c87b90337dcda7507.tar.gz
Add vhost-user snapshot support to wmediumd am: 89da3783ed
Original change: https://android-review.googlesource.com/c/platform/external/wmediumd/+/2759933 Change-Id: I72669d0783ca5e4df4d7f3d17d1cc375904bc611 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--wmediumd/inc/usfstl/vhostproto.h20
-rw-r--r--wmediumd/lib/vhost.c58
2 files changed, 78 insertions, 0 deletions
diff --git a/wmediumd/inc/usfstl/vhostproto.h b/wmediumd/inc/usfstl/vhostproto.h
index 4550179..579af54 100644
--- a/wmediumd/inc/usfstl/vhostproto.h
+++ b/wmediumd/inc/usfstl/vhostproto.h
@@ -8,6 +8,10 @@
#define MAX_REGIONS 8
+// For simplicity, we only support snapshotting a fixed number of queues. Should
+// be equal to HWSIM_NUM_VQS.
+#define NUM_SNAPSHOT_QUEUES 2
+
/* these are from the vhost-user spec */
struct vhost_user_msg_hdr {
@@ -29,11 +33,16 @@ struct vhost_user_region {
uint64_t mmap_offset;
};
+struct vhost_user_snapshot {
+ int8_t sleeping[NUM_SNAPSHOT_QUEUES];
+};
+
struct vhost_user_msg {
struct vhost_user_msg_hdr hdr;
union {
#define VHOST_USER_U64_VRING_IDX_MSK 0x7f
#define VHOST_USER_U64_NO_FD 0x80
+ int8_t i8;
uint64_t u64;
struct {
uint32_t idx, num;
@@ -63,6 +72,13 @@ struct vhost_user_msg {
uint64_t size;
uint64_t offset;
} vring_area;
+ struct {
+ int8_t bool_store;
+ struct vhost_user_snapshot snapshot;
+ } __attribute__((packed)) snapshot_response;
+ struct {
+ struct vhost_user_snapshot snapshot;
+ } __attribute__((packed)) restore_request;
} __attribute__((packed)) payload;
};
@@ -82,6 +98,10 @@ struct vhost_user_msg {
#define VHOST_USER_GET_CONFIG 24
#define VHOST_USER_VRING_KICK 35
#define VHOST_USER_GET_SHARED_MEMORY_REGIONS 41
+#define VHOST_USER_SLEEP 42
+#define VHOST_USER_WAKE 43
+#define VHOST_USER_SNAPSHOT 44
+#define VHOST_USER_RESTORE 45
#define VHOST_USER_SLAVE_CONFIG_CHANGE_MSG 2
#define VHOST_USER_SLAVE_VRING_CALL 4
diff --git a/wmediumd/lib/vhost.c b/wmediumd/lib/vhost.c
index b6a7a70..7e177ac 100644
--- a/wmediumd/lib/vhost.c
+++ b/wmediumd/lib/vhost.c
@@ -41,6 +41,7 @@ struct usfstl_vhost_user_dev_int {
struct {
struct usfstl_loop_entry entry;
bool enabled;
+ bool sleeping;
bool triggered;
struct vring virtq;
int call_fd;
@@ -673,6 +674,63 @@ static void usfstl_vhost_user_handle_msg(struct usfstl_loop_entry *entry)
reply_len = sizeof(uint64_t);
msg.payload.u64 = 0;
break;
+ case VHOST_USER_SLEEP:
+ USFSTL_ASSERT_EQ(len, (ssize_t)0, "%zd");
+ USFSTL_ASSERT_EQ(dev->ext.server->max_queues, NUM_SNAPSHOT_QUEUES, "%d");
+ for (virtq = 0; virtq < dev->ext.server->max_queues; virtq++) {
+ if (dev->virtqs[virtq].enabled) {
+ dev->virtqs[virtq].enabled = false;
+ dev->virtqs[virtq].sleeping = true;
+ usfstl_loop_unregister(&dev->virtqs[virtq].entry);
+ }
+ }
+ break;
+ case VHOST_USER_WAKE:
+ USFSTL_ASSERT_EQ(len, (ssize_t)0, "%zd");
+ USFSTL_ASSERT_EQ(dev->ext.server->max_queues, NUM_SNAPSHOT_QUEUES, "%d");
+ // enable previously enabled queues on wake
+ for (virtq = 0; virtq < dev->ext.server->max_queues; virtq++) {
+ if (dev->virtqs[virtq].sleeping) {
+ dev->virtqs[virtq].enabled = true;
+ dev->virtqs[virtq].sleeping = false;
+ usfstl_loop_register(&dev->virtqs[virtq].entry);
+ // TODO: is this needed?
+ usfstl_vhost_user_virtq_kick(dev, virtq);
+ }
+ }
+ break;
+ case VHOST_USER_SNAPSHOT: {
+ USFSTL_ASSERT_EQ(len, (ssize_t)0, "%zd");
+ USFSTL_ASSERT_EQ(dev->ext.server->max_queues, NUM_SNAPSHOT_QUEUES, "%d");
+ for (virtq = 0; virtq < dev->ext.server->max_queues; virtq++) {
+ msg.payload.snapshot_response.snapshot.sleeping[virtq] = dev->virtqs[virtq].sleeping;
+ }
+ msg.payload.snapshot_response.bool_store = 1;
+ reply_len = (int)sizeof(msg.payload.snapshot_response);
+ break;
+ }
+ case VHOST_USER_RESTORE: {
+ int *fds;
+ USFSTL_ASSERT(len == (int)sizeof(msg.payload.restore_request));
+ USFSTL_ASSERT_EQ(dev->ext.server->max_queues, NUM_SNAPSHOT_QUEUES, "%d");
+
+ fds = (int*)malloc(dev->ext.server->max_queues * sizeof(int));
+ for (virtq = 0; virtq < dev->ext.server->max_queues; virtq++) {
+ fds[virtq] = -1;
+ }
+ usfstl_vhost_user_get_msg_fds(&msghdr, fds, 2);
+
+ for (virtq = 0; virtq < dev->ext.server->max_queues; virtq++) {
+ dev->virtqs[virtq].sleeping = msg.payload.restore_request.snapshot.sleeping[virtq];
+ dev->virtqs[virtq].entry.fd = fds[virtq];
+ }
+
+ free(fds);
+
+ msg.payload.i8 = 1; // success
+ reply_len = sizeof(msg.payload.i8);
+ break;
+ }
default:
USFSTL_ASSERT(0, "Unsupported message: %d\n", msg.hdr.request);
}