Unverified Commit 15f539c4 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!5260 [OLK-6.6] Support live migration for CSV/CSV2 guest, and support rebooting CSV/CSV2 guest

Merge Pull Request from: @hanliyang 
 
Support live migration for CSV/CSV2 guest, and support rebooting CSV/CSV2 guest

issue:
https://gitee.com/open_euler/dashboard?issue_id=I98WBH

In order to support migration for CSV(2) guest's memory pages, we provide the following patches
to make use of CSV RING_BUFFER mode in the CSV firmware, in CSV RING_BUFFER mode, the firmware can
process private memory pages in batch which will speedup the migration.

    crypto: ccp: Introduce init and free helpers to manage CSV RING_BUFFER queues
    crypto: ccp: Add support for enqueue command pointers in CSV RING_BUFFER mode
    crypto: ccp: Add support for dequeue status in CSV RING_BUFFER mode
    crypto: ccp: Add support to switch to CSV RING_BUFFER mode
    crypto: ccp: Add support for issue commands in CSV RING_BUFFER mode
    KVM: SVM: Add KVM_CSV_COMMAND_BATCH command for applying CSV RING_BUFFER mode
    KVM: SVM: Prepare memory pool to allocate buffers for KVM_CSV_COMMAND_BATCH
    KVM: SVM: Add SEND_UPDATE_DATA command helper to support KVM_CSV_COMMAND_BATCH
    KVM: SVM: Add RECEIVE_UPDATE_DATA command helper to support KVM_CSV_COMMAND_BATCH

In order to support migrate CSV2 guest's CPU states, we need add support to migrate VMSA,GHCB and
other important infos. We provide the following patches to support migrate VMSA, GHCB and other
important infos.

    crypto: ccp: Fix definition of struct sev_data_send_update_vmsa
    KVM: SVM: Add KVM_SEV_SEND_UPDATE_VMSA command
    KVM: SVM: Add KVM_SEV_RECEIVE_UPDATE_VMSA command
    KVM: x86: Restore control registers in __set_sregs() to support CSV2 guest live migration
    KVM: SVM: Export MSR_AMD64_SEV_ES_GHCB to userspace for CSV2 guest

In order to support to reboot CSV2 guest and prevent cache coherency issue, we provide the following
patches to reset VMSA during rebooting and flush caches if necessary.

    KVM: x86: Introduce control_{pre,post}_system_reset ioctl interfaces
    KVM: SVM: Add support for rebooting CSV2 guest
    KVM: SVM: Force flush caches before reboot CSV guest 
 
Link:https://gitee.com/openeuler/kernel/pulls/5260

 

Reviewed-by: default avatarKevin Zhu <zhukeqian1@huawei.com>
Signed-off-by: default avatarZhang Peng <zhangpeng362@huawei.com>
parents fc720a9b 459a38af
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -137,6 +137,8 @@ KVM_X86_OP(vcpu_deliver_sipi_vector)
KVM_X86_OP_OPTIONAL_RET0(vcpu_get_apicv_inhibit_reasons);
KVM_X86_OP_OPTIONAL(get_untagged_addr)
KVM_X86_OP_OPTIONAL(vm_attestation)
KVM_X86_OP_OPTIONAL(control_pre_system_reset)
KVM_X86_OP_OPTIONAL(control_post_system_reset)

#undef KVM_X86_OP
#undef KVM_X86_OP_OPTIONAL
+3 −1
Original line number Diff line number Diff line
@@ -1773,9 +1773,11 @@ struct kvm_x86_ops {
	gva_t (*get_untagged_addr)(struct kvm_vcpu *vcpu, gva_t gva, unsigned int flags);

	/*
	 * Attestation interface for HYGON CSV guest
	 * Interfaces for HYGON CSV guest
	 */
	int (*vm_attestation)(struct kvm *kvm, unsigned long gpa, unsigned long len);
	int (*control_pre_system_reset)(struct kvm *kvm);
	int (*control_post_system_reset)(struct kvm *kvm);
};

struct kvm_x86_nested_ops {
+968 −0

File changed.

Preview size limit exceeded, changes collapsed.

+84 −0
Original line number Diff line number Diff line
@@ -12,6 +12,26 @@

#include <asm/processor-hygon.h>

/* same to the ring buffer max num */
#define SVM_RING_BUFFER_MAX 4094

struct csv_ringbuf_info_item {
	struct page **pages;
	uintptr_t hdr_vaddr;
	uintptr_t trans_vaddr;
	uintptr_t data_vaddr;
	uintptr_t trans_uaddr;
	uintptr_t hdr_uaddr;
	unsigned long trans_len;
	unsigned long hdr_len;
	unsigned long n;
};

struct csv_ringbuf_infos {
	struct csv_ringbuf_info_item *item[SVM_RING_BUFFER_MAX];
	int num;
};

#ifdef CONFIG_HYGON_CSV

/*
@@ -20,6 +40,8 @@
 */
extern struct hygon_kvm_hooks_table {
	bool sev_hooks_installed;
	bool *sev_enabled;
	unsigned long *sev_me_mask;
	int (*sev_issue_cmd)(struct kvm *kvm, int id, void *data, int *error);
	unsigned long (*get_num_contig_pages)(unsigned long idx,
					      struct page **inpages,
@@ -29,16 +51,78 @@ extern struct hygon_kvm_hooks_table {
					int write);
	void (*sev_unpin_memory)(struct kvm *kvm, struct page **pages,
				 unsigned long npages);
	void (*sev_clflush_pages)(struct page *pages[], unsigned long npages);
} hygon_kvm_hooks;

void __init csv_init(struct kvm_x86_ops *ops);
void csv_exit(void);

int csv_alloc_trans_mempool(void);
void csv_free_trans_mempool(void);
int csv_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
int csv_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
bool csv_has_emulated_ghcb_msr(struct kvm *kvm);
void csv2_sync_reset_vmsa(struct vcpu_svm *svm);
void csv2_free_reset_vmsa(struct vcpu_svm *svm);
int csv2_setup_reset_vmsa(struct vcpu_svm *svm);

static inline bool csv2_state_unstable(struct vcpu_svm *svm)
{
	return svm->sev_es.receiver_ghcb_map_fail;
}

#else	/* !CONFIG_HYGON_CSV */

static inline void __init csv_init(struct kvm_x86_ops *ops) { }
static inline void csv_exit(void) { }

static inline int csv_alloc_trans_mempool(void) { return 0; }
static inline void csv_free_trans_mempool(void) { }
static inline
int csv_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) { return 1; }
static inline
int csv_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) { return 1; }
static inline bool csv_has_emulated_ghcb_msr(struct kvm *kvm) { return false; }
static inline bool csv2_state_unstable(struct vcpu_svm *svm) { return false; }
static inline void csv2_sync_reset_vmsa(struct vcpu_svm *svm) { }
static inline void csv2_free_reset_vmsa(struct vcpu_svm *svm) { }
static inline int csv2_setup_reset_vmsa(struct vcpu_svm *svm) { return 0; }

#endif	/* CONFIG_HYGON_CSV */

#include <asm/sev-common.h>

/*
 * CSV2 live migration support:
 *     If MSR_AMD64_SEV_ES_GHCB in migration didn't apply GHCB MSR protocol,
 *     reuse bits [52-63] to indicate vcpu status. The following status are
 *     currently included:
 *         * ghcb_map: indicate whether GHCB page was mapped. The mapped GHCB
 *                     page may be filled with GPRs before VMRUN, so we must
 *                     remap GHCB page on the recipient's side.
 *         * received_first_sipi: indicate AP's INIT-SIPI-SIPI stage. Reuse
 *                     these bits for received_first_sipi is acceptable cause
 *                     runtime stage of guest's linux only applies GHCB page
 *                     protocol.
 *                     It's unlikely that the migration encounter other stages
 *                     of guest's linux. Once encountered, AP bringup may fail
 *                     which will not impact user payload.
 *     Otherbits keep their's original meaning. (See GHCB Spec 2.3.1 for detail)
 */
#define GHCB_MSR_KVM_STATUS_POS		52
#define GHCB_MSR_KVM_STATUS_BITS	12
#define GHCB_MSR_KVM_STATUS_MASK				\
	((BIT_ULL(GHCB_MSR_KVM_STATUS_BITS) - 1)		\
			<< GHCB_MSR_KVM_STATUS_POS)
#define GHCB_MSR_MAPPED_POS		63
#define GHCB_MSR_MAPPED_BITS		1
#define GHCB_MSR_MAPPED_MASK					\
	((BIT_ULL(GHCB_MSR_MAPPED_BITS) - 1)			\
			 << GHCB_MSR_MAPPED_POS)
#define GHCB_MSR_RECEIVED_FIRST_SIPI_POS	62
#define GHCB_MSR_RECEIVED_FIRST_SIPI_BITS	1
#define GHCB_MSR_RECEIVED_FIRST_SIPI_MASK			\
	((BIT_ULL(GHCB_MSR_RECEIVED_FIRST_SIPI_BITS) - 1)	\
			 << GHCB_MSR_RECEIVED_FIRST_SIPI_POS)

#endif	/* __SVM_CSV_H */
+37 −5
Original line number Diff line number Diff line
@@ -667,6 +667,18 @@ static int __sev_launch_update_vmsa(struct kvm *kvm, struct kvm_vcpu *vcpu,
	  return ret;

	vcpu->arch.guest_state_protected = true;

	/*
	 * Backup encrypted vmsa to support rebooting CSV2 guest. The
	 * clflush_cache_range() is necessary to invalidate prefetched
	 * memory area pointed by svm->sev_es.vmsa so that we can read
	 * fresh memory updated by PSP.
	 */
	if (is_x86_vendor_hygon()) {
		clflush_cache_range(svm->sev_es.vmsa, PAGE_SIZE);
		csv2_sync_reset_vmsa(svm);
	}

	return 0;
}

@@ -2197,10 +2209,13 @@ void __init sev_set_cpu_caps(void)
/* Code to set all of the function and vaiable pointers */
void sev_install_hooks(void)
{
	hygon_kvm_hooks.sev_enabled = &sev_enabled;
	hygon_kvm_hooks.sev_me_mask = &sev_me_mask;
	hygon_kvm_hooks.sev_issue_cmd = sev_issue_cmd;
	hygon_kvm_hooks.get_num_contig_pages = get_num_contig_pages;
	hygon_kvm_hooks.sev_pin_memory = sev_pin_memory;
	hygon_kvm_hooks.sev_unpin_memory = sev_unpin_memory;
	hygon_kvm_hooks.sev_clflush_pages = sev_clflush_pages;

	hygon_kvm_hooks.sev_hooks_installed = true;
}
@@ -2309,12 +2324,22 @@ void __init sev_hardware_setup(void)
		sev_es_debug_swap_enabled = false;

#ifdef CONFIG_HYGON_CSV
	/* Setup resources which are necessary for HYGON CSV */
	if (is_x86_vendor_hygon()) {
		/*
	 * Install sev related function and variable pointers hooks only for
	 * Hygon CPUs.
		 * Install sev related function and variable pointers hooks
		 * no matter @sev_enabled is false.
		 */
	if (is_x86_vendor_hygon())
		sev_install_hooks();

		/*
		 * Allocate a memory pool to speed up live migration of
		 * the CSV/CSV2 guests. If the allocation fails, no
		 * acceleration is performed at live migration.
		 */
		if (sev_enabled)
			csv_alloc_trans_mempool();
	}
#endif

#endif
@@ -2325,6 +2350,10 @@ void sev_hardware_unsetup(void)
	if (!sev_enabled)
		return;

	/* Free the memory pool that allocated in sev_hardware_setup(). */
	if (is_x86_vendor_hygon())
		csv_free_trans_mempool();

	/* No need to take sev_bitmap_lock, all VMs have been destroyed. */
	sev_flush_asids(1, max_sev_asid);

@@ -2411,6 +2440,9 @@ void sev_free_vcpu(struct kvm_vcpu *vcpu)

	if (svm->sev_es.ghcb_sa_free)
		kvfree(svm->sev_es.ghcb_sa);

	if (is_x86_vendor_hygon())
		csv2_free_reset_vmsa(svm);
}

static void dump_ghcb(struct vcpu_svm *svm)
Loading