Re: [PATCH v2 2/7] arm64/fpsimd: Track the saved FPSIMD state type separately to TIF_SVE

2022-07-20 Thread Mark Brown
On Wed, Jul 20, 2022 at 10:40:03AM +0100, Marc Zyngier wrote:
> Mark Brown  wrote:

> > Yes, someone might forget to update the state type but my experience
> > with this code is that it's a lot easier to spot "this is writing new
> > state, did it update the state type?" than "this is writing new state,
> > did it call the helper that implicitly updates the state type or the
> > other one?".

> My experience in maintaining the KVM code is that the least state
> leaks outside of this sort of helpers, the least problematic they
> are. I'd rather have multiple helpers that have different *documented*
> behaviours than expecting the random hacker to know (or in this case,
> *guess*) when or not to add some extra state-twiddling. It also makes
> the code far more readable because it is self-contained.

> If this series is supposed to help making things more maintainable,
> then this is one way to do it.

There's nothing self contained going on, and based on what the users are
doing it isn't at all obvious to me that taking a copy of the data in
another format should be part of the same operation as deciding which
format should be the live data.  I'm all for helpers but between that
and the direct awareness the users already need to have of what's going
on I'm just not seeing that a combined convert and make active operation
is jumping out as something that should be a helper.


signature.asc
Description: PGP signature
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v2 2/7] arm64/fpsimd: Track the saved FPSIMD state type separately to TIF_SVE

2022-07-20 Thread Marc Zyngier
On Mon, 11 Jul 2022 16:53:43 +0100,
Mark Brown  wrote:
> 
> On Mon, Jul 11, 2022 at 03:33:51PM +0100, Marc Zyngier wrote:
> > Mark Brown  wrote:
> > > On Mon, Jul 11, 2022 at 10:40:50AM +0100, Marc Zyngier wrote:
> > > > Mark Brown  wrote:
> 
> > > > > + enum fp_state *type;
> 
> > > > For consistency: s/type/fp_type/ ?
> 
> > > Sure if nobody else wants a different bikeshed.  It really needs a
> > > longer name like fp_state_t or something but that had it's own problems
> > > with non-idiomaticness.
> 
> > I'm not talking about the name of the type, but about the name of the
> > member in the struct fpsimd_last_state_struct. I'd like it to be
> > homogeneous to the name you use in struct kvm_vcpu_arch. 'type' is way
> 
> Ah, sure I can do that.  I had thought this being in the FP last state
> structure made things clear here.
> 
> > > > > - thread_sm_enabled(>thread))
> > > > > + thread_sm_enabled(>thread)) {
> > > > >   sve_to_fpsimd(task);
> > > > > + task->thread.fp_type = FP_STATE_FPSIMD;
> 
> > > > Can you move this assignment into the sve_to_fpsimd() helper?
> 
> > > There are cases where we want a FPSIMD version of the state for
> > > reading but don't want to affect the actual state of the process
> > > (eg, if someone reads the FPSIMD registers via ptrace) so we don't
> > > want to change the active register state just because we converted
> > > it.  Adding another API that does the convert and update didn't feel
> > > like it was helping since you then have to remember which API does
> > > what and we already have lots of similarly named functions for
> > > slightly different contexts.
> 
> > I still think the state conversion should be self contained.
> > Sprinkling this context tracking is bound to end-up with a bug, while
> > documenting what is to be used when, or with a helper named
> > explicitly enough ("extract_fp_from_sve()" springs to mind) for
> > ptrace.
> 
> My experience trying to follow and update this code has been that
> layering on more helpers just shifts the potential for bugs around -
> it's easy to have the calling context using the wrong helper and looking
> correct, or to spend time cross checking if the helper in a particular
> context is the right one.  Sometimes this happens because something
> about the calling context changed rather than due to writing a new use.
> Yes, someone might forget to update the state type but my experience
> with this code is that it's a lot easier to spot "this is writing new
> state, did it update the state type?" than "this is writing new state,
> did it call the helper that implicitly updates the state type or the
> other one?".

My experience in maintaining the KVM code is that the least state
leaks outside of this sort of helpers, the least problematic they
are. I'd rather have multiple helpers that have different *documented*
behaviours than expecting the random hacker to know (or in this case,
*guess*) when or not to add some extra state-twiddling. It also makes
the code far more readable because it is self-contained.

If this series is supposed to help making things more maintainable,
then this is one way to do it.

M.

-- 
Without deviation from the norm, progress is not possible.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v2 2/7] arm64/fpsimd: Track the saved FPSIMD state type separately to TIF_SVE

2022-07-11 Thread Mark Brown
On Mon, Jul 11, 2022 at 03:33:51PM +0100, Marc Zyngier wrote:
> Mark Brown  wrote:
> > On Mon, Jul 11, 2022 at 10:40:50AM +0100, Marc Zyngier wrote:
> > > Mark Brown  wrote:

> > > > +   enum fp_state *type;

> > > For consistency: s/type/fp_type/ ?

> > Sure if nobody else wants a different bikeshed.  It really needs a
> > longer name like fp_state_t or something but that had it's own problems
> > with non-idiomaticness.

> I'm not talking about the name of the type, but about the name of the
> member in the struct fpsimd_last_state_struct. I'd like it to be
> homogeneous to the name you use in struct kvm_vcpu_arch. 'type' is way

Ah, sure I can do that.  I had thought this being in the FP last state
structure made things clear here.

> > > > -   thread_sm_enabled(>thread))
> > > > +   thread_sm_enabled(>thread)) {
> > > > sve_to_fpsimd(task);
> > > > +   task->thread.fp_type = FP_STATE_FPSIMD;

> > > Can you move this assignment into the sve_to_fpsimd() helper?

> > There are cases where we want a FPSIMD version of the state for
> > reading but don't want to affect the actual state of the process
> > (eg, if someone reads the FPSIMD registers via ptrace) so we don't
> > want to change the active register state just because we converted
> > it.  Adding another API that does the convert and update didn't feel
> > like it was helping since you then have to remember which API does
> > what and we already have lots of similarly named functions for
> > slightly different contexts.

> I still think the state conversion should be self contained.
> Sprinkling this context tracking is bound to end-up with a bug, while
> documenting what is to be used when, or with a helper named
> explicitly enough ("extract_fp_from_sve()" springs to mind) for
> ptrace.

My experience trying to follow and update this code has been that
layering on more helpers just shifts the potential for bugs around -
it's easy to have the calling context using the wrong helper and looking
correct, or to spend time cross checking if the helper in a particular
context is the right one.  Sometimes this happens because something
about the calling context changed rather than due to writing a new use.
Yes, someone might forget to update the state type but my experience
with this code is that it's a lot easier to spot "this is writing new
state, did it update the state type?" than "this is writing new state,
did it call the helper that implicitly updates the state type or the
other one?".

Since these callers are already explicitly peering into the data in one
form or another (like reading or writing the actual register values, and
including for some checking the type information) it seems reasonable
for them to also be doing updates to the type selection explicitly.  It
does also make the error handling a little neater, if we are switching
between state types then in the case of error we just leave things using
the old, unmodified state.


signature.asc
Description: PGP signature
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v2 2/7] arm64/fpsimd: Track the saved FPSIMD state type separately to TIF_SVE

2022-07-11 Thread Marc Zyngier
On Mon, 11 Jul 2022 12:39:51 +0100,
Mark Brown  wrote:
> 
> [1  ]
> On Mon, Jul 11, 2022 at 10:40:50AM +0100, Marc Zyngier wrote:
> > Mark Brown  wrote:
> 
> > > + enum fp_state *type;
> 
> > For consistency: s/type/fp_type/ ?
> 
> Sure if nobody else wants a different bikeshed.  It really needs a
> longer name like fp_state_t or something but that had it's own problems
> with non-idiomaticness.

I'm not talking about the name of the type, but about the name of the
member in the struct fpsimd_last_state_struct. I'd like it to be
homogeneous to the name you use in struct kvm_vcpu_arch. 'type' is way
too vague a name, and maybe it should be fp_reg_type, as that's what
it actually indicates.

> 
> > >   if (test_and_clear_tsk_thread_flag(task, TIF_SVE) ||
> > > - thread_sm_enabled(>thread))
> > > + thread_sm_enabled(>thread)) {
> > >   sve_to_fpsimd(task);
> > > + task->thread.fp_type = FP_STATE_FPSIMD;
> 
> > Can you move this assignment into the sve_to_fpsimd() helper?
> 
> There are cases where we want a FPSIMD version of the state for
> reading but don't want to affect the actual state of the process
> (eg, if someone reads the FPSIMD registers via ptrace) so we don't
> want to change the active register state just because we converted
> it.  Adding another API that does the convert and update didn't feel
> like it was helping since you then have to remember which API does
> what and we already have lots of similarly named functions for
> slightly different contexts.

I still think the state conversion should be self contained.
Sprinkling this context tracking is bound to end-up with a bug, while
documenting what is to be used when, or with a helper named
explicitly enough ("extract_fp_from_sve()" springs to mind) for
ptrace.

> > >   } else {
> > >   fpsimd_to_sve(current);
> > > + current->thread.fp_type = FP_STATE_SVE;
> 
> > Same thing here.
> 
> There's not the same issue with reading FPSIMD state via the SVE APIs
> but for consistency it seems best to always leave these updates in the
> callers.

I disagree again. I really want these things to be self-contained, and
be able to reason about what they do from their name and the arguments
they take (and even some documentation). Relying on some extra updates
adds complexity to a difficult part of the kernel, and an even more
difficult part of the architecture.

Thanks,

M.

-- 
Without deviation from the norm, progress is not possible.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v2 2/7] arm64/fpsimd: Track the saved FPSIMD state type separately to TIF_SVE

2022-07-11 Thread Mark Brown
On Mon, Jul 11, 2022 at 10:40:50AM +0100, Marc Zyngier wrote:
> Mark Brown  wrote:

> > +   enum fp_state *type;

> For consistency: s/type/fp_type/ ?

Sure if nobody else wants a different bikeshed.  It really needs a
longer name like fp_state_t or something but that had it's own problems
with non-idiomaticness.

> > if (test_and_clear_tsk_thread_flag(task, TIF_SVE) ||
> > -   thread_sm_enabled(>thread))
> > +   thread_sm_enabled(>thread)) {
> > sve_to_fpsimd(task);
> > +   task->thread.fp_type = FP_STATE_FPSIMD;

> Can you move this assignment into the sve_to_fpsimd() helper?

There are cases where we want a FPSIMD version of the state for reading
but don't want to affect the actual state of the process (eg, if someone
reads the FPSIMD registers via ptrace) so we don't want to change the
active register state just because we converted it.  Adding another API
that does the convert and update didn't feel like it was helping since
you then have to remember which API does what and we already have lots
of similarly named functions for slightly different contexts.

> > } else {
> > fpsimd_to_sve(current);
> > +   current->thread.fp_type = FP_STATE_SVE;

> Same thing here.

There's not the same issue with reading FPSIMD state via the SVE APIs
but for consistency it seems best to always leave these updates in the
callers.

> > --- a/arch/arm64/kernel/ptrace.c
> > +++ b/arch/arm64/kernel/ptrace.c
> > @@ -892,8 +892,7 @@ static int sve_set_common(struct task_struct *target,
> > ret = __fpr_set(target, regset, pos, count, kbuf, ubuf,
> > SVE_PT_FPSIMD_OFFSET);
> > clear_tsk_thread_flag(target, TIF_SVE);
> > -   if (type == ARM64_VEC_SME)
> > -   fpsimd_force_sync_to_sve(target);

> I don't get this particular change. Can you please clarify?

That should probably be shifted to a later patch in the series, I think
I just rebased it to the wrong place.


signature.asc
Description: PGP signature
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v2 2/7] arm64/fpsimd: Track the saved FPSIMD state type separately to TIF_SVE

2022-07-11 Thread Marc Zyngier
On Mon, 20 Jun 2022 13:41:53 +0100,
Mark Brown  wrote:
> 
> When we save the state for the floating point registers this can be done
> in the form visible through either the FPSIMD V registers or the SVE Z and
> P registers. At present we track which format is currently used based on
> TIF_SVE and the SME streaming mode state but particularly in the SVE case
> this limits our options for optimising things, especially around syscalls.
> Introduce a new enum in thread_struct which explicitly states which format
> is active and keep it up to date when we change it.
> 
> At present we do not use this state except to verify that it has the
> expected value when loading the state, future patches will introduce
> functional changes.
> 
> Signed-off-by: Mark Brown 
> ---
>  arch/arm64/include/asm/fpsimd.h|  2 +-
>  arch/arm64/include/asm/kvm_host.h  |  1 +
>  arch/arm64/include/asm/processor.h |  6 
>  arch/arm64/kernel/fpsimd.c | 57 ++
>  arch/arm64/kernel/process.c|  2 ++
>  arch/arm64/kernel/ptrace.c |  6 ++--
>  arch/arm64/kernel/signal.c |  3 ++
>  arch/arm64/kvm/fpsimd.c|  3 +-
>  8 files changed, 61 insertions(+), 19 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
> index 847fd119cdb8..5762419fdcc0 100644
> --- a/arch/arm64/include/asm/fpsimd.h
> +++ b/arch/arm64/include/asm/fpsimd.h
> @@ -61,7 +61,7 @@ extern void fpsimd_kvm_prepare(void);
>  extern void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *state,
>void *sve_state, unsigned int sve_vl,
>void *za_state, unsigned int sme_vl,
> -  u64 *svcr);
> +  u64 *svcr, enum fp_state *type);
>  
>  extern void fpsimd_flush_task_state(struct task_struct *target);
>  extern void fpsimd_save_and_flush_cpu_state(void);
> diff --git a/arch/arm64/include/asm/kvm_host.h 
> b/arch/arm64/include/asm/kvm_host.h
> index de32152cea04..250e23f221c4 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -310,6 +310,7 @@ struct kvm_vcpu_arch {
>   void *sve_state;
>   unsigned int sve_max_vl;
>   u64 svcr;
> + enum fp_state fp_type;
>  
>   /* Stage 2 paging state used by the hardware on next switch */
>   struct kvm_s2_mmu *hw_mmu;
> diff --git a/arch/arm64/include/asm/processor.h 
> b/arch/arm64/include/asm/processor.h
> index 9e58749db21d..192986509a8e 100644
> --- a/arch/arm64/include/asm/processor.h
> +++ b/arch/arm64/include/asm/processor.h
> @@ -122,6 +122,11 @@ enum vec_type {
>   ARM64_VEC_MAX,
>  };
>  
> +enum fp_state {
> + FP_STATE_FPSIMD,
> + FP_STATE_SVE,
> +};
> +
>  struct cpu_context {
>   unsigned long x19;
>   unsigned long x20;
> @@ -152,6 +157,7 @@ struct thread_struct {
>   struct user_fpsimd_state fpsimd_state;
>   } uw;
>  
> + enum fp_state   fp_type;/* registers FPSIMD or SVE? */
>   unsigned intfpsimd_cpu;
>   void*sve_state; /* SVE registers, if any */
>   void*za_state;  /* ZA register, if any */
> diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
> index d67e658f1e24..fdb2925becdf 100644
> --- a/arch/arm64/kernel/fpsimd.c
> +++ b/arch/arm64/kernel/fpsimd.c
> @@ -125,6 +125,7 @@ struct fpsimd_last_state_struct {
>   u64 *svcr;
>   unsigned int sve_vl;
>   unsigned int sme_vl;
> + enum fp_state *type;

For consistency: s/type/fp_type/ ?

>  };
>  
>  static DEFINE_PER_CPU(struct fpsimd_last_state_struct, fpsimd_last_state);
> @@ -330,15 +331,6 @@ void task_set_vl_onexec(struct task_struct *task, enum 
> vec_type type,
>   *The task can execute SVE instructions while in userspace without
>   *trapping to the kernel.
>   *
> - *When stored, Z0-Z31 (incorporating Vn in bits[127:0] or the
> - *corresponding Zn), P0-P15 and FFR are encoded in
> - *task->thread.sve_state, formatted appropriately for vector
> - *length task->thread.sve_vl or, if SVCR.SM is set,
> - *task->thread.sme_vl.
> - *
> - *task->thread.sve_state must point to a valid buffer at least
> - *sve_state_size(task) bytes in size.
> - *
>   *During any syscall, the kernel may optionally clear TIF_SVE and
>   *discard the vector state except for the FPSIMD subset.
>   *
> @@ -348,7 +340,15 @@ void task_set_vl_onexec(struct task_struct *task, enum 
> vec_type type,
>   *do_sve_acc() to be called, which does some preparation and then
>   *sets TIF_SVE.
>   *
> - *When stored, FPSIMD registers V0-V31 are encoded in
> + * During any syscall, the kernel may optionally clear TIF_SVE and
> + * discard the vector state except for the FPSIMD subset.
> + *
> + * The data will be stored in one of two formats:
> + *
> + *  * FPSIMD only - FP_STATE_FPSIMD:
> 

[PATCH v2 2/7] arm64/fpsimd: Track the saved FPSIMD state type separately to TIF_SVE

2022-06-20 Thread Mark Brown
When we save the state for the floating point registers this can be done
in the form visible through either the FPSIMD V registers or the SVE Z and
P registers. At present we track which format is currently used based on
TIF_SVE and the SME streaming mode state but particularly in the SVE case
this limits our options for optimising things, especially around syscalls.
Introduce a new enum in thread_struct which explicitly states which format
is active and keep it up to date when we change it.

At present we do not use this state except to verify that it has the
expected value when loading the state, future patches will introduce
functional changes.

Signed-off-by: Mark Brown 
---
 arch/arm64/include/asm/fpsimd.h|  2 +-
 arch/arm64/include/asm/kvm_host.h  |  1 +
 arch/arm64/include/asm/processor.h |  6 
 arch/arm64/kernel/fpsimd.c | 57 ++
 arch/arm64/kernel/process.c|  2 ++
 arch/arm64/kernel/ptrace.c |  6 ++--
 arch/arm64/kernel/signal.c |  3 ++
 arch/arm64/kvm/fpsimd.c|  3 +-
 8 files changed, 61 insertions(+), 19 deletions(-)

diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index 847fd119cdb8..5762419fdcc0 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -61,7 +61,7 @@ extern void fpsimd_kvm_prepare(void);
 extern void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *state,
 void *sve_state, unsigned int sve_vl,
 void *za_state, unsigned int sme_vl,
-u64 *svcr);
+u64 *svcr, enum fp_state *type);
 
 extern void fpsimd_flush_task_state(struct task_struct *target);
 extern void fpsimd_save_and_flush_cpu_state(void);
diff --git a/arch/arm64/include/asm/kvm_host.h 
b/arch/arm64/include/asm/kvm_host.h
index de32152cea04..250e23f221c4 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -310,6 +310,7 @@ struct kvm_vcpu_arch {
void *sve_state;
unsigned int sve_max_vl;
u64 svcr;
+   enum fp_state fp_type;
 
/* Stage 2 paging state used by the hardware on next switch */
struct kvm_s2_mmu *hw_mmu;
diff --git a/arch/arm64/include/asm/processor.h 
b/arch/arm64/include/asm/processor.h
index 9e58749db21d..192986509a8e 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -122,6 +122,11 @@ enum vec_type {
ARM64_VEC_MAX,
 };
 
+enum fp_state {
+   FP_STATE_FPSIMD,
+   FP_STATE_SVE,
+};
+
 struct cpu_context {
unsigned long x19;
unsigned long x20;
@@ -152,6 +157,7 @@ struct thread_struct {
struct user_fpsimd_state fpsimd_state;
} uw;
 
+   enum fp_state   fp_type;/* registers FPSIMD or SVE? */
unsigned intfpsimd_cpu;
void*sve_state; /* SVE registers, if any */
void*za_state;  /* ZA register, if any */
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index d67e658f1e24..fdb2925becdf 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -125,6 +125,7 @@ struct fpsimd_last_state_struct {
u64 *svcr;
unsigned int sve_vl;
unsigned int sme_vl;
+   enum fp_state *type;
 };
 
 static DEFINE_PER_CPU(struct fpsimd_last_state_struct, fpsimd_last_state);
@@ -330,15 +331,6 @@ void task_set_vl_onexec(struct task_struct *task, enum 
vec_type type,
  *The task can execute SVE instructions while in userspace without
  *trapping to the kernel.
  *
- *When stored, Z0-Z31 (incorporating Vn in bits[127:0] or the
- *corresponding Zn), P0-P15 and FFR are encoded in
- *task->thread.sve_state, formatted appropriately for vector
- *length task->thread.sve_vl or, if SVCR.SM is set,
- *task->thread.sme_vl.
- *
- *task->thread.sve_state must point to a valid buffer at least
- *sve_state_size(task) bytes in size.
- *
  *During any syscall, the kernel may optionally clear TIF_SVE and
  *discard the vector state except for the FPSIMD subset.
  *
@@ -348,7 +340,15 @@ void task_set_vl_onexec(struct task_struct *task, enum 
vec_type type,
  *do_sve_acc() to be called, which does some preparation and then
  *sets TIF_SVE.
  *
- *When stored, FPSIMD registers V0-V31 are encoded in
+ * During any syscall, the kernel may optionally clear TIF_SVE and
+ * discard the vector state except for the FPSIMD subset.
+ *
+ * The data will be stored in one of two formats:
+ *
+ *  * FPSIMD only - FP_STATE_FPSIMD:
+ *
+ *When the FPSIMD only state stored task->thread.fp_type is set to
+ *FP_STATE_FPSIMD, the FPSIMD registers V0-V31 are encoded in
  *task->thread.uw.fpsimd_state; bits [max : 128] for each of Z0-Z31 are
  *logically zero but not stored anywhere; P0-P15 and