diff mbox series

[v2] KVM: SVM: Convert plain error code numbers to defines

Message ID 20241202214032.350109-1-huibo.wang@amd.com (mailing list archive)
State New
Headers show
Series [v2] KVM: SVM: Convert plain error code numbers to defines | expand

Commit Message

Melody (Huibo) Wang Dec. 2, 2024, 9:40 p.m. UTC
Convert VMGEXIT SW_EXITINFO1 codes from plain numbers to proper defines.

No functionality changed.

Signed-off-by: Melody Wang <huibo.wang@amd.com>
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
Reviewed-by: Pavan Kumar Paluri <papaluri@amd.com>
---
 arch/x86/include/asm/sev-common.h |  8 ++++++++
 arch/x86/kvm/svm/sev.c            | 12 ++++++------
 arch/x86/kvm/svm/svm.c            |  2 +-
 3 files changed, 15 insertions(+), 7 deletions(-)

Comments

Sean Christopherson Dec. 3, 2024, 12:11 a.m. UTC | #1
On Mon, Dec 02, 2024, Melody Wang wrote:
> Convert VMGEXIT SW_EXITINFO1 codes from plain numbers to proper defines.
> 
> No functionality changed.
> 
> Signed-off-by: Melody Wang <huibo.wang@amd.com>
> Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
> Reviewed-by: Pavan Kumar Paluri <papaluri@amd.com>
> ---
>  arch/x86/include/asm/sev-common.h |  8 ++++++++
>  arch/x86/kvm/svm/sev.c            | 12 ++++++------
>  arch/x86/kvm/svm/svm.c            |  2 +-
>  3 files changed, 15 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/x86/include/asm/sev-common.h b/arch/x86/include/asm/sev-common.h
> index 98726c2b04f8..01d4744e880a 100644
> --- a/arch/x86/include/asm/sev-common.h
> +++ b/arch/x86/include/asm/sev-common.h
> @@ -209,6 +209,14 @@ struct snp_psc_desc {
>  
>  #define GHCB_RESP_CODE(v)		((v) & GHCB_MSR_INFO_MASK)
>  
> +/*
> + * Error codes of the GHCB SW_EXITINFO1 related to GHCB input that can be
> + * communicated back to the guest
> + */
> +#define GHCB_HV_RESP_SUCCESS		0
> +#define GHCB_HV_RESP_ISSUE_EXCEPTION	1
> +#define GHCB_HV_RESP_MALFORMED_INPUT	2
> +
>  /*
>   * Error codes related to GHCB input that can be communicated back to the guest
>   * by setting the lower 32-bits of the GHCB SW_EXITINFO1 field to 2.
> diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
> index 72674b8825c4..e7db7a5703b7 100644
> --- a/arch/x86/kvm/svm/sev.c
> +++ b/arch/x86/kvm/svm/sev.c
> @@ -3433,7 +3433,7 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
>  		dump_ghcb(svm);
>  	}
>  
> -	ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 2);
> +	ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, GHCB_HV_RESP_MALFORMED_INPUT);
>  	ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, reason);

Hmm, IMO, open coding literals in multiple locations is a symptom of not providing
helpers.  From a certain (slightly warped) perspective, setting exit_info_1 vs.
exit_info_2 is just weird version of an open coded literal.

Rather than provide macros (or probably in addition to), what if we provide helpers
to set the error code and the payload?  That would also ensure KVM sets both '1'
and '2' fields.  E.g. in sev_handle_vmgexit()'s SVM_VMGEXIT_AP_JUMP_TABLE path,
setting '2' but not '1' is mildly confusing at first glance, because it takes some
staring to understand that's it's NOT a failure path.  Ditto for
sev_vcpu_deliver_sipi_vector().

And IMO, not having to parse input parameters to understand success vs. failure
usually makes code easier to read.

E.g. something like this?  Definitely feel free to suggest better names.

static inline void svm_vmgexit_set_return_code(struct vcpu_svm *svm,
					       u64 response, u64 data)
{
	ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, response);
	ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, data);
}

static inline void svm_vmgexit_inject_exception(struct vcpu_svm *svm, u8 vector)
{
	u64 data = SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_EXEPT | vector;

	svm_vmgexit_set_return_code(svm, GHCB_HV_RESP_ISSUE_EXCEPTION, data);
}

static inline void svm_vmgexit_bad_input(struct vcpu_svm *svm, u64 suberror)
{
	svm_vmgexit_set_return_code(svm, GHCB_HV_RESP_MALFORMED_INPUT, suberror);
}

static inline void svm_vmgexit_success(struct vcpu_svm *svm, u64 data)
{
	svm_vmgexit_set_return_code(svm, GHCB_HV_RESP_SUCCESS, data);
}
Melody (Huibo) Wang Dec. 3, 2024, 9:46 p.m. UTC | #2
Hi Sean,

On 12/2/2024 4:11 PM, Sean Christopherson wrote:

> 
> E.g. something like this?  Definitely feel free to suggest better names.
> 
> static inline void svm_vmgexit_set_return_code(struct vcpu_svm *svm,
> 					       u64 response, u64 data)
> {
> 	ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, response);
> 	ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, data);
> }
> 
If I make this function more generic where the exit info is set for both KVM and the guest, then maybe I can write something like this:

void ghcb_set_exit_info(struct ghcb *ghcb,
                      u64 info1, u64 info2)
{
	ghcb_set_sw_exit_info_1(ghcb, info1);
	ghcb_set_sw_exit_info_2(ghcb, info2);

}
This way we can address every possible case that sets the exit info - not only KVM. 

And I am not sure about the wrappers for each specific case because we will have too many, too specific small functions, but if you want them I can add them.

Thanks,
Melody
Sean Christopherson Dec. 4, 2024, 12:50 a.m. UTC | #3
On Tue, Dec 03, 2024, Melody (Huibo) Wang wrote:
> Hi Sean,
> 
> On 12/2/2024 4:11 PM, Sean Christopherson wrote:
> 
> > 
> > E.g. something like this?  Definitely feel free to suggest better names.
> > 
> > static inline void svm_vmgexit_set_return_code(struct vcpu_svm *svm,
> > 					       u64 response, u64 data)
> > {
> > 	ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, response);
> > 	ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, data);
> > }
> > 
> If I make this function more generic where the exit info is set for both KVM
> and the guest, then maybe I can write something like this:

I like the idea, but I actually think it's better to keep the guest and host code
separate in the case, because the guest code should actually set a triple, e.g.

static __always_inline void sev_es_vmgexit_set_exit_info(struct ghcb *ghcb,
							 u64 exit_code,
							 u64 exit_info_1,
							 u64 exit_info_2)
{
	ghcb_set_sw_exit_code(ghcb, exit_code);
	ghcb_set_sw_exit_info_1(ghcb, exit_info_1);
	ghcb_set_sw_exit_info_2(ghcb, exit_info_2);
}

I'm not totally opposed to sharing code, but I think it will be counter-productive
in this specific case.  E.g. the guest version needs to be __always_inline so that
it can be used in noinstr code.

> void ghcb_set_exit_info(struct ghcb *ghcb,
>                       u64 info1, u64 info2)
> {
> 	ghcb_set_sw_exit_info_1(ghcb, info1);
> 	ghcb_set_sw_exit_info_2(ghcb, info2);
> 
> }
> This way we can address every possible case that sets the exit info - not only KVM. 
> 
> And I am not sure about the wrappers for each specific case because we will
> have too many, too specific small functions, but if you want them I can add
> them.

I count three.  We have far, far more wrappers VMX's is_exception_n(), and IMO
those wrappers make the code significantly more readable.
diff mbox series

Patch

diff --git a/arch/x86/include/asm/sev-common.h b/arch/x86/include/asm/sev-common.h
index 98726c2b04f8..01d4744e880a 100644
--- a/arch/x86/include/asm/sev-common.h
+++ b/arch/x86/include/asm/sev-common.h
@@ -209,6 +209,14 @@  struct snp_psc_desc {
 
 #define GHCB_RESP_CODE(v)		((v) & GHCB_MSR_INFO_MASK)
 
+/*
+ * Error codes of the GHCB SW_EXITINFO1 related to GHCB input that can be
+ * communicated back to the guest
+ */
+#define GHCB_HV_RESP_SUCCESS		0
+#define GHCB_HV_RESP_ISSUE_EXCEPTION	1
+#define GHCB_HV_RESP_MALFORMED_INPUT	2
+
 /*
  * Error codes related to GHCB input that can be communicated back to the guest
  * by setting the lower 32-bits of the GHCB SW_EXITINFO1 field to 2.
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 72674b8825c4..e7db7a5703b7 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -3433,7 +3433,7 @@  static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
 		dump_ghcb(svm);
 	}
 
-	ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 2);
+	ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, GHCB_HV_RESP_MALFORMED_INPUT);
 	ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, reason);
 
 	/* Resume the guest to "return" the error code. */
@@ -3577,7 +3577,7 @@  static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
 	return 0;
 
 e_scratch:
-	ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 2);
+	ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, GHCB_HV_RESP_MALFORMED_INPUT);
 	ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, GHCB_ERR_INVALID_SCRATCH_AREA);
 
 	return 1;
@@ -4124,7 +4124,7 @@  static int snp_handle_ext_guest_req(struct vcpu_svm *svm, gpa_t req_gpa, gpa_t r
 	return snp_handle_guest_req(svm, req_gpa, resp_gpa);
 
 request_invalid:
-	ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 2);
+	ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, GHCB_HV_RESP_MALFORMED_INPUT);
 	ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, GHCB_ERR_INVALID_INPUT);
 	return 1; /* resume guest */
 }
@@ -4317,7 +4317,7 @@  int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
 	if (ret)
 		return ret;
 
-	ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 0);
+	ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, GHCB_HV_RESP_SUCCESS);
 	ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, 0);
 
 	exit_code = kvm_ghcb_get_sw_exit_code(control);
@@ -4367,7 +4367,7 @@  int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
 		default:
 			pr_err("svm: vmgexit: unsupported AP jump table request - exit_info_1=%#llx\n",
 			       control->exit_info_1);
-			ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 2);
+			ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, GHCB_HV_RESP_MALFORMED_INPUT);
 			ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, GHCB_ERR_INVALID_INPUT);
 		}
 
@@ -4397,7 +4397,7 @@  int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
 	case SVM_VMGEXIT_AP_CREATION:
 		ret = sev_snp_ap_creation(svm);
 		if (ret) {
-			ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 2);
+			ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, GHCB_HV_RESP_MALFORMED_INPUT);
 			ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, GHCB_ERR_INVALID_INPUT);
 		}
 
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index dd15cc635655..58bce5f1ab0c 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -2977,7 +2977,7 @@  static int svm_complete_emulated_msr(struct kvm_vcpu *vcpu, int err)
 	if (!err || !sev_es_guest(vcpu->kvm) || WARN_ON_ONCE(!svm->sev_es.ghcb))
 		return kvm_complete_insn_gp(vcpu, err);
 
-	ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 1);
+	ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, GHCB_HV_RESP_ISSUE_EXCEPTION);
 	ghcb_set_sw_exit_info_2(svm->sev_es.ghcb,
 				X86_TRAP_GP |
 				SVM_EVTINJ_TYPE_EXEPT |