From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752788AbeCYLAL (ORCPT ); Sun, 25 Mar 2018 07:00:11 -0400 Received: from mail-wm0-f65.google.com ([74.125.82.65]:52971 "EHLO mail-wm0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752115AbeCYLAF (ORCPT ); Sun, 25 Mar 2018 07:00:05 -0400 X-Google-Smtp-Source: AG47ELtTajhgf4vVO+MNX1D19whZMQ+jh4WxoGcR+2Pq9cFB8V50wfs+L+ZvzO0SMj/5SuyobjFCMQ== From: "=?UTF-8?q?Christian=20K=C3=B6nig?=" X-Google-Original-From: =?UTF-8?q?Christian=20K=C3=B6nig?= To: linaro-mm-sig@lists.linaro.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, amd-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/8] PCI: Add pci_peer_traffic_supported() Date: Sun, 25 Mar 2018 12:59:55 +0200 Message-Id: <20180325110000.2238-3-christian.koenig@amd.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20180325110000.2238-1-christian.koenig@amd.com> References: <20180325110000.2238-1-christian.koenig@amd.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: "wdavis@nvidia.com" Add checks for topology and ACS configuration to determine whether or not peer traffic should be supported between two PCI devices. Signed-off-by: Will Davis Signed-off-by: Christian König --- drivers/pci/pci.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/pci.h | 1 + 2 files changed, 113 insertions(+) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index f6a4dd10d9b0..efdca3c9dad1 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -5285,6 +5286,117 @@ void pci_ignore_hotplug(struct pci_dev *dev) } EXPORT_SYMBOL_GPL(pci_ignore_hotplug); +static bool pci_peer_host_traffic_supported(struct pci_host_bridge *host) +{ + struct pci_dev *bridge = pci_get_slot(host->bus, PCI_DEVFN(0, 0)); + unsigned short vendor, device; + + if (!bridge) + return false; + + vendor = bridge->vendor; + device = bridge->device; + pci_dev_put(bridge); + + /* AMD ZEN host bridges can do peer to peer */ + if (vendor == PCI_VENDOR_ID_AMD && device == 0x1450) + return true; + + /* TODO: Extend that to a proper whitelist */ + return false; +} + +bool pci_peer_traffic_supported(struct pci_dev *dev, struct pci_dev *peer) +{ + struct pci_dev *rp_dev, *rp_peer, *common_upstream; + struct pci_host_bridge *peer_host_bridge; + struct pci_host_bridge *dev_host_bridge; + int pos; + u16 cap; + + /* This is tricky enough, focus on PCIe for now */ + if (!pci_is_pcie(dev) || !pci_is_pcie(peer)) + return false; + + /* + * Disallow the peer-to-peer traffic if the devices do not share a + * host bridge. The PCI specifications does not make any guarantees + * about P2P capabilities between devices under separate domains. + * + * PCI Local Bus Specification Revision 3.0, section 3.10: + * "Peer-to-peer transactions crossing multiple host bridges + * PCI host bridges may, but are not required to, support PCI + * peer-to-peer transactions that traverse multiple PCI host + * bridges." + */ + dev_host_bridge = pci_find_host_bridge(dev->bus); + peer_host_bridge = pci_find_host_bridge(peer->bus); + if (dev_host_bridge != peer_host_bridge) + return pci_peer_host_traffic_supported(dev_host_bridge); + + rp_dev = pcie_find_root_port(dev); + rp_peer = pcie_find_root_port(peer); + common_upstream = pci_find_common_upstream_dev(dev, peer); + + /* + * Access Control Services (ACS) Checks + * + * ACS has a capability bit for P2P Request Redirects (RR), + * but unfortunately it doesn't tell us much about the real + * capabilities of the hardware. + * + * PCI Express Base Specification Revision 3.0, section + * 6.12.1.1: + * "ACS P2P Request Redirect: must be implemented by Root + * Ports that support peer-to-peer traffic with other + * Root Ports; [80]" + * but + * "[80] Root Port indication of ACS P2P Request Redirect + * or ACS P2P Completion Redirect support does not imply + * any particular level of peer-to-peer support by the + * Root Complex, or that peer-to-peer traffic is + * supported at all" + */ + + /* + * If ACS is not implemented, we have no idea about P2P + * support. Optimistically allow this if there is a common + * upstream device. + */ + pos = pci_find_ext_capability(rp_dev, PCI_EXT_CAP_ID_ACS); + if (!pos) + return common_upstream != NULL; + + /* + * If the devices are under the same root port and have a common + * upstream device, allow if the root port is further upstream + * from the common upstream device and the common upstream + * device has Upstream Forwarding disabled, or if the root port + * is the common upstream device and ACS is not implemented. + */ + pci_read_config_word(rp_dev, pos + PCI_ACS_CAP, &cap); + if ((rp_dev == rp_peer && common_upstream) && + (((common_upstream != rp_dev) && + !pci_acs_enabled(common_upstream, PCI_ACS_UF)) || + ((common_upstream == rp_dev) && ((cap & PCI_ACS_RR) == 0)))) + return true; + + /* + * If ACS RR is implemented and disabled, allow only if the + * devices are under the same root port. + */ + if (cap & PCI_ACS_RR && !pci_acs_enabled(rp_dev, PCI_ACS_RR)) + return rp_dev == rp_peer; + + /* + * If ACS RR is not implemented, or is implemented and enabled, + * only allow if there's a translation agent enabled to do the + * redirect. + */ + return iommu_present(&pci_bus_type); +} +EXPORT_SYMBOL(pci_peer_traffic_supported); + resource_size_t __weak pcibios_default_alignment(void) { return 0; diff --git a/include/linux/pci.h b/include/linux/pci.h index 0d29f5cdcb04..3c8eaa505991 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -921,6 +921,7 @@ void pci_remove_root_bus(struct pci_bus *bus); void pci_setup_cardbus(struct pci_bus *bus); void pcibios_setup_bridge(struct pci_bus *bus, unsigned long type); void pci_sort_breadthfirst(void); +bool pci_peer_traffic_supported(struct pci_dev *dev, struct pci_dev *peer); #define dev_is_pci(d) ((d)->bus == &pci_bus_type) #define dev_is_pf(d) ((dev_is_pci(d) ? to_pci_dev(d)->is_physfn : false)) -- 2.14.1 From mboxrd@z Thu Jan 1 00:00:00 1970 From: "=?UTF-8?q?Christian=20K=C3=B6nig?=" Subject: [PATCH 3/8] PCI: Add pci_peer_traffic_supported() Date: Sun, 25 Mar 2018 12:59:55 +0200 Message-ID: <20180325110000.2238-3-christian.koenig@amd.com> References: <20180325110000.2238-1-christian.koenig@amd.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <20180325110000.2238-1-christian.koenig-5C7GfCeVMHo@public.gmane.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: amd-gfx-bounces-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org Sender: "amd-gfx" To: linaro-mm-sig-cunTk1MwBs8s++Sfvej+rw@public.gmane.org, linux-media-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org, amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org List-Id: dri-devel@lists.freedesktop.org RnJvbTogIndkYXZpc0BudmlkaWEuY29tIiA8d2RhdmlzQG52aWRpYS5jb20+CgpBZGQgY2hlY2tz IGZvciB0b3BvbG9neSBhbmQgQUNTIGNvbmZpZ3VyYXRpb24gdG8gZGV0ZXJtaW5lIHdoZXRoZXIg b3Igbm90CnBlZXIgdHJhZmZpYyBzaG91bGQgYmUgc3VwcG9ydGVkIGJldHdlZW4gdHdvIFBDSSBk ZXZpY2VzLgoKU2lnbmVkLW9mZi1ieTogV2lsbCBEYXZpcyA8d2RhdmlzQG52aWRpYS5jb20+ClNp Z25lZC1vZmYtYnk6IENocmlzdGlhbiBLw7ZuaWcgPGNocmlzdGlhbi5rb2VuaWdAYW1kLmNvbT4K LS0tCiBkcml2ZXJzL3BjaS9wY2kuYyAgIHwgMTEyICsrKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysKIGluY2x1ZGUvbGludXgvcGNpLmggfCAgIDEgKwog MiBmaWxlcyBjaGFuZ2VkLCAxMTMgaW5zZXJ0aW9ucygrKQoKZGlmZiAtLWdpdCBhL2RyaXZlcnMv cGNpL3BjaS5jIGIvZHJpdmVycy9wY2kvcGNpLmMKaW5kZXggZjZhNGRkMTBkOWIwLi5lZmRjYTNj OWRhZDEgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvcGNpL3BjaS5jCisrKyBiL2RyaXZlcnMvcGNpL3Bj aS5jCkBAIC0yOCw2ICsyOCw3IEBACiAjaW5jbHVkZSA8bGludXgvZGV2aWNlLmg+CiAjaW5jbHVk ZSA8bGludXgvcG1fcnVudGltZS5oPgogI2luY2x1ZGUgPGxpbnV4L3BjaV9ob3RwbHVnLmg+Cisj aW5jbHVkZSA8bGludXgvaW9tbXUuaD4KICNpbmNsdWRlIDxsaW51eC92bWFsbG9jLmg+CiAjaW5j bHVkZSA8bGludXgvcGNpLWF0cy5oPgogI2luY2x1ZGUgPGFzbS9zZXR1cC5oPgpAQCAtNTI4NSw2 ICs1Mjg2LDExNyBAQCB2b2lkIHBjaV9pZ25vcmVfaG90cGx1ZyhzdHJ1Y3QgcGNpX2RldiAqZGV2 KQogfQogRVhQT1JUX1NZTUJPTF9HUEwocGNpX2lnbm9yZV9ob3RwbHVnKTsKIAorc3RhdGljIGJv b2wgcGNpX3BlZXJfaG9zdF90cmFmZmljX3N1cHBvcnRlZChzdHJ1Y3QgcGNpX2hvc3RfYnJpZGdl ICpob3N0KQoreworCXN0cnVjdCBwY2lfZGV2ICpicmlkZ2UgPSBwY2lfZ2V0X3Nsb3QoaG9zdC0+ YnVzLCBQQ0lfREVWRk4oMCwgMCkpOworCXVuc2lnbmVkIHNob3J0IHZlbmRvciwgZGV2aWNlOwor CisJaWYgKCFicmlkZ2UpCisJCXJldHVybiBmYWxzZTsKKworCXZlbmRvciA9IGJyaWRnZS0+dmVu ZG9yOworCWRldmljZSA9IGJyaWRnZS0+ZGV2aWNlOworCXBjaV9kZXZfcHV0KGJyaWRnZSk7CisK KwkvKiBBTUQgWkVOIGhvc3QgYnJpZGdlcyBjYW4gZG8gcGVlciB0byBwZWVyICovCisJaWYgKHZl bmRvciA9PSBQQ0lfVkVORE9SX0lEX0FNRCAmJiBkZXZpY2UgPT0gMHgxNDUwKQorCQlyZXR1cm4g dHJ1ZTsKKworCS8qIFRPRE86IEV4dGVuZCB0aGF0IHRvIGEgcHJvcGVyIHdoaXRlbGlzdCAqLwor CXJldHVybiBmYWxzZTsKK30KKworYm9vbCBwY2lfcGVlcl90cmFmZmljX3N1cHBvcnRlZChzdHJ1 Y3QgcGNpX2RldiAqZGV2LCBzdHJ1Y3QgcGNpX2RldiAqcGVlcikKK3sKKwlzdHJ1Y3QgcGNpX2Rl diAqcnBfZGV2LCAqcnBfcGVlciwgKmNvbW1vbl91cHN0cmVhbTsKKwlzdHJ1Y3QgcGNpX2hvc3Rf YnJpZGdlICpwZWVyX2hvc3RfYnJpZGdlOworCXN0cnVjdCBwY2lfaG9zdF9icmlkZ2UgKmRldl9o b3N0X2JyaWRnZTsKKwlpbnQgcG9zOworCXUxNiBjYXA7CisKKwkvKiBUaGlzIGlzIHRyaWNreSBl bm91Z2gsIGZvY3VzIG9uIFBDSWUgZm9yIG5vdyAqLworCWlmICghcGNpX2lzX3BjaWUoZGV2KSB8 fCAhcGNpX2lzX3BjaWUocGVlcikpCisJCXJldHVybiBmYWxzZTsKKworCS8qCisJICogRGlzYWxs b3cgdGhlIHBlZXItdG8tcGVlciB0cmFmZmljIGlmIHRoZSBkZXZpY2VzIGRvIG5vdCBzaGFyZSBh CisJICogaG9zdCBicmlkZ2UuIFRoZSBQQ0kgc3BlY2lmaWNhdGlvbnMgZG9lcyBub3QgbWFrZSBh bnkgZ3VhcmFudGVlcworCSAqIGFib3V0IFAyUCBjYXBhYmlsaXRpZXMgYmV0d2VlbiBkZXZpY2Vz IHVuZGVyIHNlcGFyYXRlIGRvbWFpbnMuCisJICoKKwkgKiBQQ0kgTG9jYWwgQnVzIFNwZWNpZmlj YXRpb24gUmV2aXNpb24gMy4wLCBzZWN0aW9uIDMuMTA6CisJICogICAgIlBlZXItdG8tcGVlciB0 cmFuc2FjdGlvbnMgY3Jvc3NpbmcgbXVsdGlwbGUgaG9zdCBicmlkZ2VzCisJICogICAgIFBDSSBo b3N0IGJyaWRnZXMgbWF5LCBidXQgYXJlIG5vdCByZXF1aXJlZCB0bywgc3VwcG9ydCBQQ0kKKwkg KiAgICAgcGVlci10by1wZWVyIHRyYW5zYWN0aW9ucyB0aGF0IHRyYXZlcnNlIG11bHRpcGxlIFBD SSBob3N0CisJICogICAgIGJyaWRnZXMuIgorCSAqLworCWRldl9ob3N0X2JyaWRnZSA9IHBjaV9m aW5kX2hvc3RfYnJpZGdlKGRldi0+YnVzKTsKKwlwZWVyX2hvc3RfYnJpZGdlID0gcGNpX2ZpbmRf aG9zdF9icmlkZ2UocGVlci0+YnVzKTsKKwlpZiAoZGV2X2hvc3RfYnJpZGdlICE9IHBlZXJfaG9z dF9icmlkZ2UpCisJCXJldHVybiBwY2lfcGVlcl9ob3N0X3RyYWZmaWNfc3VwcG9ydGVkKGRldl9o b3N0X2JyaWRnZSk7CisKKwlycF9kZXYgPSBwY2llX2ZpbmRfcm9vdF9wb3J0KGRldik7CisJcnBf cGVlciA9IHBjaWVfZmluZF9yb290X3BvcnQocGVlcik7CisJY29tbW9uX3Vwc3RyZWFtID0gcGNp X2ZpbmRfY29tbW9uX3Vwc3RyZWFtX2RldihkZXYsIHBlZXIpOworCisJLyoKKwkgKiBBY2Nlc3Mg Q29udHJvbCBTZXJ2aWNlcyAoQUNTKSBDaGVja3MKKwkgKgorCSAqIEFDUyBoYXMgYSBjYXBhYmls aXR5IGJpdCBmb3IgUDJQIFJlcXVlc3QgUmVkaXJlY3RzIChSUiksCisJICogYnV0IHVuZm9ydHVu YXRlbHkgaXQgZG9lc24ndCB0ZWxsIHVzIG11Y2ggYWJvdXQgdGhlIHJlYWwKKwkgKiBjYXBhYmls aXRpZXMgb2YgdGhlIGhhcmR3YXJlLgorCSAqCisJICogUENJIEV4cHJlc3MgQmFzZSBTcGVjaWZp Y2F0aW9uIFJldmlzaW9uIDMuMCwgc2VjdGlvbgorCSAqIDYuMTIuMS4xOgorCSAqICAgICJBQ1Mg UDJQIFJlcXVlc3QgUmVkaXJlY3Q6IG11c3QgYmUgaW1wbGVtZW50ZWQgYnkgUm9vdAorCSAqICAg ICBQb3J0cyB0aGF0IHN1cHBvcnQgcGVlci10by1wZWVyIHRyYWZmaWMgd2l0aCBvdGhlcgorCSAq ICAgICBSb290IFBvcnRzOyBbODBdIgorCSAqIGJ1dAorCSAqICAgICJbODBdIFJvb3QgUG9ydCBp bmRpY2F0aW9uIG9mIEFDUyBQMlAgUmVxdWVzdCBSZWRpcmVjdAorCSAqICAgICBvciBBQ1MgUDJQ IENvbXBsZXRpb24gUmVkaXJlY3Qgc3VwcG9ydCBkb2VzIG5vdCBpbXBseQorCSAqICAgICBhbnkg cGFydGljdWxhciBsZXZlbCBvZiBwZWVyLXRvLXBlZXIgc3VwcG9ydCBieSB0aGUKKwkgKiAgICAg Um9vdCBDb21wbGV4LCBvciB0aGF0IHBlZXItdG8tcGVlciB0cmFmZmljIGlzCisJICogICAgIHN1 cHBvcnRlZCBhdCBhbGwiCisJICovCisKKwkvKgorCSAqIElmIEFDUyBpcyBub3QgaW1wbGVtZW50 ZWQsIHdlIGhhdmUgbm8gaWRlYSBhYm91dCBQMlAKKwkgKiBzdXBwb3J0LiBPcHRpbWlzdGljYWxs eSBhbGxvdyB0aGlzIGlmIHRoZXJlIGlzIGEgY29tbW9uCisJICogdXBzdHJlYW0gZGV2aWNlLgor CSAqLworCXBvcyA9IHBjaV9maW5kX2V4dF9jYXBhYmlsaXR5KHJwX2RldiwgUENJX0VYVF9DQVBf SURfQUNTKTsKKwlpZiAoIXBvcykKKwkJcmV0dXJuIGNvbW1vbl91cHN0cmVhbSAhPSBOVUxMOwor CisJLyoKKwkgKiBJZiB0aGUgZGV2aWNlcyBhcmUgdW5kZXIgdGhlIHNhbWUgcm9vdCBwb3J0IGFu ZCBoYXZlIGEgY29tbW9uCisJICogdXBzdHJlYW0gZGV2aWNlLCBhbGxvdyBpZiB0aGUgcm9vdCBw b3J0IGlzIGZ1cnRoZXIgdXBzdHJlYW0KKwkgKiBmcm9tIHRoZSBjb21tb24gdXBzdHJlYW0gZGV2 aWNlIGFuZCB0aGUgY29tbW9uIHVwc3RyZWFtCisJICogZGV2aWNlIGhhcyBVcHN0cmVhbSBGb3J3 YXJkaW5nIGRpc2FibGVkLCBvciBpZiB0aGUgcm9vdCBwb3J0CisJICogaXMgdGhlIGNvbW1vbiB1 cHN0cmVhbSBkZXZpY2UgYW5kIEFDUyBpcyBub3QgaW1wbGVtZW50ZWQuCisJICovCisJcGNpX3Jl YWRfY29uZmlnX3dvcmQocnBfZGV2LCBwb3MgKyBQQ0lfQUNTX0NBUCwgJmNhcCk7CisJaWYgKChy cF9kZXYgPT0gcnBfcGVlciAmJiBjb21tb25fdXBzdHJlYW0pICYmCisJICAgICgoKGNvbW1vbl91 cHN0cmVhbSAhPSBycF9kZXYpICYmCisJICAgICAgIXBjaV9hY3NfZW5hYmxlZChjb21tb25fdXBz dHJlYW0sIFBDSV9BQ1NfVUYpKSB8fAorCSAgICAgKChjb21tb25fdXBzdHJlYW0gPT0gcnBfZGV2 KSAmJiAoKGNhcCAmIFBDSV9BQ1NfUlIpID09IDApKSkpCisJCXJldHVybiB0cnVlOworCisJLyoK KwkgKiBJZiBBQ1MgUlIgaXMgaW1wbGVtZW50ZWQgYW5kIGRpc2FibGVkLCBhbGxvdyBvbmx5IGlm IHRoZQorCSAqIGRldmljZXMgYXJlIHVuZGVyIHRoZSBzYW1lIHJvb3QgcG9ydC4KKwkgKi8KKwlp ZiAoY2FwICYgUENJX0FDU19SUiAmJiAhcGNpX2Fjc19lbmFibGVkKHJwX2RldiwgUENJX0FDU19S UikpCisJCXJldHVybiBycF9kZXYgPT0gcnBfcGVlcjsKKworCS8qCisJICogSWYgQUNTIFJSIGlz IG5vdCBpbXBsZW1lbnRlZCwgb3IgaXMgaW1wbGVtZW50ZWQgYW5kIGVuYWJsZWQsCisJICogb25s eSBhbGxvdyBpZiB0aGVyZSdzIGEgdHJhbnNsYXRpb24gYWdlbnQgZW5hYmxlZCB0byBkbyB0aGUK KwkgKiByZWRpcmVjdC4KKwkgKi8KKwlyZXR1cm4gaW9tbXVfcHJlc2VudCgmcGNpX2J1c190eXBl KTsKK30KK0VYUE9SVF9TWU1CT0wocGNpX3BlZXJfdHJhZmZpY19zdXBwb3J0ZWQpOworCiByZXNv dXJjZV9zaXplX3QgX193ZWFrIHBjaWJpb3NfZGVmYXVsdF9hbGlnbm1lbnQodm9pZCkKIHsKIAly ZXR1cm4gMDsKZGlmZiAtLWdpdCBhL2luY2x1ZGUvbGludXgvcGNpLmggYi9pbmNsdWRlL2xpbnV4 L3BjaS5oCmluZGV4IDBkMjlmNWNkY2IwNC4uM2M4ZWFhNTA1OTkxIDEwMDY0NAotLS0gYS9pbmNs dWRlL2xpbnV4L3BjaS5oCisrKyBiL2luY2x1ZGUvbGludXgvcGNpLmgKQEAgLTkyMSw2ICs5MjEs NyBAQCB2b2lkIHBjaV9yZW1vdmVfcm9vdF9idXMoc3RydWN0IHBjaV9idXMgKmJ1cyk7CiB2b2lk IHBjaV9zZXR1cF9jYXJkYnVzKHN0cnVjdCBwY2lfYnVzICpidXMpOwogdm9pZCBwY2liaW9zX3Nl dHVwX2JyaWRnZShzdHJ1Y3QgcGNpX2J1cyAqYnVzLCB1bnNpZ25lZCBsb25nIHR5cGUpOwogdm9p ZCBwY2lfc29ydF9icmVhZHRoZmlyc3Qodm9pZCk7Citib29sIHBjaV9wZWVyX3RyYWZmaWNfc3Vw cG9ydGVkKHN0cnVjdCBwY2lfZGV2ICpkZXYsIHN0cnVjdCBwY2lfZGV2ICpwZWVyKTsKICNkZWZp bmUgZGV2X2lzX3BjaShkKSAoKGQpLT5idXMgPT0gJnBjaV9idXNfdHlwZSkKICNkZWZpbmUgZGV2 X2lzX3BmKGQpICgoZGV2X2lzX3BjaShkKSA/IHRvX3BjaV9kZXYoZCktPmlzX3BoeXNmbiA6IGZh bHNlKSkKIAotLSAKMi4xNC4xCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fXwphbWQtZ2Z4IG1haWxpbmcgbGlzdAphbWQtZ2Z4QGxpc3RzLmZyZWVkZXNrdG9w Lm9yZwpodHRwczovL2xpc3RzLmZyZWVkZXNrdG9wLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2FtZC1n ZngK