snapshot/restore the vrings am: 5138739433 am: d12c03eb48 am: 1bc3442715

Original change: https://android-review.googlesource.com/c/platform/external/wmediumd/+/2794978

Change-Id: I6c24a9599be8c4b9877ad220cbfddecab70bd4fd
Signed-off-by: Automerger Merge Worker <[email protected]>
diff --git a/wmediumd/inc/usfstl/vhost.h b/wmediumd/inc/usfstl/vhost.h
index 017d0b5..85a76d9 100644
--- a/wmediumd/inc/usfstl/vhost.h
+++ b/wmediumd/inc/usfstl/vhost.h
@@ -141,6 +141,13 @@
 void *usfstl_vhost_user_to_va(struct usfstl_vhost_user_dev *dev, uint64_t addr);
 
 /**
+ * usfstl_vhost_user_to_va - translate address
+ * @dev: device to translate address for
+ * @addr: host-side virtual addr
+ */
+uint64_t usfstl_vhost_user_to_phys(struct usfstl_vhost_user_dev *dev, uint64_t addr);
+
+/**
  * usfstl_vhost_phys_to_va - translate address
  * @dev: device to translate address for
  * @addr: guest-side physical addr
diff --git a/wmediumd/inc/usfstl/vhostproto.h b/wmediumd/inc/usfstl/vhostproto.h
index 579af54..28756fa 100644
--- a/wmediumd/inc/usfstl/vhostproto.h
+++ b/wmediumd/inc/usfstl/vhostproto.h
@@ -33,10 +33,23 @@
 	uint64_t mmap_offset;
 };
 
-struct vhost_user_snapshot {
-	int8_t sleeping[NUM_SNAPSHOT_QUEUES];
+struct vring_snapshot {
+	int8_t enabled;
+	int8_t sleeping;
+	int8_t triggered;
+
+	unsigned int num;
+	uint64_t desc_guest_addr;
+	uint64_t avail_guest_addr;
+	uint64_t used_guest_addr;
+	uint16_t last_avail_idx;
 };
 
+struct vhost_user_snapshot {
+	struct vring_snapshot vrings[NUM_SNAPSHOT_QUEUES];
+};
+
+
 struct vhost_user_msg {
 	struct vhost_user_msg_hdr hdr;
 	union {
diff --git a/wmediumd/lib/vhost.c b/wmediumd/lib/vhost.c
index 7e177ac..4e13012 100644
--- a/wmediumd/lib/vhost.c
+++ b/wmediumd/lib/vhost.c
@@ -43,6 +43,9 @@
 		bool enabled;
 		bool sleeping;
 		bool triggered;
+		uint64_t desc_guest_addr;
+		uint64_t avail_guest_addr;
+		uint64_t used_guest_addr;
 		struct vring virtq;
 		int call_fd;
 		uint16_t last_avail_idx;
@@ -579,6 +582,15 @@
 			      dev->ext.server->max_queues);
 		USFSTL_ASSERT_EQ(msg.payload.vring_addr.flags, (uint32_t)0, "0x%x");
 		USFSTL_ASSERT(!dev->virtqs[msg.payload.vring_addr.idx].enabled);
+
+		// Save the guest physical addresses to make snapshotting more convenient.
+		dev->virtqs[msg.payload.vring_addr.idx].desc_guest_addr =
+			usfstl_vhost_user_to_phys(&dev->ext, msg.payload.vring_addr.descriptor);
+		dev->virtqs[msg.payload.vring_addr.idx].used_guest_addr =
+			usfstl_vhost_user_to_phys(&dev->ext, msg.payload.vring_addr.used);
+		dev->virtqs[msg.payload.vring_addr.idx].avail_guest_addr =
+			usfstl_vhost_user_to_phys(&dev->ext, msg.payload.vring_addr.avail);
+
 		dev->virtqs[msg.payload.vring_addr.idx].last_avail_idx = 0;
 		dev->virtqs[msg.payload.vring_addr.idx].virtq.desc =
 			usfstl_vhost_user_to_va(&dev->ext,
@@ -703,7 +715,15 @@
 		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;
+			struct vring_snapshot* snapshot = &msg.payload.snapshot_response.snapshot.vrings[virtq];
+			snapshot->enabled = dev->virtqs[virtq].enabled;
+			snapshot->sleeping = dev->virtqs[virtq].sleeping;
+			snapshot->triggered = dev->virtqs[virtq].triggered;
+			snapshot->num = dev->virtqs[virtq].virtq.num;
+			snapshot->desc_guest_addr = dev->virtqs[virtq].desc_guest_addr;
+			snapshot->avail_guest_addr = dev->virtqs[virtq].avail_guest_addr;
+			snapshot->used_guest_addr = dev->virtqs[virtq].used_guest_addr;
+			snapshot->last_avail_idx = dev->virtqs[virtq].last_avail_idx;
 		}
 		msg.payload.snapshot_response.bool_store = 1;
 		reply_len = (int)sizeof(msg.payload.snapshot_response);
@@ -721,8 +741,25 @@
 		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];
+			const struct vring_snapshot* snapshot = &msg.payload.snapshot_response.snapshot.vrings[virtq];
+			dev->virtqs[virtq].enabled = snapshot->enabled;
+			dev->virtqs[virtq].sleeping = snapshot->sleeping;
+			dev->virtqs[virtq].triggered = snapshot->triggered;
+			dev->virtqs[virtq].virtq.num = snapshot->num;
+			dev->virtqs[virtq].desc_guest_addr = snapshot->desc_guest_addr;
+			dev->virtqs[virtq].avail_guest_addr = snapshot->avail_guest_addr;
+			dev->virtqs[virtq].used_guest_addr = snapshot->used_guest_addr;
+			dev->virtqs[virtq].last_avail_idx = snapshot->last_avail_idx;
+
 			dev->virtqs[virtq].entry.fd = fds[virtq];
+
+			// Translate vring guest physical addresses.
+			dev->virtqs[virtq].virtq.desc = usfstl_vhost_phys_to_va(&dev->ext, dev->virtqs[virtq].desc_guest_addr);
+			dev->virtqs[virtq].virtq.used = usfstl_vhost_phys_to_va(&dev->ext, dev->virtqs[virtq].used_guest_addr);
+			dev->virtqs[virtq].virtq.avail = usfstl_vhost_phys_to_va(&dev->ext, dev->virtqs[virtq].avail_guest_addr);
+			USFSTL_ASSERT(dev->virtqs[virtq].virtq.avail &&
+				      dev->virtqs[virtq].virtq.desc &&
+				      dev->virtqs[virtq].virtq.used);
 		}
 
 		free(fds);
@@ -901,11 +938,29 @@
 				dev->regions[region].user_addr +
 				dev->regions[region].mmap_offset);
 	}
-
 	USFSTL_ASSERT(0, "cannot translate user address %"PRIx64"\n", addr);
 	return NULL;
 }
 
+uint64_t usfstl_vhost_user_to_phys(struct usfstl_vhost_user_dev *extdev, uint64_t addr)
+{
+	struct usfstl_vhost_user_dev_int *dev;
+	unsigned int region;
+
+	dev = container_of(extdev, struct usfstl_vhost_user_dev_int, ext);
+
+	for (region = 0; region < dev->n_regions; region++) {
+		if (addr >= dev->regions[region].user_addr &&
+		    addr < dev->regions[region].user_addr +
+			   dev->regions[region].size)
+			return addr -
+				dev->regions[region].user_addr +
+				dev->regions[region].guest_phys_addr;
+	}
+	USFSTL_ASSERT(0, "cannot translate user address %"PRIx64"\n", addr);
+	return 0;
+}
+
 void *usfstl_vhost_phys_to_va(struct usfstl_vhost_user_dev *extdev, uint64_t addr)
 {
 	struct usfstl_vhost_user_dev_int *dev;