From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753448AbdJFJHG (ORCPT ); Fri, 6 Oct 2017 05:07:06 -0400 Received: from mail-wm0-f68.google.com ([74.125.82.68]:36811 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753002AbdJFJGq (ORCPT ); Fri, 6 Oct 2017 05:06:46 -0400 X-Google-Smtp-Source: AOwi7QB/8gmCOq/5jGEdhAobGlC+iC+nbpExQ1+WY7JfCWgeyFhF5MZvL3Z0XeW0snVkjwPNGkZJOA== From: Daniel Vetter To: Intel Graphics Development Cc: LKML , Daniel Vetter , Chris Wilson , Mika Kuoppala , Thomas Gleixner , Marta Lofstedt , Daniel Vetter Subject: [PATCH 2/2] drm/i915: Use rcu instead of stop_machine in set_wedged Date: Fri, 6 Oct 2017 11:06:37 +0200 Message-Id: <20171006090637.25545-2-daniel.vetter@ffwll.ch> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20171006090637.25545-1-daniel.vetter@ffwll.ch> References: <20171006090637.25545-1-daniel.vetter@ffwll.ch> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org stop_machine is not really a locking primitive we should use, except when the hw folks tell us the hw is broken and that's the only way to work around it. This patch tries to address the locking abuse of stop_machine() from commit 20e4933c478a1ca694b38fa4ac44d99e659941f5 Author: Chris Wilson Date: Tue Nov 22 14:41:21 2016 +0000 drm/i915: Stop the machine as we install the wedged submit_request handler Chris said parts of the reasons for going with stop_machine() was that it's no overhead for the fast-path. But these callbacks use irqsave spinlocks and do a bunch of MMIO, and rcu_read_lock is _real_ fast. To stay as close as possible to the stop_machine semantics we first update all the submit function pointers to the nop handler, then call synchronize_rcu() to make sure no new requests can be submitted. This should give us exactly the huge barrier we want. I pondered whether we should annotate engine->submit_request as __rcu and use rcu_assign_pointer and rcu_dereference on it. But the reason behind those is to make sure the compiler/cpu barriers are there for when you have an actual data structure you point at, to make sure all the writes are seen correctly on the read side. But we just have a function pointer, and .text isn't changed, so no need for these barriers and hence no need for annotations. This should fix the followwing lockdep splat: ====================================================== WARNING: possible circular locking dependency detected 4.14.0-rc3-CI-CI_DRM_3179+ #1 Tainted: G U ------------------------------------------------------ kworker/3:4/562 is trying to acquire lock: (cpu_hotplug_lock.rw_sem){++++}, at: [] stop_machine+0x1c/0x40 but task is already holding lock: (&dev->struct_mutex){+.+.}, at: [] i915_reset_device+0x1e8/0x260 [i915] which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #6 (&dev->struct_mutex){+.+.}: __lock_acquire+0x1420/0x15e0 lock_acquire+0xb0/0x200 __mutex_lock+0x86/0x9b0 mutex_lock_interruptible_nested+0x1b/0x20 i915_mutex_lock_interruptible+0x51/0x130 [i915] i915_gem_fault+0x209/0x650 [i915] __do_fault+0x1e/0x80 __handle_mm_fault+0xa08/0xed0 handle_mm_fault+0x156/0x300 __do_page_fault+0x2c5/0x570 do_page_fault+0x28/0x250 page_fault+0x22/0x30 -> #5 (&mm->mmap_sem){++++}: __lock_acquire+0x1420/0x15e0 lock_acquire+0xb0/0x200 __might_fault+0x68/0x90 _copy_to_user+0x23/0x70 filldir+0xa5/0x120 dcache_readdir+0xf9/0x170 iterate_dir+0x69/0x1a0 SyS_getdents+0xa5/0x140 entry_SYSCALL_64_fastpath+0x1c/0xb1 -> #4 (&sb->s_type->i_mutex_key#5){++++}: down_write+0x3b/0x70 handle_create+0xcb/0x1e0 devtmpfsd+0x139/0x180 kthread+0x152/0x190 ret_from_fork+0x27/0x40 -> #3 ((complete)&req.done){+.+.}: __lock_acquire+0x1420/0x15e0 lock_acquire+0xb0/0x200 wait_for_common+0x58/0x210 wait_for_completion+0x1d/0x20 devtmpfs_create_node+0x13d/0x160 device_add+0x5eb/0x620 device_create_groups_vargs+0xe0/0xf0 device_create+0x3a/0x40 msr_device_create+0x2b/0x40 cpuhp_invoke_callback+0xc9/0xbf0 cpuhp_thread_fun+0x17b/0x240 smpboot_thread_fn+0x18a/0x280 kthread+0x152/0x190 ret_from_fork+0x27/0x40 -> #2 (cpuhp_state-up){+.+.}: __lock_acquire+0x1420/0x15e0 lock_acquire+0xb0/0x200 cpuhp_issue_call+0x133/0x1c0 __cpuhp_setup_state_cpuslocked+0x139/0x2a0 __cpuhp_setup_state+0x46/0x60 page_writeback_init+0x43/0x67 pagecache_init+0x3d/0x42 start_kernel+0x3a8/0x3fc x86_64_start_reservations+0x2a/0x2c x86_64_start_kernel+0x6d/0x70 verify_cpu+0x0/0xfb -> #1 (cpuhp_state_mutex){+.+.}: __lock_acquire+0x1420/0x15e0 lock_acquire+0xb0/0x200 __mutex_lock+0x86/0x9b0 mutex_lock_nested+0x1b/0x20 __cpuhp_setup_state_cpuslocked+0x53/0x2a0 __cpuhp_setup_state+0x46/0x60 page_alloc_init+0x28/0x30 start_kernel+0x145/0x3fc x86_64_start_reservations+0x2a/0x2c x86_64_start_kernel+0x6d/0x70 verify_cpu+0x0/0xfb -> #0 (cpu_hotplug_lock.rw_sem){++++}: check_prev_add+0x430/0x840 __lock_acquire+0x1420/0x15e0 lock_acquire+0xb0/0x200 cpus_read_lock+0x3d/0xb0 stop_machine+0x1c/0x40 i915_gem_set_wedged+0x1a/0x20 [i915] i915_reset+0xb9/0x230 [i915] i915_reset_device+0x1f6/0x260 [i915] i915_handle_error+0x2d8/0x430 [i915] hangcheck_declare_hang+0xd3/0xf0 [i915] i915_hangcheck_elapsed+0x262/0x2d0 [i915] process_one_work+0x233/0x660 worker_thread+0x4e/0x3b0 kthread+0x152/0x190 ret_from_fork+0x27/0x40 other info that might help us debug this: Chain exists of: cpu_hotplug_lock.rw_sem --> &mm->mmap_sem --> &dev->struct_mutex Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&dev->struct_mutex); lock(&mm->mmap_sem); lock(&dev->struct_mutex); lock(cpu_hotplug_lock.rw_sem); *** DEADLOCK *** 3 locks held by kworker/3:4/562: #0: ("events_long"){+.+.}, at: [] process_one_work+0x1aa/0x660 #1: ((&(&i915->gpu_error.hangcheck_work)->work)){+.+.}, at: [] process_one_work+0x1aa/0x660 #2: (&dev->struct_mutex){+.+.}, at: [] i915_reset_device+0x1e8/0x260 [i915] stack backtrace: CPU: 3 PID: 562 Comm: kworker/3:4 Tainted: G U 4.14.0-rc3-CI-CI_DRM_3179+ #1 Hardware name: /NUC7i5BNB, BIOS BNKBL357.86A.0048.2017.0704.1415 07/04/2017 Workqueue: events_long i915_hangcheck_elapsed [i915] Call Trace: dump_stack+0x68/0x9f print_circular_bug+0x235/0x3c0 ? lockdep_init_map_crosslock+0x20/0x20 check_prev_add+0x430/0x840 ? irq_work_queue+0x86/0xe0 ? wake_up_klogd+0x53/0x70 __lock_acquire+0x1420/0x15e0 ? __lock_acquire+0x1420/0x15e0 ? lockdep_init_map_crosslock+0x20/0x20 lock_acquire+0xb0/0x200 ? stop_machine+0x1c/0x40 ? i915_gem_object_truncate+0x50/0x50 [i915] cpus_read_lock+0x3d/0xb0 ? stop_machine+0x1c/0x40 stop_machine+0x1c/0x40 i915_gem_set_wedged+0x1a/0x20 [i915] i915_reset+0xb9/0x230 [i915] i915_reset_device+0x1f6/0x260 [i915] ? gen8_gt_irq_ack+0x170/0x170 [i915] ? work_on_cpu_safe+0x60/0x60 i915_handle_error+0x2d8/0x430 [i915] ? vsnprintf+0xd1/0x4b0 ? scnprintf+0x3a/0x70 hangcheck_declare_hang+0xd3/0xf0 [i915] ? intel_runtime_pm_put+0x56/0xa0 [i915] i915_hangcheck_elapsed+0x262/0x2d0 [i915] process_one_work+0x233/0x660 worker_thread+0x4e/0x3b0 kthread+0x152/0x190 ? process_one_work+0x660/0x660 ? kthread_create_on_node+0x40/0x40 ret_from_fork+0x27/0x40 Setting dangerous option reset - tainting kernel i915 0000:00:02.0: Resetting chip after gpu hang Setting dangerous option reset - tainting kernel i915 0000:00:02.0: Resetting chip after gpu hang v2: Have 1 global synchronize_rcu() barrier across all engines, and improve commit message. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=102886 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103096 Cc: Chris Wilson Cc: Mika Kuoppala Cc: Thomas Gleixner Cc: Marta Lofstedt Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 31 +++++++++-------------- drivers/gpu/drm/i915/i915_gem_request.c | 2 ++ drivers/gpu/drm/i915/selftests/i915_gem_request.c | 2 ++ 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index ab8c6946fea4..e79a6ca60265 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3020,16 +3020,8 @@ static void nop_submit_request(struct drm_i915_gem_request *request) intel_engine_init_global_seqno(request->engine, request->global_seqno); } -static void engine_set_wedged(struct intel_engine_cs *engine) +static void engine_complete_requests(struct intel_engine_cs *engine) { - /* We need to be sure that no thread is running the old callback as - * we install the nop handler (otherwise we would submit a request - * to hardware that will never complete). In order to prevent this - * race, we wait until the machine is idle before making the swap - * (using stop_machine()). - */ - engine->submit_request = nop_submit_request; - /* Mark all executing requests as skipped */ engine->cancel_requests(engine); @@ -3041,24 +3033,25 @@ static void engine_set_wedged(struct intel_engine_cs *engine) intel_engine_last_submit(engine)); } -static int __i915_gem_set_wedged_BKL(void *data) +void i915_gem_set_wedged(struct drm_i915_private *i915) { - struct drm_i915_private *i915 = data; struct intel_engine_cs *engine; enum intel_engine_id id; for_each_engine(engine, i915, id) - engine_set_wedged(engine); + engine->submit_request = nop_submit_request; - set_bit(I915_WEDGED, &i915->gpu_error.flags); - wake_up_all(&i915->gpu_error.reset_queue); + /* Make sure no one is running the old callback before we proceed with + * cancelling requests and resetting the completion tracking. Otherwise + * we might submit a request to the hardware which never completes. + */ + synchronize_rcu(); - return 0; -} + for_each_engine(engine, i915, id) + engine_complete_requests(engine); -void i915_gem_set_wedged(struct drm_i915_private *dev_priv) -{ - stop_machine(__i915_gem_set_wedged_BKL, dev_priv, NULL); + set_bit(I915_WEDGED, &i915->gpu_error.flags); + wake_up_all(&i915->gpu_error.reset_queue); } bool i915_gem_unset_wedged(struct drm_i915_private *i915) diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index b100b38f1dd2..ef78a85cb845 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -556,7 +556,9 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) switch (state) { case FENCE_COMPLETE: trace_i915_gem_request_submit(request); + rcu_read_lock(); request->engine->submit_request(request); + rcu_read_unlock(); break; case FENCE_FREE: diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_request.c b/drivers/gpu/drm/i915/selftests/i915_gem_request.c index 78b9f811707f..a999161e8db1 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_request.c @@ -215,7 +215,9 @@ static int igt_request_rewind(void *arg) } i915_gem_request_get(vip); i915_add_request(vip); + rcu_read_lock(); request->engine->submit_request(request); + rcu_read_unlock(); mutex_unlock(&i915->drm.struct_mutex); -- 2.14.1 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Daniel Vetter Subject: [PATCH 2/2] drm/i915: Use rcu instead of stop_machine in set_wedged Date: Fri, 6 Oct 2017 11:06:37 +0200 Message-ID: <20171006090637.25545-2-daniel.vetter@ffwll.ch> References: <20171006090637.25545-1-daniel.vetter@ffwll.ch> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Received: from mail-wm0-x242.google.com (mail-wm0-x242.google.com [IPv6:2a00:1450:400c:c09::242]) by gabe.freedesktop.org (Postfix) with ESMTPS id B1EE16E8EC for ; Fri, 6 Oct 2017 09:06:46 +0000 (UTC) Received: by mail-wm0-x242.google.com with SMTP id l10so8346972wmg.1 for ; Fri, 06 Oct 2017 02:06:46 -0700 (PDT) In-Reply-To: <20171006090637.25545-1-daniel.vetter@ffwll.ch> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" To: Intel Graphics Development Cc: Daniel Vetter , LKML , Daniel Vetter , Thomas Gleixner , Mika Kuoppala List-Id: intel-gfx@lists.freedesktop.org c3RvcF9tYWNoaW5lIGlzIG5vdCByZWFsbHkgYSBsb2NraW5nIHByaW1pdGl2ZSB3ZSBzaG91bGQg dXNlLCBleGNlcHQKd2hlbiB0aGUgaHcgZm9sa3MgdGVsbCB1cyB0aGUgaHcgaXMgYnJva2VuIGFu ZCB0aGF0J3MgdGhlIG9ubHkgd2F5IHRvCndvcmsgYXJvdW5kIGl0LgoKVGhpcyBwYXRjaCB0cmll cyB0byBhZGRyZXNzIHRoZSBsb2NraW5nIGFidXNlIG9mIHN0b3BfbWFjaGluZSgpIGZyb20KCmNv bW1pdCAyMGU0OTMzYzQ3OGExY2E2OTRiMzhmYTRhYzQ0ZDk5ZTY1OTk0MWY1CkF1dGhvcjogQ2hy aXMgV2lsc29uIDxjaHJpc0BjaHJpcy13aWxzb24uY28udWs+CkRhdGU6ICAgVHVlIE5vdiAyMiAx NDo0MToyMSAyMDE2ICswMDAwCgogICAgZHJtL2k5MTU6IFN0b3AgdGhlIG1hY2hpbmUgYXMgd2Ug aW5zdGFsbCB0aGUgd2VkZ2VkIHN1Ym1pdF9yZXF1ZXN0IGhhbmRsZXIKCkNocmlzIHNhaWQgcGFy dHMgb2YgdGhlIHJlYXNvbnMgZm9yIGdvaW5nIHdpdGggc3RvcF9tYWNoaW5lKCkgd2FzIHRoYXQK aXQncyBubyBvdmVyaGVhZCBmb3IgdGhlIGZhc3QtcGF0aC4gQnV0IHRoZXNlIGNhbGxiYWNrcyB1 c2UgaXJxc2F2ZQpzcGlubG9ja3MgYW5kIGRvIGEgYnVuY2ggb2YgTU1JTywgYW5kIHJjdV9yZWFk X2xvY2sgaXMgX3JlYWxfIGZhc3QuCgpUbyBzdGF5IGFzIGNsb3NlIGFzIHBvc3NpYmxlIHRvIHRo ZSBzdG9wX21hY2hpbmUgc2VtYW50aWNzIHdlIGZpcnN0CnVwZGF0ZSBhbGwgdGhlIHN1Ym1pdCBm dW5jdGlvbiBwb2ludGVycyB0byB0aGUgbm9wIGhhbmRsZXIsIHRoZW4gY2FsbApzeW5jaHJvbml6 ZV9yY3UoKSB0byBtYWtlIHN1cmUgbm8gbmV3IHJlcXVlc3RzIGNhbiBiZSBzdWJtaXR0ZWQuIFRo aXMKc2hvdWxkIGdpdmUgdXMgZXhhY3RseSB0aGUgaHVnZSBiYXJyaWVyIHdlIHdhbnQuCgpJIHBv bmRlcmVkIHdoZXRoZXIgd2Ugc2hvdWxkIGFubm90YXRlIGVuZ2luZS0+c3VibWl0X3JlcXVlc3Qg YXMgX19yY3UKYW5kIHVzZSByY3VfYXNzaWduX3BvaW50ZXIgYW5kIHJjdV9kZXJlZmVyZW5jZSBv biBpdC4gQnV0IHRoZSByZWFzb24KYmVoaW5kIHRob3NlIGlzIHRvIG1ha2Ugc3VyZSB0aGUgY29t cGlsZXIvY3B1IGJhcnJpZXJzIGFyZSB0aGVyZSBmb3IKd2hlbiB5b3UgaGF2ZSBhbiBhY3R1YWwg ZGF0YSBzdHJ1Y3R1cmUgeW91IHBvaW50IGF0LCB0byBtYWtlIHN1cmUgYWxsCnRoZSB3cml0ZXMg YXJlIHNlZW4gY29ycmVjdGx5IG9uIHRoZSByZWFkIHNpZGUuIEJ1dCB3ZSBqdXN0IGhhdmUgYQpm dW5jdGlvbiBwb2ludGVyLCBhbmQgLnRleHQgaXNuJ3QgY2hhbmdlZCwgc28gbm8gbmVlZCBmb3Ig dGhlc2UKYmFycmllcnMgYW5kIGhlbmNlIG5vIG5lZWQgZm9yIGFubm90YXRpb25zLgoKVGhpcyBz aG91bGQgZml4IHRoZSBmb2xsb3d3aW5nIGxvY2tkZXAgc3BsYXQ6Cgo9PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KV0FSTklORzogcG9zc2libGUg Y2lyY3VsYXIgbG9ja2luZyBkZXBlbmRlbmN5IGRldGVjdGVkCjQuMTQuMC1yYzMtQ0ktQ0lfRFJN XzMxNzkrICMxIFRhaW50ZWQ6IEcgICAgIFUKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCmt3b3JrZXIvMzo0LzU2MiBpcyB0cnlpbmcgdG8gYWNx dWlyZSBsb2NrOgogKGNwdV9ob3RwbHVnX2xvY2sucndfc2VtKXsrKysrfSwgYXQ6IFs8ZmZmZmZm ZmY4MTEzZDRiYz5dIHN0b3BfbWFjaGluZSsweDFjLzB4NDAKCmJ1dCB0YXNrIGlzIGFscmVhZHkg aG9sZGluZyBsb2NrOgogKCZkZXYtPnN0cnVjdF9tdXRleCl7Ky4rLn0sIGF0OiBbPGZmZmZmZmZm YTAxMzY1ODg+XSBpOTE1X3Jlc2V0X2RldmljZSsweDFlOC8weDI2MCBbaTkxNV0KCndoaWNoIGxv Y2sgYWxyZWFkeSBkZXBlbmRzIG9uIHRoZSBuZXcgbG9jay4KCnRoZSBleGlzdGluZyBkZXBlbmRl bmN5IGNoYWluIChpbiByZXZlcnNlIG9yZGVyKSBpczoKCi0+ICM2ICgmZGV2LT5zdHJ1Y3RfbXV0 ZXgpeysuKy59OgogICAgICAgX19sb2NrX2FjcXVpcmUrMHgxNDIwLzB4MTVlMAogICAgICAgbG9j a19hY3F1aXJlKzB4YjAvMHgyMDAKICAgICAgIF9fbXV0ZXhfbG9jaysweDg2LzB4OWIwCiAgICAg ICBtdXRleF9sb2NrX2ludGVycnVwdGlibGVfbmVzdGVkKzB4MWIvMHgyMAogICAgICAgaTkxNV9t dXRleF9sb2NrX2ludGVycnVwdGlibGUrMHg1MS8weDEzMCBbaTkxNV0KICAgICAgIGk5MTVfZ2Vt X2ZhdWx0KzB4MjA5LzB4NjUwIFtpOTE1XQogICAgICAgX19kb19mYXVsdCsweDFlLzB4ODAKICAg ICAgIF9faGFuZGxlX21tX2ZhdWx0KzB4YTA4LzB4ZWQwCiAgICAgICBoYW5kbGVfbW1fZmF1bHQr MHgxNTYvMHgzMDAKICAgICAgIF9fZG9fcGFnZV9mYXVsdCsweDJjNS8weDU3MAogICAgICAgZG9f cGFnZV9mYXVsdCsweDI4LzB4MjUwCiAgICAgICBwYWdlX2ZhdWx0KzB4MjIvMHgzMAoKLT4gIzUg KCZtbS0+bW1hcF9zZW0peysrKyt9OgogICAgICAgX19sb2NrX2FjcXVpcmUrMHgxNDIwLzB4MTVl MAogICAgICAgbG9ja19hY3F1aXJlKzB4YjAvMHgyMDAKICAgICAgIF9fbWlnaHRfZmF1bHQrMHg2 OC8weDkwCiAgICAgICBfY29weV90b191c2VyKzB4MjMvMHg3MAogICAgICAgZmlsbGRpcisweGE1 LzB4MTIwCiAgICAgICBkY2FjaGVfcmVhZGRpcisweGY5LzB4MTcwCiAgICAgICBpdGVyYXRlX2Rp cisweDY5LzB4MWEwCiAgICAgICBTeVNfZ2V0ZGVudHMrMHhhNS8weDE0MAogICAgICAgZW50cnlf U1lTQ0FMTF82NF9mYXN0cGF0aCsweDFjLzB4YjEKCi0+ICM0ICgmc2ItPnNfdHlwZS0+aV9tdXRl eF9rZXkjNSl7KysrK306CiAgICAgICBkb3duX3dyaXRlKzB4M2IvMHg3MAogICAgICAgaGFuZGxl X2NyZWF0ZSsweGNiLzB4MWUwCiAgICAgICBkZXZ0bXBmc2QrMHgxMzkvMHgxODAKICAgICAgIGt0 aHJlYWQrMHgxNTIvMHgxOTAKICAgICAgIHJldF9mcm9tX2ZvcmsrMHgyNy8weDQwCgotPiAjMyAo KGNvbXBsZXRlKSZyZXEuZG9uZSl7Ky4rLn06CiAgICAgICBfX2xvY2tfYWNxdWlyZSsweDE0MjAv MHgxNWUwCiAgICAgICBsb2NrX2FjcXVpcmUrMHhiMC8weDIwMAogICAgICAgd2FpdF9mb3JfY29t bW9uKzB4NTgvMHgyMTAKICAgICAgIHdhaXRfZm9yX2NvbXBsZXRpb24rMHgxZC8weDIwCiAgICAg ICBkZXZ0bXBmc19jcmVhdGVfbm9kZSsweDEzZC8weDE2MAogICAgICAgZGV2aWNlX2FkZCsweDVl Yi8weDYyMAogICAgICAgZGV2aWNlX2NyZWF0ZV9ncm91cHNfdmFyZ3MrMHhlMC8weGYwCiAgICAg ICBkZXZpY2VfY3JlYXRlKzB4M2EvMHg0MAogICAgICAgbXNyX2RldmljZV9jcmVhdGUrMHgyYi8w eDQwCiAgICAgICBjcHVocF9pbnZva2VfY2FsbGJhY2srMHhjOS8weGJmMAogICAgICAgY3B1aHBf dGhyZWFkX2Z1bisweDE3Yi8weDI0MAogICAgICAgc21wYm9vdF90aHJlYWRfZm4rMHgxOGEvMHgy ODAKICAgICAgIGt0aHJlYWQrMHgxNTIvMHgxOTAKICAgICAgIHJldF9mcm9tX2ZvcmsrMHgyNy8w eDQwCgotPiAjMiAoY3B1aHBfc3RhdGUtdXApeysuKy59OgogICAgICAgX19sb2NrX2FjcXVpcmUr MHgxNDIwLzB4MTVlMAogICAgICAgbG9ja19hY3F1aXJlKzB4YjAvMHgyMDAKICAgICAgIGNwdWhw X2lzc3VlX2NhbGwrMHgxMzMvMHgxYzAKICAgICAgIF9fY3B1aHBfc2V0dXBfc3RhdGVfY3B1c2xv Y2tlZCsweDEzOS8weDJhMAogICAgICAgX19jcHVocF9zZXR1cF9zdGF0ZSsweDQ2LzB4NjAKICAg ICAgIHBhZ2Vfd3JpdGViYWNrX2luaXQrMHg0My8weDY3CiAgICAgICBwYWdlY2FjaGVfaW5pdCsw eDNkLzB4NDIKICAgICAgIHN0YXJ0X2tlcm5lbCsweDNhOC8weDNmYwogICAgICAgeDg2XzY0X3N0 YXJ0X3Jlc2VydmF0aW9ucysweDJhLzB4MmMKICAgICAgIHg4Nl82NF9zdGFydF9rZXJuZWwrMHg2 ZC8weDcwCiAgICAgICB2ZXJpZnlfY3B1KzB4MC8weGZiCgotPiAjMSAoY3B1aHBfc3RhdGVfbXV0 ZXgpeysuKy59OgogICAgICAgX19sb2NrX2FjcXVpcmUrMHgxNDIwLzB4MTVlMAogICAgICAgbG9j a19hY3F1aXJlKzB4YjAvMHgyMDAKICAgICAgIF9fbXV0ZXhfbG9jaysweDg2LzB4OWIwCiAgICAg ICBtdXRleF9sb2NrX25lc3RlZCsweDFiLzB4MjAKICAgICAgIF9fY3B1aHBfc2V0dXBfc3RhdGVf Y3B1c2xvY2tlZCsweDUzLzB4MmEwCiAgICAgICBfX2NwdWhwX3NldHVwX3N0YXRlKzB4NDYvMHg2 MAogICAgICAgcGFnZV9hbGxvY19pbml0KzB4MjgvMHgzMAogICAgICAgc3RhcnRfa2VybmVsKzB4 MTQ1LzB4M2ZjCiAgICAgICB4ODZfNjRfc3RhcnRfcmVzZXJ2YXRpb25zKzB4MmEvMHgyYwogICAg ICAgeDg2XzY0X3N0YXJ0X2tlcm5lbCsweDZkLzB4NzAKICAgICAgIHZlcmlmeV9jcHUrMHgwLzB4 ZmIKCi0+ICMwIChjcHVfaG90cGx1Z19sb2NrLnJ3X3NlbSl7KysrK306CiAgICAgICBjaGVja19w cmV2X2FkZCsweDQzMC8weDg0MAogICAgICAgX19sb2NrX2FjcXVpcmUrMHgxNDIwLzB4MTVlMAog ICAgICAgbG9ja19hY3F1aXJlKzB4YjAvMHgyMDAKICAgICAgIGNwdXNfcmVhZF9sb2NrKzB4M2Qv MHhiMAogICAgICAgc3RvcF9tYWNoaW5lKzB4MWMvMHg0MAogICAgICAgaTkxNV9nZW1fc2V0X3dl ZGdlZCsweDFhLzB4MjAgW2k5MTVdCiAgICAgICBpOTE1X3Jlc2V0KzB4YjkvMHgyMzAgW2k5MTVd CiAgICAgICBpOTE1X3Jlc2V0X2RldmljZSsweDFmNi8weDI2MCBbaTkxNV0KICAgICAgIGk5MTVf aGFuZGxlX2Vycm9yKzB4MmQ4LzB4NDMwIFtpOTE1XQogICAgICAgaGFuZ2NoZWNrX2RlY2xhcmVf aGFuZysweGQzLzB4ZjAgW2k5MTVdCiAgICAgICBpOTE1X2hhbmdjaGVja19lbGFwc2VkKzB4MjYy LzB4MmQwIFtpOTE1XQogICAgICAgcHJvY2Vzc19vbmVfd29yaysweDIzMy8weDY2MAogICAgICAg d29ya2VyX3RocmVhZCsweDRlLzB4M2IwCiAgICAgICBrdGhyZWFkKzB4MTUyLzB4MTkwCiAgICAg ICByZXRfZnJvbV9mb3JrKzB4MjcvMHg0MAoKb3RoZXIgaW5mbyB0aGF0IG1pZ2h0IGhlbHAgdXMg ZGVidWcgdGhpczoKCkNoYWluIGV4aXN0cyBvZjoKICBjcHVfaG90cGx1Z19sb2NrLnJ3X3NlbSAt LT4gJm1tLT5tbWFwX3NlbSAtLT4gJmRldi0+c3RydWN0X211dGV4CgogUG9zc2libGUgdW5zYWZl IGxvY2tpbmcgc2NlbmFyaW86CgogICAgICAgQ1BVMCAgICAgICAgICAgICAgICAgICAgQ1BVMQog ICAgICAgLS0tLSAgICAgICAgICAgICAgICAgICAgLS0tLQogIGxvY2soJmRldi0+c3RydWN0X211 dGV4KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2soJm1tLT5tbWFwX3NlbSk7 CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NrKCZkZXYtPnN0cnVjdF9tdXRleCk7 CiAgbG9jayhjcHVfaG90cGx1Z19sb2NrLnJ3X3NlbSk7CgogKioqIERFQURMT0NLICoqKgoKMyBs b2NrcyBoZWxkIGJ5IGt3b3JrZXIvMzo0LzU2MjoKICMwOiAgKCJldmVudHNfbG9uZyIpeysuKy59 LCBhdDogWzxmZmZmZmZmZjgxMDljNjRhPl0gcHJvY2Vzc19vbmVfd29yaysweDFhYS8weDY2MAog IzE6ICAoKCYoJmk5MTUtPmdwdV9lcnJvci5oYW5nY2hlY2tfd29yayktPndvcmspKXsrLisufSwg YXQ6IFs8ZmZmZmZmZmY4MTA5YzY0YT5dIHByb2Nlc3Nfb25lX3dvcmsrMHgxYWEvMHg2NjAKICMy OiAgKCZkZXYtPnN0cnVjdF9tdXRleCl7Ky4rLn0sIGF0OiBbPGZmZmZmZmZmYTAxMzY1ODg+XSBp OTE1X3Jlc2V0X2RldmljZSsweDFlOC8weDI2MCBbaTkxNV0KCnN0YWNrIGJhY2t0cmFjZToKQ1BV OiAzIFBJRDogNTYyIENvbW06IGt3b3JrZXIvMzo0IFRhaW50ZWQ6IEcgICAgIFUgICAgICAgICAg NC4xNC4wLXJjMy1DSS1DSV9EUk1fMzE3OSsgIzEKSGFyZHdhcmUgbmFtZTogICAgICAgICAgICAg ICAgICAvTlVDN2k1Qk5CLCBCSU9TIEJOS0JMMzU3Ljg2QS4wMDQ4LjIwMTcuMDcwNC4xNDE1IDA3 LzA0LzIwMTcKV29ya3F1ZXVlOiBldmVudHNfbG9uZyBpOTE1X2hhbmdjaGVja19lbGFwc2VkIFtp OTE1XQpDYWxsIFRyYWNlOgogZHVtcF9zdGFjaysweDY4LzB4OWYKIHByaW50X2NpcmN1bGFyX2J1 ZysweDIzNS8weDNjMAogPyBsb2NrZGVwX2luaXRfbWFwX2Nyb3NzbG9jaysweDIwLzB4MjAKIGNo ZWNrX3ByZXZfYWRkKzB4NDMwLzB4ODQwCiA/IGlycV93b3JrX3F1ZXVlKzB4ODYvMHhlMAogPyB3 YWtlX3VwX2tsb2dkKzB4NTMvMHg3MAogX19sb2NrX2FjcXVpcmUrMHgxNDIwLzB4MTVlMAogPyBf X2xvY2tfYWNxdWlyZSsweDE0MjAvMHgxNWUwCiA/IGxvY2tkZXBfaW5pdF9tYXBfY3Jvc3Nsb2Nr KzB4MjAvMHgyMAogbG9ja19hY3F1aXJlKzB4YjAvMHgyMDAKID8gc3RvcF9tYWNoaW5lKzB4MWMv MHg0MAogPyBpOTE1X2dlbV9vYmplY3RfdHJ1bmNhdGUrMHg1MC8weDUwIFtpOTE1XQogY3B1c19y ZWFkX2xvY2srMHgzZC8weGIwCiA/IHN0b3BfbWFjaGluZSsweDFjLzB4NDAKIHN0b3BfbWFjaGlu ZSsweDFjLzB4NDAKIGk5MTVfZ2VtX3NldF93ZWRnZWQrMHgxYS8weDIwIFtpOTE1XQogaTkxNV9y ZXNldCsweGI5LzB4MjMwIFtpOTE1XQogaTkxNV9yZXNldF9kZXZpY2UrMHgxZjYvMHgyNjAgW2k5 MTVdCiA/IGdlbjhfZ3RfaXJxX2FjaysweDE3MC8weDE3MCBbaTkxNV0KID8gd29ya19vbl9jcHVf c2FmZSsweDYwLzB4NjAKIGk5MTVfaGFuZGxlX2Vycm9yKzB4MmQ4LzB4NDMwIFtpOTE1XQogPyB2 c25wcmludGYrMHhkMS8weDRiMAogPyBzY25wcmludGYrMHgzYS8weDcwCiBoYW5nY2hlY2tfZGVj bGFyZV9oYW5nKzB4ZDMvMHhmMCBbaTkxNV0KID8gaW50ZWxfcnVudGltZV9wbV9wdXQrMHg1Ni8w eGEwIFtpOTE1XQogaTkxNV9oYW5nY2hlY2tfZWxhcHNlZCsweDI2Mi8weDJkMCBbaTkxNV0KIHBy b2Nlc3Nfb25lX3dvcmsrMHgyMzMvMHg2NjAKIHdvcmtlcl90aHJlYWQrMHg0ZS8weDNiMAoga3Ro cmVhZCsweDE1Mi8weDE5MAogPyBwcm9jZXNzX29uZV93b3JrKzB4NjYwLzB4NjYwCiA/IGt0aHJl YWRfY3JlYXRlX29uX25vZGUrMHg0MC8weDQwCiByZXRfZnJvbV9mb3JrKzB4MjcvMHg0MApTZXR0 aW5nIGRhbmdlcm91cyBvcHRpb24gcmVzZXQgLSB0YWludGluZyBrZXJuZWwKaTkxNSAwMDAwOjAw OjAyLjA6IFJlc2V0dGluZyBjaGlwIGFmdGVyIGdwdSBoYW5nClNldHRpbmcgZGFuZ2Vyb3VzIG9w dGlvbiByZXNldCAtIHRhaW50aW5nIGtlcm5lbAppOTE1IDAwMDA6MDA6MDIuMDogUmVzZXR0aW5n IGNoaXAgYWZ0ZXIgZ3B1IGhhbmcKCnYyOiBIYXZlIDEgZ2xvYmFsIHN5bmNocm9uaXplX3JjdSgp IGJhcnJpZXIgYWNyb3NzIGFsbCBlbmdpbmVzLCBhbmQKaW1wcm92ZSBjb21taXQgbWVzc2FnZS4K CkJ1Z3ppbGxhOiBodHRwczovL2J1Z3MuZnJlZWRlc2t0b3Aub3JnL3Nob3dfYnVnLmNnaT9pZD0x MDI4ODYKQnVnemlsbGE6IGh0dHBzOi8vYnVncy5mcmVlZGVza3RvcC5vcmcvc2hvd19idWcuY2dp P2lkPTEwMzA5NgpDYzogQ2hyaXMgV2lsc29uIDxjaHJpc0BjaHJpcy13aWxzb24uY28udWs+CkNj OiBNaWthIEt1b3BwYWxhIDxtaWthLmt1b3BwYWxhQGludGVsLmNvbT4KQ2M6IFRob21hcyBHbGVp eG5lciA8dGdseEBsaW51dHJvbml4LmRlPgpDYzogTWFydGEgTG9mc3RlZHQgPG1hcnRhLmxvZnN0 ZWR0QGludGVsLmNvbT4KU2lnbmVkLW9mZi1ieTogRGFuaWVsIFZldHRlciA8ZGFuaWVsLnZldHRl ckBpbnRlbC5jb20+Ci0tLQogZHJpdmVycy9ncHUvZHJtL2k5MTUvaTkxNV9nZW0uYyAgICAgICAg ICAgICAgICAgICB8IDMxICsrKysrKysrKy0tLS0tLS0tLS0tLS0tCiBkcml2ZXJzL2dwdS9kcm0v aTkxNS9pOTE1X2dlbV9yZXF1ZXN0LmMgICAgICAgICAgIHwgIDIgKysKIGRyaXZlcnMvZ3B1L2Ry bS9pOTE1L3NlbGZ0ZXN0cy9pOTE1X2dlbV9yZXF1ZXN0LmMgfCAgMiArKwogMyBmaWxlcyBjaGFu Z2VkLCAxNiBpbnNlcnRpb25zKCspLCAxOSBkZWxldGlvbnMoLSkKCmRpZmYgLS1naXQgYS9kcml2 ZXJzL2dwdS9kcm0vaTkxNS9pOTE1X2dlbS5jIGIvZHJpdmVycy9ncHUvZHJtL2k5MTUvaTkxNV9n ZW0uYwppbmRleCBhYjhjNjk0NmZlYTQuLmU3OWE2Y2E2MDI2NSAxMDA2NDQKLS0tIGEvZHJpdmVy cy9ncHUvZHJtL2k5MTUvaTkxNV9nZW0uYworKysgYi9kcml2ZXJzL2dwdS9kcm0vaTkxNS9pOTE1 X2dlbS5jCkBAIC0zMDIwLDE2ICszMDIwLDggQEAgc3RhdGljIHZvaWQgbm9wX3N1Ym1pdF9yZXF1 ZXN0KHN0cnVjdCBkcm1faTkxNV9nZW1fcmVxdWVzdCAqcmVxdWVzdCkKIAlpbnRlbF9lbmdpbmVf aW5pdF9nbG9iYWxfc2Vxbm8ocmVxdWVzdC0+ZW5naW5lLCByZXF1ZXN0LT5nbG9iYWxfc2Vxbm8p OwogfQogCi1zdGF0aWMgdm9pZCBlbmdpbmVfc2V0X3dlZGdlZChzdHJ1Y3QgaW50ZWxfZW5naW5l X2NzICplbmdpbmUpCitzdGF0aWMgdm9pZCBlbmdpbmVfY29tcGxldGVfcmVxdWVzdHMoc3RydWN0 IGludGVsX2VuZ2luZV9jcyAqZW5naW5lKQogewotCS8qIFdlIG5lZWQgdG8gYmUgc3VyZSB0aGF0 IG5vIHRocmVhZCBpcyBydW5uaW5nIHRoZSBvbGQgY2FsbGJhY2sgYXMKLQkgKiB3ZSBpbnN0YWxs IHRoZSBub3AgaGFuZGxlciAob3RoZXJ3aXNlIHdlIHdvdWxkIHN1Ym1pdCBhIHJlcXVlc3QKLQkg KiB0byBoYXJkd2FyZSB0aGF0IHdpbGwgbmV2ZXIgY29tcGxldGUpLiBJbiBvcmRlciB0byBwcmV2 ZW50IHRoaXMKLQkgKiByYWNlLCB3ZSB3YWl0IHVudGlsIHRoZSBtYWNoaW5lIGlzIGlkbGUgYmVm b3JlIG1ha2luZyB0aGUgc3dhcAotCSAqICh1c2luZyBzdG9wX21hY2hpbmUoKSkuCi0JICovCi0J ZW5naW5lLT5zdWJtaXRfcmVxdWVzdCA9IG5vcF9zdWJtaXRfcmVxdWVzdDsKLQogCS8qIE1hcmsg YWxsIGV4ZWN1dGluZyByZXF1ZXN0cyBhcyBza2lwcGVkICovCiAJZW5naW5lLT5jYW5jZWxfcmVx dWVzdHMoZW5naW5lKTsKIApAQCAtMzA0MSwyNCArMzAzMywyNSBAQCBzdGF0aWMgdm9pZCBlbmdp bmVfc2V0X3dlZGdlZChzdHJ1Y3QgaW50ZWxfZW5naW5lX2NzICplbmdpbmUpCiAJCQkJICAgICAg IGludGVsX2VuZ2luZV9sYXN0X3N1Ym1pdChlbmdpbmUpKTsKIH0KIAotc3RhdGljIGludCBfX2k5 MTVfZ2VtX3NldF93ZWRnZWRfQktMKHZvaWQgKmRhdGEpCit2b2lkIGk5MTVfZ2VtX3NldF93ZWRn ZWQoc3RydWN0IGRybV9pOTE1X3ByaXZhdGUgKmk5MTUpCiB7Ci0Jc3RydWN0IGRybV9pOTE1X3By aXZhdGUgKmk5MTUgPSBkYXRhOwogCXN0cnVjdCBpbnRlbF9lbmdpbmVfY3MgKmVuZ2luZTsKIAll bnVtIGludGVsX2VuZ2luZV9pZCBpZDsKIAogCWZvcl9lYWNoX2VuZ2luZShlbmdpbmUsIGk5MTUs IGlkKQotCQllbmdpbmVfc2V0X3dlZGdlZChlbmdpbmUpOworCQllbmdpbmUtPnN1Ym1pdF9yZXF1 ZXN0ID0gbm9wX3N1Ym1pdF9yZXF1ZXN0OwogCi0Jc2V0X2JpdChJOTE1X1dFREdFRCwgJmk5MTUt PmdwdV9lcnJvci5mbGFncyk7Ci0Jd2FrZV91cF9hbGwoJmk5MTUtPmdwdV9lcnJvci5yZXNldF9x dWV1ZSk7CisJLyogTWFrZSBzdXJlIG5vIG9uZSBpcyBydW5uaW5nIHRoZSBvbGQgY2FsbGJhY2sg YmVmb3JlIHdlIHByb2NlZWQgd2l0aAorCSAqIGNhbmNlbGxpbmcgcmVxdWVzdHMgYW5kIHJlc2V0 dGluZyB0aGUgY29tcGxldGlvbiB0cmFja2luZy4gT3RoZXJ3aXNlCisJICogd2UgbWlnaHQgc3Vi bWl0IGEgcmVxdWVzdCB0byB0aGUgaGFyZHdhcmUgd2hpY2ggbmV2ZXIgY29tcGxldGVzLgorCSAq LworCXN5bmNocm9uaXplX3JjdSgpOwogCi0JcmV0dXJuIDA7Ci19CisJZm9yX2VhY2hfZW5naW5l KGVuZ2luZSwgaTkxNSwgaWQpCisJCWVuZ2luZV9jb21wbGV0ZV9yZXF1ZXN0cyhlbmdpbmUpOwog Ci12b2lkIGk5MTVfZ2VtX3NldF93ZWRnZWQoc3RydWN0IGRybV9pOTE1X3ByaXZhdGUgKmRldl9w cml2KQotewotCXN0b3BfbWFjaGluZShfX2k5MTVfZ2VtX3NldF93ZWRnZWRfQktMLCBkZXZfcHJp diwgTlVMTCk7CisJc2V0X2JpdChJOTE1X1dFREdFRCwgJmk5MTUtPmdwdV9lcnJvci5mbGFncyk7 CisJd2FrZV91cF9hbGwoJmk5MTUtPmdwdV9lcnJvci5yZXNldF9xdWV1ZSk7CiB9CiAKIGJvb2wg aTkxNV9nZW1fdW5zZXRfd2VkZ2VkKHN0cnVjdCBkcm1faTkxNV9wcml2YXRlICppOTE1KQpkaWZm IC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL2k5MTUvaTkxNV9nZW1fcmVxdWVzdC5jIGIvZHJpdmVy cy9ncHUvZHJtL2k5MTUvaTkxNV9nZW1fcmVxdWVzdC5jCmluZGV4IGIxMDBiMzhmMWRkMi4uZWY3 OGE4NWNiODQ1IDEwMDY0NAotLS0gYS9kcml2ZXJzL2dwdS9kcm0vaTkxNS9pOTE1X2dlbV9yZXF1 ZXN0LmMKKysrIGIvZHJpdmVycy9ncHUvZHJtL2k5MTUvaTkxNV9nZW1fcmVxdWVzdC5jCkBAIC01 NTYsNyArNTU2LDkgQEAgc3VibWl0X25vdGlmeShzdHJ1Y3QgaTkxNV9zd19mZW5jZSAqZmVuY2Us IGVudW0gaTkxNV9zd19mZW5jZV9ub3RpZnkgc3RhdGUpCiAJc3dpdGNoIChzdGF0ZSkgewogCWNh c2UgRkVOQ0VfQ09NUExFVEU6CiAJCXRyYWNlX2k5MTVfZ2VtX3JlcXVlc3Rfc3VibWl0KHJlcXVl c3QpOworCQlyY3VfcmVhZF9sb2NrKCk7CiAJCXJlcXVlc3QtPmVuZ2luZS0+c3VibWl0X3JlcXVl c3QocmVxdWVzdCk7CisJCXJjdV9yZWFkX3VubG9jaygpOwogCQlicmVhazsKIAogCWNhc2UgRkVO Q0VfRlJFRToKZGlmZiAtLWdpdCBhL2RyaXZlcnMvZ3B1L2RybS9pOTE1L3NlbGZ0ZXN0cy9pOTE1 X2dlbV9yZXF1ZXN0LmMgYi9kcml2ZXJzL2dwdS9kcm0vaTkxNS9zZWxmdGVzdHMvaTkxNV9nZW1f cmVxdWVzdC5jCmluZGV4IDc4YjlmODExNzA3Zi4uYTk5OTE2MWU4ZGIxIDEwMDY0NAotLS0gYS9k cml2ZXJzL2dwdS9kcm0vaTkxNS9zZWxmdGVzdHMvaTkxNV9nZW1fcmVxdWVzdC5jCisrKyBiL2Ry aXZlcnMvZ3B1L2RybS9pOTE1L3NlbGZ0ZXN0cy9pOTE1X2dlbV9yZXF1ZXN0LmMKQEAgLTIxNSw3 ICsyMTUsOSBAQCBzdGF0aWMgaW50IGlndF9yZXF1ZXN0X3Jld2luZCh2b2lkICphcmcpCiAJfQog CWk5MTVfZ2VtX3JlcXVlc3RfZ2V0KHZpcCk7CiAJaTkxNV9hZGRfcmVxdWVzdCh2aXApOworCXJj dV9yZWFkX2xvY2soKTsKIAlyZXF1ZXN0LT5lbmdpbmUtPnN1Ym1pdF9yZXF1ZXN0KHJlcXVlc3Qp OworCXJjdV9yZWFkX3VubG9jaygpOwogCiAJbXV0ZXhfdW5sb2NrKCZpOTE1LT5kcm0uc3RydWN0 X211dGV4KTsKIAotLSAKMi4xNC4xCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fXwpJbnRlbC1nZnggbWFpbGluZyBsaXN0CkludGVsLWdmeEBsaXN0cy5mcmVl ZGVza3RvcC5vcmcKaHR0cHM6Ly9saXN0cy5mcmVlZGVza3RvcC5vcmcvbWFpbG1hbi9saXN0aW5m by9pbnRlbC1nZngK