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=-11.2 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_SANE_2 autolearn=unavailable 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 8DFA7C5517A for ; Mon, 26 Oct 2020 21:02:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5FCD720829 for ; Mon, 26 Oct 2020 21:02:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729430AbgJZVCq convert rfc822-to-8bit (ORCPT ); Mon, 26 Oct 2020 17:02:46 -0400 Received: from mga07.intel.com ([134.134.136.100]:18534 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729408AbgJZVCq (ORCPT ); Mon, 26 Oct 2020 17:02:46 -0400 IronPort-SDR: HMqKp3TjzD6sSgiJaG3ZqyAbqq8gV8UnCaUie/Q0VmwbFlyRz/scBcFb5QfER5uYhb5RdGmCgx QO6foiDjGJjQ== X-IronPort-AV: E=McAfee;i="6000,8403,9786"; a="232175267" X-IronPort-AV: E=Sophos;i="5.77,421,1596524400"; d="scan'208";a="232175267" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Oct 2020 14:02:43 -0700 IronPort-SDR: Rpwgz74q8iMYBMaa4Xw4dslHQZsh8zc/YSfyibLs49v0eL5uA/NgXrhurmpCkEfgaIxCELC+TU +x5Glim8r4dg== X-IronPort-AV: E=Sophos;i="5.77,421,1596524400"; d="scan'208";a="322680136" Received: from jacob-builder.jf.intel.com (HELO jacob-builder) ([10.7.199.155]) by orsmga006-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Oct 2020 14:02:43 -0700 Date: Mon, 26 Oct 2020 14:05:06 -0700 From: Jacob Pan To: Jean-Philippe Brucker Cc: Jacob Pan , iommu@lists.linux-foundation.org, LKML , Joerg Roedel , Alex Williamson , Lu Baolu , David Woodhouse , Jonathan Corbet , linux-api@vger.kernel.org, Jean-Philippe Brucker , Eric Auger , Yi Liu , "Tian, Kevin" , Raj Ashok , Wu Hao , Yi Sun , Dave Jiang , Randy Dunlap , linux-doc@vger.kernel.org, jacob.jun.pan@linux.intel.com Subject: Re: [PATCH v3 01/14] docs: Document IO Address Space ID (IOASID) APIs Message-ID: <20201026140506.1349dbb5@jacob-builder> In-Reply-To: <20201020135809.GA1515830@myrica> References: <1601329121-36979-1-git-send-email-jacob.jun.pan@linux.intel.com> <1601329121-36979-2-git-send-email-jacob.jun.pan@linux.intel.com> <20201020135809.GA1515830@myrica> Organization: OTC X-Mailer: Claws Mail 3.13.2 (GTK+ 2.24.30; x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8BIT Precedence: bulk List-ID: X-Mailing-List: linux-api@vger.kernel.org Hi Jean-Philippe, Thanks a lot for the review. Comments inline. On Tue, 20 Oct 2020 15:58:09 +0200, Jean-Philippe Brucker wrote: > On Mon, Sep 28, 2020 at 02:38:28PM -0700, Jacob Pan wrote: > > IOASID is used to identify address spaces that can be targeted by device > > DMA. It is a system-wide resource that is essential to its many users. > > This document is an attempt to help developers from all vendors navigate > > the APIs. At this time, ARM SMMU and Intel’s Scalable IO Virtualization > > (SIOV) enabled platforms are the primary users of IOASID. Examples of > > how SIOV components interact with IOASID APIs are provided in that many > > APIs are driven by the requirements from SIOV. > > > > Cc: Jonathan Corbet > > Cc: linux-doc@vger.kernel.org > > Cc: Randy Dunlap > > Signed-off-by: Liu Yi L > > Signed-off-by: Wu Hao > > Signed-off-by: Jacob Pan > > This looks good to me, with small comments below. > Can I add your Reviewed-by tag after addressing the comments? > > --- > > Documentation/driver-api/ioasid.rst | 648 > > ++++++++++++++++++++++++++++++++++++ 1 file changed, 648 insertions(+) > > create mode 100644 Documentation/driver-api/ioasid.rst > > > > diff --git a/Documentation/driver-api/ioasid.rst > > b/Documentation/driver-api/ioasid.rst new file mode 100644 > > index 000000000000..7f8e702997ab > > --- /dev/null > > +++ b/Documentation/driver-api/ioasid.rst > > @@ -0,0 +1,648 @@ > > +.. SPDX-License-Identifier: GPL-2.0 > > +.. ioasid: > > + > > +=================== > > +IO Address Space ID > > +=================== > > + > > +IOASID is a generic name for PCIe Process Address ID (PASID) or ARM > > +SMMU SubstreamID. An IOASID identifies an address space that DMA > > +requests can target. > > + > > +The primary use cases for IOASID are Shared Virtual Address (SVA) and > > +multiple IOVA spaces per device. However, the requirements for IOASID > > +management can vary among hardware architectures. > > + > > +For baremetal IOVA, IOASID #0 is used for DMA request without > > bare metal got it > > > +PASID. Even though some architectures such as VT-d also offers > > +the flexibility of using any PASIDs for DMA request without PASID. > > +PASID #0 is reserved and not allocated from any ioasid_set. > > + > > +Multiple IOVA spaces per device are mapped to auxiliary domains which > > +can be used for mediated device assignment with and without a virtual > > +IOMMU (vIOMMU). An IOASID is allocated for each auxiliary domain as > > default +PASID. Without vIOMMU, default IOASID is used for DMA map/unmap > > +APIs. With vIOMMU, default IOASID is used for guest IOVA where DMA > > +request with PASID is required for the device. The reason is that > > +there is only one PASID #0 per device, e.g. VT-d, RID_PASID is per > > PCI > > on VT-d got that > > > +device. > > + > > +This document covers the generic features supported by IOASID > > +APIs. Vendor-specific use cases are also illustrated with Intel's VT-d > > +based platforms as the first example. > > + > > +.. contents:: :local: > > + > > +Glossary > > +======== > > +PASID - Process Address Space ID > > + > > +IOASID - IO Address Space ID (generic term for PCIe PASID and > > +SubstreamID in SMMU) > > + > > +SVA/SVM - Shared Virtual Addressing/Memory > > + > > +ENQCMD - Intel X86 ISA for efficient workqueue submission [1] > > +!!!TODO: Link to Spec at the bottom > > Yes, or maybe hyperlinks at the end of this section would be better. There > are references and lists all over the document so keeping things as close > as possible avoids confusion. > sounds good. > > + > > +DSA - Intel Data Streaming Accelerator [2] > > + > > +VDCM - Virtual Device Composition Module [3] > > + > > +SIOV - Intel Scalable IO Virtualization > > + > > + > > +Key Concepts > > +============ > > + > > +IOASID Set > > +----------- > > +An IOASID set is a group of IOASIDs allocated from the system-wide > > +IOASID pool. Refer to IOASID set APIs for more details. > > IOASID Set Level APIs > Yes, I should use the exact section title. > > + > > +IOASID set is particularly useful for guest SVA where each guest could > > +have its own IOASID set for security and efficiency reasons. > > + > > +IOASID Set Private ID (SPID) > > +---------------------------- > > +Each IOASID set has a private namespace of SPIDs. An SPID maps to a > > +single system-wide IOASID. Conversely, each IOASID may be associated > > +with an alias ID, local to the IOASID set, named SPID. > > +SPIDs can be used as guest IOASIDs where each guest could do > > +IOASID allocation from its own pool and map them to host physical > > +IOASIDs. SPIDs are particularly useful for supporting live migration > > +where decoupling guest and host physical resources are necessary. > > + > > +For example, two VMs can both allocate guest PASID/SPID #101 but map to > > +different host PASIDs #201 and #202 respectively as shown in the > > +diagram below. > > +:: > > + > > + .------------------. .------------------. > > + | VM 1 | | VM 2 | > > + | | | | > > + |------------------| |------------------| > > + | GPASID/SPID 101 | | GPASID/SPID 101 | > > + '------------------' -------------------' Guest > > + __________|______________________|____________________ > > + | | Host > > + v v > > + .------------------. .------------------. > > + | Host IOASID 201 | | Host IOASID 202 | > > + '------------------' '------------------' > > + | IOASID set 1 | | IOASID set 2 | > > + '------------------' '------------------' > > + > > +Guest PASID is treated as IOASID set private ID (SPID) within an > > +IOASID set, mappings between guest and host IOASIDs are stored in the > > +set for inquiry. > > + > > +IOASID APIs > > +=========== > > +To get the IOASID APIs, users must #include . These > > APIs +serve the following functionalities: > > + > > + - IOASID allocation/Free > > freeing (or release) > got it > > + - Group management in the form of ioasid_set > > + - Private data storage and lookup > > + - Reference counting > > + - Event notification in case of a state change > > + > > +IOASID Set Level APIs > > +-------------------------- > > +For use cases such as guest SVA it is necessary to manage IOASIDs at > > +ioasid_set level. For example, VMs may allocate multiple IOASIDs for > > +guest process address sharing (vSVA). It is imperative to enforce > > +VM-IOASID ownership such that a malicious guest cannot target DMA > > +traffic outside its own IOASIDs, or free an active IOASID that belongs > > +to another VM. > > + > > +The IOASID set APIs serve the following purposes: > > + > > + - Ownership/permission enforcement > > + - Take collective actions, e.g. free an entire set > > + - Event notifications within a set > > + - Look up a set based on token > > + - Quota enforcement > > + > > +Each IOASID set is created with a token, which can be one of the > > +following token types: > > + > > + - IOASID_SET_TYPE_NULL (Arbitrary u64 value) > > Maybe NULL isn't the best name then. NONE? > Agreed, 'NONE' makes more sense. > > + - IOASID_SET_TYPE_MM (Set token is a mm_struct) > > + > > +The explicit MM token type is useful when multiple users of an IOASID > > +set under the same process need to communicate about their shared > > IOASIDs. +E.g. An IOASID set created by VFIO for one guest can be > > associated +with the KVM instance for the same guest since they share a > > common mm_struct. +A token must be unique within its type. > > + > > +:: > > + > > + struct ioasid_set *ioasid_alloc_set(void *token, ioasid_t quota, u32 > > type) + > > + int ioasid_adjust_set(struct ioasid_set *set, int quota); > > + > > + void ioasid_set_get(struct ioasid_set *set) > > + > > + void ioasid_set_put(struct ioasid_set *set) > > + > > + void ioasid_set_get_locked(struct ioasid_set *set) > > + > > + void ioasid_set_put_locked(struct ioasid_set *set) > > + > > + int ioasid_set_for_each_ioasid(struct ioasid_set *set, > > + void (*fn)(ioasid_t id, void *data), > > + void *data) > > misaligned > got it > > + > > + > > +Individual IOASID APIs > > +---------------------- > > +Once an ioasid_set is created, IOASIDs can be allocated from the set. > > +Within the IOASID set namespace, set private ID (SPID) is supported. In > > +the VM use case, SPID can be used for storing guest PASID. > > + > > +:: > > + > > + ioasid_t ioasid_alloc(struct ioasid_set *set, ioasid_t min, ioasid_t > > max, > > + void *private); > > + > > + int ioasid_get(struct ioasid_set *set, ioasid_t ioasid); > > + > > + void ioasid_put(struct ioasid_set *set, ioasid_t ioasid); > > + > > + int ioasid_get_locked(struct ioasid_set *set, ioasid_t ioasid); > > + > > + void ioasid_put_locked(struct ioasid_set *set, ioasid_t ioasid); > > + > > + void *ioasid_find(struct ioasid_set *set, ioasid_t ioasid, > > + bool (*getter)(void *)); > > + > > + ioasid_t ioasid_find_by_spid(struct ioasid_set *set, ioasid_t spid) > > + > > + int ioasid_attach_data(struct ioasid_set *set, ioasid_t ioasid, > > + void *data); > > + int ioasid_attach_spid(struct ioasid_set *set, ioasid_t ioasid, > > + ioasid_t spid); > > + > > + > > +Notifications > > +------------- > > +An IOASID may have multiple users, each user may have hardware context > > +associated with an IOASID. When the status of an IOASID changes, > > +e.g. an IOASID is being freed, users need to be notified such that the > > +associated hardware context can be cleared, flushed, and drained. > > + > > +:: > > + > > + int ioasid_register_notifier(struct ioasid_set *set, struct > > + notifier_block *nb) > > + > > + void ioasid_unregister_notifier(struct ioasid_set *set, > > + struct notifier_block *nb) > > + > > + int ioasid_register_notifier_mm(struct mm_struct *mm, struct > > + notifier_block *nb) > > + > > + void ioasid_unregister_notifier_mm(struct mm_struct *mm, struct > > + notifier_block *nb) > > + > > + int ioasid_notify(ioasid_t ioasid, enum ioasid_notify_val cmd, > > + unsigned int flags) > > + > > +"_mm" flavor of the ioasid_register_notifier() APIs are used when > > +an IOASID user need to listen to the IOASID events belong to a > > +process but without the knowledge of the associated ioasid_set. > > + > > +Events > > +~~~~~~ > > +Notification events are pertinent to individual IOASIDs, they can be > > +one of the following: > > + > > + - ALLOC > > + - FREE > > + - BIND > > + - UNBIND > > + > > +Ordering > > +~~~~~~~~ > > +Ordering is supported by IOASID notification priorities as the > > +following (in ascending order): > > + > > +:: > > + > > + enum ioasid_notifier_prios { > > + IOASID_PRIO_LAST, > > + IOASID_PRIO_IOMMU, > > + IOASID_PRIO_DEVICE, > > + IOASID_PRIO_CPU, > > + }; > > + > > +When registered, notifiers are assigned a priority that affect the > > +call order. For example, notifiers with CPU priority get called before > > +notifiers with device priority and so on. > > + > > +The typical use case is when an IOASID is freed due to an exception, > > DMA +source should be quiesced before tearing down other hardware > > contexts +in the system. This will reduce the churn in handling faults. > > DMA work +submission is performed by the CPU which is granted higher > > priority than +devices. > > + > > +Level Sensitivity > > +~~~~~~~~~~~~~~~~~ > > +For each IOASID state transition, IOASID core ensures that there is > > +only one notification sent. This resembles level triggered interrupt > > +where a single interrupt is raised during a state transition. > > +For example, if ioasid_free() is called twice by a user before the > > +IOASID is reclaimed, IOASID core will only send out a single > > +IOASID_NOTIFY_FREE event. Similarly, for IOASID_NOTIFY_BIND/UNBIND > > +events, which is only sent out once when a SPID is attached/detached. > > + > > +IOASID notifications cannot be sent directly by IOASID users, they are > > +sent out by the IOASID core as a by-product of the following APIs: > > +- ioasid_alloc/free(), emit IOASID_NOTIFY_ALLOC/FREE > > +- ioasid_attach/detach_spid() emit IOASID_NOTIFY_BIND/UNBIND > > + > > +Scopes > > +~~~~~~ > > +There are two types of notifiers in IOASID core: system-wide and > > +ioasid_set-wide. > > + > > +System-wide notifier is catering for users that need to handle all the > > +IOASIDs in the system. E.g. The IOMMU driver. > > + > > +Per ioasid_set notifier can be used by VM specific components such as > > +KVM. After all, each KVM instance only cares about IOASIDs within its > > +own set/guest. > > + > > + > > +Atomicity > > +~~~~~~~~~ > > +IOASID notifiers are atomic due to spinlocks used inside the IOASID > > +core. For tasks that cannot be completed in the notifier handler, > > +async work can be submitted to complete the work later as long as > > +there is no ordering requirement. > > + > > +Reference counting > > +------------------ > > +IOASID lifecycle management is based on reference counting. Users of > > +IOASID who intend to align lifecycle with the IOASID need to hold > > +a reference of the IOASID. The IOASID will not be returned to the pool > > +for allocation until all references are dropped. Calling ioasid_free() > > +will mark the IOASID as FREE_PENDING if the IOASID has outstanding > > +references. No new references can be taken by ioasid_get() once an > > +IOASID is in the FREE_PENDING state. ioasid_free() can be called > > +multiple times without an error until all refs are dropped. > > + > > +ioasid_put() decrements and tests refcount of the IOASID. If refcount > > +is 0, ioasid will be freed. Deleted from the system-wide xarray as > > +well as per set xarray. > > These xarray structures haven't been introduced so far. I would leave out > this level of detail because it's not relevant to the user and will be > difficult to keep in sync with the internals of IOASID. > Right, I will deleted the xarray part. > > The IOASID will be returned to the pool and > > +available for new allocations. > > + > > +Event notifications are used to inform users of IOASID status change. > > +IOASID_FREE event prompts users to drop their references after > > +clearing its context. > > + > > +For example, on VT-d platform when an IOASID is freed, teardown > > +actions are performed on KVM, device driver (VDCM), and the IOMMU > > +driver. To quiesce VCPU for work submission, KVM notifier handler must > > +be called before VDCM handler. Therefore, KVM and VDCM shall use > > +notification priority IOASID_PRIO_CPU andIOASID_PRIO_DEVICE > > and IOASID_PRIO_DEVICE > go it. > > +respectively. > > + > > +For both KVM and VDCM, notifier blocks shall be registered on the > > +IOASID set such that *only* events from the matching VM are received. > > + > > +If KVM attempts to register a notifier block before the IOASID set is > > +created using the MM token, the notifier block will be placed on a > > +pending list inside IOASID core. Once the token matching IOASID set > > +is created, IOASID will register the notifier block automatically. > > +IOASID core does not replay events for the existing IOASIDs in the > > +set. For IOASID set of MM type, notification blocks can be registered > > +on empty sets only. This is to avoid lost events. > > + > > +IOMMU driver shall register notifier block on global chain:: > > + > > + static struct notifier_block pasid_nb_vtd = { > > + .notifier_call = pasid_status_change_vtd, > > + .priority = IOASID_PRIO_IOMMU, > > + }; > > + > > +Custom allocator APIs > > +--------------------- > > + > > +:: > > + > > + int ioasid_register_allocator(struct ioasid_allocator_ops *allocator); > > + > > + void ioasid_unregister_allocator(struct ioasid_allocator_ops > > *allocator); + > > +Allocator Choices > > +~~~~~~~~~~~~~~~~~ > > +IOASIDs are allocated for both host and guest SVA/IOVA usage. However, > > +allocators can be different. For example, on VT-d guest PASID > > +allocation must be performed via a virtual command interface which is > > +emulated by VMM. > > + > > +IOASID core has the notion of "custom allocator" such that guest can > > +register virtual command allocator that precedes the default one. > > "Supersedes", rather than "precedes"? > My understanding is that 'supersede' means replace something but 'precede' means get in front of something. I do want to emphasis that the custom allocator takes precedence over the default allocator. > > + > > +Namespaces > > +~~~~~~~~~~ > > +IOASIDs are limited system resources that default to 20 bits in > > +size. Each device can have its own PASID table for security reasons. > > +Theoretically the namespace can be per device also. > > + > > +However IOASID namespace is system-wide for two reasons: > > +- Simplicity > > +- Sharing resources of a single device to multiple VMs. > > + > > +Take VT-d as an example, VT-d supports shared workqueue and ENQCMD[1] > > +where one IOASID could be used to submit work on multiple devices that > > +are shared with other VMs. This requires IOASID to be > > +system-wide. This is also the reason why guests must use an > > +emulated virtual command interface to allocate IOASID from the host. > > + > > +Life cycle > > +========== > > +This section covers IOASID life cycle management for both bare-metal > > +and guest usages. In bare-metal SVA, MMU notifier is directly hooked > > +up with IOMMU driver, therefore the IOASID life cycle matches the > > +process address space (MM) life cycle. > > + > > +However, guest MMU notifier is not available to host IOMMU driver, > > +when guest MM terminates unexpectedly, the events have to go through > > +VFIO and IOMMU UAPI to reach host IOMMU driver. There are also more > > +parties involved in guest SVA, e.g. on Intel VT-d platform, IOASIDs > > +are used by IOMMU driver, KVM, VDCM, and VFIO. > > + > > +Native IOASID Life Cycle (VT-d Example) > > +--------------------------------------- > > + > > +The normal flow of native SVA code with Intel Data Streaming > > +Accelerator(DSA) [2] as example: > > + > > +1. Host user opens accelerator FD, e.g. DSA driver, or uacce; > > +2. DSA driver allocate WQ, do sva_bind_device(); > > +3. IOMMU driver calls ioasid_alloc(), then bind PASID with device, > > + mmu_notifier_get() > > +4. DMA starts by DSA driver userspace > > +5. DSA userspace close FD > > +6. DSA/uacce kernel driver handles FD.close() > > +7. DSA driver stops DMA > > +8. DSA driver calls sva_unbind_device(); > > +9. IOMMU driver does unbind, clears PASID context in IOMMU, flush > > + TLBs. mmu_notifier_put() called. > > +10. mmu_notifier.release() called, IOMMU SVA code calls ioasid_free()* > > +11. The IOASID is returned to the pool, reclaimed. > > + > > +:: > > + > > + * With ENQCMD, PASID used on VT-d is not released in mmu_notifier() > > but > > + mmdrop(). mmdrop comes after FD close which does not make a > > difference. + > > +During the normal teardown, the following three key steps would happen > > in +order: (7), (9), (11). > > + > > +Exception happens when process terminates *before* device driver stops > > +DMA and call IOMMU driver to unbind. The detailed flow of process > > +exits are as follows: > > + > > +:: > > + > > + do_exit() { > > + exit_mm() { > > + mm_put(); > > + exit_mmap() { > > + intel_invalidate_range() //mmu notifier > > + tlb_finish_mmu() > > + mmu_notifier_release(mm) { > > + intel_mm_release() { > > + (9) > > intel_iommu_teardown_pasid(); > > + intel_iommu_flush_tlbs(); > > + } > > + // tlb_invalidate_range cb removed > > + } > > + unmap_vmas(); > > + free_pgtables(); // IOMMU cannot walk PGT > > after this > > or rather, it *must* not walk PGT at this point? PGT should be disabled on > the IOMMU side at step 9, before the TLB invalidation > Yes, agreed already guaranteed. I will delete the comment. > > + }; > > + } > > + exit_files(tsk) { > > + close_files() { > > + dsa_close(); > > + (7) dsa_stop_dma(); > > + intel_svm_unbind_pasid(); //nothing to do > > + } > > + } > > + } > > + > > + mmdrop() /* some random time later, lazy mm user */ { > > + mm_free_pgd(); > > + destroy_context(mm); { > > + (11) ioasid_free(); > > + } > > + } > > + > > +As shown in the list above, step #2 could happen before > > +#1. Unrecoverable(UR) faults could happen between #2 and #1. > > +Fault processing is disabled by the IOMMU driver in #2, therefore the > > UR +fault never reaches the driver. > > Did you mean steps (7) and (9) instead for #1 and #2? > Yes, forgot to update the index. > > + > > + > > +Also notice that TLB invalidation occurs at mmu_notifier > > +invalidate_range callback as well as the release callback. The reason > > +is that release callback will delete IOMMU driver from the notifier > > +chain which may skip invalidate_range() calls during the exit path. > > I think this whole section also goes too deep in implementation details, > and is susceptible to become out of sync with the code pretty quickly. > I don't feel strongly about this, though, leave it if you want. > I will delete this, better be accurate than misleading. > > + > > +To avoid unnecessary reporting of UR fault, IOMMU driver shall disable > > +fault reporting after free and before unbind. > > + > > +Guest IOASID Life Cycle (VT-d Example) > > +-------------------------------------- > > +Guest IOASID life cycle starts with guest driver open(), this could be > > +uacce or individual accelerator driver such as DSA. At FD open, > > +sva_bind_device() is called which triggers a series of actions. > > + > > +The example below is an illustration of *normal* operations that > > +involves *all* the SW components in VT-d. The flow can be simpler if > > +no ENQCMD is supported. > > + > > +:: > > + > > + VFIO IOMMU KVM VDCM IOASID Ref > > + .................................................................. > > + 1 ioasid_register_notifier/_mm() > > + 2 ioasid_alloc() 1 > > + 3 bind_gpasid() > > + 4 iommu_bind()->ioasid_get() 2 > > + 5 ioasid_notify(BIND) > > + 6 -> ioasid_get() 3 > > + 7 -> vmcs_update_atomic() > > + 8 mdev_write(gpasid) > > + 9 hpasid= > > + 10 find_by_spid(gpasid) 4 > > Are 9 and 10 the same step? > yes, here is just line #. > > + 11 vdev_write(hpasid) > > What's the 'v' in vdev? Aren't we writing to the physical device here? > Yes, we are writing to the physical resource of the virtual device. Let me remove the 'v'. > > + 12 -------- GUEST STARTS DMA -------------------------- > > + 13 -------- GUEST STOPS DMA -------------------------- > > + 14 mdev_clear(gpasid) > > + 15 vdev_clear(hpasid) > > + 16 ioasid_put() 3 > > + 17 unbind_gpasid() > > + 18 iommu_ubind() > > + 19 ioasid_notify(UNBIND) > > + 20 -> vmcs_update_atomic() > > + 21 -> ioasid_put() 2 > > + 22 ioasid_free() 1 > > + 23 ioasid_put() 0 > > + 24 Reclaimed > > + -------------- New Life Cycle Begin ---------------------------- > > + 1 ioasid_alloc() -> 1 > > + > > + Note: IOASID Notification Events: FREE, BIND, UNBIND > > Is FREE at step 22? > Yes the IOASID_FREE event should be sent at step 22, let me call it out explicitly. > > + > > +Exception cases arise when a guest crashes or a malicious guest > > +attempts to cause disruption on the host system. The fault handling > > +rules are: > > + > > +1. IOASID free must *always* succeed. > > +2. An inactive period may be required before the freed IOASID is > > + reclaimed. During this period, consumers of IOASID perform cleanup. > > +3. Malfunction is limited to the guest owned resources for all > > + programming errors. > > + > > +The primary source of exception is when the following are out of > > +order: > > + > > +1. Start/Stop of DMA activity > > + (Guest device driver, mdev via VFIO) > > +2. Setup/Teardown of IOMMU PASID context, IOTLB, DevTLB flushes > > + (Host IOMMU driver bind/unbind) > > +3. Setup/Teardown of VMCS PASID translation table entries (KVM) in > > + case of ENQCMD > > +4. Programming/Clearing host PASID in VDCM (Host VDCM driver) > > +5. IOASID alloc/free (Host IOASID) > > + > > +VFIO is the *only* user-kernel interface, which is ultimately > > +responsible for exception handling. > > + > > +#1 is processed the same way as the assigned device today based on > > +device file descriptors and events. There is no special handling. > > + > > +#3 is based on bind/unbind events emitted by #2. > > + > > +#4 is naturally aligned with IOASID life cycle in that an illegal > > +guest PASID programming would fail in obtaining reference of the > > +matching host IOASID. > > + > > +#5 is similar to #4. The fault will be reported to the user if PASID > > +used in the ENQCMD is not set up in VMCS PASID translation table. > > + > > +Therefore, the remaining out of order problem is between #2 and > > +#5. I.e. unbind vs. free. More specifically, free before unbind. > > + > > +IOASID notifier and refcounting are used to ensure order. Following > > +a publisher-subscriber pattern where: > > + > > +- Publishers: VFIO & IOMMU > > +- Subscribers: KVM, VDCM, IOMMU > > + > > +IOASID reference must be acquired before receiving the FREE event. The > > +reference must be dropped at the end of the processing in order to > > +return the IOASID to the pool. > > + > > +Let's examine the IOASID life cycle again when free happens *before* > > +unbind. This could be a result of misbehaving guests or crash. Assuming > > +VFIO cannot enforce unbind->free order. Notice that the setup part up > > +until step #12 is identical to the normal case, the flow below starts > > +with step 13. > > + > > +:: > > + > > + VFIO IOMMU KVM VDCM IOASID Ref > > + .................................................................. > > + 13 -------- GUEST STARTS DMA -------------------------- > > + 14 -------- *GUEST MISBEHAVES!!!* ---------------- > > + 15 ioasid_free() > > + 16 ioasid_notify(FREE) > > + 17 mark_free_pending > > (1) > > Could we use superscript ¹²³⁴ for footnotes? These look like function > parameters > yes, much better > > + 18 kvm_nb_handler(FREE) > > + 19 vmcs_update_atomic() > > + 20 ioasid_put_locked() -> 3 > > + 21 vdcm_nb_handler(FREE) > > + 22 iomm_nb_handler(FREE) > > iommu_nb_handler > got it > > + 23 ioasid_free() returns(2) schedule_work() 2 > > I completely lost track here, couldn't figure out in which direction to > read the diagram. What work is scheduled? The time line goes downward but we only control the notification order in terms of when the events are received. Some completions are async thus out of order done by work items. The only in-order completion is the KVM update of its PASID translation table. After #23, the async works are scheduled to complete clean up work outside the spinlock(held by the caller of the atomic notifier). Any suggestions to improve the readability of the time line? > Why does the IOMMU driver drop > its reference to the IOASID before unbdind_gpasid()? > This is the exception case where userspace issues IOASID free before unbind_gpasid(). The equivalent of unbind is performed in the IOASID_FREE notification handler. In IOASID_FREE handler, reference is dropped and private data deleted. After that, if unbind comes to IOMMU driver, it will not find IOASID private data therefore just return. > > + 24 schedule_work() vdev_clear_wk(hpasid) > > + 25 teardown_pasid_wk() > > + 26 ioasid_put() -> 1 > > + 27 ioasid_put() 0 > > + 28 Reclaimed > > + 29 unbind_gpasid() > > + 30 iommu_unbind()->ioasid_find() Fails(3) > > + -------------- New Life Cycle Begin ---------------------------- > > + > > +Note: > > + > > +1. By marking IOASID FREE_PENDING at step #17, no new references can be > > + held. ioasid_get/find() will return -ENOENT; > > s/held/taken > Got it. > Thanks, > Jean > > > +2. After step #23, all events can go out of order. Shall not affect > > + the outcome. > > +3. IOMMU driver fails to find private data for unbinding. If unbind is > > + called after the same IOASID is allocated for the same guest again, > > + this is a programming error. The damage is limited to the guest > > + itself since unbind performs permission checking based on the > > + IOASID set associated with the guest process. > > +4. Workqueues are used by VDCM and IOMMU driver for processing that > > + requires thread context. > > + > > + > > +KVM PASID Translation Table Updates > > +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > > +Per VM PASID translation table is maintained by KVM in order to > > +support ENQCMD in the guest. The table contains host-guest PASID > > +translations to be consumed by CPU ucode. The synchronization of the > > +PASID states depends on VFIO/IOMMU driver, where IOCTL and atomic > > +notifiers are used. KVM must register IOASID notifier per VM instance > > +during launch time. The following events are handled: > > + > > +1. BIND/UNBIND > > +2. FREE > > + > > +Rules: > > + > > +1. Multiple devices can bind with the same PASID, this can be > > different PCI > > + devices or mdevs within the same PCI device. However, only the > > + *first* BIND and *last* UNBIND emit notifications. > > +2. IOASID code is responsible for ensuring the correctness of H-G > > + PASID mapping. There is no need for KVM to validate the > > + notification data. > > +3. When UNBIND happens *after* FREE, KVM will see error in > > + ioasid_get() even when the reclaim is not done. IOMMU driver will > > + also avoid sending UNBIND if the PASID is already FREE. > > +4. When KVM terminates *before* FREE & UNBIND, references will be > > + dropped for all host PASIDs. > > + > > +VDCM PASID Programming > > +~~~~~~~~~~~~~~~~~~~~~~ > > +VDCM composes virtual devices and exposes them to the guests. When > > +the guest allocates a PASID then program it to the virtual device, VDCM > > +intercepts the programming attempt then programs the matching host > > +PASID on to the hardware. > > +Conversely, when a device is going away, VDCM must be informed such > > +that PASID context on the hardware can be cleared. There could be > > +multiple mdevs assigned to different guests in the same VDCM. Since > > +the PASID table is shared at PCI device level, lazy clearing is not > > +secure. A malicious guest can attack by using newly freed PASIDs that > > +are allocated by another guest. > > + > > +By holding a reference of the PASID until VDCM cleans up the HW > > context, +it is guaranteed that PASID life cycles do not cross within > > the same +device. > > + > > + > > +Reference > > +==================================================== > > +1. > > https://software.intel.com/sites/default/files/managed/c5/15/architecture-instruction-set-extensions-programming-reference.pdf > > + +2. > > https://01.org/blogs/2019/introducing-intel-data-streaming-accelerator + > > +3. > > https://software.intel.com/en-us/download/intel-data-streaming-accelerator-preliminary-architecture-specification > > -- 2.7.4 > > Thanks, Jacob 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=-11.2 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_SANE_2 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 BD2DDC388F9 for ; Mon, 26 Oct 2020 21:02:53 +0000 (UTC) Received: from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136]) (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 380322076D for ; Mon, 26 Oct 2020 21:02:53 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 380322076D Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=iommu-bounces@lists.linux-foundation.org Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id CA71A20337; Mon, 26 Oct 2020 21:02:52 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from silver.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ne3eg1xwLtCR; Mon, 26 Oct 2020 21:02:49 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by silver.osuosl.org (Postfix) with ESMTP id 1C5221FF11; Mon, 26 Oct 2020 21:02:49 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id F258DC0859; Mon, 26 Oct 2020 21:02:48 +0000 (UTC) Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 4D8BFC0051 for ; Mon, 26 Oct 2020 21:02:47 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 3B1A085EFB for ; Mon, 26 Oct 2020 21:02:47 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id CR5s0zHdMB_j for ; Mon, 26 Oct 2020 21:02:44 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by fraxinus.osuosl.org (Postfix) with ESMTPS id B31EF85EF0 for ; Mon, 26 Oct 2020 21:02:44 +0000 (UTC) IronPort-SDR: QwLw6UjM8KNi6ozHNzCitgxMcwE0vy2t014vLDxwQqYBv8V7LxqFDgIMziNfkMzhOIX6BCZ32Y 2bhRLk8D3N2Q== X-IronPort-AV: E=McAfee;i="6000,8403,9786"; a="185717893" X-IronPort-AV: E=Sophos;i="5.77,421,1596524400"; d="scan'208";a="185717893" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga006.jf.intel.com ([10.7.209.51]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Oct 2020 14:02:44 -0700 IronPort-SDR: Rpwgz74q8iMYBMaa4Xw4dslHQZsh8zc/YSfyibLs49v0eL5uA/NgXrhurmpCkEfgaIxCELC+TU +x5Glim8r4dg== X-IronPort-AV: E=Sophos;i="5.77,421,1596524400"; d="scan'208";a="322680136" Received: from jacob-builder.jf.intel.com (HELO jacob-builder) ([10.7.199.155]) by orsmga006-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Oct 2020 14:02:43 -0700 Date: Mon, 26 Oct 2020 14:05:06 -0700 From: Jacob Pan To: Jean-Philippe Brucker Subject: Re: [PATCH v3 01/14] docs: Document IO Address Space ID (IOASID) APIs Message-ID: <20201026140506.1349dbb5@jacob-builder> In-Reply-To: <20201020135809.GA1515830@myrica> References: <1601329121-36979-1-git-send-email-jacob.jun.pan@linux.intel.com> <1601329121-36979-2-git-send-email-jacob.jun.pan@linux.intel.com> <20201020135809.GA1515830@myrica> Organization: OTC X-Mailer: Claws Mail 3.13.2 (GTK+ 2.24.30; x86_64-pc-linux-gnu) MIME-Version: 1.0 Cc: "Tian, Kevin" , Jacob Pan , Raj Ashok , Jonathan Corbet , linux-api@vger.kernel.org, Randy Dunlap , linux-doc@vger.kernel.org, iommu@lists.linux-foundation.org, LKML , Jean-Philippe Brucker , Alex Williamson , Dave Jiang , Wu Hao , David Woodhouse , Yi Sun X-BeenThere: iommu@lists.linux-foundation.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Development issues for Linux IOMMU support List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Errors-To: iommu-bounces@lists.linux-foundation.org Sender: "iommu" SGkgSmVhbi1QaGlsaXBwZSwKClRoYW5rcyBhIGxvdCBmb3IgdGhlIHJldmlldy4gQ29tbWVudHMg aW5saW5lLgoKT24gVHVlLCAyMCBPY3QgMjAyMCAxNTo1ODowOSArMDIwMCwgSmVhbi1QaGlsaXBw ZSBCcnVja2VyCjxqZWFuLXBoaWxpcHBlQGxpbmFyby5vcmc+IHdyb3RlOgoKPiBPbiBNb24sIFNl cCAyOCwgMjAyMCBhdCAwMjozODoyOFBNIC0wNzAwLCBKYWNvYiBQYW4gd3JvdGU6Cj4gPiBJT0FT SUQgaXMgdXNlZCB0byBpZGVudGlmeSBhZGRyZXNzIHNwYWNlcyB0aGF0IGNhbiBiZSB0YXJnZXRl ZCBieSBkZXZpY2UKPiA+IERNQS4gSXQgaXMgYSBzeXN0ZW0td2lkZSByZXNvdXJjZSB0aGF0IGlz IGVzc2VudGlhbCB0byBpdHMgbWFueSB1c2Vycy4KPiA+IFRoaXMgZG9jdW1lbnQgaXMgYW4gYXR0 ZW1wdCB0byBoZWxwIGRldmVsb3BlcnMgZnJvbSBhbGwgdmVuZG9ycyBuYXZpZ2F0ZQo+ID4gdGhl IEFQSXMuIEF0IHRoaXMgdGltZSwgQVJNIFNNTVUgYW5kIEludGVs4oCZcyBTY2FsYWJsZSBJTyBW aXJ0dWFsaXphdGlvbgo+ID4gKFNJT1YpIGVuYWJsZWQgcGxhdGZvcm1zIGFyZSB0aGUgcHJpbWFy eSB1c2VycyBvZiBJT0FTSUQuIEV4YW1wbGVzIG9mCj4gPiBob3cgU0lPViBjb21wb25lbnRzIGlu dGVyYWN0IHdpdGggSU9BU0lEIEFQSXMgYXJlIHByb3ZpZGVkIGluIHRoYXQgbWFueQo+ID4gQVBJ cyBhcmUgZHJpdmVuIGJ5IHRoZSByZXF1aXJlbWVudHMgZnJvbSBTSU9WLgo+ID4gCj4gPiBDYzog Sm9uYXRoYW4gQ29yYmV0IDxjb3JiZXRAbHduLm5ldD4KPiA+IENjOiBsaW51eC1kb2NAdmdlci5r ZXJuZWwub3JnCj4gPiBDYzogUmFuZHkgRHVubGFwIDxyZHVubGFwQGluZnJhZGVhZC5vcmc+Cj4g PiBTaWduZWQtb2ZmLWJ5OiBMaXUgWWkgTCA8eWkubC5saXVAaW50ZWwuY29tPgo+ID4gU2lnbmVk LW9mZi1ieTogV3UgSGFvIDxoYW8ud3VAaW50ZWwuY29tPgo+ID4gU2lnbmVkLW9mZi1ieTogSmFj b2IgUGFuIDxqYWNvYi5qdW4ucGFuQGxpbnV4LmludGVsLmNvbT4gIAo+IAo+IFRoaXMgbG9va3Mg Z29vZCB0byBtZSwgd2l0aCBzbWFsbCBjb21tZW50cyBiZWxvdy4KPiAKQ2FuIEkgYWRkIHlvdXIg UmV2aWV3ZWQtYnkgdGFnIGFmdGVyIGFkZHJlc3NpbmcgdGhlIGNvbW1lbnRzPwoKPiA+IC0tLQo+ ID4gIERvY3VtZW50YXRpb24vZHJpdmVyLWFwaS9pb2FzaWQucnN0IHwgNjQ4Cj4gPiArKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysgMSBmaWxlIGNoYW5nZWQsIDY0OCBpbnNlcnRp b25zKCspCj4gPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IERvY3VtZW50YXRpb24vZHJpdmVyLWFwaS9p b2FzaWQucnN0Cj4gPiAKPiA+IGRpZmYgLS1naXQgYS9Eb2N1bWVudGF0aW9uL2RyaXZlci1hcGkv aW9hc2lkLnJzdAo+ID4gYi9Eb2N1bWVudGF0aW9uL2RyaXZlci1hcGkvaW9hc2lkLnJzdCBuZXcg ZmlsZSBtb2RlIDEwMDY0NAo+ID4gaW5kZXggMDAwMDAwMDAwMDAwLi43ZjhlNzAyOTk3YWIKPiA+ IC0tLSAvZGV2L251bGwKPiA+ICsrKyBiL0RvY3VtZW50YXRpb24vZHJpdmVyLWFwaS9pb2FzaWQu cnN0Cj4gPiBAQCAtMCwwICsxLDY0OCBAQAo+ID4gKy4uIFNQRFgtTGljZW5zZS1JZGVudGlmaWVy OiBHUEwtMi4wCj4gPiArLi4gaW9hc2lkOgo+ID4gKwo+ID4gKz09PT09PT09PT09PT09PT09PT0K PiA+ICtJTyBBZGRyZXNzIFNwYWNlIElECj4gPiArPT09PT09PT09PT09PT09PT09PQo+ID4gKwo+ ID4gK0lPQVNJRCBpcyBhIGdlbmVyaWMgbmFtZSBmb3IgUENJZSBQcm9jZXNzIEFkZHJlc3MgSUQg KFBBU0lEKSBvciBBUk0KPiA+ICtTTU1VIFN1YnN0cmVhbUlELiBBbiBJT0FTSUQgaWRlbnRpZmll cyBhbiBhZGRyZXNzIHNwYWNlIHRoYXQgRE1BCj4gPiArcmVxdWVzdHMgY2FuIHRhcmdldC4KPiA+ ICsKPiA+ICtUaGUgcHJpbWFyeSB1c2UgY2FzZXMgZm9yIElPQVNJRCBhcmUgU2hhcmVkIFZpcnR1 YWwgQWRkcmVzcyAoU1ZBKSBhbmQKPiA+ICttdWx0aXBsZSBJT1ZBIHNwYWNlcyBwZXIgZGV2aWNl LiBIb3dldmVyLCB0aGUgcmVxdWlyZW1lbnRzIGZvciBJT0FTSUQKPiA+ICttYW5hZ2VtZW50IGNh biB2YXJ5IGFtb25nIGhhcmR3YXJlIGFyY2hpdGVjdHVyZXMuCj4gPiArCj4gPiArRm9yIGJhcmVt ZXRhbCBJT1ZBLCBJT0FTSUQgIzAgaXMgdXNlZCBmb3IgRE1BIHJlcXVlc3Qgd2l0aG91dCAgCj4g Cj4gICAgICAgIGJhcmUgbWV0YWwKZ290IGl0Cgo+IAo+ID4gK1BBU0lELiBFdmVuIHRob3VnaCBz b21lIGFyY2hpdGVjdHVyZXMgc3VjaCBhcyBWVC1kIGFsc28gb2ZmZXJzCj4gPiArdGhlIGZsZXhp YmlsaXR5IG9mIHVzaW5nIGFueSBQQVNJRHMgZm9yIERNQSByZXF1ZXN0IHdpdGhvdXQgUEFTSUQu Cj4gPiArUEFTSUQgIzAgaXMgcmVzZXJ2ZWQgYW5kIG5vdCBhbGxvY2F0ZWQgZnJvbSBhbnkgaW9h c2lkX3NldC4KPiA+ICsKPiA+ICtNdWx0aXBsZSBJT1ZBIHNwYWNlcyBwZXIgZGV2aWNlIGFyZSBt YXBwZWQgdG8gYXV4aWxpYXJ5IGRvbWFpbnMgd2hpY2gKPiA+ICtjYW4gYmUgdXNlZCBmb3IgbWVk aWF0ZWQgZGV2aWNlIGFzc2lnbm1lbnQgd2l0aCBhbmQgd2l0aG91dCBhIHZpcnR1YWwKPiA+ICtJ T01NVSAodklPTU1VKS4gQW4gSU9BU0lEIGlzIGFsbG9jYXRlZCBmb3IgZWFjaCBhdXhpbGlhcnkg ZG9tYWluIGFzCj4gPiBkZWZhdWx0ICtQQVNJRC4gV2l0aG91dCB2SU9NTVUsIGRlZmF1bHQgSU9B U0lEIGlzIHVzZWQgZm9yIERNQSBtYXAvdW5tYXAKPiA+ICtBUElzLiBXaXRoIHZJT01NVSwgZGVm YXVsdCBJT0FTSUQgaXMgdXNlZCBmb3IgZ3Vlc3QgSU9WQSB3aGVyZSBETUEKPiA+ICtyZXF1ZXN0 IHdpdGggUEFTSUQgaXMgcmVxdWlyZWQgZm9yIHRoZSBkZXZpY2UuIFRoZSByZWFzb24gaXMgdGhh dAo+ID4gK3RoZXJlIGlzIG9ubHkgb25lIFBBU0lEICMwIHBlciBkZXZpY2UsIGUuZy4gVlQtZCwg UklEX1BBU0lEIGlzIHBlcgo+ID4gUENJICAKPiAKPiAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgIG9uIFZULWQKZ290IHRoYXQKPiAKPiA+ICtkZXZpY2UuCj4g PiArCj4gPiArVGhpcyBkb2N1bWVudCBjb3ZlcnMgdGhlIGdlbmVyaWMgZmVhdHVyZXMgc3VwcG9y dGVkIGJ5IElPQVNJRAo+ID4gK0FQSXMuIFZlbmRvci1zcGVjaWZpYyB1c2UgY2FzZXMgYXJlIGFs c28gaWxsdXN0cmF0ZWQgd2l0aCBJbnRlbCdzIFZULWQKPiA+ICtiYXNlZCBwbGF0Zm9ybXMgYXMg dGhlIGZpcnN0IGV4YW1wbGUuCj4gPiArCj4gPiArLi4gY29udGVudHM6OiA6bG9jYWw6Cj4gPiAr Cj4gPiArR2xvc3NhcnkKPiA+ICs9PT09PT09PQo+ID4gK1BBU0lEIC0gUHJvY2VzcyBBZGRyZXNz IFNwYWNlIElECj4gPiArCj4gPiArSU9BU0lEIC0gSU8gQWRkcmVzcyBTcGFjZSBJRCAoZ2VuZXJp YyB0ZXJtIGZvciBQQ0llIFBBU0lEIGFuZAo+ID4gK1N1YnN0cmVhbUlEIGluIFNNTVUpCj4gPiAr Cj4gPiArU1ZBL1NWTSAtIFNoYXJlZCBWaXJ0dWFsIEFkZHJlc3NpbmcvTWVtb3J5Cj4gPiArCj4g PiArRU5RQ01EIC0gSW50ZWwgWDg2IElTQSBmb3IgZWZmaWNpZW50IHdvcmtxdWV1ZSBzdWJtaXNz aW9uIFsxXQo+ID4gKyEhIVRPRE86IExpbmsgdG8gU3BlYyBhdCB0aGUgYm90dG9tICAKPiAKPiBZ ZXMsIG9yIG1heWJlIGh5cGVybGlua3MgYXQgdGhlIGVuZCBvZiB0aGlzIHNlY3Rpb24gd291bGQg YmUgYmV0dGVyLiBUaGVyZQo+IGFyZSByZWZlcmVuY2VzIGFuZCBsaXN0cyBhbGwgb3ZlciB0aGUg ZG9jdW1lbnQgc28ga2VlcGluZyB0aGluZ3MgYXMgY2xvc2UKPiBhcyBwb3NzaWJsZSBhdm9pZHMg Y29uZnVzaW9uLgo+IApzb3VuZHMgZ29vZC4KCj4gPiArCj4gPiArRFNBIC0gSW50ZWwgRGF0YSBT dHJlYW1pbmcgQWNjZWxlcmF0b3IgWzJdCj4gPiArCj4gPiArVkRDTSAtIFZpcnR1YWwgRGV2aWNl IENvbXBvc2l0aW9uIE1vZHVsZSBbM10KPiA+ICsKPiA+ICtTSU9WIC0gSW50ZWwgU2NhbGFibGUg SU8gVmlydHVhbGl6YXRpb24KPiA+ICsKPiA+ICsKPiA+ICtLZXkgQ29uY2VwdHMKPiA+ICs9PT09 PT09PT09PT0KPiA+ICsKPiA+ICtJT0FTSUQgU2V0Cj4gPiArLS0tLS0tLS0tLS0KPiA+ICtBbiBJ T0FTSUQgc2V0IGlzIGEgZ3JvdXAgb2YgSU9BU0lEcyBhbGxvY2F0ZWQgZnJvbSB0aGUgc3lzdGVt LXdpZGUKPiA+ICtJT0FTSUQgcG9vbC4gUmVmZXIgdG8gSU9BU0lEIHNldCBBUElzIGZvciBtb3Jl IGRldGFpbHMuICAKPiAKPiAgICAgICAgICAgICAgICAgICAgICAgICAgSU9BU0lEIFNldCBMZXZl bCBBUElzCj4gClllcywgSSBzaG91bGQgdXNlIHRoZSBleGFjdCBzZWN0aW9uIHRpdGxlLgoKPiA+ ICsKPiA+ICtJT0FTSUQgc2V0IGlzIHBhcnRpY3VsYXJseSB1c2VmdWwgZm9yIGd1ZXN0IFNWQSB3 aGVyZSBlYWNoIGd1ZXN0IGNvdWxkCj4gPiAraGF2ZSBpdHMgb3duIElPQVNJRCBzZXQgZm9yIHNl Y3VyaXR5IGFuZCBlZmZpY2llbmN5IHJlYXNvbnMuCj4gPiArCj4gPiArSU9BU0lEIFNldCBQcml2 YXRlIElEIChTUElEKQo+ID4gKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KPiA+ICtFYWNo IElPQVNJRCBzZXQgaGFzIGEgcHJpdmF0ZSBuYW1lc3BhY2Ugb2YgU1BJRHMuIEFuIFNQSUQgbWFw cyB0byBhCj4gPiArc2luZ2xlIHN5c3RlbS13aWRlIElPQVNJRC4gQ29udmVyc2VseSwgZWFjaCBJ T0FTSUQgbWF5IGJlIGFzc29jaWF0ZWQKPiA+ICt3aXRoIGFuIGFsaWFzIElELCBsb2NhbCB0byB0 aGUgSU9BU0lEIHNldCwgbmFtZWQgU1BJRC4KPiA+ICtTUElEcyBjYW4gYmUgdXNlZCBhcyBndWVz dCBJT0FTSURzIHdoZXJlIGVhY2ggZ3Vlc3QgY291bGQgZG8KPiA+ICtJT0FTSUQgYWxsb2NhdGlv biBmcm9tIGl0cyBvd24gcG9vbCBhbmQgbWFwIHRoZW0gdG8gaG9zdCBwaHlzaWNhbAo+ID4gK0lP QVNJRHMuIFNQSURzIGFyZSBwYXJ0aWN1bGFybHkgdXNlZnVsIGZvciBzdXBwb3J0aW5nIGxpdmUg bWlncmF0aW9uCj4gPiArd2hlcmUgZGVjb3VwbGluZyBndWVzdCBhbmQgaG9zdCBwaHlzaWNhbCBy ZXNvdXJjZXMgYXJlIG5lY2Vzc2FyeS4KPiA+ICsKPiA+ICtGb3IgZXhhbXBsZSwgdHdvIFZNcyBj YW4gYm90aCBhbGxvY2F0ZSBndWVzdCBQQVNJRC9TUElEICMxMDEgYnV0IG1hcCB0bwo+ID4gK2Rp ZmZlcmVudCBob3N0IFBBU0lEcyAjMjAxIGFuZCAjMjAyIHJlc3BlY3RpdmVseSBhcyBzaG93biBp biB0aGUKPiA+ICtkaWFncmFtIGJlbG93Lgo+ID4gKzo6Cj4gPiArCj4gPiArIC4tLS0tLS0tLS0t LS0tLS0tLS0uICAgIC4tLS0tLS0tLS0tLS0tLS0tLS0uCj4gPiArIHwgICBWTSAxICAgICAgICAg ICB8ICAgIHwgICBWTSAyICAgICAgICAgICB8Cj4gPiArIHwgICAgICAgICAgICAgICAgICB8ICAg IHwgICAgICAgICAgICAgICAgICB8Cj4gPiArIHwtLS0tLS0tLS0tLS0tLS0tLS18ICAgIHwtLS0t LS0tLS0tLS0tLS0tLS18Cj4gPiArIHwgR1BBU0lEL1NQSUQgMTAxICB8ICAgIHwgR1BBU0lEL1NQ SUQgMTAxICB8Cj4gPiArICctLS0tLS0tLS0tLS0tLS0tLS0nICAgIC0tLS0tLS0tLS0tLS0tLS0t LS0nICAgICBHdWVzdAo+ID4gKyBfX19fX19fX19ffF9fX19fX19fX19fX19fX19fX19fX198X19f X19fX19fX19fX19fX19fX18KPiA+ICsgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAg fCAgICAgICAgICAgICAgIEhvc3QKPiA+ICsgICAgICAgICAgIHYgICAgICAgICAgICAgICAgICAg ICAgdgo+ID4gKyAuLS0tLS0tLS0tLS0tLS0tLS0tLiAgICAuLS0tLS0tLS0tLS0tLS0tLS0tLgo+ ID4gKyB8IEhvc3QgSU9BU0lEIDIwMSAgfCAgICB8IEhvc3QgSU9BU0lEIDIwMiAgfAo+ID4gKyAn LS0tLS0tLS0tLS0tLS0tLS0tJyAgICAnLS0tLS0tLS0tLS0tLS0tLS0tJwo+ID4gKyB8ICAgSU9B U0lEIHNldCAxICAgfCAgICB8ICAgSU9BU0lEIHNldCAyICAgfAo+ID4gKyAnLS0tLS0tLS0tLS0t LS0tLS0tJyAgICAnLS0tLS0tLS0tLS0tLS0tLS0tJwo+ID4gKwo+ID4gK0d1ZXN0IFBBU0lEIGlz IHRyZWF0ZWQgYXMgSU9BU0lEIHNldCBwcml2YXRlIElEIChTUElEKSB3aXRoaW4gYW4KPiA+ICtJ T0FTSUQgc2V0LCBtYXBwaW5ncyBiZXR3ZWVuIGd1ZXN0IGFuZCBob3N0IElPQVNJRHMgYXJlIHN0 b3JlZCBpbiB0aGUKPiA+ICtzZXQgZm9yIGlucXVpcnkuCj4gPiArCj4gPiArSU9BU0lEIEFQSXMK PiA+ICs9PT09PT09PT09PQo+ID4gK1RvIGdldCB0aGUgSU9BU0lEIEFQSXMsIHVzZXJzIG11c3Qg I2luY2x1ZGUgPGxpbnV4L2lvYXNpZC5oPi4gVGhlc2UKPiA+IEFQSXMgK3NlcnZlIHRoZSBmb2xs b3dpbmcgZnVuY3Rpb25hbGl0aWVzOgo+ID4gKwo+ID4gKyAgLSBJT0FTSUQgYWxsb2NhdGlvbi9G cmVlICAKPiAKPiAgICAgICAgICAgICAgICAgICAgICAgICAgZnJlZWluZyAob3IgcmVsZWFzZSkK PiAKZ290IGl0Cgo+ID4gKyAgLSBHcm91cCBtYW5hZ2VtZW50IGluIHRoZSBmb3JtIG9mIGlvYXNp ZF9zZXQKPiA+ICsgIC0gUHJpdmF0ZSBkYXRhIHN0b3JhZ2UgYW5kIGxvb2t1cAo+ID4gKyAgLSBS ZWZlcmVuY2UgY291bnRpbmcKPiA+ICsgIC0gRXZlbnQgbm90aWZpY2F0aW9uIGluIGNhc2Ugb2Yg YSBzdGF0ZSBjaGFuZ2UKPiA+ICsKPiA+ICtJT0FTSUQgU2V0IExldmVsIEFQSXMKPiA+ICstLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLQo+ID4gK0ZvciB1c2UgY2FzZXMgc3VjaCBhcyBndWVzdCBT VkEgaXQgaXMgbmVjZXNzYXJ5IHRvIG1hbmFnZSBJT0FTSURzIGF0Cj4gPiAraW9hc2lkX3NldCBs ZXZlbC4gRm9yIGV4YW1wbGUsIFZNcyBtYXkgYWxsb2NhdGUgbXVsdGlwbGUgSU9BU0lEcyBmb3IK PiA+ICtndWVzdCBwcm9jZXNzIGFkZHJlc3Mgc2hhcmluZyAodlNWQSkuIEl0IGlzIGltcGVyYXRp dmUgdG8gZW5mb3JjZQo+ID4gK1ZNLUlPQVNJRCBvd25lcnNoaXAgc3VjaCB0aGF0IGEgbWFsaWNp b3VzIGd1ZXN0IGNhbm5vdCB0YXJnZXQgRE1BCj4gPiArdHJhZmZpYyBvdXRzaWRlIGl0cyBvd24g SU9BU0lEcywgb3IgZnJlZSBhbiBhY3RpdmUgSU9BU0lEIHRoYXQgYmVsb25ncwo+ID4gK3RvIGFu b3RoZXIgVk0uCj4gPiArCj4gPiArVGhlIElPQVNJRCBzZXQgQVBJcyBzZXJ2ZSB0aGUgZm9sbG93 aW5nIHB1cnBvc2VzOgo+ID4gKwo+ID4gKyAtIE93bmVyc2hpcC9wZXJtaXNzaW9uIGVuZm9yY2Vt ZW50Cj4gPiArIC0gVGFrZSBjb2xsZWN0aXZlIGFjdGlvbnMsIGUuZy4gZnJlZSBhbiBlbnRpcmUg c2V0Cj4gPiArIC0gRXZlbnQgbm90aWZpY2F0aW9ucyB3aXRoaW4gYSBzZXQKPiA+ICsgLSBMb29r IHVwIGEgc2V0IGJhc2VkIG9uIHRva2VuCj4gPiArIC0gUXVvdGEgZW5mb3JjZW1lbnQKPiA+ICsK PiA+ICtFYWNoIElPQVNJRCBzZXQgaXMgY3JlYXRlZCB3aXRoIGEgdG9rZW4sIHdoaWNoIGNhbiBi ZSBvbmUgb2YgdGhlCj4gPiArZm9sbG93aW5nIHRva2VuIHR5cGVzOgo+ID4gKwo+ID4gKyAtIElP QVNJRF9TRVRfVFlQRV9OVUxMIChBcmJpdHJhcnkgdTY0IHZhbHVlKSAgCj4gCj4gTWF5YmUgTlVM TCBpc24ndCB0aGUgYmVzdCBuYW1lIHRoZW4uIE5PTkU/Cj4gCkFncmVlZCwgJ05PTkUnIG1ha2Vz IG1vcmUgc2Vuc2UuCgo+ID4gKyAtIElPQVNJRF9TRVRfVFlQRV9NTSAoU2V0IHRva2VuIGlzIGEg bW1fc3RydWN0KQo+ID4gKwo+ID4gK1RoZSBleHBsaWNpdCBNTSB0b2tlbiB0eXBlIGlzIHVzZWZ1 bCB3aGVuIG11bHRpcGxlIHVzZXJzIG9mIGFuIElPQVNJRAo+ID4gK3NldCB1bmRlciB0aGUgc2Ft ZSBwcm9jZXNzIG5lZWQgdG8gY29tbXVuaWNhdGUgYWJvdXQgdGhlaXIgc2hhcmVkCj4gPiBJT0FT SURzLiArRS5nLiBBbiBJT0FTSUQgc2V0IGNyZWF0ZWQgYnkgVkZJTyBmb3Igb25lIGd1ZXN0IGNh biBiZQo+ID4gYXNzb2NpYXRlZCArd2l0aCB0aGUgS1ZNIGluc3RhbmNlIGZvciB0aGUgc2FtZSBn dWVzdCBzaW5jZSB0aGV5IHNoYXJlIGEKPiA+IGNvbW1vbiBtbV9zdHJ1Y3QuICtBIHRva2VuIG11 c3QgYmUgdW5pcXVlIHdpdGhpbiBpdHMgdHlwZS4KPiA+ICsKPiA+ICs6Ogo+ID4gKwo+ID4gKyBz dHJ1Y3QgaW9hc2lkX3NldCAqaW9hc2lkX2FsbG9jX3NldCh2b2lkICp0b2tlbiwgaW9hc2lkX3Qg cXVvdGEsIHUzMgo+ID4gdHlwZSkgKwo+ID4gKyBpbnQgaW9hc2lkX2FkanVzdF9zZXQoc3RydWN0 IGlvYXNpZF9zZXQgKnNldCwgaW50IHF1b3RhKTsKPiA+ICsKPiA+ICsgdm9pZCBpb2FzaWRfc2V0 X2dldChzdHJ1Y3QgaW9hc2lkX3NldCAqc2V0KQo+ID4gKwo+ID4gKyB2b2lkIGlvYXNpZF9zZXRf cHV0KHN0cnVjdCBpb2FzaWRfc2V0ICpzZXQpCj4gPiArCj4gPiArIHZvaWQgaW9hc2lkX3NldF9n ZXRfbG9ja2VkKHN0cnVjdCBpb2FzaWRfc2V0ICpzZXQpCj4gPiArCj4gPiArIHZvaWQgaW9hc2lk X3NldF9wdXRfbG9ja2VkKHN0cnVjdCBpb2FzaWRfc2V0ICpzZXQpCj4gPiArCj4gPiArIGludCBp b2FzaWRfc2V0X2Zvcl9lYWNoX2lvYXNpZChzdHJ1Y3QgaW9hc2lkX3NldCAqc2V0LAo+ID4gKyAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdm9pZCAoKmZuKShpb2FzaWRfdCBpZCwgdm9p ZCAqZGF0YSksCj4gPiArCQkJCXZvaWQgKmRhdGEpICAKPiAKPiBtaXNhbGlnbmVkCj4gCmdvdCBp dAoKPiA+ICsKPiA+ICsKPiA+ICtJbmRpdmlkdWFsIElPQVNJRCBBUElzCj4gPiArLS0tLS0tLS0t LS0tLS0tLS0tLS0tLQo+ID4gK09uY2UgYW4gaW9hc2lkX3NldCBpcyBjcmVhdGVkLCBJT0FTSURz IGNhbiBiZSBhbGxvY2F0ZWQgZnJvbSB0aGUgc2V0Lgo+ID4gK1dpdGhpbiB0aGUgSU9BU0lEIHNl dCBuYW1lc3BhY2UsIHNldCBwcml2YXRlIElEIChTUElEKSBpcyBzdXBwb3J0ZWQuIEluCj4gPiAr dGhlIFZNIHVzZSBjYXNlLCBTUElEIGNhbiBiZSB1c2VkIGZvciBzdG9yaW5nIGd1ZXN0IFBBU0lE Lgo+ID4gKwo+ID4gKzo6Cj4gPiArCj4gPiArIGlvYXNpZF90IGlvYXNpZF9hbGxvYyhzdHJ1Y3Qg aW9hc2lkX3NldCAqc2V0LCBpb2FzaWRfdCBtaW4sIGlvYXNpZF90Cj4gPiBtYXgsCj4gPiArICAg ICAgICAgICAgICAgICAgICAgICB2b2lkICpwcml2YXRlKTsKPiA+ICsKPiA+ICsgaW50IGlvYXNp ZF9nZXQoc3RydWN0IGlvYXNpZF9zZXQgKnNldCwgaW9hc2lkX3QgaW9hc2lkKTsKPiA+ICsKPiA+ ICsgdm9pZCBpb2FzaWRfcHV0KHN0cnVjdCBpb2FzaWRfc2V0ICpzZXQsIGlvYXNpZF90IGlvYXNp ZCk7Cj4gPiArCj4gPiArIGludCBpb2FzaWRfZ2V0X2xvY2tlZChzdHJ1Y3QgaW9hc2lkX3NldCAq c2V0LCBpb2FzaWRfdCBpb2FzaWQpOwo+ID4gKwo+ID4gKyB2b2lkIGlvYXNpZF9wdXRfbG9ja2Vk KHN0cnVjdCBpb2FzaWRfc2V0ICpzZXQsIGlvYXNpZF90IGlvYXNpZCk7Cj4gPiArCj4gPiArIHZv aWQgKmlvYXNpZF9maW5kKHN0cnVjdCBpb2FzaWRfc2V0ICpzZXQsIGlvYXNpZF90IGlvYXNpZCwK PiA+ICsgICAgICAgICAgICAgICAgICAgYm9vbCAoKmdldHRlcikodm9pZCAqKSk7Cj4gPiArCj4g PiArIGlvYXNpZF90IGlvYXNpZF9maW5kX2J5X3NwaWQoc3RydWN0IGlvYXNpZF9zZXQgKnNldCwg aW9hc2lkX3Qgc3BpZCkKPiA+ICsKPiA+ICsgaW50IGlvYXNpZF9hdHRhY2hfZGF0YShzdHJ1Y3Qg aW9hc2lkX3NldCAqc2V0LCBpb2FzaWRfdCBpb2FzaWQsCj4gPiArICAgICAgICAgICAgICAgICAg ICAgICAgdm9pZCAqZGF0YSk7Cj4gPiArIGludCBpb2FzaWRfYXR0YWNoX3NwaWQoc3RydWN0IGlv YXNpZF9zZXQgKnNldCwgaW9hc2lkX3QgaW9hc2lkLAo+ID4gKyAgICAgICAgICAgICAgICAgICAg ICAgIGlvYXNpZF90IHNwaWQpOwo+ID4gKwo+ID4gKwo+ID4gK05vdGlmaWNhdGlvbnMKPiA+ICst LS0tLS0tLS0tLS0tCj4gPiArQW4gSU9BU0lEIG1heSBoYXZlIG11bHRpcGxlIHVzZXJzLCBlYWNo IHVzZXIgbWF5IGhhdmUgaGFyZHdhcmUgY29udGV4dAo+ID4gK2Fzc29jaWF0ZWQgd2l0aCBhbiBJ T0FTSUQuIFdoZW4gdGhlIHN0YXR1cyBvZiBhbiBJT0FTSUQgY2hhbmdlcywKPiA+ICtlLmcuIGFu IElPQVNJRCBpcyBiZWluZyBmcmVlZCwgdXNlcnMgbmVlZCB0byBiZSBub3RpZmllZCBzdWNoIHRo YXQgdGhlCj4gPiArYXNzb2NpYXRlZCBoYXJkd2FyZSBjb250ZXh0IGNhbiBiZSBjbGVhcmVkLCBm bHVzaGVkLCBhbmQgZHJhaW5lZC4KPiA+ICsKPiA+ICs6Ogo+ID4gKwo+ID4gKyBpbnQgaW9hc2lk X3JlZ2lzdGVyX25vdGlmaWVyKHN0cnVjdCBpb2FzaWRfc2V0ICpzZXQsIHN0cnVjdAo+ID4gKyAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vdGlmaWVyX2Jsb2NrICpuYikKPiA+ICsKPiA+ ICsgdm9pZCBpb2FzaWRfdW5yZWdpc3Rlcl9ub3RpZmllcihzdHJ1Y3QgaW9hc2lkX3NldCAqc2V0 LAo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCBub3RpZmllcl9i bG9jayAqbmIpCj4gPiArCj4gPiArIGludCBpb2FzaWRfcmVnaXN0ZXJfbm90aWZpZXJfbW0oc3Ry dWN0IG1tX3N0cnVjdCAqbW0sIHN0cnVjdAo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIG5vdGlmaWVyX2Jsb2NrICpuYikKPiA+ICsKPiA+ICsgdm9pZCBpb2FzaWRfdW5yZWdp c3Rlcl9ub3RpZmllcl9tbShzdHJ1Y3QgbW1fc3RydWN0ICptbSwgc3RydWN0Cj4gPiArICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm90aWZpZXJfYmxvY2sgKm5iKQo+ID4gKwo+ ID4gKyBpbnQgaW9hc2lkX25vdGlmeShpb2FzaWRfdCBpb2FzaWQsIGVudW0gaW9hc2lkX25vdGlm eV92YWwgY21kLAo+ID4gKyAgICAgICAgICAgICAgICAgICB1bnNpZ25lZCBpbnQgZmxhZ3MpCj4g PiArCj4gPiArIl9tbSIgZmxhdm9yIG9mIHRoZSBpb2FzaWRfcmVnaXN0ZXJfbm90aWZpZXIoKSBB UElzIGFyZSB1c2VkIHdoZW4KPiA+ICthbiBJT0FTSUQgdXNlciBuZWVkIHRvIGxpc3RlbiB0byB0 aGUgSU9BU0lEIGV2ZW50cyBiZWxvbmcgdG8gYQo+ID4gK3Byb2Nlc3MgYnV0IHdpdGhvdXQgdGhl IGtub3dsZWRnZSBvZiB0aGUgYXNzb2NpYXRlZCBpb2FzaWRfc2V0Lgo+ID4gKwo+ID4gK0V2ZW50 cwo+ID4gK35+fn5+fgo+ID4gK05vdGlmaWNhdGlvbiBldmVudHMgYXJlIHBlcnRpbmVudCB0byBp bmRpdmlkdWFsIElPQVNJRHMsIHRoZXkgY2FuIGJlCj4gPiArb25lIG9mIHRoZSBmb2xsb3dpbmc6 Cj4gPiArCj4gPiArIC0gQUxMT0MKPiA+ICsgLSBGUkVFCj4gPiArIC0gQklORAo+ID4gKyAtIFVO QklORAo+ID4gKwo+ID4gK09yZGVyaW5nCj4gPiArfn5+fn5+fn4KPiA+ICtPcmRlcmluZyBpcyBz dXBwb3J0ZWQgYnkgSU9BU0lEIG5vdGlmaWNhdGlvbiBwcmlvcml0aWVzIGFzIHRoZQo+ID4gK2Zv bGxvd2luZyAoaW4gYXNjZW5kaW5nIG9yZGVyKToKPiA+ICsKPiA+ICs6Ogo+ID4gKwo+ID4gKyBl bnVtIGlvYXNpZF9ub3RpZmllcl9wcmlvcyB7Cj4gPiArCUlPQVNJRF9QUklPX0xBU1QsCj4gPiAr CUlPQVNJRF9QUklPX0lPTU1VLAo+ID4gKwlJT0FTSURfUFJJT19ERVZJQ0UsCj4gPiArCUlPQVNJ RF9QUklPX0NQVSwKPiA+ICsgfTsKPiA+ICsKPiA+ICtXaGVuIHJlZ2lzdGVyZWQsIG5vdGlmaWVy cyBhcmUgYXNzaWduZWQgYSBwcmlvcml0eSB0aGF0IGFmZmVjdCB0aGUKPiA+ICtjYWxsIG9yZGVy LiBGb3IgZXhhbXBsZSwgbm90aWZpZXJzIHdpdGggQ1BVIHByaW9yaXR5IGdldCBjYWxsZWQgYmVm b3JlCj4gPiArbm90aWZpZXJzIHdpdGggZGV2aWNlIHByaW9yaXR5IGFuZCBzbyBvbi4KPiA+ICsK PiA+ICtUaGUgdHlwaWNhbCB1c2UgY2FzZSBpcyB3aGVuIGFuIElPQVNJRCBpcyBmcmVlZCBkdWUg dG8gYW4gZXhjZXB0aW9uLAo+ID4gRE1BICtzb3VyY2Ugc2hvdWxkIGJlIHF1aWVzY2VkIGJlZm9y ZSB0ZWFyaW5nIGRvd24gb3RoZXIgaGFyZHdhcmUKPiA+IGNvbnRleHRzICtpbiB0aGUgc3lzdGVt LiBUaGlzIHdpbGwgcmVkdWNlIHRoZSBjaHVybiBpbiBoYW5kbGluZyBmYXVsdHMuCj4gPiBETUEg d29yayArc3VibWlzc2lvbiBpcyBwZXJmb3JtZWQgYnkgdGhlIENQVSB3aGljaCBpcyBncmFudGVk IGhpZ2hlcgo+ID4gcHJpb3JpdHkgdGhhbiArZGV2aWNlcy4KPiA+ICsKPiA+ICtMZXZlbCBTZW5z aXRpdml0eQo+ID4gK35+fn5+fn5+fn5+fn5+fn5+Cj4gPiArRm9yIGVhY2ggSU9BU0lEIHN0YXRl IHRyYW5zaXRpb24sIElPQVNJRCBjb3JlIGVuc3VyZXMgdGhhdCB0aGVyZSBpcwo+ID4gK29ubHkg b25lIG5vdGlmaWNhdGlvbiBzZW50LiBUaGlzIHJlc2VtYmxlcyBsZXZlbCB0cmlnZ2VyZWQgaW50 ZXJydXB0Cj4gPiArd2hlcmUgYSBzaW5nbGUgaW50ZXJydXB0IGlzIHJhaXNlZCBkdXJpbmcgYSBz dGF0ZSB0cmFuc2l0aW9uLgo+ID4gK0ZvciBleGFtcGxlLCBpZiBpb2FzaWRfZnJlZSgpIGlzIGNh bGxlZCB0d2ljZSBieSBhIHVzZXIgYmVmb3JlIHRoZQo+ID4gK0lPQVNJRCBpcyByZWNsYWltZWQs IElPQVNJRCBjb3JlIHdpbGwgb25seSBzZW5kIG91dCBhIHNpbmdsZQo+ID4gK0lPQVNJRF9OT1RJ RllfRlJFRSBldmVudC4gU2ltaWxhcmx5LCBmb3IgSU9BU0lEX05PVElGWV9CSU5EL1VOQklORAo+ ID4gK2V2ZW50cywgd2hpY2ggaXMgb25seSBzZW50IG91dCBvbmNlIHdoZW4gYSBTUElEIGlzIGF0 dGFjaGVkL2RldGFjaGVkLgo+ID4gKwo+ID4gK0lPQVNJRCBub3RpZmljYXRpb25zIGNhbm5vdCBi ZSBzZW50IGRpcmVjdGx5IGJ5IElPQVNJRCB1c2VycywgdGhleSBhcmUKPiA+ICtzZW50IG91dCBi eSB0aGUgSU9BU0lEIGNvcmUgYXMgYSBieS1wcm9kdWN0IG9mIHRoZSBmb2xsb3dpbmcgQVBJczoK PiA+ICstIGlvYXNpZF9hbGxvYy9mcmVlKCksIGVtaXQgSU9BU0lEX05PVElGWV9BTExPQy9GUkVF Cj4gPiArLSBpb2FzaWRfYXR0YWNoL2RldGFjaF9zcGlkKCkgZW1pdCBJT0FTSURfTk9USUZZX0JJ TkQvVU5CSU5ECj4gPiArCj4gPiArU2NvcGVzCj4gPiArfn5+fn5+Cj4gPiArVGhlcmUgYXJlIHR3 byB0eXBlcyBvZiBub3RpZmllcnMgaW4gSU9BU0lEIGNvcmU6IHN5c3RlbS13aWRlIGFuZAo+ID4g K2lvYXNpZF9zZXQtd2lkZS4KPiA+ICsKPiA+ICtTeXN0ZW0td2lkZSBub3RpZmllciBpcyBjYXRl cmluZyBmb3IgdXNlcnMgdGhhdCBuZWVkIHRvIGhhbmRsZSBhbGwgdGhlCj4gPiArSU9BU0lEcyBp biB0aGUgc3lzdGVtLiBFLmcuIFRoZSBJT01NVSBkcml2ZXIuCj4gPiArCj4gPiArUGVyIGlvYXNp ZF9zZXQgbm90aWZpZXIgY2FuIGJlIHVzZWQgYnkgVk0gc3BlY2lmaWMgY29tcG9uZW50cyBzdWNo IGFzCj4gPiArS1ZNLiBBZnRlciBhbGwsIGVhY2ggS1ZNIGluc3RhbmNlIG9ubHkgY2FyZXMgYWJv dXQgSU9BU0lEcyB3aXRoaW4gaXRzCj4gPiArb3duIHNldC9ndWVzdC4KPiA+ICsKPiA+ICsKPiA+ ICtBdG9taWNpdHkKPiA+ICt+fn5+fn5+fn4KPiA+ICtJT0FTSUQgbm90aWZpZXJzIGFyZSBhdG9t aWMgZHVlIHRvIHNwaW5sb2NrcyB1c2VkIGluc2lkZSB0aGUgSU9BU0lECj4gPiArY29yZS4gRm9y IHRhc2tzIHRoYXQgY2Fubm90IGJlIGNvbXBsZXRlZCBpbiB0aGUgbm90aWZpZXIgaGFuZGxlciwK PiA+ICthc3luYyB3b3JrIGNhbiBiZSBzdWJtaXR0ZWQgdG8gY29tcGxldGUgdGhlIHdvcmsgbGF0 ZXIgYXMgbG9uZyBhcwo+ID4gK3RoZXJlIGlzIG5vIG9yZGVyaW5nIHJlcXVpcmVtZW50Lgo+ID4g Kwo+ID4gK1JlZmVyZW5jZSBjb3VudGluZwo+ID4gKy0tLS0tLS0tLS0tLS0tLS0tLQo+ID4gK0lP QVNJRCBsaWZlY3ljbGUgbWFuYWdlbWVudCBpcyBiYXNlZCBvbiByZWZlcmVuY2UgY291bnRpbmcu IFVzZXJzIG9mCj4gPiArSU9BU0lEIHdobyBpbnRlbmQgdG8gYWxpZ24gbGlmZWN5Y2xlIHdpdGgg dGhlIElPQVNJRCBuZWVkIHRvIGhvbGQKPiA+ICthIHJlZmVyZW5jZSBvZiB0aGUgSU9BU0lELiBU aGUgSU9BU0lEIHdpbGwgbm90IGJlIHJldHVybmVkIHRvIHRoZSBwb29sCj4gPiArZm9yIGFsbG9j YXRpb24gdW50aWwgYWxsIHJlZmVyZW5jZXMgYXJlIGRyb3BwZWQuIENhbGxpbmcgaW9hc2lkX2Zy ZWUoKQo+ID4gK3dpbGwgbWFyayB0aGUgSU9BU0lEIGFzIEZSRUVfUEVORElORyBpZiB0aGUgSU9B U0lEIGhhcyBvdXRzdGFuZGluZwo+ID4gK3JlZmVyZW5jZXMuIE5vIG5ldyByZWZlcmVuY2VzIGNh biBiZSB0YWtlbiBieSBpb2FzaWRfZ2V0KCkgb25jZSBhbgo+ID4gK0lPQVNJRCBpcyBpbiB0aGUg RlJFRV9QRU5ESU5HIHN0YXRlLiBpb2FzaWRfZnJlZSgpIGNhbiBiZSBjYWxsZWQKPiA+ICttdWx0 aXBsZSB0aW1lcyB3aXRob3V0IGFuIGVycm9yIHVudGlsIGFsbCByZWZzIGFyZSBkcm9wcGVkLgo+ ID4gKwo+ID4gK2lvYXNpZF9wdXQoKSBkZWNyZW1lbnRzIGFuZCB0ZXN0cyByZWZjb3VudCBvZiB0 aGUgSU9BU0lELiBJZiByZWZjb3VudAo+ID4gK2lzIDAsIGlvYXNpZCB3aWxsIGJlIGZyZWVkLiBE ZWxldGVkIGZyb20gdGhlIHN5c3RlbS13aWRlIHhhcnJheSBhcwo+ID4gK3dlbGwgYXMgcGVyIHNl dCB4YXJyYXkuICAKPiAKPiBUaGVzZSB4YXJyYXkgc3RydWN0dXJlcyBoYXZlbid0IGJlZW4gaW50 cm9kdWNlZCBzbyBmYXIuIEkgd291bGQgbGVhdmUgb3V0Cj4gdGhpcyBsZXZlbCBvZiBkZXRhaWwg YmVjYXVzZSBpdCdzIG5vdCByZWxldmFudCB0byB0aGUgdXNlciBhbmQgd2lsbCBiZQo+IGRpZmZp Y3VsdCB0byBrZWVwIGluIHN5bmMgd2l0aCB0aGUgaW50ZXJuYWxzIG9mIElPQVNJRC4KPiAKUmln aHQsIEkgd2lsbCBkZWxldGVkIHRoZSB4YXJyYXkgcGFydC4KCj4gPiBUaGUgSU9BU0lEIHdpbGwg YmUgcmV0dXJuZWQgdG8gdGhlIHBvb2wgYW5kCj4gPiArYXZhaWxhYmxlIGZvciBuZXcgYWxsb2Nh dGlvbnMuCj4gPiArCj4gPiArRXZlbnQgbm90aWZpY2F0aW9ucyBhcmUgdXNlZCB0byBpbmZvcm0g dXNlcnMgb2YgSU9BU0lEIHN0YXR1cyBjaGFuZ2UuCj4gPiArSU9BU0lEX0ZSRUUgZXZlbnQgcHJv bXB0cyB1c2VycyB0byBkcm9wIHRoZWlyIHJlZmVyZW5jZXMgYWZ0ZXIKPiA+ICtjbGVhcmluZyBp dHMgY29udGV4dC4KPiA+ICsKPiA+ICtGb3IgZXhhbXBsZSwgb24gVlQtZCBwbGF0Zm9ybSB3aGVu IGFuIElPQVNJRCBpcyBmcmVlZCwgdGVhcmRvd24KPiA+ICthY3Rpb25zIGFyZSBwZXJmb3JtZWQg b24gS1ZNLCBkZXZpY2UgZHJpdmVyIChWRENNKSwgYW5kIHRoZSBJT01NVQo+ID4gK2RyaXZlci4g VG8gcXVpZXNjZSBWQ1BVIGZvciB3b3JrIHN1Ym1pc3Npb24sIEtWTSBub3RpZmllciBoYW5kbGVy IG11c3QKPiA+ICtiZSBjYWxsZWQgYmVmb3JlIFZEQ00gaGFuZGxlci4gVGhlcmVmb3JlLCBLVk0g YW5kIFZEQ00gc2hhbGwgdXNlCj4gPiArbm90aWZpY2F0aW9uIHByaW9yaXR5IElPQVNJRF9QUklP X0NQVSBhbmRJT0FTSURfUFJJT19ERVZJQ0UgIAo+IAo+ICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgYW5kIElPQVNJRF9QUklPX0RFVklDRQo+IApnbyBpdC4KCj4gPiAr cmVzcGVjdGl2ZWx5Lgo+ID4gKwo+ID4gK0ZvciBib3RoIEtWTSBhbmQgVkRDTSwgbm90aWZpZXIg YmxvY2tzIHNoYWxsIGJlIHJlZ2lzdGVyZWQgb24gdGhlCj4gPiArSU9BU0lEIHNldCBzdWNoIHRo YXQgKm9ubHkqIGV2ZW50cyBmcm9tIHRoZSBtYXRjaGluZyBWTSBhcmUgcmVjZWl2ZWQuCj4gPiAr Cj4gPiArSWYgS1ZNIGF0dGVtcHRzIHRvIHJlZ2lzdGVyIGEgbm90aWZpZXIgYmxvY2sgYmVmb3Jl IHRoZSBJT0FTSUQgc2V0IGlzCj4gPiArY3JlYXRlZCB1c2luZyB0aGUgTU0gdG9rZW4sIHRoZSBu b3RpZmllciBibG9jayB3aWxsIGJlIHBsYWNlZCBvbiBhCj4gPiArcGVuZGluZyBsaXN0IGluc2lk ZSBJT0FTSUQgY29yZS4gT25jZSB0aGUgdG9rZW4gbWF0Y2hpbmcgSU9BU0lEIHNldAo+ID4gK2lz IGNyZWF0ZWQsIElPQVNJRCB3aWxsIHJlZ2lzdGVyIHRoZSBub3RpZmllciBibG9jayBhdXRvbWF0 aWNhbGx5Lgo+ID4gK0lPQVNJRCBjb3JlIGRvZXMgbm90IHJlcGxheSBldmVudHMgZm9yIHRoZSBl eGlzdGluZyBJT0FTSURzIGluIHRoZQo+ID4gK3NldC4gRm9yIElPQVNJRCBzZXQgb2YgTU0gdHlw ZSwgbm90aWZpY2F0aW9uIGJsb2NrcyBjYW4gYmUgcmVnaXN0ZXJlZAo+ID4gK29uIGVtcHR5IHNl dHMgb25seS4gVGhpcyBpcyB0byBhdm9pZCBsb3N0IGV2ZW50cy4KPiA+ICsKPiA+ICtJT01NVSBk cml2ZXIgc2hhbGwgcmVnaXN0ZXIgbm90aWZpZXIgYmxvY2sgb24gZ2xvYmFsIGNoYWluOjoKPiA+ ICsKPiA+ICsgc3RhdGljIHN0cnVjdCBub3RpZmllcl9ibG9jayBwYXNpZF9uYl92dGQgPSB7Cj4g PiArCS5ub3RpZmllcl9jYWxsID0gcGFzaWRfc3RhdHVzX2NoYW5nZV92dGQsCj4gPiArCS5wcmlv cml0eSAgICAgID0gSU9BU0lEX1BSSU9fSU9NTVUsCj4gPiArIH07Cj4gPiArCj4gPiArQ3VzdG9t IGFsbG9jYXRvciBBUElzCj4gPiArLS0tLS0tLS0tLS0tLS0tLS0tLS0tCj4gPiArCj4gPiArOjoK PiA+ICsKPiA+ICsgaW50IGlvYXNpZF9yZWdpc3Rlcl9hbGxvY2F0b3Ioc3RydWN0IGlvYXNpZF9h bGxvY2F0b3Jfb3BzICphbGxvY2F0b3IpOwo+ID4gKwo+ID4gKyB2b2lkIGlvYXNpZF91bnJlZ2lz dGVyX2FsbG9jYXRvcihzdHJ1Y3QgaW9hc2lkX2FsbG9jYXRvcl9vcHMKPiA+ICphbGxvY2F0b3Ip OyArCj4gPiArQWxsb2NhdG9yIENob2ljZXMKPiA+ICt+fn5+fn5+fn5+fn5+fn5+fgo+ID4gK0lP QVNJRHMgYXJlIGFsbG9jYXRlZCBmb3IgYm90aCBob3N0IGFuZCBndWVzdCBTVkEvSU9WQSB1c2Fn ZS4gSG93ZXZlciwKPiA+ICthbGxvY2F0b3JzIGNhbiBiZSBkaWZmZXJlbnQuIEZvciBleGFtcGxl LCBvbiBWVC1kIGd1ZXN0IFBBU0lECj4gPiArYWxsb2NhdGlvbiBtdXN0IGJlIHBlcmZvcm1lZCB2 aWEgYSB2aXJ0dWFsIGNvbW1hbmQgaW50ZXJmYWNlIHdoaWNoIGlzCj4gPiArZW11bGF0ZWQgYnkg Vk1NLgo+ID4gKwo+ID4gK0lPQVNJRCBjb3JlIGhhcyB0aGUgbm90aW9uIG9mICJjdXN0b20gYWxs b2NhdG9yIiBzdWNoIHRoYXQgZ3Vlc3QgY2FuCj4gPiArcmVnaXN0ZXIgdmlydHVhbCBjb21tYW5k IGFsbG9jYXRvciB0aGF0IHByZWNlZGVzIHRoZSBkZWZhdWx0IG9uZS4gIAo+IAo+ICJTdXBlcnNl ZGVzIiwgcmF0aGVyIHRoYW4gInByZWNlZGVzIj8KPiAKTXkgdW5kZXJzdGFuZGluZyBpcyB0aGF0 ICdzdXBlcnNlZGUnIG1lYW5zIHJlcGxhY2Ugc29tZXRoaW5nIGJ1dCAncHJlY2VkZScKbWVhbnMg Z2V0IGluIGZyb250IG9mIHNvbWV0aGluZy4gSSBkbyB3YW50IHRvIGVtcGhhc2lzIHRoYXQgdGhl IGN1c3RvbQphbGxvY2F0b3IgdGFrZXMgcHJlY2VkZW5jZSBvdmVyIHRoZSBkZWZhdWx0IGFsbG9j YXRvci4KCj4gPiArCj4gPiArTmFtZXNwYWNlcwo+ID4gK35+fn5+fn5+fn4KPiA+ICtJT0FTSURz IGFyZSBsaW1pdGVkIHN5c3RlbSByZXNvdXJjZXMgdGhhdCBkZWZhdWx0IHRvIDIwIGJpdHMgaW4K PiA+ICtzaXplLiBFYWNoIGRldmljZSBjYW4gaGF2ZSBpdHMgb3duIFBBU0lEIHRhYmxlIGZvciBz ZWN1cml0eSByZWFzb25zLgo+ID4gK1RoZW9yZXRpY2FsbHkgdGhlIG5hbWVzcGFjZSBjYW4gYmUg cGVyIGRldmljZSBhbHNvLgo+ID4gKwo+ID4gK0hvd2V2ZXIgSU9BU0lEIG5hbWVzcGFjZSBpcyBz eXN0ZW0td2lkZSBmb3IgdHdvIHJlYXNvbnM6Cj4gPiArLSBTaW1wbGljaXR5Cj4gPiArLSBTaGFy aW5nIHJlc291cmNlcyBvZiBhIHNpbmdsZSBkZXZpY2UgdG8gbXVsdGlwbGUgVk1zLgo+ID4gKwo+ ID4gK1Rha2UgVlQtZCBhcyBhbiBleGFtcGxlLCBWVC1kIHN1cHBvcnRzIHNoYXJlZCB3b3JrcXVl dWUgYW5kIEVOUUNNRFsxXQo+ID4gK3doZXJlIG9uZSBJT0FTSUQgY291bGQgYmUgdXNlZCB0byBz dWJtaXQgd29yayBvbiBtdWx0aXBsZSBkZXZpY2VzIHRoYXQKPiA+ICthcmUgc2hhcmVkIHdpdGgg b3RoZXIgVk1zLiBUaGlzIHJlcXVpcmVzIElPQVNJRCB0byBiZQo+ID4gK3N5c3RlbS13aWRlLiBU aGlzIGlzIGFsc28gdGhlIHJlYXNvbiB3aHkgZ3Vlc3RzIG11c3QgdXNlIGFuCj4gPiArZW11bGF0 ZWQgdmlydHVhbCBjb21tYW5kIGludGVyZmFjZSB0byBhbGxvY2F0ZSBJT0FTSUQgZnJvbSB0aGUg aG9zdC4KPiA+ICsKPiA+ICtMaWZlIGN5Y2xlCj4gPiArPT09PT09PT09PQo+ID4gK1RoaXMgc2Vj dGlvbiBjb3ZlcnMgSU9BU0lEIGxpZmUgY3ljbGUgbWFuYWdlbWVudCBmb3IgYm90aCBiYXJlLW1l dGFsCj4gPiArYW5kIGd1ZXN0IHVzYWdlcy4gSW4gYmFyZS1tZXRhbCBTVkEsIE1NVSBub3RpZmll ciBpcyBkaXJlY3RseSBob29rZWQKPiA+ICt1cCB3aXRoIElPTU1VIGRyaXZlciwgdGhlcmVmb3Jl IHRoZSBJT0FTSUQgbGlmZSBjeWNsZSBtYXRjaGVzIHRoZQo+ID4gK3Byb2Nlc3MgYWRkcmVzcyBz cGFjZSAoTU0pIGxpZmUgY3ljbGUuCj4gPiArCj4gPiArSG93ZXZlciwgZ3Vlc3QgTU1VIG5vdGlm aWVyIGlzIG5vdCBhdmFpbGFibGUgdG8gaG9zdCBJT01NVSBkcml2ZXIsCj4gPiArd2hlbiBndWVz dCBNTSB0ZXJtaW5hdGVzIHVuZXhwZWN0ZWRseSwgdGhlIGV2ZW50cyBoYXZlIHRvIGdvIHRocm91 Z2gKPiA+ICtWRklPIGFuZCBJT01NVSBVQVBJIHRvIHJlYWNoIGhvc3QgSU9NTVUgZHJpdmVyLiBU aGVyZSBhcmUgYWxzbyBtb3JlCj4gPiArcGFydGllcyBpbnZvbHZlZCBpbiBndWVzdCBTVkEsIGUu Zy4gb24gSW50ZWwgVlQtZCBwbGF0Zm9ybSwgSU9BU0lEcwo+ID4gK2FyZSB1c2VkIGJ5IElPTU1V IGRyaXZlciwgS1ZNLCBWRENNLCBhbmQgVkZJTy4KPiA+ICsKPiA+ICtOYXRpdmUgSU9BU0lEIExp ZmUgQ3ljbGUgKFZULWQgRXhhbXBsZSkKPiA+ICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0KPiA+ICsKPiA+ICtUaGUgbm9ybWFsIGZsb3cgb2YgbmF0aXZlIFNWQSBjb2Rl IHdpdGggSW50ZWwgRGF0YSBTdHJlYW1pbmcKPiA+ICtBY2NlbGVyYXRvcihEU0EpIFsyXSBhcyBl eGFtcGxlOgo+ID4gKwo+ID4gKzEuIEhvc3QgdXNlciBvcGVucyBhY2NlbGVyYXRvciBGRCwgZS5n LiBEU0EgZHJpdmVyLCBvciB1YWNjZTsKPiA+ICsyLiBEU0EgZHJpdmVyIGFsbG9jYXRlIFdRLCBk byBzdmFfYmluZF9kZXZpY2UoKTsKPiA+ICszLiBJT01NVSBkcml2ZXIgY2FsbHMgaW9hc2lkX2Fs bG9jKCksIHRoZW4gYmluZCBQQVNJRCB3aXRoIGRldmljZSwKPiA+ICsgICBtbXVfbm90aWZpZXJf Z2V0KCkKPiA+ICs0LiBETUEgc3RhcnRzIGJ5IERTQSBkcml2ZXIgdXNlcnNwYWNlCj4gPiArNS4g RFNBIHVzZXJzcGFjZSBjbG9zZSBGRAo+ID4gKzYuIERTQS91YWNjZSBrZXJuZWwgZHJpdmVyIGhh bmRsZXMgRkQuY2xvc2UoKQo+ID4gKzcuIERTQSBkcml2ZXIgc3RvcHMgRE1BCj4gPiArOC4gRFNB IGRyaXZlciBjYWxscyBzdmFfdW5iaW5kX2RldmljZSgpOwo+ID4gKzkuIElPTU1VIGRyaXZlciBk b2VzIHVuYmluZCwgY2xlYXJzIFBBU0lEIGNvbnRleHQgaW4gSU9NTVUsIGZsdXNoCj4gPiArICAg VExCcy4gbW11X25vdGlmaWVyX3B1dCgpIGNhbGxlZC4KPiA+ICsxMC4gbW11X25vdGlmaWVyLnJl bGVhc2UoKSBjYWxsZWQsIElPTU1VIFNWQSBjb2RlIGNhbGxzIGlvYXNpZF9mcmVlKCkqCj4gPiAr MTEuIFRoZSBJT0FTSUQgaXMgcmV0dXJuZWQgdG8gdGhlIHBvb2wsIHJlY2xhaW1lZC4KPiA+ICsK PiA+ICs6Ogo+ID4gKwo+ID4gKyAgICogV2l0aCBFTlFDTUQsIFBBU0lEIHVzZWQgb24gVlQtZCBp cyBub3QgcmVsZWFzZWQgaW4gbW11X25vdGlmaWVyKCkKPiA+IGJ1dAo+ID4gKyAgICAgbW1kcm9w KCkuIG1tZHJvcCBjb21lcyBhZnRlciBGRCBjbG9zZSB3aGljaCBkb2VzIG5vdCBtYWtlIGEKPiA+ IGRpZmZlcmVuY2UuICsKPiA+ICtEdXJpbmcgdGhlIG5vcm1hbCB0ZWFyZG93biwgdGhlIGZvbGxv d2luZyB0aHJlZSBrZXkgc3RlcHMgd291bGQgaGFwcGVuCj4gPiBpbiArb3JkZXI6ICg3KSwgKDkp LCAoMTEpLgo+ID4gKwo+ID4gK0V4Y2VwdGlvbiBoYXBwZW5zIHdoZW4gcHJvY2VzcyB0ZXJtaW5h dGVzICpiZWZvcmUqIGRldmljZSBkcml2ZXIgc3RvcHMKPiA+ICtETUEgYW5kIGNhbGwgSU9NTVUg ZHJpdmVyIHRvIHVuYmluZC4gVGhlIGRldGFpbGVkIGZsb3cgb2YgcHJvY2Vzcwo+ID4gK2V4aXRz IGFyZSBhcyBmb2xsb3dzOgo+ID4gKwo+ID4gKzo6Cj4gPiArCj4gPiArICAgZG9fZXhpdCgpIHsK PiA+ICsJZXhpdF9tbSgpIHsKPiA+ICsJCW1tX3B1dCgpOwo+ID4gKwkJZXhpdF9tbWFwKCkgewo+ ID4gKwkJCWludGVsX2ludmFsaWRhdGVfcmFuZ2UoKSAvL21tdSBub3RpZmllcgo+ID4gKwkJCXRs Yl9maW5pc2hfbW11KCkKPiA+ICsJCQltbXVfbm90aWZpZXJfcmVsZWFzZShtbSkgewo+ID4gKwkJ CQlpbnRlbF9tbV9yZWxlYXNlKCkgewo+ID4gKyAgICg5KQo+ID4gaW50ZWxfaW9tbXVfdGVhcmRv d25fcGFzaWQoKTsKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg aW50ZWxfaW9tbXVfZmx1c2hfdGxicygpOwo+ID4gKwkJCQl9Cj4gPiArCQkJCS8vIHRsYl9pbnZh bGlkYXRlX3JhbmdlIGNiIHJlbW92ZWQKPiA+ICsJCQl9Cj4gPiArCQkJdW5tYXBfdm1hcygpOwo+ ID4gKyAgICAgICAgICAgICAgICAgICAgICAgIGZyZWVfcGd0YWJsZXMoKTsgLy8gSU9NTVUgY2Fu bm90IHdhbGsgUEdUCj4gPiBhZnRlciB0aGlzICAKPiAKPiBvciByYXRoZXIsIGl0ICptdXN0KiBu b3Qgd2FsayBQR1QgYXQgdGhpcyBwb2ludD8gUEdUIHNob3VsZCBiZSBkaXNhYmxlZCBvbgo+IHRo ZSBJT01NVSBzaWRlIGF0IHN0ZXAgOSwgYmVmb3JlIHRoZSBUTEIgaW52YWxpZGF0aW9uCj4gClll cywgYWdyZWVkIGFscmVhZHkgZ3VhcmFudGVlZC4gSSB3aWxsIGRlbGV0ZSB0aGUgY29tbWVudC4K Cj4gPiArCQl9Owo+ID4gKwl9Cj4gPiArCWV4aXRfZmlsZXModHNrKSB7Cj4gPiArCQljbG9zZV9m aWxlcygpIHsKPiA+ICsJCQlkc2FfY2xvc2UoKTsKPiA+ICsgICAoNykJCQlkc2Ffc3RvcF9kbWEo KTsKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICBpbnRlbF9zdm1fdW5iaW5kX3Bhc2lkKCk7 IC8vbm90aGluZyB0byBkbwo+ID4gKwkJfQo+ID4gKwl9Cj4gPiArICAgfQo+ID4gKwo+ID4gKyAg IG1tZHJvcCgpIC8qIHNvbWUgcmFuZG9tIHRpbWUgbGF0ZXIsIGxhenkgbW0gdXNlciAqLyB7Cj4g PiArICAgCW1tX2ZyZWVfcGdkKCk7Cj4gPiArICAgICAgICBkZXN0cm95X2NvbnRleHQobW0pOyB7 Cj4gPiArICAgKDExKQkgICAgICAgIGlvYXNpZF9mcmVlKCk7Cj4gPiArCX0KPiA+ICsgICB9Cj4g PiArCj4gPiArQXMgc2hvd24gaW4gdGhlIGxpc3QgYWJvdmUsIHN0ZXAgIzIgY291bGQgaGFwcGVu IGJlZm9yZQo+ID4gKyMxLiBVbnJlY292ZXJhYmxlKFVSKSBmYXVsdHMgY291bGQgaGFwcGVuIGJl dHdlZW4gIzIgYW5kICMxLgo+ID4gK0ZhdWx0IHByb2Nlc3NpbmcgaXMgZGlzYWJsZWQgYnkgdGhl IElPTU1VIGRyaXZlciBpbiAjMiwgdGhlcmVmb3JlIHRoZQo+ID4gVVIgK2ZhdWx0IG5ldmVyIHJl YWNoZXMgdGhlIGRyaXZlci4gIAo+IAo+IERpZCB5b3UgbWVhbiBzdGVwcyAoNykgYW5kICg5KSBp bnN0ZWFkIGZvciAjMSBhbmQgIzI/Cj4gClllcywgZm9yZ290IHRvIHVwZGF0ZSB0aGUgaW5kZXgu Cgo+ID4gKwo+ID4gKwo+ID4gK0Fsc28gbm90aWNlIHRoYXQgVExCIGludmFsaWRhdGlvbiBvY2N1 cnMgYXQgbW11X25vdGlmaWVyCj4gPiAraW52YWxpZGF0ZV9yYW5nZSBjYWxsYmFjayBhcyB3ZWxs IGFzIHRoZSByZWxlYXNlIGNhbGxiYWNrLiBUaGUgcmVhc29uCj4gPiAraXMgdGhhdCByZWxlYXNl IGNhbGxiYWNrIHdpbGwgZGVsZXRlIElPTU1VIGRyaXZlciBmcm9tIHRoZSBub3RpZmllcgo+ID4g K2NoYWluIHdoaWNoIG1heSBza2lwIGludmFsaWRhdGVfcmFuZ2UoKSBjYWxscyBkdXJpbmcgdGhl IGV4aXQgcGF0aC4gIAo+IAo+IEkgdGhpbmsgdGhpcyB3aG9sZSBzZWN0aW9uIGFsc28gZ29lcyB0 b28gZGVlcCBpbiBpbXBsZW1lbnRhdGlvbiBkZXRhaWxzLAo+IGFuZCBpcyBzdXNjZXB0aWJsZSB0 byBiZWNvbWUgb3V0IG9mIHN5bmMgd2l0aCB0aGUgY29kZSBwcmV0dHkgcXVpY2tseS4KPiBJIGRv bid0IGZlZWwgc3Ryb25nbHkgYWJvdXQgdGhpcywgdGhvdWdoLCBsZWF2ZSBpdCBpZiB5b3Ugd2Fu dC4KPiAKSSB3aWxsIGRlbGV0ZSB0aGlzLCBiZXR0ZXIgYmUgYWNjdXJhdGUgdGhhbiBtaXNsZWFk aW5nLgoKPiA+ICsKPiA+ICtUbyBhdm9pZCB1bm5lY2Vzc2FyeSByZXBvcnRpbmcgb2YgVVIgZmF1 bHQsIElPTU1VIGRyaXZlciBzaGFsbCBkaXNhYmxlCj4gPiArZmF1bHQgcmVwb3J0aW5nIGFmdGVy IGZyZWUgYW5kIGJlZm9yZSB1bmJpbmQuCj4gPiArCj4gPiArR3Vlc3QgSU9BU0lEIExpZmUgQ3lj bGUgKFZULWQgRXhhbXBsZSkKPiA+ICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLQo+ID4gK0d1ZXN0IElPQVNJRCBsaWZlIGN5Y2xlIHN0YXJ0cyB3aXRoIGd1ZXN0IGRyaXZl ciBvcGVuKCksIHRoaXMgY291bGQgYmUKPiA+ICt1YWNjZSBvciBpbmRpdmlkdWFsIGFjY2VsZXJh dG9yIGRyaXZlciBzdWNoIGFzIERTQS4gQXQgRkQgb3BlbiwKPiA+ICtzdmFfYmluZF9kZXZpY2Uo KSBpcyBjYWxsZWQgd2hpY2ggdHJpZ2dlcnMgYSBzZXJpZXMgb2YgYWN0aW9ucy4KPiA+ICsKPiA+ ICtUaGUgZXhhbXBsZSBiZWxvdyBpcyBhbiBpbGx1c3RyYXRpb24gb2YgKm5vcm1hbCogb3BlcmF0 aW9ucyB0aGF0Cj4gPiAraW52b2x2ZXMgKmFsbCogdGhlIFNXIGNvbXBvbmVudHMgaW4gVlQtZC4g VGhlIGZsb3cgY2FuIGJlIHNpbXBsZXIgaWYKPiA+ICtubyBFTlFDTUQgaXMgc3VwcG9ydGVkLgo+ ID4gKwo+ID4gKzo6Cj4gPiArCj4gPiArICAgICBWRklPICAgICAgICBJT01NVSAgICAgICAgS1ZN ICAgICAgICBWRENNICAgICAgICBJT0FTSUQgICAgICAgUmVmCj4gPiArICAgLi4uLi4uLi4uLi4u Li4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uCj4g PiArICAgMSAgICAgICAgICAgICBpb2FzaWRfcmVnaXN0ZXJfbm90aWZpZXIvX21tKCkKPiA+ICsg ICAyIGlvYXNpZF9hbGxvYygpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAxCj4gPiArICAgMyBiaW5kX2dwYXNpZCgpCj4gPiArICAgNCAgICAgICAgICAgICBp b21tdV9iaW5kKCktPmlvYXNpZF9nZXQoKSAgICAgICAgICAgICAgICAgICAgICAgMgo+ID4gKyAg IDUgICAgICAgICAgICAgaW9hc2lkX25vdGlmeShCSU5EKQo+ID4gKyAgIDYgICAgICAgICAgICAg ICAgICAgICAgICAgIC0+IGlvYXNpZF9nZXQoKSAgICAgICAgICAgICAgICAgICAgIDMKPiA+ICsg ICA3ICAgICAgICAgICAgICAgICAgICAgICAgICAtPiB2bWNzX3VwZGF0ZV9hdG9taWMoKQo+ID4g KyAgIDggbWRldl93cml0ZShncGFzaWQpCj4gPiArICAgOSAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgIGhwYXNpZD0KPiA+ICsgICAxMCAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgZmluZF9ieV9zcGlkKGdwYXNpZCkgICAgICA0ICAKPiAKPiBBcmUgOSBhbmQgMTAg dGhlIHNhbWUgc3RlcD8KPiAKeWVzLCBoZXJlIGlzIGp1c3QgbGluZSAjLgoKPiA+ICsgICAxMSAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmRldl93cml0ZShocGFzaWQpICAKPiAK PiBXaGF0J3MgdGhlICd2JyBpbiB2ZGV2PyBBcmVuJ3Qgd2Ugd3JpdGluZyB0byB0aGUgcGh5c2lj YWwgZGV2aWNlIGhlcmU/Cj4gClllcywgd2UgYXJlIHdyaXRpbmcgdG8gdGhlIHBoeXNpY2FsIHJl c291cmNlIG9mIHRoZSB2aXJ0dWFsIGRldmljZS4gTGV0IG1lCnJlbW92ZSB0aGUgJ3YnLgoKPiA+ ICsgICAxMiAtLS0tLS0tLSBHVUVTVCBTVEFSVFMgRE1BIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tCj4gPiArICAgMTMgLS0tLS0tLS0gR1VFU1QgU1RPUFMgRE1BIC0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tCj4gPiArICAgMTQgbWRldl9jbGVhcihncGFzaWQpCj4gPiArICAgMTUgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZkZXZfY2xlYXIoaHBhc2lkKQo+ID4gKyAgIDE2 ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpb2FzaWRfcHV0KCkgICAgICAgICAg ICAgICAzCj4gPiArICAgMTcgdW5iaW5kX2dwYXNpZCgpCj4gPiArICAgMTggICAgICAgICAgICBp b21tdV91YmluZCgpCj4gPiArICAgMTkgICAgICAgICAgICBpb2FzaWRfbm90aWZ5KFVOQklORCkK PiA+ICsgICAyMCAgICAgICAgICAgICAgICAgICAgICAgICAgLT4gdm1jc191cGRhdGVfYXRvbWlj KCkKPiA+ICsgICAyMSAgICAgICAgICAgICAgICAgICAgICAgICAgLT4gaW9hc2lkX3B1dCgpICAg ICAgICAgICAgICAgICAgICAgMgo+ID4gKyAgIDIyIGlvYXNpZF9mcmVlKCkgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxCj4gPiArICAgMjMgICAgICAgICAg ICBpb2FzaWRfcHV0KCkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDAKPiA+ ICsgICAyNCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBS ZWNsYWltZWQKPiA+ICsgICAtLS0tLS0tLS0tLS0tLSBOZXcgTGlmZSBDeWNsZSBCZWdpbiAtLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCj4gPiArICAgMSAgaW9hc2lkX2FsbG9jKCkgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgLT4gICAgICAgICAgIDEKPiA+ICsKPiA+ICsgICBO b3RlOiBJT0FTSUQgTm90aWZpY2F0aW9uIEV2ZW50czogRlJFRSwgQklORCwgVU5CSU5EICAKPiAK PiBJcyBGUkVFIGF0IHN0ZXAgMjI/Cj4gClllcyB0aGUgSU9BU0lEX0ZSRUUgZXZlbnQgc2hvdWxk IGJlIHNlbnQgYXQgc3RlcCAyMiwgbGV0IG1lIGNhbGwgaXQgb3V0CmV4cGxpY2l0bHkuCgo+ID4g Kwo+ID4gK0V4Y2VwdGlvbiBjYXNlcyBhcmlzZSB3aGVuIGEgZ3Vlc3QgY3Jhc2hlcyBvciBhIG1h bGljaW91cyBndWVzdAo+ID4gK2F0dGVtcHRzIHRvIGNhdXNlIGRpc3J1cHRpb24gb24gdGhlIGhv c3Qgc3lzdGVtLiBUaGUgZmF1bHQgaGFuZGxpbmcKPiA+ICtydWxlcyBhcmU6Cj4gPiArCj4gPiAr MS4gSU9BU0lEIGZyZWUgbXVzdCAqYWx3YXlzKiBzdWNjZWVkLgo+ID4gKzIuIEFuIGluYWN0aXZl IHBlcmlvZCBtYXkgYmUgcmVxdWlyZWQgYmVmb3JlIHRoZSBmcmVlZCBJT0FTSUQgaXMKPiA+ICsg ICByZWNsYWltZWQuIER1cmluZyB0aGlzIHBlcmlvZCwgY29uc3VtZXJzIG9mIElPQVNJRCBwZXJm b3JtIGNsZWFudXAuCj4gPiArMy4gTWFsZnVuY3Rpb24gaXMgbGltaXRlZCB0byB0aGUgZ3Vlc3Qg b3duZWQgcmVzb3VyY2VzIGZvciBhbGwKPiA+ICsgICBwcm9ncmFtbWluZyBlcnJvcnMuCj4gPiAr Cj4gPiArVGhlIHByaW1hcnkgc291cmNlIG9mIGV4Y2VwdGlvbiBpcyB3aGVuIHRoZSBmb2xsb3dp bmcgYXJlIG91dCBvZgo+ID4gK29yZGVyOgo+ID4gKwo+ID4gKzEuIFN0YXJ0L1N0b3Agb2YgRE1B IGFjdGl2aXR5Cj4gPiArICAgKEd1ZXN0IGRldmljZSBkcml2ZXIsIG1kZXYgdmlhIFZGSU8pCj4g PiArMi4gU2V0dXAvVGVhcmRvd24gb2YgSU9NTVUgUEFTSUQgY29udGV4dCwgSU9UTEIsIERldlRM QiBmbHVzaGVzCj4gPiArICAgKEhvc3QgSU9NTVUgZHJpdmVyIGJpbmQvdW5iaW5kKQo+ID4gKzMu IFNldHVwL1RlYXJkb3duIG9mIFZNQ1MgUEFTSUQgdHJhbnNsYXRpb24gdGFibGUgZW50cmllcyAo S1ZNKSBpbgo+ID4gKyAgIGNhc2Ugb2YgRU5RQ01ECj4gPiArNC4gUHJvZ3JhbW1pbmcvQ2xlYXJp bmcgaG9zdCBQQVNJRCBpbiBWRENNIChIb3N0IFZEQ00gZHJpdmVyKQo+ID4gKzUuIElPQVNJRCBh bGxvYy9mcmVlIChIb3N0IElPQVNJRCkKPiA+ICsKPiA+ICtWRklPIGlzIHRoZSAqb25seSogdXNl ci1rZXJuZWwgaW50ZXJmYWNlLCB3aGljaCBpcyB1bHRpbWF0ZWx5Cj4gPiArcmVzcG9uc2libGUg Zm9yIGV4Y2VwdGlvbiBoYW5kbGluZy4KPiA+ICsKPiA+ICsjMSBpcyBwcm9jZXNzZWQgdGhlIHNh bWUgd2F5IGFzIHRoZSBhc3NpZ25lZCBkZXZpY2UgdG9kYXkgYmFzZWQgb24KPiA+ICtkZXZpY2Ug ZmlsZSBkZXNjcmlwdG9ycyBhbmQgZXZlbnRzLiBUaGVyZSBpcyBubyBzcGVjaWFsIGhhbmRsaW5n Lgo+ID4gKwo+ID4gKyMzIGlzIGJhc2VkIG9uIGJpbmQvdW5iaW5kIGV2ZW50cyBlbWl0dGVkIGJ5 ICMyLgo+ID4gKwo+ID4gKyM0IGlzIG5hdHVyYWxseSBhbGlnbmVkIHdpdGggSU9BU0lEIGxpZmUg Y3ljbGUgaW4gdGhhdCBhbiBpbGxlZ2FsCj4gPiArZ3Vlc3QgUEFTSUQgcHJvZ3JhbW1pbmcgd291 bGQgZmFpbCBpbiBvYnRhaW5pbmcgcmVmZXJlbmNlIG9mIHRoZQo+ID4gK21hdGNoaW5nIGhvc3Qg SU9BU0lELgo+ID4gKwo+ID4gKyM1IGlzIHNpbWlsYXIgdG8gIzQuIFRoZSBmYXVsdCB3aWxsIGJl IHJlcG9ydGVkIHRvIHRoZSB1c2VyIGlmIFBBU0lECj4gPiArdXNlZCBpbiB0aGUgRU5RQ01EIGlz IG5vdCBzZXQgdXAgaW4gVk1DUyBQQVNJRCB0cmFuc2xhdGlvbiB0YWJsZS4KPiA+ICsKPiA+ICtU aGVyZWZvcmUsIHRoZSByZW1haW5pbmcgb3V0IG9mIG9yZGVyIHByb2JsZW0gaXMgYmV0d2VlbiAj MiBhbmQKPiA+ICsjNS4gSS5lLiB1bmJpbmQgdnMuIGZyZWUuIE1vcmUgc3BlY2lmaWNhbGx5LCBm cmVlIGJlZm9yZSB1bmJpbmQuCj4gPiArCj4gPiArSU9BU0lEIG5vdGlmaWVyIGFuZCByZWZjb3Vu dGluZyBhcmUgdXNlZCB0byBlbnN1cmUgb3JkZXIuIEZvbGxvd2luZwo+ID4gK2EgcHVibGlzaGVy LXN1YnNjcmliZXIgcGF0dGVybiB3aGVyZToKPiA+ICsKPiA+ICstIFB1Ymxpc2hlcnM6IFZGSU8g JiBJT01NVQo+ID4gKy0gU3Vic2NyaWJlcnM6IEtWTSwgVkRDTSwgSU9NTVUKPiA+ICsKPiA+ICtJ T0FTSUQgcmVmZXJlbmNlIG11c3QgYmUgYWNxdWlyZWQgYmVmb3JlIHJlY2VpdmluZyB0aGUgRlJF RSBldmVudC4gVGhlCj4gPiArcmVmZXJlbmNlIG11c3QgYmUgZHJvcHBlZCBhdCB0aGUgZW5kIG9m IHRoZSBwcm9jZXNzaW5nIGluIG9yZGVyIHRvCj4gPiArcmV0dXJuIHRoZSBJT0FTSUQgdG8gdGhl IHBvb2wuCj4gPiArCj4gPiArTGV0J3MgZXhhbWluZSB0aGUgSU9BU0lEIGxpZmUgY3ljbGUgYWdh aW4gd2hlbiBmcmVlIGhhcHBlbnMgKmJlZm9yZSoKPiA+ICt1bmJpbmQuIFRoaXMgY291bGQgYmUg YSByZXN1bHQgb2YgbWlzYmVoYXZpbmcgZ3Vlc3RzIG9yIGNyYXNoLiBBc3N1bWluZwo+ID4gK1ZG SU8gY2Fubm90IGVuZm9yY2UgdW5iaW5kLT5mcmVlIG9yZGVyLiBOb3RpY2UgdGhhdCB0aGUgc2V0 dXAgcGFydCB1cAo+ID4gK3VudGlsIHN0ZXAgIzEyIGlzIGlkZW50aWNhbCB0byB0aGUgbm9ybWFs IGNhc2UsIHRoZSBmbG93IGJlbG93IHN0YXJ0cwo+ID4gK3dpdGggc3RlcCAxMy4KPiA+ICsKPiA+ ICs6Ogo+ID4gKwo+ID4gKyAgICAgVkZJTyAgICAgICAgSU9NTVUgICAgICAgIEtWTSAgICAgICAg VkRDTSAgICAgICAgSU9BU0lEICAgICAgIFJlZgo+ID4gKyAgIC4uLi4uLi4uLi4uLi4uLi4uLi4u Li4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLgo+ID4gKyAgIDEz IC0tLS0tLS0tIEdVRVNUIFNUQVJUUyBETUEgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KPiA+ ICsgICAxNCAtLS0tLS0tLSAqR1VFU1QgTUlTQkVIQVZFUyEhISogLS0tLS0tLS0tLS0tLS0tLQo+ ID4gKyAgIDE1IGlvYXNpZF9mcmVlKCkKPiA+ICsgICAxNiAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgIGlvYXNpZF9ub3RpZnkoRlJFRSkKPiA+ICsgICAxNyAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtfZnJlZV9wZW5kaW5n Cj4gPiAoMSkgIAo+IAo+IENvdWxkIHdlIHVzZSBzdXBlcnNjcmlwdCDCucKywrPigbQgZm9yIGZv b3Rub3Rlcz8gVGhlc2UgbG9vayBsaWtlIGZ1bmN0aW9uCj4gcGFyYW1ldGVycwo+IAp5ZXMsIG11 Y2ggYmV0dGVyCgo+ID4gKyAgIDE4ICAgICAgICAgICAgICAgICAgICAgICAgICBrdm1fbmJfaGFu ZGxlcihGUkVFKQo+ID4gKyAgIDE5ICAgICAgICAgICAgICAgICAgICAgICAgICB2bWNzX3VwZGF0 ZV9hdG9taWMoKQo+ID4gKyAgIDIwICAgICAgICAgICAgICAgICAgICAgICAgICBpb2FzaWRfcHV0 X2xvY2tlZCgpICAgLT4gICAgICAgICAgIDMKPiA+ICsgICAyMSAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgdmRjbV9uYl9oYW5kbGVyKEZSRUUpCj4gPiArICAgMjIgICAgICAgICAg ICBpb21tX25iX2hhbmRsZXIoRlJFRSkgIAo+IAo+IGlvbW11X25iX2hhbmRsZXIKPiAKZ290IGl0 Cgo+ID4gKyAgIDIzIGlvYXNpZF9mcmVlKCkgcmV0dXJucygyKSAgICAgICAgICBzY2hlZHVsZV93 b3JrKCkgICAgICAgICAgIDIgIAo+IAo+IEkgY29tcGxldGVseSBsb3N0IHRyYWNrIGhlcmUsIGNv dWxkbid0IGZpZ3VyZSBvdXQgaW4gd2hpY2ggZGlyZWN0aW9uIHRvCj4gcmVhZCB0aGUgZGlhZ3Jh bS4gV2hhdCB3b3JrIGlzIHNjaGVkdWxlZD8KVGhlIHRpbWUgbGluZSBnb2VzIGRvd253YXJkIGJ1 dCB3ZSBvbmx5IGNvbnRyb2wgdGhlIG5vdGlmaWNhdGlvbiBvcmRlciBpbgp0ZXJtcyBvZiB3aGVu IHRoZSBldmVudHMgYXJlIHJlY2VpdmVkLiBTb21lIGNvbXBsZXRpb25zIGFyZSBhc3luYyB0aHVz IG91dApvZiBvcmRlciBkb25lIGJ5IHdvcmsgaXRlbXMuIFRoZSBvbmx5IGluLW9yZGVyIGNvbXBs ZXRpb24gaXMgdGhlIEtWTSB1cGRhdGUKb2YgaXRzIFBBU0lEIHRyYW5zbGF0aW9uIHRhYmxlLgoK QWZ0ZXIgIzIzLCB0aGUgYXN5bmMgd29ya3MgYXJlIHNjaGVkdWxlZCB0byBjb21wbGV0ZSBjbGVh biB1cCB3b3JrIG91dHNpZGUKdGhlIHNwaW5sb2NrKGhlbGQgYnkgdGhlIGNhbGxlciBvZiB0aGUg YXRvbWljIG5vdGlmaWVyKS4KCkFueSBzdWdnZXN0aW9ucyB0byBpbXByb3ZlIHRoZSByZWFkYWJp bGl0eSBvZiB0aGUgdGltZSBsaW5lPwoKPiBXaHkgZG9lcyB0aGUgSU9NTVUgZHJpdmVyIGRyb3AK PiBpdHMgcmVmZXJlbmNlIHRvIHRoZSBJT0FTSUQgYmVmb3JlIHVuYmRpbmRfZ3Bhc2lkKCk/Cj4g ClRoaXMgaXMgdGhlIGV4Y2VwdGlvbiBjYXNlIHdoZXJlIHVzZXJzcGFjZSBpc3N1ZXMgSU9BU0lE IGZyZWUgYmVmb3JlCnVuYmluZF9ncGFzaWQoKS4gVGhlIGVxdWl2YWxlbnQgb2YgdW5iaW5kIGlz IHBlcmZvcm1lZCBpbiB0aGUgSU9BU0lEX0ZSRUUKbm90aWZpY2F0aW9uIGhhbmRsZXIuIEluIElP QVNJRF9GUkVFIGhhbmRsZXIsIHJlZmVyZW5jZSBpcyBkcm9wcGVkIGFuZApwcml2YXRlIGRhdGEg ZGVsZXRlZC4gQWZ0ZXIgdGhhdCwgaWYgdW5iaW5kIGNvbWVzIHRvIElPTU1VIGRyaXZlciwgaXQg d2lsbApub3QgZmluZCBJT0FTSUQgcHJpdmF0ZSBkYXRhIHRoZXJlZm9yZSBqdXN0IHJldHVybi4K Cj4gPiArICAgMjQgICAgICAgICAgICBzY2hlZHVsZV93b3JrKCkgICAgICAgIHZkZXZfY2xlYXJf d2soaHBhc2lkKQo+ID4gKyAgIDI1ICAgICAgICAgICAgdGVhcmRvd25fcGFzaWRfd2soKQo+ID4g KyAgIDI2ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpb2FzaWRfcHV0KCkgLT4g ICAgICAgICAgIDEKPiA+ICsgICAyNyAgICAgICAgICAgIGlvYXNpZF9wdXQoKSAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAwCj4gPiArICAgMjggICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUmVjbGFpbWVkCj4gPiArICAgMjkgdW5iaW5k X2dwYXNpZCgpCj4gPiArICAgMzAgICAgICAgICAgICBpb21tdV91bmJpbmQoKS0+aW9hc2lkX2Zp bmQoKSBGYWlscygzKQo+ID4gKyAgIC0tLS0tLS0tLS0tLS0tIE5ldyBMaWZlIEN5Y2xlIEJlZ2lu IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KPiA+ICsKPiA+ICtOb3RlOgo+ID4gKwo+ID4g KzEuIEJ5IG1hcmtpbmcgSU9BU0lEIEZSRUVfUEVORElORyBhdCBzdGVwICMxNywgbm8gbmV3IHJl ZmVyZW5jZXMgY2FuIGJlCj4gPiArICAgaGVsZC4gaW9hc2lkX2dldC9maW5kKCkgd2lsbCByZXR1 cm4gLUVOT0VOVDsgIAo+IAo+IHMvaGVsZC90YWtlbgo+IApHb3QgaXQuCgo+IFRoYW5rcywKPiBK ZWFuCj4gCj4gPiArMi4gQWZ0ZXIgc3RlcCAjMjMsIGFsbCBldmVudHMgY2FuIGdvIG91dCBvZiBv cmRlci4gU2hhbGwgbm90IGFmZmVjdAo+ID4gKyAgIHRoZSBvdXRjb21lLgo+ID4gKzMuIElPTU1V IGRyaXZlciBmYWlscyB0byBmaW5kIHByaXZhdGUgZGF0YSBmb3IgdW5iaW5kaW5nLiBJZiB1bmJp bmQgaXMKPiA+ICsgICBjYWxsZWQgYWZ0ZXIgdGhlIHNhbWUgSU9BU0lEIGlzIGFsbG9jYXRlZCBm b3IgdGhlIHNhbWUgZ3Vlc3QgYWdhaW4sCj4gPiArICAgdGhpcyBpcyBhIHByb2dyYW1taW5nIGVy cm9yLiBUaGUgZGFtYWdlIGlzIGxpbWl0ZWQgdG8gdGhlIGd1ZXN0Cj4gPiArICAgaXRzZWxmIHNp bmNlIHVuYmluZCBwZXJmb3JtcyBwZXJtaXNzaW9uIGNoZWNraW5nIGJhc2VkIG9uIHRoZQo+ID4g KyAgIElPQVNJRCBzZXQgYXNzb2NpYXRlZCB3aXRoIHRoZSBndWVzdCBwcm9jZXNzLgo+ID4gKzQu IFdvcmtxdWV1ZXMgYXJlIHVzZWQgYnkgVkRDTSBhbmQgSU9NTVUgZHJpdmVyIGZvciBwcm9jZXNz aW5nIHRoYXQKPiA+ICsgICByZXF1aXJlcyB0aHJlYWQgY29udGV4dC4KPiA+ICsKPiA+ICsKPiA+ ICtLVk0gUEFTSUQgVHJhbnNsYXRpb24gVGFibGUgVXBkYXRlcwo+ID4gK35+fn5+fn5+fn5+fn5+ fn5+fn5+fn5+fn5+fn5+fn5+fn5+Cj4gPiArUGVyIFZNIFBBU0lEIHRyYW5zbGF0aW9uIHRhYmxl IGlzIG1haW50YWluZWQgYnkgS1ZNIGluIG9yZGVyIHRvCj4gPiArc3VwcG9ydCBFTlFDTUQgaW4g dGhlIGd1ZXN0LiBUaGUgdGFibGUgY29udGFpbnMgaG9zdC1ndWVzdCBQQVNJRAo+ID4gK3RyYW5z bGF0aW9ucyB0byBiZSBjb25zdW1lZCBieSBDUFUgdWNvZGUuIFRoZSBzeW5jaHJvbml6YXRpb24g b2YgdGhlCj4gPiArUEFTSUQgc3RhdGVzIGRlcGVuZHMgb24gVkZJTy9JT01NVSBkcml2ZXIsIHdo ZXJlIElPQ1RMIGFuZCBhdG9taWMKPiA+ICtub3RpZmllcnMgYXJlIHVzZWQuIEtWTSBtdXN0IHJl Z2lzdGVyIElPQVNJRCBub3RpZmllciBwZXIgVk0gaW5zdGFuY2UKPiA+ICtkdXJpbmcgbGF1bmNo IHRpbWUuIFRoZSBmb2xsb3dpbmcgZXZlbnRzIGFyZSBoYW5kbGVkOgo+ID4gKwo+ID4gKzEuIEJJ TkQvVU5CSU5ECj4gPiArMi4gRlJFRQo+ID4gKwo+ID4gK1J1bGVzOgo+ID4gKwo+ID4gKzEuIE11 bHRpcGxlIGRldmljZXMgY2FuIGJpbmQgd2l0aCB0aGUgc2FtZSBQQVNJRCwgdGhpcyBjYW4gYmUK PiA+IGRpZmZlcmVudCBQQ0kKPiA+ICsgICBkZXZpY2VzIG9yIG1kZXZzIHdpdGhpbiB0aGUgc2Ft ZSBQQ0kgZGV2aWNlLiBIb3dldmVyLCBvbmx5IHRoZQo+ID4gKyAgICpmaXJzdCogQklORCBhbmQg Kmxhc3QqIFVOQklORCBlbWl0IG5vdGlmaWNhdGlvbnMuCj4gPiArMi4gSU9BU0lEIGNvZGUgaXMg cmVzcG9uc2libGUgZm9yIGVuc3VyaW5nIHRoZSBjb3JyZWN0bmVzcyBvZiBILUcKPiA+ICsgICBQ QVNJRCBtYXBwaW5nLiBUaGVyZSBpcyBubyBuZWVkIGZvciBLVk0gdG8gdmFsaWRhdGUgdGhlCj4g PiArICAgbm90aWZpY2F0aW9uIGRhdGEuCj4gPiArMy4gV2hlbiBVTkJJTkQgaGFwcGVucyAqYWZ0 ZXIqIEZSRUUsIEtWTSB3aWxsIHNlZSBlcnJvciBpbgo+ID4gKyAgIGlvYXNpZF9nZXQoKSBldmVu IHdoZW4gdGhlIHJlY2xhaW0gaXMgbm90IGRvbmUuIElPTU1VIGRyaXZlciB3aWxsCj4gPiArICAg YWxzbyBhdm9pZCBzZW5kaW5nIFVOQklORCBpZiB0aGUgUEFTSUQgaXMgYWxyZWFkeSBGUkVFLgo+ ID4gKzQuIFdoZW4gS1ZNIHRlcm1pbmF0ZXMgKmJlZm9yZSogRlJFRSAmIFVOQklORCwgcmVmZXJl bmNlcyB3aWxsIGJlCj4gPiArICAgZHJvcHBlZCBmb3IgYWxsIGhvc3QgUEFTSURzLgo+ID4gKwo+ ID4gK1ZEQ00gUEFTSUQgUHJvZ3JhbW1pbmcKPiA+ICt+fn5+fn5+fn5+fn5+fn5+fn5+fn5+Cj4g PiArVkRDTSBjb21wb3NlcyB2aXJ0dWFsIGRldmljZXMgYW5kIGV4cG9zZXMgdGhlbSB0byB0aGUg Z3Vlc3RzLiBXaGVuCj4gPiArdGhlIGd1ZXN0IGFsbG9jYXRlcyBhIFBBU0lEIHRoZW4gcHJvZ3Jh bSBpdCB0byB0aGUgdmlydHVhbCBkZXZpY2UsIFZEQ00KPiA+ICtpbnRlcmNlcHRzIHRoZSBwcm9n cmFtbWluZyBhdHRlbXB0IHRoZW4gcHJvZ3JhbXMgdGhlIG1hdGNoaW5nIGhvc3QKPiA+ICtQQVNJ RCBvbiB0byB0aGUgaGFyZHdhcmUuCj4gPiArQ29udmVyc2VseSwgd2hlbiBhIGRldmljZSBpcyBn b2luZyBhd2F5LCBWRENNIG11c3QgYmUgaW5mb3JtZWQgc3VjaAo+ID4gK3RoYXQgUEFTSUQgY29u dGV4dCBvbiB0aGUgaGFyZHdhcmUgY2FuIGJlIGNsZWFyZWQuIFRoZXJlIGNvdWxkIGJlCj4gPiAr bXVsdGlwbGUgbWRldnMgYXNzaWduZWQgdG8gZGlmZmVyZW50IGd1ZXN0cyBpbiB0aGUgc2FtZSBW RENNLiBTaW5jZQo+ID4gK3RoZSBQQVNJRCB0YWJsZSBpcyBzaGFyZWQgYXQgUENJIGRldmljZSBs ZXZlbCwgbGF6eSBjbGVhcmluZyBpcyBub3QKPiA+ICtzZWN1cmUuIEEgbWFsaWNpb3VzIGd1ZXN0 IGNhbiBhdHRhY2sgYnkgdXNpbmcgbmV3bHkgZnJlZWQgUEFTSURzIHRoYXQKPiA+ICthcmUgYWxs b2NhdGVkIGJ5IGFub3RoZXIgZ3Vlc3QuCj4gPiArCj4gPiArQnkgaG9sZGluZyBhIHJlZmVyZW5j ZSBvZiB0aGUgUEFTSUQgdW50aWwgVkRDTSBjbGVhbnMgdXAgdGhlIEhXCj4gPiBjb250ZXh0LCAr aXQgaXMgZ3VhcmFudGVlZCB0aGF0IFBBU0lEIGxpZmUgY3ljbGVzIGRvIG5vdCBjcm9zcyB3aXRo aW4KPiA+IHRoZSBzYW1lICtkZXZpY2UuCj4gPiArCj4gPiArCj4gPiArUmVmZXJlbmNlCj4gPiAr PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQo+ID4g KzEuCj4gPiBodHRwczovL3NvZnR3YXJlLmludGVsLmNvbS9zaXRlcy9kZWZhdWx0L2ZpbGVzL21h bmFnZWQvYzUvMTUvYXJjaGl0ZWN0dXJlLWluc3RydWN0aW9uLXNldC1leHRlbnNpb25zLXByb2dy YW1taW5nLXJlZmVyZW5jZS5wZGYKPiA+ICsgKzIuCj4gPiBodHRwczovLzAxLm9yZy9ibG9ncy8y MDE5L2ludHJvZHVjaW5nLWludGVsLWRhdGEtc3RyZWFtaW5nLWFjY2VsZXJhdG9yICsKPiA+ICsz Lgo+ID4gaHR0cHM6Ly9zb2Z0d2FyZS5pbnRlbC5jb20vZW4tdXMvZG93bmxvYWQvaW50ZWwtZGF0 YS1zdHJlYW1pbmctYWNjZWxlcmF0b3ItcHJlbGltaW5hcnktYXJjaGl0ZWN0dXJlLXNwZWNpZmlj YXRpb24KPiA+IC0tIDIuNy40Cj4gPiAgIAoKClRoYW5rcywKCkphY29iCl9fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmlvbW11IG1haWxpbmcgbGlzdAppb21t dUBsaXN0cy5saW51eC1mb3VuZGF0aW9uLm9yZwpodHRwczovL2xpc3RzLmxpbnV4Zm91bmRhdGlv bi5vcmcvbWFpbG1hbi9saXN0aW5mby9pb21tdQ==