[RFC PATCH v2 1/6] KVM: PPC: Use getters and setters for vcpu register state

Nicholas Piggin npiggin at gmail.com
Wed Jun 7 17:51:59 AEST 2023


On Mon Jun 5, 2023 at 4:48 PM AEST, Jordan Niethe wrote:
> There are already some getter and setter functions used for accessing
> vcpu register state, e.g. kvmppc_get_pc(). There are also more
> complicated examples that are generated by macros like
> kvmppc_get_sprg0() which are generated by the SHARED_SPRNG_WRAPPER()
> macro.
>
> In the new PAPR API for nested guest partitions the L1 is required to
> communicate with the L0 to modify and read nested guest state.
>
> Prepare to support this by replacing direct accesses to vcpu register
> state with wrapper functions. Follow the existing pattern of using
> macros to generate individual wrappers. These wrappers will
> be augmented for supporting PAPR nested guests later.
>
> Signed-off-by: Jordan Niethe <jpn at linux.vnet.ibm.com>
> ---
>  arch/powerpc/include/asm/kvm_book3s.h  |  68 +++++++-
>  arch/powerpc/include/asm/kvm_ppc.h     |  48 ++++--
>  arch/powerpc/kvm/book3s.c              |  22 +--
>  arch/powerpc/kvm/book3s_64_mmu_hv.c    |   4 +-
>  arch/powerpc/kvm/book3s_64_mmu_radix.c |   9 +-
>  arch/powerpc/kvm/book3s_64_vio.c       |   4 +-
>  arch/powerpc/kvm/book3s_hv.c           | 222 +++++++++++++------------
>  arch/powerpc/kvm/book3s_hv.h           |  59 +++++++
>  arch/powerpc/kvm/book3s_hv_builtin.c   |  10 +-
>  arch/powerpc/kvm/book3s_hv_p9_entry.c  |   4 +-
>  arch/powerpc/kvm/book3s_hv_ras.c       |   5 +-
>  arch/powerpc/kvm/book3s_hv_rm_mmu.c    |   8 +-
>  arch/powerpc/kvm/book3s_hv_rm_xics.c   |   4 +-
>  arch/powerpc/kvm/book3s_xive.c         |   9 +-
>  arch/powerpc/kvm/powerpc.c             |   4 +-
>  15 files changed, 322 insertions(+), 158 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
> index bbf5e2c5fe09..4e91f54a3f9f 100644
> --- a/arch/powerpc/include/asm/kvm_book3s.h
> +++ b/arch/powerpc/include/asm/kvm_book3s.h
> @@ -392,6 +392,16 @@ static inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu)
>  	return vcpu->arch.regs.nip;
>  }
>  
> +static inline void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 val)
> +{
> +	vcpu->arch.pid = val;
> +}
> +
> +static inline u32 kvmppc_get_pid(struct kvm_vcpu *vcpu)
> +{
> +	return vcpu->arch.pid;
> +}
> +
>  static inline u64 kvmppc_get_msr(struct kvm_vcpu *vcpu);
>  static inline bool kvmppc_need_byteswap(struct kvm_vcpu *vcpu)
>  {
> @@ -403,10 +413,66 @@ static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
>  	return vcpu->arch.fault_dar;
>  }
>  
> +#define BOOK3S_WRAPPER_SET(reg, size)					\
> +static inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, u##size val)	\
> +{									\
> +									\
> +	vcpu->arch.reg = val;						\
> +}
> +
> +#define BOOK3S_WRAPPER_GET(reg, size)					\
> +static inline u##size kvmppc_get_##reg(struct kvm_vcpu *vcpu)		\
> +{									\
> +	return vcpu->arch.reg;						\
> +}
> +
> +#define BOOK3S_WRAPPER(reg, size)					\
> +	BOOK3S_WRAPPER_SET(reg, size)					\
> +	BOOK3S_WRAPPER_GET(reg, size)					\
> +
> +BOOK3S_WRAPPER(tar, 64)
> +BOOK3S_WRAPPER(ebbhr, 64)
> +BOOK3S_WRAPPER(ebbrr, 64)
> +BOOK3S_WRAPPER(bescr, 64)
> +BOOK3S_WRAPPER(ic, 64)
> +BOOK3S_WRAPPER(vrsave, 64)
> +
> +
> +#define VCORE_WRAPPER_SET(reg, size)					\
> +static inline void kvmppc_set_##reg ##_hv(struct kvm_vcpu *vcpu, u##size val)	\
> +{									\
> +	vcpu->arch.vcore->reg = val;					\
> +}
> +
> +#define VCORE_WRAPPER_GET(reg, size)					\
> +static inline u##size kvmppc_get_##reg ##_hv(struct kvm_vcpu *vcpu)	\
> +{									\
> +	return vcpu->arch.vcore->reg;					\
> +}
> +
> +#define VCORE_WRAPPER(reg, size)					\
> +	VCORE_WRAPPER_SET(reg, size)					\
> +	VCORE_WRAPPER_GET(reg, size)					\
> +
> +
> +VCORE_WRAPPER(vtb, 64)
> +VCORE_WRAPPER(tb_offset, 64)
> +VCORE_WRAPPER(lpcr, 64)

The general idea is fine, some of the names could use a bit of
improvement. What's a BOOK3S_WRAPPER for example, is it not a
VCPU_WRAPPER, or alternatively why isn't a VCORE_WRAPPER Book3S
as well?

> +
> +static inline u64 kvmppc_get_dec_expires(struct kvm_vcpu *vcpu)
> +{
> +	return vcpu->arch.dec_expires;
> +}
> +
> +static inline void kvmppc_set_dec_expires(struct kvm_vcpu *vcpu, u64 val)
> +{
> +	vcpu->arch.dec_expires = val;
> +}
> +
>  /* Expiry time of vcpu DEC relative to host TB */
>  static inline u64 kvmppc_dec_expires_host_tb(struct kvm_vcpu *vcpu)
>  {
> -	return vcpu->arch.dec_expires - vcpu->arch.vcore->tb_offset;
> +	return kvmppc_get_dec_expires(vcpu) - kvmppc_get_tb_offset_hv(vcpu);
>  }
>  
>  static inline bool is_kvmppc_resume_guest(int r)
> diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
> index 79a9c0bb8bba..fbac353ac46b 100644
> --- a/arch/powerpc/include/asm/kvm_ppc.h
> +++ b/arch/powerpc/include/asm/kvm_ppc.h
> @@ -936,7 +936,7 @@ static inline ulong kvmppc_get_##reg(struct kvm_vcpu *vcpu)		\
>  #define SPRNG_WRAPPER_SET(reg, bookehv_spr)				\
>  static inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, ulong val)	\
>  {									\
> -	mtspr(bookehv_spr, val);						\
> +	mtspr(bookehv_spr, val);					\
>  }									\
>  
>  #define SHARED_WRAPPER_GET(reg, size)					\

Stray hunk I think.

> @@ -957,10 +957,32 @@ static inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, u##size val)	\
>  	       vcpu->arch.shared->reg = cpu_to_le##size(val);		\
>  }									\
>  
> +#define SHARED_CACHE_WRAPPER_GET(reg, size)				\
> +static inline u##size kvmppc_get_##reg(struct kvm_vcpu *vcpu)		\
> +{									\
> +	if (kvmppc_shared_big_endian(vcpu))				\
> +	       return be##size##_to_cpu(vcpu->arch.shared->reg);	\
> +	else								\
> +	       return le##size##_to_cpu(vcpu->arch.shared->reg);	\
> +}									\
> +
> +#define SHARED_CACHE_WRAPPER_SET(reg, size)				\
> +static inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, u##size val)	\
> +{									\
> +	if (kvmppc_shared_big_endian(vcpu))				\
> +	       vcpu->arch.shared->reg = cpu_to_be##size(val);		\
> +	else								\
> +	       vcpu->arch.shared->reg = cpu_to_le##size(val);		\
> +}									\
> +
>  #define SHARED_WRAPPER(reg, size)					\
>  	SHARED_WRAPPER_GET(reg, size)					\
>  	SHARED_WRAPPER_SET(reg, size)					\
>  
> +#define SHARED_CACHE_WRAPPER(reg, size)					\
> +	SHARED_CACHE_WRAPPER_GET(reg, size)				\
> +	SHARED_CACHE_WRAPPER_SET(reg, size)				\

SHARED_CACHE_WRAPPER that does the same thing as SHARED_WRAPPER.

I know some of the names are a but crufty but it's probably a good time
to rethink them a bit.

KVMPPC_VCPU_SHARED_REG_ACCESSOR or something like that. A few
more keystrokes could help imensely.

> diff --git a/arch/powerpc/kvm/book3s_hv_p9_entry.c b/arch/powerpc/kvm/book3s_hv_p9_entry.c
> index 34f1db212824..34bc0a8a1288 100644
> --- a/arch/powerpc/kvm/book3s_hv_p9_entry.c
> +++ b/arch/powerpc/kvm/book3s_hv_p9_entry.c
> @@ -305,7 +305,7 @@ static void switch_mmu_to_guest_radix(struct kvm *kvm, struct kvm_vcpu *vcpu, u6
>  	u32 pid;
>  
>  	lpid = nested ? nested->shadow_lpid : kvm->arch.lpid;
> -	pid = vcpu->arch.pid;
> +	pid = kvmppc_get_pid(vcpu);
>  
>  	/*
>  	 * Prior memory accesses to host PID Q3 must be completed before we

Could add some accessors for get_lpid / get_guest_id which check for the
correct KVM mode maybe.

Thanks,
Nick


More information about the Linuxppc-dev mailing list