Re: [PATCH v4 1/3] KVM: PPC: Book3S: Get/set guest SPRs using the GET/SET_ONE_REG interface

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 25.09.2012, at 11:44, Paul Mackerras wrote:

> This enables userspace to get and set various SPRs (special-purpose
> registers) using the KVM_[GS]ET_ONE_REG ioctls.  With this, userspace
> can get and set all the SPRs that are part of the guest state, either
> through the KVM_[GS]ET_REGS ioctls, the KVM_[GS]ET_SREGS ioctls, or
> the KVM_[GS]ET_ONE_REG ioctls.
> 
> The SPRs that are added here are:
> 
> - DABR:  Data address breakpoint register
> - DSCR:  Data stream control register
> - PURR:  Processor utilization of resources register
> - SPURR: Scaled PURR
> - DAR:   Data address register
> - DSISR: Data storage interrupt status register
> - AMR:   Authority mask register
> - UAMOR: User authority mask override register
> - MMCR0, MMCR1, MMCRA: Performance monitor unit control registers
> - PMC1..PMC8: Performance monitor unit counter registers
> 
> In order to reduce code duplication between PR and HV KVM code, this
> moves the kvm_vcpu_ioctl_[gs]et_one_reg functions into book3s.c and
> centralizes the copying between user and kernel space there.  The
> registers that are handled differently between PR and HV, and those
> that exist only in one flavor, are handled in kvmppc_[gs]et_one_reg()
> functions that are specific to each flavor.
> 
> Signed-off-by: Paul Mackerras <paulus@xxxxxxxxx>
> ---
> v4: define and use set_one_reg/get_one_reg macros
> 
> Documentation/virtual/kvm/api.txt  |   19 +++++++++
> arch/powerpc/include/asm/kvm.h     |   21 ++++++++++
> arch/powerpc/include/asm/kvm_ppc.h |   30 ++++++++++++++
> arch/powerpc/kvm/book3s.c          |   68 ++++++++++++++++++++++++++++++++
> arch/powerpc/kvm/book3s_hv.c       |   76 ++++++++++++++++++++++++++++++------
> arch/powerpc/kvm/book3s_pr.c       |   23 ++++++-----
> 6 files changed, 213 insertions(+), 24 deletions(-)
> 
> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> index a12f4e4..407556f 100644
> --- a/Documentation/virtual/kvm/api.txt
> +++ b/Documentation/virtual/kvm/api.txt
> @@ -1740,6 +1740,25 @@ registers, find a list below:
>   PPC   | KVM_REG_PPC_IAC4      | 64
>   PPC   | KVM_REG_PPC_DAC1      | 64
>   PPC   | KVM_REG_PPC_DAC2      | 64
> +  PPC   | KVM_REG_PPC_DABR      | 64
> +  PPC   | KVM_REG_PPC_DSCR      | 64
> +  PPC   | KVM_REG_PPC_PURR      | 64
> +  PPC   | KVM_REG_PPC_SPURR     | 64
> +  PPC   | KVM_REG_PPC_DAR       | 64
> +  PPC   | KVM_REG_PPC_DSISR	| 32
> +  PPC   | KVM_REG_PPC_AMR       | 64
> +  PPC   | KVM_REG_PPC_UAMOR     | 64
> +  PPC   | KVM_REG_PPC_MMCR0     | 64
> +  PPC   | KVM_REG_PPC_MMCR1     | 64
> +  PPC   | KVM_REG_PPC_MMCRA     | 64
> +  PPC   | KVM_REG_PPC_PMC1      | 32
> +  PPC   | KVM_REG_PPC_PMC2      | 32
> +  PPC   | KVM_REG_PPC_PMC3      | 32
> +  PPC   | KVM_REG_PPC_PMC4      | 32
> +  PPC   | KVM_REG_PPC_PMC5      | 32
> +  PPC   | KVM_REG_PPC_PMC6      | 32
> +  PPC   | KVM_REG_PPC_PMC7      | 32
> +  PPC   | KVM_REG_PPC_PMC8      | 32
> 
> 4.69 KVM_GET_ONE_REG
> 
> diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h
> index 3c14202..9557576 100644
> --- a/arch/powerpc/include/asm/kvm.h
> +++ b/arch/powerpc/include/asm/kvm.h
> @@ -338,5 +338,26 @@ struct kvm_book3e_206_tlb_params {
> #define KVM_REG_PPC_IAC4	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x5)
> #define KVM_REG_PPC_DAC1	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x6)
> #define KVM_REG_PPC_DAC2	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x7)
> +#define KVM_REG_PPC_DABR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8)
> +#define KVM_REG_PPC_DSCR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x9)
> +#define KVM_REG_PPC_PURR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa)
> +#define KVM_REG_PPC_SPURR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb)
> +#define KVM_REG_PPC_DAR		(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc)
> +#define KVM_REG_PPC_DSISR	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd)
> +#define KVM_REG_PPC_AMR		(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xe)
> +#define KVM_REG_PPC_UAMOR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xf)
> +
> +#define KVM_REG_PPC_MMCR0	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x10)
> +#define KVM_REG_PPC_MMCR1	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x11)
> +#define KVM_REG_PPC_MMCRA	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x12)
> +
> +#define KVM_REG_PPC_PMC1	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x18)
> +#define KVM_REG_PPC_PMC2	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x19)
> +#define KVM_REG_PPC_PMC3	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1a)
> +#define KVM_REG_PPC_PMC4	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1b)
> +#define KVM_REG_PPC_PMC5	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1c)
> +#define KVM_REG_PPC_PMC6	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1d)
> +#define KVM_REG_PPC_PMC7	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1e)
> +#define KVM_REG_PPC_PMC8	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1f)
> 
> #endif /* __LINUX_KVM_POWERPC_H */
> diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
> index 3fb980d..a460f024 100644
> --- a/arch/powerpc/include/asm/kvm_ppc.h
> +++ b/arch/powerpc/include/asm/kvm_ppc.h
> @@ -28,6 +28,7 @@
> #include <linux/types.h>
> #include <linux/kvm_types.h>
> #include <linux/kvm_host.h>
> +#include <linux/bug.h>
> #ifdef CONFIG_PPC_BOOK3S
> #include <asm/kvm_book3s.h>
> #else
> @@ -196,6 +197,33 @@ static inline u32 kvmppc_set_field(u64 inst, int msb, int lsb, int value)
> 	return r;
> }
> 
> +union kvmppc_one_reg {
> +	u32	wval;
> +	u64	dval;
> +};
> +
> +#define one_reg_size(id)	\
> +	(1ul << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
> +
> +#define get_one_reg(id, val, reg)	do {	\
> +	switch (one_reg_size(id)) {		\
> +	case 4: (val).wval = (reg); break;	\
> +	case 8: (val).dval = (reg); break;	\
> +	default: BUG();				\
> +	}					\
> +} while (0)
> +
> +#define set_one_reg(id, val, reg)	do {	\
> +	switch (one_reg_size(id)) {		\
> +	case 4: (reg) = (val).wval; break;	\
> +	case 8: (reg) = (val).dval; break;	\
> +	default: BUG();				\
> +	}					\
> +} while (0)
> +
> +extern void get_one_reg_called_with_bad_size(void);
> +extern void set_one_reg_called_with_bad_size(void);
> +
> void kvmppc_core_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
> int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
> 
> @@ -204,6 +232,8 @@ int kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
> 
> int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg);
> int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg);
> +int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *);
> +int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *);
> 
> void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid);
> 
> diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
> index e946665..0ebf03b 100644
> --- a/arch/powerpc/kvm/book3s.c
> +++ b/arch/powerpc/kvm/book3s.c
> @@ -485,6 +485,74 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
> 	return -ENOTSUPP;
> }
> 
> +int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
> +{
> +	int r;
> +	union kvmppc_one_reg val;
> +	int size;
> +
> +	size = one_reg_size(reg->id);
> +	if (size > sizeof(val))
> +		return -EINVAL;
> +
> +	r = kvmppc_get_one_reg(vcpu, reg->id, &val);
> +
> +	if (r == -EINVAL) {
> +		r = 0;
> +		switch (reg->id) {
> +		case KVM_REG_PPC_DAR:
> +			get_one_reg(reg->id, val, vcpu->arch.shared->dar);

This doesn't look all as obvious as I had hoped. Do you think it's possible to cpp away something like

val = get_reg_val(reg->id, vcpu->arch.shared->dar);

? That way things would become a lot more obvious. If not, no worries, the rest looks good. I would apply it as is already, but if we could get this one a bit nicer, we might be able to set a good precedence for following code.


Alex

--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM Development]     [KVM ARM]     [KVM ia64]     [Linux Virtualization]     [Linux USB Devel]     [Linux Video]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux