migration/cgs-tdx: add tdx_mig_setup
tdx_mig_setup is assigned to the cgs migration framework's savevm_state_setup API (invoked on the source side) and loadvm_state_setup API (invoked on the destination side). The setup work includes: - create a kvm_device from the tdx-mig driver in KVM. The device fd is returned for later communication with the device. - negotiate with the driver for the size if the memory to map, this includes: -- KVM_SET_DEVICE_ATTR: sets the configurable attr (only the migration buffer size currently) of the device to KVM. The migration flow currently finds and send dirty pages one by one, so the migration buffer size set to the driver is 4KB (TAGET_PAGE_SIZE); -- KVM_GET_DEVICE_ATTR: gets the negotiated kvm_device's attr. This obtains from KVM the sizes of the 4 parts (i.e. mbmd buffer size, migration buffer size, mac list buffer size, and gpa list buffer size) of shared memory. - map the 4 parts of shared memory. Signed-off-by: Wei Wang <wei.w.wang@intel.com>
This commit is contained in:
committed by
Nikolay Borisov
parent
b8fc99d9d6
commit
e4049cd161
@@ -690,4 +690,20 @@ struct kvm_tdx_get_migration_info {
|
|||||||
__u8 pad[6];
|
__u8 pad[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define KVM_DEV_TDX_MIG_ATTR 0x1
|
||||||
|
|
||||||
|
struct kvm_dev_tdx_mig_attr {
|
||||||
|
#define KVM_DEV_TDX_MIG_ATTR_VERSION 0
|
||||||
|
__u32 version;
|
||||||
|
/* 4KB buffer can hold 512 entries at most */
|
||||||
|
#define TDX_MIG_BUF_LIST_PAGES_MAX 512
|
||||||
|
__u32 buf_list_pages;
|
||||||
|
__u32 max_migs;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TDX_MIG_STREAM_MBMD_MAP_OFFSET 0
|
||||||
|
#define TDX_MIG_STREAM_GPA_LIST_MAP_OFFSET 1
|
||||||
|
#define TDX_MIG_STREAM_MAC_LIST_MAP_OFFSET 2
|
||||||
|
#define TDX_MIG_STREAM_BUF_LIST_MAP_OFFSET 4
|
||||||
|
|
||||||
#endif /* _ASM_X86_KVM_H */
|
#endif /* _ASM_X86_KVM_H */
|
||||||
|
@@ -1511,6 +1511,8 @@ enum kvm_device_type {
|
|||||||
#define KVM_DEV_TYPE_XIVE KVM_DEV_TYPE_XIVE
|
#define KVM_DEV_TYPE_XIVE KVM_DEV_TYPE_XIVE
|
||||||
KVM_DEV_TYPE_ARM_PV_TIME,
|
KVM_DEV_TYPE_ARM_PV_TIME,
|
||||||
#define KVM_DEV_TYPE_ARM_PV_TIME KVM_DEV_TYPE_ARM_PV_TIME
|
#define KVM_DEV_TYPE_ARM_PV_TIME KVM_DEV_TYPE_ARM_PV_TIME
|
||||||
|
KVM_DEV_TYPE_TDX_MIG_STREAM,
|
||||||
|
#define KVM_DEV_TYPE_TDX_MIG_STREAM KVM_DEV_TYPE_TDX_MIG_STREAM
|
||||||
KVM_DEV_TYPE_MAX,
|
KVM_DEV_TYPE_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -34,6 +34,101 @@ static bool tdx_mig_is_ready(void)
|
|||||||
return tdx_premig_is_done();
|
return tdx_premig_is_done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int tdx_mig_stream_create(TdxMigStream *stream)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_TDX_MIG_STREAM, false);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_report("Failed to create stream due to %s", strerror(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
stream->fd = ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tdx_mig_stream_setup(void)
|
||||||
|
{
|
||||||
|
TdxMigStream *stream = &tdx_mig.streams[0];
|
||||||
|
struct kvm_dev_tdx_mig_attr tdx_mig_attr;
|
||||||
|
struct kvm_device_attr attr = {
|
||||||
|
.group = KVM_DEV_TDX_MIG_ATTR,
|
||||||
|
.addr = (uint64_t)&tdx_mig_attr,
|
||||||
|
.attr = sizeof(struct kvm_dev_tdx_mig_attr),
|
||||||
|
};
|
||||||
|
size_t map_size;
|
||||||
|
off_t map_offset;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = tdx_mig_stream_create(stream);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tell the tdx_mig driver the number of pages to add to buffer list for
|
||||||
|
* TD private page export/import. Currently, TD private pages are migrated
|
||||||
|
* one by one.
|
||||||
|
*/
|
||||||
|
tdx_mig_attr.buf_list_pages = 1;
|
||||||
|
tdx_mig_attr.version = KVM_DEV_TDX_MIG_ATTR_VERSION;
|
||||||
|
if (kvm_device_ioctl(stream->fd, KVM_SET_DEVICE_ATTR, &attr) < 0) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&tdx_mig_attr, 0, sizeof(struct kvm_dev_tdx_mig_attr));
|
||||||
|
tdx_mig_attr.version = KVM_DEV_TDX_MIG_ATTR_VERSION;
|
||||||
|
if (kvm_device_ioctl(stream->fd, KVM_GET_DEVICE_ATTR, &attr) < 0) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
map_offset = TDX_MIG_STREAM_MBMD_MAP_OFFSET;
|
||||||
|
map_size = (TDX_MIG_STREAM_GPA_LIST_MAP_OFFSET -
|
||||||
|
TDX_MIG_STREAM_MBMD_MAP_OFFSET) * TARGET_PAGE_SIZE;
|
||||||
|
stream->mbmd = mmap(NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||||
|
stream->fd, map_offset);
|
||||||
|
if (stream->mbmd == MAP_FAILED) {
|
||||||
|
ret = -errno;
|
||||||
|
error_report("Failed to map mbmd due to %s", strerror(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
map_offset = TDX_MIG_STREAM_GPA_LIST_MAP_OFFSET * TARGET_PAGE_SIZE;
|
||||||
|
map_size = (TDX_MIG_STREAM_MAC_LIST_MAP_OFFSET -
|
||||||
|
TDX_MIG_STREAM_GPA_LIST_MAP_OFFSET) * TARGET_PAGE_SIZE;
|
||||||
|
stream->gpa_list = mmap(NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||||
|
stream->fd, map_offset);
|
||||||
|
if (stream->gpa_list == MAP_FAILED) {
|
||||||
|
ret = -errno;
|
||||||
|
error_report("Failed to map gpa list due to %s", strerror(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
map_offset = TDX_MIG_STREAM_MAC_LIST_MAP_OFFSET * TARGET_PAGE_SIZE;
|
||||||
|
map_size = (TDX_MIG_STREAM_BUF_LIST_MAP_OFFSET -
|
||||||
|
TDX_MIG_STREAM_MAC_LIST_MAP_OFFSET) * TARGET_PAGE_SIZE;
|
||||||
|
stream->mac_list = mmap(NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||||
|
stream->fd, map_offset);
|
||||||
|
if (stream->mac_list == MAP_FAILED) {
|
||||||
|
ret = -errno;
|
||||||
|
error_report("Failed to map mac list due to %s", strerror(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
map_offset = TDX_MIG_STREAM_BUF_LIST_MAP_OFFSET * TARGET_PAGE_SIZE;
|
||||||
|
map_size = tdx_mig_attr.buf_list_pages * TARGET_PAGE_SIZE;
|
||||||
|
stream->buf_list = mmap(NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||||
|
stream->fd, map_offset);
|
||||||
|
if (stream->buf_list == MAP_FAILED) {
|
||||||
|
ret = -errno;
|
||||||
|
error_report("Failed to map buf list due to %s", strerror(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void tdx_mig_init(CgsMig *cgs_mig, uint32_t nr_channels)
|
void tdx_mig_init(CgsMig *cgs_mig, uint32_t nr_channels)
|
||||||
{
|
{
|
||||||
/* Only support 1 migration channel currently */
|
/* Only support 1 migration channel currently */
|
||||||
@@ -42,4 +137,6 @@ void tdx_mig_init(CgsMig *cgs_mig, uint32_t nr_channels)
|
|||||||
tdx_mig.streams = g_malloc0(sizeof(struct TdxMigStream) * nr_channels);
|
tdx_mig.streams = g_malloc0(sizeof(struct TdxMigStream) * nr_channels);
|
||||||
|
|
||||||
cgs_mig->is_ready = tdx_mig_is_ready;
|
cgs_mig->is_ready = tdx_mig_is_ready;
|
||||||
|
cgs_mig->savevm_state_setup = tdx_mig_stream_setup;
|
||||||
|
cgs_mig->loadvm_state_setup = tdx_mig_stream_setup;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user