diff mbox series

[v4,18/28] KVM: arm64: nv: Add trap forwarding for CNTHCTL_EL2

Message ID 20230815183903.2735724-19-maz@kernel.org (mailing list archive)
State New, archived
Headers show
Series KVM: arm64: NV trap forwarding infrastructure | expand

Commit Message

Marc Zyngier Aug. 15, 2023, 6:38 p.m. UTC
Describe the CNTHCTL_EL2 register, and associate it with all the sysregs
it allows to trap.

Reviewed-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/kvm/emulate-nested.c | 50 ++++++++++++++++++++++++++++++++-
 1 file changed, 49 insertions(+), 1 deletion(-)

Comments

Jing Zhang Aug. 15, 2023, 10:42 p.m. UTC | #1
Hi Marc,

On Tue, Aug 15, 2023 at 11:47 AM Marc Zyngier <maz@kernel.org> wrote:
>
> Describe the CNTHCTL_EL2 register, and associate it with all the sysregs
> it allows to trap.
>
> Reviewed-by: Eric Auger <eric.auger@redhat.com>
> Signed-off-by: Marc Zyngier <maz@kernel.org>
> ---
>  arch/arm64/kvm/emulate-nested.c | 50 ++++++++++++++++++++++++++++++++-
>  1 file changed, 49 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c
> index 241e44eeed6d..860910386b5b 100644
> --- a/arch/arm64/kvm/emulate-nested.c
> +++ b/arch/arm64/kvm/emulate-nested.c
> @@ -100,9 +100,11 @@ enum cgt_group_id {
>
>         /*
>          * Anything after this point requires a callback evaluating a
> -        * complex trap condition. Hopefully we'll never need this...
> +        * complex trap condition. Ugly stuff.
>          */
>         __COMPLEX_CONDITIONS__,
> +       CGT_CNTHCTL_EL1PCTEN = __COMPLEX_CONDITIONS__,
> +       CGT_CNTHCTL_EL1PTEN,
>
>         /* Must be last */
>         __NR_CGT_GROUP_IDS__
> @@ -369,10 +371,51 @@ static const enum cgt_group_id *coarse_control_combo[] = {
>
>  typedef enum trap_behaviour (*complex_condition_check)(struct kvm_vcpu *);
>
> +/*
> + * Warning, maximum confusion ahead.
> + *
> + * When E2H=0, CNTHCTL_EL2[1:0] are defined as EL1PCEN:EL1PCTEN
> + * When E2H=1, CNTHCTL_EL2[11:10] are defined as EL1PTEN:EL1PCTEN
> + *
> + * Note the single letter difference? Yet, the bits have the same
> + * function despite a different layout and a different name.
> + *
> + * We don't try to reconcile this mess. We just use the E2H=0 bits
> + * to generate something that is in the E2H=1 format, and live with
> + * it. You're welcome.
> + */
> +static u64 get_sanitized_cnthctl(struct kvm_vcpu *vcpu)
> +{
> +       u64 val = __vcpu_sys_reg(vcpu, CNTHCTL_EL2);
> +
> +       if (!vcpu_el2_e2h_is_set(vcpu))
> +               val = (val & (CNTHCTL_EL1PCEN | CNTHCTL_EL1PCTEN)) << 10;
> +
> +       return val & ((CNTHCTL_EL1PCEN | CNTHCTL_EL1PCTEN) << 10);
> +}
> +
> +static enum trap_behaviour check_cnthctl_el1pcten(struct kvm_vcpu *vcpu)
> +{
> +       if (get_sanitized_cnthctl(vcpu) & (CNTHCTL_EL1PCTEN << 10))
> +               return BEHAVE_HANDLE_LOCALLY;
> +
> +       return BEHAVE_FORWARD_ANY;
> +}
> +
> +static enum trap_behaviour check_cnthctl_el1pten(struct kvm_vcpu *vcpu)
> +{
> +       if (get_sanitized_cnthctl(vcpu) & (CNTHCTL_EL1PCEN << 10))
> +               return BEHAVE_HANDLE_LOCALLY;
> +
> +       return BEHAVE_FORWARD_ANY;
> +}
> +
>  #define CCC(id, fn)                            \
>         [id - __COMPLEX_CONDITIONS__] = fn
>
>  static const complex_condition_check ccc[] = {
> +       CCC(CGT_CNTHCTL_EL1PCTEN, check_cnthctl_el1pcten),
> +       CCC(CGT_CNTHCTL_EL1PTEN, check_cnthctl_el1pten),
>  };
>
>  /*
> @@ -877,6 +920,11 @@ static const struct encoding_to_trap_config encoding_to_cgt[] __initconst = {
>         SR_TRAP(SYS_TRBPTR_EL1,         CGT_MDCR_E2TB),
>         SR_TRAP(SYS_TRBSR_EL1,          CGT_MDCR_E2TB),
>         SR_TRAP(SYS_TRBTRG_EL1,         CGT_MDCR_E2TB),
> +       SR_TRAP(SYS_CNTP_TVAL_EL0,      CGT_CNTHCTL_EL1PTEN),
> +       SR_TRAP(SYS_CNTP_CVAL_EL0,      CGT_CNTHCTL_EL1PTEN),
> +       SR_TRAP(SYS_CNTP_CTL_EL0,       CGT_CNTHCTL_EL1PTEN),
> +       SR_TRAP(SYS_CNTPCT_EL0,         CGT_CNTHCTL_EL1PCTEN),
> +       SR_TRAP(SYS_CNTPCTSS_EL0,       CGT_CNTHCTL_EL1PCTEN),
>  };
>
>  static DEFINE_XARRAY(sr_forward_xa);
> --
> 2.34.1
>

Reviewed-by: Jing Zhang <jingzhangos@google.com>

Jing
diff mbox series

Patch

diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c
index 241e44eeed6d..860910386b5b 100644
--- a/arch/arm64/kvm/emulate-nested.c
+++ b/arch/arm64/kvm/emulate-nested.c
@@ -100,9 +100,11 @@  enum cgt_group_id {
 
 	/*
 	 * Anything after this point requires a callback evaluating a
-	 * complex trap condition. Hopefully we'll never need this...
+	 * complex trap condition. Ugly stuff.
 	 */
 	__COMPLEX_CONDITIONS__,
+	CGT_CNTHCTL_EL1PCTEN = __COMPLEX_CONDITIONS__,
+	CGT_CNTHCTL_EL1PTEN,
 
 	/* Must be last */
 	__NR_CGT_GROUP_IDS__
@@ -369,10 +371,51 @@  static const enum cgt_group_id *coarse_control_combo[] = {
 
 typedef enum trap_behaviour (*complex_condition_check)(struct kvm_vcpu *);
 
+/*
+ * Warning, maximum confusion ahead.
+ *
+ * When E2H=0, CNTHCTL_EL2[1:0] are defined as EL1PCEN:EL1PCTEN
+ * When E2H=1, CNTHCTL_EL2[11:10] are defined as EL1PTEN:EL1PCTEN
+ *
+ * Note the single letter difference? Yet, the bits have the same
+ * function despite a different layout and a different name.
+ *
+ * We don't try to reconcile this mess. We just use the E2H=0 bits
+ * to generate something that is in the E2H=1 format, and live with
+ * it. You're welcome.
+ */
+static u64 get_sanitized_cnthctl(struct kvm_vcpu *vcpu)
+{
+	u64 val = __vcpu_sys_reg(vcpu, CNTHCTL_EL2);
+
+	if (!vcpu_el2_e2h_is_set(vcpu))
+		val = (val & (CNTHCTL_EL1PCEN | CNTHCTL_EL1PCTEN)) << 10;
+
+	return val & ((CNTHCTL_EL1PCEN | CNTHCTL_EL1PCTEN) << 10);
+}
+
+static enum trap_behaviour check_cnthctl_el1pcten(struct kvm_vcpu *vcpu)
+{
+	if (get_sanitized_cnthctl(vcpu) & (CNTHCTL_EL1PCTEN << 10))
+		return BEHAVE_HANDLE_LOCALLY;
+
+	return BEHAVE_FORWARD_ANY;
+}
+
+static enum trap_behaviour check_cnthctl_el1pten(struct kvm_vcpu *vcpu)
+{
+	if (get_sanitized_cnthctl(vcpu) & (CNTHCTL_EL1PCEN << 10))
+		return BEHAVE_HANDLE_LOCALLY;
+
+	return BEHAVE_FORWARD_ANY;
+}
+
 #define CCC(id, fn)				\
 	[id - __COMPLEX_CONDITIONS__] = fn
 
 static const complex_condition_check ccc[] = {
+	CCC(CGT_CNTHCTL_EL1PCTEN, check_cnthctl_el1pcten),
+	CCC(CGT_CNTHCTL_EL1PTEN, check_cnthctl_el1pten),
 };
 
 /*
@@ -877,6 +920,11 @@  static const struct encoding_to_trap_config encoding_to_cgt[] __initconst = {
 	SR_TRAP(SYS_TRBPTR_EL1, 	CGT_MDCR_E2TB),
 	SR_TRAP(SYS_TRBSR_EL1, 		CGT_MDCR_E2TB),
 	SR_TRAP(SYS_TRBTRG_EL1,		CGT_MDCR_E2TB),
+	SR_TRAP(SYS_CNTP_TVAL_EL0,	CGT_CNTHCTL_EL1PTEN),
+	SR_TRAP(SYS_CNTP_CVAL_EL0,	CGT_CNTHCTL_EL1PTEN),
+	SR_TRAP(SYS_CNTP_CTL_EL0,	CGT_CNTHCTL_EL1PTEN),
+	SR_TRAP(SYS_CNTPCT_EL0,		CGT_CNTHCTL_EL1PCTEN),
+	SR_TRAP(SYS_CNTPCTSS_EL0,	CGT_CNTHCTL_EL1PCTEN),
 };
 
 static DEFINE_XARRAY(sr_forward_xa);