Re: [PATCH 2/4] KVM: x86: separate pending and injected exception

2021-04-02 Thread Sean Christopherson
On Fri, Apr 02, 2021, Paolo Bonzini wrote:
> On 02/04/21 01:05, Sean Christopherson wrote:
> > > 
> > > +struct kvm_queued_exception {
> > > + bool valid;
> > > + u8 nr;
> > 
> > If we're refactoring all this code anyways, maybe change "nr" to something a
> > bit more descriptive?  E.g. vector.
> 
> "nr" is part of the userspace structure, so consistency is an advantage too.

Foiled at every turn.  Keeping "nr" probably does make sense.


Re: [PATCH 2/4] KVM: x86: separate pending and injected exception

2021-04-02 Thread Paolo Bonzini

On 02/04/21 01:05, Sean Christopherson wrote:


+struct kvm_queued_exception {
+   bool valid;
+   u8 nr;


If we're refactoring all this code anyways, maybe change "nr" to something a
bit more descriptive?  E.g. vector.


"nr" is part of the userspace structure, so consistency is an advantage too.


+   struct kvm_exception_payload {
+   bool valid;
+   unsigned long value;
u8 nested_apf;
-   } exception;
+   } exception_payload;


Hmm, even if it's dead code at this time, I think the exception payload should
be part of 'struct kvm_queued_exception'.  The payload is very much tied to a
single exception.


Agreed, when handling injected exceptions you can WARN that there is no 
payload.


Paolo



Re: [PATCH 2/4] KVM: x86: separate pending and injected exception

2021-04-01 Thread Sean Christopherson
On Thu, Apr 01, 2021, Maxim Levitsky wrote:
> Use 'pending_exception' and 'injected_exception' fields
> to store the pending and the injected exceptions.
> 
> After this patch still only one is active, but
> in the next patch both could co-exist in some cases.

Please explain _why_.  

> Signed-off-by: Maxim Levitsky 
> ---
>  arch/x86/include/asm/kvm_host.h |  25 --
>  arch/x86/kvm/svm/nested.c   |  26 +++---
>  arch/x86/kvm/svm/svm.c  |   6 +-
>  arch/x86/kvm/vmx/nested.c   |  36 
>  arch/x86/kvm/vmx/vmx.c  |  12 +--
>  arch/x86/kvm/x86.c  | 145 ++--
>  arch/x86/kvm/x86.h  |   6 +-
>  7 files changed, 143 insertions(+), 113 deletions(-)
> 
> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> index a52f973bdff6..3b2fd276e8d5 100644
> --- a/arch/x86/include/asm/kvm_host.h
> +++ b/arch/x86/include/asm/kvm_host.h
> @@ -547,6 +547,14 @@ struct kvm_vcpu_xen {
>   u64 runstate_times[4];
>  };
>  
> +struct kvm_queued_exception {
> + bool valid;
> + u8 nr;

If we're refactoring all this code anyways, maybe change "nr" to something a
bit more descriptive?  E.g. vector.

> + bool has_error_code;
> + u32 error_code;
> +};
> +
> +
>  struct kvm_vcpu_arch {
>   /*
>* rip and regs accesses must go through
> @@ -645,16 +653,15 @@ struct kvm_vcpu_arch {
>  
>   u8 event_exit_inst_len;
>  
> - struct kvm_queued_exception {
> - bool pending;
> - bool injected;
> - bool has_error_code;
> - u8 nr;
> - u32 error_code;
> - unsigned long payload;
> - bool has_payload;
> + struct kvm_queued_exception pending_exception;
> +
> + struct kvm_exception_payload {
> + bool valid;
> + unsigned long value;
>   u8 nested_apf;
> - } exception;
> + } exception_payload;

Hmm, even if it's dead code at this time, I think the exception payload should
be part of 'struct kvm_queued_exception'.  The payload is very much tied to a
single exception.

> +
> + struct kvm_queued_exception injected_exception;

Any objection to keeping the current syntax, arch.exception.{pending,injected}?
Maybe it's fear of change, but I like the current style, I think because the
relevant info is condensed at the end, e.g. I can ignore "vcpu->arch.exception"
and look at "pending.vector" or whatever.  E.g.

struct {
struct kvm_queued_exception pending;
struct kvm_queued_exception injected;
} exception;
>  
>   struct kvm_queued_interrupt {
>   bool injected;


[PATCH 2/4] KVM: x86: separate pending and injected exception

2021-04-01 Thread Maxim Levitsky
Use 'pending_exception' and 'injected_exception' fields
to store the pending and the injected exceptions.

After this patch still only one is active, but
in the next patch both could co-exist in some cases.

Signed-off-by: Maxim Levitsky 
---
 arch/x86/include/asm/kvm_host.h |  25 --
 arch/x86/kvm/svm/nested.c   |  26 +++---
 arch/x86/kvm/svm/svm.c  |   6 +-
 arch/x86/kvm/vmx/nested.c   |  36 
 arch/x86/kvm/vmx/vmx.c  |  12 +--
 arch/x86/kvm/x86.c  | 145 ++--
 arch/x86/kvm/x86.h  |   6 +-
 7 files changed, 143 insertions(+), 113 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index a52f973bdff6..3b2fd276e8d5 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -547,6 +547,14 @@ struct kvm_vcpu_xen {
u64 runstate_times[4];
 };
 
+struct kvm_queued_exception {
+   bool valid;
+   u8 nr;
+   bool has_error_code;
+   u32 error_code;
+};
+
+
 struct kvm_vcpu_arch {
/*
 * rip and regs accesses must go through
@@ -645,16 +653,15 @@ struct kvm_vcpu_arch {
 
u8 event_exit_inst_len;
 
-   struct kvm_queued_exception {
-   bool pending;
-   bool injected;
-   bool has_error_code;
-   u8 nr;
-   u32 error_code;
-   unsigned long payload;
-   bool has_payload;
+   struct kvm_queued_exception pending_exception;
+
+   struct kvm_exception_payload {
+   bool valid;
+   unsigned long value;
u8 nested_apf;
-   } exception;
+   } exception_payload;
+
+   struct kvm_queued_exception injected_exception;
 
struct kvm_queued_interrupt {
bool injected;
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index 34a37b2bd486..7adad9b6dcad 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -349,14 +349,14 @@ static void nested_save_pending_event_to_vmcb12(struct 
vcpu_svm *svm,
u32 exit_int_info = 0;
unsigned int nr;
 
-   if (vcpu->arch.exception.injected) {
-   nr = vcpu->arch.exception.nr;
+   if (vcpu->arch.injected_exception.valid) {
+   nr = vcpu->arch.injected_exception.nr;
exit_int_info = nr | SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_EXEPT;
 
-   if (vcpu->arch.exception.has_error_code) {
+   if (vcpu->arch.injected_exception.has_error_code) {
exit_int_info |= SVM_EVTINJ_VALID_ERR;
vmcb12->control.exit_int_info_err =
-   vcpu->arch.exception.error_code;
+   vcpu->arch.injected_exception.error_code;
}
 
} else if (vcpu->arch.nmi_injected) {
@@ -1000,30 +1000,30 @@ int nested_svm_check_permissions(struct kvm_vcpu *vcpu)
 
 static bool nested_exit_on_exception(struct vcpu_svm *svm)
 {
-   unsigned int nr = svm->vcpu.arch.exception.nr;
+   unsigned int nr = svm->vcpu.arch.pending_exception.nr;
 
return (svm->nested.ctl.intercepts[INTERCEPT_EXCEPTION] & BIT(nr));
 }
 
 static void nested_svm_inject_exception_vmexit(struct vcpu_svm *svm)
 {
-   unsigned int nr = svm->vcpu.arch.exception.nr;
+   unsigned int nr = svm->vcpu.arch.pending_exception.nr;
 
svm->vmcb->control.exit_code = SVM_EXIT_EXCP_BASE + nr;
svm->vmcb->control.exit_code_hi = 0;
 
-   if (svm->vcpu.arch.exception.has_error_code)
-   svm->vmcb->control.exit_info_1 = 
svm->vcpu.arch.exception.error_code;
+   if (svm->vcpu.arch.pending_exception.has_error_code)
+   svm->vmcb->control.exit_info_1 = 
svm->vcpu.arch.pending_exception.error_code;
 
/*
 * EXITINFO2 is undefined for all exception intercepts other
 * than #PF.
 */
if (nr == PF_VECTOR) {
-   if (svm->vcpu.arch.exception.nested_apf)
+   if (svm->vcpu.arch.exception_payload.nested_apf)
svm->vmcb->control.exit_info_2 = 
svm->vcpu.arch.apf.nested_apf_token;
-   else if (svm->vcpu.arch.exception.has_payload)
-   svm->vmcb->control.exit_info_2 = 
svm->vcpu.arch.exception.payload;
+   else if (svm->vcpu.arch.exception_payload.valid)
+   svm->vmcb->control.exit_info_2 = 
svm->vcpu.arch.exception_payload.value;
else
svm->vmcb->control.exit_info_2 = svm->vcpu.arch.cr2;
} else if (nr == DB_VECTOR) {
@@ -1034,7 +1034,7 @@ static void nested_svm_inject_exception_vmexit(struct 
vcpu_svm *svm)
kvm_update_dr7(>vcpu);
}
} else
-   WARN_ON(svm->vcpu.arch.exception.has_payload);
+   WARN_ON(svm->vcpu.arch.exception_payload.valid);
 
nested_svm_vmexit(svm);
 }
@@