Add AMD SEV guest live migration support
Subsystems (10)
v11 cover Add AMD SEV guest live migration support
From: Ashish Kalra <[email protected]>
The series add support for AMD SEV guest live migration commands. To protect the confidentiality of an SEV protected guest memory while in transit we need to use the SEV commands defined in SEV API spec [1].
SEV guest VMs have the concept of private and shared memory. Private memory is encrypted with the guest-specific key, while shared memory may be encrypted with hypervisor key. The commands provided by the SEV FW are meant to be used for the private memory only. The patch series introduces a new hypercall. The guest OS can use this hypercall to notify the page encryption status. If the page is encrypted with guest specific-key then we use SEV command during the migration. If page is not encrypted then fallback to default.
The patch adds new KVM_EXIT_DMA_SHARE/KVM_EXIT_DMA_UNSHARE hypercall to userspace exit functionality as a common interface from the guest back to the VMM and passing on the guest shared/unencrypted page information to the userspace VMM/Qemu. Qemu can consult this information during migration to know whether the page is encrypted.
This section descibes how the SEV live migration feature is negotiated between the host and guest, the host indicates this feature support via KVM_FEATURE_CPUID. The guest firmware (OVMF) detects this feature and sets a UEFI enviroment variable indicating OVMF support for live migration, the guest kernel also detects the host support for this feature via cpuid and in case of an EFI boot verifies if OVMF also supports this feature by getting the UEFI enviroment variable and if it set then enables live migration feature on host by writing to a custom MSR, if not booted under EFI, then it simply enables the feature by again writing to the custom MSR. The MSR is also handled by the userspace VMM/Qemu.
A branch containing these patches is available here:
https://github.com/AMDESE/linux/tree/sev-migration-v11
[1] https://developer.amd.com/wp-content/resources/55766.PDF
Changes since v10:
- Adds new KVM_EXIT_DMA_SHARE/KVM_EXIT_DMA_UNSHARE hypercall to userspace exit functionality as a common interface from the guest back to the KVM and passing on the guest shared/unencrypted region information to the userspace VMM/Qemu. KVM/host kernel does not maintain the guest shared memory regions information anymore.
- Remove implicit enabling of SEV live migration feature for an SEV guest, now this is explicitly in control of the userspace VMM/Qemu.
- Custom MSR handling is also now moved into userspace VMM/Qemu.
- As KVM does not maintain the guest shared memory region information anymore, sev_dbg_crypt() cannot bypass unencrypted guest memory regions without support from userspace VMM/Qemu.
Changes since v9:
- Transitioning from page encryption bitmap to the shared pages list to keep track of guest's shared/unencrypted memory regions.
- Move back to marking the complete _bss_decrypted section as decrypted in the shared pages list.
- Invoke a new function check_kvm_sev_migration() via kvm_init_platform() for guest to query for host-side support for SEV live migration and to enable the SEV live migration feature, to avoid #ifdefs in code
- Rename MSR_KVM_SEV_LIVE_MIG_EN to MSR_KVM_SEV_LIVE_MIGRATION.
- Invoke a new function handle_unencrypted_region() from sev_dbg_crypt() to bypass unencrypted guest memory regions.
Changes since v8:
- Rebasing to kvm next branch.
- Fixed and added comments as per review feedback on v8 patches.
- Removed implicitly enabling live migration for incoming VMs in in KVM_SET_PAGE_ENC_BITMAP, it is now done via KVM_SET_MSR ioctl.
- Adds support for bypassing unencrypted guest memory regions for DBG_DECRYPT API calls, guest memory region encryption status in sev_dbg_decrypt() is referenced using the page encryption bitmap.
Changes since v7:
- Removed the hypervisor specific hypercall/paravirt callback for SEV live migration and moved back to calling kvm_sev_hypercall3 directly.
- Fix build errors as
build error when CONFIG_HYPERVISOR_GUEST=y and CONFIG_AMD_MEM_ENCRYPT=n.
- Implicitly enabled live migration for incoming VM(s) to handle A->B->C->... VM migrations.
- Fixed Documentation as per comments on v6 patches.
- Fixed error return path in sev_send_update_data() as per comments on v6 patches.
Changes since v6:
- Rebasing to mainline and refactoring to the new split SVM infrastructre.
- Move to static allocation of the unified Page Encryption bitmap instead of the dynamic resizing of the bitmap, the static allocation is done implicitly by extending kvm_arch_commit_memory_region() callack to add svm specific x86_ops which can read the userspace provided memory region/memslots and calculate the amount of guest RAM managed by the KVM and grow the bitmap.
- Fixed KVM_SET_PAGE_ENC_BITMAP ioctl to set the whole bitmap instead of simply clearing specific bits.
- Removed KVM_PAGE_ENC_BITMAP_RESET ioctl, which is now performed using KVM_SET_PAGE_ENC_BITMAP.
- Extended guest support for enabling Live Migration feature by adding a check for UEFI environment variable indicating OVMF support for Live Migration feature and additionally checking for KVM capability for the same feature. If not booted under EFI, then we simply check for KVM capability.
- Add hypervisor specific hypercall for SEV live migration by adding a new paravirt callback as part of x86_hyper_runtime.
(x86 hypervisor specific runtime callbacks)
- Moving MSR handling for MSR_KVM_SEV_LIVE_MIG_EN into svm/sev code and adding check for SEV live migration enabled by guest in the KVM_GET_PAGE_ENC_BITMAP ioctl.
- Instead of the complete __bss_decrypted section, only specific variables such as hv_clock_boot and wall_clock are marked as decrypted in the page encryption bitmap
Changes since v5:
- Fix build errors as
Changes since v4:
- Host support has been added to extend KVM capabilities/feature bits to include a new KVM_FEATURE_SEV_LIVE_MIGRATION, which the guest can query for host-side support for SEV live migration and a new custom MSR MSR_KVM_SEV_LIVE_MIG_EN is added for guest to enable the SEV live migration feature.
- Ensure that _bss_decrypted section is marked as decrypted in the page encryption bitmap.
- Fixing KVM_GET_PAGE_ENC_BITMAP ioctl to return the correct bitmap as per the number of pages being requested by the user. Ensure that we only copy bmap->num_pages bytes in the userspace buffer, if bmap->num_pages is not byte aligned we read the trailing bits from the userspace and copy those bits as is. This fixes guest page(s) corruption issues observed after migration completion.
- Add kexec support for SEV Live Migration to reset the host's page encryption bitmap related to kernel specific page encryption status settings before we load a new kernel by kexec. We cannot reset the complete page encryption bitmap here as we need to retain the UEFI/OVMF firmware specific settings.
Changes since v3:
- Rebasing to mainline and testing.
- Adding a new KVM_PAGE_ENC_BITMAP_RESET ioctl, which resets the page encryption bitmap on a guest reboot event.
- Adding a more reliable sanity check for GPA range being passed to the hypercall to ensure that guest MMIO ranges are also marked in the page encryption bitmap.
Changes since v2:
- reset the page encryption bitmap on vcpu reboot
Changes since v1:
- Add support to share the page encryption between the source and target machine.
- Fix review feedbacks from Tom Lendacky.
- Add check to limit the session blob length.
- Update KVM_GET_PAGE_ENC_BITMAP icotl to use the base_gfn instead of the memory slot when querying the bitmap.
Ashish Kalra (5):
KVM: X86: Introduce KVM_HC_PAGE_ENC_STATUS hypercall
KVM: x86: Introduce new KVM_FEATURE_SEV_LIVE_MIGRATION feature &
Custom MSR.
EFI: Introduce the new AMD Memory Encryption GUID. x86/kvm: Add guest support for detecting and enabling SEV Live
Migration feature.
x86/kvm: Add kexec support for SEV Live Migration.
Brijesh Singh (8):
KVM: SVM: Add KVM_SEV SEND_START command
KVM: SVM: Add KVM_SEND_UPDATE_DATA command
KVM: SVM: Add KVM_SEV_SEND_FINISH command
KVM: SVM: Add support for KVM_SEV_RECEIVE_START command
KVM: SVM: Add KVM_SEV_RECEIVE_UPDATE_DATA command
KVM: SVM: Add KVM_SEV_RECEIVE_FINISH command
KVM: x86: Add AMD SEV specific Hypercall3
mm: x86: Invoke hypercall when page encryption status is changed
.../virt/kvm/amd-memory-encryption.rst | 120 ++++ Documentation/virt/kvm/api.rst | 18 + Documentation/virt/kvm/cpuid.rst | 5 + Documentation/virt/kvm/hypercalls.rst | 15 + Documentation/virt/kvm/msr.rst | 12 + arch/x86/include/asm/kvm_host.h | 2 + arch/x86/include/asm/kvm_para.h | 12 + arch/x86/include/asm/mem_encrypt.h | 8 + arch/x86/include/asm/paravirt.h | 10 + arch/x86/include/asm/paravirt_types.h | 2 + arch/x86/include/uapi/asm/kvm_para.h | 4 + arch/x86/kernel/kvm.c | 76 +++ arch/x86/kernel/paravirt.c | 1 + arch/x86/kvm/cpuid.c | 3 +- arch/x86/kvm/svm/sev.c | 514 ++++++++++++++++++ arch/x86/kvm/svm/svm.c | 24 + arch/x86/kvm/svm/svm.h | 2 + arch/x86/kvm/vmx/vmx.c | 1 + arch/x86/kvm/x86.c | 12 + arch/x86/mm/mem_encrypt.c | 98 +++- arch/x86/mm/pat/set_memory.c | 7 + include/linux/efi.h | 1 + include/linux/psp-sev.h | 8 +- include/uapi/linux/kvm.h | 47 ++ include/uapi/linux/kvm_para.h | 1 + 25 files changed, 997 insertions(+), 6 deletions(-)
Signature · 1 line
2.17.1
PATCH v11 1/13 KVM: SVM: Add KVM_SEV SEND_START command
From: Brijesh Singh <[email protected]>
The command is used to create an outgoing SEV guest encryption context.
--- .../virt/kvm/amd-memory-encryption.rst | 27 ++++ arch/x86/kvm/svm/sev.c | 125 ++++++++++++++++++ include/linux/psp-sev.h | 8 +- include/uapi/linux/kvm.h | 12 ++ 4 files changed, 168 insertions(+), 4 deletions(-)
Documentation/virt/kvm/amd-memory-encryption.rst +27 -0
@@ -284,6 +284,33 @@ Returns: 0 on success, -negative on error __u32 len; }; +10. KVM_SEV_SEND_START +---------------------- + +The KVM_SEV_SEND_START command can be used by the hypervisor to create an +outgoing guest encryption context. + +Parameters (in): struct kvm_sev_send_start + +Returns: 0 on success, -negative on error + +:: + struct kvm_sev_send_start { + __u32 policy; /* guest policy */ + + __u64 pdh_cert_uaddr; /* platform Diffie-Hellman certificate */ + __u32 pdh_cert_len; + + __u64 plat_certs_uaddr; /* platform certificate chain */ + __u32 plat_certs_len; + + __u64 amd_certs_uaddr; /* AMD certificate */ + __u32 amd_certs_len; + + __u64 session_uaddr; /* Guest session information */ + __u32 session_len; + }; + References ==========
arch/x86/kvm/svm/sev.c +125 -0
137 lines not on this page · raw message
include/linux/psp-sev.h +4 -4
@@ -326,11 +326,11 @@ struct sev_data_send_start {u64 pdh_cert_address;/* In */ u32 pdh_cert_len;/* In */ u32 reserved1; -u64 plat_cert_address;/* In */ -u32 plat_cert_len;/* In */ +u64 plat_certs_address;/* In */ +u32 plat_certs_len;/* In */ u32 reserved2; -u64 amd_cert_address;/* In */ -u32 amd_cert_len;/* In */ +u64 amd_certs_address;/* In */ +u32 amd_certs_len;/* In */ u32 reserved3;u64 session_address;/* In */ u32 session_len;/* In/Out */
include/uapi/linux/kvm.h +12 -0
@@ -1729,6 +1729,18 @@ struct kvm_sev_attestation_report {__u32 len; }; +struct kvm_sev_send_start { +__u32 policy; +__u64 pdh_cert_uaddr; +__u32 pdh_cert_len; +__u64 plat_certs_uaddr; +__u32 plat_certs_len; +__u64 amd_certs_uaddr; +__u32 amd_certs_len; +__u64 session_uaddr; +__u32 session_len; +}; +#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)#define KVM_DEV_ASSIGN_MASK_INTX (1 << 2)
Signature · 1 line
2.17.1
PATCH v11 2/13 KVM: SVM: Add KVM_SEND_UPDATE_DATA command
In reply to Ashish KalraFrom: Brijesh Singh <[email protected]>
The command is used for encrypting the guest memory region using the encryption context created with KVM_SEV_SEND_START.
--- .../virt/kvm/amd-memory-encryption.rst | 24 ++++ arch/x86/kvm/svm/sev.c | 122 ++++++++++++++++++ include/uapi/linux/kvm.h | 9 ++ 3 files changed, 155 insertions(+)
Documentation/virt/kvm/amd-memory-encryption.rst +24 -0
@@ -311,6 +311,30 @@ Returns: 0 on success, -negative on error __u32 session_len; }; +11. KVM_SEV_SEND_UPDATE_DATA +---------------------------- + +The KVM_SEV_SEND_UPDATE_DATA command can be used by the hypervisor to encrypt the +outgoing guest memory region with the encryption context creating using +KVM_SEV_SEND_START. + +Parameters (in): struct kvm_sev_send_update_data + +Returns: 0 on success, -negative on error + +:: + + struct kvm_sev_launch_send_update_data { + __u64 hdr_uaddr; /* userspace address containing the packet header */ + __u32 hdr_len; + + __u64 guest_uaddr; /* the source memory region to be encrypted */ + __u32 guest_len; + + __u64 trans_uaddr; /* the destition memory region */ + __u32 trans_len; + }; + References ==========
arch/x86/kvm/svm/sev.c +122 -0
146 lines not on this page · raw message
include/uapi/linux/kvm.h +9 -0
@@ -1741,6 +1741,15 @@ struct kvm_sev_send_start {__u32 session_len; }; +struct kvm_sev_send_update_data { +__u64 hdr_uaddr; +__u32 hdr_len; +__u64 guest_uaddr; +__u32 guest_len; +__u64 trans_uaddr; +__u32 trans_len; +}; +#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)#define KVM_DEV_ASSIGN_MASK_INTX (1 << 2)
Signature · 1 line
2.17.1
PATCH v11 3/13 KVM: SVM: Add KVM_SEV_SEND_FINISH command
In reply to Ashish KalraFrom: Brijesh Singh <[email protected]>
The command is used to finailize the encryption context created with KVM_SEV_SEND_START command.
--- .../virt/kvm/amd-memory-encryption.rst | 8 +++++++ arch/x86/kvm/svm/sev.c | 23 +++++++++++++++++++ 2 files changed, 31 insertions(+)
Documentation/virt/kvm/amd-memory-encryption.rst +8 -0
@@ -335,6 +335,14 @@ Returns: 0 on success, -negative on error __u32 trans_len; }; +12. KVM_SEV_SEND_FINISH +------------------------ + +After completion of the migration flow, the KVM_SEV_SEND_FINISH command can be +issued by the hypervisor to delete the encryption context. + +Returns: 0 on success, -negative on error + References ==========
arch/x86/kvm/svm/sev.c +23 -0
@@ -1350,6 +1350,26 @@ static int sev_send_update_data(struct kvm *kvm, struct kvm_sev_cmd *argp)return ret; } +static int sev_send_finish (struct kvm *kvm,struct kvm_sev_cmd *argp) +{ +struct kvm_sev_info *sev = &to_kvm_svm (kvm)->sev_info; +struct sev_data_send_finish *data; +int ret; + +if (!sev_guest (kvm)) +return -ENOTTY ; + + data =kzalloc (sizeof (*data),GFP_KERNEL ); +if (!data) +return -ENOMEM ; + + data->handle = sev->handle; + ret =sev_issue_cmd (kvm,SEV_CMD_SEND_FINISH , data, &argp->error); + +kfree (data); +return ret; +} +int svm_mem_enc_op (struct kvm *kvm,void __user *argp) {struct kvm_sev_cmd sev_cmd;
@@ -1409,6 +1429,9 @@ int svm_mem_enc_op(struct kvm *kvm, void __user *argp)case KVM_SEV_SEND_UPDATE_DATA : r =sev_send_update_data (kvm, &sev_cmd);break ; +case KVM_SEV_SEND_FINISH : + r =sev_send_finish (kvm, &sev_cmd); +break ;default : r = -EINVAL ; goto out;
Signature · 1 line
2.17.1
PATCH v11 4/13 KVM: SVM: Add support for KVM_SEV_RECEIVE_START command
In reply to Ashish KalraFrom: Brijesh Singh <[email protected]>
The command is used to create the encryption context for an incoming SEV guest. The encryption context can be later used by the hypervisor to import the incoming data into the SEV guest memory space.
--- .../virt/kvm/amd-memory-encryption.rst | 29 +++++++ arch/x86/kvm/svm/sev.c | 81 +++++++++++++++++++ include/uapi/linux/kvm.h | 9 +++ 3 files changed, 119 insertions(+)
Documentation/virt/kvm/amd-memory-encryption.rst +29 -0
@@ -343,6 +343,35 @@ issued by the hypervisor to delete the encryption context. Returns: 0 on success, -negative on error +13. KVM_SEV_RECEIVE_START +------------------------ + +The KVM_SEV_RECEIVE_START command is used for creating the memory encryption +context for an incoming SEV guest. To create the encryption context, the user must +provide a guest policy, the platform public Diffie-Hellman (PDH) key and session +information. + +Parameters: struct kvm_sev_receive_start (in/out) + +Returns: 0 on success, -negative on error + +:: + + struct kvm_sev_receive_start { + __u32 handle; /* if zero then firmware creates a new handle */ + __u32 policy; /* guest's policy */ + + __u64 pdh_uaddr; /* userspace address pointing to the PDH key */ + __u32 pdh_len; + + __u64 session_uaddr; /* userspace address which points to the guest session information */ + __u32 session_len; + }; + +On success, the 'handle' field contains a new handle and on error, a negative value. + +For more details, see SEV spec Section 6.12. + References ==========
arch/x86/kvm/svm/sev.c +81 -0
93 lines not on this page · raw message
include/uapi/linux/kvm.h +9 -0
@@ -1750,6 +1750,15 @@ struct kvm_sev_send_update_data {__u32 trans_len; }; +struct kvm_sev_receive_start { +__u32 handle; +__u32 policy; +__u64 pdh_uaddr; +__u32 pdh_len; +__u64 session_uaddr; +__u32 session_len; +}; +#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)#define KVM_DEV_ASSIGN_MASK_INTX (1 << 2)
Signature · 1 line
2.17.1
PATCH v11 5/13 KVM: SVM: Add KVM_SEV_RECEIVE_UPDATE_DATA command
In reply to Ashish KalraFrom: Brijesh Singh <[email protected]>
The command is used for copying the incoming buffer into the SEV guest memory space.
--- .../virt/kvm/amd-memory-encryption.rst | 24 ++++++ arch/x86/kvm/svm/sev.c | 79 +++++++++++++++++++ include/uapi/linux/kvm.h | 9 +++ 3 files changed, 112 insertions(+)
Documentation/virt/kvm/amd-memory-encryption.rst +24 -0
@@ -372,6 +372,30 @@ On success, the 'handle' field contains a new handle and on error, a negative va For more details, see SEV spec Section 6.12. +14. KVM_SEV_RECEIVE_UPDATE_DATA +---------------------------- + +The KVM_SEV_RECEIVE_UPDATE_DATA command can be used by the hypervisor to copy +the incoming buffers into the guest memory region with encryption context +created during the KVM_SEV_RECEIVE_START. + +Parameters (in): struct kvm_sev_receive_update_data + +Returns: 0 on success, -negative on error + +:: + + struct kvm_sev_launch_receive_update_data { + __u64 hdr_uaddr; /* userspace address containing the packet header */ + __u32 hdr_len; + + __u64 guest_uaddr; /* the destination guest memory region */ + __u32 guest_len; + + __u64 trans_uaddr; /* the incoming buffer memory region */ + __u32 trans_len; + }; + References ==========
arch/x86/kvm/svm/sev.c +79 -0
91 lines not on this page · raw message
include/uapi/linux/kvm.h +9 -0
@@ -1759,6 +1759,15 @@ struct kvm_sev_receive_start {__u32 session_len; }; +struct kvm_sev_receive_update_data { +__u64 hdr_uaddr; +__u32 hdr_len; +__u64 guest_uaddr; +__u32 guest_len; +__u64 trans_uaddr; +__u32 trans_len; +}; +#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)#define KVM_DEV_ASSIGN_MASK_INTX (1 << 2)
Signature · 1 line
2.17.1
PATCH v11 6/13 KVM: SVM: Add KVM_SEV_RECEIVE_FINISH command
In reply to Ashish KalraFrom: Brijesh Singh <[email protected]>
The command finalize the guest receiving process and make the SEV guest ready for the execution.
--- .../virt/kvm/amd-memory-encryption.rst | 8 +++++++ arch/x86/kvm/svm/sev.c | 23 +++++++++++++++++++ 2 files changed, 31 insertions(+)
Documentation/virt/kvm/amd-memory-encryption.rst +8 -0
@@ -396,6 +396,14 @@ Returns: 0 on success, -negative on error __u32 trans_len; }; +15. KVM_SEV_RECEIVE_FINISH +------------------------ + +After completion of the migration flow, the KVM_SEV_RECEIVE_FINISH command can be +issued by the hypervisor to make the guest ready for execution. + +Returns: 0 on success, -negative on error + References ==========
arch/x86/kvm/svm/sev.c +23 -0
@@ -1524,6 +1524,26 @@ static int sev_receive_update_data(struct kvm *kvm, struct kvm_sev_cmd *argp)return ret; } +static int sev_receive_finish (struct kvm *kvm,struct kvm_sev_cmd *argp) +{ +struct kvm_sev_info *sev = &to_kvm_svm (kvm)->sev_info; +struct sev_data_receive_finish *data; +int ret; + +if (!sev_guest (kvm)) +return -ENOTTY ; + + data =kzalloc (sizeof (*data),GFP_KERNEL ); +if (!data) +return -ENOMEM ; + + data->handle = sev->handle; + ret =sev_issue_cmd (kvm,SEV_CMD_RECEIVE_FINISH , data, &argp->error); + +kfree (data); +return ret; +} +int svm_mem_enc_op (struct kvm *kvm,void __user *argp) {struct kvm_sev_cmd sev_cmd;
@@ -1592,6 +1612,9 @@ int svm_mem_enc_op(struct kvm *kvm, void __user *argp)case KVM_SEV_RECEIVE_UPDATE_DATA : r =sev_receive_update_data (kvm, &sev_cmd);break ; +case KVM_SEV_RECEIVE_FINISH : + r =sev_receive_finish (kvm, &sev_cmd); +break ;default : r = -EINVAL ; goto out;
Signature · 1 line
2.17.1
PATCH v11 7/13 KVM: x86: Add AMD SEV specific Hypercall3
In reply to Ashish KalraFrom: Brijesh Singh <[email protected]>
KVM hypercall framework relies on alternative framework to patch the VMCALL -> VMMCALL on AMD platform. If a hypercall is made before apply_alternative() is called then it defaults to VMCALL. The approach works fine on non SEV guest. A VMCALL would causes #UD, and hypervisor will be able to decode the instruction and do the right things. But when SEV is active, guest memory is encrypted with guest key and hypervisor will not be able to decode the instruction bytes.
Add SEV specific hypercall3, it unconditionally uses VMMCALL. The hypercall will be used by the SEV guest to notify encrypted pages to the hypervisor.
--- arch/x86/include/asm/kvm_para.h | 12 ++++++++++++ 1 file changed, 12 insertions(+)
arch/x86/include/asm/kvm_para.h +12 -0
@@ -85,6 +85,18 @@ static inline long kvm_hypercall4(unsigned int nr, unsigned long p1,return ret; } +static inline long kvm_sev_hypercall3 (unsigned int nr,unsigned long p1, +unsigned long p2,unsigned long p3) +{ +long ret; + + asmvolatile ("vmmcall" + :"=a" (ret) + :"a" (nr),"b" (p1),"c" (p2),"d" (p3) + :"memory" ); +return ret; +} +#ifdef CONFIG_KVM_GUEST bool kvm_para_available (void );unsigned int kvm_arch_para_features (void );
Signature · 1 line
2.17.1
PATCH v11 8/13 KVM: X86: Introduce KVM_HC_PAGE_ENC_STATUS hypercall
In reply to Ashish KalraFrom: Ashish Kalra <[email protected]>
This hypercall is used by the SEV guest to notify a change in the page encryption status to the hypervisor. The hypercall should be invoked only when the encryption attribute is changed from encrypted -> decrypted and vice versa. By default all guest pages are considered encrypted.
The hypercall exits to userspace to manage the guest shared regions and integrate with the userspace VMM's migration code.
The patch integrates and extends DMA_SHARE/UNSHARE hypercall to userspace exit functionality (arm64-specific) patch from Marc Zyngier, to avoid arch-specific stuff and have a common interface from the guest back to the VMM and sharing of the host handling of the hypercall to support use case for a guest to share memory with a host.
--- Documentation/virt/kvm/api.rst | 18 ++++++++ Documentation/virt/kvm/hypercalls.rst | 15 +++++++ arch/x86/include/asm/kvm_host.h | 2 + arch/x86/kvm/svm/sev.c | 61 +++++++++++++++++++++++++++ arch/x86/kvm/svm/svm.c | 2 + arch/x86/kvm/svm/svm.h | 2 + arch/x86/kvm/vmx/vmx.c | 1 + arch/x86/kvm/x86.c | 12 ++++++ include/uapi/linux/kvm.h | 8 ++++ include/uapi/linux/kvm_para.h | 1 + 10 files changed, 122 insertions(+)
Documentation/virt/kvm/api.rst +18 -0
@@ -5475,6 +5475,24 @@ Valid values for 'type' are: Userspace is expected to place the hypercall result into the appropriate field before invoking KVM_RUN again. +:: + + /* KVM_EXIT_DMA_SHARE / KVM_EXIT_DMA_UNSHARE */ + struct { + __u64 addr; + __u64 len; + __u64 ret; + } dma_sharing; + +This defines a common interface from the guest back to the KVM to support +use case for a guest to share memory with a host. + +The addr and len fields define the starting address and length of the +shared memory region. + +Userspace is expected to place the hypercall result into the "ret" field +before invoking KVM_RUN again. + :: /* Fix the size of the union. */
Documentation/virt/kvm/hypercalls.rst +15 -0
@@ -169,3 +169,18 @@ a0: destination APIC ID :Usage example: When sending a call-function IPI-many to vCPUs, yield if any of the IPI target vCPUs was preempted. + + +8. KVM_HC_PAGE_ENC_STATUS +------------------------- +:Architecture: x86 +:Status: active +:Purpose: Notify the encryption status changes in guest page table (SEV guest) + +a0: the guest physical address of the start page +a1: the number of pages +a2: encryption attribute + + Where: + * 1: Encryption attribute is set + * 0: Encryption attribute is cleared
arch/x86/include/asm/kvm_host.h +2 -0
@@ -1352,6 +1352,8 @@ struct kvm_x86_ops {int (*complete_emulated_msr)(struct kvm_vcpu *vcpu,int err);void (*vcpu_deliver_sipi_vector)(struct kvm_vcpu *vcpu,u8 vector); +int (*page_enc_status_hc)(struct kvm_vcpu *vcpu,unsigned long gpa, +unsigned long sz,unsigned long mode); };struct kvm_x86_nested_ops {
arch/x86/kvm/svm/sev.c +61 -0
67 lines not on this page · raw message
arch/x86/kvm/svm/svm.c +2 -0
@@ -4620,6 +4620,8 @@ static struct kvm_x86_ops svm_x86_ops __initdata = { .complete_emulated_msr = svm_complete_emulated_msr, .vcpu_deliver_sipi_vector = svm_vcpu_deliver_sipi_vector, + + .page_enc_status_hc = svm_page_enc_status_hc, };static struct kvm_x86_init_ops svm_init_ops__initdata = {
arch/x86/kvm/svm/svm.h +2 -0
@@ -451,6 +451,8 @@ int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr, bool has_error_code, u32 error_code);int nested_svm_exit_special (struct vcpu_svm *svm);void sync_nested_vmcb_control (struct vcpu_svm *svm); +int svm_page_enc_status_hc (struct kvm_vcpu *vcpu,unsigned long gpa, +unsigned long npages,unsigned long enc);extern struct kvm_x86_nested_ops svm_nested_ops;
arch/x86/kvm/vmx/vmx.c +1 -0
@@ -7748,6 +7748,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = { .can_emulate_instruction = vmx_can_emulate_instruction, .apic_init_signal_blocked = vmx_apic_init_signal_blocked, .migrate_timers = vmx_migrate_timers, + .page_enc_status_hc = NULL, .msr_filter_changed = vmx_msr_filter_changed, .complete_emulated_msr = kvm_complete_insn_gp,
arch/x86/kvm/x86.c +12 -0
@@ -8273,6 +8273,18 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)kvm_sched_yield (vcpu->kvm, a0); ret =0 ;break ; +case KVM_HC_PAGE_ENC_STATUS : { +int r; + + ret = -KVM_ENOSYS ; +if (kvm_x86_ops.page_enc_status_hc) { + r = kvm_x86_ops.page_enc_status_hc (vcpu, a0, a1, a2); +if (r >=0 ) +return r; + ret = r; + } +break ; + }default : ret = -KVM_ENOSYS ;break ;
include/uapi/linux/kvm.h +8 -0
@@ -268,6 +268,8 @@ struct kvm_xen_exit {#define KVM_EXIT_AP_RESET_HOLD 32#define KVM_EXIT_X86_BUS_LOCK 33#define KVM_EXIT_XEN 34 +#define KVM_EXIT_DMA_SHARE 35 +#define KVM_EXIT_DMA_UNSHARE 36/* For KVM_EXIT_INTERNAL_ERROR */ /* Emulate instruction failed. */
@@ -446,6 +448,12 @@ struct kvm_run { } msr;/* KVM_EXIT_XEN */ struct kvm_xen_exit xen; +/* KVM_EXIT_DMA_SHARE / KVM_EXIT_DMA_UNSHARE */ +struct { +__u64 addr; +__u64 len; +__u64 ret; + } dma_sharing;/* Fix the size of the union. */ char padding[256 ]; };
include/uapi/linux/kvm_para.h +1 -0
@@ -29,6 +29,7 @@#define KVM_HC_CLOCK_PAIRING 9#define KVM_HC_SEND_IPI 10#define KVM_HC_SCHED_YIELD 11 +#define KVM_HC_PAGE_ENC_STATUS 12/* * hypercalls use architecture specific
Signature · 1 line
2.17.1
Re: [PATCH v11 08/13] KVM: X86: Introduce KVM_HC_PAGE_ENC_STATUS hypercall
Quoted 112 lines · Ashish Kalra
From: Ashish Kalra <[email protected]>
This hypercall is used by the SEV guest to notify a change in the page encryption status to the hypervisor. The hypercall should be invoked only when the encryption attribute is changed from encrypted -> decrypted and vice versa. By default all guest pages are considered encrypted.
The hypercall exits to userspace to manage the guest shared regions and integrate with the userspace VMM's migration code.
The patch integrates and extends DMA_SHARE/UNSHARE hypercall to userspace exit functionality (arm64-specific) patch from Marc Zyngier, to avoid arch-specific stuff and have a common interface from the guest back to the VMM and sharing of the host handling of the hypercall to support use case for a guest to share memory with a host.
Cc Thomas Gleixner <[email protected]>Cc Ingo Molnar <[email protected]>Cc "H. Peter Anvin" <[email protected]>Cc Paolo Bonzini <[email protected]>Cc Joerg Roedel <[email protected]>Cc Borislav Petkov <[email protected]>Cc Tom Lendacky <[email protected]>Signed-off-by Brijesh Singh <[email protected]>Signed-off-by Ashish Kalra <[email protected]>--- Documentation/virt/kvm/api.rst | 18 ++++++++ Documentation/virt/kvm/hypercalls.rst | 15 +++++++ arch/x86/include/asm/kvm_host.h | 2 + arch/x86/kvm/svm/sev.c | 61 +++++++++++++++++++++++++++ arch/x86/kvm/svm/svm.c | 2 + arch/x86/kvm/svm/svm.h | 2 + arch/x86/kvm/vmx/vmx.c | 1 + arch/x86/kvm/x86.c | 12 ++++++ include/uapi/linux/kvm.h | 8 ++++ include/uapi/linux/kvm_para.h | 1 + 10 files changed, 122 insertions(+)Documentation/virt/kvm/api.rst +18
-0@@ -5475,6 +5475,24 @@ Valid values for 'type' are: Userspace is expected to place the hypercall result into the appropriate field before invoking KVM_RUN again. +:: + + /* KVM_EXIT_DMA_SHARE / KVM_EXIT_DMA_UNSHARE */ + struct { + __u64 addr; + __u64 len; + __u64 ret; + } dma_sharing; + +This defines a common interface from the guest back to the KVM to support +use case for a guest to share memory with a host. + +The addr and len fields define the starting address and length of the +shared memory region. + +Userspace is expected to place the hypercall result into the "ret" field +before invoking KVM_RUN again. + :: /* Fix the size of the union. */Documentation/virt/kvm/hypercalls.rst +15
-0@@ -169,3 +169,18 @@ a0: destination APIC ID :Usage example: When sending a call-function IPI-many to vCPUs, yield if any of the IPI target vCPUs was preempted. + + +8. KVM_HC_PAGE_ENC_STATUS +------------------------- +:Architecture: x86 +:Status: active +:Purpose: Notify the encryption status changes in guest page table (SEV guest) + +a0: the guest physical address of the start page +a1: the number of pages +a2: encryption attribute + + Where: + * 1: Encryption attribute is set + * 0: Encryption attribute is clearedarch/x86/include/asm/kvm_host.h +2
-0@@ -1352,6 +1352,8 @@ struct kvm_x86_ops {int (*complete_emulated_msr)(struct kvm_vcpu *vcpu,int err);void (*vcpu_deliver_sipi_vector)(struct kvm_vcpu *vcpu,u8 vector); +int (*page_enc_status_hc)(struct kvm_vcpu *vcpu,unsigned long gpa, +unsigned long sz,unsigned long mode); };struct kvm_x86_nested_ops {arch/x86/kvm/svm/sev.c +0
-0
arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1549
Quoted 6 lines
arch/x86/kvm/svm/sev.c +3
-0@@ -1544,6 +1544,67 @@ static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp)return ret; } +static int sev_complete_userspace_page_enc_status_hc (struct kvm_vcpu *vcpu) +{ + vcpu->run->exit_reason =0 ;
I don't believe you need to clear exit_reason: it's universally set on exit.
Quoted 106 lines
arch/x86/kvm/svm/sev.c +58
-0+kvm_rax_write (vcpu, vcpu->run->dma_sharing.ret); + ++vcpu->stat.hypercalls; +return kvm_skip_emulated_instruction (vcpu); +} + +int svm_page_enc_status_hc (struct kvm_vcpu *vcpu,unsigned long gpa, +unsigned long npages,unsigned long enc) +{ +kvm_pfn_t pfn_start, pfn_end; +struct kvm *kvm = vcpu->kvm; +gfn_t gfn_start, gfn_end; + +if (!sev_guest (kvm)) +return -EINVAL ; + +if (!npages) +return 0 ; + + gfn_start =gpa_to_gfn (gpa); + gfn_end = gfn_start + npages; + +/* out of bound access error check */ +if (gfn_end <= gfn_start) +return -EINVAL ; + +/* lets make sure that gpa exist in our memslot */ + pfn_start =gfn_to_pfn (kvm, gfn_start); + pfn_end =gfn_to_pfn (kvm, gfn_end); + +if (is_error_noslot_pfn (pfn_start) && !is_noslot_pfn (pfn_start)) { +/* +* Allow guest MMIO range(s) to be added +* to the shared pages list. +*/ +return -EINVAL ; + } + +if (is_error_noslot_pfn (pfn_end) && !is_noslot_pfn (pfn_end)) { +/* +* Allow guest MMIO range(s) to be added +* to the shared pages list. +*/ +return -EINVAL ; + } + +if (enc) + vcpu->run->exit_reason =KVM_EXIT_DMA_UNSHARE ; +else + vcpu->run->exit_reason =KVM_EXIT_DMA_SHARE ; + + vcpu->run->dma_sharing.addr = gfn_start; + vcpu->run->dma_sharing.len = npages *PAGE_SIZE ; + vcpu->arch.complete_userspace_io = + sev_complete_userspace_page_enc_status_hc; + +return 0 ; +} +int svm_mem_enc_op (struct kvm *kvm,void __user *argp) {struct kvm_sev_cmd sev_cmd;arch/x86/kvm/svm/svm.c +2
-0@@ -4620,6 +4620,8 @@ static struct kvm_x86_ops svm_x86_ops __initdata = { .complete_emulated_msr = svm_complete_emulated_msr, .vcpu_deliver_sipi_vector = svm_vcpu_deliver_sipi_vector, + + .page_enc_status_hc = svm_page_enc_status_hc, };static struct kvm_x86_init_ops svm_init_ops__initdata = {arch/x86/kvm/svm/svm.h +2
-0@@ -451,6 +451,8 @@ int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr, bool has_error_code, u32 error_code);int nested_svm_exit_special (struct vcpu_svm *svm);void sync_nested_vmcb_control (struct vcpu_svm *svm); +int svm_page_enc_status_hc (struct kvm_vcpu *vcpu,unsigned long gpa, +unsigned long npages,unsigned long enc);extern struct kvm_x86_nested_ops svm_nested_ops;arch/x86/kvm/vmx/vmx.c +1
-0@@ -7748,6 +7748,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = { .can_emulate_instruction = vmx_can_emulate_instruction, .apic_init_signal_blocked = vmx_apic_init_signal_blocked, .migrate_timers = vmx_migrate_timers, + .page_enc_status_hc = NULL, .msr_filter_changed = vmx_msr_filter_changed, .complete_emulated_msr = kvm_complete_insn_gp,arch/x86/kvm/x86.c +0
-0@@ -8273,6 +8273,18 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)kvm_sched_yield (vcpu->kvm, a0); ret =0 ;
arch/x86/kvm/x86.c int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) · line 8284
Quoted 10 lines
arch/x86/kvm/x86.c +9
-0break ; +case KVM_HC_PAGE_ENC_STATUS : { +int r; + + ret = -KVM_ENOSYS ; +if (kvm_x86_ops.page_enc_status_hc) { + r = kvm_x86_ops.page_enc_status_hc (vcpu, a0, a1, a2); +if (r >=0 ) +return r; + ret = r;
Style nit: Why not just set ret, and return ret if ret >=0?
This looks good. I just had a few nitpicks.
Re: [PATCH v11 08/13] KVM: X86: Introduce KVM_HC_PAGE_ENC_STATUS hypercall
Quoted 230 lines · Steve Rutherford
Quoted 112 lines · Ashish Kalra
From: Ashish Kalra <[email protected]>
This hypercall is used by the SEV guest to notify a change in the page encryption status to the hypervisor. The hypercall should be invoked only when the encryption attribute is changed from encrypted -> decrypted and vice versa. By default all guest pages are considered encrypted.
The hypercall exits to userspace to manage the guest shared regions and integrate with the userspace VMM's migration code.
The patch integrates and extends DMA_SHARE/UNSHARE hypercall to userspace exit functionality (arm64-specific) patch from Marc Zyngier, to avoid arch-specific stuff and have a common interface from the guest back to the VMM and sharing of the host handling of the hypercall to support use case for a guest to share memory with a host.
Cc Thomas Gleixner <[email protected]>Cc Ingo Molnar <[email protected]>Cc "H. Peter Anvin" <[email protected]>Cc Paolo Bonzini <[email protected]>Cc Joerg Roedel <[email protected]>Cc Borislav Petkov <[email protected]>Cc Tom Lendacky <[email protected]>Signed-off-by Brijesh Singh <[email protected]>Signed-off-by Ashish Kalra <[email protected]>--- Documentation/virt/kvm/api.rst | 18 ++++++++ Documentation/virt/kvm/hypercalls.rst | 15 +++++++ arch/x86/include/asm/kvm_host.h | 2 + arch/x86/kvm/svm/sev.c | 61 +++++++++++++++++++++++++++ arch/x86/kvm/svm/svm.c | 2 + arch/x86/kvm/svm/svm.h | 2 + arch/x86/kvm/vmx/vmx.c | 1 + arch/x86/kvm/x86.c | 12 ++++++ include/uapi/linux/kvm.h | 8 ++++ include/uapi/linux/kvm_para.h | 1 + 10 files changed, 122 insertions(+)Documentation/virt/kvm/api.rst +18
-0@@ -5475,6 +5475,24 @@ Valid values for 'type' are: Userspace is expected to place the hypercall result into the appropriate field before invoking KVM_RUN again. +:: + + /* KVM_EXIT_DMA_SHARE / KVM_EXIT_DMA_UNSHARE */ + struct { + __u64 addr; + __u64 len; + __u64 ret; + } dma_sharing; + +This defines a common interface from the guest back to the KVM to support +use case for a guest to share memory with a host. + +The addr and len fields define the starting address and length of the +shared memory region. + +Userspace is expected to place the hypercall result into the "ret" field +before invoking KVM_RUN again. + :: /* Fix the size of the union. */Documentation/virt/kvm/hypercalls.rst +15
-0@@ -169,3 +169,18 @@ a0: destination APIC ID :Usage example: When sending a call-function IPI-many to vCPUs, yield if any of the IPI target vCPUs was preempted. + + +8. KVM_HC_PAGE_ENC_STATUS +------------------------- +:Architecture: x86 +:Status: active +:Purpose: Notify the encryption status changes in guest page table (SEV guest) + +a0: the guest physical address of the start page +a1: the number of pages +a2: encryption attribute + + Where: + * 1: Encryption attribute is set + * 0: Encryption attribute is clearedarch/x86/include/asm/kvm_host.h +2
-0@@ -1352,6 +1352,8 @@ struct kvm_x86_ops {int (*complete_emulated_msr)(struct kvm_vcpu *vcpu,int err);void (*vcpu_deliver_sipi_vector)(struct kvm_vcpu *vcpu,u8 vector); +int (*page_enc_status_hc)(struct kvm_vcpu *vcpu,unsigned long gpa, +unsigned long sz,unsigned long mode); };struct kvm_x86_nested_ops {arch/x86/kvm/svm/sev.c +0
-0arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1549
Quoted 6 lines
arch/x86/kvm/svm/sev.c +3
-0@@ -1544,6 +1544,67 @@ static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp)return ret; } +static int sev_complete_userspace_page_enc_status_hc (struct kvm_vcpu *vcpu) +{ + vcpu->run->exit_reason =0 ;I don't believe you need to clear
exit_reason: it's universally set on exit.Quoted 109 lines
arch/x86/kvm/svm/sev.c +58
-0+kvm_rax_write (vcpu, vcpu->run->dma_sharing.ret); + ++vcpu->stat.hypercalls; +return kvm_skip_emulated_instruction (vcpu); +} + +int svm_page_enc_status_hc (struct kvm_vcpu *vcpu,unsigned long gpa, +unsigned long npages,unsigned long enc) +{ +kvm_pfn_t pfn_start, pfn_end; +struct kvm *kvm = vcpu->kvm; +gfn_t gfn_start, gfn_end; + +if (!sev_guest (kvm)) +return -EINVAL ; + +if (!npages) +return 0 ; + + gfn_start =gpa_to_gfn (gpa); + gfn_end = gfn_start + npages; + +/* out of bound access error check */ +if (gfn_end <= gfn_start) +return -EINVAL ; + +/* lets make sure that gpa exist in our memslot */ + pfn_start =gfn_to_pfn (kvm, gfn_start); + pfn_end =gfn_to_pfn (kvm, gfn_end); + +if (is_error_noslot_pfn (pfn_start) && !is_noslot_pfn (pfn_start)) { +/* +* Allow guest MMIO range(s) to be added +* to the shared pages list. +*/ +return -EINVAL ; + } + +if (is_error_noslot_pfn (pfn_end) && !is_noslot_pfn (pfn_end)) { +/* +* Allow guest MMIO range(s) to be added +* to the shared pages list. +*/ +return -EINVAL ; + } + +if (enc) + vcpu->run->exit_reason =KVM_EXIT_DMA_UNSHARE ; +else + vcpu->run->exit_reason =KVM_EXIT_DMA_SHARE ; + + vcpu->run->dma_sharing.addr = gfn_start; + vcpu->run->dma_sharing.len = npages *PAGE_SIZE ; + vcpu->arch.complete_userspace_io = + sev_complete_userspace_page_enc_status_hc; + +return 0 ; +} +int svm_mem_enc_op (struct kvm *kvm,void __user *argp) {struct kvm_sev_cmd sev_cmd;arch/x86/kvm/svm/svm.c +2
-0@@ -4620,6 +4620,8 @@ static struct kvm_x86_ops svm_x86_ops __initdata = { .complete_emulated_msr = svm_complete_emulated_msr, .vcpu_deliver_sipi_vector = svm_vcpu_deliver_sipi_vector, + + .page_enc_status_hc = svm_page_enc_status_hc, };static struct kvm_x86_init_ops svm_init_ops__initdata = {arch/x86/kvm/svm/svm.h +2
-0@@ -451,6 +451,8 @@ int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr, bool has_error_code, u32 error_code);int nested_svm_exit_special (struct vcpu_svm *svm);void sync_nested_vmcb_control (struct vcpu_svm *svm); +int svm_page_enc_status_hc (struct kvm_vcpu *vcpu,unsigned long gpa, +unsigned long npages,unsigned long enc);extern struct kvm_x86_nested_ops svm_nested_ops;arch/x86/kvm/vmx/vmx.c +1
-0@@ -7748,6 +7748,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = { .can_emulate_instruction = vmx_can_emulate_instruction, .apic_init_signal_blocked = vmx_apic_init_signal_blocked, .migrate_timers = vmx_migrate_timers, + .page_enc_status_hc = NULL, .msr_filter_changed = vmx_msr_filter_changed, .complete_emulated_msr = kvm_complete_insn_gp,arch/x86/kvm/x86.c +2
-0@@ -8273,6 +8273,18 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)kvm_sched_yield (vcpu->kvm, a0); ret =0 ;break ; +case KVM_HC_PAGE_ENC_STATUS : { +int r;
Quoted 9 lines
arch/x86/kvm/x86.c int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) · line 8284
Quoted 7 lines
arch/x86/kvm/x86.c +7
-0+ + ret = -KVM_ENOSYS ; +if (kvm_x86_ops.page_enc_status_hc) { + r = kvm_x86_ops.page_enc_status_hc (vcpu, a0, a1, a2); +if (r >=0 ) +return r; + ret = r;Style nit: Why not just set ret, and return ret if ret >=0?
But ret is "unsigned long", if i set ret and return, then i will return to guest even in case of error above ?
Thanks,
Ashish
Quoted 2 lines
This looks good. I just had a few nitpicks.
Reviewed-by Steve Rutherford <[email protected]>
Sean Christopherson
maintainerRe: [PATCH v11 08/13] KVM: X86: Introduce KVM_HC_PAGE_ENC_STATUS hypercall
Quoted 22 lines · Ashish Kalra
Quoted 11 lines · Steve Rutherford
Quoted 10 lines · Ashish Kalra
arch/x86/kvm/x86.c +2
-0@@ -8273,6 +8273,18 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)kvm_sched_yield (vcpu->kvm, a0); ret =0 ;break ; +case KVM_HC_PAGE_ENC_STATUS : { +int r;Quoted 9 lines
arch/x86/kvm/x86.c int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) · line 8284
Quoted 7 lines
arch/x86/kvm/x86.c +7
-0+ + ret = -KVM_ENOSYS ; +if (kvm_x86_ops.page_enc_status_hc) { + r = kvm_x86_ops.page_enc_status_hc (vcpu, a0, a1, a2); +if (r >=0 ) +return r; + ret = r;Style nit: Why not just set ret, and return ret if ret >=0?
Quoted 2 lines
But ret is "unsigned long", if i set ret and return, then i will return to guest even in case of error above ?
As proposed, svm_page_enc_status_hc() already hooks complete_userspace_io(), so this could be hoisted out of the switch statement.
arch/x86/kvm/x86.c +4 -0
@@ -8261,6 +8261,10 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) goto out; } +/* comment goes here */ +if (nr ==KVM_HC_PAGE_ENC_STATUS && kvm_x86_ops.page_enc_status_hc) +return static_call (kvm_x86_page_enc_status_hc (vcpu, a0, a1, a2)); + ret = -KVM_ENOSYS ;switch (nr) {
Sean Christopherson
maintainerRe: [PATCH v11 08/13] KVM: X86: Introduce KVM_HC_PAGE_ENC_STATUS hypercall
Quoted 34 lines · Sean Christopherson
Quoted 22 lines · Ashish Kalra
Quoted 11 lines · Steve Rutherford
Quoted 10 lines · Ashish Kalra
arch/x86/kvm/x86.c +2
-0@@ -8273,6 +8273,18 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)kvm_sched_yield (vcpu->kvm, a0); ret =0 ;break ; +case KVM_HC_PAGE_ENC_STATUS : { +int r;Quoted 9 lines
arch/x86/kvm/x86.c int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) · line 8284
Quoted 7 lines
arch/x86/kvm/x86.c +7
-0+ + ret = -KVM_ENOSYS ; +if (kvm_x86_ops.page_enc_status_hc) { + r = kvm_x86_ops.page_enc_status_hc (vcpu, a0, a1, a2); +if (r >=0 ) +return r; + ret = r;Style nit: Why not just set ret, and return ret if ret >=0?
Quoted 2 lines
But ret is "unsigned long", if i set ret and return, then i will return to guest even in case of error above ?
As proposed,
svm_page_enc_status_hc()already hookscomplete_userspace_io(), so this could be hoisted out of the switch statement.arch/x86/kvm/x86.c +0
-0
arch/x86/kvm/x86.c int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) · line 8266
Quoted 6 lines
arch/x86/kvm/x86.c +3
-0@@ -8261,6 +8261,10 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) goto out; } +/* comment goes here */ +if (nr ==KVM_HC_PAGE_ENC_STATUS && kvm_x86_ops.page_enc_status_hc) +return static_call (kvm_x86_page_enc_status_hc (vcpu, a0, a1, a2));
Gah, the SEV implementation can also return -EINVAL, and that should fail the hypercall, not kill the guest. Normally we try to avoid output params, but in this case it might be less ugly to do:
case KVM_HC_PAGE_ENC_STATUS: {
if (!kvm_x86_ops.page_enc_status_hc)
break;
if (!static_call(kvm_x86_page_enc_status_hc(vcpu, a0, a1,
a2, &ret));
return 0;
break;Quoted 5 lines
arch/x86/kvm/x86.c +1
-0+ ret = -KVM_ENOSYS ;switch (nr) {
Re: [PATCH v11 08/13] KVM: X86: Introduce KVM_HC_PAGE_ENC_STATUS hypercall
In reply to Ashish KalraQuoted 241 lines · Ashish Kalra
Quoted 230 lines · Steve Rutherford
Quoted 112 lines · Ashish Kalra
From: Ashish Kalra <[email protected]>
This hypercall is used by the SEV guest to notify a change in the page encryption status to the hypervisor. The hypercall should be invoked only when the encryption attribute is changed from encrypted -> decrypted and vice versa. By default all guest pages are considered encrypted.
The hypercall exits to userspace to manage the guest shared regions and integrate with the userspace VMM's migration code.
The patch integrates and extends DMA_SHARE/UNSHARE hypercall to userspace exit functionality (arm64-specific) patch from Marc Zyngier, to avoid arch-specific stuff and have a common interface from the guest back to the VMM and sharing of the host handling of the hypercall to support use case for a guest to share memory with a host.
Cc Thomas Gleixner <[email protected]>Cc Ingo Molnar <[email protected]>Cc "H. Peter Anvin" <[email protected]>Cc Paolo Bonzini <[email protected]>Cc Joerg Roedel <[email protected]>Cc Borislav Petkov <[email protected]>Cc Tom Lendacky <[email protected]>Signed-off-by Brijesh Singh <[email protected]>Signed-off-by Ashish Kalra <[email protected]>--- Documentation/virt/kvm/api.rst | 18 ++++++++ Documentation/virt/kvm/hypercalls.rst | 15 +++++++ arch/x86/include/asm/kvm_host.h | 2 + arch/x86/kvm/svm/sev.c | 61 +++++++++++++++++++++++++++ arch/x86/kvm/svm/svm.c | 2 + arch/x86/kvm/svm/svm.h | 2 + arch/x86/kvm/vmx/vmx.c | 1 + arch/x86/kvm/x86.c | 12 ++++++ include/uapi/linux/kvm.h | 8 ++++ include/uapi/linux/kvm_para.h | 1 + 10 files changed, 122 insertions(+)Documentation/virt/kvm/api.rst +18
-0@@ -5475,6 +5475,24 @@ Valid values for 'type' are: Userspace is expected to place the hypercall result into the appropriate field before invoking KVM_RUN again. +:: + + /* KVM_EXIT_DMA_SHARE / KVM_EXIT_DMA_UNSHARE */ + struct { + __u64 addr; + __u64 len; + __u64 ret; + } dma_sharing; + +This defines a common interface from the guest back to the KVM to support +use case for a guest to share memory with a host. + +The addr and len fields define the starting address and length of the +shared memory region. + +Userspace is expected to place the hypercall result into the "ret" field +before invoking KVM_RUN again. + :: /* Fix the size of the union. */Documentation/virt/kvm/hypercalls.rst +15
-0@@ -169,3 +169,18 @@ a0: destination APIC ID :Usage example: When sending a call-function IPI-many to vCPUs, yield if any of the IPI target vCPUs was preempted. + + +8. KVM_HC_PAGE_ENC_STATUS +------------------------- +:Architecture: x86 +:Status: active +:Purpose: Notify the encryption status changes in guest page table (SEV guest) + +a0: the guest physical address of the start page +a1: the number of pages +a2: encryption attribute + + Where: + * 1: Encryption attribute is set + * 0: Encryption attribute is clearedarch/x86/include/asm/kvm_host.h +2
-0@@ -1352,6 +1352,8 @@ struct kvm_x86_ops {int (*complete_emulated_msr)(struct kvm_vcpu *vcpu,int err);void (*vcpu_deliver_sipi_vector)(struct kvm_vcpu *vcpu,u8 vector); +int (*page_enc_status_hc)(struct kvm_vcpu *vcpu,unsigned long gpa, +unsigned long sz,unsigned long mode); };struct kvm_x86_nested_ops {arch/x86/kvm/svm/sev.c +0
-0arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1549
Quoted 6 lines
arch/x86/kvm/svm/sev.c +3
-0@@ -1544,6 +1544,67 @@ static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp)return ret; } +static int sev_complete_userspace_page_enc_status_hc (struct kvm_vcpu *vcpu) +{ + vcpu->run->exit_reason =0 ;I don't believe you need to clear
exit_reason: it's universally set on exit.Quoted 109 lines
arch/x86/kvm/svm/sev.c +58
-0+kvm_rax_write (vcpu, vcpu->run->dma_sharing.ret); + ++vcpu->stat.hypercalls; +return kvm_skip_emulated_instruction (vcpu); +} + +int svm_page_enc_status_hc (struct kvm_vcpu *vcpu,unsigned long gpa, +unsigned long npages,unsigned long enc) +{ +kvm_pfn_t pfn_start, pfn_end; +struct kvm *kvm = vcpu->kvm; +gfn_t gfn_start, gfn_end; + +if (!sev_guest (kvm)) +return -EINVAL ; + +if (!npages) +return 0 ; + + gfn_start =gpa_to_gfn (gpa); + gfn_end = gfn_start + npages; + +/* out of bound access error check */ +if (gfn_end <= gfn_start) +return -EINVAL ; + +/* lets make sure that gpa exist in our memslot */ + pfn_start =gfn_to_pfn (kvm, gfn_start); + pfn_end =gfn_to_pfn (kvm, gfn_end); + +if (is_error_noslot_pfn (pfn_start) && !is_noslot_pfn (pfn_start)) { +/* +* Allow guest MMIO range(s) to be added +* to the shared pages list. +*/ +return -EINVAL ; + } + +if (is_error_noslot_pfn (pfn_end) && !is_noslot_pfn (pfn_end)) { +/* +* Allow guest MMIO range(s) to be added +* to the shared pages list. +*/ +return -EINVAL ; + } + +if (enc) + vcpu->run->exit_reason =KVM_EXIT_DMA_UNSHARE ; +else + vcpu->run->exit_reason =KVM_EXIT_DMA_SHARE ; + + vcpu->run->dma_sharing.addr = gfn_start; + vcpu->run->dma_sharing.len = npages *PAGE_SIZE ; + vcpu->arch.complete_userspace_io = + sev_complete_userspace_page_enc_status_hc; + +return 0 ; +} +int svm_mem_enc_op (struct kvm *kvm,void __user *argp) {struct kvm_sev_cmd sev_cmd;arch/x86/kvm/svm/svm.c +2
-0@@ -4620,6 +4620,8 @@ static struct kvm_x86_ops svm_x86_ops __initdata = { .complete_emulated_msr = svm_complete_emulated_msr, .vcpu_deliver_sipi_vector = svm_vcpu_deliver_sipi_vector, + + .page_enc_status_hc = svm_page_enc_status_hc, };static struct kvm_x86_init_ops svm_init_ops__initdata = {arch/x86/kvm/svm/svm.h +2
-0@@ -451,6 +451,8 @@ int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr, bool has_error_code, u32 error_code);int nested_svm_exit_special (struct vcpu_svm *svm);void sync_nested_vmcb_control (struct vcpu_svm *svm); +int svm_page_enc_status_hc (struct kvm_vcpu *vcpu,unsigned long gpa, +unsigned long npages,unsigned long enc);extern struct kvm_x86_nested_ops svm_nested_ops;arch/x86/kvm/vmx/vmx.c +1
-0@@ -7748,6 +7748,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = { .can_emulate_instruction = vmx_can_emulate_instruction, .apic_init_signal_blocked = vmx_apic_init_signal_blocked, .migrate_timers = vmx_migrate_timers, + .page_enc_status_hc = NULL, .msr_filter_changed = vmx_msr_filter_changed, .complete_emulated_msr = kvm_complete_insn_gp,arch/x86/kvm/x86.c +2
-0@@ -8273,6 +8273,18 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)kvm_sched_yield (vcpu->kvm, a0); ret =0 ;break ; +case KVM_HC_PAGE_ENC_STATUS : { +int r;Quoted 9 lines
arch/x86/kvm/x86.c int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) · line 8284
Quoted 7 lines
arch/x86/kvm/x86.c +7
-0+ + ret = -KVM_ENOSYS ; +if (kvm_x86_ops.page_enc_status_hc) { + r = kvm_x86_ops.page_enc_status_hc (vcpu, a0, a1, a2); +if (r >=0 ) +return r; + ret = r;Style nit: Why not just set ret, and return ret if ret >=0?
Quoted 3 lines
But ret is "unsigned long", if i set ret and return, then i will return to guest even in case of error above ?
I actually meant that we will return to userspace in case of errors above, instead of returning to guest with errors indicated above.
But i am now more inclined to adopting Sean's latest commments on this patches and removing the kvm_x86_ops hook and instead using a flag to indicate support for this hypercall.
Thanks,
Ashish
Quoted 2 lines
Quoted 2 lines
This looks good. I just had a few nitpicks.
Reviewed-by Steve Rutherford <[email protected]>
Sean Christopherson
maintainerRe: [PATCH v11 08/13] KVM: X86: Introduce KVM_HC_PAGE_ENC_STATUS hypercall
In reply to Ashish KalraQuoted 1 line · Ashish Kalra
From: Ashish Kalra <[email protected]>
...
Quoted 31 lines
arch/x86/include/asm/kvm_host.h +2
-0@@ -1352,6 +1352,8 @@ struct kvm_x86_ops {int (*complete_emulated_msr)(struct kvm_vcpu *vcpu,int err);void (*vcpu_deliver_sipi_vector)(struct kvm_vcpu *vcpu,u8 vector); +int (*page_enc_status_hc)(struct kvm_vcpu *vcpu,unsigned long gpa, +unsigned long sz,unsigned long mode); };struct kvm_x86_nested_ops {arch/x86/kvm/svm/sev.c +10
-0@@ -1544,6 +1544,67 @@ static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp)return ret; } +static int sev_complete_userspace_page_enc_status_hc (struct kvm_vcpu *vcpu) +{ + vcpu->run->exit_reason =0 ; +kvm_rax_write (vcpu, vcpu->run->dma_sharing.ret); + ++vcpu->stat.hypercalls; +return kvm_skip_emulated_instruction (vcpu); +} + +int svm_page_enc_status_hc (struct kvm_vcpu *vcpu,unsigned long gpa, +unsigned long npages,unsigned long enc)
arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1566
Quoted 10 lines
arch/x86/kvm/svm/sev.c +10
-0+{ +kvm_pfn_t pfn_start, pfn_end; +struct kvm *kvm = vcpu->kvm; +gfn_t gfn_start, gfn_end; + +if (!sev_guest (kvm)) +return -EINVAL ; + +if (!npages) +return 0 ;
Parth of me thinks passing a zero size should be an error not a nop. Either way works, just feels a bit weird to allow this to be a nop.
arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1568
Quoted 2 lines
arch/x86/kvm/svm/sev.c +2
-0+ + gfn_start =gpa_to_gfn (gpa);
This should check that @gpa is aligned.
Quoted 15 lines
arch/x86/kvm/svm/sev.c +15
-0+ gfn_end = gfn_start + npages; + +/* out of bound access error check */ +if (gfn_end <= gfn_start) +return -EINVAL ; + +/* lets make sure that gpa exist in our memslot */ + pfn_start =gfn_to_pfn (kvm, gfn_start); + pfn_end =gfn_to_pfn (kvm, gfn_end); + +if (is_error_noslot_pfn (pfn_start) && !is_noslot_pfn (pfn_start)) { +/* +* Allow guest MMIO range(s) to be added +* to the shared pages list. +*/
arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1593
Quoted 10 lines
arch/x86/kvm/svm/sev.c +10
-0+return -EINVAL ; + } + +if (is_error_noslot_pfn (pfn_end) && !is_noslot_pfn (pfn_end)) { +/* +* Allow guest MMIO range(s) to be added +* to the shared pages list. +*/ +return -EINVAL ; + }
I don't think KVM should do any checks beyond gfn_end <= gfn_start. Just punt to userspace and give userspace full say over what is/isn't legal.
arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1598
Quoted 5 lines
arch/x86/kvm/svm/sev.c +5
-0+ +if (enc) + vcpu->run->exit_reason =KVM_EXIT_DMA_UNSHARE ; +else + vcpu->run->exit_reason =KVM_EXIT_DMA_SHARE ;
Use a single exit and pass "enc" via kvm_run. I also strongly dislike "DMA", there's no guarantee the guest is sharing memory for DMA.
I think we can usurp KVM_EXIT_HYPERCALL for this? E.g.
vcpu->run->exit_reason = KVM_EXIT_HYPERCALL; vcpu->run->hypercall.nr = KVM_HC_PAGE_ENC_STATUS; vcpu->run->hypercall.args[0] = gfn_start << PAGE_SHIFT; vcpu->run->hypercall.args[1] = npages * PAGE_SIZE; vcpu->run->hypercall.args[2] = enc; vcpu->run->hypercall.longmode = is_64_bit_mode(vcpu);
arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1600
Quoted 2 lines
arch/x86/kvm/svm/sev.c +2
-0+ + vcpu->run->dma_sharing.addr = gfn_start;
Addresses and pfns are not the same thing. If you're passing the size in bytes, then it's probably best to pass the gpa, not the gfn. Same for the params from the guest, they should be in the same "domain".
arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1603
Quoted 3 lines
arch/x86/kvm/svm/sev.c +3
-0+ vcpu->run->dma_sharing.len = npages *PAGE_SIZE ; + vcpu->arch.complete_userspace_io = + sev_complete_userspace_page_enc_status_hc;
I vote to drop the "userspace" part, it's already quite verbose.
vcpu->arch.complete_userspace_io = sev_complete_page_enc_status_hc;
Quoted 4 lines
arch/x86/kvm/svm/sev.c +4
-0+ +return 0 ; +} +
..
Quoted 5 lines
arch/x86/kvm/x86.c +0
-0
arch/x86/kvm/x86.c int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) · line 8281
Quoted 9 lines
arch/x86/kvm/x86.c +6
-0@@ -8273,6 +8273,18 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)kvm_sched_yield (vcpu->kvm, a0); ret =0 ;break ; +case KVM_HC_PAGE_ENC_STATUS : { +int r; + + ret = -KVM_ENOSYS ; +if (kvm_x86_ops.page_enc_status_hc) { + r = kvm_x86_ops.page_enc_status_hc (vcpu, a0, a1, a2);
Use static_call().
arch/x86/kvm/x86.c int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) · line 8285
Quoted 4 lines
arch/x86/kvm/x86.c +4
-0+if (r >=0 ) +return r; + ret = r; + }
Hmm, an alternative to adding a kvm_x86_ops hook would be to tag the VM as supporting/allowing the hypercall. That would clean up this code, ensure VMX and SVM don't end up creating a different userspace ABI, and make it easier to reuse the hypercall in the future (I'm still hopeful :-) ). E.g.
case KVM_HC_PAGE_ENC_STATUS: {
u64 gpa = a0, nr_bytes = a1;
if (!vcpu->kvm->arch.page_enc_hc_enable)
break;
if (!PAGE_ALIGNED(gpa) || !PAGE_ALIGNED(nr_bytes) ||
!nr_bytes || gpa + nr_bytes <= gpa)) {
ret = -EINVAL;
break;
}
vcpu->run->exit_reason = KVM_EXIT_HYPERCALL;
vcpu->run->hypercall.nr = KVM_HC_PAGE_ENC_STATUS;
vcpu->run->hypercall.args[0] = gpa;
vcpu->run->hypercall.args[1] = nr_bytes;
vcpu->run->hypercall.args[2] = enc;
vcpu->run->hypercall.longmode = op_64_bit;
vcpu->arch.complete_userspace_io = complete_page_enc_hc;
return 0;
}Quoted 5 lines
arch/x86/kvm/x86.c +2
-0+break ; + }default : ret = -KVM_ENOSYS ;break ;
Re: [PATCH v11 08/13] KVM: X86: Introduce KVM_HC_PAGE_ENC_STATUS hypercall
Quoted 93 lines · Sean Christopherson
Quoted 1 line · Ashish Kalra
From: Ashish Kalra <[email protected]>
...
Quoted 31 lines
arch/x86/include/asm/kvm_host.h +2
-0@@ -1352,6 +1352,8 @@ struct kvm_x86_ops {int (*complete_emulated_msr)(struct kvm_vcpu *vcpu,int err);void (*vcpu_deliver_sipi_vector)(struct kvm_vcpu *vcpu,u8 vector); +int (*page_enc_status_hc)(struct kvm_vcpu *vcpu,unsigned long gpa, +unsigned long sz,unsigned long mode); };struct kvm_x86_nested_ops {arch/x86/kvm/svm/sev.c +10
-0@@ -1544,6 +1544,67 @@ static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp)return ret; } +static int sev_complete_userspace_page_enc_status_hc (struct kvm_vcpu *vcpu) +{ + vcpu->run->exit_reason =0 ; +kvm_rax_write (vcpu, vcpu->run->dma_sharing.ret); + ++vcpu->stat.hypercalls; +return kvm_skip_emulated_instruction (vcpu); +} + +int svm_page_enc_status_hc (struct kvm_vcpu *vcpu,unsigned long gpa, +unsigned long npages,unsigned long enc)arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1566
Quoted 10 lines
arch/x86/kvm/svm/sev.c +10
-0+{ +kvm_pfn_t pfn_start, pfn_end; +struct kvm *kvm = vcpu->kvm; +gfn_t gfn_start, gfn_end; + +if (!sev_guest (kvm)) +return -EINVAL ; + +if (!npages) +return 0 ;Parth of me thinks passing a zero size should be an error not a nop. Either way works, just feels a bit weird to allow this to be a nop.
arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1568
Quoted 2 lines
arch/x86/kvm/svm/sev.c +2
-0+ + gfn_start =gpa_to_gfn (gpa);This should check that @gpa is aligned.
Quoted 15 lines
arch/x86/kvm/svm/sev.c +15
-0+ gfn_end = gfn_start + npages; + +/* out of bound access error check */ +if (gfn_end <= gfn_start) +return -EINVAL ; + +/* lets make sure that gpa exist in our memslot */ + pfn_start =gfn_to_pfn (kvm, gfn_start); + pfn_end =gfn_to_pfn (kvm, gfn_end); + +if (is_error_noslot_pfn (pfn_start) && !is_noslot_pfn (pfn_start)) { +/* +* Allow guest MMIO range(s) to be added +* to the shared pages list. +*/ arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1593
Quoted 10 lines
arch/x86/kvm/svm/sev.c +10
-0+return -EINVAL ; + } + +if (is_error_noslot_pfn (pfn_end) && !is_noslot_pfn (pfn_end)) { +/* +* Allow guest MMIO range(s) to be added +* to the shared pages list. +*/ +return -EINVAL ; + }I don't think KVM should do any checks beyond
gfn_end<=gfn_start. Just punt to userspace and give userspace full say over what is/isn't legal.arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1598
Quoted 5 lines
arch/x86/kvm/svm/sev.c +5
-0+ +if (enc) + vcpu->run->exit_reason =KVM_EXIT_DMA_UNSHARE ; +else + vcpu->run->exit_reason =KVM_EXIT_DMA_SHARE ;Use a single exit and pass "enc" via
kvm_run. I also strongly dislike "DMA", there's no guarantee the guest is sharing memory for DMA.
Quoted 2 lines
I think we can usurp
KVM_EXIT_HYPERCALLfor this? E.g.
I see the following in Documentation/virt/kvm/api.rst :
..
..
/* KVM_EXIT_HYPERCALL */
struct {
__u64 nr;
__u64 args[6];
__u64 ret;
__u32 longmode;
__u32 pad;
} hypercall;Unused. This was once used for 'hypercall to userspace'. To implement such functionality, use KVM_EXIT_IO (x86) or KVM_EXIT_MMIO (all except s390).
This mentions this exitcode to be unused and implementing this functionality using KVM_EXIT_IO for x86?
Thanks,
Ashish
Quoted 84 lines
vcpu->run->exit_reason = KVM_EXIT_HYPERCALL; vcpu->run->hypercall.nr = KVM_HC_PAGE_ENC_STATUS; vcpu->run->hypercall.args[0] = gfn_start << PAGE_SHIFT; vcpu->run->hypercall.args[1] = npages * PAGE_SIZE; vcpu->run->hypercall.args[2] = enc; vcpu->run->hypercall.longmode = is_64_bit_mode(vcpu);arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1600
Quoted 2 lines
arch/x86/kvm/svm/sev.c +2
-0+ + vcpu->run->dma_sharing.addr = gfn_start;Addresses and pfns are not the same thing. If you're passing the size in bytes, then it's probably best to pass the gpa, not the gfn. Same for the params from the guest, they should be in the same "domain".
arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1603
Quoted 3 lines
arch/x86/kvm/svm/sev.c +3
-0+ vcpu->run->dma_sharing.len = npages *PAGE_SIZE ; + vcpu->arch.complete_userspace_io = + sev_complete_userspace_page_enc_status_hc;I vote to drop the "userspace" part, it's already quite verbose.
vcpu->arch.complete_userspace_io = sev_complete_page_enc_status_hc;Quoted 4 lines
arch/x86/kvm/svm/sev.c +4
-0+ +return 0 ; +} +..
Quoted 5 lines
arch/x86/kvm/x86.c +0
-0arch/x86/kvm/x86.c int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) · line 8281
Quoted 9 lines
arch/x86/kvm/x86.c +6
-0@@ -8273,6 +8273,18 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)kvm_sched_yield (vcpu->kvm, a0); ret =0 ;break ; +case KVM_HC_PAGE_ENC_STATUS : { +int r; + + ret = -KVM_ENOSYS ; +if (kvm_x86_ops.page_enc_status_hc) { + r = kvm_x86_ops.page_enc_status_hc (vcpu, a0, a1, a2);Use
static_call().arch/x86/kvm/x86.c int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) · line 8285
Quoted 4 lines
arch/x86/kvm/x86.c +4
-0+if (r >=0 ) +return r; + ret = r; + }Hmm, an alternative to adding a
kvm_x86_opshook would be to tag the VM as supporting/allowing the hypercall. That would clean up this code, ensure VMX and SVM don't end up creating a different userspace ABI, and make it easier to reuse the hypercall in the future (I'm still hopeful :-) ). E.g.case KVM_HC_PAGE_ENC_STATUS: { u64 gpa = a0, nr_bytes = a1; if (!vcpu->kvm->arch.page_enc_hc_enable) break; if (!PAGE_ALIGNED(gpa) || !PAGE_ALIGNED(nr_bytes) || !nr_bytes || gpa + nr_bytes <= gpa)) { ret = -EINVAL; break; } vcpu->run->exit_reason = KVM_EXIT_HYPERCALL; vcpu->run->hypercall.nr = KVM_HC_PAGE_ENC_STATUS; vcpu->run->hypercall.args[0] = gpa; vcpu->run->hypercall.args[1] = nr_bytes; vcpu->run->hypercall.args[2] = enc; vcpu->run->hypercall.longmode = op_64_bit; vcpu->arch.complete_userspace_io = complete_page_enc_hc; return 0; }Quoted 5 lines
arch/x86/kvm/x86.c +2
-0+break ; + }default : ret = -KVM_ENOSYS ;break ;
Re: [PATCH v11 08/13] KVM: X86: Introduce KVM_HC_PAGE_ENC_STATUS hypercall
Quoted 110 lines · Ashish Kalra
Quoted 90 lines · Sean Christopherson
Quoted 1 line · Ashish Kalra
From: Ashish Kalra <[email protected]>
...
Quoted 31 lines
arch/x86/include/asm/kvm_host.h +2
-0@@ -1352,6 +1352,8 @@ struct kvm_x86_ops {int (*complete_emulated_msr)(struct kvm_vcpu *vcpu,int err);void (*vcpu_deliver_sipi_vector)(struct kvm_vcpu *vcpu,u8 vector); +int (*page_enc_status_hc)(struct kvm_vcpu *vcpu,unsigned long gpa, +unsigned long sz,unsigned long mode); };struct kvm_x86_nested_ops {arch/x86/kvm/svm/sev.c +10
-0@@ -1544,6 +1544,67 @@ static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp)return ret; } +static int sev_complete_userspace_page_enc_status_hc (struct kvm_vcpu *vcpu) +{ + vcpu->run->exit_reason =0 ; +kvm_rax_write (vcpu, vcpu->run->dma_sharing.ret); + ++vcpu->stat.hypercalls; +return kvm_skip_emulated_instruction (vcpu); +} + +int svm_page_enc_status_hc (struct kvm_vcpu *vcpu,unsigned long gpa, +unsigned long npages,unsigned long enc)arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1566
Quoted 10 lines
arch/x86/kvm/svm/sev.c +10
-0+{ +kvm_pfn_t pfn_start, pfn_end; +struct kvm *kvm = vcpu->kvm; +gfn_t gfn_start, gfn_end; + +if (!sev_guest (kvm)) +return -EINVAL ; + +if (!npages) +return 0 ;Parth of me thinks passing a zero size should be an error not a nop. Either way works, just feels a bit weird to allow this to be a nop.
arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1568
Quoted 2 lines
arch/x86/kvm/svm/sev.c +2
-0+ + gfn_start =gpa_to_gfn (gpa);This should check that @gpa is aligned.
Quoted 15 lines
arch/x86/kvm/svm/sev.c +15
-0+ gfn_end = gfn_start + npages; + +/* out of bound access error check */ +if (gfn_end <= gfn_start) +return -EINVAL ; + +/* lets make sure that gpa exist in our memslot */ + pfn_start =gfn_to_pfn (kvm, gfn_start); + pfn_end =gfn_to_pfn (kvm, gfn_end); + +if (is_error_noslot_pfn (pfn_start) && !is_noslot_pfn (pfn_start)) { +/* +* Allow guest MMIO range(s) to be added +* to the shared pages list. +*/ arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1593
Quoted 10 lines
arch/x86/kvm/svm/sev.c +10
-0+return -EINVAL ; + } + +if (is_error_noslot_pfn (pfn_end) && !is_noslot_pfn (pfn_end)) { +/* +* Allow guest MMIO range(s) to be added +* to the shared pages list. +*/ +return -EINVAL ; + }I don't think KVM should do any checks beyond
gfn_end<=gfn_start. Just punt to userspace and give userspace full say over what is/isn't legal.arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1598
Quoted 5 lines
arch/x86/kvm/svm/sev.c +5
-0+ +if (enc) + vcpu->run->exit_reason =KVM_EXIT_DMA_UNSHARE ; +else + vcpu->run->exit_reason =KVM_EXIT_DMA_SHARE ;Quoted 5 lines
Use a single exit and pass "enc" via
kvm_run. I also strongly dislike "DMA", there's no guarantee the guest is sharing memory for DMA.I think we can usurp
KVM_EXIT_HYPERCALLfor this? E.g.I see the following in
Documentation/virt/kvm/api.rst:
..
..
/*KVM_EXIT_HYPERCALL*/struct { __u64 nr; __u64 args[6]; __u64 ret; __u32 longmode; __u32 pad; } hypercall;
Quoted 5 lines
Unused. This was once used for 'hypercall to userspace'. To implement such functionality, use
KVM_EXIT_IO(x86) orKVM_EXIT_MMIO(all except s390).This mentions this exitcode to be unused and implementing this functionality using
KVM_EXIT_IOfor x86?
I suspect this description is historical. It was originally from 2009. KVM_EXIT_IO is used for IO port reads/writes.
Personally, I would prefer to stay the course and use a name similar to KVM_EXIT_DMA_SHARE, say KVM_EXIT_MEM_SHARE and KVM_EXIT_MEM_UNSHARE. These just seem very clear, which I appreciate. Reusing hypercall would work, but shoehorning this into KVM_EXIT_HYPERCALL when we don't have generic hypercall exits feels a bit off in my mind. Note: that preference isn't particularly strong.
Steve
Quoted 88 lines
Thanks,
AshishQuoted 84 lines
vcpu->run->exit_reason = KVM_EXIT_HYPERCALL; vcpu->run->hypercall.nr = KVM_HC_PAGE_ENC_STATUS; vcpu->run->hypercall.args[0] = gfn_start << PAGE_SHIFT; vcpu->run->hypercall.args[1] = npages * PAGE_SIZE; vcpu->run->hypercall.args[2] = enc; vcpu->run->hypercall.longmode = is_64_bit_mode(vcpu);arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1600
Quoted 2 lines
arch/x86/kvm/svm/sev.c +2
-0+ + vcpu->run->dma_sharing.addr = gfn_start;Addresses and pfns are not the same thing. If you're passing the size in bytes, then it's probably best to pass the gpa, not the gfn. Same for the params from the guest, they should be in the same "domain".
arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1603
Quoted 3 lines
arch/x86/kvm/svm/sev.c +3
-0+ vcpu->run->dma_sharing.len = npages *PAGE_SIZE ; + vcpu->arch.complete_userspace_io = + sev_complete_userspace_page_enc_status_hc;I vote to drop the "userspace" part, it's already quite verbose.
vcpu->arch.complete_userspace_io = sev_complete_page_enc_status_hc;Quoted 4 lines
arch/x86/kvm/svm/sev.c +4
-0+ +return 0 ; +} +..
Quoted 5 lines
arch/x86/kvm/x86.c +0
-0arch/x86/kvm/x86.c int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) · line 8281
Quoted 9 lines
arch/x86/kvm/x86.c +6
-0@@ -8273,6 +8273,18 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)kvm_sched_yield (vcpu->kvm, a0); ret =0 ;break ; +case KVM_HC_PAGE_ENC_STATUS : { +int r; + + ret = -KVM_ENOSYS ; +if (kvm_x86_ops.page_enc_status_hc) { + r = kvm_x86_ops.page_enc_status_hc (vcpu, a0, a1, a2);Use
static_call().arch/x86/kvm/x86.c int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) · line 8285
Quoted 4 lines
arch/x86/kvm/x86.c +4
-0+if (r >=0 ) +return r; + ret = r; + }Hmm, an alternative to adding a
kvm_x86_opshook would be to tag the VM as supporting/allowing the hypercall. That would clean up this code, ensure VMX and SVM don't end up creating a different userspace ABI, and make it easier to reuse the hypercall in the future (I'm still hopeful :-) ). E.g.case KVM_HC_PAGE_ENC_STATUS: { u64 gpa = a0, nr_bytes = a1; if (!vcpu->kvm->arch.page_enc_hc_enable) break; if (!PAGE_ALIGNED(gpa) || !PAGE_ALIGNED(nr_bytes) || !nr_bytes || gpa + nr_bytes <= gpa)) { ret = -EINVAL; break; } vcpu->run->exit_reason = KVM_EXIT_HYPERCALL; vcpu->run->hypercall.nr = KVM_HC_PAGE_ENC_STATUS; vcpu->run->hypercall.args[0] = gpa; vcpu->run->hypercall.args[1] = nr_bytes; vcpu->run->hypercall.args[2] = enc; vcpu->run->hypercall.longmode = op_64_bit; vcpu->arch.complete_userspace_io = complete_page_enc_hc; return 0; }Quoted 5 lines
arch/x86/kvm/x86.c +2
-0+break ; + }default : ret = -KVM_ENOSYS ;break ;
Sean Christopherson
maintainerRe: [PATCH v11 08/13] KVM: X86: Introduce KVM_HC_PAGE_ENC_STATUS hypercall
Quoted 13 lines · Steve Rutherford
Quoted 12 lines · Ashish Kalra
I see the following in
Documentation/virt/kvm/api.rst:
..
..
/*KVM_EXIT_HYPERCALL*/struct { __u64 nr; __u64 args[6]; __u64 ret; __u32 longmode; __u32 pad; } hypercall;
Quoted 8 lines
Quoted 5 lines
Unused. This was once used for 'hypercall to userspace'. To implement such functionality, use
KVM_EXIT_IO(x86) orKVM_EXIT_MMIO(all except s390).This mentions this exitcode to be unused and implementing this functionality using
KVM_EXIT_IOfor x86?I suspect this description is historical. It was originally from 2009.
KVM_EXIT_IOis used for IO port reads/writes.
The purpose of the comment is to discourage use of hypercalls for things that can instead be done via port I/O and/or MMIO. The biggest advantage is that KVM doesn't need to act as an intermediary; userspace can define whatever paravirt shenanigans it so desires and KVM naturally handles the I/O accesses.
MMIO in particular also allows for finer granularity of permissions in the guest, e.g. the guest kernel can expose the address to a userspace application to allow said application to make "hypercalls". Port I/O technically has similar properties, but the I/O bitmaps are heinous.
For this particular case, because we want to make a _KVM_ hypercall that just happens to get punted to userspace, and because there is no known or projected use case for letting guest userspace control memory encryption it makes sense to use a "real" hypercall.
Quoted 6 lines
Personally, I would prefer to stay the course and use a name similar to
KVM_EXIT_DMA_SHARE, sayKVM_EXIT_MEM_SHAREandKVM_EXIT_MEM_UNSHARE. These just seem very clear, which I appreciate. Reusing hypercall would work, but shoehorning this intoKVM_EXIT_HYPERCALLwhen we don't have generic hypercall exits feels a bit off in my mind. Note: that preference isn't particularly strong.
I'm not against adding a new exit type, I'm against adding _two_ new exit types.
I also don't like using "(UN)SHARE" because there may be future use cases where the hypercall isn't used to "share' memory, but to inform the host of a change in state. I don't have a concrete example, but it's not completely absurd to think that there might be a scenario where a guest has the ability to use multiple keys and needs to communicate key usage to the host. Linux already has horrific (IMO) names for describing encrypted vs. "other" memory, I'd strongly prefer to avoid adding yet another potentially wrong name to the mix.
Re: [PATCH v11 08/13] KVM: X86: Introduce KVM_HC_PAGE_ENC_STATUS hypercall
In reply to Sean ChristophersonQuoted 164 lines · Sean Christopherson
Quoted 1 line · Ashish Kalra
From: Ashish Kalra <[email protected]>
...
Quoted 31 lines
arch/x86/include/asm/kvm_host.h +2
-0@@ -1352,6 +1352,8 @@ struct kvm_x86_ops {int (*complete_emulated_msr)(struct kvm_vcpu *vcpu,int err);void (*vcpu_deliver_sipi_vector)(struct kvm_vcpu *vcpu,u8 vector); +int (*page_enc_status_hc)(struct kvm_vcpu *vcpu,unsigned long gpa, +unsigned long sz,unsigned long mode); };struct kvm_x86_nested_ops {arch/x86/kvm/svm/sev.c +10
-0@@ -1544,6 +1544,67 @@ static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp)return ret; } +static int sev_complete_userspace_page_enc_status_hc (struct kvm_vcpu *vcpu) +{ + vcpu->run->exit_reason =0 ; +kvm_rax_write (vcpu, vcpu->run->dma_sharing.ret); + ++vcpu->stat.hypercalls; +return kvm_skip_emulated_instruction (vcpu); +} + +int svm_page_enc_status_hc (struct kvm_vcpu *vcpu,unsigned long gpa, +unsigned long npages,unsigned long enc)arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1566
Quoted 10 lines
arch/x86/kvm/svm/sev.c +10
-0+{ +kvm_pfn_t pfn_start, pfn_end; +struct kvm *kvm = vcpu->kvm; +gfn_t gfn_start, gfn_end; + +if (!sev_guest (kvm)) +return -EINVAL ; + +if (!npages) +return 0 ;Parth of me thinks passing a zero size should be an error not a nop. Either way works, just feels a bit weird to allow this to be a nop.
arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1568
Quoted 2 lines
arch/x86/kvm/svm/sev.c +2
-0+ + gfn_start =gpa_to_gfn (gpa);This should check that @gpa is aligned.
Quoted 15 lines
arch/x86/kvm/svm/sev.c +15
-0+ gfn_end = gfn_start + npages; + +/* out of bound access error check */ +if (gfn_end <= gfn_start) +return -EINVAL ; + +/* lets make sure that gpa exist in our memslot */ + pfn_start =gfn_to_pfn (kvm, gfn_start); + pfn_end =gfn_to_pfn (kvm, gfn_end); + +if (is_error_noslot_pfn (pfn_start) && !is_noslot_pfn (pfn_start)) { +/* +* Allow guest MMIO range(s) to be added +* to the shared pages list. +*/ arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1593
Quoted 10 lines
arch/x86/kvm/svm/sev.c +10
-0+return -EINVAL ; + } + +if (is_error_noslot_pfn (pfn_end) && !is_noslot_pfn (pfn_end)) { +/* +* Allow guest MMIO range(s) to be added +* to the shared pages list. +*/ +return -EINVAL ; + }I don't think KVM should do any checks beyond
gfn_end<=gfn_start. Just punt to userspace and give userspace full say over what is/isn't legal.arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1598
Quoted 5 lines
arch/x86/kvm/svm/sev.c +5
-0+ +if (enc) + vcpu->run->exit_reason =KVM_EXIT_DMA_UNSHARE ; +else + vcpu->run->exit_reason =KVM_EXIT_DMA_SHARE ;Use a single exit and pass "enc" via
kvm_run. I also strongly dislike "DMA", there's no guarantee the guest is sharing memory for DMA.I think we can usurp
KVM_EXIT_HYPERCALLfor this? E.g.vcpu->run->exit_reason = KVM_EXIT_HYPERCALL; vcpu->run->hypercall.nr = KVM_HC_PAGE_ENC_STATUS; vcpu->run->hypercall.args[0] = gfn_start << PAGE_SHIFT; vcpu->run->hypercall.args[1] = npages * PAGE_SIZE; vcpu->run->hypercall.args[2] = enc; vcpu->run->hypercall.longmode = is_64_bit_mode(vcpu);arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1600
Quoted 2 lines
arch/x86/kvm/svm/sev.c +2
-0+ + vcpu->run->dma_sharing.addr = gfn_start;Addresses and pfns are not the same thing. If you're passing the size in bytes, then it's probably best to pass the gpa, not the gfn. Same for the params from the guest, they should be in the same "domain".
arch/x86/kvm/svm/sev.c static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · line 1603
Quoted 3 lines
arch/x86/kvm/svm/sev.c +3
-0+ vcpu->run->dma_sharing.len = npages *PAGE_SIZE ; + vcpu->arch.complete_userspace_io = + sev_complete_userspace_page_enc_status_hc;I vote to drop the "userspace" part, it's already quite verbose.
vcpu->arch.complete_userspace_io = sev_complete_page_enc_status_hc;Quoted 4 lines
arch/x86/kvm/svm/sev.c +4
-0+ +return 0 ; +} +..
Quoted 5 lines
arch/x86/kvm/x86.c +0
-0arch/x86/kvm/x86.c int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) · line 8281
Quoted 9 lines
arch/x86/kvm/x86.c +6
-0@@ -8273,6 +8273,18 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)kvm_sched_yield (vcpu->kvm, a0); ret =0 ;break ; +case KVM_HC_PAGE_ENC_STATUS : { +int r; + + ret = -KVM_ENOSYS ; +if (kvm_x86_ops.page_enc_status_hc) { + r = kvm_x86_ops.page_enc_status_hc (vcpu, a0, a1, a2);Use
static_call().arch/x86/kvm/x86.c int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) · line 8285
Quoted 4 lines
arch/x86/kvm/x86.c +4
-0+if (r >=0 ) +return r; + ret = r; + }Hmm, an alternative to adding a
kvm_x86_opshook would be to tag the VM as supporting/allowing the hypercall. That would clean up this code, ensure VMX and SVM don't end up creating a different userspace ABI, and make it easier to reuse the hypercall in the future (I'm still hopeful :-) ). E.g.case KVM_HC_PAGE_ENC_STATUS: { u64 gpa = a0, nr_bytes = a1; if (!vcpu->kvm->arch.page_enc_hc_enable) break; if (!PAGE_ALIGNED(gpa) || !PAGE_ALIGNED(nr_bytes) || !nr_bytes || gpa + nr_bytes <= gpa)) { ret = -EINVAL; break; } vcpu->run->exit_reason = KVM_EXIT_HYPERCALL;
Quoted 8 lines
vcpu->run->hypercall.nr = KVM_HC_PAGE_ENC_STATUS;
vcpu->run->hypercall.args[0] = gpa;
vcpu->run->hypercall.args[1] = nr_bytes;
vcpu->run->hypercall.args[2] = enc;
vcpu->run->hypercall.longmode = op_64_bit;
vcpu->arch.complete_userspace_io = complete_page_enc_hc;
return 0;
}I really like the above approach, but one thing that concerns me above is the addition of architecture specific code, for example, the page encryption stuff as part of the generic x86 KVM code ?
Especially bits like the page enc hypercall completion callback and testing the architecture specific page encryption hypercall enabled flag, probably the hypercall completion callback can be named something as complete_userspace_hypercall(), as anyway what it does inside the callback is all very generic.
The above naming may also go well with KVM_EXIT_HYPERCALL exitcode interface.
Thanks,
Ashish
Quoted 7 lines
Quoted 7 lines
arch/x86/kvm/x86.c +2
-0+break ; + }default : ret = -KVM_ENOSYS ;break ;
PATCH v11 9/13 mm: x86: Invoke hypercall when page encryption status is changed
In reply to Ashish KalraFrom: Brijesh Singh <[email protected]>
Invoke a hypercall when a memory region is changed from encrypted -> decrypted and vice versa. Hypervisor needs to know the page encryption status during the guest migration.
--- arch/x86/include/asm/paravirt.h | 10 +++++ arch/x86/include/asm/paravirt_types.h | 2 + arch/x86/kernel/paravirt.c | 1 + arch/x86/mm/mem_encrypt.c | 57 ++++++++++++++++++++++++++- arch/x86/mm/pat/set_memory.c | 7 ++++ 5 files changed, 76 insertions(+), 1 deletion(-)
arch/x86/include/asm/paravirt.h +10 -0
@@ -84,6 +84,12 @@ static inline void paravirt_arch_exit_mmap(struct mm_struct *mm)PVOP_VCALL1 (mmu.exit_mmap, mm); } +static inline void page_encryption_changed (unsigned long vaddr,int npages, +bool enc) +{ +PVOP_VCALL3 (mmu.page_encryption_changed, vaddr, npages, enc); +} +#ifdef CONFIG_PARAVIRT_XXL static inline void load_sp0 (unsigned long sp0) {
@@ -799,6 +805,10 @@ static inline void paravirt_arch_dup_mmap(struct mm_struct *oldmm,static inline void paravirt_arch_exit_mmap (struct mm_struct *mm) { } + +static inline void page_encryption_changed (unsigned long vaddr,int npages,bool enc) +{ +}#endif #endif /* __ASSEMBLY__ */ #endif /* _ASM_X86_PARAVIRT_H */
arch/x86/include/asm/paravirt_types.h +2 -0
@@ -195,6 +195,8 @@ struct pv_mmu_ops {/* Hook for intercepting the destruction of an mm_struct. */ void (*exit_mmap)(struct mm_struct *mm); +void (*page_encryption_changed)(unsigned long vaddr,int npages, +bool enc);#ifdef CONFIG_PARAVIRT_XXL struct paravirt_callee_save read_cr2;
arch/x86/kernel/paravirt.c +1 -0
@@ -335,6 +335,7 @@ struct paravirt_patch_template pv_ops = { (void (*)(struct mmu_gather *, void *))tlb_remove_page, .mmu.exit_mmap = paravirt_nop, + .mmu.page_encryption_changed = paravirt_nop, #ifdef CONFIG_PARAVIRT_XXL .mmu.read_cr2 = __PV_IS_CALLEE_SAVE(native_read_cr2),
arch/x86/mm/mem_encrypt.c +56 -1
98 lines not on this page · raw message
arch/x86/mm/pat/set_memory.c +7 -0
@@ -27,6 +27,7 @@#include <asm/proto.h> #include <asm/memtype.h> #include <asm/set_memory.h> +#include <asm/paravirt.h> #include "../mm_internal.h"
@@ -2012,6 +2013,12 @@ static int __set_memory_enc_dec(unsigned long addr, int numpages, bool enc)*/ cpa_flush (&cpa,0 ); +/* Notify hypervisor that a given memory range is mapped encrypted +* or decrypted. The hypervisor will use this information during the +* VM migration. +*/ +page_encryption_changed (addr, numpages, enc); +return ret; }
Signature · 1 line
2.17.1
PATCH v11 10/13 KVM: x86: Introduce new KVM_FEATURE_SEV_LIVE_MIGRATION feature & Custom MSR.
In reply to Ashish KalraFrom: Ashish Kalra <[email protected]>
Add new KVM_FEATURE_SEV_LIVE_MIGRATION feature for guest to check for host-side support for SEV live migration. Also add a new custom MSR_KVM_SEV_LIVE_MIGRATION for guest to enable the SEV live migration feature.
MSR is handled by userspace using MSR filters.
--- Documentation/virt/kvm/cpuid.rst | 5 +++++ Documentation/virt/kvm/msr.rst | 12 ++++++++++++ arch/x86/include/uapi/asm/kvm_para.h | 4 ++++ arch/x86/kvm/cpuid.c | 3 ++- arch/x86/kvm/svm/svm.c | 22 ++++++++++++++++++++++ 5 files changed, 45 insertions(+), 1 deletion(-)
Documentation/virt/kvm/cpuid.rst +5 -0
@@ -96,6 +96,11 @@ KVM_FEATURE_MSI_EXT_DEST_ID 15 guest checks this feature bit before using extended destination ID bits in MSI address bits 11-5. +KVM_FEATURE_SEV_LIVE_MIGRATION 16 guest checks this feature bit before + using the page encryption state + hypercall to notify the page state + change + KVM_FEATURE_CLOCKSOURCE_STABLE_BIT 24 host will warn if no guest-side per-cpu warps are expected in kvmclock
Documentation/virt/kvm/msr.rst +12 -0
@@ -376,3 +376,15 @@ data: write '1' to bit 0 of the MSR, this causes the host to re-scan its queue and check if there are more notifications pending. The MSR is available if KVM_FEATURE_ASYNC_PF_INT is present in CPUID. + +MSR_KVM_SEV_LIVE_MIGRATION: + 0x4b564d08 + + Control SEV Live Migration features. + +data: + Bit 0 enables (1) or disables (0) host-side SEV Live Migration feature, + in other words, this is guest->host communication that it's properly + handling the shared pages list. + + All other bits are reserved.
arch/x86/include/uapi/asm/kvm_para.h +4 -0
@@ -33,6 +33,7 @@#define KVM_FEATURE_PV_SCHED_YIELD 13#define KVM_FEATURE_ASYNC_PF_INT 14#define KVM_FEATURE_MSI_EXT_DEST_ID 15 +#define KVM_FEATURE_SEV_LIVE_MIGRATION 16#define KVM_HINTS_REALTIME 0
@@ -54,6 +55,7 @@#define MSR_KVM_POLL_CONTROL 0x4b564d05#define MSR_KVM_ASYNC_PF_INT 0x4b564d06#define MSR_KVM_ASYNC_PF_ACK 0x4b564d07 +#define MSR_KVM_SEV_LIVE_MIGRATION 0x4b564d08struct kvm_steal_time {__u64 steal;
@@ -136,4 +138,6 @@ struct kvm_vcpu_pv_apf_data {#define KVM_PV_EOI_ENABLED KVM_PV_EOI_MASK#define KVM_PV_EOI_DISABLED 0x0 +#define KVM_SEV_LIVE_MIGRATION_ENABLED BIT_ULL(0) +#endif /* _UAPI_ASM_X86_KVM_PARA_H */
arch/x86/kvm/cpuid.c +2 -1
@@ -812,7 +812,8 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) (1 <<KVM_FEATURE_PV_SEND_IPI ) | (1 <<KVM_FEATURE_POLL_CONTROL ) | (1 <<KVM_FEATURE_PV_SCHED_YIELD ) | - (1 <<KVM_FEATURE_ASYNC_PF_INT ); + (1 <<KVM_FEATURE_ASYNC_PF_INT ) | + (1 <<KVM_FEATURE_SEV_LIVE_MIGRATION );if (sched_info_on ()) entry->eax |= (1 <<KVM_FEATURE_STEAL_TIME );
arch/x86/kvm/svm/svm.c +22 -0
@@ -2800,6 +2800,17 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)case MSR_F10H_DECFG : msr_info->data = svm->msr_decfg;break ; +case MSR_KVM_SEV_LIVE_MIGRATION : +if (!sev_guest (vcpu->kvm)) +return 1 ; + +if (!guest_cpuid_has (vcpu,KVM_FEATURE_SEV_LIVE_MIGRATION )) +return 1 ; + +/* +* Let userspace handle the MSR using MSR filters. +*/ +return KVM_MSR_RET_FILTERED ;default :return kvm_get_msr_common (vcpu, msr_info); }
@@ -2996,6 +3007,17 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) svm->msr_decfg = data;break ; } +case MSR_KVM_SEV_LIVE_MIGRATION : +if (!sev_guest (vcpu->kvm)) +return 1 ; + +if (!guest_cpuid_has (vcpu,KVM_FEATURE_SEV_LIVE_MIGRATION )) +return 1 ; + +/* +* Let userspace handle the MSR using MSR filters. +*/ +return KVM_MSR_RET_FILTERED ;case MSR_IA32_APICBASE :if (kvm_vcpu_apicv_active (vcpu))avic_update_vapic_bar (to_svm (vcpu), data);
Signature · 1 line
2.17.1
Re: [PATCH v11 10/13] KVM: x86: Introduce new KVM_FEATURE_SEV_LIVE_MIGRATION feature & Custom MSR.
Quoted 123 lines · Ashish Kalra
From: Ashish Kalra <[email protected]>
Add new
KVM_FEATURE_SEV_LIVE_MIGRATIONfeature for guest to check for host-side support for SEV live migration. Also add a new customMSR_KVM_SEV_LIVE_MIGRATIONfor guest to enable the SEV live migration feature.MSR is handled by userspace using MSR filters.
Signed-off-by Ashish Kalra <[email protected]>--- Documentation/virt/kvm/cpuid.rst | 5 +++++ Documentation/virt/kvm/msr.rst | 12 ++++++++++++ arch/x86/include/uapi/asm/kvm_para.h | 4 ++++ arch/x86/kvm/cpuid.c | 3 ++- arch/x86/kvm/svm/svm.c | 22 ++++++++++++++++++++++ 5 files changed, 45 insertions(+), 1 deletion(-)Documentation/virt/kvm/cpuid.rst +5
-0@@ -96,6 +96,11 @@ KVM_FEATURE_MSI_EXT_DEST_ID 15 guest checks this feature bit before using extended destination ID bits in MSI address bits 11-5. +KVM_FEATURE_SEV_LIVE_MIGRATION 16 guest checks this feature bit before + using the page encryption state + hypercall to notify the page state + change + KVM_FEATURE_CLOCKSOURCE_STABLE_BIT 24 host will warn if no guest-side per-cpu warps are expected in kvmclockDocumentation/virt/kvm/msr.rst +12
-0@@ -376,3 +376,15 @@ data: write '1' to bit 0 of the MSR, this causes the host to re-scan its queue and check if there are more notifications pending. The MSR is available if KVM_FEATURE_ASYNC_PF_INT is present in CPUID. + +MSR_KVM_SEV_LIVE_MIGRATION: + 0x4b564d08 + + Control SEV Live Migration features. + +data: + Bit 0 enables (1) or disables (0) host-side SEV Live Migration feature, + in other words, this is guest->host communication that it's properly + handling the shared pages list. + + All other bits are reserved.arch/x86/include/uapi/asm/kvm_para.h +4
-0@@ -33,6 +33,7 @@#define KVM_FEATURE_PV_SCHED_YIELD 13#define KVM_FEATURE_ASYNC_PF_INT 14#define KVM_FEATURE_MSI_EXT_DEST_ID 15 +#define KVM_FEATURE_SEV_LIVE_MIGRATION 16#define KVM_HINTS_REALTIME 0@@ -54,6 +55,7 @@#define MSR_KVM_POLL_CONTROL 0x4b564d05#define MSR_KVM_ASYNC_PF_INT 0x4b564d06#define MSR_KVM_ASYNC_PF_ACK 0x4b564d07 +#define MSR_KVM_SEV_LIVE_MIGRATION 0x4b564d08struct kvm_steal_time {__u64 steal;@@ -136,4 +138,6 @@ struct kvm_vcpu_pv_apf_data {#define KVM_PV_EOI_ENABLED KVM_PV_EOI_MASK#define KVM_PV_EOI_DISABLED 0x0 +#define KVM_SEV_LIVE_MIGRATION_ENABLED BIT_ULL(0) +#endif /* _UAPI_ASM_X86_KVM_PARA_H */ arch/x86/kvm/cpuid.c +2
-1@@ -812,7 +812,8 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) (1 <<KVM_FEATURE_PV_SEND_IPI ) | (1 <<KVM_FEATURE_POLL_CONTROL ) | (1 <<KVM_FEATURE_PV_SCHED_YIELD ) | - (1 <<KVM_FEATURE_ASYNC_PF_INT ); + (1 <<KVM_FEATURE_ASYNC_PF_INT ) | + (1 <<KVM_FEATURE_SEV_LIVE_MIGRATION );if (sched_info_on ()) entry->eax |= (1 <<KVM_FEATURE_STEAL_TIME );arch/x86/kvm/svm/svm.c +12
-0@@ -2800,6 +2800,17 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)case MSR_F10H_DECFG : msr_info->data = svm->msr_decfg;break ; +case MSR_KVM_SEV_LIVE_MIGRATION : +if (!sev_guest (vcpu->kvm)) +return 1 ; + +if (!guest_cpuid_has (vcpu,KVM_FEATURE_SEV_LIVE_MIGRATION )) +return 1 ; + +/* +* Let userspace handle the MSR using MSR filters. +*/ +return KVM_MSR_RET_FILTERED ;default :return kvm_get_msr_common (vcpu, msr_info); }@@ -2996,6 +3007,17 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) svm->msr_decfg = data;break ; } +case MSR_KVM_SEV_LIVE_MIGRATION :
arch/x86/kvm/svm/svm.c static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) · line 3020
Quoted 10 lines
arch/x86/kvm/svm/svm.c +10
-0+if (!sev_guest (vcpu->kvm)) +return 1 ; + +if (!guest_cpuid_has (vcpu,KVM_FEATURE_SEV_LIVE_MIGRATION )) +return 1 ; + +/* +* Let userspace handle the MSR using MSR filters. +*/ +return KVM_MSR_RET_FILTERED ;
It's a little unintuitive to see KVM_MSR_RET_FILTERED here, since userspace can make this happen on its own without having an entry in this switch statement (by setting it in the msr filter bitmaps). When using MSR filters, I would only expect to get MSR filter exits for MSRs I specifically asked for.
Not a huge deal, just a little unintuitive. I'm not sure other options are much better (you could put KVM_MSR_RET_INVALID, or you could just not have these entries in svm_{get,set}_msr).
--Steve
Re: [PATCH v11 10/13] KVM: x86: Introduce new KVM_FEATURE_SEV_LIVE_MIGRATION feature & Custom MSR.
Hello Steve,
Quoted 141 lines · Steve Rutherford
Quoted 123 lines · Ashish Kalra
From: Ashish Kalra <[email protected]>
Add new
KVM_FEATURE_SEV_LIVE_MIGRATIONfeature for guest to check for host-side support for SEV live migration. Also add a new customMSR_KVM_SEV_LIVE_MIGRATIONfor guest to enable the SEV live migration feature.MSR is handled by userspace using MSR filters.
Signed-off-by Ashish Kalra <[email protected]>--- Documentation/virt/kvm/cpuid.rst | 5 +++++ Documentation/virt/kvm/msr.rst | 12 ++++++++++++ arch/x86/include/uapi/asm/kvm_para.h | 4 ++++ arch/x86/kvm/cpuid.c | 3 ++- arch/x86/kvm/svm/svm.c | 22 ++++++++++++++++++++++ 5 files changed, 45 insertions(+), 1 deletion(-)Documentation/virt/kvm/cpuid.rst +5
-0@@ -96,6 +96,11 @@ KVM_FEATURE_MSI_EXT_DEST_ID 15 guest checks this feature bit before using extended destination ID bits in MSI address bits 11-5. +KVM_FEATURE_SEV_LIVE_MIGRATION 16 guest checks this feature bit before + using the page encryption state + hypercall to notify the page state + change + KVM_FEATURE_CLOCKSOURCE_STABLE_BIT 24 host will warn if no guest-side per-cpu warps are expected in kvmclockDocumentation/virt/kvm/msr.rst +12
-0@@ -376,3 +376,15 @@ data: write '1' to bit 0 of the MSR, this causes the host to re-scan its queue and check if there are more notifications pending. The MSR is available if KVM_FEATURE_ASYNC_PF_INT is present in CPUID. + +MSR_KVM_SEV_LIVE_MIGRATION: + 0x4b564d08 + + Control SEV Live Migration features. + +data: + Bit 0 enables (1) or disables (0) host-side SEV Live Migration feature, + in other words, this is guest->host communication that it's properly + handling the shared pages list. + + All other bits are reserved.arch/x86/include/uapi/asm/kvm_para.h +4
-0@@ -33,6 +33,7 @@#define KVM_FEATURE_PV_SCHED_YIELD 13#define KVM_FEATURE_ASYNC_PF_INT 14#define KVM_FEATURE_MSI_EXT_DEST_ID 15 +#define KVM_FEATURE_SEV_LIVE_MIGRATION 16#define KVM_HINTS_REALTIME 0@@ -54,6 +55,7 @@#define MSR_KVM_POLL_CONTROL 0x4b564d05#define MSR_KVM_ASYNC_PF_INT 0x4b564d06#define MSR_KVM_ASYNC_PF_ACK 0x4b564d07 +#define MSR_KVM_SEV_LIVE_MIGRATION 0x4b564d08struct kvm_steal_time {__u64 steal;@@ -136,4 +138,6 @@ struct kvm_vcpu_pv_apf_data {#define KVM_PV_EOI_ENABLED KVM_PV_EOI_MASK#define KVM_PV_EOI_DISABLED 0x0 +#define KVM_SEV_LIVE_MIGRATION_ENABLED BIT_ULL(0) +#endif /* _UAPI_ASM_X86_KVM_PARA_H */ arch/x86/kvm/cpuid.c +2
-1@@ -812,7 +812,8 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) (1 <<KVM_FEATURE_PV_SEND_IPI ) | (1 <<KVM_FEATURE_POLL_CONTROL ) | (1 <<KVM_FEATURE_PV_SCHED_YIELD ) | - (1 <<KVM_FEATURE_ASYNC_PF_INT ); + (1 <<KVM_FEATURE_ASYNC_PF_INT ) | + (1 <<KVM_FEATURE_SEV_LIVE_MIGRATION );if (sched_info_on ()) entry->eax |= (1 <<KVM_FEATURE_STEAL_TIME );arch/x86/kvm/svm/svm.c +12
-0@@ -2800,6 +2800,17 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)case MSR_F10H_DECFG : msr_info->data = svm->msr_decfg;break ; +case MSR_KVM_SEV_LIVE_MIGRATION : +if (!sev_guest (vcpu->kvm)) +return 1 ; + +if (!guest_cpuid_has (vcpu,KVM_FEATURE_SEV_LIVE_MIGRATION )) +return 1 ; + +/* +* Let userspace handle the MSR using MSR filters. +*/ +return KVM_MSR_RET_FILTERED ;default :return kvm_get_msr_common (vcpu, msr_info); }@@ -2996,6 +3007,17 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) svm->msr_decfg = data;break ; } +case MSR_KVM_SEV_LIVE_MIGRATION :arch/x86/kvm/svm/svm.c static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) · line 3020
Quoted 10 lines
arch/x86/kvm/svm/svm.c +10
-0+if (!sev_guest (vcpu->kvm)) +return 1 ; + +if (!guest_cpuid_has (vcpu,KVM_FEATURE_SEV_LIVE_MIGRATION )) +return 1 ; + +/* +* Let userspace handle the MSR using MSR filters. +*/ +return KVM_MSR_RET_FILTERED ;It's a little unintuitive to see
KVM_MSR_RET_FILTEREDhere, since userspace can make this happen on its own without having an entry in this switch statement (by setting it in the msr filter bitmaps). When using MSR filters, I would only expect to get MSR filter exits for MSRs I specifically asked for.
Quoted 4 lines
Not a huge deal, just a little unintuitive. I'm not sure other options are much better (you could put
KVM_MSR_RET_INVALID, or you could just not have these entries in svm_{get,set}_msr).
Actually KVM_MSR_RET_FILTERED seems more logical to use, especially in comparison with KVM_MSR_RET_INVALID.
Also, hooking this msr in svm_{get,set}_msr allows some in-kernel error pre-processsing before doing the pass-through to userspace.
Thanks,
Ashish
Paolo Bonzini
maintainerRe: [PATCH v11 10/13] KVM: x86: Introduce new KVM_FEATURE_SEV_LIVE_MIGRATION feature & Custom MSR.
Quoted 10 lines · Ashish Kalra
Quoted 10 lines
It's a little unintuitive to see
KVM_MSR_RET_FILTEREDhere, since userspace can make this happen on its own without having an entry in this switch statement (by setting it in the msr filter bitmaps). When using MSR filters, I would only expect to get MSR filter exits for MSRs I specifically asked for.Not a huge deal, just a little unintuitive. I'm not sure other options are much better (you could put
KVM_MSR_RET_INVALID, or you could just not have these entries in svm_{get,set}_msr).
Quoted 5 lines
Actually
KVM_MSR_RET_FILTEREDseems more logical to use, especially in comparison withKVM_MSR_RET_INVALID.Also, hooking this msr in svm_{get,set}_msr allows some in-kernel error pre-processsing before doing the pass-through to userspace.
I agree that it should be up to userspace to set up the filter since we now have that functionality.
Let me read the whole threads for the past versions to see what the objections were...
Paolo
Re: [PATCH v11 10/13] KVM: x86: Introduce new KVM_FEATURE_SEV_LIVE_MIGRATION feature & Custom MSR.
Hello Paolo,
Quoted 11 lines · Paolo Bonzini
Quoted 10 lines · Ashish Kalra
Quoted 10 lines
It's a little unintuitive to see
KVM_MSR_RET_FILTEREDhere, since userspace can make this happen on its own without having an entry in this switch statement (by setting it in the msr filter bitmaps). When using MSR filters, I would only expect to get MSR filter exits for MSRs I specifically asked for.Not a huge deal, just a little unintuitive. I'm not sure other options are much better (you could put
KVM_MSR_RET_INVALID, or you could just not have these entries in svm_{get,set}_msr).
Quoted 9 lines
Quoted 5 lines
Actually
KVM_MSR_RET_FILTEREDseems more logical to use, especially in comparison withKVM_MSR_RET_INVALID.Also, hooking this msr in svm_{get,set}_msr allows some in-kernel error pre-processsing before doing the pass-through to userspace.
I agree that it should be up to userspace to set up the filter since we now have that functionality.
The userspace is still setting up the filter and handling this MSR, it is only some basic error pre-processing being done in-kernel here.
Thanks,
Ashish
Quoted 5 lines
Let me read the whole threads for the past versions to see what the objections were...
Paolo
Re: [PATCH v11 10/13] KVM: x86: Introduce new KVM_FEATURE_SEV_LIVE_MIGRATION feature & Custom MSR.
Quoted 21 lines · Ashish Kalra
Hello Paolo,
Quoted 17 lines · Paolo Bonzini
Quoted 15 lines · Ashish Kalra
Quoted 10 lines
It's a little unintuitive to see
KVM_MSR_RET_FILTEREDhere, since userspace can make this happen on its own without having an entry in this switch statement (by setting it in the msr filter bitmaps). When using MSR filters, I would only expect to get MSR filter exits for MSRs I specifically asked for.Not a huge deal, just a little unintuitive. I'm not sure other options are much better (you could put
KVM_MSR_RET_INVALID, or you could just not have these entries in svm_{get,set}_msr).Actually
KVM_MSR_RET_FILTEREDseems more logical to use, especially in comparison withKVM_MSR_RET_INVALID.Also, hooking this msr in svm_{get,set}_msr allows some in-kernel error pre-processsing before doing the pass-through to userspace.
Quoted 6 lines
Quoted 3 lines
I agree that it should be up to userspace to set up the filter since we now have that functionality.
The userspace is still setting up the filter and handling this MSR, it is only some basic error pre-processing being done in-kernel here.
The bit that is unintuitive is that userspace will still get the kvm_exit from an msr filter for KVM_MSR_RET_FILTERED even if they did not add it to the filters. I don't think this is a huge deal:
userspace asked for it indirectly (through cpuid+sev enablement).
Quoted 9 lines
Thanks,
AshishQuoted 5 lines
Let me read the whole threads for the past versions to see what the objections were...
Paolo
PATCH v11 11/13 EFI: Introduce the new AMD Memory Encryption GUID.
In reply to Ashish KalraFrom: Ashish Kalra <[email protected]>
Introduce a new AMD Memory Encryption GUID which is currently used for defining a new UEFI environment variable which indicates UEFI/OVMF support for the SEV live migration feature. This variable is setup when UEFI/OVMF detects host/hypervisor support for SEV live migration and later this variable is read by the kernel using EFI runtime services to verify if OVMF supports the live migration feature.
--- include/linux/efi.h | 1 + 1 file changed, 1 insertion(+)
include/linux/efi.h +1 -0
@@ -362,6 +362,7 @@ void efi_native_runtime_setup(void);/* OEM GUIDs */ #define DELLEMC_EFI_RCI2_TABLE_GUID EFI_GUID(0x2d9f28a2, 0xa886, 0x456a, 0x97, 0xa8, 0xf1, 0x1e, 0xf2, 0x4f, 0xf4, 0x55) +#define MEM_ENCRYPT_GUID EFI_GUID(0x0cf29b71, 0x9e51, 0x433a, 0xa3, 0xb7, 0x81, 0xf3, 0xab, 0x16, 0xb8, 0x75) typedef struct { efi_guid_t guid;
Signature · 1 line
2.17.1
PATCH v11 12/13 x86/kvm: Add guest support for detecting and enabling SEV Live Migration feature.
In reply to Ashish KalraFrom: Ashish Kalra <[email protected]>
The guest support for detecting and enabling SEV Live migration feature uses the following logic :
- kvm_init_plaform() invokes check_kvm_sev_migration() which checks if its booted under the EFI
- If not EFI,
i) check for the KVM_FEATURE_CPUID
ii) if CPUID reports that migration is supported, issue a wrmsrl()
to enable the SEV live migration support
- If EFI,
i) check for the KVM_FEATURE_CPUID
ii) If CPUID reports that migration is supported, read the UEFI variable which
indicates OVMF support for live migration
iii) the variable indicates live migration is supported, issue a wrmsrl() to
enable the SEV live migration support
The EFI live migration check is done using a late_initcall() callback.
Also, ensure that _bss_decrypted section is marked as decrypted in the shared pages list.
--- arch/x86/include/asm/mem_encrypt.h | 8 +++++ arch/x86/kernel/kvm.c | 52 ++++++++++++++++++++++++++++++ arch/x86/mm/mem_encrypt.c | 41 +++++++++++++++++++++++ 3 files changed, 101 insertions(+)
arch/x86/include/asm/mem_encrypt.h +8 -0
@@ -21,6 +21,7 @@extern u64 sme_me_mask;extern u64 sev_status;extern bool sev_enabled; +extern bool sev_live_migration_enabled; void sme_encrypt_execute(unsigned long encrypted_kernel_vaddr, unsigned long decrypted_kernel_vaddr,
@@ -44,8 +45,11 @@ void __init sme_enable(struct boot_params *bp);int __init early_set_memory_decrypted (unsigned long vaddr,unsigned long size);int __init early_set_memory_encrypted (unsigned long vaddr,unsigned long size); +void __init early_set_mem_enc_dec_hypercall (unsigned long vaddr,int npages, +bool enc);void __init mem_encrypt_free_decrypted_mem (void ); +void __init check_kvm_sev_migration (void );/* Architecture __weak replacement functions */ void __init mem_encrypt_init (void );
@@ -60,6 +64,7 @@ bool sev_es_active(void);#else /* !CONFIG_AMD_MEM_ENCRYPT */ #define sme_me_mask 0ULL +#define sev_live_migration_enabled falsestatic inline void __init sme_early_encrypt (resource_size_t paddr,unsigned long size) { }
@@ -84,8 +89,11 @@ static inline int __init early_set_memory_decrypted(unsigned long vaddr, unsigned long size) { return 0; }static inline int __init early_set_memory_encrypted (unsigned long vaddr,unsigned long size) {return 0 ; } +static inline void __init +early_set_mem_enc_dec_hypercall (unsigned long vaddr,int npages,bool enc) {}static inline void mem_encrypt_free_decrypted_mem (void ) { } +static inline void check_kvm_sev_migration (void ) { }#define __bss_decrypted
arch/x86/kernel/kvm.c +52 -0
70 lines not on this page · raw message
arch/x86/mm/mem_encrypt.c +41 -0
71 lines not on this page · raw message
Signature · 1 line
2.17.1
PATCH v11 13/13 x86/kvm: Add kexec support for SEV Live Migration.
In reply to Ashish KalraFrom: Ashish Kalra <[email protected]>
Reset the host's shared pages list related to kernel specific page encryption status settings before we load a new kernel by kexec. We cannot reset the complete shared pages list here as we need to retain the UEFI/OVMF firmware specific settings.
The host's shared pages list is maintained for the guest to keep track of all unencrypted guest memory regions, therefore we need to explicitly mark all shared pages as encrypted again before rebooting into the new guest kernel.
--- arch/x86/kernel/kvm.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
arch/x86/kernel/kvm.c +24 -0
@@ -39,6 +39,7 @@#include <asm/cpuidle_haltpoll.h> #include <asm/ptrace.h> #include <asm/svm.h> +#include <asm/e820/api.h> DEFINE_STATIC_KEY_FALSE (kvm_async_pf_enabled);
@@ -384,6 +385,29 @@ static void kvm_pv_guest_cpu_reboot(void *unused)*/ if (kvm_para_has_feature (KVM_FEATURE_PV_EOI ))wrmsrl (MSR_KVM_PV_EOI_EN ,0 ); +/* +* Reset the host's shared pages list related to kernel +* specific page encryption status settings before we load a +* new kernel by kexec. NOTE: We cannot reset the complete +* shared pages list here as we need to retain the +* UEFI/OVMF firmware specific settings. +*/ +if (sev_live_migration_enabled & (smp_processor_id () ==0 )) { +int i; +unsigned long nr_pages; + +for (i =0 ; i < e820_table->nr_entries; i++) { +struct e820_entry *entry = &e820_table->entries[i]; + +if (entry->type !=E820_TYPE_RAM ) +continue ; + + nr_pages =DIV_ROUND_UP (entry->size,PAGE_SIZE ); + +kvm_sev_hypercall3 (KVM_HC_PAGE_ENC_STATUS , + entry->addr, nr_pages,1 ); + } + }kvm_pv_disable_apf ();kvm_disable_steal_time (); }
Signature · 1 line
2.17.1
Could this patch set include support for the SEND_CANCEL command?
Quoted 207 lines · Ashish Kalra
From: Ashish Kalra <[email protected]>
The series add support for AMD SEV guest live migration commands. To protect the confidentiality of an SEV protected guest memory while in transit we need to use the SEV commands defined in SEV API spec [1].
SEV guest VMs have the concept of private and shared memory. Private memory is encrypted with the guest-specific key, while shared memory may be encrypted with hypervisor key. The commands provided by the SEV FW are meant to be used for the private memory only. The patch series introduces a new hypercall. The guest OS can use this hypercall to notify the page encryption status. If the page is encrypted with guest specific-key then we use SEV command during the migration. If page is not encrypted then fallback to default.
The patch adds new KVM_EXIT_DMA_SHARE/KVM_EXIT_DMA_UNSHARE hypercall to userspace exit functionality as a common interface from the guest back to the VMM and passing on the guest shared/unencrypted page information to the userspace VMM/Qemu. Qemu can consult this information during migration to know whether the page is encrypted.
This section descibes how the SEV live migration feature is negotiated between the host and guest, the host indicates this feature support via
KVM_FEATURE_CPUID. The guest firmware (OVMF) detects this feature and sets a UEFI enviroment variable indicating OVMF support for live migration, the guest kernel also detects the host support for this feature via cpuid and in case of an EFI boot verifies if OVMF also supports this feature by getting the UEFI enviroment variable and if it set then enables live migration feature on host by writing to a custom MSR, if not booted under EFI, then it simply enables the feature by again writing to the custom MSR. The MSR is also handled by the userspace VMM/Qemu.A branch containing these patches is available here:
https://github.com/AMDESE/linux/tree/sev-migration-v11[1] https://developer.amd.com/wp-content/resources/55766.PDF
Changes since v10:
- Adds new KVM_EXIT_DMA_SHARE/KVM_EXIT_DMA_UNSHARE hypercall to userspace exit functionality as a common interface from the guest back to the KVM and passing on the guest shared/unencrypted region information to the userspace VMM/Qemu. KVM/host kernel does not maintain the guest shared memory regions information anymore.
- Remove implicit enabling of SEV live migration feature for an SEV guest, now this is explicitly in control of the userspace VMM/Qemu.
- Custom MSR handling is also now moved into userspace VMM/Qemu.
- As KVM does not maintain the guest shared memory region information anymore,sev_dbg_crypt()cannot bypass unencrypted guest memory regions without support from userspace VMM/Qemu.Changes since v9:
- Transitioning from page encryption bitmap to the shared pages list to keep track of guest's shared/unencrypted memory regions.
- Move back to marking the complete_bss_decryptedsection as decrypted in the shared pages list.
- Invoke a new functioncheck_kvm_sev_migration()viakvm_init_platform()for guest to query for host-side support for SEV live migration and to enable the SEV live migration feature, to avoid #ifdefs in code
- RenameMSR_KVM_SEV_LIVE_MIG_ENtoMSR_KVM_SEV_LIVE_MIGRATION.
- Invoke a new functionhandle_unencrypted_region()fromsev_dbg_crypt()to bypass unencrypted guest memory regions.Changes since v8:
- Rebasing to kvm next branch.
- Fixed and added comments as per review feedback on v8 patches.
- Removed implicitly enabling live migration for incoming VMs in inKVM_SET_PAGE_ENC_BITMAP, it is now done viaKVM_SET_MSRioctl.
- Adds support for bypassing unencrypted guest memory regions forDBG_DECRYPTAPI calls, guest memory region encryption status insev_dbg_decrypt()is referenced using the page encryption bitmap.Changes since v7:
- Removed the hypervisor specific hypercall/paravirt callback for SEV live migration and moved back to callingkvm_sev_hypercall3directly.
- Fix build errors asbuild error when
CONFIG_HYPERVISOR_GUEST=yandCONFIG_AMD_MEM_ENCRYPT=n.
- Implicitly enabled live migration for incoming VM(s) to handle A->B->C->... VM migrations.
- Fixed Documentation as per comments on v6 patches.
- Fixed error return path insev_send_update_data()as per comments on v6 patches.Changes since v6:
- Rebasing to mainline and refactoring to the new split SVM infrastructre.
- Move to static allocation of the unified Page Encryption bitmap instead of the dynamic resizing of the bitmap, the static allocation is done implicitly by extendingkvm_arch_commit_memory_region()callack to add svm specificx86_opswhich can read the userspace provided memory region/memslots and calculate the amount of guest RAM managed by the KVM and grow the bitmap.
- FixedKVM_SET_PAGE_ENC_BITMAPioctl to set the whole bitmap instead of simply clearing specific bits.
- RemovedKVM_PAGE_ENC_BITMAP_RESETioctl, which is now performed usingKVM_SET_PAGE_ENC_BITMAP.
- Extended guest support for enabling Live Migration feature by adding a check for UEFI environment variable indicating OVMF support for Live Migration feature and additionally checking for KVM capability for the same feature. If not booted under EFI, then we simply check for KVM capability.
- Add hypervisor specific hypercall for SEV live migration by adding a new paravirt callback as part ofx86_hyper_runtime.
(x86 hypervisor specific runtime callbacks)
- Moving MSR handling forMSR_KVM_SEV_LIVE_MIG_ENinto svm/sev code and adding check for SEV live migration enabled by guest in theKVM_GET_PAGE_ENC_BITMAPioctl.
- Instead of the complete__bss_decryptedsection, only specific variables such ashv_clock_bootandwall_clockare marked as decrypted in the page encryption bitmapChanges since v5:
- Fix build errors asReported-by kbuild test robot <[email protected]>Changes since v4:
- Host support has been added to extend KVM capabilities/feature bits to include a newKVM_FEATURE_SEV_LIVE_MIGRATION, which the guest can query for host-side support for SEV live migration and a new custom MSRMSR_KVM_SEV_LIVE_MIG_ENis added for guest to enable the SEV live migration feature.
- Ensure that_bss_decryptedsection is marked as decrypted in the page encryption bitmap.
- FixingKVM_GET_PAGE_ENC_BITMAPioctl to return the correct bitmap as per the number of pages being requested by the user. Ensure that we only copybmap->num_pagesbytes in the userspace buffer, ifbmap->num_pagesis not byte aligned we read the trailing bits from the userspace and copy those bits as is. This fixes guest page(s) corruption issues observed after migration completion.
- Add kexec support for SEV Live Migration to reset the host's page encryption bitmap related to kernel specific page encryption status settings before we load a new kernel by kexec. We cannot reset the complete page encryption bitmap here as we need to retain the UEFI/OVMF firmware specific settings.Changes since v3:
- Rebasing to mainline and testing.
- Adding a newKVM_PAGE_ENC_BITMAP_RESETioctl, which resets the page encryption bitmap on a guest reboot event.
- Adding a more reliable sanity check for GPA range being passed to the hypercall to ensure that guest MMIO ranges are also marked in the page encryption bitmap.Changes since v2:
- reset the page encryption bitmap on vcpu rebootChanges since v1:
- Add support to share the page encryption between the source and target machine.
- Fix review feedbacks from Tom Lendacky.
- Add check to limit the session blob length.
- UpdateKVM_GET_PAGE_ENC_BITMAPicotl to use thebase_gfninstead of the memory slot when querying the bitmap.Ashish Kalra (5):
KVM: X86: IntroduceKVM_HC_PAGE_ENC_STATUShypercall
KVM: x86: Introduce newKVM_FEATURE_SEV_LIVE_MIGRATIONfeature &
Custom MSR.
EFI: Introduce the new AMD Memory Encryption GUID. x86/kvm: Add guest support for detecting and enabling SEV Live
Migration feature.
x86/kvm: Add kexec support for SEV Live Migration.Brijesh Singh (8):
KVM: SVM: AddKVM_SEVSEND_STARTcommand
KVM: SVM: AddKVM_SEND_UPDATE_DATAcommand
KVM: SVM: AddKVM_SEV_SEND_FINISHcommand
KVM: SVM: Add support forKVM_SEV_RECEIVE_STARTcommand
KVM: SVM: AddKVM_SEV_RECEIVE_UPDATE_DATAcommand
KVM: SVM: AddKVM_SEV_RECEIVE_FINISHcommand
KVM: x86: Add AMD SEV specific Hypercall3
mm: x86: Invoke hypercall when page encryption status is changed.../virt/kvm/amd-memory-encryption.rst | 120 ++++ Documentation/virt/kvm/api.rst | 18 + Documentation/virt/kvm/cpuid.rst | 5 + Documentation/virt/kvm/hypercalls.rst | 15 + Documentation/virt/kvm/msr.rst | 12 + arch/x86/include/asm/kvm_host.h | 2 + arch/x86/include/asm/kvm_para.h | 12 + arch/x86/include/asm/mem_encrypt.h | 8 + arch/x86/include/asm/paravirt.h | 10 + arch/x86/include/asm/paravirt_types.h | 2 + arch/x86/include/uapi/asm/kvm_para.h | 4 + arch/x86/kernel/kvm.c | 76 +++ arch/x86/kernel/paravirt.c | 1 + arch/x86/kvm/cpuid.c | 3 +- arch/x86/kvm/svm/sev.c | 514 ++++++++++++++++++ arch/x86/kvm/svm/svm.c | 24 + arch/x86/kvm/svm/svm.h | 2 + arch/x86/kvm/vmx/vmx.c | 1 + arch/x86/kvm/x86.c | 12 + arch/x86/mm/mem_encrypt.c | 98 +++- arch/x86/mm/pat/set_memory.c | 7 + include/linux/efi.h | 1 + include/linux/psp-sev.h | 8 +- include/uapi/linux/kvm.h | 47 ++ include/uapi/linux/kvm_para.h | 1 + 25 files changed, 997 insertions(+), 6 deletions(-)--
2.17.1
Quoted 3 lines · Peter Gonda
Could this patch set include support for the
SEND_CANCELcommand?
That's separate from this patchset. I sent up an implementation last week.
Paolo Bonzini
maintainerQuoted 5 lines · Steve Rutherford
Quoted 3 lines · Peter Gonda
Could this patch set include support for the
SEND_CANCELcommand?That's separate from this patchset. I sent up an implementation last week.
And I was going to queue it today.
Paolo
Quoted 204 lines · Ashish Kalra
From: Ashish Kalra <[email protected]>
The series add support for AMD SEV guest live migration commands. To protect the confidentiality of an SEV protected guest memory while in transit we need to use the SEV commands defined in SEV API spec [1].
SEV guest VMs have the concept of private and shared memory. Private memory is encrypted with the guest-specific key, while shared memory may be encrypted with hypervisor key. The commands provided by the SEV FW are meant to be used for the private memory only. The patch series introduces a new hypercall. The guest OS can use this hypercall to notify the page encryption status. If the page is encrypted with guest specific-key then we use SEV command during the migration. If page is not encrypted then fallback to default.
The patch adds new KVM_EXIT_DMA_SHARE/KVM_EXIT_DMA_UNSHARE hypercall to userspace exit functionality as a common interface from the guest back to the VMM and passing on the guest shared/unencrypted page information to the userspace VMM/Qemu. Qemu can consult this information during migration to know whether the page is encrypted.
This section descibes how the SEV live migration feature is negotiated between the host and guest, the host indicates this feature support via
KVM_FEATURE_CPUID. The guest firmware (OVMF) detects this feature and sets a UEFI enviroment variable indicating OVMF support for live migration, the guest kernel also detects the host support for this feature via cpuid and in case of an EFI boot verifies if OVMF also supports this feature by getting the UEFI enviroment variable and if it set then enables live migration feature on host by writing to a custom MSR, if not booted under EFI, then it simply enables the feature by again writing to the custom MSR. The MSR is also handled by the userspace VMM/Qemu.A branch containing these patches is available here:
https://github.com/AMDESE/linux/tree/sev-migration-v11[1] https://developer.amd.com/wp-content/resources/55766.PDF
Changes since v10:
- Adds new KVM_EXIT_DMA_SHARE/KVM_EXIT_DMA_UNSHARE hypercall to userspace exit functionality as a common interface from the guest back to the KVM and passing on the guest shared/unencrypted region information to the userspace VMM/Qemu. KVM/host kernel does not maintain the guest shared memory regions information anymore.
- Remove implicit enabling of SEV live migration feature for an SEV guest, now this is explicitly in control of the userspace VMM/Qemu.
- Custom MSR handling is also now moved into userspace VMM/Qemu.
- As KVM does not maintain the guest shared memory region information anymore,sev_dbg_crypt()cannot bypass unencrypted guest memory regions without support from userspace VMM/Qemu.Changes since v9:
- Transitioning from page encryption bitmap to the shared pages list to keep track of guest's shared/unencrypted memory regions.
- Move back to marking the complete_bss_decryptedsection as decrypted in the shared pages list.
- Invoke a new functioncheck_kvm_sev_migration()viakvm_init_platform()for guest to query for host-side support for SEV live migration and to enable the SEV live migration feature, to avoid #ifdefs in code
- RenameMSR_KVM_SEV_LIVE_MIG_ENtoMSR_KVM_SEV_LIVE_MIGRATION.
- Invoke a new functionhandle_unencrypted_region()fromsev_dbg_crypt()to bypass unencrypted guest memory regions.Changes since v8:
- Rebasing to kvm next branch.
- Fixed and added comments as per review feedback on v8 patches.
- Removed implicitly enabling live migration for incoming VMs in inKVM_SET_PAGE_ENC_BITMAP, it is now done viaKVM_SET_MSRioctl.
- Adds support for bypassing unencrypted guest memory regions forDBG_DECRYPTAPI calls, guest memory region encryption status insev_dbg_decrypt()is referenced using the page encryption bitmap.Changes since v7:
- Removed the hypervisor specific hypercall/paravirt callback for SEV live migration and moved back to callingkvm_sev_hypercall3directly.
- Fix build errors asbuild error when
CONFIG_HYPERVISOR_GUEST=yandCONFIG_AMD_MEM_ENCRYPT=n.
- Implicitly enabled live migration for incoming VM(s) to handle A->B->C->... VM migrations.
- Fixed Documentation as per comments on v6 patches.
- Fixed error return path insev_send_update_data()as per comments on v6 patches.Changes since v6:
- Rebasing to mainline and refactoring to the new split SVM infrastructre.
- Move to static allocation of the unified Page Encryption bitmap instead of the dynamic resizing of the bitmap, the static allocation is done implicitly by extendingkvm_arch_commit_memory_region()callack to add svm specificx86_opswhich can read the userspace provided memory region/memslots and calculate the amount of guest RAM managed by the KVM and grow the bitmap.
- FixedKVM_SET_PAGE_ENC_BITMAPioctl to set the whole bitmap instead of simply clearing specific bits.
- RemovedKVM_PAGE_ENC_BITMAP_RESETioctl, which is now performed usingKVM_SET_PAGE_ENC_BITMAP.
- Extended guest support for enabling Live Migration feature by adding a check for UEFI environment variable indicating OVMF support for Live Migration feature and additionally checking for KVM capability for the same feature. If not booted under EFI, then we simply check for KVM capability.
- Add hypervisor specific hypercall for SEV live migration by adding a new paravirt callback as part ofx86_hyper_runtime.
(x86 hypervisor specific runtime callbacks)
- Moving MSR handling forMSR_KVM_SEV_LIVE_MIG_ENinto svm/sev code and adding check for SEV live migration enabled by guest in theKVM_GET_PAGE_ENC_BITMAPioctl.
- Instead of the complete__bss_decryptedsection, only specific variables such ashv_clock_bootandwall_clockare marked as decrypted in the page encryption bitmapChanges since v5:
- Fix build errors asReported-by kbuild test robot <[email protected]>Changes since v4:
- Host support has been added to extend KVM capabilities/feature bits to include a newKVM_FEATURE_SEV_LIVE_MIGRATION, which the guest can query for host-side support for SEV live migration and a new custom MSRMSR_KVM_SEV_LIVE_MIG_ENis added for guest to enable the SEV live migration feature.
- Ensure that_bss_decryptedsection is marked as decrypted in the page encryption bitmap.
- FixingKVM_GET_PAGE_ENC_BITMAPioctl to return the correct bitmap as per the number of pages being requested by the user. Ensure that we only copybmap->num_pagesbytes in the userspace buffer, ifbmap->num_pagesis not byte aligned we read the trailing bits from the userspace and copy those bits as is. This fixes guest page(s) corruption issues observed after migration completion.
- Add kexec support for SEV Live Migration to reset the host's page encryption bitmap related to kernel specific page encryption status settings before we load a new kernel by kexec. We cannot reset the complete page encryption bitmap here as we need to retain the UEFI/OVMF firmware specific settings.Changes since v3:
- Rebasing to mainline and testing.
- Adding a newKVM_PAGE_ENC_BITMAP_RESETioctl, which resets the page encryption bitmap on a guest reboot event.
- Adding a more reliable sanity check for GPA range being passed to the hypercall to ensure that guest MMIO ranges are also marked in the page encryption bitmap.Changes since v2:
- reset the page encryption bitmap on vcpu rebootChanges since v1:
- Add support to share the page encryption between the source and target machine.
- Fix review feedbacks from Tom Lendacky.
- Add check to limit the session blob length.
- UpdateKVM_GET_PAGE_ENC_BITMAPicotl to use thebase_gfninstead of the memory slot when querying the bitmap.Ashish Kalra (5):
KVM: X86: IntroduceKVM_HC_PAGE_ENC_STATUShypercall
KVM: x86: Introduce newKVM_FEATURE_SEV_LIVE_MIGRATIONfeature &
Custom MSR.
EFI: Introduce the new AMD Memory Encryption GUID. x86/kvm: Add guest support for detecting and enabling SEV Live
Migration feature.
x86/kvm: Add kexec support for SEV Live Migration.Brijesh Singh (8):
KVM: SVM: AddKVM_SEVSEND_STARTcommand
KVM: SVM: AddKVM_SEND_UPDATE_DATAcommand
KVM: SVM: AddKVM_SEV_SEND_FINISHcommand
KVM: SVM: Add support forKVM_SEV_RECEIVE_STARTcommand
KVM: SVM: AddKVM_SEV_RECEIVE_UPDATE_DATAcommand
KVM: SVM: AddKVM_SEV_RECEIVE_FINISHcommand
KVM: x86: Add AMD SEV specific Hypercall3
mm: x86: Invoke hypercall when page encryption status is changed.../virt/kvm/amd-memory-encryption.rst | 120 ++++ Documentation/virt/kvm/api.rst | 18 + Documentation/virt/kvm/cpuid.rst | 5 + Documentation/virt/kvm/hypercalls.rst | 15 + Documentation/virt/kvm/msr.rst | 12 + arch/x86/include/asm/kvm_host.h | 2 + arch/x86/include/asm/kvm_para.h | 12 + arch/x86/include/asm/mem_encrypt.h | 8 + arch/x86/include/asm/paravirt.h | 10 + arch/x86/include/asm/paravirt_types.h | 2 + arch/x86/include/uapi/asm/kvm_para.h | 4 + arch/x86/kernel/kvm.c | 76 +++ arch/x86/kernel/paravirt.c | 1 + arch/x86/kvm/cpuid.c | 3 +- arch/x86/kvm/svm/sev.c | 514 ++++++++++++++++++ arch/x86/kvm/svm/svm.c | 24 + arch/x86/kvm/svm/svm.h | 2 + arch/x86/kvm/vmx/vmx.c | 1 + arch/x86/kvm/x86.c | 12 + arch/x86/mm/mem_encrypt.c | 98 +++- arch/x86/mm/pat/set_memory.c | 7 + include/linux/efi.h | 1 + include/linux/psp-sev.h | 8 +- include/uapi/linux/kvm.h | 47 ++ include/uapi/linux/kvm_para.h | 1 + 25 files changed, 997 insertions(+), 6 deletions(-)
Quoted 3 lines
--
2.17.1
Overall, these patches are in pretty good shape. I have some nits, but otherwise these seem good to go.