Define Secure Encrypted Virtualization (SEV) key management command id and structure. The command definition is available in SEV KM [1] spec 0.14 and Documentation/virtual/kvm/amd-memory-encryption.txt [1] http://support.amd.com/TechDocs/55766_SEV-KM API_Specification.pdf Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Cc: Ingo Molnar <mingo@xxxxxxxxxx> Cc: "H. Peter Anvin" <hpa@xxxxxxxxx> Cc: Paolo Bonzini <pbonzini@xxxxxxxxxx> Cc: "Radim Krčmář" <rkrcmar@xxxxxxxxxx> Cc: Joerg Roedel <joro@xxxxxxxxxx> Cc: Borislav Petkov <bp@xxxxxxx> Cc: Tom Lendacky <thomas.lendacky@xxxxxxx> Cc: x86@xxxxxxxxxx Cc: kvm@xxxxxxxxxxxxxxx Cc: linux-kernel@xxxxxxxxxxxxxxx Signed-off-by: Brijesh Singh <brijesh.singh@xxxxxxx> --- .../virtual/kvm/amd-memory-encryption.txt | 191 +++++++++++++++++++++ include/uapi/linux/kvm.h | 79 +++++++++ 2 files changed, 270 insertions(+) diff --git a/Documentation/virtual/kvm/amd-memory-encryption.txt b/Documentation/virtual/kvm/amd-memory-encryption.txt index 26472b4cdbaf..8c79946b4d43 100644 --- a/Documentation/virtual/kvm/amd-memory-encryption.txt +++ b/Documentation/virtual/kvm/amd-memory-encryption.txt @@ -36,3 +36,194 @@ setting the SEV bit before executing VMRUN. SEV hardware uses ASIDs to associate a memory encryption key with a VM. Hence, the ASID for the SEV-enabled guests must be from 1 to a maximum value defined in the CPUID 0x8000001f[ecx] field. + +SEV Key Management +------------------ +The Key management for the SEV guest is handled by a separate processor known as +the AMD Secure Processor (AMD-SP). Firmware running inside the AMD-SP provides a +secure key management interface to perform common hypervisor activities such as +encrypting bootstrap code, snapshot, migrating and debugging the guest. For +more information, see SEV Key Management spec at + +http://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf + +KVM implements the following commands to support SEV guests common lifecycle +events such as launching, running, snapshotting, migrating and decommissioning +guests. + +1. KVM_SEV_INIT + +Returns: 0 on success, -negative on error + +The KVM_SEV_INIT command is used by the hypervisor to initialize the SEV platform +context. In a typical workflow, this command should be the first command issued. + +2. KVM_SEV_LAUNCH_START + +Parameters: struct kvm_sev_launch_start (in/out) +Returns: 0 on success, -negative on error + +The KVM_SEV_LAUNCH_START command is used for creating the memory encryption +context. To create the encryption context, user must provide a guest policy, +the owner's public Diffie-Hellman (PDH) key and session information. + +struct kvm_sev_launch_start { + /* if zero then firmware creates a new handle */ + __u32 handle; + + /* guest's policy */ + __u32 policy; + + /* userspace address pointing to the guest owner's PDH key */ + __u64 dh_uaddr; + __u32 dh_len; + + /* userspace address which points to the guest session information */ + __u64 session_addr; + __u32 session_len; +}; + +On success, the 'handle' field contain a new handle and on error, a negative value. + +For more details, see SEV spec Section 6.2. + +3. KVM_SEV_LAUNCH_UPDATE_DATA + +Parameters (in): struct kvm_sev_launch_update_data +Returns: 0 on success, -negative on error + +The KVM_SEV_LAUNCH_UPDATE_DATA is used for encrypting the memory region. It also +calculates a measurement of the memory contents. The measurement is a signature +of the memory contents that can be sent to the guest owner as an attestation +that the memory was encrypted correctly by the firmware. + +struct kvm_sev_launch_update { + /* userspace address need to be encrypted (must be 16-byte aligned) */ + __u64 uaddr; + + /* length of the data to be encrypted (must be 16-byte aligned) */ + __u32 len; +}; + +For more details, see SEV spec Section 6.3. + +4. KVM_SEV_LAUNCH_MEASURE + +Parameters (in): struct kvm_sev_launch_measure +Returns: 0 on success, -negative on error + +The KVM_SEV_LAUNCH_MEASURE command is used to retrieve the measurement +of the data encrypted by the KVM_SEV_LAUNCH_UPDATE_DATA. The guest owner +may wait to provide the guest with confidential information until it can +verify the measurement. Since the guest owner knows the initial contents +of the guest at boot, the measurement can be verified by comparing it to +what the guest owner expects. + +struct kvm_sev_launch_measure { + /* where to copy the measurement */ + __u64 uaddr; + + /* length of measurement blob */ + __u32 len; +}; + +For more details on the measurement verification flow, see SEV spec Section 6.4 + +5. KVM_SEV_LAUNCH_FINISH + +Returns: 0 on success, -negative on error + +After completion of the launch flow, the KVM_SEV_LAUNCH_FINISH command can be +issued to make the guest ready for the execution. + +6. KVM_SEV_GUEST_STATUS + +Parameters (out): struct kvm_sev_guest_status +Returns: 0 on success, -negative on error + +The KVM_SEV_GUEST_STATUS command is used to retrieve status information about a +SEV-enabled guest. + +struct kvm_sev_guest_status { + /* guest handle */ + __u32 handle; + + /* guest policy */ + __u32 policy; + + /* guest state (see below) */ + __u8 state; +}; + +SEV guest state: + +enum { + SEV_STATE_INVALID = 0; + SEV_STATE_LAUNCHING, /* guest is currently being launched */ + SEV_STATE_SECRET, /* guest is being launched and ready to accept the ciphertext data */ + SEV_STATE_RUNNING, /* guest is fully launched and running */ + SEV_STATE_RECEIVING, /* guest is being migrated in from another SEV machine */ + SEV_STATE_SENDING /* guest is getting migrated out to another SEV machine */ +}; + +7. KVM_SEV_DBG_DECRYPT + +Parameters (in): struct kvm_sev_dbg +Returns: 0 on success, -negative on error + +The KVM_SEV_DEBUG_DECRYPT command can be used by the hypervisor to request the +firmware to decrypt the data at the given memory region. + +struct kvm_sev_dbg { + /* userspace address of data to decrypt */ + __u64 src_uaddr; + /* userspace address of destination */ + __u64 dst_uaddr; + + /* length of memory region to decrypt */ + __u32 len; +}; + +The command returns an error if guest policy does not allow debugging. + +8. KVM_SEV_DBG_ENCRYPT + +Parameters (in): struct kvm_sev_dbg +Returns: 0 on success, -negative on error + +The KVM_SEV_DEBUG_ENCRYPT command can be used by the hypervisor to request the +firmware to encrypt the data at the given memory region. + +struct kvm_sev_dbg { + /* userspace address of data to encrypt */ + __u64 src_uaddr; + /* userspace address of destination */ + __u64 dst_uaddr; + + /* length of memory region to encrypt */ + __u32 len; +}; + +The command returns an error if guest policy does not allow debugging. + +9. KVM_SEV_LAUNCH_SECRET + +Parameters (in): struct kvm_sev_launch_secret +Returns: 0 on success, -negative on error + +The KVM_SEV_LAUNCH_SECRET command can be used by the hypervisor to inject a secret +data after the measurement has been validated by the guest owner. + +struct kvm_sev_launch_secret { + /* userspace address containing the packet header */ + __u64 hdr_uaddr; + __u32 hdr_len; + + /* the guest memory region where the secret should be injected */ + __u64 guest_uaddr; + __u32 guest_len; + + /* the hypervisor memory region which contains the secret */ + __u64 trans_uaddr; + __u32 trans_len; +}; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index d595d3970390..115c75156711 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1368,6 +1368,85 @@ struct kvm_enc_region { struct kvm_enc_region) #define KVM_MEMORY_ENCRYPT_UNREGISTER_REGION _IOR(KVMIO, 0xbc,\ struct kvm_enc_region) +/* Secure Encrypted Virtualization command */ +enum sev_cmd_id { + /* Guest initialization commands */ + KVM_SEV_INIT = 0, + KVM_SEV_ES_INIT, + /* Guest launch commands */ + KVM_SEV_LAUNCH_START, + KVM_SEV_LAUNCH_UPDATE_DATA, + KVM_SEV_LAUNCH_UPDATE_VMSA, + KVM_SEV_LAUNCH_SECRET, + KVM_SEV_LAUNCH_MEASURE, + KVM_SEV_LAUNCH_FINISH, + /* Guest migration commands (outgoing) */ + KVM_SEV_SEND_START, + KVM_SEV_SEND_UPDATE_DATA, + KVM_SEV_SEND_UPDATE_VMSA, + KVM_SEV_SEND_FINISH, + /* Guest migration commands (incoming) */ + KVM_SEV_RECEIVE_START, + KVM_SEV_RECEIVE_UPDATE_DATA, + KVM_SEV_RECEIVE_UPDATE_VMSA, + KVM_SEV_RECEIVE_FINISH, + /* Guest status and debug commands */ + KVM_SEV_GUEST_STATUS, + KVM_SEV_DBG_DECRYPT, + KVM_SEV_DBG_ENCRYPT, + /* Guest certificates commands */ + KVM_SEV_CERT_EXPORT, + + KVM_SEV_NR_MAX, +}; + +struct kvm_sev_cmd { + __u32 id; + __u64 data; + __u32 error; + __u32 sev_fd; +}; + +struct kvm_sev_launch_start { + __u32 handle; + __u32 policy; + __u64 dh_uaddr; + __u32 dh_len; + __u64 session_uaddr; + __u32 session_len; +}; + +struct kvm_sev_launch_update_data { + __u64 uaddr; + __u32 len; +}; + + +struct kvm_sev_launch_secret { + __u64 hdr_uaddr; + __u32 hdr_len; + __u64 guest_uaddr; + __u32 guest_len; + __u64 trans_uaddr; + __u32 trans_len; +}; + +struct kvm_sev_launch_measure { + __u64 uaddr; + __u32 len; +}; + +struct kvm_sev_guest_status { + __u32 handle; + __u32 policy; + __u32 state; +}; + +struct kvm_sev_dbg { + __u64 src_uaddr; + __u64 dst_uaddr; + __u32 len; +}; #define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0) #define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1) -- 2.9.5