On Tue, Sep 19, 2017 at 03:45:59PM -0500, Brijesh Singh wrote: > Create a Documentation entry to describe the AMD Secure Encrypted > Virtualization (SEV) feature. > > 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: Jonathan Corbet <corbet@xxxxxxx> > Cc: Borislav Petkov <bp@xxxxxxx> > Cc: Tom Lendacky <thomas.lendacky@xxxxxxx> > Cc: kvm@xxxxxxxxxxxxxxx > Cc: x86@xxxxxxxxxx > Cc: linux-kernel@xxxxxxxxxxxxxxx > Signed-off-by: Brijesh Singh <brijesh.singh@xxxxxxx> > --- > Documentation/virtual/kvm/00-INDEX | 3 + > .../virtual/kvm/amd-memory-encryption.txt | 210 +++++++++++++++++++++ > 2 files changed, 213 insertions(+) > create mode 100644 Documentation/virtual/kvm/amd-memory-encryption.txt Here's a diff which applies ontop of this one, it moves the KVM_SEV_* commands to Documentation/virtual/kvm/api.txt where they're all together in one place for obvious advantages. Also I did some small cleanups while at it. Notable is that the commands are a smaller number now and KVM_SEV_RECEIVE_UPDATE_DATA, KVM_SEV_RECEIVE_START and a couple more are missing. On purpose? --- diff --git a/Documentation/virtual/kvm/amd-memory-encryption.txt b/Documentation/virtual/kvm/amd-memory-encryption.txt index 5b38b4feb9b7..2f17400f5720 100644 --- a/Documentation/virtual/kvm/amd-memory-encryption.txt +++ b/Documentation/virtual/kvm/amd-memory-encryption.txt @@ -1,16 +1,18 @@ Secure Encrypted Virtualization (SEV) is a feature found on AMD processors. -SEV is an extension to the AMD-V architecture which supports running virtual -machines (VMs) under the control of a hypervisor. When enabled, the memory -contents of VM will be transparently encrypted with a key unique to the VM. +SEV is an extension to the AMD-V architecture which supports running +virtual machines (VMs) under the control of a hypervisor. When enabled, +the memory contents of a VM will be transparently encrypted with a key +unique to that VM. -Hypervisor can determine the SEV support through the CPUID instruction. The CPUID -function 0x8000001f reports information related to SEV: +The hypervisor can determine the SEV support through the CPUID +instruction. The CPUID function 0x8000001f reports information related +to SEV: 0x8000001f[eax]: Bit[1] indicates support for SEV - - 0x8000001f[ecx]: + ... + [ecx]: Bits[31:0] Number of encrypted guests supported simultaneously If support for SEV is present, MSR 0xc001_0010 (MSR_K8_SYSCFG) and MSR 0xc001_0015 @@ -24,8 +26,8 @@ If support for SEV is present, MSR 0xc001_0010 (MSR_K8_SYSCFG) and MSR 0xc001_00 Bit[0] 1 = memory encryption can be enabled 0 = memory encryption can not be enabled -When SEV support is available, it can be enabled in a specific VM by setting SEV -bit before executing VMRUN. +When SEV support is available, it can be enabled in a specific VM by +setting the SEV bit before executing VMRUN. VMCB[0x90]: Bit[1] 1 = SEV is enabled @@ -45,182 +47,6 @@ 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 owners 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 expect. - -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 an -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 - -Te KVM_SEV_LAUNCH_SECRET command can be used by the hypevisor 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; -}; +See Documentation/virtual/kvm/api.txt for the commands KVM implements to +support common lifecycle events of SEV guests such as launching, running, +snapshotting, migrating and decommissioning. diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index e63a35fafef0..d48f338b67e0 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -3390,6 +3390,183 @@ invalid, if invalid pages are written to (e.g. after the end of memory) or if no page table is present for the addresses (e.g. when using hugepages). +4.109 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. + +4.110 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. + +4.111 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.112 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 + +4.113 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. + +4.114 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 */ +}; + +4.115 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. + +4.116 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. + +4.117 KVM_SEV_LAUNCH_SECRET + +Parameters (in): struct kvm_sev_launch_secret +Returns: 0 on success, -negative on error + +Te 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; +}; + 5. The kvm_run structure ------------------------ diff --git a/Documentation/x86/amd-memory-encryption.txt b/Documentation/x86/amd-memory-encryption.txt index afc41f544dab..b6b64b01692a 100644 --- a/Documentation/x86/amd-memory-encryption.txt +++ b/Documentation/x86/amd-memory-encryption.txt @@ -39,7 +39,7 @@ CPUID function 0x8000001f reports information related to SME: 0x8000001f[eax]: Bit[0] indicates support for SME Bit[1] indicates support for SEV - 0x8000001f[ebx]: + ... [ebx]: Bits[5:0] pagetable bit number used to activate memory encryption Bits[11:6] reduction in physical address space, in bits, when @@ -50,14 +50,14 @@ CPUID function 0x8000001f reports information related to SME: If support for SME is present, MSR 0xc00100010 (MSR_K8_SYSCFG) can be used to determine if SME is enabled and/or to enable memory encryption: - 0xc0010010: + 0xc001_0010: Bit[23] 0 = memory encryption features are disabled 1 = memory encryption features are enabled If SEV is supported, MSR 0xc0010131 (MSR_AMD64_SEV) can be used to determine if SEV is active: - 0xc0010131: + 0xc001_0131: Bit[0] 0 = memory encryption is not active 1 = memory encryption is active -- Regards/Gruss, Boris. SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg) --