From patchwork Wed Sep 12 00:18:10 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Mackerras X-Patchwork-Id: 183218 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id B45BC2C0092 for ; Wed, 12 Sep 2012 10:19:45 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752176Ab2ILATD (ORCPT ); Tue, 11 Sep 2012 20:19:03 -0400 Received: from ozlabs.org ([203.10.76.45]:58298 "EHLO ozlabs.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751342Ab2ILATB (ORCPT ); Tue, 11 Sep 2012 20:19:01 -0400 Received: by ozlabs.org (Postfix, from userid 1003) id C81BE2C0092; Wed, 12 Sep 2012 10:19:00 +1000 (EST) Date: Wed, 12 Sep 2012 10:18:10 +1000 From: Paul Mackerras To: Alexander Graf Cc: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org Subject: [PATCH 1/2] KVM: PPC: Book3S HV: Get/set guest SPRs using the GET/SET_ONE_REG interface Message-ID: <20120912001810.GF32642@bloggs.ozlabs.ibm.com> References: <20120912001719.GE32642@bloggs.ozlabs.ibm.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20120912001719.GE32642@bloggs.ozlabs.ibm.com> User-Agent: Mutt/1.5.21 (2010-09-15) Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org 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 Signed-off-by: Paul Mackerras --- arch/powerpc/include/asm/kvm.h | 21 ++++++++ arch/powerpc/kvm/book3s_hv.c | 106 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) 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/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 83e929e..7fe5c9a 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -538,11 +538,53 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) { int r = -EINVAL; + long int i; switch (reg->id) { case KVM_REG_PPC_HIOR: r = put_user(0, (u64 __user *)reg->addr); break; + case KVM_REG_PPC_DABR: + r = put_user(vcpu->arch.dabr, (u64 __user *)reg->addr); + break; + case KVM_REG_PPC_DSCR: + r = put_user(vcpu->arch.dscr, (u64 __user *)reg->addr); + break; + case KVM_REG_PPC_PURR: + r = put_user(vcpu->arch.purr, (u64 __user *)reg->addr); + break; + case KVM_REG_PPC_SPURR: + r = put_user(vcpu->arch.spurr, (u64 __user *)reg->addr); + break; + case KVM_REG_PPC_DAR: + r = put_user(vcpu->arch.shregs.dar, (u64 __user *)reg->addr); + break; + case KVM_REG_PPC_DSISR: + r = put_user(vcpu->arch.shregs.dsisr, (u32 __user *)reg->addr); + break; + case KVM_REG_PPC_AMR: + r = put_user(vcpu->arch.amr, (u64 __user *)reg->addr); + break; + case KVM_REG_PPC_UAMOR: + r = put_user(vcpu->arch.uamor, (u64 __user *)reg->addr); + break; + case KVM_REG_PPC_MMCR0: + case KVM_REG_PPC_MMCR1: + case KVM_REG_PPC_MMCRA: + i = reg->id - KVM_REG_PPC_MMCR0; + r = put_user(vcpu->arch.mmcr[i], (u64 __user *)reg->addr); + break; + case KVM_REG_PPC_PMC1: + case KVM_REG_PPC_PMC2: + case KVM_REG_PPC_PMC3: + case KVM_REG_PPC_PMC4: + case KVM_REG_PPC_PMC5: + case KVM_REG_PPC_PMC6: + case KVM_REG_PPC_PMC7: + case KVM_REG_PPC_PMC8: + i = reg->id - KVM_REG_PPC_PMC1; + r = put_user(vcpu->arch.pmc[i], (u32 __user *)reg->addr); + break; default: break; } @@ -553,6 +595,9 @@ 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 r = -EINVAL; + u64 val; + u32 wval; + long int i; switch (reg->id) { case KVM_REG_PPC_HIOR: @@ -564,6 +609,67 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) r = -EINVAL; break; } + case KVM_REG_PPC_DABR: + r = get_user(val, (u64 __user *)reg->addr); + if (!r) + vcpu->arch.dabr = val; + break; + case KVM_REG_PPC_DSCR: + r = get_user(val, (u64 __user *)reg->addr); + if (!r) + vcpu->arch.dscr = val; + break; + case KVM_REG_PPC_PURR: + r = get_user(val, (u64 __user *)reg->addr); + if (!r) + vcpu->arch.purr = val; + break; + case KVM_REG_PPC_SPURR: + r = get_user(val, (u64 __user *)reg->addr); + if (!r) + vcpu->arch.spurr = val; + break; + case KVM_REG_PPC_DAR: + r = get_user(val, (u64 __user *)reg->addr); + if (!r) + vcpu->arch.shregs.dar = val; + break; + case KVM_REG_PPC_DSISR: + r = get_user(wval, (u32 __user *)reg->addr); + if (!r) + vcpu->arch.shregs.dsisr = wval; + break; + case KVM_REG_PPC_AMR: + r = get_user(val, (u64 __user *)reg->addr); + if (!r) + vcpu->arch.amr = val; + break; + case KVM_REG_PPC_UAMOR: + r = get_user(val, (u64 __user *)reg->addr); + if (!r) + vcpu->arch.uamor = val; + break; + case KVM_REG_PPC_MMCR0: + case KVM_REG_PPC_MMCR1: + case KVM_REG_PPC_MMCRA: + i = reg->id - KVM_REG_PPC_MMCR0; + r = get_user(val, (u64 __user *)reg->addr); + if (!r) + vcpu->arch.mmcr[i] = val; + break; + case KVM_REG_PPC_PMC1: + case KVM_REG_PPC_PMC2: + case KVM_REG_PPC_PMC3: + case KVM_REG_PPC_PMC4: + case KVM_REG_PPC_PMC5: + case KVM_REG_PPC_PMC6: + case KVM_REG_PPC_PMC7: + case KVM_REG_PPC_PMC8: + i = reg->id - KVM_REG_PPC_PMC1; + r = get_user(wval, (u32 __user *)reg->addr); + if (!r) + vcpu->arch.pmc[i] = wval; + break; default: break; }