From patchwork Thu Aug 8 22:21:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Herring X-Patchwork-Id: 170870 Delivered-To: patch@linaro.org Received: by 2002:a92:512:0:0:0:0:0 with SMTP id q18csp9165316ile; Thu, 8 Aug 2019 15:22:17 -0700 (PDT) X-Google-Smtp-Source: APXvYqyc46/z3g5uTH7XB7V5DbmpSd9+DiO1M8XktPCA/YK5USTSwFw5AJPPJZngV3I8FjRxv9BG X-Received: by 2002:a17:90a:7788:: with SMTP id v8mr6413964pjk.132.1565302937558; Thu, 08 Aug 2019 15:22:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1565302937; cv=none; d=google.com; s=arc-20160816; b=jt9ROxPmUe1T+xYPULC5HzC+296rOhXGB1c1KxvsSdysaLUb/UadCrI7B0GQPGKZjd G2MYE4cBCypgmUuTX7iFZqb78ZsiWJAsXhNkxzHPIKGOX8v22AmXtjVyG5SXYivSFwXr pH/ceerCLA3sxt8jEjzCPRNwIa9mETgAW+sFxnTaCPNF+m4zLsdT7iM1wLZxSsiIYxTV kLCA0wMQvDmbgeQMyAXHigYNyxtg5z9mGZVUBNNPRCNPaYPLujl0mMn4EpdNfT4b8TFm 1ZKnzPLuTvavdBlHnSHDM8NJ51WJqdpsJUTtjuRjmzXzYHe08l0AYK0hij6z9CS6zrNE nz0w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:mime-version:references:in-reply-to:message-id:date :subject:to:from:delivered-to; bh=k5FxeWVjQx0Zn5bL8ejNMcD70KLvlFCaFzzpTuDoogo=; b=aLkUFVSMfo+vN+Bpk/aJ5uuRwUlPBBXhKMyIbf8OrBFwpkuQYdv0ypck0pKiPpCbB6 lNmr+7DTHpTYRglllBmA39uKgnvmxJS68tsnsW0IcjUY9dtbMnpbSBX5pktaZz1Ap/yX ETj78PVksnRGyxSMs+xVYD7cFiocbcJXHY/HSBE9GEFDD87jD84Uv8mT7MMSeMVL7eou xT14umpV2Qvo54ctepwjCgfmrQmbfNRywfGWpmTp2WgBehqSXx7RG7P1d+I9bFTf+CyB x18vT26ySVg86QHv8Jho521OKuV6NgUczbOecFlpChXwQElULtVZQGyefHB7ezMUN0y8 mO9w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 2610:10:20:722:a800:ff:fe36:1795 as permitted sender) smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from gabe.freedesktop.org (gabe.freedesktop.org. [2610:10:20:722:a800:ff:fe36:1795]) by mx.google.com with ESMTPS id l6si53944150pgg.489.2019.08.08.15.22.17 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 08 Aug 2019 15:22:17 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 2610:10:20:722:a800:ff:fe36:1795 as permitted sender) client-ip=2610:10:20:722:a800:ff:fe36:1795; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 2610:10:20:722:a800:ff:fe36:1795 as permitted sender) smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 7CDDF6ECD2; Thu, 8 Aug 2019 22:22:14 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-ot1-f66.google.com (mail-ot1-f66.google.com [209.85.210.66]) by gabe.freedesktop.org (Postfix) with ESMTPS id 39F8E6ECD0 for ; Thu, 8 Aug 2019 22:22:10 +0000 (UTC) Received: by mail-ot1-f66.google.com with SMTP id s20so59577139otp.4 for ; Thu, 08 Aug 2019 15:22:10 -0700 (PDT) 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:mime-version:content-transfer-encoding; bh=U5aq6+CMjPdu74RcykL36X8rKkb/+fTPEkGiQ5mxOLE=; b=VMDDSslr2G5dtGV5mnA0BQPQSgMNYmL8eP3oZodODUemHfX8+LDZ+P/N5fOlVJNCOg KqgHJBvaKB69YV1/UGdOVcxkcpo8UzOxB+WQn/u4+pmjebY3kOAydmc8V73LeuLtbUrE i/DvbWJx9gUfbM+Kf+tM0hKUrtjDx5LfYKGy9BgqZjnrEAAS7OVym0vgnWe4C5kaEphv VSovzpxBREYmUQUU+JCBbNAaQ+LjYcbc08KM60lccXaOe4JYxwqdaplO2r9abRiw+z3H 0rs+nL+LqmtCg74Avzc/iQA+HESFbD3j+r7crXc6ygLQxRjxHFvkVCqE+XhP/C7+1IWx 3dWw== X-Gm-Message-State: APjAAAXckp7QtV1E18JyxBAVzZL3Gzc70+2zGwR0/liviBzF14DFaYBf lar6ujPeFyb9QQBd/qf7EfSrB+k= X-Received: by 2002:a5d:9710:: with SMTP id h16mr2716736iol.237.1565302928721; Thu, 08 Aug 2019 15:22:08 -0700 (PDT) Received: from xps15.herring.priv ([64.188.179.254]) by smtp.googlemail.com with ESMTPSA id i4sm118528553iog.31.2019.08.08.15.22.07 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Thu, 08 Aug 2019 15:22:08 -0700 (PDT) From: Rob Herring To: dri-devel@lists.freedesktop.org Subject: [PATCH v4 5/9] drm/panfrost: Add a no execute flag for BO allocations Date: Thu, 8 Aug 2019 16:21:56 -0600 Message-Id: <20190808222200.13176-6-robh@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190808222200.13176-1-robh@kernel.org> References: <20190808222200.13176-1-robh@kernel.org> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Tomeu Vizoso , Maxime Ripard , Robin Murphy , Steven Price , David Airlie , Boris Brezillon , Alyssa Rosenzweig , Sean Paul Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Executable buffers have an alignment restriction that they can't cross 16MB boundary as the GPU program counter is 24-bits. This restriction is currently not handled and we just get lucky. As current userspace assumes all BOs are executable, that has to remain the default. So add a new PANFROST_BO_NOEXEC flag to allow userspace to indicate which BOs are not executable. There is also a restriction that executable buffers cannot start or end on a 4GB boundary. This is mostly avoided as there is only 4GB of space currently and the beginning is already blocked out for NULL ptr detection. Add support to handle this restriction fully regardless of the current constraints. For existing userspace, all created BOs remain executable, but the GPU VA alignment will be increased to the size of the BO. This shouldn't matter as there is plenty of GPU VA space. Cc: Tomeu Vizoso Cc: Boris Brezillon Cc: Robin Murphy Reviewed-by: Steven Price Acked-by: Alyssa Rosenzweig Signed-off-by: Rob Herring --- drivers/gpu/drm/panfrost/panfrost_drv.c | 42 +++++++++++++++++---- drivers/gpu/drm/panfrost/panfrost_gem.c | 50 ++++++++++++++++++++++++- drivers/gpu/drm/panfrost/panfrost_gem.h | 9 ++++- drivers/gpu/drm/panfrost/panfrost_mmu.c | 3 ++ include/uapi/drm/panfrost_drm.h | 2 + 5 files changed, 96 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index 2894cfbbce2b..f070f2dd9f84 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -78,18 +78,19 @@ static int panfrost_ioctl_get_param(struct drm_device *ddev, void *data, struct static int panfrost_ioctl_create_bo(struct drm_device *dev, void *data, struct drm_file *file) { - struct drm_gem_shmem_object *shmem; + struct panfrost_gem_object *bo; struct drm_panfrost_create_bo *args = data; - if (!args->size || args->flags || args->pad) + if (!args->size || args->pad || + (args->flags & ~PANFROST_BO_NOEXEC)) return -EINVAL; - shmem = drm_gem_shmem_create_with_handle(file, dev, args->size, - &args->handle); - if (IS_ERR(shmem)) - return PTR_ERR(shmem); + bo = panfrost_gem_create_with_handle(file, dev, args->size, args->flags, + &args->handle); + if (IS_ERR(bo)) + return PTR_ERR(bo); - args->offset = to_panfrost_bo(&shmem->base)->node.start << PAGE_SHIFT; + args->offset = bo->node.start << PAGE_SHIFT; return 0; } @@ -364,6 +365,32 @@ int panfrost_unstable_ioctl_check(void) return 0; } +#define PFN_4G (SZ_4G >> PAGE_SHIFT) +#define PFN_4G_MASK (PFN_4G - 1) +#define PFN_16M (SZ_16M >> PAGE_SHIFT) + +static void panfrost_drm_mm_color_adjust(const struct drm_mm_node *node, + unsigned long color, + u64 *start, u64 *end) +{ + /* Executable buffers can't start or end on a 4GB boundary */ + if (!(color & PANFROST_BO_NOEXEC)) { + u64 next_seg; + + if ((*start & PFN_4G_MASK) == 0) + (*start)++; + + if ((*end & PFN_4G_MASK) == 0) + (*end)--; + + next_seg = ALIGN(*start, PFN_4G); + if (next_seg - *start <= PFN_16M) + *start = next_seg + 1; + + *end = min(*end, ALIGN(*start, PFN_4G) - 1); + } +} + static int panfrost_open(struct drm_device *dev, struct drm_file *file) { @@ -461,6 +488,7 @@ static int panfrost_probe(struct platform_device *pdev) /* 4G enough for now. can be 48-bit */ drm_mm_init(&pfdev->mm, SZ_32M >> PAGE_SHIFT, (SZ_4G - SZ_32M) >> PAGE_SHIFT); + pfdev->mm.color_adjust = panfrost_drm_mm_color_adjust; pm_runtime_use_autosuspend(pfdev->dev); pm_runtime_set_autosuspend_delay(pfdev->dev, 50); /* ~3 frames */ diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c b/drivers/gpu/drm/panfrost/panfrost_gem.c index 3933f83ba6b0..f398109b8e0c 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gem.c +++ b/drivers/gpu/drm/panfrost/panfrost_gem.c @@ -28,13 +28,25 @@ static int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_p { int ret; size_t size = obj->size; - u64 align = size >= SZ_2M ? SZ_2M >> PAGE_SHIFT : 0; + u64 align; struct panfrost_gem_object *bo = to_panfrost_bo(obj); struct panfrost_device *pfdev = obj->dev->dev_private; + unsigned long color = bo->noexec ? PANFROST_BO_NOEXEC : 0; + + /* + * Executable buffers cannot cross a 16MB boundary as the program + * counter is 24-bits. We assume executable buffers will be less than + * 16MB and aligning executable buffers to their size will avoid + * crossing a 16MB boundary. + */ + if (!bo->noexec) + align = size >> PAGE_SHIFT; + else + align = size >= SZ_2M ? SZ_2M >> PAGE_SHIFT : 0; spin_lock(&pfdev->mm_lock); ret = drm_mm_insert_node_generic(&pfdev->mm, &bo->node, - size >> PAGE_SHIFT, align, 0, 0); + size >> PAGE_SHIFT, align, color, 0); if (ret) goto out; @@ -95,16 +107,50 @@ struct drm_gem_object *panfrost_gem_create_object(struct drm_device *dev, size_t return &obj->base.base; } +struct panfrost_gem_object * +panfrost_gem_create_with_handle(struct drm_file *file_priv, + struct drm_device *dev, size_t size, + u32 flags, + uint32_t *handle) +{ + int ret; + struct drm_gem_shmem_object *shmem; + struct panfrost_gem_object *bo; + + shmem = drm_gem_shmem_create(dev, size); + if (IS_ERR(shmem)) + return ERR_CAST(shmem); + + bo = to_panfrost_bo(&shmem->base); + bo->noexec = !!(flags & PANFROST_BO_NOEXEC); + + /* + * Allocate an id of idr table where the obj is registered + * and handle has the id what user can see. + */ + ret = drm_gem_handle_create(file_priv, &shmem->base, handle); + /* drop reference from allocate - handle holds it now. */ + drm_gem_object_put_unlocked(&shmem->base); + if (ret) + return ERR_PTR(ret); + + return bo; +} + struct drm_gem_object * panfrost_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sgt) { struct drm_gem_object *obj; + struct panfrost_gem_object *bo; obj = drm_gem_shmem_prime_import_sg_table(dev, attach, sgt); if (IS_ERR(obj)) return ERR_CAST(obj); + bo = to_panfrost_bo(obj); + bo->noexec = true; + return obj; } diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.h b/drivers/gpu/drm/panfrost/panfrost_gem.h index 5f51f881ea3f..d4c7aa1790a7 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gem.h +++ b/drivers/gpu/drm/panfrost/panfrost_gem.h @@ -11,7 +11,8 @@ struct panfrost_gem_object { struct drm_gem_shmem_object base; struct drm_mm_node node; - bool is_mapped; + bool is_mapped :1; + bool noexec :1; }; static inline @@ -27,6 +28,12 @@ panfrost_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sgt); +struct panfrost_gem_object * +panfrost_gem_create_with_handle(struct drm_file *file_priv, + struct drm_device *dev, size_t size, + u32 flags, + uint32_t *handle); + void panfrost_gem_shrinker_init(struct drm_device *dev); void panfrost_gem_shrinker_cleanup(struct drm_device *dev); diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index b4ac149b2399..eba6ce785ef0 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -190,6 +190,9 @@ int panfrost_mmu_map(struct panfrost_gem_object *bo) if (WARN_ON(bo->is_mapped)) return 0; + if (bo->noexec) + prot |= IOMMU_NOEXEC; + sgt = drm_gem_shmem_get_pages_sgt(obj); if (WARN_ON(IS_ERR(sgt))) return PTR_ERR(sgt); diff --git a/include/uapi/drm/panfrost_drm.h b/include/uapi/drm/panfrost_drm.h index 1e547f9692e9..b80c20d17dec 100644 --- a/include/uapi/drm/panfrost_drm.h +++ b/include/uapi/drm/panfrost_drm.h @@ -84,6 +84,8 @@ struct drm_panfrost_wait_bo { __s64 timeout_ns; /* absolute */ }; +#define PANFROST_BO_NOEXEC 1 + /** * struct drm_panfrost_create_bo - ioctl argument for creating Panfrost BOs. *