From patchwork Thu Mar 17 15:18:45 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shanker Donthineni X-Patchwork-Id: 8612291 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id E1A899F6E1 for ; Thu, 17 Mar 2016 15:30:05 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0937320374 for ; Thu, 17 Mar 2016 15:30:05 +0000 (UTC) Received: from bombadil.infradead.org (unknown [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id F034320351 for ; Thu, 17 Mar 2016 15:30:03 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1agZim-0001zn-Cx; Thu, 17 Mar 2016 15:20:20 +0000 Received: from smtp.codeaurora.org ([198.145.29.96]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1agZii-0000m2-J5 for linux-arm-kernel@lists.infradead.org; Thu, 17 Mar 2016 15:20:17 +0000 Received: from smtp.codeaurora.org (localhost [127.0.0.1]) by smtp.codeaurora.org (Postfix) with ESMTP id 1E00660328; Thu, 17 Mar 2016 15:19:56 +0000 (UTC) Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 11A696089A; Thu, 17 Mar 2016 15:19:56 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-3.4 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RDNS_NONE,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from shankerd-ubuntu.qualcomm.com (rrcs-67-52-129-61.west.biz.rr.com [67.52.129.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: shankerd@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 83B8660328; Thu, 17 Mar 2016 15:19:53 +0000 (UTC) From: Shanker Donthineni To: Marc Zyngier , linux-arm-kernel , linux-kernel Subject: [PATCH v4] irqchip/gicv3-its: Don't allow devices whose ID is outside range Date: Thu, 17 Mar 2016 10:18:45 -0500 Message-Id: <1458227925-21952-1-git-send-email-shankerd@codeaurora.org> X-Mailer: git-send-email 1.9.1 X-Virus-Scanned: ClamAV using ClamSMTP X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160317_082016_691123_1D7337D8 X-CRM114-Status: GOOD ( 18.29 ) X-Spam-Score: -1.9 (-) 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: Thomas Gleixner , Shanker Donthineni , Jason Cooper , Vikram Sethi , Eric Auger MIME-Version: 1.0 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 We are not checking whether the requested device identifier fits into the device table memory or not. The function its_create_device() assumes that enough memory has been allocated for whole DevID space (reported by ITS_TYPER.Devbits) during the ITS probe() and continues to initialize ITS hardware. This assumption is not perfect, sometimes we reduce memory size either because of its size crossing MAX_ORDER-1 or BASERn max size limit. The MAPD command fails if 'Device ID' is outside of device table range. Add a simple validation check to avoid MAPD failures since we are not handling ITS command errors. This change also helps to return an error -ENOMEM instead of success to caller. Signed-off-by: Shanker Donthineni --- [v3]->[v4] Cleanup code based on Marc's comments, remove the variable 'device_table' and extend validation check to cover case ITS HW with on-chip device table memory. [v2]->[v3] Fix typo. [v1]->[v2] Rebase to v4.5-rc6, edit commit text and simplify code changes. drivers/irqchip/irq-gic-v3-its.c | 42 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 43dfd15..d50d837 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -55,6 +55,16 @@ struct its_collection { }; /* + * The ITS_BASER structure - contains memory information and cached + * value of BASER register configuration. + */ +struct its_baser { + void *base; + u64 val; + u32 order; +}; + +/* * The ITS structure - contains most of the infrastructure, with the * top-level MSI domain, the command queue, the collections, and the * list of devices writing to it. @@ -66,14 +76,12 @@ struct its_node { unsigned long phys_base; struct its_cmd_block *cmd_base; struct its_cmd_block *cmd_write; - struct { - void *base; - u32 order; - } tables[GITS_BASER_NR_REGS]; + struct its_baser tables[GITS_BASER_NR_REGS]; struct its_collection *collections; struct list_head its_device_list; u64 flags; u32 ite_size; + u32 device_ids; }; #define ITS_ITT_ALIGN SZ_256 @@ -839,6 +847,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its) ids = GITS_TYPER_DEVBITS(typer); } + its->device_ids = ids; + for (i = 0; i < GITS_BASER_NR_REGS; i++) { u64 val = readq_relaxed(its->base + GITS_BASER + i * 8); u64 type = GITS_BASER_TYPE(val); @@ -914,6 +924,7 @@ retry_baser: } val |= alloc_pages - 1; + its->tables[i].val = val; writeq_relaxed(val, its->base + GITS_BASER + i * 8); tmp = readq_relaxed(its->base + GITS_BASER + i * 8); @@ -1139,9 +1150,22 @@ static struct its_device *its_find_device(struct its_node *its, u32 dev_id) return its_dev; } +static struct its_baser *its_get_baser(struct its_node *its, u32 type) +{ + int i; + + for (i = 0; i < GITS_BASER_NR_REGS; i++) { + if (GITS_BASER_TYPE(its->tables[i].val) == type) + return &its->tables[i]; + } + + return NULL; +} + static struct its_device *its_create_device(struct its_node *its, u32 dev_id, int nvecs) { + struct its_baser *baser; struct its_device *dev; unsigned long *lpi_map; unsigned long flags; @@ -1152,6 +1176,16 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, int nr_ites; int sz; + baser = its_get_baser(its, GITS_BASER_TYPE_DEVICE); + + /* Don't allow 'dev_id' that exceeds single, flat table limit */ + if (baser) { + if (dev_id >= (PAGE_ORDER_TO_SIZE(baser->order) / + GITS_BASER_ENTRY_SIZE(baser->val))) + return NULL; + } else if (ilog2(dev_id) >= its->device_ids) + return NULL; + dev = kzalloc(sizeof(*dev), GFP_KERNEL); /* * At least one bit of EventID is being used, hence a minimum