KVM: SVM: Make VMGEXIT GHCB exit codes more readable
v5 cover KVM: SVM: Make VMGEXIT GHCB exit codes more readable
This patchset includes two patches to make VMGEXIT GHCB exit codes returned by the hypervisor more readable. One patch coverts plain error code numbers to defines, the other one adds helpers to set the error code.
No functionality changed.
Thanks,
Melody
Changelog:
Changes since v4:
* Add explanation comment about svm_vmgexit_no_action() is corresponding to SW_EXITINFO1.
* Add explanation comment about svm_vmgexit_no_action() when the request failed due to a firmware error.
Changes since v3:
* Document the weirdness with PSC's SW_EXITINFO1.
* Add svm_vmgexit_no_action() helper along with svm_vmgexit_success() to clarify meaning.
* Change GHCB_HV_RESP_SUCCESS to GHCB_HV_RESP_NO_ACTION to avoid the confusion.
Changes since v2:
* Add one patch for providing helpers to set the error code when converting VMGEXIT SW_EXITINFO1 and SW_EXITINFO2 codes from plain numbers to proper defines.
* Add comments for better code readability.
Changes since v1: Rebase with the latest KVM next.
Melody Wang (2):
KVM: SVM: Convert plain error code numbers to defines
KVM: SVM: Provide helpers to set the error code
arch/x86/include/asm/sev-common.h | 8 +++++++ arch/x86/kvm/svm/sev.c | 39 +++++++++++++++++-------------- arch/x86/kvm/svm/svm.c | 6 +---- arch/x86/kvm/svm/svm.h | 29 +++++++++++++++++++++++ 4 files changed, 59 insertions(+), 23 deletions(-)
Signature · 1 line
2.34.1
PATCH v5 1/2 KVM: SVM: Convert plain error code numbers to defines
Convert VMGEXIT SW_EXITINFO1 codes from plain numbers to proper defines.
No functionality changed.
--- 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(-)
arch/x86/include/asm/sev-common.h +8 -0
@@ -211,6 +211,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_NO_ACTION 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.
arch/x86/kvm/svm/sev.c +6 -6
@@ -3430,7 +3430,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. */
@@ -3574,7 +3574,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 ;
@@ -4135,7 +4135,7 @@ static int snp_handle_ext_guest_req(struct vcpu_svm *svm, gpa_t req_gpa, gpa_t rreturn 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 */ }
@@ -4328,7 +4328,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_NO_ACTION );ghcb_set_sw_exit_info_2 (svm->sev_es.ghcb,0 ); exit_code =kvm_ghcb_get_sw_exit_code (control);
@@ -4378,7 +4378,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 ); }
@@ -4408,7 +4408,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 ); }
arch/x86/kvm/svm/svm.c +1 -1
@@ -2973,7 +2973,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 |
Signature · 1 line
2.34.1
Sean Christopherson
maintainerRe: [PATCH v5 1/2] KVM: SVM: Convert plain error code numbers to defines
Quoted 18 lines · Melody Wang
Convert VMGEXIT
SW_EXITINFO1codes from plain numbers to proper defines.No functionality changed.
Signed-off-by Melody Wang <[email protected]>Reviewed-by Tom Lendacky <[email protected]>Reviewed-by Pavan Kumar Paluri <[email protected]>--- 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(-)arch/x86/include/asm/sev-common.h +0
-0
arch/x86/include/asm/sev-common.h struct snp_psc_desc { · line 215
Quoted 5 lines
arch/x86/include/asm/sev-common.h +2
-0@@ -211,6 +211,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
The use of "Error codes" is confusing due to a psuedo-conflict with the below comment for the "Error codes" for malformed input.
On that topic, the comment for _those_ error codes is a bad example, and shouldn't be used as the basis for copy+paste. Most notably, it doesn't explicitly state that the values are *defined* by the GHCB.
arch/x86/include/asm/sev-common.h struct snp_psc_desc { · line 224
Quoted 9 lines
arch/x86/include/asm/sev-common.h +6
-0+* communicated back to the guest +*/ +#define GHCB_HV_RESP_NO_ACTION 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.
Now that GHCB_HV_RESP_MALFORMED_INPUT is properly defined, this comment can refer to "malformed input (see above)" instead of open coding '2'.
PATCH v5 2/2 KVM: SVM: Provide helpers to set the error code
In reply to Melody WangProvide helpers to set the error code when converting VMGEXIT SW_EXITINFO1 and SW_EXITINFO2 codes from plain numbers to proper defines. Add comments for better code readability.
No functionality changed.
--- arch/x86/kvm/svm/sev.c | 39 +++++++++++++++++++++------------------ arch/x86/kvm/svm/svm.c | 6 +----- arch/x86/kvm/svm/svm.h | 29 +++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 23 deletions(-)
arch/x86/kvm/svm/sev.c +21 -18
@@ -3430,8 +3430,7 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)dump_ghcb (svm); } -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); +svm_vmgexit_bad_input (svm, reason);/* Resume the guest to "return" the error code. */ return 1 ;
@@ -3574,8 +3573,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,GHCB_HV_RESP_MALFORMED_INPUT ); -ghcb_set_sw_exit_info_2 (svm->sev_es.ghcb,GHCB_ERR_INVALID_SCRATCH_AREA ); +svm_vmgexit_bad_input (svm,GHCB_ERR_INVALID_SCRATCH_AREA );return 1 ; }
@@ -3675,8 +3673,13 @@ static void snp_complete_psc(struct vcpu_svm *svm, u64 psc_ret) svm->sev_es.psc_inflight =0 ; svm->sev_es.psc_idx =0 ; svm->sev_es.psc_2m = false; -ghcb_set_sw_exit_info_2 (svm->sev_es.ghcb, psc_ret); -} + +/* +* A value of zero in SW_EXITINFO1 does not guarantee that all operations have +* completed or completed successfully. PSC requests always get a "no action" +* response in SW_EXITINFO1, with a PSC-specific return code in SW_EXITINFO2. +*/ +svm_vmgexit_no_action (svm, psc_ret); }static void __snp_complete_one_psc (struct vcpu_svm *svm) {
@@ -4079,7 +4082,10 @@ static int snp_handle_guest_req(struct vcpu_svm *svm, gpa_t req_gpa, gpa_t resp_ goto out_unlock; } -ghcb_set_sw_exit_info_2 (svm->sev_es.ghcb,SNP_GUEST_ERR (0 , fw_err)); +/* +* No action is requested from Hypervisor while there is a firmware error +*/ +svm_vmgexit_no_action (svm,SNP_GUEST_ERR (0 , fw_err)); ret =1 ;/* resume guest */
@@ -4135,8 +4141,7 @@ static int snp_handle_ext_guest_req(struct vcpu_svm *svm, gpa_t req_gpa, gpa_t rreturn snp_handle_guest_req (svm, req_gpa, resp_gpa); request_invalid: -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 ); +svm_vmgexit_bad_input (svm,GHCB_ERR_INVALID_INPUT );return 1 ;/* resume guest */ }
@@ -4328,8 +4333,7 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)if (ret)return ret; -ghcb_set_sw_exit_info_1 (svm->sev_es.ghcb,GHCB_HV_RESP_NO_ACTION ); -ghcb_set_sw_exit_info_2 (svm->sev_es.ghcb,0 ); +svm_vmgexit_success (svm,0 ); exit_code =kvm_ghcb_get_sw_exit_code (control);switch (exit_code) {
@@ -4373,20 +4377,20 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)break ;case 1 :/* Get AP jump table address */ -ghcb_set_sw_exit_info_2 (svm->sev_es.ghcb, sev->ap_jump_table); +svm_vmgexit_success (svm, sev->ap_jump_table);break ;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,GHCB_HV_RESP_MALFORMED_INPUT ); -ghcb_set_sw_exit_info_2 (svm->sev_es.ghcb,GHCB_ERR_INVALID_INPUT ); +svm_vmgexit_bad_input (svm,GHCB_ERR_INVALID_INPUT ); } ret =1 ;break ; }case SVM_VMGEXIT_HV_FEATURES : -ghcb_set_sw_exit_info_2 (svm->sev_es.ghcb,GHCB_HV_FT_SUPPORTED ); +/* Get hypervisor supported features */ +svm_vmgexit_success (svm,GHCB_HV_FT_SUPPORTED ); ret =1 ;break ;
@@ -4408,8 +4412,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,GHCB_HV_RESP_MALFORMED_INPUT ); -ghcb_set_sw_exit_info_2 (svm->sev_es.ghcb,GHCB_ERR_INVALID_INPUT ); +svm_vmgexit_bad_input (svm,GHCB_ERR_INVALID_INPUT ); } ret =1 ;
@@ -4645,7 +4648,7 @@ void sev_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, u8 vector)* Return from an AP Reset Hold VMGEXIT, where the guest will * set the CS and RIP. Set SW_EXIT_INFO_2 to a non-zero value. */ -ghcb_set_sw_exit_info_2 (svm->sev_es.ghcb,1 ); +svm_vmgexit_success (svm,1 );break ;case AP_RESET_HOLD_MSR_PROTO :/*
arch/x86/kvm/svm/svm.c +1 -5
@@ -2973,11 +2973,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,GHCB_HV_RESP_ISSUE_EXCEPTION ); -ghcb_set_sw_exit_info_2 (svm->sev_es.ghcb, -X86_TRAP_GP | -SVM_EVTINJ_TYPE_EXEPT | -SVM_EVTINJ_VALID ); +svm_vmgexit_inject_exception (svm,X86_TRAP_GP );return 1 ; }
arch/x86/kvm/svm/svm.h +29 -0
@@ -581,6 +581,35 @@ static inline bool is_vnmi_enabled(struct vcpu_svm *svm)return false; } +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_NO_ACTION , data); +} + +static inline void svm_vmgexit_no_action (struct vcpu_svm *svm,u64 data) +{ +svm_vmgexit_set_return_code (svm,GHCB_HV_RESP_NO_ACTION , data); +} +/* svm.c */ #define MSR_INVALID 0xffffffffU
Signature · 1 line
2.34.1
Sean Christopherson
maintainerRe: [PATCH v5 2/2] KVM: SVM: Provide helpers to set the error code
arch/x86/kvm/svm/sev.c static void snp_complete_psc(struct vcpu_svm *svm, u64 psc_ret) · line 3678
Quoted 9 lines · Melody Wang
arch/x86/kvm/svm/sev.c +3
-2@@ -3675,8 +3673,13 @@ static void snp_complete_psc(struct vcpu_svm *svm, u64 psc_ret) svm->sev_es.psc_inflight =0 ; svm->sev_es.psc_idx =0 ; svm->sev_es.psc_2m = false; -ghcb_set_sw_exit_info_2 (svm->sev_es.ghcb, psc_ret); -} + +/* +* A value of zero in SW_EXITINFO1 does not guarantee that all operations have
"A value of zero" is largely redundant, and somewhat confusing. There's no '0' in the below code, so to understand the comment, the reader needs to know that "no action" is a response code of '0' (and is communicated in SW_EXITINFO1, though that's much less of a problem).
arch/x86/kvm/svm/sev.c static void snp_complete_psc(struct vcpu_svm *svm, u64 psc_ret) · line 3680
Quoted 2 lines
arch/x86/kvm/svm/sev.c +2
-0+* completed or completed successfully. PSC requests always get a "no action" +* response in SW_EXITINFO1, with a PSC-specific return code in SW_EXITINFO2.
Please wrap at ~80. Yes, it's a "soft limit", but preferred KVM style is to wrap at 80 unless running long makes the code more readable. For a multi-line comment, I don't see any reason to wrap in the mid-80s.
This is what I ended up with
/*
* PSC requests always get a "no action" response in SW_EXITINFO1, with
* a PSC-specific return code in SW_EXITINFO2 that provides the "real"
* return code. E.g. if the PSC request was interrupted, the need to
* retry is communicated via SW_EXITINFO2, not SW_EXITINFO1. */
arch/x86/kvm/svm/sev.c static void snp_complete_psc(struct vcpu_svm *svm, u64 psc_ret) · line 3682
Quoted 2 lines
arch/x86/kvm/svm/sev.c +2
-0+*/ +svm_vmgexit_no_action (svm, psc_ret); }
Malformed change to the closing curly brace.
arch/x86/kvm/svm/sev.c int sev_handle_vmgexit(struct kvm_vcpu *vcpu) · line 4392
Quoted 3 lines
arch/x86/kvm/svm/sev.c +1
-1case SVM_VMGEXIT_HV_FEATURES : -ghcb_set_sw_exit_info_2 (svm->sev_es.ghcb,GHCB_HV_FT_SUPPORTED ); +/* Get hypervisor supported features */
This doesn't add any value. If the logic isn't clear, then GHCB_HV_FT_SUPPORTED needs to be renamed.
Quoted 4 lines
arch/x86/kvm/svm/sev.c +1
-0+svm_vmgexit_success (svm,GHCB_HV_FT_SUPPORTED ); ret =1 ;break ;
Sean Christopherson
maintainerQuoted 9 lines · Melody Wang
Melody Wang (2):
KVM: SVM: Convert plain error code numbers to defines
KVM: SVM: Provide helpers to set the error codearch/x86/include/asm/sev-common.h | 8 +++++++ arch/x86/kvm/svm/sev.c | 39 +++++++++++++++++-------------- arch/x86/kvm/svm/svm.c | 6 +---- arch/x86/kvm/svm/svm.h | 29 +++++++++++++++++++++++ 4 files changed, 59 insertions(+), 23 deletions(-)
A few nits, but I'll fixup when applying. No need for a new version.
Quoted 10 lines · Melody Wang
This patchset includes two patches to make VMGEXIT GHCB exit codes returned by the hypervisor more readable. One patch coverts plain error code numbers to defines, the other one adds helpers to set the error code.
No functionality changed.
Thanks,
Melody[...]
Applied to kvm-x86 svm, with some massaging. Thanks!
[1/2] KVM: SVM: Convert plain error code numbers to defines
https://github.com/kvm-x86/linux/commit/ea4c2f2f5ed3 [2/2] KVM: SVM: Provide helpers to set the error code https://github.com/kvm-x86/linux/commit/c3392d0ab714