From 51387394334843ebff79dc7db94ad19d71f98bb9 Mon Sep 17 00:00:00 2001 From: Frederick Mayle Date: Wed, 18 Oct 2023 14:03:55 -0700 Subject: snapshot/restore the vrings Wifi still doesn't completely work: when a CF device is restored, it can see the virtual wifi networks but fails to connect to them. Bug: 295028005 Test: do CF snapshot/restore flow with wifi enabled Change-Id: I28fe3385cf09eef4d489c78771c65af8e0ad0689 --- wmediumd/inc/usfstl/vhost.h | 7 +++++ wmediumd/inc/usfstl/vhostproto.h | 15 +++++++++- wmediumd/lib/vhost.c | 61 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 79 insertions(+), 4 deletions(-) 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 @@ -140,6 +140,13 @@ void usfstl_vhost_user_config_changed(struct usfstl_vhost_user_dev *dev); */ 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 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 @@ struct vhost_user_region { uint64_t mmap_offset; }; +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 { - int8_t sleeping[NUM_SNAPSHOT_QUEUES]; + 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 @@ struct usfstl_vhost_user_dev_int { 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 @@ static void usfstl_vhost_user_handle_msg(struct usfstl_loop_entry *entry) 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 @@ static void usfstl_vhost_user_handle_msg(struct usfstl_loop_entry *entry) 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 @@ static void usfstl_vhost_user_handle_msg(struct usfstl_loop_entry *entry) 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 @@ void *usfstl_vhost_user_to_va(struct usfstl_vhost_user_dev *extdev, uint64_t add 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; -- cgit v1.2.3