From patchwork Sat Oct 29 11:19:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Zyngier X-Patchwork-Id: 9403601 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 5F70160588 for ; Sat, 29 Oct 2016 12:01:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5549328BDD for ; Sat, 29 Oct 2016 12:01:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 497D829170; Sat, 29 Oct 2016 12:01:37 +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.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable 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 C0C3328BDD for ; Sat, 29 Oct 2016 12:01:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752899AbcJ2MBd (ORCPT ); Sat, 29 Oct 2016 08:01:33 -0400 Received: from inca-roads.misterjones.org ([213.251.177.50]:36462 "EHLO inca-roads.misterjones.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752124AbcJ2MBc (ORCPT ); Sat, 29 Oct 2016 08:01:32 -0400 X-Greylist: delayed 2518 seconds by postgrey-1.27 at vger.kernel.org; Sat, 29 Oct 2016 08:01:32 EDT Received: from 78.163-31-62.static.virginmediabusiness.co.uk ([62.31.163.78] helo=why.lan) by cheepnis.misterjones.org with esmtpsa (TLSv1.2:DHE-RSA-AES128-GCM-SHA256:128) (Exim 4.80) (envelope-from ) id 1c0Rfg-0003mW-KM; Sat, 29 Oct 2016 13:19:32 +0200 From: Marc Zyngier To: linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Andre Przywara , Christoffer Dall Subject: [PATCH] KVM: arm/arm64: vgic: Prevent VGIC_ADDR_TO_INTID from emiting divisions Date: Sat, 29 Oct 2016 12:19:01 +0100 Message-Id: <20161029111901.16668-1-marc.zyngier@arm.com> X-Mailer: git-send-email 2.9.3 X-SA-Exim-Connect-IP: 62.31.163.78 X-SA-Exim-Rcpt-To: linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu, andre.przywara@arm.com, christoffer.dall@linaro.org X-SA-Exim-Mail-From: marc.zyngier@arm.com X-SA-Exim-Scanned: No (on cheepnis.misterjones.org); SAEximRunCond expanded to false Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Using non-constant number of bits for VGIC_ADDR_TO_INTID() leads to gcc 6.1 emiting calls to __aeabi_uldivmod, which the kernel does not implement. As we really don't want to implement complex division in the kernel, the only other option is to prove to the compiler that there is only a few values that are possible for the number of bits per IRQ, and that they are all power of 2. We turn the VGIC_ADDR_TO_INTID macro into a switch that looks for the supported set of values (1, 2, 8, 64), and perform the computation accordingly. When "bits" is a constant, the compiler optimizes away the other cases. If not, we end-up with a small number of cases that GCC optimises reasonably well. Out of range values are detected both at build time (constants) and at run time (variables). Signed-off-by: Marc Zyngier Acked-by: Christoffer Dall --- This should be applied *before* Andre's patch fixing out of bound SPIs. virt/kvm/arm/vgic/vgic-mmio.h | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h index 4c34d39..a457282 100644 --- a/virt/kvm/arm/vgic/vgic-mmio.h +++ b/virt/kvm/arm/vgic/vgic-mmio.h @@ -57,10 +57,41 @@ extern struct kvm_io_device_ops kvm_io_gic_ops; * multiplication with the inverted fraction, and scale up both the * numerator and denominator with 8 to support at most 64 bits per IRQ: */ -#define VGIC_ADDR_TO_INTID(addr, bits) (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \ +#define __VGIC_ADDR_INTID(addr, bits) (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \ 64 / (bits) / 8) /* + * Perform the same computation, but also handle non-constant number + * of bits. We only care about the few cases that are required by + * GICv2/v3. + */ +#define VGIC_ADDR_TO_INTID(addr, bits) \ + ({ \ + u32 __v; \ + switch((bits)) { \ + case 1: \ + __v = __VGIC_ADDR_INTID((addr), 1); \ + break; \ + case 2: \ + __v = __VGIC_ADDR_INTID((addr), 2); \ + break; \ + case 8: \ + __v = __VGIC_ADDR_INTID((addr), 8); \ + break; \ + case 64: \ + __v = __VGIC_ADDR_INTID((addr), 64); \ + break; \ + default: \ + if (__builtin_constant_p((bits))) \ + BUILD_BUG(); \ + else \ + BUG(); \ + } \ + \ + __v; \ + }) + +/* * Some VGIC registers store per-IRQ information, with a different number * of bits per IRQ. For those registers this macro is used. * The _WITH_LENGTH version instantiates registers with a fixed length