From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1FFA1C4743D for ; Tue, 8 Jun 2021 08:45:09 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E365E61073 for ; Tue, 8 Jun 2021 08:45:08 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E365E61073 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 2A3B56EB42; Tue, 8 Jun 2021 08:45:05 +0000 (UTC) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by gabe.freedesktop.org (Postfix) with ESMTPS id 994196EB3E; Tue, 8 Jun 2021 08:45:03 +0000 (UTC) IronPort-SDR: K2/QWP3+1v7FWav3yCTOVZMX+D7+yGQ9RioeheFLSTLNcQqiH0Wuk7xLEJBY4Q6bG+PmLxFk4x NmMjPeX39XSw== X-IronPort-AV: E=McAfee;i="6200,9189,10008"; a="202943824" X-IronPort-AV: E=Sophos;i="5.83,257,1616482800"; d="scan'208";a="202943824" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Jun 2021 01:45:03 -0700 IronPort-SDR: S4anKoU4zt77KhIlrtZrNUDQ8HAJx6F1WW9dIJ3fdq13zFiQD6eTvWiszL8ouxaQX56QJ7w/8E Bb8yMq36fKSQ== X-IronPort-AV: E=Sophos;i="5.83,257,1616482800"; d="scan'208";a="440381992" Received: from mrahim1x-mobl.gar.corp.intel.com (HELO mwauld-desk1.intel.com) ([10.215.170.251]) by orsmga007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Jun 2021 01:45:00 -0700 From: Matthew Auld To: intel-gfx@lists.freedesktop.org Subject: [PATCH v2 2/6] drm/i915/ttm: add i915_sg_from_buddy_resource Date: Tue, 8 Jun 2021 09:44:24 +0100 Message-Id: <20210608084428.142676-3-matthew.auld@intel.com> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210608084428.142676-1-matthew.auld@intel.com> References: <20210608084428.142676-1-matthew.auld@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= , dri-devel@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" We need to be able to build an sg table from our list of buddy blocks, so that we can later plug this into our ttm backend, and replace our use of the range manager. Signed-off-by: Matthew Auld Cc: Thomas Hellström Reviewed-by: Thomas Hellström --- drivers/gpu/drm/i915/i915_scatterlist.c | 80 +++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_scatterlist.h | 5 ++ 2 files changed, 85 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_scatterlist.c b/drivers/gpu/drm/i915/i915_scatterlist.c index 69e9e6c3135e..0959fe3efbbb 100644 --- a/drivers/gpu/drm/i915/i915_scatterlist.c +++ b/drivers/gpu/drm/i915/i915_scatterlist.c @@ -6,6 +6,9 @@ #include "i915_scatterlist.h" +#include "i915_buddy.h" +#include "i915_ttm_buddy_manager.h" + #include #include @@ -104,6 +107,83 @@ struct sg_table *i915_sg_from_mm_node(const struct drm_mm_node *node, return st; } +/** + * i915_sg_from_buddy_resource - Create an sg_table from a struct + * i915_buddy_block list + * @res: The i915_ttm_buddy_resource. + * @region_start: An offset to add to the dma addresses of the sg list. + * + * Create a struct sg_table, initializing it from struct i915_buddy_block list, + * taking a maximum segment length into account, splitting into segments + * if necessary. + * + * Return: A pointer to a kmalloced struct sg_table on success, negative + * error code cast to an error pointer on failure. + */ +struct sg_table *i915_sg_from_buddy_resource(struct ttm_resource *res, + u64 region_start) +{ + struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res); + struct i915_buddy_mm *mm = bman_res->mm; + const u64 size = res->num_pages << PAGE_SHIFT; + const u64 max_segment = UINT_MAX; + struct list_head *blocks = &bman_res->blocks; + struct i915_buddy_block *block; + struct scatterlist *sg; + struct sg_table *st; + resource_size_t prev_end; + + GEM_BUG_ON(list_empty(blocks)); + + st = kmalloc(sizeof(*st), GFP_KERNEL); + if (!st) + return ERR_PTR(-ENOMEM); + + if (sg_alloc_table(st, size >> PAGE_SHIFT, GFP_KERNEL)) { + kfree(st); + return ERR_PTR(-ENOMEM); + } + + sg = st->sgl; + st->nents = 0; + prev_end = (resource_size_t)-1; + + list_for_each_entry(block, blocks, link) { + u64 block_size, offset; + + block_size = min_t(u64, size, i915_buddy_block_size(mm, block)); + offset = i915_buddy_block_offset(block); + + while (block_size) { + u64 len; + + if (offset != prev_end || sg->length >= max_segment) { + if (st->nents) + sg = __sg_next(sg); + + sg_dma_address(sg) = region_start + offset; + sg_dma_len(sg) = 0; + sg->length = 0; + st->nents++; + } + + len = min(block_size, max_segment - sg->length); + sg->length += len; + sg_dma_len(sg) += len; + + offset += len; + block_size -= len; + + prev_end = offset; + } + } + + sg_mark_end(sg); + i915_sg_trim(st); + + return st; +} + #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftests/scatterlist.c" #endif diff --git a/drivers/gpu/drm/i915/i915_scatterlist.h b/drivers/gpu/drm/i915/i915_scatterlist.h index 5acca45ea981..b8bd5925b03f 100644 --- a/drivers/gpu/drm/i915/i915_scatterlist.h +++ b/drivers/gpu/drm/i915/i915_scatterlist.h @@ -14,6 +14,7 @@ #include "i915_gem.h" struct drm_mm_node; +struct ttm_resource; /* * Optimised SGL iterator for GEM objects @@ -145,4 +146,8 @@ bool i915_sg_trim(struct sg_table *orig_st); struct sg_table *i915_sg_from_mm_node(const struct drm_mm_node *node, u64 region_start); + +struct sg_table *i915_sg_from_buddy_resource(struct ttm_resource *res, + u64 region_start); + #endif -- 2.26.3 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 13C5DC47082 for ; Tue, 8 Jun 2021 08:45:08 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D2D316124B for ; Tue, 8 Jun 2021 08:45:07 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D2D316124B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=intel-gfx-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E8E096EB41; Tue, 8 Jun 2021 08:45:04 +0000 (UTC) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by gabe.freedesktop.org (Postfix) with ESMTPS id 994196EB3E; Tue, 8 Jun 2021 08:45:03 +0000 (UTC) IronPort-SDR: K2/QWP3+1v7FWav3yCTOVZMX+D7+yGQ9RioeheFLSTLNcQqiH0Wuk7xLEJBY4Q6bG+PmLxFk4x NmMjPeX39XSw== X-IronPort-AV: E=McAfee;i="6200,9189,10008"; a="202943824" X-IronPort-AV: E=Sophos;i="5.83,257,1616482800"; d="scan'208";a="202943824" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Jun 2021 01:45:03 -0700 IronPort-SDR: S4anKoU4zt77KhIlrtZrNUDQ8HAJx6F1WW9dIJ3fdq13zFiQD6eTvWiszL8ouxaQX56QJ7w/8E Bb8yMq36fKSQ== X-IronPort-AV: E=Sophos;i="5.83,257,1616482800"; d="scan'208";a="440381992" Received: from mrahim1x-mobl.gar.corp.intel.com (HELO mwauld-desk1.intel.com) ([10.215.170.251]) by orsmga007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Jun 2021 01:45:00 -0700 From: Matthew Auld To: intel-gfx@lists.freedesktop.org Date: Tue, 8 Jun 2021 09:44:24 +0100 Message-Id: <20210608084428.142676-3-matthew.auld@intel.com> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210608084428.142676-1-matthew.auld@intel.com> References: <20210608084428.142676-1-matthew.auld@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v2 2/6] drm/i915/ttm: add i915_sg_from_buddy_resource X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= , dri-devel@lists.freedesktop.org Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" V2UgbmVlZCB0byBiZSBhYmxlIHRvIGJ1aWxkIGFuIHNnIHRhYmxlIGZyb20gb3VyIGxpc3Qgb2Yg YnVkZHkgYmxvY2tzLApzbyB0aGF0IHdlIGNhbiBsYXRlciBwbHVnIHRoaXMgaW50byBvdXIgdHRt IGJhY2tlbmQsIGFuZCByZXBsYWNlIG91ciB1c2UKb2YgdGhlIHJhbmdlIG1hbmFnZXIuCgpTaWdu ZWQtb2ZmLWJ5OiBNYXR0aGV3IEF1bGQgPG1hdHRoZXcuYXVsZEBpbnRlbC5jb20+CkNjOiBUaG9t YXMgSGVsbHN0csO2bSA8dGhvbWFzLmhlbGxzdHJvbUBsaW51eC5pbnRlbC5jb20+ClJldmlld2Vk LWJ5OiBUaG9tYXMgSGVsbHN0csO2bSA8dGhvbWFzLmhlbGxzdHJvbUBsaW51eC5pbnRlbC5jb20+ Ci0tLQogZHJpdmVycy9ncHUvZHJtL2k5MTUvaTkxNV9zY2F0dGVybGlzdC5jIHwgODAgKysrKysr KysrKysrKysrKysrKysrKysrKwogZHJpdmVycy9ncHUvZHJtL2k5MTUvaTkxNV9zY2F0dGVybGlz dC5oIHwgIDUgKysKIDIgZmlsZXMgY2hhbmdlZCwgODUgaW5zZXJ0aW9ucygrKQoKZGlmZiAtLWdp dCBhL2RyaXZlcnMvZ3B1L2RybS9pOTE1L2k5MTVfc2NhdHRlcmxpc3QuYyBiL2RyaXZlcnMvZ3B1 L2RybS9pOTE1L2k5MTVfc2NhdHRlcmxpc3QuYwppbmRleCA2OWU5ZTZjMzEzNWUuLjA5NTlmZTNl ZmJiYiAxMDA2NDQKLS0tIGEvZHJpdmVycy9ncHUvZHJtL2k5MTUvaTkxNV9zY2F0dGVybGlzdC5j CisrKyBiL2RyaXZlcnMvZ3B1L2RybS9pOTE1L2k5MTVfc2NhdHRlcmxpc3QuYwpAQCAtNiw2ICs2 LDkgQEAKIAogI2luY2x1ZGUgImk5MTVfc2NhdHRlcmxpc3QuaCIKIAorI2luY2x1ZGUgImk5MTVf YnVkZHkuaCIKKyNpbmNsdWRlICJpOTE1X3R0bV9idWRkeV9tYW5hZ2VyLmgiCisKICNpbmNsdWRl IDxkcm0vZHJtX21tLmg+CiAKICNpbmNsdWRlIDxsaW51eC9zbGFiLmg+CkBAIC0xMDQsNiArMTA3 LDgzIEBAIHN0cnVjdCBzZ190YWJsZSAqaTkxNV9zZ19mcm9tX21tX25vZGUoY29uc3Qgc3RydWN0 IGRybV9tbV9ub2RlICpub2RlLAogCXJldHVybiBzdDsKIH0KIAorLyoqCisgKiBpOTE1X3NnX2Zy b21fYnVkZHlfcmVzb3VyY2UgLSBDcmVhdGUgYW4gc2dfdGFibGUgZnJvbSBhIHN0cnVjdAorICog aTkxNV9idWRkeV9ibG9jayBsaXN0CisgKiBAcmVzOiBUaGUgaTkxNV90dG1fYnVkZHlfcmVzb3Vy Y2UuCisgKiBAcmVnaW9uX3N0YXJ0OiBBbiBvZmZzZXQgdG8gYWRkIHRvIHRoZSBkbWEgYWRkcmVz c2VzIG9mIHRoZSBzZyBsaXN0LgorICoKKyAqIENyZWF0ZSBhIHN0cnVjdCBzZ190YWJsZSwgaW5p dGlhbGl6aW5nIGl0IGZyb20gc3RydWN0IGk5MTVfYnVkZHlfYmxvY2sgbGlzdCwKKyAqIHRha2lu ZyBhIG1heGltdW0gc2VnbWVudCBsZW5ndGggaW50byBhY2NvdW50LCBzcGxpdHRpbmcgaW50byBz ZWdtZW50cworICogaWYgbmVjZXNzYXJ5LgorICoKKyAqIFJldHVybjogQSBwb2ludGVyIHRvIGEg a21hbGxvY2VkIHN0cnVjdCBzZ190YWJsZSBvbiBzdWNjZXNzLCBuZWdhdGl2ZQorICogZXJyb3Ig Y29kZSBjYXN0IHRvIGFuIGVycm9yIHBvaW50ZXIgb24gZmFpbHVyZS4KKyAqLworc3RydWN0IHNn X3RhYmxlICppOTE1X3NnX2Zyb21fYnVkZHlfcmVzb3VyY2Uoc3RydWN0IHR0bV9yZXNvdXJjZSAq cmVzLAorCQkJCQkgICAgIHU2NCByZWdpb25fc3RhcnQpCit7CisJc3RydWN0IGk5MTVfdHRtX2J1 ZGR5X3Jlc291cmNlICpibWFuX3JlcyA9IHRvX3R0bV9idWRkeV9yZXNvdXJjZShyZXMpOworCXN0 cnVjdCBpOTE1X2J1ZGR5X21tICptbSA9IGJtYW5fcmVzLT5tbTsKKwljb25zdCB1NjQgc2l6ZSA9 IHJlcy0+bnVtX3BhZ2VzIDw8IFBBR0VfU0hJRlQ7CisJY29uc3QgdTY0IG1heF9zZWdtZW50ID0g VUlOVF9NQVg7CisJc3RydWN0IGxpc3RfaGVhZCAqYmxvY2tzID0gJmJtYW5fcmVzLT5ibG9ja3M7 CisJc3RydWN0IGk5MTVfYnVkZHlfYmxvY2sgKmJsb2NrOworCXN0cnVjdCBzY2F0dGVybGlzdCAq c2c7CisJc3RydWN0IHNnX3RhYmxlICpzdDsKKwlyZXNvdXJjZV9zaXplX3QgcHJldl9lbmQ7CisK KwlHRU1fQlVHX09OKGxpc3RfZW1wdHkoYmxvY2tzKSk7CisKKwlzdCA9IGttYWxsb2Moc2l6ZW9m KCpzdCksIEdGUF9LRVJORUwpOworCWlmICghc3QpCisJCXJldHVybiBFUlJfUFRSKC1FTk9NRU0p OworCisJaWYgKHNnX2FsbG9jX3RhYmxlKHN0LCBzaXplID4+IFBBR0VfU0hJRlQsIEdGUF9LRVJO RUwpKSB7CisJCWtmcmVlKHN0KTsKKwkJcmV0dXJuIEVSUl9QVFIoLUVOT01FTSk7CisJfQorCisJ c2cgPSBzdC0+c2dsOworCXN0LT5uZW50cyA9IDA7CisJcHJldl9lbmQgPSAocmVzb3VyY2Vfc2l6 ZV90KS0xOworCisJbGlzdF9mb3JfZWFjaF9lbnRyeShibG9jaywgYmxvY2tzLCBsaW5rKSB7CisJ CXU2NCBibG9ja19zaXplLCBvZmZzZXQ7CisKKwkJYmxvY2tfc2l6ZSA9IG1pbl90KHU2NCwgc2l6 ZSwgaTkxNV9idWRkeV9ibG9ja19zaXplKG1tLCBibG9jaykpOworCQlvZmZzZXQgPSBpOTE1X2J1 ZGR5X2Jsb2NrX29mZnNldChibG9jayk7CisKKwkJd2hpbGUgKGJsb2NrX3NpemUpIHsKKwkJCXU2 NCBsZW47CisKKwkJCWlmIChvZmZzZXQgIT0gcHJldl9lbmQgfHwgc2ctPmxlbmd0aCA+PSBtYXhf c2VnbWVudCkgeworCQkJCWlmIChzdC0+bmVudHMpCisJCQkJCXNnID0gX19zZ19uZXh0KHNnKTsK KworCQkJCXNnX2RtYV9hZGRyZXNzKHNnKSA9IHJlZ2lvbl9zdGFydCArIG9mZnNldDsKKwkJCQlz Z19kbWFfbGVuKHNnKSA9IDA7CisJCQkJc2ctPmxlbmd0aCA9IDA7CisJCQkJc3QtPm5lbnRzKys7 CisJCQl9CisKKwkJCWxlbiA9IG1pbihibG9ja19zaXplLCBtYXhfc2VnbWVudCAtIHNnLT5sZW5n dGgpOworCQkJc2ctPmxlbmd0aCArPSBsZW47CisJCQlzZ19kbWFfbGVuKHNnKSArPSBsZW47CisK KwkJCW9mZnNldCArPSBsZW47CisJCQlibG9ja19zaXplIC09IGxlbjsKKworCQkJcHJldl9lbmQg PSBvZmZzZXQ7CisJCX0KKwl9CisKKwlzZ19tYXJrX2VuZChzZyk7CisJaTkxNV9zZ190cmltKHN0 KTsKKworCXJldHVybiBzdDsKK30KKwogI2lmIElTX0VOQUJMRUQoQ09ORklHX0RSTV9JOTE1X1NF TEZURVNUKQogI2luY2x1ZGUgInNlbGZ0ZXN0cy9zY2F0dGVybGlzdC5jIgogI2VuZGlmCmRpZmYg LS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vaTkxNS9pOTE1X3NjYXR0ZXJsaXN0LmggYi9kcml2ZXJz L2dwdS9kcm0vaTkxNS9pOTE1X3NjYXR0ZXJsaXN0LmgKaW5kZXggNWFjY2E0NWVhOTgxLi5iOGJk NTkyNWIwM2YgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvZ3B1L2RybS9pOTE1L2k5MTVfc2NhdHRlcmxp c3QuaAorKysgYi9kcml2ZXJzL2dwdS9kcm0vaTkxNS9pOTE1X3NjYXR0ZXJsaXN0LmgKQEAgLTE0 LDYgKzE0LDcgQEAKICNpbmNsdWRlICJpOTE1X2dlbS5oIgogCiBzdHJ1Y3QgZHJtX21tX25vZGU7 CitzdHJ1Y3QgdHRtX3Jlc291cmNlOwogCiAvKgogICogT3B0aW1pc2VkIFNHTCBpdGVyYXRvciBm b3IgR0VNIG9iamVjdHMKQEAgLTE0NSw0ICsxNDYsOCBAQCBib29sIGk5MTVfc2dfdHJpbShzdHJ1 Y3Qgc2dfdGFibGUgKm9yaWdfc3QpOwogCiBzdHJ1Y3Qgc2dfdGFibGUgKmk5MTVfc2dfZnJvbV9t bV9ub2RlKGNvbnN0IHN0cnVjdCBkcm1fbW1fbm9kZSAqbm9kZSwKIAkJCQkgICAgICB1NjQgcmVn aW9uX3N0YXJ0KTsKKworc3RydWN0IHNnX3RhYmxlICppOTE1X3NnX2Zyb21fYnVkZHlfcmVzb3Vy Y2Uoc3RydWN0IHR0bV9yZXNvdXJjZSAqcmVzLAorCQkJCQkgICAgIHU2NCByZWdpb25fc3RhcnQp OworCiAjZW5kaWYKLS0gCjIuMjYuMwoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX18KSW50ZWwtZ2Z4IG1haWxpbmcgbGlzdApJbnRlbC1nZnhAbGlzdHMuZnJl ZWRlc2t0b3Aub3JnCmh0dHBzOi8vbGlzdHMuZnJlZWRlc2t0b3Aub3JnL21haWxtYW4vbGlzdGlu Zm8vaW50ZWwtZ2Z4Cg==