From patchwork Fri May 18 09:28:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qiang Yu X-Patchwork-Id: 10414083 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 3A9BA6032B for ; Mon, 21 May 2018 08:18:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0EC512434C for ; Mon, 21 May 2018 08:18:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F3C0325D99; Mon, 21 May 2018 08:18:17 +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=-5.1 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id E10FC2434C for ; Mon, 21 May 2018 08:18:16 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 09FE18929D; Mon, 21 May 2018 08:18:12 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-pl0-x242.google.com (mail-pl0-x242.google.com [IPv6:2607:f8b0:400e:c01::242]) by gabe.freedesktop.org (Postfix) with ESMTPS id CFC586ECC9 for ; Fri, 18 May 2018 09:30:42 +0000 (UTC) Received: by mail-pl0-x242.google.com with SMTP id n10-v6so4267998plp.0 for ; Fri, 18 May 2018 02:30:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=JS0+Y+cKBLLydXtTWyITUNrWQM1bzoZ7ETMiW9aahaA=; b=YIAHbBbbzx53gnVFkwTRsMdDPW4RJNAgZcp3iMgcyiIviJNnmv3LHuUm0k4/ODw9KT +EIAz0K/O0rQX9P5kmoRFHUv2o/XgvuGVg1sWPpOAYmmEDaMHxTJp1c+FGGpQExxG5Pe xzrHPgVpHWS9iuy2DlS+o16UJA46Mvy9kD1ciYa5cPGF3uuxQANBMn54pxD1I7hb8gEH CcHfRJI5KnKrcuWbFZ3qik8yx1nj0kUXiIgeqOQQZE3bHd0YMSuwnEmHD3SWK/M3qEVk KW4yRrE6tsMyH6XOBseh6k+b75+Ek2cfCSoTwVCiNYH70mRWVL9L0OT/LlDEeJoMW10T WVpg== 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=JS0+Y+cKBLLydXtTWyITUNrWQM1bzoZ7ETMiW9aahaA=; b=DB1H2ApINhoHl/oP7jDad6iP4+p9j4UnI4/dktjJhkkrUgtXAZ9s/O8YIiTagXUWdx ugzjp5JHG0+zCwNLfIWX9AOcI55FJFHEIy/8scfJAArRiN5jDWPsU3GX3PS143FUAkAf 81FUwgkclCcAuBKSw5QMTLFvJvxJH3n44jzQgDxtLVvqytqFNK7a5xLpyqLXYHXG86yK ARTjRXByuXvPpPwt0rJwzAdV0MEg2nXmztn7pJ5iw2S2cchtHadjysci44ElvyMzzMi1 1WyHsU5Blbm0QvH9dst/fJrCf8YkDlQELbOhg4XCoBZcas92JhQaEcFmWyDcLrW9Nvlm cAAQ== X-Gm-Message-State: ALKqPwfD0fswL1ZVA5fcMgk7eK+NhvOq74J9SWr+lFmLFXYAnH/EdGML kcYCJ2pYbo5DePddj5YuPK0J5DCSY1c= X-Google-Smtp-Source: AB8JxZrJHEM5/d56OI30osVZZCady/WgqOUskJaSsugW3EZNpJ4iyuDrx7tzzhp5cchWjfPwDqSc7g== X-Received: by 2002:a17:902:9004:: with SMTP id a4-v6mr8658105plp.143.1526635842191; Fri, 18 May 2018 02:30:42 -0700 (PDT) Received: from localhost.localdomain (210-140-84-216.jp-east.compute.idcfcloud.com. [210.140.84.216]) by smtp.gmail.com with ESMTPSA id h191-v6sm10543832pgc.11.2018.05.18.02.30.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 02:30:41 -0700 (PDT) From: Qiang Yu To: dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org Subject: [PATCH RFC 17/24] drm/lima: add GPU virtual memory space handing Date: Fri, 18 May 2018 17:28:08 +0800 Message-Id: <20180518092815.25280-18-yuq825@gmail.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180518092815.25280-1-yuq825@gmail.com> References: <20180518092815.25280-1-yuq825@gmail.com> X-Mailman-Approved-At: Mon, 21 May 2018 08:18:10 +0000 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: Simon Shields , Marek Vasut , Connor Abbott , Neil Armstrong , Andrei Paulau <7134956@gmail.com>, Vasily Khoruzhick , Qiang Yu , Erico Nunes MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Lima Project Developers Signed-off-by: Qiang Yu Signed-off-by: Vasily Khoruzhick --- drivers/gpu/drm/lima/lima_vm.c | 312 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/lima/lima_vm.h | 73 ++++++++ 2 files changed, 385 insertions(+) create mode 100644 drivers/gpu/drm/lima/lima_vm.c create mode 100644 drivers/gpu/drm/lima/lima_vm.h diff --git a/drivers/gpu/drm/lima/lima_vm.c b/drivers/gpu/drm/lima/lima_vm.c new file mode 100644 index 000000000000..00a3f6b59a33 --- /dev/null +++ b/drivers/gpu/drm/lima/lima_vm.c @@ -0,0 +1,312 @@ +/* + * Copyright (C) 2017-2018 Lima Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include + +#include "lima_device.h" +#include "lima_vm.h" +#include "lima_object.h" +#include "lima_regs.h" + +struct lima_bo_va_mapping { + struct list_head list; + struct rb_node rb; + uint32_t start; + uint32_t last; + uint32_t __subtree_last; +}; + +struct lima_bo_va { + struct list_head list; + unsigned ref_count; + + struct list_head mapping; + + struct lima_vm *vm; +}; + +#define LIMA_PDE(va) (va >> 22) +#define LIMA_PTE(va) ((va & 0x3FFFFF) >> 12) + +#define START(node) ((node)->start) +#define LAST(node) ((node)->last) + +INTERVAL_TREE_DEFINE(struct lima_bo_va_mapping, rb, uint32_t, __subtree_last, + START, LAST, static, lima_vm_it) + +#undef START +#undef LAST + +static void lima_vm_unmap_page_table(struct lima_vm *vm, u32 start, u32 end) +{ + u32 addr; + + for (addr = start; addr <= end; addr += LIMA_PAGE_SIZE) { + u32 pde = LIMA_PDE(addr); + u32 pte = LIMA_PTE(addr); + u32 *pt; + + pt = lima_bo_kmap(vm->pt[pde]); + pt[pte] = 0; + } +} + +static int lima_vm_map_page_table(struct lima_vm *vm, dma_addr_t *dma, + u32 start, u32 end) +{ + u64 addr; + int err, i = 0; + + for (addr = start; addr <= end; addr += LIMA_PAGE_SIZE) { + u32 pde = LIMA_PDE(addr); + u32 pte = LIMA_PTE(addr); + u32 *pd, *pt; + + if (vm->pt[pde]) + pt = lima_bo_kmap(vm->pt[pde]); + else { + vm->pt[pde] = lima_bo_create( + vm->dev, LIMA_PAGE_SIZE, 0, ttm_bo_type_kernel, + NULL, vm->pd->tbo.resv); + if (IS_ERR(vm->pt[pde])) { + err = PTR_ERR(vm->pt[pde]); + goto err_out; + } + + pt = lima_bo_kmap(vm->pt[pde]); + if (IS_ERR(pt)) { + err = PTR_ERR(pt); + goto err_out; + } + + pd = lima_bo_kmap(vm->pd); + pd[pde] = *lima_bo_get_pages(vm->pt[pde]) | LIMA_VM_FLAG_PRESENT; + } + + pt[pte] = dma[i++] | LIMA_VM_FLAGS_CACHE; + } + + return 0; + +err_out: + if (addr != start) + lima_vm_unmap_page_table(vm, start, addr - 1); + return err; +} + +static struct lima_bo_va * +lima_vm_bo_find(struct lima_vm *vm, struct lima_bo *bo) +{ + struct lima_bo_va *bo_va, *ret = NULL; + + list_for_each_entry(bo_va, &bo->va, list) { + if (bo_va->vm == vm) { + ret = bo_va; + break; + } + } + + return ret; +} + +int lima_vm_bo_map(struct lima_vm *vm, struct lima_bo *bo, u32 start) +{ + int err; + struct lima_bo_va_mapping *it, *mapping; + u32 end = start + bo->gem.size - 1; + dma_addr_t *pages_dma = lima_bo_get_pages(bo); + struct lima_bo_va *bo_va; + + it = lima_vm_it_iter_first(&vm->va, start, end); + if (it) { + dev_dbg(bo->gem.dev->dev, "lima vm map va overlap %x-%x %x-%x\n", + start, end, it->start, it->last); + return -EINVAL; + } + + mapping = kmalloc(sizeof(*mapping), GFP_KERNEL); + if (!mapping) + return -ENOMEM; + mapping->start = start; + mapping->last = end; + + err = lima_vm_map_page_table(vm, pages_dma, start, end); + if (err) { + kfree(mapping); + return err; + } + + lima_vm_it_insert(mapping, &vm->va); + + bo_va = lima_vm_bo_find(vm, bo); + list_add_tail(&mapping->list, &bo_va->mapping); + + return 0; +} + +static void lima_vm_unmap(struct lima_vm *vm, + struct lima_bo_va_mapping *mapping) +{ + lima_vm_it_remove(mapping, &vm->va); + + lima_vm_unmap_page_table(vm, mapping->start, mapping->last); + + list_del(&mapping->list); + kfree(mapping); +} + +int lima_vm_bo_unmap(struct lima_vm *vm, struct lima_bo *bo, u32 start) +{ + struct lima_bo_va *bo_va; + struct lima_bo_va_mapping *mapping; + + bo_va = lima_vm_bo_find(vm, bo); + list_for_each_entry(mapping, &bo_va->mapping, list) { + if (mapping->start == start) { + lima_vm_unmap(vm, mapping); + break; + } + } + + return 0; +} + +int lima_vm_bo_add(struct lima_vm *vm, struct lima_bo *bo) +{ + struct lima_bo_va *bo_va; + + bo_va = lima_vm_bo_find(vm, bo); + if (bo_va) { + bo_va->ref_count++; + return 0; + } + + bo_va = kmalloc(sizeof(*bo_va), GFP_KERNEL); + if (!bo_va) + return -ENOMEM; + + bo_va->vm = vm; + bo_va->ref_count = 1; + INIT_LIST_HEAD(&bo_va->mapping); + list_add_tail(&bo_va->list, &bo->va); + return 0; +} + +int lima_vm_bo_del(struct lima_vm *vm, struct lima_bo *bo) +{ + struct lima_bo_va *bo_va; + struct lima_bo_va_mapping *mapping, *tmp; + + bo_va = lima_vm_bo_find(vm, bo); + if (--bo_va->ref_count > 0) + return 0; + + list_for_each_entry_safe(mapping, tmp, &bo_va->mapping, list) { + lima_vm_unmap(vm, mapping); + } + list_del(&bo_va->list); + kfree(bo_va); + return 0; +} + +struct lima_vm *lima_vm_create(struct lima_device *dev) +{ + struct lima_vm *vm; + void *pd; + + vm = kzalloc(sizeof(*vm), GFP_KERNEL); + if (!vm) + return NULL; + + vm->dev = dev; + vm->va = RB_ROOT_CACHED; + kref_init(&vm->refcount); + + vm->pd = lima_bo_create(dev, LIMA_PAGE_SIZE, 0, + ttm_bo_type_kernel, NULL, NULL); + if (IS_ERR(vm->pd)) + goto err_out0; + + pd = lima_bo_kmap(vm->pd); + if (IS_ERR(pd)) + goto err_out1; + + if (dev->dlbu_cpu) { + int err = lima_vm_map_page_table( + vm, &dev->dlbu_dma, LIMA_VA_RESERVE_DLBU, + LIMA_VA_RESERVE_DLBU + LIMA_PAGE_SIZE - 1); + if (err) + goto err_out1; + } + + return vm; + +err_out1: + lima_bo_unref(vm->pd); +err_out0: + kfree(vm); + return NULL; +} + +void lima_vm_release(struct kref *kref) +{ + struct lima_vm *vm = container_of(kref, struct lima_vm, refcount); + struct lima_device *dev = vm->dev; + int i; + + if (!RB_EMPTY_ROOT(&vm->va.rb_root)) { + dev_err(dev->dev, "still active bo inside vm\n"); + } + + for (i = 0; i < LIMA_PAGE_ENT_NUM; i++) { + if (vm->pt[i]) + lima_bo_unref(vm->pt[i]); + } + + if (vm->pd) + lima_bo_unref(vm->pd); + + kfree(vm); +} + +void lima_vm_print(struct lima_vm *vm) +{ + int i, j; + u32 *pd = lima_bo_kmap(vm->pd); + + /* to avoid the defined by not used warning */ + (void)&lima_vm_it_iter_next; + + for (i = 0; i < LIMA_PAGE_ENT_NUM; i++) { + if (pd[i]) { + u32 *pt = lima_bo_kmap(vm->pt[i]); + + printk(KERN_INFO "lima vm pd %03x:%08x\n", i, pd[i]); + for (j = 0; j < LIMA_PAGE_ENT_NUM; j++) { + if (pt[j]) + printk(KERN_INFO " pt %03x:%08x\n", j, pt[j]); + } + } + } +} diff --git a/drivers/gpu/drm/lima/lima_vm.h b/drivers/gpu/drm/lima/lima_vm.h new file mode 100644 index 000000000000..20506459def0 --- /dev/null +++ b/drivers/gpu/drm/lima/lima_vm.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2017-2018 Lima Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef __LIMA_VM_H__ +#define __LIMA_VM_H__ + +#include +#include + +#define LIMA_PAGE_SIZE 4096 +#define LIMA_PAGE_MASK (LIMA_PAGE_SIZE - 1) +#define LIMA_PAGE_ENT_NUM (LIMA_PAGE_SIZE / sizeof(u32)) + +#define LIMA_VA_RESERVE_START 0xFFF00000 +#define LIMA_VA_RESERVE_DLBU LIMA_VA_RESERVE_START +#define LIMA_VA_RESERVE_END 0x100000000 + +struct lima_bo; +struct lima_device; + +struct lima_vm { + struct kref refcount; + + /* tree of virtual addresses mapped */ + struct rb_root_cached va; + + struct lima_device *dev; + + struct lima_bo *pd; + struct lima_bo *pt[LIMA_PAGE_ENT_NUM]; +}; + +int lima_vm_bo_map(struct lima_vm *vm, struct lima_bo *bo, u32 start); +int lima_vm_bo_unmap(struct lima_vm *vm, struct lima_bo *bo, u32 start); + +int lima_vm_bo_add(struct lima_vm *vm, struct lima_bo *bo); +int lima_vm_bo_del(struct lima_vm *vm, struct lima_bo *bo); + +struct lima_vm *lima_vm_create(struct lima_device *dev); +void lima_vm_release(struct kref *kref); + +static inline struct lima_vm *lima_vm_get(struct lima_vm *vm) +{ + kref_get(&vm->refcount); + return vm; +} + +static inline void lima_vm_put(struct lima_vm *vm) +{ + kref_put(&vm->refcount, lima_vm_release); +} + +void lima_vm_print(struct lima_vm *vm); + +#endif