* [PATCH 1/5] KVM: SVM: Decrypt SEV VMSA in dump_vmcb() if debugging is enabled
2025-03-20 13:26 [PATCH 0/5] Provide SEV-ES/SEV-SNP support for decrypting the VMSA Tom Lendacky
@ 2025-03-20 13:26 ` Tom Lendacky
2025-03-21 14:36 ` Tom Lendacky
2025-03-24 21:31 ` Tom Lendacky
2025-03-20 13:26 ` [PATCH 2/5] KVM: SVM: Dump guest register state in dump_vmcb() Tom Lendacky
` (5 subsequent siblings)
6 siblings, 2 replies; 16+ messages in thread
From: Tom Lendacky @ 2025-03-20 13:26 UTC (permalink / raw)
To: kvm, linux-kernel, x86
Cc: Paolo Bonzini, Sean Christopherson, Borislav Petkov, Dave Hansen,
Ingo Molnar, Thomas Gleixner, Michael Roth
An SEV-ES/SEV-SNP VM save area (VMSA) can be decrypted if the guest
policy allows debugging. Update the dump_vmcb() routine to output
some of the SEV VMSA contents if possible. This can be useful for
debug purposes.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
arch/x86/kvm/svm/sev.c | 98 ++++++++++++++++++++++++++++++++++++++++++
arch/x86/kvm/svm/svm.c | 13 ++++++
arch/x86/kvm/svm/svm.h | 11 +++++
3 files changed, 122 insertions(+)
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 661108d65ee7..6e3f5042d9ce 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -563,6 +563,8 @@ static int sev_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp)
if (copy_from_user(¶ms, u64_to_user_ptr(argp->data), sizeof(params)))
return -EFAULT;
+ sev->policy = params.policy;
+
memset(&start, 0, sizeof(start));
dh_blob = NULL;
@@ -2220,6 +2222,8 @@ static int snp_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp)
if (params.policy & SNP_POLICY_MASK_SINGLE_SOCKET)
return -EINVAL;
+ sev->policy = params.policy;
+
sev->snp_context = snp_context_create(kvm, argp);
if (!sev->snp_context)
return -ENOTTY;
@@ -4975,3 +4979,97 @@ int sev_private_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn)
return level;
}
+
+struct vmcb_save_area *sev_decrypt_vmsa(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+ struct vmcb_save_area *vmsa;
+ struct kvm_sev_info *sev;
+ int error = 0;
+ int ret;
+
+ if (!sev_es_guest(vcpu->kvm))
+ return NULL;
+
+ /*
+ * If the VMSA has not yet been encrypted, return a pointer to the
+ * current un-encrypted VMSA.
+ */
+ if (!vcpu->arch.guest_state_protected)
+ return (struct vmcb_save_area *)svm->sev_es.vmsa;
+
+ sev = to_kvm_sev_info(vcpu->kvm);
+
+ /* Check if the SEV policy allows debugging */
+ if (sev_snp_guest(vcpu->kvm)) {
+ if (!(sev->policy & SNP_POLICY_DEBUG))
+ return NULL;
+ } else {
+ if (sev->policy & SEV_POLICY_NODBG)
+ return NULL;
+ }
+
+ if (sev_snp_guest(vcpu->kvm)) {
+ struct sev_data_snp_dbg dbg = {0};
+
+ vmsa = snp_alloc_firmware_page(__GFP_ZERO);
+ if (!vmsa)
+ return NULL;
+
+ dbg.gctx_paddr = __psp_pa(sev->snp_context);
+ dbg.src_addr = svm->vmcb->control.vmsa_pa;
+ dbg.dst_addr = __psp_pa(vmsa);
+
+ ret = sev_issue_cmd(vcpu->kvm, SEV_CMD_SNP_DBG_DECRYPT, &dbg, &error);
+
+ /*
+ * Return the target page to a hypervisor page no matter what.
+ * If this fails, the page can't be used, so leak it and don't
+ * try to use it.
+ */
+ if (snp_page_reclaim(vcpu->kvm, PHYS_PFN(__pa(vmsa))))
+ return NULL;
+
+ if (ret) {
+ pr_err("SEV: SNP_DBG_DECRYPT failed ret=%d, fw_error=%d (%#x)\n",
+ ret, error, error);
+ free_page((unsigned long)vmsa);
+
+ return NULL;
+ }
+ } else {
+ struct sev_data_dbg dbg = {0};
+ struct page *vmsa_page;
+
+ vmsa_page = alloc_page(GFP_KERNEL);
+ if (!vmsa_page)
+ return NULL;
+
+ vmsa = page_address(vmsa_page);
+
+ dbg.handle = sev->handle;
+ dbg.src_addr = svm->vmcb->control.vmsa_pa;
+ dbg.dst_addr = __psp_pa(vmsa);
+ dbg.len = PAGE_SIZE;
+
+ ret = sev_issue_cmd(vcpu->kvm, SEV_CMD_DBG_DECRYPT, &dbg, &error);
+ if (ret) {
+ pr_err("SEV: SEV_CMD_DBG_DECRYPT failed ret=%d, fw_error=%d (0x%x)\n",
+ ret, error, error);
+ __free_page(vmsa_page);
+
+ return NULL;
+ }
+ }
+
+ return vmsa;
+}
+
+void sev_free_decrypted_vmsa(struct kvm_vcpu *vcpu, struct vmcb_save_area *vmsa)
+{
+ /* If the VMSA has not yet been encrypted, nothing was allocated */
+ if (!vcpu->arch.guest_state_protected || !vmsa)
+ return;
+
+ free_page((unsigned long)vmsa);
+}
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index e67de787fc71..21477871073c 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -3423,6 +3423,15 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
pr_err("%-20s%016llx\n", "avic_logical_id:", control->avic_logical_id);
pr_err("%-20s%016llx\n", "avic_physical_id:", control->avic_physical_id);
pr_err("%-20s%016llx\n", "vmsa_pa:", control->vmsa_pa);
+
+ if (sev_es_guest(vcpu->kvm)) {
+ save = sev_decrypt_vmsa(vcpu);
+ if (!save)
+ goto no_vmsa;
+
+ save01 = save;
+ }
+
pr_err("VMCB State Save Area:\n");
pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
"es:",
@@ -3493,6 +3502,10 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
pr_err("%-15s %016llx %-13s %016llx\n",
"excp_from:", save->last_excp_from,
"excp_to:", save->last_excp_to);
+
+no_vmsa:
+ if (sev_es_guest(vcpu->kvm))
+ sev_free_decrypted_vmsa(vcpu, save);
}
static bool svm_check_exit_valid(u64 exit_code)
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index ea44c1da5a7c..66979ddc3659 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -98,6 +98,7 @@ struct kvm_sev_info {
unsigned int asid; /* ASID used for this guest */
unsigned int handle; /* SEV firmware handle */
int fd; /* SEV device fd */
+ unsigned long policy;
unsigned long pages_locked; /* Number of pages locked */
struct list_head regions_list; /* List of registered regions */
u64 ap_jump_table; /* SEV-ES AP Jump Table address */
@@ -114,6 +115,9 @@ struct kvm_sev_info {
struct mutex guest_req_mutex; /* Must acquire before using bounce buffers */
};
+#define SEV_POLICY_NODBG BIT_ULL(0)
+#define SNP_POLICY_DEBUG BIT_ULL(19)
+
struct kvm_svm {
struct kvm kvm;
@@ -756,6 +760,8 @@ void sev_snp_init_protected_guest_state(struct kvm_vcpu *vcpu);
int sev_gmem_prepare(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order);
void sev_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end);
int sev_private_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn);
+struct vmcb_save_area *sev_decrypt_vmsa(struct kvm_vcpu *vcpu);
+void sev_free_decrypted_vmsa(struct kvm_vcpu *vcpu, struct vmcb_save_area *vmsa);
#else
static inline struct page *snp_safe_alloc_page_node(int node, gfp_t gfp)
{
@@ -787,6 +793,11 @@ static inline int sev_private_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn)
return 0;
}
+static inline struct vmcb_save_area *sev_decrypt_vmsa(struct kvm_vcpu *vcpu)
+{
+ return NULL;
+}
+static inline void sev_free_decrypted_vmsa(struct kvm_vcpu *vcpu, struct vmcb_save_area *vmsa) {}
#endif
/* vmenter.S */
--
2.46.2
^ permalink raw reply related [flat|nested] 16+ messages in thread* Re: [PATCH 1/5] KVM: SVM: Decrypt SEV VMSA in dump_vmcb() if debugging is enabled
2025-03-20 13:26 ` [PATCH 1/5] KVM: SVM: Decrypt SEV VMSA in dump_vmcb() if debugging is enabled Tom Lendacky
@ 2025-03-21 14:36 ` Tom Lendacky
2025-03-21 14:40 ` Tom Lendacky
2025-03-24 21:31 ` Tom Lendacky
1 sibling, 1 reply; 16+ messages in thread
From: Tom Lendacky @ 2025-03-21 14:36 UTC (permalink / raw)
To: kvm, linux-kernel, x86
Cc: Paolo Bonzini, Sean Christopherson, Borislav Petkov, Dave Hansen,
Ingo Molnar, Thomas Gleixner, Michael Roth
On 3/20/25 08:26, Tom Lendacky wrote:
> An SEV-ES/SEV-SNP VM save area (VMSA) can be decrypted if the guest
> policy allows debugging. Update the dump_vmcb() routine to output
> some of the SEV VMSA contents if possible. This can be useful for
> debug purposes.
>
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
> arch/x86/kvm/svm/sev.c | 98 ++++++++++++++++++++++++++++++++++++++++++
> arch/x86/kvm/svm/svm.c | 13 ++++++
> arch/x86/kvm/svm/svm.h | 11 +++++
> 3 files changed, 122 insertions(+)
>
> diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
> index 661108d65ee7..6e3f5042d9ce 100644
> --- a/arch/x86/kvm/svm/sev.c
> +++ b/arch/x86/kvm/svm/sev.c
> @@ -563,6 +563,8 @@ static int sev_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp)
> if (copy_from_user(¶ms, u64_to_user_ptr(argp->data), sizeof(params)))
> return -EFAULT;
>
> + sev->policy = params.policy;
> +
> memset(&start, 0, sizeof(start));
>
> dh_blob = NULL;
> @@ -2220,6 +2222,8 @@ static int snp_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp)
> if (params.policy & SNP_POLICY_MASK_SINGLE_SOCKET)
> return -EINVAL;
>
> + sev->policy = params.policy;
> +
> sev->snp_context = snp_context_create(kvm, argp);
> if (!sev->snp_context)
> return -ENOTTY;
> @@ -4975,3 +4979,97 @@ int sev_private_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn)
>
> return level;
> }
> +
> +struct vmcb_save_area *sev_decrypt_vmsa(struct kvm_vcpu *vcpu)
> +{
> + struct vcpu_svm *svm = to_svm(vcpu);
> + struct vmcb_save_area *vmsa;
> + struct kvm_sev_info *sev;
> + int error = 0;
> + int ret;
> +
> + if (!sev_es_guest(vcpu->kvm))
> + return NULL;
> +
> + /*
> + * If the VMSA has not yet been encrypted, return a pointer to the
> + * current un-encrypted VMSA.
> + */
> + if (!vcpu->arch.guest_state_protected)
> + return (struct vmcb_save_area *)svm->sev_es.vmsa;
> +
> + sev = to_kvm_sev_info(vcpu->kvm);
> +
> + /* Check if the SEV policy allows debugging */
> + if (sev_snp_guest(vcpu->kvm)) {
> + if (!(sev->policy & SNP_POLICY_DEBUG))
> + return NULL;
> + } else {
> + if (sev->policy & SEV_POLICY_NODBG)
> + return NULL;
> + }
> +
> + if (sev_snp_guest(vcpu->kvm)) {
> + struct sev_data_snp_dbg dbg = {0};
> +
> + vmsa = snp_alloc_firmware_page(__GFP_ZERO);
> + if (!vmsa)
> + return NULL;
> +
> + dbg.gctx_paddr = __psp_pa(sev->snp_context);
> + dbg.src_addr = svm->vmcb->control.vmsa_pa;
> + dbg.dst_addr = __psp_pa(vmsa);
> +
> + ret = sev_issue_cmd(vcpu->kvm, SEV_CMD_SNP_DBG_DECRYPT, &dbg, &error);
> +
> + /*
> + * Return the target page to a hypervisor page no matter what.
> + * If this fails, the page can't be used, so leak it and don't
> + * try to use it.
> + */
> + if (snp_page_reclaim(vcpu->kvm, PHYS_PFN(__pa(vmsa))))
> + return NULL;
And actually I should call snp_leak_pages() here to record that. I'll add
that to the next version.
Thanks,
Tom
> +
> + if (ret) {
> + pr_err("SEV: SNP_DBG_DECRYPT failed ret=%d, fw_error=%d (%#x)\n",
> + ret, error, error);
> + free_page((unsigned long)vmsa);
> +
> + return NULL;
> + }
> + } else {
> + struct sev_data_dbg dbg = {0};
> + struct page *vmsa_page;
> +
> + vmsa_page = alloc_page(GFP_KERNEL);
> + if (!vmsa_page)
> + return NULL;
> +
> + vmsa = page_address(vmsa_page);
> +
> + dbg.handle = sev->handle;
> + dbg.src_addr = svm->vmcb->control.vmsa_pa;
> + dbg.dst_addr = __psp_pa(vmsa);
> + dbg.len = PAGE_SIZE;
> +
> + ret = sev_issue_cmd(vcpu->kvm, SEV_CMD_DBG_DECRYPT, &dbg, &error);
> + if (ret) {
> + pr_err("SEV: SEV_CMD_DBG_DECRYPT failed ret=%d, fw_error=%d (0x%x)\n",
> + ret, error, error);
> + __free_page(vmsa_page);
> +
> + return NULL;
> + }
> + }
> +
> + return vmsa;
> +}
> +
> +void sev_free_decrypted_vmsa(struct kvm_vcpu *vcpu, struct vmcb_save_area *vmsa)
> +{
> + /* If the VMSA has not yet been encrypted, nothing was allocated */
> + if (!vcpu->arch.guest_state_protected || !vmsa)
> + return;
> +
> + free_page((unsigned long)vmsa);
> +}
> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> index e67de787fc71..21477871073c 100644
> --- a/arch/x86/kvm/svm/svm.c
> +++ b/arch/x86/kvm/svm/svm.c
> @@ -3423,6 +3423,15 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
> pr_err("%-20s%016llx\n", "avic_logical_id:", control->avic_logical_id);
> pr_err("%-20s%016llx\n", "avic_physical_id:", control->avic_physical_id);
> pr_err("%-20s%016llx\n", "vmsa_pa:", control->vmsa_pa);
> +
> + if (sev_es_guest(vcpu->kvm)) {
> + save = sev_decrypt_vmsa(vcpu);
> + if (!save)
> + goto no_vmsa;
> +
> + save01 = save;
> + }
> +
> pr_err("VMCB State Save Area:\n");
> pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
> "es:",
> @@ -3493,6 +3502,10 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
> pr_err("%-15s %016llx %-13s %016llx\n",
> "excp_from:", save->last_excp_from,
> "excp_to:", save->last_excp_to);
> +
> +no_vmsa:
> + if (sev_es_guest(vcpu->kvm))
> + sev_free_decrypted_vmsa(vcpu, save);
> }
>
> static bool svm_check_exit_valid(u64 exit_code)
> diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
> index ea44c1da5a7c..66979ddc3659 100644
> --- a/arch/x86/kvm/svm/svm.h
> +++ b/arch/x86/kvm/svm/svm.h
> @@ -98,6 +98,7 @@ struct kvm_sev_info {
> unsigned int asid; /* ASID used for this guest */
> unsigned int handle; /* SEV firmware handle */
> int fd; /* SEV device fd */
> + unsigned long policy;
> unsigned long pages_locked; /* Number of pages locked */
> struct list_head regions_list; /* List of registered regions */
> u64 ap_jump_table; /* SEV-ES AP Jump Table address */
> @@ -114,6 +115,9 @@ struct kvm_sev_info {
> struct mutex guest_req_mutex; /* Must acquire before using bounce buffers */
> };
>
> +#define SEV_POLICY_NODBG BIT_ULL(0)
> +#define SNP_POLICY_DEBUG BIT_ULL(19)
> +
> struct kvm_svm {
> struct kvm kvm;
>
> @@ -756,6 +760,8 @@ void sev_snp_init_protected_guest_state(struct kvm_vcpu *vcpu);
> int sev_gmem_prepare(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order);
> void sev_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end);
> int sev_private_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn);
> +struct vmcb_save_area *sev_decrypt_vmsa(struct kvm_vcpu *vcpu);
> +void sev_free_decrypted_vmsa(struct kvm_vcpu *vcpu, struct vmcb_save_area *vmsa);
> #else
> static inline struct page *snp_safe_alloc_page_node(int node, gfp_t gfp)
> {
> @@ -787,6 +793,11 @@ static inline int sev_private_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn)
> return 0;
> }
>
> +static inline struct vmcb_save_area *sev_decrypt_vmsa(struct kvm_vcpu *vcpu)
> +{
> + return NULL;
> +}
> +static inline void sev_free_decrypted_vmsa(struct kvm_vcpu *vcpu, struct vmcb_save_area *vmsa) {}
> #endif
>
> /* vmenter.S */
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH 1/5] KVM: SVM: Decrypt SEV VMSA in dump_vmcb() if debugging is enabled
2025-03-21 14:36 ` Tom Lendacky
@ 2025-03-21 14:40 ` Tom Lendacky
0 siblings, 0 replies; 16+ messages in thread
From: Tom Lendacky @ 2025-03-21 14:40 UTC (permalink / raw)
To: kvm, linux-kernel, x86
Cc: Paolo Bonzini, Sean Christopherson, Borislav Petkov, Dave Hansen,
Ingo Molnar, Thomas Gleixner, Michael Roth
On 3/21/25 09:36, Tom Lendacky wrote:
> On 3/20/25 08:26, Tom Lendacky wrote:
>> An SEV-ES/SEV-SNP VM save area (VMSA) can be decrypted if the guest
>> policy allows debugging. Update the dump_vmcb() routine to output
>> some of the SEV VMSA contents if possible. This can be useful for
>> debug purposes.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>> + /*
>> + * Return the target page to a hypervisor page no matter what.
>> + * If this fails, the page can't be used, so leak it and don't
>> + * try to use it.
>> + */
>> + if (snp_page_reclaim(vcpu->kvm, PHYS_PFN(__pa(vmsa))))
>> + return NULL;
>
> And actually I should call snp_leak_pages() here to record that. I'll add
> that to the next version.
Err... snp_page_reclaim() already does that. Nevermind.
Thanks,
Tom
>
> Thanks,
> Tom
>
>> +
>> + if (ret) {
>> + pr_err("SEV: SNP_DBG_DECRYPT failed ret=%d, fw_error=%d (%#x)\n",
>> + ret, error, error);
>> + free_page((unsigned long)vmsa);
>> +
>> + return NULL;
>> + }
>> + } else {
>> + struct sev_data_dbg dbg = {0};
>> + struct page *vmsa_page;
>> +
>> + vmsa_page = alloc_page(GFP_KERNEL);
>> + if (!vmsa_page)
>> + return NULL;
>> +
>> + vmsa = page_address(vmsa_page);
>> +
>> + dbg.handle = sev->handle;
>> + dbg.src_addr = svm->vmcb->control.vmsa_pa;
>> + dbg.dst_addr = __psp_pa(vmsa);
>> + dbg.len = PAGE_SIZE;
>> +
>> + ret = sev_issue_cmd(vcpu->kvm, SEV_CMD_DBG_DECRYPT, &dbg, &error);
>> + if (ret) {
>> + pr_err("SEV: SEV_CMD_DBG_DECRYPT failed ret=%d, fw_error=%d (0x%x)\n",
>> + ret, error, error);
>> + __free_page(vmsa_page);
>> +
>> + return NULL;
>> + }
>> + }
>> +
>> + return vmsa;
>> +}
>> +
>> +void sev_free_decrypted_vmsa(struct kvm_vcpu *vcpu, struct vmcb_save_area *vmsa)
>> +{
>> + /* If the VMSA has not yet been encrypted, nothing was allocated */
>> + if (!vcpu->arch.guest_state_protected || !vmsa)
>> + return;
>> +
>> + free_page((unsigned long)vmsa);
>> +}
>> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
>> index e67de787fc71..21477871073c 100644
>> --- a/arch/x86/kvm/svm/svm.c
>> +++ b/arch/x86/kvm/svm/svm.c
>> @@ -3423,6 +3423,15 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
>> pr_err("%-20s%016llx\n", "avic_logical_id:", control->avic_logical_id);
>> pr_err("%-20s%016llx\n", "avic_physical_id:", control->avic_physical_id);
>> pr_err("%-20s%016llx\n", "vmsa_pa:", control->vmsa_pa);
>> +
>> + if (sev_es_guest(vcpu->kvm)) {
>> + save = sev_decrypt_vmsa(vcpu);
>> + if (!save)
>> + goto no_vmsa;
>> +
>> + save01 = save;
>> + }
>> +
>> pr_err("VMCB State Save Area:\n");
>> pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
>> "es:",
>> @@ -3493,6 +3502,10 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
>> pr_err("%-15s %016llx %-13s %016llx\n",
>> "excp_from:", save->last_excp_from,
>> "excp_to:", save->last_excp_to);
>> +
>> +no_vmsa:
>> + if (sev_es_guest(vcpu->kvm))
>> + sev_free_decrypted_vmsa(vcpu, save);
>> }
>>
>> static bool svm_check_exit_valid(u64 exit_code)
>> diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
>> index ea44c1da5a7c..66979ddc3659 100644
>> --- a/arch/x86/kvm/svm/svm.h
>> +++ b/arch/x86/kvm/svm/svm.h
>> @@ -98,6 +98,7 @@ struct kvm_sev_info {
>> unsigned int asid; /* ASID used for this guest */
>> unsigned int handle; /* SEV firmware handle */
>> int fd; /* SEV device fd */
>> + unsigned long policy;
>> unsigned long pages_locked; /* Number of pages locked */
>> struct list_head regions_list; /* List of registered regions */
>> u64 ap_jump_table; /* SEV-ES AP Jump Table address */
>> @@ -114,6 +115,9 @@ struct kvm_sev_info {
>> struct mutex guest_req_mutex; /* Must acquire before using bounce buffers */
>> };
>>
>> +#define SEV_POLICY_NODBG BIT_ULL(0)
>> +#define SNP_POLICY_DEBUG BIT_ULL(19)
>> +
>> struct kvm_svm {
>> struct kvm kvm;
>>
>> @@ -756,6 +760,8 @@ void sev_snp_init_protected_guest_state(struct kvm_vcpu *vcpu);
>> int sev_gmem_prepare(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order);
>> void sev_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end);
>> int sev_private_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn);
>> +struct vmcb_save_area *sev_decrypt_vmsa(struct kvm_vcpu *vcpu);
>> +void sev_free_decrypted_vmsa(struct kvm_vcpu *vcpu, struct vmcb_save_area *vmsa);
>> #else
>> static inline struct page *snp_safe_alloc_page_node(int node, gfp_t gfp)
>> {
>> @@ -787,6 +793,11 @@ static inline int sev_private_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn)
>> return 0;
>> }
>>
>> +static inline struct vmcb_save_area *sev_decrypt_vmsa(struct kvm_vcpu *vcpu)
>> +{
>> + return NULL;
>> +}
>> +static inline void sev_free_decrypted_vmsa(struct kvm_vcpu *vcpu, struct vmcb_save_area *vmsa) {}
>> #endif
>>
>> /* vmenter.S */
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/5] KVM: SVM: Decrypt SEV VMSA in dump_vmcb() if debugging is enabled
2025-03-20 13:26 ` [PATCH 1/5] KVM: SVM: Decrypt SEV VMSA in dump_vmcb() if debugging is enabled Tom Lendacky
2025-03-21 14:36 ` Tom Lendacky
@ 2025-03-24 21:31 ` Tom Lendacky
2025-04-10 23:14 ` Sean Christopherson
1 sibling, 1 reply; 16+ messages in thread
From: Tom Lendacky @ 2025-03-24 21:31 UTC (permalink / raw)
To: kvm, linux-kernel, x86
Cc: Paolo Bonzini, Sean Christopherson, Borislav Petkov, Dave Hansen,
Ingo Molnar, Thomas Gleixner, Michael Roth
On 3/20/25 08:26, Tom Lendacky wrote:
> An SEV-ES/SEV-SNP VM save area (VMSA) can be decrypted if the guest
> policy allows debugging. Update the dump_vmcb() routine to output
> some of the SEV VMSA contents if possible. This can be useful for
> debug purposes.
>
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
> arch/x86/kvm/svm/sev.c | 98 ++++++++++++++++++++++++++++++++++++++++++
> arch/x86/kvm/svm/svm.c | 13 ++++++
> arch/x86/kvm/svm/svm.h | 11 +++++
> 3 files changed, 122 insertions(+)
>
> diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
> index 661108d65ee7..6e3f5042d9ce 100644
> --- a/arch/x86/kvm/svm/sev.c
> +++ b/arch/x86/kvm/svm/sev.c
> +
> + if (sev_snp_guest(vcpu->kvm)) {
> + struct sev_data_snp_dbg dbg = {0};
> +
> + vmsa = snp_alloc_firmware_page(__GFP_ZERO);
> + if (!vmsa)
> + return NULL;
> +
> + dbg.gctx_paddr = __psp_pa(sev->snp_context);
> + dbg.src_addr = svm->vmcb->control.vmsa_pa;
> + dbg.dst_addr = __psp_pa(vmsa);
> +
> + ret = sev_issue_cmd(vcpu->kvm, SEV_CMD_SNP_DBG_DECRYPT, &dbg, &error);
This can also be sev_do_cmd() where the file descriptor isn't checked.
Since it isn't really a user initiated call, that might be desirable since
this could also be useful for debugging during guest destruction (when the
file descriptor has already been closed) for VMSAs that haven't exited
with an INVALID exit code.
Just an FYI, I can change this call and the one below to sev_do_cmd() if
agreed upon.
Thanks,
Tom
> +
> + /*
> + * Return the target page to a hypervisor page no matter what.
> + * If this fails, the page can't be used, so leak it and don't
> + * try to use it.
> + */
> + if (snp_page_reclaim(vcpu->kvm, PHYS_PFN(__pa(vmsa))))
> + return NULL;
> +
> + if (ret) {
> + pr_err("SEV: SNP_DBG_DECRYPT failed ret=%d, fw_error=%d (%#x)\n",
> + ret, error, error);
> + free_page((unsigned long)vmsa);
> +
> + return NULL;
> + }
> + } else {
> + struct sev_data_dbg dbg = {0};
> + struct page *vmsa_page;
> +
> + vmsa_page = alloc_page(GFP_KERNEL);
> + if (!vmsa_page)
> + return NULL;
> +
> + vmsa = page_address(vmsa_page);
> +
> + dbg.handle = sev->handle;
> + dbg.src_addr = svm->vmcb->control.vmsa_pa;
> + dbg.dst_addr = __psp_pa(vmsa);
> + dbg.len = PAGE_SIZE;
> +
> + ret = sev_issue_cmd(vcpu->kvm, SEV_CMD_DBG_DECRYPT, &dbg, &error);
> + if (ret) {
> + pr_err("SEV: SEV_CMD_DBG_DECRYPT failed ret=%d, fw_error=%d (0x%x)\n",
> + ret, error, error);
> + __free_page(vmsa_page);
> +
> + return NULL;
> + }
> + }
> +
> + return vmsa;
> +}
> +
> +void sev_free_decrypted_vmsa(struct kvm_vcpu *vcpu, struct vmcb_save_area *vmsa)
> +{
> + /* If the VMSA has not yet been encrypted, nothing was allocated */
> + if (!vcpu->arch.guest_state_protected || !vmsa)
> + return;
> +
> + free_page((unsigned long)vmsa);
> +}
> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> index e67de787fc71..21477871073c 100644
> --- a/arch/x86/kvm/svm/svm.c
> +++ b/arch/x86/kvm/svm/svm.c
> @@ -3423,6 +3423,15 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
> pr_err("%-20s%016llx\n", "avic_logical_id:", control->avic_logical_id);
> pr_err("%-20s%016llx\n", "avic_physical_id:", control->avic_physical_id);
> pr_err("%-20s%016llx\n", "vmsa_pa:", control->vmsa_pa);
> +
> + if (sev_es_guest(vcpu->kvm)) {
> + save = sev_decrypt_vmsa(vcpu);
> + if (!save)
> + goto no_vmsa;
> +
> + save01 = save;
> + }
> +
> pr_err("VMCB State Save Area:\n");
> pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
> "es:",
> @@ -3493,6 +3502,10 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
> pr_err("%-15s %016llx %-13s %016llx\n",
> "excp_from:", save->last_excp_from,
> "excp_to:", save->last_excp_to);
> +
> +no_vmsa:
> + if (sev_es_guest(vcpu->kvm))
> + sev_free_decrypted_vmsa(vcpu, save);
> }
>
> static bool svm_check_exit_valid(u64 exit_code)
> diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
> index ea44c1da5a7c..66979ddc3659 100644
> --- a/arch/x86/kvm/svm/svm.h
> +++ b/arch/x86/kvm/svm/svm.h
> @@ -98,6 +98,7 @@ struct kvm_sev_info {
> unsigned int asid; /* ASID used for this guest */
> unsigned int handle; /* SEV firmware handle */
> int fd; /* SEV device fd */
> + unsigned long policy;
> unsigned long pages_locked; /* Number of pages locked */
> struct list_head regions_list; /* List of registered regions */
> u64 ap_jump_table; /* SEV-ES AP Jump Table address */
> @@ -114,6 +115,9 @@ struct kvm_sev_info {
> struct mutex guest_req_mutex; /* Must acquire before using bounce buffers */
> };
>
> +#define SEV_POLICY_NODBG BIT_ULL(0)
> +#define SNP_POLICY_DEBUG BIT_ULL(19)
> +
> struct kvm_svm {
> struct kvm kvm;
>
> @@ -756,6 +760,8 @@ void sev_snp_init_protected_guest_state(struct kvm_vcpu *vcpu);
> int sev_gmem_prepare(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order);
> void sev_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end);
> int sev_private_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn);
> +struct vmcb_save_area *sev_decrypt_vmsa(struct kvm_vcpu *vcpu);
> +void sev_free_decrypted_vmsa(struct kvm_vcpu *vcpu, struct vmcb_save_area *vmsa);
> #else
> static inline struct page *snp_safe_alloc_page_node(int node, gfp_t gfp)
> {
> @@ -787,6 +793,11 @@ static inline int sev_private_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn)
> return 0;
> }
>
> +static inline struct vmcb_save_area *sev_decrypt_vmsa(struct kvm_vcpu *vcpu)
> +{
> + return NULL;
> +}
> +static inline void sev_free_decrypted_vmsa(struct kvm_vcpu *vcpu, struct vmcb_save_area *vmsa) {}
> #endif
>
> /* vmenter.S */
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH 1/5] KVM: SVM: Decrypt SEV VMSA in dump_vmcb() if debugging is enabled
2025-03-24 21:31 ` Tom Lendacky
@ 2025-04-10 23:14 ` Sean Christopherson
2025-04-14 16:11 ` Tom Lendacky
0 siblings, 1 reply; 16+ messages in thread
From: Sean Christopherson @ 2025-04-10 23:14 UTC (permalink / raw)
To: Tom Lendacky
Cc: kvm, linux-kernel, x86, Paolo Bonzini, Borislav Petkov,
Dave Hansen, Ingo Molnar, Thomas Gleixner, Michael Roth
On Mon, Mar 24, 2025, Tom Lendacky wrote:
> On 3/20/25 08:26, Tom Lendacky wrote:
> > An SEV-ES/SEV-SNP VM save area (VMSA) can be decrypted if the guest
> > policy allows debugging. Update the dump_vmcb() routine to output
> > some of the SEV VMSA contents if possible. This can be useful for
> > debug purposes.
> >
> > Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> > ---
> > arch/x86/kvm/svm/sev.c | 98 ++++++++++++++++++++++++++++++++++++++++++
> > arch/x86/kvm/svm/svm.c | 13 ++++++
> > arch/x86/kvm/svm/svm.h | 11 +++++
> > 3 files changed, 122 insertions(+)
> >
> > diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
> > index 661108d65ee7..6e3f5042d9ce 100644
> > --- a/arch/x86/kvm/svm/sev.c
> > +++ b/arch/x86/kvm/svm/sev.c
>
> > +
> > + if (sev_snp_guest(vcpu->kvm)) {
> > + struct sev_data_snp_dbg dbg = {0};
> > +
> > + vmsa = snp_alloc_firmware_page(__GFP_ZERO);
> > + if (!vmsa)
> > + return NULL;
> > +
> > + dbg.gctx_paddr = __psp_pa(sev->snp_context);
> > + dbg.src_addr = svm->vmcb->control.vmsa_pa;
> > + dbg.dst_addr = __psp_pa(vmsa);
> > +
> > + ret = sev_issue_cmd(vcpu->kvm, SEV_CMD_SNP_DBG_DECRYPT, &dbg, &error);
>
> This can also be sev_do_cmd() where the file descriptor isn't checked.
> Since it isn't really a user initiated call, that might be desirable since
> this could also be useful for debugging during guest destruction (when the
> file descriptor has already been closed) for VMSAs that haven't exited
> with an INVALID exit code.
>
> Just an FYI, I can change this call and the one below to sev_do_cmd() if
> agreed upon.
Works for me. Want to provide a delta patch? I can fixup when applying.
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH 1/5] KVM: SVM: Decrypt SEV VMSA in dump_vmcb() if debugging is enabled
2025-04-10 23:14 ` Sean Christopherson
@ 2025-04-14 16:11 ` Tom Lendacky
2025-04-14 17:20 ` Tom Lendacky
0 siblings, 1 reply; 16+ messages in thread
From: Tom Lendacky @ 2025-04-14 16:11 UTC (permalink / raw)
To: Sean Christopherson
Cc: kvm, linux-kernel, x86, Paolo Bonzini, Borislav Petkov,
Dave Hansen, Ingo Molnar, Thomas Gleixner, Michael Roth
On 4/10/25 18:14, Sean Christopherson wrote:
> On Mon, Mar 24, 2025, Tom Lendacky wrote:
>> On 3/20/25 08:26, Tom Lendacky wrote:
>>> An SEV-ES/SEV-SNP VM save area (VMSA) can be decrypted if the guest
>>> policy allows debugging. Update the dump_vmcb() routine to output
>>> some of the SEV VMSA contents if possible. This can be useful for
>>> debug purposes.
>>>
>>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>>> ---
>>> arch/x86/kvm/svm/sev.c | 98 ++++++++++++++++++++++++++++++++++++++++++
>>> arch/x86/kvm/svm/svm.c | 13 ++++++
>>> arch/x86/kvm/svm/svm.h | 11 +++++
>>> 3 files changed, 122 insertions(+)
>>>
>>> diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
>>> index 661108d65ee7..6e3f5042d9ce 100644
>>> --- a/arch/x86/kvm/svm/sev.c
>>> +++ b/arch/x86/kvm/svm/sev.c
>>
>>> +
>>> + if (sev_snp_guest(vcpu->kvm)) {
>>> + struct sev_data_snp_dbg dbg = {0};
>>> +
>>> + vmsa = snp_alloc_firmware_page(__GFP_ZERO);
>>> + if (!vmsa)
>>> + return NULL;
>>> +
>>> + dbg.gctx_paddr = __psp_pa(sev->snp_context);
>>> + dbg.src_addr = svm->vmcb->control.vmsa_pa;
>>> + dbg.dst_addr = __psp_pa(vmsa);
>>> +
>>> + ret = sev_issue_cmd(vcpu->kvm, SEV_CMD_SNP_DBG_DECRYPT, &dbg, &error);
>>
>> This can also be sev_do_cmd() where the file descriptor isn't checked.
>> Since it isn't really a user initiated call, that might be desirable since
>> this could also be useful for debugging during guest destruction (when the
>> file descriptor has already been closed) for VMSAs that haven't exited
>> with an INVALID exit code.
>>
>> Just an FYI, I can change this call and the one below to sev_do_cmd() if
>> agreed upon.
>
> Works for me. Want to provide a delta patch? I can fixup when applying.
Will do.
Thanks,
Tom
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH 1/5] KVM: SVM: Decrypt SEV VMSA in dump_vmcb() if debugging is enabled
2025-04-14 16:11 ` Tom Lendacky
@ 2025-04-14 17:20 ` Tom Lendacky
0 siblings, 0 replies; 16+ messages in thread
From: Tom Lendacky @ 2025-04-14 17:20 UTC (permalink / raw)
To: Sean Christopherson
Cc: kvm, linux-kernel, x86, Paolo Bonzini, Borislav Petkov,
Dave Hansen, Ingo Molnar, Thomas Gleixner, Michael Roth
On 4/14/25 11:11, Tom Lendacky wrote:
> On 4/10/25 18:14, Sean Christopherson wrote:
>> On Mon, Mar 24, 2025, Tom Lendacky wrote:
>>> On 3/20/25 08:26, Tom Lendacky wrote:
>>>> An SEV-ES/SEV-SNP VM save area (VMSA) can be decrypted if the guest
>>>> policy allows debugging. Update the dump_vmcb() routine to output
>>>> some of the SEV VMSA contents if possible. This can be useful for
>>>> debug purposes.
>>>>
>>>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>>>> ---
>>>> arch/x86/kvm/svm/sev.c | 98 ++++++++++++++++++++++++++++++++++++++++++
>>>> arch/x86/kvm/svm/svm.c | 13 ++++++
>>>> arch/x86/kvm/svm/svm.h | 11 +++++
>>>> 3 files changed, 122 insertions(+)
>>>>
>>>> diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
>>>> index 661108d65ee7..6e3f5042d9ce 100644
>>>> --- a/arch/x86/kvm/svm/sev.c
>>>> +++ b/arch/x86/kvm/svm/sev.c
>>>
>>>> +
>>>> + if (sev_snp_guest(vcpu->kvm)) {
>>>> + struct sev_data_snp_dbg dbg = {0};
>>>> +
>>>> + vmsa = snp_alloc_firmware_page(__GFP_ZERO);
>>>> + if (!vmsa)
>>>> + return NULL;
>>>> +
>>>> + dbg.gctx_paddr = __psp_pa(sev->snp_context);
>>>> + dbg.src_addr = svm->vmcb->control.vmsa_pa;
>>>> + dbg.dst_addr = __psp_pa(vmsa);
>>>> +
>>>> + ret = sev_issue_cmd(vcpu->kvm, SEV_CMD_SNP_DBG_DECRYPT, &dbg, &error);
>>>
>>> This can also be sev_do_cmd() where the file descriptor isn't checked.
>>> Since it isn't really a user initiated call, that might be desirable since
>>> this could also be useful for debugging during guest destruction (when the
>>> file descriptor has already been closed) for VMSAs that haven't exited
>>> with an INVALID exit code.
>>>
>>> Just an FYI, I can change this call and the one below to sev_do_cmd() if
>>> agreed upon.
>>
>> Works for me. Want to provide a delta patch? I can fixup when applying.
>
> Will do.
Here's the diff on top:
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 6e3f5042d9ce..4e9ab172e3f0 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -5020,7 +5020,7 @@ struct vmcb_save_area *sev_decrypt_vmsa(struct kvm_vcpu *vcpu)
dbg.src_addr = svm->vmcb->control.vmsa_pa;
dbg.dst_addr = __psp_pa(vmsa);
- ret = sev_issue_cmd(vcpu->kvm, SEV_CMD_SNP_DBG_DECRYPT, &dbg, &error);
+ ret = sev_do_cmd(SEV_CMD_SNP_DBG_DECRYPT, &dbg, &error);
/*
* Return the target page to a hypervisor page no matter what.
@@ -5052,7 +5052,7 @@ struct vmcb_save_area *sev_decrypt_vmsa(struct kvm_vcpu *vcpu)
dbg.dst_addr = __psp_pa(vmsa);
dbg.len = PAGE_SIZE;
- ret = sev_issue_cmd(vcpu->kvm, SEV_CMD_DBG_DECRYPT, &dbg, &error);
+ ret = sev_do_cmd(SEV_CMD_DBG_DECRYPT, &dbg, &error);
if (ret) {
pr_err("SEV: SEV_CMD_DBG_DECRYPT failed ret=%d, fw_error=%d (0x%x)\n",
ret, error, error);
>
> Thanks,
> Tom
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 2/5] KVM: SVM: Dump guest register state in dump_vmcb()
2025-03-20 13:26 [PATCH 0/5] Provide SEV-ES/SEV-SNP support for decrypting the VMSA Tom Lendacky
2025-03-20 13:26 ` [PATCH 1/5] KVM: SVM: Decrypt SEV VMSA in dump_vmcb() if debugging is enabled Tom Lendacky
@ 2025-03-20 13:26 ` Tom Lendacky
2025-03-20 13:26 ` [PATCH 3/5] KVM: SVM: Add the type of VM for which the VMCB/VMSA is being dumped Tom Lendacky
` (4 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Tom Lendacky @ 2025-03-20 13:26 UTC (permalink / raw)
To: kvm, linux-kernel, x86
Cc: Paolo Bonzini, Sean Christopherson, Borislav Petkov, Dave Hansen,
Ingo Molnar, Thomas Gleixner, Michael Roth
Guest register state can be useful when debugging, include it as part
of dump_vmcb().
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
arch/x86/kvm/svm/svm.c | 53 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 21477871073c..5ed6009bcf69 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -3503,6 +3503,59 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
"excp_from:", save->last_excp_from,
"excp_to:", save->last_excp_to);
+ if (sev_es_guest(vcpu->kvm)) {
+ struct sev_es_save_area *vmsa = (struct sev_es_save_area *)save;
+
+ pr_err("%-15s %016llx\n",
+ "sev_features", vmsa->sev_features);
+
+ pr_err("%-15s %016llx %-13s %016llx\n",
+ "rax:", vmsa->rax, "rbx:", vmsa->rbx);
+ pr_err("%-15s %016llx %-13s %016llx\n",
+ "rcx:", vmsa->rcx, "rdx:", vmsa->rdx);
+ pr_err("%-15s %016llx %-13s %016llx\n",
+ "rsi:", vmsa->rsi, "rdi:", vmsa->rdi);
+ pr_err("%-15s %016llx %-13s %016llx\n",
+ "rbp:", vmsa->rbp, "rsp:", vmsa->rsp);
+ pr_err("%-15s %016llx %-13s %016llx\n",
+ "r8:", vmsa->r8, "r9:", vmsa->r9);
+ pr_err("%-15s %016llx %-13s %016llx\n",
+ "r10:", vmsa->r10, "r11:", vmsa->r11);
+ pr_err("%-15s %016llx %-13s %016llx\n",
+ "r12:", vmsa->r12, "r13:", vmsa->r13);
+ pr_err("%-15s %016llx %-13s %016llx\n",
+ "r14:", vmsa->r14, "r15:", vmsa->r15);
+ pr_err("%-15s %016llx %-13s %016llx\n",
+ "xcr0:", vmsa->xcr0, "xss:", vmsa->xss);
+ } else {
+ pr_err("%-15s %016llx %-13s %016lx\n",
+ "rax:", save->rax, "rbx:",
+ vcpu->arch.regs[VCPU_REGS_RBX]);
+ pr_err("%-15s %016lx %-13s %016lx\n",
+ "rcx:", vcpu->arch.regs[VCPU_REGS_RCX],
+ "rdx:", vcpu->arch.regs[VCPU_REGS_RDX]);
+ pr_err("%-15s %016lx %-13s %016lx\n",
+ "rsi:", vcpu->arch.regs[VCPU_REGS_RSI],
+ "rdi:", vcpu->arch.regs[VCPU_REGS_RDI]);
+ pr_err("%-15s %016lx %-13s %016llx\n",
+ "rbp:", vcpu->arch.regs[VCPU_REGS_RBP],
+ "rsp:", save->rsp);
+#ifdef CONFIG_X86_64
+ pr_err("%-15s %016lx %-13s %016lx\n",
+ "r8:", vcpu->arch.regs[VCPU_REGS_R8],
+ "r9:", vcpu->arch.regs[VCPU_REGS_R9]);
+ pr_err("%-15s %016lx %-13s %016lx\n",
+ "r10:", vcpu->arch.regs[VCPU_REGS_R10],
+ "r11:", vcpu->arch.regs[VCPU_REGS_R11]);
+ pr_err("%-15s %016lx %-13s %016lx\n",
+ "r12:", vcpu->arch.regs[VCPU_REGS_R12],
+ "r13:", vcpu->arch.regs[VCPU_REGS_R13]);
+ pr_err("%-15s %016lx %-13s %016lx\n",
+ "r14:", vcpu->arch.regs[VCPU_REGS_R14],
+ "r15:", vcpu->arch.regs[VCPU_REGS_R15]);
+#endif
+ }
+
no_vmsa:
if (sev_es_guest(vcpu->kvm))
sev_free_decrypted_vmsa(vcpu, save);
--
2.46.2
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH 3/5] KVM: SVM: Add the type of VM for which the VMCB/VMSA is being dumped
2025-03-20 13:26 [PATCH 0/5] Provide SEV-ES/SEV-SNP support for decrypting the VMSA Tom Lendacky
2025-03-20 13:26 ` [PATCH 1/5] KVM: SVM: Decrypt SEV VMSA in dump_vmcb() if debugging is enabled Tom Lendacky
2025-03-20 13:26 ` [PATCH 2/5] KVM: SVM: Dump guest register state in dump_vmcb() Tom Lendacky
@ 2025-03-20 13:26 ` Tom Lendacky
2025-03-20 13:26 ` [PATCH 4/5] KVM: SVM: Include the vCPU ID when dumping a VMCB Tom Lendacky
` (3 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Tom Lendacky @ 2025-03-20 13:26 UTC (permalink / raw)
To: kvm, linux-kernel, x86
Cc: Paolo Bonzini, Sean Christopherson, Borislav Petkov, Dave Hansen,
Ingo Molnar, Thomas Gleixner, Michael Roth
Add the type of VM (SVM, SEV, SEV-ES, or SEV-SNP) being dumped to the
dump_vmcb() function.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
arch/x86/kvm/svm/svm.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 5ed6009bcf69..73b5ab58d2b8 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -3378,14 +3378,19 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
struct vmcb_control_area *control = &svm->vmcb->control;
struct vmcb_save_area *save = &svm->vmcb->save;
struct vmcb_save_area *save01 = &svm->vmcb01.ptr->save;
+ char *vm_type;
if (!dump_invalid_vmcb) {
pr_warn_ratelimited("set kvm_amd.dump_invalid_vmcb=1 to dump internal KVM state.\n");
return;
}
- pr_err("VMCB %p, last attempted VMRUN on CPU %d\n",
- svm->current_vmcb->ptr, vcpu->arch.last_vmentry_cpu);
+ vm_type = sev_snp_guest(vcpu->kvm) ? "SEV-SNP" :
+ sev_es_guest(vcpu->kvm) ? "SEV-ES" :
+ sev_guest(vcpu->kvm) ? "SEV" : "SVM";
+
+ pr_err("%s VMCB %p, last attempted VMRUN on CPU %d\n",
+ vm_type, svm->current_vmcb->ptr, vcpu->arch.last_vmentry_cpu);
pr_err("VMCB Control Area:\n");
pr_err("%-20s%04x\n", "cr_read:", control->intercepts[INTERCEPT_CR] & 0xffff);
pr_err("%-20s%04x\n", "cr_write:", control->intercepts[INTERCEPT_CR] >> 16);
--
2.46.2
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH 4/5] KVM: SVM: Include the vCPU ID when dumping a VMCB
2025-03-20 13:26 [PATCH 0/5] Provide SEV-ES/SEV-SNP support for decrypting the VMSA Tom Lendacky
` (2 preceding siblings ...)
2025-03-20 13:26 ` [PATCH 3/5] KVM: SVM: Add the type of VM for which the VMCB/VMSA is being dumped Tom Lendacky
@ 2025-03-20 13:26 ` Tom Lendacky
2025-03-20 13:26 ` [PATCH 5/5] KVM: SVM: Add a mutex to dump_vmcb() to prevent concurrent output Tom Lendacky
` (2 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Tom Lendacky @ 2025-03-20 13:26 UTC (permalink / raw)
To: kvm, linux-kernel, x86
Cc: Paolo Bonzini, Sean Christopherson, Borislav Petkov, Dave Hansen,
Ingo Molnar, Thomas Gleixner, Michael Roth
Provide the vCPU ID of the VMCB in dump_vmcb().
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
arch/x86/kvm/svm/svm.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 73b5ab58d2b8..99f2d9de6ce2 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -3389,8 +3389,8 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
sev_es_guest(vcpu->kvm) ? "SEV-ES" :
sev_guest(vcpu->kvm) ? "SEV" : "SVM";
- pr_err("%s VMCB %p, last attempted VMRUN on CPU %d\n",
- vm_type, svm->current_vmcb->ptr, vcpu->arch.last_vmentry_cpu);
+ pr_err("%s vCPU%u VMCB %p, last attempted VMRUN on CPU %d\n",
+ vm_type, vcpu->vcpu_id, svm->current_vmcb->ptr, vcpu->arch.last_vmentry_cpu);
pr_err("VMCB Control Area:\n");
pr_err("%-20s%04x\n", "cr_read:", control->intercepts[INTERCEPT_CR] & 0xffff);
pr_err("%-20s%04x\n", "cr_write:", control->intercepts[INTERCEPT_CR] >> 16);
--
2.46.2
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH 5/5] KVM: SVM: Add a mutex to dump_vmcb() to prevent concurrent output
2025-03-20 13:26 [PATCH 0/5] Provide SEV-ES/SEV-SNP support for decrypting the VMSA Tom Lendacky
` (3 preceding siblings ...)
2025-03-20 13:26 ` [PATCH 4/5] KVM: SVM: Include the vCPU ID when dumping a VMCB Tom Lendacky
@ 2025-03-20 13:26 ` Tom Lendacky
2025-03-20 14:17 ` [PATCH 0/5] Provide SEV-ES/SEV-SNP support for decrypting the VMSA Borislav Petkov
2025-04-25 23:23 ` Sean Christopherson
6 siblings, 0 replies; 16+ messages in thread
From: Tom Lendacky @ 2025-03-20 13:26 UTC (permalink / raw)
To: kvm, linux-kernel, x86
Cc: Paolo Bonzini, Sean Christopherson, Borislav Petkov, Dave Hansen,
Ingo Molnar, Thomas Gleixner, Michael Roth
If multiple VMRUN instructions fail, resulting in calls to dump_vmcb(),
the output can become interleaved and it is impossible to identify which
line of output belongs to which VMCB. Add a mutex to dump_vmcb() so that
the output is serialized.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
arch/x86/kvm/svm/svm.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 99f2d9de6ce2..5b62ac06a19e 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -29,6 +29,7 @@
#include <linux/cc_platform.h>
#include <linux/smp.h>
#include <linux/string_choices.h>
+#include <linux/mutex.h>
#include <asm/apic.h>
#include <asm/perf_event.h>
@@ -249,6 +250,8 @@ static unsigned long iopm_base;
DEFINE_PER_CPU(struct svm_cpu_data, svm_data);
+static DEFINE_MUTEX(vmcb_dump_mutex);
+
/*
* Only MSR_TSC_AUX is switched via the user return hook. EFER is switched via
* the VMCB, and the SYSCALL/SYSENTER MSRs are handled by VMLOAD/VMSAVE.
@@ -3385,6 +3388,8 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
return;
}
+ guard(mutex)(&vmcb_dump_mutex);
+
vm_type = sev_snp_guest(vcpu->kvm) ? "SEV-SNP" :
sev_es_guest(vcpu->kvm) ? "SEV-ES" :
sev_guest(vcpu->kvm) ? "SEV" : "SVM";
--
2.46.2
^ permalink raw reply related [flat|nested] 16+ messages in thread* Re: [PATCH 0/5] Provide SEV-ES/SEV-SNP support for decrypting the VMSA
2025-03-20 13:26 [PATCH 0/5] Provide SEV-ES/SEV-SNP support for decrypting the VMSA Tom Lendacky
` (4 preceding siblings ...)
2025-03-20 13:26 ` [PATCH 5/5] KVM: SVM: Add a mutex to dump_vmcb() to prevent concurrent output Tom Lendacky
@ 2025-03-20 14:17 ` Borislav Petkov
2025-03-21 18:43 ` Kim Phillips
2025-04-25 23:23 ` Sean Christopherson
6 siblings, 1 reply; 16+ messages in thread
From: Borislav Petkov @ 2025-03-20 14:17 UTC (permalink / raw)
To: Tom Lendacky
Cc: kvm, linux-kernel, x86, Paolo Bonzini, Sean Christopherson,
Dave Hansen, Ingo Molnar, Thomas Gleixner, Michael Roth
On Thu, Mar 20, 2025 at 08:26:48AM -0500, Tom Lendacky wrote:
> This series adds support for decrypting an SEV-ES/SEV-SNP VMSA in
> dump_vmcb() when the guest policy allows debugging.
I would really really love to have that so
Acked-by: Borislav Petkov (AMD) <bp@alien8.de>
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH 0/5] Provide SEV-ES/SEV-SNP support for decrypting the VMSA
2025-03-20 14:17 ` [PATCH 0/5] Provide SEV-ES/SEV-SNP support for decrypting the VMSA Borislav Petkov
@ 2025-03-21 18:43 ` Kim Phillips
0 siblings, 0 replies; 16+ messages in thread
From: Kim Phillips @ 2025-03-21 18:43 UTC (permalink / raw)
To: Borislav Petkov, Tom Lendacky
Cc: kvm, linux-kernel, x86, Paolo Bonzini, Sean Christopherson,
Dave Hansen, Ingo Molnar, Thomas Gleixner, Michael Roth
On 3/20/25 9:17 AM, Borislav Petkov wrote:
> On Thu, Mar 20, 2025 at 08:26:48AM -0500, Tom Lendacky wrote:
>> This series adds support for decrypting an SEV-ES/SEV-SNP VMSA in
>> dump_vmcb() when the guest policy allows debugging.
>
> I would really really love to have that so
>
> Acked-by: Borislav Petkov (AMD) <bp@alien8.de>
Me too.
Tested-by: Kim Phillips <kim.phillips@amd.com>
Thanks,
Kim
kvm_amd: SEV-SNP vCPU1 VMCB 00000000759a48a5, last attempted VMRUN on CPU 7
kvm_amd: VMCB Control Area:
kvm_amd: cr_read: 0000
kvm_amd: cr_write: 0000
kvm_amd: dr_read: 0080
kvm_amd: dr_write: 0080
kvm_amd: exceptions: 00060002
kvm_amd: intercepts: bccc8007 0111ce43
kvm_amd: pause filter count: 3000
kvm_amd: pause filter threshold:128
kvm_amd: iopm_base_pa: 0000000148e44000
kvm_amd: msrpm_base_pa: 0000000276e3e000
kvm_amd: tsc_offset: ffff6b01ea8aa6f6
kvm_amd: asid: 3
kvm_amd: tlb_ctl: 0
kvm_amd: int_ctl: 07000200
kvm_amd: int_vector: 00000000
kvm_amd: int_state: 00000000
kvm_amd: exit_code: ffffffff
kvm_amd: exit_info1: 0000000000000000
kvm_amd: exit_info2: 0000000000000000
kvm_amd: exit_int_info: 00000000
kvm_amd: exit_int_info_err: 00000000
kvm_amd: nested_ctl: 7
kvm_amd: nested_cr3: 000000022fc06000
kvm_amd: avic_vapic_bar: 0000000000000000
kvm_amd: ghcb: 00000000bfeda000
kvm_amd: event_inj: 00000000
kvm_amd: event_inj_err: 00000000
kvm_amd: virt_ext: 3
kvm_amd: next_rip: 0000000000000000
kvm_amd: avic_backing_page: 0000000000000000
kvm_amd: avic_logical_id: 0000000000000000
kvm_amd: avic_physical_id: 0000000000000000
kvm_amd: vmsa_pa: 00000005d35c0000
kvm_amd: allowed_sev_features:8000000000000001
kvm_amd: guest_sev_features: 0000000000000081
kvm_amd: VMCB State Save Area:
kvm_amd: es: s: 0000 a: 0092 l: 0000ffff b: 0000000000000000
kvm_amd: cs: s: 9900 a: 009a l: 0000ffff b: 0000000000099000
kvm_amd: ss: s: 0000 a: 0092 l: 0000ffff b: 0000000000000000
kvm_amd: ds: s: 0000 a: 0092 l: 0000ffff b: 0000000000000000
kvm_amd: fs: s: 0000 a: 0092 l: 0000ffff b: 0000000000000000
kvm_amd: gs: s: 0000 a: 0092 l: 0000ffff b: 0000000000000000
kvm_amd: gdtr: s: 0000 a: 0000 l: 0000ffff b: 0000000000000000
kvm_amd: ldtr: s: 0000 a: 0082 l: 0000ffff b: 0000000000000000
kvm_amd: idtr: s: 0000 a: 0000 l: 0000ffff b: 0000000000000000
kvm_amd: tr: s: 0000 a: 0083 l: 0000ffff b: 0000000000000000
kvm_amd: vmpl: 0 cpl: 0 efer: 0000000000001000
kvm_amd: cr0: 0000000060000010 cr2: 0000000000000000
kvm_amd: cr3: 0000000000000000 cr4: 0000000000000040
kvm_amd: dr6: 00000000ffff0ff0 dr7: 0000000000000400
kvm_amd: rip: 0000000000000050 rflags: 0000000000000002
kvm_amd: rsp: 0000000000000000 rax: 0000000000000000
kvm_amd: star: 0000000000000000 lstar: 0000000000000000
kvm_amd: cstar: 0000000000000000 sfmask: 0000000000000000
kvm_amd: kernel_gs_base: 0000000000000000 sysenter_cs: 0000000000000000
kvm_amd: sysenter_esp: 0000000000000000 sysenter_eip: 0000000000000000
kvm_amd: gpat: 0007040600070406 dbgctl: 0000000000000000
kvm_amd: br_from: 0000000000000000 br_to: 0000000000000000
kvm_amd: excp_from: 0000000000000000 excp_to: 0000000000000000
kvm_amd: sev_features 0000000000000081
kvm_amd: rax: 0000000000000000 rbx: 0000000000000000
kvm_amd: rcx: 0000000000000000 rdx: 0000000000000000
kvm_amd: rsi: 0000000000000000 rdi: 0000000000000000
kvm_amd: rbp: 0000000000000000 rsp: 0000000000000000
kvm_amd: r8: 0000000000000000 r9: 0000000000000000
kvm_amd: r10: 0000000000000000 r11: 0000000000000000
kvm_amd: r12: 0000000000000000 r13: 0000000000000000
kvm_amd: r14: 0000000000000000 r15: 0000000000000000
kvm_amd: xcr0: 0000000000000001 xss: 0000000000000000
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 0/5] Provide SEV-ES/SEV-SNP support for decrypting the VMSA
2025-03-20 13:26 [PATCH 0/5] Provide SEV-ES/SEV-SNP support for decrypting the VMSA Tom Lendacky
` (5 preceding siblings ...)
2025-03-20 14:17 ` [PATCH 0/5] Provide SEV-ES/SEV-SNP support for decrypting the VMSA Borislav Petkov
@ 2025-04-25 23:23 ` Sean Christopherson
2025-04-26 14:53 ` Tom Lendacky
6 siblings, 1 reply; 16+ messages in thread
From: Sean Christopherson @ 2025-04-25 23:23 UTC (permalink / raw)
To: Sean Christopherson, kvm, linux-kernel, x86, Tom Lendacky
Cc: Paolo Bonzini, Borislav Petkov, Dave Hansen, Ingo Molnar,
Thomas Gleixner, Michael Roth
On Thu, 20 Mar 2025 08:26:48 -0500, Tom Lendacky wrote:
> This series adds support for decrypting an SEV-ES/SEV-SNP VMSA in
> dump_vmcb() when the guest policy allows debugging.
>
> It also contains some updates to dump_vmcb() to dump additional guest
> register state, print the type of guest, print the vCPU id, and adds a
> mutex to prevent interleaving of the dump_vmcb() messages when multiple
> vCPU threads call dump_vmcb(). These last patches can be dropped if not
> desired.
>
> [...]
Applied to kvm-x86 svm, with Tom's fixups. Please double check I didn't botch
those, the last few days have been a never ending comedy of errors on my end.
Thanks!
[1/5] KVM: SVM: Decrypt SEV VMSA in dump_vmcb() if debugging is enabled
https://github.com/kvm-x86/linux/commit/962e2b6152ef
[2/5] KVM: SVM: Dump guest register state in dump_vmcb()
https://github.com/kvm-x86/linux/commit/22f5c2003a18
[3/5] KVM: SVM: Add the type of VM for which the VMCB/VMSA is being dumped
https://github.com/kvm-x86/linux/commit/db2645096105
[4/5] KVM: SVM: Include the vCPU ID when dumping a VMCB
https://github.com/kvm-x86/linux/commit/0e6b677de730
[5/5] KVM: SVM: Add a mutex to dump_vmcb() to prevent concurrent output
https://github.com/kvm-x86/linux/commit/468c27ae0215
--
https://github.com/kvm-x86/linux/tree/next
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH 0/5] Provide SEV-ES/SEV-SNP support for decrypting the VMSA
2025-04-25 23:23 ` Sean Christopherson
@ 2025-04-26 14:53 ` Tom Lendacky
0 siblings, 0 replies; 16+ messages in thread
From: Tom Lendacky @ 2025-04-26 14:53 UTC (permalink / raw)
To: Sean Christopherson, kvm, linux-kernel, x86
Cc: Paolo Bonzini, Borislav Petkov, Dave Hansen, Ingo Molnar,
Thomas Gleixner, Michael Roth
On 4/25/25 18:23, Sean Christopherson wrote:
> On Thu, 20 Mar 2025 08:26:48 -0500, Tom Lendacky wrote:
>> This series adds support for decrypting an SEV-ES/SEV-SNP VMSA in
>> dump_vmcb() when the guest policy allows debugging.
>>
>> It also contains some updates to dump_vmcb() to dump additional guest
>> register state, print the type of guest, print the vCPU id, and adds a
>> mutex to prevent interleaving of the dump_vmcb() messages when multiple
>> vCPU threads call dump_vmcb(). These last patches can be dropped if not
>> desired.
>>
>> [...]
>
> Applied to kvm-x86 svm, with Tom's fixups. Please double check I didn't botch
> those, the last few days have been a never ending comedy of errors on my end.
Everything looks good.
Thanks!
Tom
>
> Thanks!
>
> [1/5] KVM: SVM: Decrypt SEV VMSA in dump_vmcb() if debugging is enabled
> https://github.com/kvm-x86/linux/commit/962e2b6152ef
> [2/5] KVM: SVM: Dump guest register state in dump_vmcb()
> https://github.com/kvm-x86/linux/commit/22f5c2003a18
> [3/5] KVM: SVM: Add the type of VM for which the VMCB/VMSA is being dumped
> https://github.com/kvm-x86/linux/commit/db2645096105
> [4/5] KVM: SVM: Include the vCPU ID when dumping a VMCB
> https://github.com/kvm-x86/linux/commit/0e6b677de730
> [5/5] KVM: SVM: Add a mutex to dump_vmcb() to prevent concurrent output
> https://github.com/kvm-x86/linux/commit/468c27ae0215
>
> --
> https://github.com/kvm-x86/linux/tree/next
^ permalink raw reply [flat|nested] 16+ messages in thread