[PATCH v10 4/5] KVM: arm64: Reuse fields of sys_reg_desc for idreg

Oliver Upton oliver.upton at linux.dev
Fri May 26 14:37:04 PDT 2023


Hi Jing,

On Mon, May 22, 2023 at 10:18:34PM +0000, Jing Zhang wrote:
> Since reset() and val are not used for idreg in sys_reg_desc, they would
> be used with other purposes for idregs.
> The callback reset() would be used to return KVM sanitised id register
> values. The u64 val would be used as mask for writable fields in idregs.
> Only bits with 1 in val are writable from userspace.

The tense of the changelog is wrong (should be in an imperative mood).
Maybe something like:

  sys_reg_desc::{reset, val} are presently unused for ID register
  descriptors. Repurpose these fields to support user-configurable ID
  registers.

  Use the ::reset() function pointer to return the sanitised value of a
  given ID register, optionally with KVM-specific feature sanitisation.
  Additionally, keep a mask of writable register fields in ::val.

> Signed-off-by: Jing Zhang <jingzhangos at google.com>
> ---
>  arch/arm64/kvm/sys_regs.c | 101 +++++++++++++++++++++++++++-----------
>  arch/arm64/kvm/sys_regs.h |  15 ++++--
>  2 files changed, 82 insertions(+), 34 deletions(-)
> 

[...]

> +/*
> + * Since reset() callback and field val are not used for idregs, they will be
> + * used for specific purposes for idregs.
> + * The reset() would return KVM sanitised register value. The value would be the
> + * same as the host kernel sanitised value if there is no KVM sanitisation.
> + * The val would be used as a mask indicating writable fields for the idreg.
> + * Only bits with 1 are writable from userspace. This mask might not be
> + * necessary in the future whenever all ID registers are enabled as writable
> + * from userspace.
> + */
> +
>  /* sys_reg_desc initialiser for known cpufeature ID registers */
>  #define ID_SANITISED(name) {			\
>  	SYS_DESC(SYS_##name),			\
> @@ -1751,6 +1788,8 @@ static unsigned int elx2_visibility(const struct kvm_vcpu *vcpu,
>  	.get_user = get_id_reg,			\
>  	.set_user = set_id_reg,			\
>  	.visibility = id_visibility,		\
> +	.reset = general_read_kvm_sanitised_reg,\
> +	.val = 0,				\

I generally think unions are more trouble than they're worth, but it
might make sense to throw the fields with dual meaning into one, like

  struct sys_reg_desc {

  	[...]
	union {
		struct {
			void (*reset)(struct kvm_vcpu *, const struct sys_reg_desc *);
			u64 val;
		};
		struct {
			u64 (*read_sanitised)(struct kvm_vcpu *vcpu, const struct sys_reg_desc *);
			u64 mask;
		};
	};
  }

You could then avoid repainting the world to handle ->reset() returning
a value and usage of the fields in an id register context become a bit
more self-documenting. And you get to play with fire while you do it!

Let's see if the other side of the pond agrees with my bikeshedding...

-- 
Thanks,
Oliver



More information about the linux-arm-kernel mailing list