From patchwork Tue Nov 8 00:46:42 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Gunthorpe X-Patchwork-Id: 9416287 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 CF6D160585 for ; Tue, 8 Nov 2016 00:49:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C323D28BEF for ; Tue, 8 Nov 2016 00:49:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B599B28BF8; Tue, 8 Nov 2016 00:49:01 +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=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id B94CA28BEF for ; Tue, 8 Nov 2016 00:49:00 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1c3uZH-0004YI-UO; Tue, 08 Nov 2016 00:47:15 +0000 Received: from quartz.orcorp.ca ([184.70.90.242]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1c3uZB-0004Wh-95 for linux-arm-kernel@lists.infradead.org; Tue, 08 Nov 2016 00:47:10 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=obsidianresearch.com; s=rsa1; h=In-Reply-To:Content-Type:MIME-Version:References:Message-ID:Subject:Cc:To:From:Date; bh=OOS8nHjM5kmGZ3ofKdLh6hcLOEVqmAXFKmdTi6YKcvM=; b=Mo7VNkpxILrF152nkQXhHfNjs0k5JfFHs7zwFsQVwgV4EQX1cEUkDVmcr/DO5dvdm80Y4gd8B5mtyV6kBZGMmJM+9shpWHT6CqGDUTVDMhT7Btwaf2SK3LtGKyHS01/bA226SPDDCDb31Osurr+/Vc/gmE9gf5bk2d15d8yofTg=; Received: from [10.0.0.151] (helo=jggl.edm.orcorp.ca) by quartz.orcorp.ca with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1c3uYk-0003xy-HW; Mon, 07 Nov 2016 17:46:42 -0700 Received: from jgg by jggl.edm.orcorp.ca with local (Exim 4.84) (envelope-from ) id 1c3uYk-0008Td-D6; Mon, 07 Nov 2016 17:46:42 -0700 Date: Mon, 7 Nov 2016 17:46:42 -0700 From: Jason Gunthorpe To: Moritz Fischer Subject: Re: [PATCH] fpga zynq: Check the bitstream for validity Message-ID: <20161108004642.GB32444@obsidianresearch.com> References: <20161027143937.GC6818@obsidianresearch.com> <8bed213a-96e3-1891-a46a-234253a2561e@suse.com> <20161028154740.GC10441@obsidianresearch.com> <5ea0e77e-11c5-b4f7-00a9-9c5425ffac5a@suse.com> <20161028165555.GA17998@obsidianresearch.com> <20161028182308.GB18325@live.com> <20161028202619.GA29625@obsidianresearch.com> <20161028210015.GA19901@live.com> <20161028220546.GA19693@obsidianresearch.com> <20161029000926.GA30169@live.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20161029000926.GA30169@live.com> User-Agent: Mutt/1.5.23 (2014-03-12) X-Broken-Reverse-DNS: no host name found for IP address 10.0.0.151 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20161107_164709_442290_1CD1433D X-CRM114-Status: GOOD ( 18.79 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Tull , Matthias Brugger , Michal Simek , S??ren Brinkmann , linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP On Fri, Oct 28, 2016 at 05:09:26PM -0700, Moritz Fischer wrote: > That being said, I don't like the idea of the driver having to search > either... I think we are stuck with that, considering what Xilinx tools produce.. Here is a v2, what do you think? From 93ffde371ca50809ba9b4cdca17051a050b0f92d Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Wed, 26 Oct 2016 16:51:26 -0600 Subject: [PATCH v2] fpga zynq: Check the bitstream for validity There is no sense in sending a bitstream we know will not work, and with the variety of options for bitstream generation in Xilinx tools it is not terribly clear or very well documented what the correct input should be, especially since auto-detection was removed from this driver. All Zynq full configuration bitstreams must start with the sync word in the correct byte order. Zynq is also only able to DMA dword quantities, so bitstreams must be a multiple of 4 bytes. This also fixes a DMA-past the end bug. Signed-off-by: Jason Gunthorpe --- drivers/fpga/zynq-fpga.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c index c2fb4120bd62..de475a6a1882 100644 --- a/drivers/fpga/zynq-fpga.c +++ b/drivers/fpga/zynq-fpga.c @@ -175,6 +175,19 @@ static irqreturn_t zynq_fpga_isr(int irq, void *data) return IRQ_HANDLED; } +/* Sanity check the proposed bitstream. It must start with the sync word in + * the correct byte order. The input is a Xilinx .bin file with every 32 bit + * quantity swapped. + */ +static bool zynq_fpga_has_sync(const char *buf, size_t count) +{ + for (; count > 4; buf += 4, --count) + if (buf[0] == 0x66 && buf[1] == 0x55 && buf[2] == 0x99 && + buf[3] == 0xaa) + return true; + return false; +} + static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags, const char *buf, size_t count) { @@ -184,12 +197,23 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags, priv = mgr->priv; + /* The hardware can only DMA multiples of 4 bytes, and we need at + * least the sync word and something else to do anything. + */ + if (count <= 4 || (count % 4) != 0) + return -EINVAL; + err = clk_enable(priv->clk); if (err) return err; /* don't globally reset PL if we're doing partial reconfig */ if (!(flags & FPGA_MGR_PARTIAL_RECONFIG)) { + if (!zynq_fpga_has_sync(buf, count)) { + err = -EINVAL; + goto out_err; + } + /* assert AXI interface resets */ regmap_write(priv->slcr, SLCR_FPGA_RST_CTRL_OFFSET, FPGA_RST_ALL_MASK); @@ -287,12 +311,9 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr, struct zynq_fpga_priv *priv; int err; char *kbuf; - size_t in_count; dma_addr_t dma_addr; - u32 transfer_length; u32 intr_status; - in_count = count; priv = mgr->priv; kbuf = dma_alloc_coherent(priv->dev, count, &dma_addr, GFP_KERNEL); @@ -318,11 +339,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr, */ zynq_fpga_write(priv, DMA_SRC_ADDR_OFFSET, (u32)(dma_addr) + 1); zynq_fpga_write(priv, DMA_DST_ADDR_OFFSET, (u32)DMA_INVALID_ADDRESS); - - /* convert #bytes to #words */ - transfer_length = (count + 3) / 4; - - zynq_fpga_write(priv, DMA_SRC_LEN_OFFSET, transfer_length); + zynq_fpga_write(priv, DMA_SRC_LEN_OFFSET, count / 4); zynq_fpga_write(priv, DMA_DEST_LEN_OFFSET, 0); wait_for_completion(&priv->dma_done); @@ -338,7 +355,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr, clk_disable(priv->clk); out_free: - dma_free_coherent(priv->dev, in_count, kbuf, dma_addr); + dma_free_coherent(priv->dev, count, kbuf, dma_addr); return err; }