From patchwork Tue Mar 21 11:05:29 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoffer Dall X-Patchwork-Id: 9636393 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 6DDF960328 for ; Tue, 21 Mar 2017 11:06:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6E8BD27F07 for ; Tue, 21 Mar 2017 11:06:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6358B28329; Tue, 21 Mar 2017 11:06:08 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 20D5228338 for ; Tue, 21 Mar 2017 11:06:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757017AbdCULFu (ORCPT ); Tue, 21 Mar 2017 07:05:50 -0400 Received: from mail-wm0-f47.google.com ([74.125.82.47]:38009 "EHLO mail-wm0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756962AbdCULFo (ORCPT ); Tue, 21 Mar 2017 07:05:44 -0400 Received: by mail-wm0-f47.google.com with SMTP id t189so9534296wmt.1 for ; Tue, 21 Mar 2017 04:05:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=qAIkR/EaLRaPSupBaMZduJ/M/XZ89SYIZ/EumT66aTw=; b=aqXjbwgYosWExAuWIhboHcp/+v+AeINvN4toV6w8wb4aKCoDsHloVdKleIwyRMWq2r Snoh2c4Sii0v2+rsYwqjryfhepDWtNvBar2pqdBTmMaV67sC7O/wo34V0U27L7o96U/e u1AXRulLGPNKPQJ0q0tNW793XfVVZ2woQ9yVE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=qAIkR/EaLRaPSupBaMZduJ/M/XZ89SYIZ/EumT66aTw=; b=KfbKAmVtNx+AmgwsJnB/PUfHBVyHlrRBcusPdLGioJOLKvDm2Jmh0bpWp+5z9BlxI2 dYVN4AEARV5QM9mRjjyEs/trs4GsX1eXCgonEZPKf3JHXngf1oBXZ299gfnfOkKgPl5n IPuyS3TAEWAwRZ9S3Qq5zB1shH32ylpRNrQZtkgKARR7ITMQEU9Mt33BrZcHceLUwZz+ k8Nq0LUwEcC/UubYwBumD3v+CWN82D+zxI1xOBWVMtdbyNefQuDXlIpiTuxrDEmYoZ1U 3DtShImQjSVjMSZKCjJ3nAW4YIANArdRN2X7/10RDe1Q/etPrd6845bal8wQFGl8QjcR 6Q2A== X-Gm-Message-State: AFeK/H25Mb5lMKMVw8EDb/iOXz4CCNeqBQ9HOcFAV+XUkLIFx6mnSF8CJLgpNVTBkJuKp98l X-Received: by 10.28.37.135 with SMTP id l129mr2086600wml.49.1490094342190; Tue, 21 Mar 2017 04:05:42 -0700 (PDT) Received: from localhost.localdomain (xd93ddc2d.cust.hiper.dk. [217.61.220.45]) by smtp.gmail.com with ESMTPSA id f48sm24358252wrf.17.2017.03.21.04.05.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 21 Mar 2017 04:05:41 -0700 (PDT) From: Christoffer Dall To: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org Cc: kvm@vger.kernel.org, Marc Zyngier , Andre Przywara , Eric Auger , Vijaya.Kumar@cavium.com, Christoffer Dall Subject: [PATCH 4/5] KVM: arm64: vgic: Get rid of struct vmcr for GICv3 Date: Tue, 21 Mar 2017 12:05:29 +0100 Message-Id: <20170321110530.15857-5-cdall@linaro.org> X-Mailer: git-send-email 2.9.0 In-Reply-To: <20170321110530.15857-1-cdall@linaro.org> References: <20170321110530.15857-1-cdall@linaro.org> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP There is no common code in the VGIC that uses the VMCR, so we have no use of the intermediate architecture-agnostic representation of the VMCR and might as well manipulate the bits specifically using the logic for the version of the GIC that the code supports. For GICv3, this means translating between the ICH_VMCR register format stored in memory and the ICC_X_EL1 registers exported to user space. Signed-off-by: Christoffer Dall --- arch/arm64/kvm/vgic-sys-reg-v3.c | 133 +++++++++++++++------------------------ virt/kvm/arm/vgic/vgic-mmio.c | 4 +- virt/kvm/arm/vgic/vgic-v3.c | 38 ----------- virt/kvm/arm/vgic/vgic.h | 2 - 4 files changed, 53 insertions(+), 124 deletions(-) diff --git a/arch/arm64/kvm/vgic-sys-reg-v3.c b/arch/arm64/kvm/vgic-sys-reg-v3.c index 33f111c..cd51433 100644 --- a/arch/arm64/kvm/vgic-sys-reg-v3.c +++ b/arch/arm64/kvm/vgic-sys-reg-v3.c @@ -21,10 +21,9 @@ static bool write_gic_ctlr(struct kvm_vcpu *vcpu, u32 val) { struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; + u32 *vmcr = &vgic_cpu->vgic_v3.vgic_vmcr; u32 host_pri_bits, host_id_bits, host_seis, host_a3v, seis, a3v; - struct vgic_vmcr vmcr; - - vgic_get_vmcr(vcpu, &vmcr); + u32 cbpr, eoimode; /* * Disallow restoring VM state if not supported by this @@ -57,24 +56,26 @@ static bool write_gic_ctlr(struct kvm_vcpu *vcpu, u32 val) if (host_a3v != a3v) return false; - /* - * Here set VMCR.CTLR in ICC_CTLR_EL1 layout. - * The vgic_set_vmcr() will convert to ICH_VMCR layout. - */ - vmcr.ctlr = val & ICC_CTLR_EL1_CBPR_MASK; - vmcr.ctlr |= val & ICC_CTLR_EL1_EOImode_MASK; + /* Mask off any immutable bits from the ICC_CTLR_EL1 layout. */ + eoimode = val & ICC_CTLR_EL1_EOImode_MASK; + cbpr = val & ICC_CTLR_EL1_CBPR_MASK; - vgic_set_vmcr(vcpu, &vmcr); + /* Convert the remaining bits to ICH_VMCR layout. */ + *vmcr &= ~(ICH_VMCR_EOIM_MASK | ICH_VMCR_CBPR_MASK); + *vmcr |= (eoimode >> ICC_CTLR_EL1_EOImode_SHIFT) << + ICH_VMCR_EOIM_SHIFT; + *vmcr |= (cbpr >> ICC_CTLR_EL1_CBPR_SHIFT) << + ICH_VMCR_CBPR_SHIFT; + + *vmcr = val; return true; } static u32 read_gic_ctlr(struct kvm_vcpu *vcpu) { struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; + u32 vmcr = vgic_cpu->vgic_v3.vgic_vmcr; u32 val = 0; - struct vgic_vmcr vmcr; - - vgic_get_vmcr(vcpu, &vmcr); val |= (vgic_cpu->num_pri_bits - 1) << ICC_CTLR_EL1_PRI_BITS_SHIFT; @@ -85,12 +86,12 @@ static u32 read_gic_ctlr(struct kvm_vcpu *vcpu) val |= ((kvm_vgic_global_state.ich_vtr_el2 & ICH_VTR_A3V_MASK) >> ICH_VTR_A3V_SHIFT) << ICC_CTLR_EL1_A3V_SHIFT; - /* - * The VMCR.CTLR value is in ICC_CTLR_EL1 layout. - * Extract it directly using ICC_CTLR_EL1 reg definitions. - */ - val |= vmcr.ctlr & ICC_CTLR_EL1_CBPR_MASK; - val |= vmcr.ctlr & ICC_CTLR_EL1_EOImode_MASK; + + /* Convert the data in the ICH_VMCR_EL1 to the ICC_CTLR_EL1 layout */ + val |= ((vmcr & ICH_VMCR_EOIM_MASK) >> ICH_VMCR_EOIM_SHIFT) << + ICC_CTLR_EL1_EOImode_SHIFT; + val |= ((vmcr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT) << + ICC_CTLR_EL1_CBPR_SHIFT; return val; } @@ -108,99 +109,67 @@ static bool access_gic_ctlr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, return ret; } -static bool access_gic_pmr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, - const struct sys_reg_desc *r) +static void access_vmcr_field(struct kvm_vcpu *vcpu, struct sys_reg_params *p, + u32 ich_mask, u32 ich_shift, u32 icc_shift) { - struct vgic_vmcr vmcr; + struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; + u32 *vmcr = &vgic_cpu->vgic_v3.vgic_vmcr; - vgic_get_vmcr(vcpu, &vmcr); if (p->is_write) { - vmcr.pmr = (p->regval & ICC_PMR_EL1_MASK) >> ICC_PMR_EL1_SHIFT; - vgic_set_vmcr(vcpu, &vmcr); + *vmcr &= ~ich_mask; + *vmcr |= ((p->regval >> icc_shift) << ich_shift) & ich_mask; } else { - p->regval = (vmcr.pmr << ICC_PMR_EL1_SHIFT) & ICC_PMR_EL1_MASK; + p->regval = ((*vmcr & ich_mask) >> ich_shift) << icc_shift; } +} +static bool access_gic_pmr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, + const struct sys_reg_desc *r) +{ + access_vmcr_field(vcpu, p, + ICH_VMCR_PMR_MASK, + ICH_VMCR_PMR_SHIFT, + ICC_PMR_EL1_SHIFT); return true; } static bool access_gic_bpr0(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) { - struct vgic_vmcr vmcr; - - vgic_get_vmcr(vcpu, &vmcr); - if (p->is_write) { - vmcr.bpr = (p->regval & ICC_BPR0_EL1_MASK) >> - ICC_BPR0_EL1_SHIFT; - vgic_set_vmcr(vcpu, &vmcr); - } else { - p->regval = (vmcr.bpr << ICC_BPR0_EL1_SHIFT) & - ICC_BPR0_EL1_MASK; - } - + access_vmcr_field(vcpu, p, + ICH_VMCR_BPR0_MASK, + ICH_VMCR_BPR0_SHIFT, + ICC_BPR0_EL1_SHIFT); return true; } static bool access_gic_bpr1(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) { - struct vgic_vmcr vmcr; - - if (!p->is_write) - p->regval = 0; - - vgic_get_vmcr(vcpu, &vmcr); - if (!((vmcr.ctlr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT)) { - if (p->is_write) { - vmcr.abpr = (p->regval & ICC_BPR1_EL1_MASK) >> - ICC_BPR1_EL1_SHIFT; - vgic_set_vmcr(vcpu, &vmcr); - } else { - p->regval = (vmcr.abpr << ICC_BPR1_EL1_SHIFT) & - ICC_BPR1_EL1_MASK; - } - } else { - if (!p->is_write) - p->regval = min((vmcr.bpr + 1), 7U); - } - + access_vmcr_field(vcpu, p, + ICH_VMCR_BPR1_MASK, + ICH_VMCR_BPR1_SHIFT, + ICC_BPR1_EL1_SHIFT); return true; } static bool access_gic_grpen0(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) { - struct vgic_vmcr vmcr; - - vgic_get_vmcr(vcpu, &vmcr); - if (p->is_write) { - vmcr.grpen0 = (p->regval & ICC_IGRPEN0_EL1_MASK) >> - ICC_IGRPEN0_EL1_SHIFT; - vgic_set_vmcr(vcpu, &vmcr); - } else { - p->regval = (vmcr.grpen0 << ICC_IGRPEN0_EL1_SHIFT) & - ICC_IGRPEN0_EL1_MASK; - } - + access_vmcr_field(vcpu, p, + ICH_VMCR_ENG0_MASK, + ICH_VMCR_ENG0_SHIFT, + ICC_IGRPEN0_EL1_SHIFT); return true; } static bool access_gic_grpen1(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) { - struct vgic_vmcr vmcr; - - vgic_get_vmcr(vcpu, &vmcr); - if (p->is_write) { - vmcr.grpen1 = (p->regval & ICC_IGRPEN1_EL1_MASK) >> - ICC_IGRPEN1_EL1_SHIFT; - vgic_set_vmcr(vcpu, &vmcr); - } else { - p->regval = (vmcr.grpen1 << ICC_IGRPEN1_EL1_SHIFT) & - ICC_IGRPEN1_EL1_MASK; - } - + access_vmcr_field(vcpu, p, + ICH_VMCR_ENG1_MASK, + ICH_VMCR_ENG1_SHIFT, + ICC_IGRPEN1_EL1_SHIFT); return true; } diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c index 3654b4c..b53c66e 100644 --- a/virt/kvm/arm/vgic/vgic-mmio.c +++ b/virt/kvm/arm/vgic/vgic-mmio.c @@ -444,7 +444,7 @@ void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr) if (kvm_vgic_global_state.type == VGIC_V2) vgic_v2_set_vmcr(vcpu, vmcr); else - vgic_v3_set_vmcr(vcpu, vmcr); + BUG(); } void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr) @@ -452,7 +452,7 @@ void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr) if (kvm_vgic_global_state.type == VGIC_V2) vgic_v2_get_vmcr(vcpu, vmcr); else - vgic_v3_get_vmcr(vcpu, vmcr); + BUG(); } /* diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c index edc6ee2..4697f5d 100644 --- a/virt/kvm/arm/vgic/vgic-v3.c +++ b/virt/kvm/arm/vgic/vgic-v3.c @@ -171,44 +171,6 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr) vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = 0; } -void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp) -{ - u32 vmcr; - - /* - * Ignore the FIQen bit, because GIC emulation always implies - * SRE=1 which means the vFIQEn bit is also RES1. - */ - vmcr = ((vmcrp->ctlr >> ICC_CTLR_EL1_EOImode_SHIFT) << - ICH_VMCR_EOIM_SHIFT) & ICH_VMCR_EOIM_MASK; - vmcr |= (vmcrp->ctlr << ICH_VMCR_CBPR_SHIFT) & ICH_VMCR_CBPR_MASK; - vmcr |= (vmcrp->abpr << ICH_VMCR_BPR1_SHIFT) & ICH_VMCR_BPR1_MASK; - vmcr |= (vmcrp->bpr << ICH_VMCR_BPR0_SHIFT) & ICH_VMCR_BPR0_MASK; - vmcr |= (vmcrp->pmr << ICH_VMCR_PMR_SHIFT) & ICH_VMCR_PMR_MASK; - vmcr |= (vmcrp->grpen0 << ICH_VMCR_ENG0_SHIFT) & ICH_VMCR_ENG0_MASK; - vmcr |= (vmcrp->grpen1 << ICH_VMCR_ENG1_SHIFT) & ICH_VMCR_ENG1_MASK; - - vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr = vmcr; -} - -void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp) -{ - u32 vmcr = vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr; - - /* - * Ignore the FIQen bit, because GIC emulation always implies - * SRE=1 which means the vFIQEn bit is also RES1. - */ - vmcrp->ctlr = ((vmcr >> ICH_VMCR_EOIM_SHIFT) << - ICC_CTLR_EL1_EOImode_SHIFT) & ICC_CTLR_EL1_EOImode_MASK; - vmcrp->ctlr |= (vmcr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT; - vmcrp->abpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT; - vmcrp->bpr = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT; - vmcrp->pmr = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT; - vmcrp->grpen0 = (vmcr & ICH_VMCR_ENG0_MASK) >> ICH_VMCR_ENG0_SHIFT; - vmcrp->grpen1 = (vmcr & ICH_VMCR_ENG1_MASK) >> ICH_VMCR_ENG1_SHIFT; -} - #define INITIAL_PENDBASER_VALUE \ (GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, RaWb) | \ GIC_BASER_CACHEABILITY(GICR_PENDBASER, OUTER, SameAsInner) | \ diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h index db28f7c..5652983 100644 --- a/virt/kvm/arm/vgic/vgic.h +++ b/virt/kvm/arm/vgic/vgic.h @@ -143,8 +143,6 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu); void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr); void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr); void vgic_v3_set_underflow(struct kvm_vcpu *vcpu); -void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr); -void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr); void vgic_v3_enable(struct kvm_vcpu *vcpu); int vgic_v3_probe(const struct gic_kvm_info *info); int vgic_v3_map_resources(struct kvm *kvm);