diff --git a/arch/arm64/include/asm/kvm_tmm.h b/arch/arm64/include/asm/kvm_tmm.h index 484940589c7cb1bf8973d57d02b4ce972a9888e2..ed30e5fcb3bf62866a5056b3bfa2be2daf3c97f7 100644 --- a/arch/arm64/include/asm/kvm_tmm.h +++ b/arch/arm64/include/asm/kvm_tmm.h @@ -14,6 +14,9 @@ enum virtcca_cvm_state { CVM_STATE_DYING }; +#define VIRTCCA_MIG_DST 0 +#define VIRTCCA_MIG_SRC 1 + #define MAX_KAE_VF_NUM 11 /* @@ -38,6 +41,21 @@ struct tmi_cvm_params { u64 kae_vf_num; u64 sec_addr[MAX_KAE_VF_NUM]; u64 hpre_addr[MAX_KAE_VF_NUM]; +#ifndef __GENKSYMS__ + u32 mig_enable; /* check the base capability of CVM migration */ + u32 mig_src; /* check the CVM is source or dest*/ + u32 migration_migvm_cap; /* the type of CVM (support migration) */ +#endif +}; + +/* the guest cvm and migcvm both use this structure */ +#define KVM_CVM_MIGVM_VERSION 0 +struct mig_cvm { + /* used by guest cvm */ + uint8_t version; /* kvm version of migcvm*/ + uint64_t migvm_cid; /* vsock cid of migvm */ + uint16_t dst_port; /* port of destination cvm */ + char dst_ip[16]; /* ip of destination cvm */ }; struct cvm { @@ -123,6 +141,7 @@ int cvm_psci_complete(struct kvm_vcpu *calling, struct kvm_vcpu *target, unsigne void kvm_cvm_unmap_destroy_range(struct kvm *kvm); int kvm_cvm_map_range(struct kvm *kvm); +int kvm_cvm_mig_map_range(struct kvm *kvm); int virtcca_cvm_arm_smmu_domain_set_kvm(void *group); int cvm_map_unmap_ipa_range(struct kvm *kvm, phys_addr_t ipa_base, phys_addr_t pa, unsigned long map_size, uint32_t is_map); @@ -157,6 +176,366 @@ static inline unsigned long cvm_ttt_level_mapsize(int level) return (1UL << CVM_TTT_LEVEL_SHIFT(level)); } + +/* virtcca MIG sub-ioctl() commands. */ +enum kvm_cvm_cmd_id { + /* virtcca MIG migcvm commands. */ + KVM_CVM_MIGCVM_SET_CID = 0, + KVM_CVM_MIGCVM_ATTEST, + KVM_CVM_MIGCVM_ATTEST_DST, + KVM_CVM_GET_BIND_STATUS, + KVM_CVM_MIG_EXPORT_ABORT, + /* virtcca MIG stream commands. */ + KVM_CVM_MIG_STREAM_START, + KVM_CVM_MIG_EXPORT_STATE_IMMUTABLE, + KVM_CVM_MIG_IMPORT_STATE_IMMUTABLE, + KVM_CVM_MIG_EXPORT_MEM, + KVM_CVM_MIG_IMPORT_MEM, + KVM_CVM_MIG_EXPORT_TRACK, + KVM_CVM_MIG_IMPORT_TRACK, + KVM_CVM_MIG_EXPORT_PAUSE, + KVM_CVM_MIG_EXPORT_STATE_TEC, + KVM_CVM_MIG_IMPORT_STATE_TEC, + KVM_CVM_MIG_IMPORT_END, + KVM_CVM_MIG_CRC, + KVM_CVM_MIG_GET_MIG_INFO, + KVM_CVM_MIG_IS_ZERO_PAGE, + KVM_CVM_MIG_IMPORT_ZERO_PAGE, + + KVM_CVM_MIG_CMD_NR_MAX, +}; + +struct kvm_virtcca_mig_cmd { + /* enum kvm_tdx_cmd_id */ + __u32 id; + /* flags for sub-commend. If sub-command doesn't use this, set zero. */ + __u32 flags; + /* + * data for each sub-command. An immediate or a pointer to the actual + * data in process virtual address. If sub-command doesn't use it, + * set zero. + */ + __u64 data; + /* + * Auxiliary error code. The sub-command may return TDX SEAMCALL + * status code in addition to -Exxx. + * Defined for consistency with struct kvm_sev_cmd. + */ + __u64 error; +}; + +/* mig virtcca head*/ +#define KVM_DEV_VIRTCCA_MIG_ATTR 0x1 + +struct kvm_dev_virtcca_mig_attr { +#define KVM_DEV_VIRTCCA_MIG_ATTR_VERSION 0 + __u32 version; +/* 4KB buffer can hold 512 entries at most */ +#define VIRTCCA_MIG_BUF_LIST_PAGES_MAX 512 + __u32 buf_list_pages; + __u32 max_migs; +}; + +#define VIRTCCA_MIG_STREAM_MBMD_MAP_OFFSET 0 +#define VIRTCCA_MIG_STREAM_GPA_LIST_MAP_OFFSET 1 +#define VIRTCCA_MIG_STREAM_MAC_LIST_MAP_OFFSET 2 +#define VIRTCCA_MIG_STREAM_BUF_LIST_MAP_OFFSET 4 + +struct virtcca_bind_info { + int16_t version; + bool premig_done; +}; + +struct virtcca_dst_host_info { + char dst_ip[16]; + uint16_t dst_port; + uint8_t version; +}; + +struct virtcca_mig_mbmd_data { /* both kvm and tmm can access */ + __u16 size; + __u16 mig_version; + __u16 migs_index; /* corresponding stream idx */ + __u8 mb_type; + __u8 rsvd0; /* reserve bit */ + __u32 mb_counter; + __u32 mig_epoch; + __u64 iv_counter; + __u8 type_specific_info[]; +} __packed; + +struct virtcca_mig_mbmd { + struct virtcca_mig_mbmd_data *data; + uint64_t hpa_and_size; /* Host physical address and size of the mbmd */ +}; + +#define VIRTCCA_MIG_EPOCH_START_TOKEN 0xffffffff + +/* + * The buffer list specifies a list of 4KB pages to be used by TDH_EXPORT_MEM + * and TDH_IMPORT_MEM to export and import guest memory pages. Each entry + * is 64-bit and points to a physical address of a 4KB page used as buffer. The + * list itself is a 4KB page, so it can hold up to 512 entries. + */ +union virtcca_mig_buf_list_entry { + uint64_t val; + struct { + uint64_t rsvd0 : 12; + uint64_t pfn : 40; + uint64_t rsvd1 : 11; + uint64_t invalid : 1; + }; +}; + +struct virtcca_mig_buf_list { + union virtcca_mig_buf_list_entry *entries; + // uint64_t *entries; + hpa_t hpa; +}; + +/* + * The page list specifies a list of 4KB pages to be used by the non-memory + * states export and import, i.e. TDH_EXPORT_STATE_* and TDH_IMPORT_STATE_*. + * Each entry is 64-bit and specifies the physical address of a 4KB buffer. + * The list itself is a 4KB page, so it can hold up to 512 entries. + */ +union virtcca_mig_page_list_info { + uint64_t val; + struct { + uint64_t rsvd0 : 12; + uint64_t pfn : 40; + uint64_t rsvd1 : 3; + uint64_t last_entry : 9; + }; +}; + +struct virtcca_mig_page_list { + hpa_t *entries; + union virtcca_mig_page_list_info info; +}; + +union virtcca_mig_gpa_list_entry { + uint64_t val; + struct{ + uint64_t level : 2; /* Bits 1:0: Mapping level */ + uint64_t pending : 1; /* Bit 2: Page is pending */ + uint64_t reserved_0 : 4; /* Bits 6:3 */ + uint64_t l2_map : 3; /* Bits 9:7: L2 mapping flags */ + uint64_t mig_type : 2; /* Bits 11:10: Migration type */ + uint64_t gfn : 40; /* Bits 51:12 */ +#define GPA_LIST_OP_NOP 0 +#define GPA_LIST_OP_EXPORT 1 +#define GPA_LIST_OP_CANCEL 2 + uint64_t operation : 2; /* Bits 53:52 */ + uint64_t reserved_1 : 2; /* Bits 55:54 */ +#define GPA_LIST_S_SUCCESS 0 + uint64_t status : 5; /* Bits 56:52 */ + uint64_t reserved_2 : 3; /* Bits 63:61 */ + }; +}; + +#define TMM_MAX_DIRTY_BITMAP_LEN 8 +/* + * The GPA list specifies a list of GPAs to be used by TDH_EXPORT_MEM and + * TDH_IMPORT_MEM, TDH_EXPORT_BLOCKW, and TDH_EXPORT_RESTORE. The list itself + * is 4KB, so it can hold up to 512 such 64-bit entries. + */ +union virtcca_mig_ipa_list_info { + uint64_t val; + struct { + uint64_t rsvd0 : 3; + uint64_t first_entry: 9; + uint64_t pfn : 40; + uint64_t rsvd1 : 3; + uint64_t last_entry : 9; + }; +}; + +struct virtcca_mig_gpa_list { + union virtcca_mig_gpa_list_entry *entries; + union virtcca_mig_ipa_list_info info; +}; + +/* + * A MAC list specifies a list of MACs over 4KB migrated pages and their GPA + * entries. It is used by TDH_EXPORT_MEM and TDH_IMPORT_MEM. Each entry is + * 128-bit containing a single AES-GMAC-256 of a migrated page. The list itself + * is a 4KB page, so it can hold up to 256 entries. To support the export and + * import of 512 pages, two such MAC lists are needed to be passed to the TDX + * module. + */ +struct virtcca_mig_mac_list { + void *entries; + hpa_t hpa; +}; + +union virtcca_mig_stream_info { + uint64_t val; + struct { + uint64_t index : 16; + uint64_t rsvd : 47; + uint64_t resume : 1; + }; + struct { + uint64_t rsvd1 : 63; + uint64_t in_order : 1; + }; +}; + +struct virtcca_mig_stream { + uint16_t idx; /* stream id */ + uint32_t buf_list_pages; /* ns memory page number of buf_list 5