diff mbox series

[15/18] KVM: arm64: Warn when PENDING_EXCEPTION and INCREMENT_PC are set together

Message ID 20220528113829.1043361-16-maz@kernel.org (mailing list archive)
State New, archived
Headers show
Series KVM/arm64: Refactoring the vcpu flags | expand

Commit Message

Marc Zyngier May 28, 2022, 11:38 a.m. UTC
We really don't want PENDING_EXCEPTION and INCREMENT_PC to ever be
set at the same time, as they are mutually exclusive. Add checks
that will generate a warning should this ever happen.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/include/asm/kvm_emulate.h | 1 +
 arch/arm64/kvm/hyp/nvhe/sys_regs.c   | 2 ++
 arch/arm64/kvm/inject_fault.c        | 8 ++++++++
 3 files changed, 11 insertions(+)

Comments

Fuad Tabba June 8, 2022, 3:16 p.m. UTC | #1
Hi Marc,

On Sat, May 28, 2022 at 12:49 PM Marc Zyngier <maz@kernel.org> wrote:
>
> We really don't want PENDING_EXCEPTION and INCREMENT_PC to ever be
> set at the same time, as they are mutually exclusive. Add checks
> that will generate a warning should this ever happen.
>
> Signed-off-by: Marc Zyngier <maz@kernel.org>
> ---
>  arch/arm64/include/asm/kvm_emulate.h | 1 +
>  arch/arm64/kvm/hyp/nvhe/sys_regs.c   | 2 ++
>  arch/arm64/kvm/inject_fault.c        | 8 ++++++++
>  3 files changed, 11 insertions(+)
>
> diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
> index 46e631cd8d9e..861fa0b24a7f 100644
> --- a/arch/arm64/include/asm/kvm_emulate.h
> +++ b/arch/arm64/include/asm/kvm_emulate.h
> @@ -473,6 +473,7 @@ static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu,
>
>  static __always_inline void kvm_incr_pc(struct kvm_vcpu *vcpu)
>  {
> +       WARN_ON(vcpu_get_flag(vcpu, PENDING_EXCEPTION));
>         vcpu_set_flag(vcpu, INCREMENT_PC);
>  }
>
> diff --git a/arch/arm64/kvm/hyp/nvhe/sys_regs.c b/arch/arm64/kvm/hyp/nvhe/sys_regs.c
> index 2841a2d447a1..04973984b6db 100644
> --- a/arch/arm64/kvm/hyp/nvhe/sys_regs.c
> +++ b/arch/arm64/kvm/hyp/nvhe/sys_regs.c
> @@ -38,6 +38,8 @@ static void inject_undef64(struct kvm_vcpu *vcpu)
>         *vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
>         *vcpu_cpsr(vcpu) = read_sysreg_el2(SYS_SPSR);
>
> +       WARN_ON(vcpu_get_flag(vcpu, INCREMENT_PC));
> +
>         vcpu_set_flag(vcpu, PENDING_EXCEPTION);
>         vcpu_set_flag(vcpu, EXCEPT_AA64_EL1_SYNC);
>
> diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
> index a9a7b513f3b0..2f4b9afc16ec 100644
> --- a/arch/arm64/kvm/inject_fault.c
> +++ b/arch/arm64/kvm/inject_fault.c
> @@ -20,6 +20,8 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
>         bool is_aarch32 = vcpu_mode_is_32bit(vcpu);
>         u32 esr = 0;
>
> +       WARN_ON(vcpu_get_flag(vcpu, INCREMENT_PC));
> +

Minor nit: While we're at it, should we just create a helper for
setting PENDING_EXCEPTION, same as we have for INCREMENT_PC? That
might make the code clearer and save us from the hassle of having this
WARN_ON before every instance of setting PENDING_EXCEPTION?

Cheers,
/fuad



>         vcpu_set_flag(vcpu, PENDING_EXCEPTION);
>         vcpu_set_flag(vcpu, EXCEPT_AA64_EL1_SYNC);
>
> @@ -51,6 +53,8 @@ static void inject_undef64(struct kvm_vcpu *vcpu)
>  {
>         u32 esr = (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT);
>
> +       WARN_ON(vcpu_get_flag(vcpu, INCREMENT_PC));
> +
>         vcpu_set_flag(vcpu, PENDING_EXCEPTION);
>         vcpu_set_flag(vcpu, EXCEPT_AA64_EL1_SYNC);
>
> @@ -71,6 +75,8 @@ static void inject_undef64(struct kvm_vcpu *vcpu)
>
>  static void inject_undef32(struct kvm_vcpu *vcpu)
>  {
> +       WARN_ON(vcpu_get_flag(vcpu, INCREMENT_PC));
> +
>         vcpu_set_flag(vcpu, PENDING_EXCEPTION);
>         vcpu_set_flag(vcpu, EXCEPT_AA32_UND);
>  }
> @@ -94,6 +100,8 @@ static void inject_abt32(struct kvm_vcpu *vcpu, bool is_pabt, u32 addr)
>
>         far = vcpu_read_sys_reg(vcpu, FAR_EL1);
>
> +       WARN_ON(vcpu_get_flag(vcpu, INCREMENT_PC));
> +
>         if (is_pabt) {
>                 vcpu_set_flag(vcpu, PENDING_EXCEPTION);
>                 vcpu_set_flag(vcpu, EXCEPT_AA32_IABT);
> --
> 2.34.1
>
Marc Zyngier June 8, 2022, 4:42 p.m. UTC | #2
On Wed, 08 Jun 2022 16:16:55 +0100,
Fuad Tabba <tabba@google.com> wrote:
> 
> Hi Marc,
> 
> On Sat, May 28, 2022 at 12:49 PM Marc Zyngier <maz@kernel.org> wrote:
> >
> > We really don't want PENDING_EXCEPTION and INCREMENT_PC to ever be
> > set at the same time, as they are mutually exclusive. Add checks
> > that will generate a warning should this ever happen.
> >
> > Signed-off-by: Marc Zyngier <maz@kernel.org>
> > ---
> >  arch/arm64/include/asm/kvm_emulate.h | 1 +
> >  arch/arm64/kvm/hyp/nvhe/sys_regs.c   | 2 ++
> >  arch/arm64/kvm/inject_fault.c        | 8 ++++++++
> >  3 files changed, 11 insertions(+)
> >
> > diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
> > index 46e631cd8d9e..861fa0b24a7f 100644
> > --- a/arch/arm64/include/asm/kvm_emulate.h
> > +++ b/arch/arm64/include/asm/kvm_emulate.h
> > @@ -473,6 +473,7 @@ static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu,
> >
> >  static __always_inline void kvm_incr_pc(struct kvm_vcpu *vcpu)
> >  {
> > +       WARN_ON(vcpu_get_flag(vcpu, PENDING_EXCEPTION));
> >         vcpu_set_flag(vcpu, INCREMENT_PC);
> >  }
> >
> > diff --git a/arch/arm64/kvm/hyp/nvhe/sys_regs.c b/arch/arm64/kvm/hyp/nvhe/sys_regs.c
> > index 2841a2d447a1..04973984b6db 100644
> > --- a/arch/arm64/kvm/hyp/nvhe/sys_regs.c
> > +++ b/arch/arm64/kvm/hyp/nvhe/sys_regs.c
> > @@ -38,6 +38,8 @@ static void inject_undef64(struct kvm_vcpu *vcpu)
> >         *vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
> >         *vcpu_cpsr(vcpu) = read_sysreg_el2(SYS_SPSR);
> >
> > +       WARN_ON(vcpu_get_flag(vcpu, INCREMENT_PC));
> > +
> >         vcpu_set_flag(vcpu, PENDING_EXCEPTION);
> >         vcpu_set_flag(vcpu, EXCEPT_AA64_EL1_SYNC);
> >
> > diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
> > index a9a7b513f3b0..2f4b9afc16ec 100644
> > --- a/arch/arm64/kvm/inject_fault.c
> > +++ b/arch/arm64/kvm/inject_fault.c
> > @@ -20,6 +20,8 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
> >         bool is_aarch32 = vcpu_mode_is_32bit(vcpu);
> >         u32 esr = 0;
> >
> > +       WARN_ON(vcpu_get_flag(vcpu, INCREMENT_PC));
> > +
> 
> Minor nit: While we're at it, should we just create a helper for
> setting PENDING_EXCEPTION, same as we have for INCREMENT_PC? That
> might make the code clearer and save us from the hassle of having this
> WARN_ON before every instance of setting PENDING_EXCEPTION?

Good point. I ended up with this:

#define kvm_pend_exception(v, e)					\
	do {								\
		WARN_ON(vcpu_get_flag((v), INCREMENT_PC));		\
		vcpu_set_flag((v), PENDING_EXCEPTION);			\
		vcpu_set_flag((v), e);					\
	} while (0)

It has to be a macro in order to deal with the flag expansion, but is
otherwise a welcome cleanup.

Thanks,

	M.
diff mbox series

Patch

diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index 46e631cd8d9e..861fa0b24a7f 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -473,6 +473,7 @@  static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu,
 
 static __always_inline void kvm_incr_pc(struct kvm_vcpu *vcpu)
 {
+	WARN_ON(vcpu_get_flag(vcpu, PENDING_EXCEPTION));
 	vcpu_set_flag(vcpu, INCREMENT_PC);
 }
 
diff --git a/arch/arm64/kvm/hyp/nvhe/sys_regs.c b/arch/arm64/kvm/hyp/nvhe/sys_regs.c
index 2841a2d447a1..04973984b6db 100644
--- a/arch/arm64/kvm/hyp/nvhe/sys_regs.c
+++ b/arch/arm64/kvm/hyp/nvhe/sys_regs.c
@@ -38,6 +38,8 @@  static void inject_undef64(struct kvm_vcpu *vcpu)
 	*vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
 	*vcpu_cpsr(vcpu) = read_sysreg_el2(SYS_SPSR);
 
+	WARN_ON(vcpu_get_flag(vcpu, INCREMENT_PC));
+
 	vcpu_set_flag(vcpu, PENDING_EXCEPTION);
 	vcpu_set_flag(vcpu, EXCEPT_AA64_EL1_SYNC);
 
diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
index a9a7b513f3b0..2f4b9afc16ec 100644
--- a/arch/arm64/kvm/inject_fault.c
+++ b/arch/arm64/kvm/inject_fault.c
@@ -20,6 +20,8 @@  static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
 	bool is_aarch32 = vcpu_mode_is_32bit(vcpu);
 	u32 esr = 0;
 
+	WARN_ON(vcpu_get_flag(vcpu, INCREMENT_PC));
+
 	vcpu_set_flag(vcpu, PENDING_EXCEPTION);
 	vcpu_set_flag(vcpu, EXCEPT_AA64_EL1_SYNC);
 
@@ -51,6 +53,8 @@  static void inject_undef64(struct kvm_vcpu *vcpu)
 {
 	u32 esr = (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT);
 
+	WARN_ON(vcpu_get_flag(vcpu, INCREMENT_PC));
+
 	vcpu_set_flag(vcpu, PENDING_EXCEPTION);
 	vcpu_set_flag(vcpu, EXCEPT_AA64_EL1_SYNC);
 
@@ -71,6 +75,8 @@  static void inject_undef64(struct kvm_vcpu *vcpu)
 
 static void inject_undef32(struct kvm_vcpu *vcpu)
 {
+	WARN_ON(vcpu_get_flag(vcpu, INCREMENT_PC));
+
 	vcpu_set_flag(vcpu, PENDING_EXCEPTION);
 	vcpu_set_flag(vcpu, EXCEPT_AA32_UND);
 }
@@ -94,6 +100,8 @@  static void inject_abt32(struct kvm_vcpu *vcpu, bool is_pabt, u32 addr)
 
 	far = vcpu_read_sys_reg(vcpu, FAR_EL1);
 
+	WARN_ON(vcpu_get_flag(vcpu, INCREMENT_PC));
+
 	if (is_pabt) {
 		vcpu_set_flag(vcpu, PENDING_EXCEPTION);
 		vcpu_set_flag(vcpu, EXCEPT_AA32_IABT);