vhost: export APIs for live migration support
Export few APIs for the vhost-user driver to log the guest memory writes, which is a must for live migration support. This patch basically moves vhost_log_write() and vhost_log_used_vring() into vhost.h and then add an wrapper (the public API) to them. Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com> Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
This commit is contained in:
parent
abd53c16b6
commit
52f8091f05
@ -41,5 +41,7 @@ DPDK_17.05 {
|
||||
rte_vhost_get_vhost_vring;
|
||||
rte_vhost_get_vring_num;
|
||||
rte_vhost_gpa_to_vva;
|
||||
rte_vhost_log_used_vring;
|
||||
rte_vhost_log_write;
|
||||
|
||||
} DPDK_16.07;
|
||||
|
@ -132,6 +132,49 @@ rte_vhost_gpa_to_vva(struct rte_vhost_memory *mem, uint64_t gpa)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RTE_VHOST_NEED_LOG(features) ((features) & (1ULL << VHOST_F_LOG_ALL))
|
||||
|
||||
/**
|
||||
* Log the memory write start with given address.
|
||||
*
|
||||
* This function only need be invoked when the live migration starts.
|
||||
* Therefore, we won't need call it at all in the most of time. For
|
||||
* making the performance impact be minimum, it's suggested to do a
|
||||
* check before calling it:
|
||||
*
|
||||
* if (unlikely(RTE_VHOST_NEED_LOG(features)))
|
||||
* rte_vhost_log_write(vid, addr, len);
|
||||
*
|
||||
* @param vid
|
||||
* vhost device ID
|
||||
* @param addr
|
||||
* the starting address for write
|
||||
* @param len
|
||||
* the length to write
|
||||
*/
|
||||
void rte_vhost_log_write(int vid, uint64_t addr, uint64_t len);
|
||||
|
||||
/**
|
||||
* Log the used ring update start at given offset.
|
||||
*
|
||||
* Same as rte_vhost_log_write, it's suggested to do a check before
|
||||
* calling it:
|
||||
*
|
||||
* if (unlikely(RTE_VHOST_NEED_LOG(features)))
|
||||
* rte_vhost_log_used_vring(vid, vring_idx, offset, len);
|
||||
*
|
||||
* @param vid
|
||||
* vhost device ID
|
||||
* @param vring_idx
|
||||
* the vring index
|
||||
* @param offset
|
||||
* the offset inside the used ring
|
||||
* @param len
|
||||
* the length to write
|
||||
*/
|
||||
void rte_vhost_log_used_vring(int vid, uint16_t vring_idx,
|
||||
uint64_t offset, uint64_t len);
|
||||
|
||||
int rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable);
|
||||
|
||||
/**
|
||||
|
@ -444,3 +444,34 @@ rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable)
|
||||
dev->virtqueue[queue_id]->used->flags = VRING_USED_F_NO_NOTIFY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rte_vhost_log_write(int vid, uint64_t addr, uint64_t len)
|
||||
{
|
||||
struct virtio_net *dev = get_device(vid);
|
||||
|
||||
if (dev == NULL)
|
||||
return;
|
||||
|
||||
vhost_log_write(dev, addr, len);
|
||||
}
|
||||
|
||||
void
|
||||
rte_vhost_log_used_vring(int vid, uint16_t vring_idx,
|
||||
uint64_t offset, uint64_t len)
|
||||
{
|
||||
struct virtio_net *dev;
|
||||
struct vhost_virtqueue *vq;
|
||||
|
||||
dev = get_device(vid);
|
||||
if (dev == NULL)
|
||||
return;
|
||||
|
||||
if (vring_idx >= VHOST_MAX_VRING)
|
||||
return;
|
||||
vq = dev->virtqueue[vring_idx];
|
||||
if (!vq)
|
||||
return;
|
||||
|
||||
vhost_log_used_vring(dev, vq, offset, len);
|
||||
}
|
||||
|
@ -198,6 +198,44 @@ struct virtio_net {
|
||||
struct guest_page *guest_pages;
|
||||
} __rte_cache_aligned;
|
||||
|
||||
|
||||
#define VHOST_LOG_PAGE 4096
|
||||
|
||||
static inline void __attribute__((always_inline))
|
||||
vhost_log_page(uint8_t *log_base, uint64_t page)
|
||||
{
|
||||
log_base[page / 8] |= 1 << (page % 8);
|
||||
}
|
||||
|
||||
static inline void __attribute__((always_inline))
|
||||
vhost_log_write(struct virtio_net *dev, uint64_t addr, uint64_t len)
|
||||
{
|
||||
uint64_t page;
|
||||
|
||||
if (likely(((dev->features & (1ULL << VHOST_F_LOG_ALL)) == 0) ||
|
||||
!dev->log_base || !len))
|
||||
return;
|
||||
|
||||
if (unlikely(dev->log_size <= ((addr + len - 1) / VHOST_LOG_PAGE / 8)))
|
||||
return;
|
||||
|
||||
/* To make sure guest memory updates are committed before logging */
|
||||
rte_smp_wmb();
|
||||
|
||||
page = addr / VHOST_LOG_PAGE;
|
||||
while (page * VHOST_LOG_PAGE < addr + len) {
|
||||
vhost_log_page((uint8_t *)(uintptr_t)dev->log_base, page);
|
||||
page += 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __attribute__((always_inline))
|
||||
vhost_log_used_vring(struct virtio_net *dev, struct vhost_virtqueue *vq,
|
||||
uint64_t offset, uint64_t len)
|
||||
{
|
||||
vhost_log_write(dev, vq->log_guest_addr + offset, len);
|
||||
}
|
||||
|
||||
/* Macros for printing using RTE_LOG */
|
||||
#define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1
|
||||
#define RTE_LOGTYPE_VHOST_DATA RTE_LOGTYPE_USER1
|
||||
|
@ -48,42 +48,6 @@
|
||||
#include "vhost.h"
|
||||
|
||||
#define MAX_PKT_BURST 32
|
||||
#define VHOST_LOG_PAGE 4096
|
||||
|
||||
static inline void __attribute__((always_inline))
|
||||
vhost_log_page(uint8_t *log_base, uint64_t page)
|
||||
{
|
||||
log_base[page / 8] |= 1 << (page % 8);
|
||||
}
|
||||
|
||||
static inline void __attribute__((always_inline))
|
||||
vhost_log_write(struct virtio_net *dev, uint64_t addr, uint64_t len)
|
||||
{
|
||||
uint64_t page;
|
||||
|
||||
if (likely(((dev->features & (1ULL << VHOST_F_LOG_ALL)) == 0) ||
|
||||
!dev->log_base || !len))
|
||||
return;
|
||||
|
||||
if (unlikely(dev->log_size <= ((addr + len - 1) / VHOST_LOG_PAGE / 8)))
|
||||
return;
|
||||
|
||||
/* To make sure guest memory updates are committed before logging */
|
||||
rte_smp_wmb();
|
||||
|
||||
page = addr / VHOST_LOG_PAGE;
|
||||
while (page * VHOST_LOG_PAGE < addr + len) {
|
||||
vhost_log_page((uint8_t *)(uintptr_t)dev->log_base, page);
|
||||
page += 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __attribute__((always_inline))
|
||||
vhost_log_used_vring(struct virtio_net *dev, struct vhost_virtqueue *vq,
|
||||
uint64_t offset, uint64_t len)
|
||||
{
|
||||
vhost_log_write(dev, vq->log_guest_addr + offset, len);
|
||||
}
|
||||
|
||||
static bool
|
||||
is_valid_virt_queue_idx(uint32_t idx, int is_tx, uint32_t nr_vring)
|
||||
|
Loading…
x
Reference in New Issue
Block a user