KVM: nSVM: ondemand nested state allocation
v4 cover KVM: nSVM: ondemand nested state allocation
This is new version of ondemand nested state allocation.
In this version I dropped the changes to set_efer and instead added a new request KVM_REQ_OUT_OF_MEMORY which makes the kvm exit to userspace with KVM_EXIT_INTERNAL_ERROR
This request is used in (unlikely) case of memory allocation failure.
Maxim Levitsky (2):
KVM: add request KVM_REQ_OUT_OF_MEMORY
KVM: nSVM: implement ondemand allocation of the nested state
arch/x86/kvm/svm/nested.c | 42 ++++++++++++++++++++++++++++++ arch/x86/kvm/svm/svm.c | 54 ++++++++++++++++++++++----------------- arch/x86/kvm/svm/svm.h | 7 +++++ arch/x86/kvm/x86.c | 7 +++++ include/linux/kvm_host.h | 1 + 5 files changed, 87 insertions(+), 24 deletions(-)
Signature · 1 line
2.26.2
PATCH v4 1/2 KVM: add request KVM_REQ_OUT_OF_MEMORY
This request will be used in rare cases when emulation can't continue due to being out of memory, to kill the current VM.
Currently only implemented for x86.
--- arch/x86/kvm/x86.c | 7 +++++++ include/linux/kvm_host.h | 1 + 2 files changed, 8 insertions(+)
arch/x86/kvm/x86.c +7 -0
@@ -8471,6 +8471,13 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)kvm_vcpu_update_apicv (vcpu);if (kvm_check_request (KVM_REQ_APF_READY , vcpu))kvm_check_async_pf_completion (vcpu); + +if (kvm_check_request (KVM_REQ_OUT_OF_MEMORY , vcpu)) { + vcpu->run->exit_reason =KVM_EXIT_INTERNAL_ERROR ; + vcpu->run->internal.suberror =KVM_INTERNAL_ERROR_EMULATION ; + r =0 ; + goto out; + } }if (kvm_check_request (KVM_REQ_EVENT , vcpu) || req_int_win) {
include/linux/kvm_host.h +1 -0
@@ -146,6 +146,7 @@ static inline bool is_error_page(struct page *page)#define KVM_REQ_MMU_RELOAD (1 | KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)#define KVM_REQ_PENDING_TIMER 2#define KVM_REQ_UNHALT 3 +#define KVM_REQ_OUT_OF_MEMORY 4#define KVM_REQUEST_ARCH_BASE 8#define KVM_ARCH_REQ_FLAGS (nr, flags) ({ \
Signature · 1 line
2.26.2
PATCH v4 2/2 KVM: nSVM: implement ondemand allocation of the nested state
In reply to Maxim LevitskyThis way we don't waste memory on VMs which don't use nesting virtualization even if it is available to them.
If allocation of nested state fails (which should happen, only when host is about to OOM anyway), use new KVM_REQ_OUT_OF_MEMORY request to shut down the guest
--- arch/x86/kvm/svm/nested.c | 42 ++++++++++++++++++++++++++++++ arch/x86/kvm/svm/svm.c | 54 ++++++++++++++++++++++----------------- arch/x86/kvm/svm/svm.h | 7 +++++ 3 files changed, 79 insertions(+), 24 deletions(-)
arch/x86/kvm/svm/nested.c +42 -0
@@ -467,6 +467,9 @@ int nested_svm_vmrun(struct vcpu_svm *svm) vmcb12 = map.hva; +if (WARN_ON (!svm->nested.initialized)) +return 1 ; +if (!nested_vmcb_checks (svm, vmcb12)) { vmcb12->control.exit_code =SVM_EXIT_ERR ; vmcb12->control.exit_code_hi =0 ;
@@ -684,6 +687,45 @@ int nested_svm_vmexit(struct vcpu_svm *svm)return 0 ; } +int svm_allocate_nested (struct vcpu_svm *svm) +{ +struct page *hsave_page; + +if (svm->nested.initialized) +return 0 ; + + hsave_page =alloc_page (GFP_KERNEL_ACCOUNT | __GFP_ZERO); +if (!hsave_page) + goto error; + + svm->nested.hsave =page_address (hsave_page); + + svm->nested.msrpm =svm_vcpu_init_msrpm (); +if (!svm->nested.msrpm) + goto err_free_hsave; + + svm->nested.initialized = true; +return 0 ; +err_free_hsave: +__free_page (hsave_page); +error: +return 1 ; +} + +void svm_free_nested (struct vcpu_svm *svm) +{ +if (!svm->nested.initialized) +return ; + +svm_vcpu_free_msrpm (svm->nested.msrpm); + svm->nested.msrpm =NULL ; + +__free_page (virt_to_page (svm->nested.hsave)); + svm->nested.hsave =NULL ; + + svm->nested.initialized = false; +} +/* * Forcibly leave nested mode in order to be able to reset the VCPU later on. */
arch/x86/kvm/svm/svm.c +30 -24
120 lines not on this page · raw message
arch/x86/kvm/svm/svm.h +7 -0
@@ -96,6 +96,8 @@ struct svm_nested_state {/* cache for control fields of the guest */ struct vmcb_control_area ctl; + +bool initialized; };struct vcpu_svm {
@@ -338,6 +340,9 @@ static inline bool gif_set(struct vcpu_svm *svm)#define MSR_INVALID 0xffffffffUu32 svm_msrpm_offset (u32 msr); +u32 *svm_vcpu_init_msrpm (void ); +void svm_vcpu_free_msrpm (u32 *msrpm); +void svm_set_efer (struct kvm_vcpu *vcpu,u64 efer);void svm_set_cr0 (struct kvm_vcpu *vcpu,unsigned long cr0);int svm_set_cr4 (struct kvm_vcpu *vcpu,unsigned long cr4);
@@ -379,6 +384,8 @@ static inline bool nested_exit_on_nmi(struct vcpu_svm *svm)int enter_svm_guest_mode (struct vcpu_svm *svm,u64 vmcb_gpa,struct vmcb *nested_vmcb);void svm_leave_nested (struct vcpu_svm *svm); +void svm_free_nested (struct vcpu_svm *svm); +int svm_allocate_nested (struct vcpu_svm *svm);int nested_svm_vmrun (struct vcpu_svm *svm);void nested_svm_vmloadsave (struct vmcb *from_vmcb,struct vmcb *to_vmcb);int nested_svm_vmexit (struct vcpu_svm *svm);
Signature · 1 line
2.26.2
Re: [PATCH v4 2/2] KVM: nSVM: implement ondemand allocation of the nested state
Quoted 32 lines · Maxim Levitsky
This way we don't waste memory on VMs which don't use nesting virtualization even if it is available to them.
If allocation of nested state fails (which should happen, only when host is about to OOM anyway), use new
KVM_REQ_OUT_OF_MEMORYrequest to shut down the guestSigned-off-by Maxim Levitsky <[email protected]>--- arch/x86/kvm/svm/nested.c | 42 ++++++++++++++++++++++++++++++ arch/x86/kvm/svm/svm.c | 54 ++++++++++++++++++++++----------------- arch/x86/kvm/svm/svm.h | 7 +++++ 3 files changed, 79 insertions(+), 24 deletions(-)arch/x86/kvm/svm/nested.c +3
-0@@ -467,6 +467,9 @@ int nested_svm_vmrun(struct vcpu_svm *svm) vmcb12 = map.hva; +if (WARN_ON (!svm->nested.initialized)) +return 1 ; +if (!nested_vmcb_checks (svm, vmcb12)) { vmcb12->control.exit_code =SVM_EXIT_ERR ; vmcb12->control.exit_code_hi =0 ;@@ -684,6 +687,45 @@ int nested_svm_vmexit(struct vcpu_svm *svm)return 0 ; }
arch/x86/kvm/svm/nested.c int nested_svm_vmexit(struct vcpu_svm *svm) · line 699
Quoted 10 lines
arch/x86/kvm/svm/nested.c +10
-0+int svm_allocate_nested (struct vcpu_svm *svm) +{ +struct page *hsave_page; + +if (svm->nested.initialized) +return 0 ; + + hsave_page =alloc_page (GFP_KERNEL_ACCOUNT | __GFP_ZERO); +if (!hsave_page) + goto error;
goto is unnecessary, just do
return -ENOMEM;
arch/x86/kvm/svm/nested.c int nested_svm_vmexit(struct vcpu_svm *svm) · line 712
Quoted 13 lines
arch/x86/kvm/svm/nested.c +13
-0+ + svm->nested.hsave =page_address (hsave_page); + + svm->nested.msrpm =svm_vcpu_init_msrpm (); +if (!svm->nested.msrpm) + goto err_free_hsave; + + svm->nested.initialized = true; +return 0 ; +err_free_hsave: +__free_page (hsave_page); +error: +return 1 ;
As above, -ENOMEM would be preferable.
Quoted 45 lines
arch/x86/kvm/svm/nested.c +16
-0+} + +void svm_free_nested (struct vcpu_svm *svm) +{ +if (!svm->nested.initialized) +return ; + +svm_vcpu_free_msrpm (svm->nested.msrpm); + svm->nested.msrpm =NULL ; + +__free_page (virt_to_page (svm->nested.hsave)); + svm->nested.hsave =NULL ; + + svm->nested.initialized = false; +} +/* * Forcibly leave nested mode in order to be able to reset the VCPU later on. */ arch/x86/kvm/svm/svm.c +8
-3@@ -266,6 +266,7 @@ static int get_max_npt_level(void)void svm_set_efer (struct kvm_vcpu *vcpu,u64 efer) {struct vcpu_svm *svm =to_svm (vcpu); +u64 old_efer = vcpu->arch.efer; vcpu->arch.efer = efer;if (!npt_enabled) {@@ -276,9 +277,26 @@ void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) efer &= ~EFER_LME ; } -if (!(efer &EFER_SVME )) { -svm_leave_nested (svm); -svm_set_gif (svm, true); +if ((old_efer &EFER_SVME ) != (efer &EFER_SVME )) { +if (!(efer &EFER_SVME )) { +svm_leave_nested (svm); +svm_set_gif (svm, true); + +/* +* Free the nested state unless we are in SMM, in which
arch/x86/kvm/svm/svm.c void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) · line 296
Quoted 10 lines
arch/x86/kvm/svm/svm.c +10
-0+* case the exit from SVM mode is only for duration of the SMI +* handler +*/ +if (!is_smm (&svm->vcpu)) +svm_free_nested (svm); + + }else { +if (svm_allocate_nested (svm)) { + vcpu->arch.efer = old_efer; +kvm_make_request (KVM_REQ_OUT_OF_MEMORY , vcpu);
I really dislike KVM_REQ_OUT_OF_MEMORY. It's redundant with -ENOMEM and creates a huge discrepancy with respect to existing code, e.g. nVMX returns -ENOMEM in a similar situation.
The deferred error handling creates other issues, e.g. vcpu->arch.efer is unwound but the guest's RIP is not.
One thought for handling this without opening a can of worms would be to do:
r = kvm_x86_ops.set_efer(vcpu, efer);
if (r) {
WARN_ON(r > 0);
return r;
}I.e. go with the original approach, but only for returning errors that will go all the way out to userspace.
Quoted 6 lines
arch/x86/kvm/svm/svm.c +3
-0+return ; + } + } } svm->vmcb->save.efer = efer |EFER_SVME ;
Paolo Bonzini
maintainerRe: [PATCH v4 2/2] KVM: nSVM: implement ondemand allocation of the nested state
Quoted 5 lines · Sean Christopherson
arch/x86/kvm/svm/svm.c void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) · line 296
Quoted 2 lines
arch/x86/kvm/svm/svm.c +2
-0+ vcpu->arch.efer = old_efer; +kvm_make_request (KVM_REQ_OUT_OF_MEMORY , vcpu);I really dislike
KVM_REQ_OUT_OF_MEMORY. It's redundant with-ENOMEMand creates a huge discrepancy with respect to existing code, e.g. nVMX returns-ENOMEMin a similar situation.
Maxim, your previous version was adding some error handling to kvm_x86_ops.set_efer. I don't remember what was the issue; did you have any problems propagating all the errors up to KVM_SET_SREGS (easy), kvm_set_msr (harder) etc.?
Paolo
Re: [PATCH v4 2/2] KVM: nSVM: implement ondemand allocation of the nested state
Quoted 11 lines · Paolo Bonzini
Quoted 5 lines · Sean Christopherson
arch/x86/kvm/svm/svm.c void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) · line 296
Quoted 2 lines
arch/x86/kvm/svm/svm.c +2
-0+ vcpu->arch.efer = old_efer; +kvm_make_request (KVM_REQ_OUT_OF_MEMORY , vcpu);I really dislike
KVM_REQ_OUT_OF_MEMORY. It's redundant with-ENOMEMand creates a huge discrepancy with respect to existing code, e.g. nVMX returns-ENOMEMin a similar situation.Maxim, your previous version was adding some error handling to kvm_x86_ops.set_efer. I don't remember what was the issue; did you have any problems propagating all the errors up to
KVM_SET_SREGS(easy),kvm_set_msr(harder) etc.?
I objected to letting .set_efer() return a fault. A relatively minor issue is the code in vmx_set_efer() that handles lack of EFER because technically KVM can emulate EFER.SCE+SYSCALL without supporting EFER in hardware. Returning success/'0' would avoid that particular issue. My primary concern is that I'd prefer not to add another case where KVM can potentially ignore a fault indicated by a helper, a la vmx_set_cr4().
To that end, I'd be ok with adding error handling to .set_efer() if KVM enforces, via WARN in one of the .set_efer() call sites, that SVM/VMX can only return negative error codes, i.e. let SVM handle the -ENOMEM case but disallow fault injection. It doesn't actually change anything, but it'd give me a warm fuzzy feeling.
Paolo Bonzini
maintainerRe: [PATCH v4 2/2] KVM: nSVM: implement ondemand allocation of the nested state
Quoted 5 lines · Sean Christopherson
Quoted 4 lines
Maxim, your previous version was adding some error handling to kvm_x86_ops.set_efer. I don't remember what was the issue; did you have any problems propagating all the errors up to
KVM_SET_SREGS(easy),kvm_set_msr(harder) etc.?I objected to letting .set_efer() return a fault.
So did I, and that's why we get KVM_REQ_OUT_OF_MEMORY. But it was more of an "it's ugly and it ought not to fail" thing than something I could pinpoint.
It looks like we agree, but still we have to choose the lesser evil?
Paolo
Quoted 6 lines
A relatively minor issue is
the code invmx_set_efer()that handles lack of EFER because technically KVM can emulate EFER.SCE+SYSCALL without supporting EFER in hardware. Returning success/'0' would avoid that particular issue. My primary concern is that I'd prefer not to add another case where KVM can potentially ignore a fault indicated by a helper, a lavmx_set_cr4().
Re: [PATCH v4 2/2] KVM: nSVM: implement ondemand allocation of the nested state
Quoted 7 lines · Paolo Bonzini
Quoted 5 lines · Sean Christopherson
Quoted 4 lines
Maxim, your previous version was adding some error handling to kvm_x86_ops.set_efer. I don't remember what was the issue; did you have any problems propagating all the errors up to
KVM_SET_SREGS(easy),kvm_set_msr(harder) etc.?I objected to letting .set_efer() return a fault.
Quoted 14 lines
So did I, and that's why we get
KVM_REQ_OUT_OF_MEMORY. But it was more of an "it's ugly and it ought not to fail" thing than something I could pinpoint.It looks like we agree, but still we have to choose the lesser evil?
Paolo
Quoted 6 lines
A relatively minor issue is
the code invmx_set_efer()that handles lack of EFER because technically KVM can emulate EFER.SCE+SYSCALL without supporting EFER in hardware. Returning success/'0' would avoid that particular issue. My primary concern is that I'd prefer not to add another case where KVM can potentially ignore a fault indicated by a helper, a lavmx_set_cr4().
The thing is that kvm_emulate_wrmsr injects #GP when kvm_set_msr returns any non zero value, and returns 1 which means keep on going if I understand correctly (0 is userspace exit, negative value would be a return to userspace with an error)
So the question is if we have other wrmsr handlers which return negative value, and would be affected by changing kvm_emulate_wrmsr to pass through the error value. I am checking the code now.
I do agree now that this is the *correct* solution to this problem.
Best regards,
Maxim Levitsky
Re: [PATCH v4 2/2] KVM: nSVM: implement ondemand allocation of the nested state
Quoted 27 lines · Maxim Levitsky
Quoted 7 lines · Paolo Bonzini
Quoted 5 lines · Sean Christopherson
Quoted 4 lines
Maxim, your previous version was adding some error handling to kvm_x86_ops.set_efer. I don't remember what was the issue; did you have any problems propagating all the errors up to
KVM_SET_SREGS(easy),kvm_set_msr(harder) etc.?I objected to letting .set_efer() return a fault.
Quoted 14 lines
So did I, and that's why we get
KVM_REQ_OUT_OF_MEMORY. But it was more of an "it's ugly and it ought not to fail" thing than something I could pinpoint.It looks like we agree, but still we have to choose the lesser evil?
Paolo
Quoted 6 lines
A relatively minor issue is
the code invmx_set_efer()that handles lack of EFER because technically KVM can emulate EFER.SCE+SYSCALL without supporting EFER in hardware. Returning success/'0' would avoid that particular issue. My primary concern is that I'd prefer not to add another case where KVM can potentially ignore a fault indicated by a helper, a lavmx_set_cr4().The thing is that
kvm_emulate_wrmsrinjects #GP whenkvm_set_msrreturns any non zero value, and returns 1 which means keep on going if I understand correctly (0 is userspace exit, negative value would be a return to userspace with an error)
Quoted 8 lines
So the question is if we have other wrmsr handlers which return negative value, and would be affected by changing
kvm_emulate_wrmsrto pass through the error value. I am checking the code now.I do agree now that this is the *correct* solution to this problem.
Best regards,
Maxim Levitsky
So those are results of my analysis:
WRMSR called functions that return negative value (I could have missed something, but I double checked the wrmsr code in both SVM and VMX, and in the common x86 code):
vmx_set_vmx_msr - this is only called from userspace (msr_info->host_initiated == true), so this can be left as is
xen_hvm_config - this code should probably return 1 in some cases, but in one case, it legit does memory allocation like I do, and failure should probably kill the guest as well (but I can keep it as is if we are afraid that new behavier will not be backward compatible)
What do you think about this (only compile tested since I don't have any xen setups):
arch/x86/kvm/x86.c +9 -14
@@ -2695,24 +2695,19 @@ static int xen_hvm_config(struct kvm_vcpu *vcpu, u64 data)u32 page_num = data & ~PAGE_MASK ;u64 page_addr = data &PAGE_MASK ;u8 *page; -int r; - r = -E2BIG ;if (page_num >= blob_size) - goto out; - r = -ENOMEM ; +return 1 ; + page =memdup_user (blob_addr + (page_num *PAGE_SIZE ),PAGE_SIZE ); -if (IS_ERR (page)) { - r =PTR_ERR (page); - goto out; +if (IS_ERR (page)) +return PTR_ERR (page); + +if (kvm_vcpu_write_guest (vcpu, page_addr, page,PAGE_SIZE )) { +kfree (page); +return 1 ; } -if (kvm_vcpu_write_guest (vcpu, page_addr, page,PAGE_SIZE )) - goto out_free; - r =0 ; -out_free: -kfree (page); -out: -return r; +return 0 ; }
The msr write itself can be reached from the guest through two functions, from kvm_emulate_wrmsr which is called in wrmsr interception from both VMX and SVM, and from em_wrmsr which is called in unlikely case the emulator needs to emulate a wrmsr.
Both should be changed to inject #GP only on positive return value and pass the error otherwise.
Sounds reasonable? If you agree I'll post the patches implementing this.
Best regards,
Maxim Levitsky
Re: [PATCH v4 2/2] KVM: nSVM: implement ondemand allocation of the nested state
In reply to Sean ChristophersonQuoted 46 lines · Sean Christopherson
Quoted 32 lines · Maxim Levitsky
This way we don't waste memory on VMs which don't use nesting virtualization even if it is available to them.
If allocation of nested state fails (which should happen, only when host is about to OOM anyway), use new
KVM_REQ_OUT_OF_MEMORYrequest to shut down the guestSigned-off-by Maxim Levitsky <[email protected]>--- arch/x86/kvm/svm/nested.c | 42 ++++++++++++++++++++++++++++++ arch/x86/kvm/svm/svm.c | 54 ++++++++++++++++++++++----------------- arch/x86/kvm/svm/svm.h | 7 +++++ 3 files changed, 79 insertions(+), 24 deletions(-)arch/x86/kvm/svm/nested.c +3
-0@@ -467,6 +467,9 @@ int nested_svm_vmrun(struct vcpu_svm *svm) vmcb12 = map.hva; +if (WARN_ON (!svm->nested.initialized)) +return 1 ; +if (!nested_vmcb_checks (svm, vmcb12)) { vmcb12->control.exit_code =SVM_EXIT_ERR ; vmcb12->control.exit_code_hi =0 ;@@ -684,6 +687,45 @@ int nested_svm_vmexit(struct vcpu_svm *svm)return 0 ; }arch/x86/kvm/svm/nested.c int nested_svm_vmexit(struct vcpu_svm *svm) · line 699
Quoted 10 lines
arch/x86/kvm/svm/nested.c +10
-0+int svm_allocate_nested (struct vcpu_svm *svm) +{ +struct page *hsave_page; + +if (svm->nested.initialized) +return 0 ; + + hsave_page =alloc_page (GFP_KERNEL_ACCOUNT | __GFP_ZERO); +if (!hsave_page) + goto error;goto is unnecessary, just do
Quoted 1 line
return -ENOMEM;
To be honest this is a philosophical question, what way is better, but I don't mind to change this.
Quoted 16 lines
Quoted 4 lines
arch/x86/kvm/svm/nested.c +3
-0+ + svm->nested.hsave =page_address (hsave_page); +arch/x86/kvm/svm/nested.c int nested_svm_vmexit(struct vcpu_svm *svm) · line 712
Quoted 10 lines
arch/x86/kvm/svm/nested.c +10
-0+ svm->nested.msrpm =svm_vcpu_init_msrpm (); +if (!svm->nested.msrpm) + goto err_free_hsave; + + svm->nested.initialized = true; +return 0 ; +err_free_hsave: +__free_page (hsave_page); +error: +return 1 ;As above,
-ENOMEMwould be preferable.
After the changes to return negative values from msr writes, this indeed makes sense and is done now.
Quoted 66 lines
Quoted 46 lines
arch/x86/kvm/svm/nested.c +16
-0+} + +void svm_free_nested (struct vcpu_svm *svm) +{ +if (!svm->nested.initialized) +return ; + +svm_vcpu_free_msrpm (svm->nested.msrpm); + svm->nested.msrpm =NULL ; + +__free_page (virt_to_page (svm->nested.hsave)); + svm->nested.hsave =NULL ; + + svm->nested.initialized = false; +} +/* * Forcibly leave nested mode in order to be able to reset the VCPU later on. */ arch/x86/kvm/svm/svm.c +8
-3@@ -266,6 +266,7 @@ static int get_max_npt_level(void)void svm_set_efer (struct kvm_vcpu *vcpu,u64 efer) {struct vcpu_svm *svm =to_svm (vcpu); +u64 old_efer = vcpu->arch.efer; vcpu->arch.efer = efer;if (!npt_enabled) {@@ -276,9 +277,26 @@ void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) efer &= ~EFER_LME ; } -if (!(efer &EFER_SVME )) { -svm_leave_nested (svm); -svm_set_gif (svm, true); +if ((old_efer &EFER_SVME ) != (efer &EFER_SVME )) { +if (!(efer &EFER_SVME )) { +svm_leave_nested (svm); +svm_set_gif (svm, true); + +/* +* Free the nested state unless we are in SMM, in which arch/x86/kvm/svm/svm.c void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) · line 296
Quoted 10 lines
arch/x86/kvm/svm/svm.c +10
-0+* case the exit from SVM mode is only for duration of the SMI +* handler +*/ +if (!is_smm (&svm->vcpu)) +svm_free_nested (svm); + + }else { +if (svm_allocate_nested (svm)) { + vcpu->arch.efer = old_efer; +kvm_make_request (KVM_REQ_OUT_OF_MEMORY , vcpu);I really dislike
KVM_REQ_OUT_OF_MEMORY. It's redundant with-ENOMEMand creates a huge discrepancy with respect to existing code, e.g. nVMX returns-ENOMEMin a similar situation.The deferred error handling creates other issues, e.g.
vcpu->arch.eferis unwound but the guest's RIP is not.One thought for handling this without opening a can of worms would be to do:
Quoted 8 lines
r = kvm_x86_ops.set_efer(vcpu, efer); if (r) { WARN_ON(r > 0); return r; }I.e. go with the original approach, but only for returning errors that will go all the way out to userspace.
Done as explained in the other reply.
Quoted 7 lines
arch/x86/kvm/svm/svm.c void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) · line 302
Quoted 7 lines
arch/x86/kvm/svm/svm.c +3
-0+return ; + } + } } svm->vmcb->save.efer = efer |EFER_SVME ;
Thanks for the review,
Best regards,
Maxim Levitsky