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" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html