From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752656AbeDJJw4 (ORCPT ); Tue, 10 Apr 2018 05:52:56 -0400 Received: from mail-lf0-f45.google.com ([209.85.215.45]:44999 "EHLO mail-lf0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752392AbeDJJwx (ORCPT ); Tue, 10 Apr 2018 05:52:53 -0400 X-Google-Smtp-Source: AIpwx4+qIf0xsRSH9Rl5gVf2mBjTwqQLel5OYKuZf/VXxIArujEmS9jjcFfnyjJ97Axh3DstySIc3A== Subject: Re: [RFC, v2, 2/9] hyper_dmabuf: architecture specification and reference guide To: Dongwon Kim , linux-kernel@vger.kernel.org, linaro-mm-sig@lists.linaro.org, xen-devel@lists.xenproject.org Cc: dri-devel@lists.freedesktop.org, mateuszx.potrola@intel.com References: <20180214015008.9513-3-dongwon.kim@intel.com> From: Oleksandr Andrushchenko Message-ID: <8d262b12-a73c-1ba1-4b08-b82b75a37b14@gmail.com> Date: Tue, 10 Apr 2018 12:52:49 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.7.0 MIME-Version: 1.0 In-Reply-To: <20180214015008.9513-3-dongwon.kim@intel.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-US Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Sorry for top-posting Can we have all this go into some header file which will not only describe the structures/commands/responses/etc, but will also allow drivers to use those directly without defining the same one more time in the code? For example, this is how it is done in Xen [1]. This way, you can keep documentation and the protocol implementation in sync easily On 02/14/2018 03:50 AM, Dongwon Kim wrote: > Reference document for hyper_DMABUF driver > > Documentation/hyper-dmabuf-sharing.txt > > Signed-off-by: Dongwon Kim > --- > Documentation/hyper-dmabuf-sharing.txt | 734 +++++++++++++++++++++++++++++++++ > 1 file changed, 734 insertions(+) > create mode 100644 Documentation/hyper-dmabuf-sharing.txt > > diff --git a/Documentation/hyper-dmabuf-sharing.txt b/Documentation/hyper-dmabuf-sharing.txt > new file mode 100644 > index 000000000000..928e411931e3 > --- /dev/null > +++ b/Documentation/hyper-dmabuf-sharing.txt > @@ -0,0 +1,734 @@ > +Linux Hyper DMABUF Driver > + > +------------------------------------------------------------------------------ > +Section 1. Overview > +------------------------------------------------------------------------------ > + > +Hyper_DMABUF driver is a Linux device driver running on multiple Virtual > +achines (VMs), which expands DMA-BUF sharing capability to the VM environment > +where multiple different OS instances need to share same physical data without > +data-copy across VMs. > + > +To share a DMA_BUF across VMs, an instance of the Hyper_DMABUF drv on the > +exporting VM (so called, “exporter”) imports a local DMA_BUF from the original > +producer of the buffer, then re-exports it with an unique ID, hyper_dmabuf_id > +for the buffer to the importing VM (so called, “importer”). > + > +Another instance of the Hyper_DMABUF driver on importer registers > +a hyper_dmabuf_id together with reference information for the shared physical > +pages associated with the DMA_BUF to its database when the export happens. > + > +The actual mapping of the DMA_BUF on the importer’s side is done by > +the Hyper_DMABUF driver when user space issues the IOCTL command to access > +the shared DMA_BUF. The Hyper_DMABUF driver works as both an importing and > +exporting driver as is, that is, no special configuration is required. > +Consequently, only a single module per VM is needed to enable cross-VM DMA_BUF > +exchange. > + > +------------------------------------------------------------------------------ > +Section 2. Architecture > +------------------------------------------------------------------------------ > + > +1. Hyper_DMABUF ID > + > +hyper_dmabuf_id is a global handle for shared DMA BUFs, which is compatible > +across VMs. It is a key used by the importer to retrieve information about > +shared Kernel pages behind the DMA_BUF structure from the IMPORT list. When > +a DMA_BUF is exported to another domain, its hyper_dmabuf_id and META data > +are also kept in the EXPORT list by the exporter for further synchronization > +of control over the DMA_BUF. > + > +hyper_dmabuf_id is “targeted”, meaning it is valid only in exporting (owner of > +the buffer) and importing VMs, where the corresponding hyper_dmabuf_id is > +stored in their database (EXPORT and IMPORT lists). > + > +A user-space application specifies the targeted VM id in the user parameter > +when it calls the IOCTL command to export shared DMA_BUF to another VM. > + > +hyper_dmabuf_id_t is a data type for hyper_dmabuf_id. It is defined as 16-byte > +data structure, and it contains id and rng_key[3] as elements for > +the structure. > + > +typedef struct { > + int id; > + int rng_key[3]; /* 12bytes long random number */ > +} hyper_dmabuf_id_t; > + > +The first element in the hyper_dmabuf_id structure, int id is combined data of > +a count number generated by the driver running on the exporter and > +the exporter’s ID. The VM’s ID is a one byte value and located at the field’s > +SB in int id. The remaining three bytes in int id are reserved for a count > +number. > + > +However, there is a limit related to this count number, which is 1000. > +Therefore, only little more than a byte starting from the LSB is actually used > +for storing this count number. > + > +#define HYPER_DMABUF_ID_CREATE(domid, id) \ > + ((((domid) & 0xFF) << 24) | ((id) & 0xFFFFFF)) > + > +This limit on the count number directly means the maximum number of DMA BUFs > +that can be shared simultaneously by one VM. The second element of > +hyper_dmabuf_id, that is int rng_key[3], is an array of three integers. These > +numbers are generated by Linux’s native random number generation mechanism. > +This field is added to enhance the security of the Hyper DMABUF driver by > +maximizing the entropy of hyper_dmabuf_id (that is, preventing it from being > +guessed by a security attacker). > + > +Once DMA_BUF is no longer shared, the hyper_dmabuf_id associated with > +the DMA_BUF is released, but the count number in hyper_dmabuf_id is saved in > +the ID list for reuse. However, random keys stored in int rng_key[3] are not > +reused. Instead, those keys are always filled with freshly generated random > +keys for security. > + > +2. IOCTLs > + > +a. IOCTL_HYPER_DMABUF_TX_CH_SETUP > + > +This type of IOCTL is used for initialization of a one-directional transmit > +communication channel with a remote domain. > + > +The user space argument for this type of IOCTL is defined as: > + > +struct ioctl_hyper_dmabuf_tx_ch_setup { > + /* IN parameters */ > + /* Remote domain id */ > + int remote_domain; > +}; > + > +b. IOCTL_HYPER_DMABUF_RX_CH_SETUP > + > +This type of IOCTL is used for initialization of a one-directional receive > +communication channel with a remote domain. > + > +The user space argument for this type of IOCTL is defined as: > + > +struct ioctl_hyper_dmabuf_rx_ch_setup { > + /* IN parameters */ > + /* Source domain id */ > + int source_domain; > +}; > + > +c. IOCTL_HYPER_DMABUF_EXPORT_REMOTE > + > +This type of IOCTL is used to export a DMA BUF to another VM. When a user > +space application makes this call to the driver, it extracts Kernel pages > +associated with the DMA_BUF, then makes those shared with the importing VM. > + > +All reference information for this shared pages and hyper_dmabuf_id is > +created, then passed to the importing domain through a communications > +channel for synchronous registration. In the meantime, the hyper_dmabuf_id > +for the shared DMA_BUF is also returned to user-space application. > + > +This IOCTL can accept a reference to “user-defined” data as well as a FD > +for the DMA BUF. This private data is then attached to the DMA BUF and > +exported together with it. > + > +More details regarding this private data can be found in chapter for > +“Hyper_DMABUF Private Data”. > + > +The user space argument for this type of IOCTL is defined as: > + > +struct ioctl_hyper_dmabuf_export_remote { > + /* IN parameters */ > + /* DMA buf fd to be exported */ > + int dmabuf_fd; > + /* Domain id to which buffer should be exported */ > + int remote_domain; > + /* exported dma buf id */ > + hyper_dmabuf_id_t hid; > + /* size of private data */ > + int sz_priv; > + /* ptr to the private data for Hyper_DMABUF */ > + char *priv; > +}; > + > +d. IOCTL_HYPER_DMABUF_EXPORT_FD > + > +The importing VM uses this IOCTL to import and re-export a shared DMA_BUF > +locally to the end-consumer using the standard Linux DMA_BUF framework. > +Upon IOCTL call, the Hyper_DMABUF driver finds the reference information > +of the shared DMA_BUF with the given hyper_dmabuf_id, then maps all shared > +pages in its own Kernel space. The driver then constructs a scatter-gather > +list with those mapped pages and creates a brand-new DMA_BUF with the list, > +which is eventually exported with a file descriptor to the local consumer. > + > +The user space argument for this type of IOCTL is defined as: > + > +struct ioctl_hyper_dmabuf_export_fd { > + /* IN parameters */ > + /* hyper dmabuf id to be imported */ > + int hyper_dmabuf_id; > + /* flags */ > + int flags; > + /* OUT parameters */ > + /* exported dma buf fd */ > + int fd; > +}; > + > +e. IOCTL_HYPER_DMABUF_UNEXPORT > + > +This type of IOCTL is used when it is necessary to terminate the current > +sharing of a DMA_BUF. When called, the driver first checks if there are any > +consumers actively using the DMA_BUF. Then, it unexports it if it is not > +mapped or used by any consumers. Otherwise, it postpones unexporting, but > +makes the buffer invalid to prevent any further import of the same DMA_BUF. > +DMA_BUF is completely unexported after the last consumer releases it. > + > +”Unexport” means removing all reference information about the DMA_BUF from the > +LISTs and make all pages private again. > + > +The user space argument for this type of IOCTL is defined as: > + > +struct ioctl_hyper_dmabuf_unexport { > + /* IN parameters */ > + /* hyper dmabuf id to be unexported */ > + int hyper_dmabuf_id; > + /* delay in ms by which unexport processing will be postponed */ > + int delay_ms; > + /* OUT parameters */ > + /* Status of request */ > + int status; > +}; > + > +f. IOCTL_HYPER_DMABUF_QUERY > + > +This IOCTL is used to retrieve specific information about a DMA_BUF that > +is being shared. > + > +The user space argument for this type of IOCTL is defined as: > + > +struct ioctl_hyper_dmabuf_query { > + /* in parameters */ > + /* hyper dmabuf id to be queried */ > + int hyper_dmabuf_id; > + /* item to be queried */ > + int item; > + /* OUT parameters */ > + /* output of query */ > + /* info can be either value or reference */ > + unsigned long info; > +}; > + > + > + > +HYPER_DMABUF_QUERY_TYPE > + - Return the type of DMA_BUF from the current domain, Exported or Imported. > + > +HYPER_DMABUF_QUERY_EXPORTER > + - Return the exporting domain’s ID of a shared DMA_BUF. > + > +HYPER_DMABUF_QUERY_IMPORTER > + - Return the importing domain’s ID of a shared DMA_BUF. > + > +HYPER_DMABUF_QUERY_SIZE > + - Return the size of a shared DMA_BUF in bytes. > + > +HYPER_DMABUF_QUERY_BUSY > + - Return ‘true’ if a shared DMA_BUF is currently used > + (mapped by the end-consumer). > + > +HYPER_DMABUF_QUERY_UNEXPORTED > + - Return ‘true’ if a shared DMA_BUF is not valid anymore > + (so it does not allow a new consumer to map it). > + > +HYPER_DMABUF_QUERY_DELAYED_UNEXPORTED > + - Return ‘true’ if a shared DMA_BUF is scheduled to be unexported > + (but is still valid) within a fixed time. > + > +HYPER_DMABUF_QUERY_PRIV_INFO > + - Return ‘private’ data attached to shared DMA_BUF to the user space. > + ‘unsigned long info’ is the user space pointer for the buffer, where > + private data will be copied to. > + > +HYPER_DMABUF_QUERY_PRIV_INFO_SIZE > + - Return the size of the private data attached to the shared DMA_BUF. > + > +3. Event Polling > + > +Event-polling can be enabled optionally by selecting the Kernel config option, > +Enable event-generation and polling operation under xen/hypervisor in Kernel’s > +menuconfig. The event-polling mechanism includes the generation of > +an import-event, adding it to the event-queue and providing a notification to > +the application so that it can retrieve the event data from the queue. > + > +For this mechanism, “Poll” and “Read” operations are added to the Hyper_DMABUF > +driver. A user application that polls the driver goes into a sleep state until > +there is a new event added to the queue. An application uses “Read” to retrieve > +event data from the event queue. Event data contains the hyper_dmabuf_id and > +the private data of the buffer that has been received by the importer. > + > +For more information on private data, refer to Section 3.5). > +Using this method, it is possible to lower the risk of the hyper_dmabuf_id and > +other sensitive information about the shared buffer (for example, meta-data > +for shared images) being leaked while being transferred to the importer because > +all of this data is shared as “private info” at the driver level. However, > +please note there should be a way for the importer to find the correct DMA_BUF > +in this case when there are multiple Hyper_DMABUFs being shared simultaneously. > +For example, the surface name or the surface ID of a specific rendering surface > +needs to be sent to the importer in advance before it is exported in a surface- > +sharing use-case. > + > +Each event data given to the user-space consists of a header and the private > +information of the buffer. The data type is defined as follows: > + > +struct hyper_dmabuf_event_hdr { > + int event_type; /* one type only for now - new import */ > + hyper_dmabuf_id_t hid; /* hyper_dmabuf_id of specific hyper_dmabuf */ > + int size; /* size of data */ > +}; > + > +struct hyper_dmabuf_event_data { > + struct hyper_dmabuf_event_hdr hdr; > + void *data; /* private data */ > +}; > + > +4. Hyper_DMABUF Private Data > + > +Each Hyper_DMABUF can come with private data, the size of which can be up to > +AX_SIZE_PRIV_DATA (currently 192 byte). This private data is just a chunk of > +plain data attached to every Hyper_DMABUF. It is guaranteed to be synchronized > +across VMs, exporter and importer. This private data does not have any specific > +structure defined at the driver level, so any “user-defined” format or > +structure can be used. In addition, there is no dedicated use-case for this > +data. It can be used virtually for any purpose. For example, it can be used to > +share meta-data such as dimension and color formats for shared images in > +a surface sharing model. Another example is when we share protected media > +contents. > + > +This private data can be used to transfer flags related to content protection > +information on streamed media to the importer. > + > +Private data is initially generated when a buffer is exported for the first > +time. Then, it is updated whenever the same buffer is re-exported. During the > +re-exporting process, the Hyper_DMABUF driver only updates private data on > +both sides with new data from user-space since the same buffer already exists > +on both the IMPORT LIST and EXPORT LIST. > + > +There are two different ways to retrieve this private data from user-space. > +The first way is to use “Read” on the Hyper_DMABUF driver. “Read” returns the > +data of events containing private data of the buffer. The second way is to > +make a query to Hyper_DMABUF. There are two query items, > +HYPER_DMABUF_QUERY_PRIV_INFO and HYPER_DMABUF_QUERY_PRIV_INFO_SIZE available > +for retrieving private data and its size. > + > +5. Scatter-Gather List Table (SGT) Management > + > +SGT management is the core part of the Hyper_DMABUF driver that manages an > +SGT, a representation of the group of kernel pages associated with a DMA_BUF. > +This block includes four different sub-blocks: > + > +a. Hyper_DMABUF_id Manager > + > +This ID manager is responsible for generating a hyper_dmabuf_id for an > +exported DMA_BUF. When an ID is requested, the ID Manager first checks if > +there are any reusable IDs left in the list and returns one of those, > +if available. Otherwise, it creates the next count number and returns it > +to the caller. > + > +b. SGT Creator > + > +The SGT (struct sg_table) contains information about the DMA_BUF such as > +references to all kernel pages for the buffer and their connections. The > +SGT Creator creates a new SGT on the importer side with pages shared by > +the hypervisor. > + > +c. Kernel Page Extractor > + > +The Page Extractor extracts pages from a given SGT before those pages > +are shared. > + > +d. List Manager Interface > + > +The SGT manger also interacts with export and import list managers. It > +sends out information (for example, hyper_dmabuf_id, reference, and > +DMA_BUF information) about the exported or imported DMA_BUFs to the > +list manager. Also, on IOCTL request, it asks the list manager to find > +and return the information for a corresponding DMA_BUF in the list. > + > +6. DMA-BUF Interface > + > +The DMA-BUF interface provides standard methods to manage DMA_BUFs > +reconstructed by the Hyper_DMABUF driver from shared pages. All of the > +relevant operations are listed in struct dma_buf_ops. These operations > +are standard DMA_BUF operations, therefore they follow standard DMA BUF > +protocols. > + > +Each DMA_BUF operation communicates with the exporter at the end of the > +routine for “indirect DMA_BUF synchronization”. > + > +7. Export/Import List Management > + > +Whenever a DMA_BUF is shared and exported, its information is added to the > +database (EXPORT-list) on the exporting VM. Similarly, information about an > +imported DMA_BUF is added to the importing database (IMPORT list) on the > +importing VM, when the export happens. > + > +All of the entries in the lists are needed to manage the exported/imported > +DMA_BUF more efficiently. Both lists are implemented as Linux hash tables. > +The key to the list is hyper_dmabuf_id and the output is the information of > +the DMA_BUF. The List Manager manages all requests from other blocks and > +transactions within lists to ensure that all entries are up-to-date and > +that the list structure is consistent. > + > +The List Manager provides basic functionality, such as: > + > +- Adding to the List > +- Removal from the List > +- Finding information about a DMA_BUF, given the hyper_dmabuf_id > + > +8. Page Sharing by Hypercalls > + > +The Hyper_DMABUF driver assumes that there is a native page-by-page memory > +sharing mechanism available on the hypervisor. Referencing a group of pages > +that are being shared is what the driver expects from “backend” APIs or the > +hypervisor itself. > + > +For the example, xen backend integrated in current code base utilizes Xen’s > +grant-table interface for sharing the underlying kernel pages (struct *page). > + > +More details about grant-table interface can be found at the following locations: > + > +https://wiki.xen.org/wiki/Grant_Table > +https://xenbits.xen.org/docs/4.6-testing/misc/grant-tables.txt > + > +9. Message Handling > + > +The exporter and importer can each create a message that consists of an opcode > +(command) and operands (parameters) and send it to each other. > + > +The message format is defined as: > + > +struct hyper_dmabuf_req { > + unsigned int req_id; /* Sequence number. Used for RING BUF > + synchronization */ > + unsigned int stat; /* Status.Response from receiver. */ > + unsigned int cmd; /* Opcode */ > + unsigned int op[MAX_NUMBER_OF_OPERANDS]; /* Operands */ > +}; > + > +The following table gives the list of opcodes: > + > + > + > +HYPER_DMABUF_EXPORT (exporter --> importer) > + - Export a DMA_BUF to the importer. The importer registers the corresponding > + DMA_BUF in its IMPORT LIST when the message is received. > + > +HYPER_DMABUF_EXPORT_FD (importer --> exporter) > + - Locally exported as FD. The importer sends out this command to the exporter > + to notify that the buffer is now locally exported (mapped and used). > + > +HYPER_DMABUF_EXPORT_FD_FAILED (importer --> exporter) > + - Failed while exporting locally. The importer sends out this command to the > + exporter to notify the exporter that the EXPORT_FD failed. > + > +HYPER_DMABUF_NOTIFY_UNEXPORT (exporter --> importer) > + - Termination of sharing. The exporter notifies the importer that the DMA_BUF > + has been unexported. > + > +HYPER_DMABUF_OPS_TO_REMOTE (importer --> exporter) > + - Not implemented yet. > + > +HYPER_DMABUF_OPS_TO_SOURCE (exporter --> importer) > + - DMA_BUF ops to the exporter, for DMA_BUF upstream synchronization. > + Note: Implemented but it is done asynchronously due to performance issues. > + > +The following table shows the list of operands for each opcode. > + > + > + > +- HYPER_DMABUF_EXPORT > + > +op0 to op3 – hyper_dmabuf_id > +op4 – number of pages to be shared > +op5 – offset of data in the first page > +op6 – length of data in the last page > +op7 – reference number for the group of shared pages > +op8 – size of private data > +op9 to (op9+op8) – private data > + > +- HYPER_DMABUF_EXPORT_FD > + > +op0 to op3 – hyper_dmabuf_id > + > +- HYPER_DMABUF_EXPORT_FD_FAILED > + > +op0 to op3 – hyper_dmabuf_id > + > +- HYPER_DMABUF_NOTIFY_UNEXPORT > + > +op0 to op3 – hyper_dmabuf_id > + > +- HYPER_DMABUF_OPS_TO_REMOTE(Not implemented) > + > +- HYPER_DMABUF_OPS_TO_SOURCE > + > +op0 to op3 – hyper_dmabuf_id > +op4 – type of DMA_BUF operation > + > +9. Inter VM (Domain) Communication > + > +Two different types of inter-domain communication channels are required, > +one in kernel space and the other in user space. The communication channel > +in user space is for transmitting or receiving the hyper_dmabuf_id. Since > +there is no specific security (for example, encryption) involved in the > +generation of a global id at the driver level, it is highly recommended that > +the customer’s user application set up a very secure channel for exchanging > +hyper_dmabuf_id between VMs. > + > +The communication channel in kernel space is required for exchanging messages > +from “message management” block between two VMs. In the current reference > +backend for Xen hypervisor, Xen ring-buffer and event-channel mechanisms are > +used for message exchange between impoter and exporter. > + > +10. What are required in hypervisor > + > +emory sharing and message communication between VMs > + > +------------------------------------------------------------------------------ > +Section 3. Hyper DMABUF Sharing Flow > +------------------------------------------------------------------------------ > + > +1. Exporting > + > +To export a DMA_BUF to another VM, user space has to call an IOCTL > +(IOCTL_HYPER_DMABUF_EXPORT_REMOTE) with a file descriptor for the buffer given > +by the original exporter. The Hyper_DMABUF driver maps a DMA_BUF locally, then > +issues a hyper_dmabuf_id and SGT for the DMA_BUF, which is registered to the > +EXPORT list. Then, all pages for the SGT are extracted and each individual > +page is shared via a hypervisor-specific memory sharing mechanism > +(for example, in Xen this is grant-table). > + > +One important requirement on this memory sharing method is that it needs to > +create a single integer value that represents the list of pages, which can > +then be used by the importer for retrieving the group of shared pages. For > +this, the “Backend” in the reference driver utilizes the multiple level > +addressing mechanism. > + > +Once the integer reference to the list of pages is created, the exporter > +builds the “export” command and sends it to the importer, then notifies the > +importer. > + > +2. Importing > + > +The Import process is divided into two sections. One is the registration > +of DMA_BUF from the exporter. The other is the actual mapping of the buffer > +before accessing the data in the buffer. The former (termed “Registration”) > +happens on an export event (that is, the export command with an interrupt) > +in the exporter. > + > +The latter (termed “Mapping”) is done asynchronously when the driver gets the > +IOCTL call from user space. When the importer gets an interrupt from the > +exporter, it checks the command in the receiving queue and if it is an > +“export” command, the registration process is started. It first finds > +hyper_dmabuf_id and the integer reference for the shared pages, then stores > +all of that information together with the “domain id” of the exporting domain > +in the IMPORT LIST. > + > +In the case where “event-polling” is enabled (Kernel Config - Enable event- > +generation and polling operation), a “new sharing available” event is > +generated right after the reference info for the new shared DMA_BUF is > +registered to the IMPORT LIST. This event is added to the event-queue. > + > +The user process that polls Hyper_DMABUF driver wakes up when this event-queue > +is not empty and is able to read back event data from the queue using the > +driver’s “Read” function. Once the user-application calls EXPORT_FD IOCTL with > +the proper parameters including hyper_dmabuf_id, the Hyper_DMABUF driver > +retrieves information about the matched DMA_BUF from the IMPORT LIST. Then, it > +maps all pages shared (referenced by the integer reference) in its kernel > +space and creates its own DMA_BUF referencing the same shared pages. After > +this, it exports this new DMA_BUF to the other drivers with a file descriptor. > +DMA_BUF can then be used just in the same way a local DMA_BUF is. > + > +3. Indirect Synchronization of DMA_BUF > + > +Synchronization of a DMA_BUF within a single OS is automatically achieved > +because all of importer’s DMA_BUF operations are done using functions defined > +on the exporter’s side, which means there is one central place that has full > +control over the DMA_BUF. In other words, any primary activities such as > +attaching/detaching and mapping/un-mapping are all captured by the exporter, > +meaning that the exporter knows basic information such as who is using the > +DMA_BUF and how it is being used. This, however, is not applicable if this > +sharing is done beyond a single OS because kernel space (where the exporter’s > +DMA_BUF operations reside) is simply not visible to the importing VM. > + > +Therefore, “indirect synchronization” was introduced as an alternative solution, > +which is now implemented in the Hyper_DMABUF driver. This technique makes > +the exporter create a shadow DMA_BUF when the end-consumer of the buffer maps > +the DMA_BUF, then duplicates any DMA_BUF operations performed on > +the importer’s side. Through this “indirect synchronization”, the exporter is > +able to virtually track all activities done by the consumer (mostly reference > +counter) as if those are done in exporter’s local system. > + > +------------------------------------------------------------------------------ > +Section 4. Hypervisor Backend Interface > +------------------------------------------------------------------------------ > + > +The Hyper_DMABUF driver has a standard “Backend” structure that contains > +mappings to various functions designed for a specific Hypervisor. Most of > +these API functions should provide a low-level implementation of communication > +and memory sharing capability that utilize a Hypervisor’s native mechanisms. > + > +struct hyper_dmabuf_backend_ops { > + /* retreiving id of current virtual machine */ > + int (*get_vm_id)(void); > + /* get pages shared via hypervisor-specific method */ > + int (*share_pages)(struct page **, int, int, void **); > + /* make shared pages unshared via hypervisor specific method */ > + int (*unshare_pages)(void **, int); > + /* map remotely shared pages on importer's side via > + * hypervisor-specific method > + */ > + struct page ** (*map_shared_pages)(int, int, int, void **); > + /* unmap and free shared pages on importer's side via > + * hypervisor-specific method > + */ > + int (*unmap_shared_pages)(void **, int); > + /* initialize communication environment */ > + int (*init_comm_env)(void); > + /* destroy communication channel */ > + void (*destroy_comm)(void); > + /* upstream ch setup (receiving and responding) */ > + int (*init_rx_ch)(int); > + /* downstream ch setup (transmitting and parsing responses) */ > + int (*init_tx_ch)(int); > + /* send msg via communication ch */ > + int (*send_req)(int, struct hyper_dmabuf_req *, int); > +}; > + > + > + > +1. get_vm_id > + > + Returns the VM (domain) ID > + > + Input: > + > + -ID of the current domain > + > + Output: > + > + None > + > +2. share_pages > + > + Get pages shared via hypervisor-specific method and return one reference > + ID that represents the complete list of shared pages > + > + Input: > + > + -Array of pages > + -ID of importing VM > + -Number of pages > + -Hypervisor specific Representation of reference info of shared > + pages > + > + Output: > + > + -Hypervisor specific integer value that represents all of > + the shared pages > + > +3. unshare_pages > + > + Stop sharing pages > + > + Input: > + > + -Hypervisor specific Representation of reference info of shared > + pages > + -Number of shared pages > + > + Output: > + > + 0 > + > +4. map_shared_pages > + > + Map shared pages locally using a hypervisor-specific method > + > + Input: > + > + -Reference number that represents all of shared pages > + -ID of exporting VM, Number of pages > + -Reference information for any purpose > + > + Output: > + > + -An array of shared pages (struct page**) > + > +5. unmap_shared_pages > + > + Unmap shared pages > + > + Input: > + > + -Hypervisor specific Representation of reference info of shared pages > + > + Output: > + > + -0 (successful) or one of Standard Kernel errors > + > +6. init_comm_env > + > + Setup infrastructure needed for communication channel > + > + Input: > + > + None > + > + Output: > + > + None > + > +7. destroy_comm > + > + Cleanup everything done via init_comm_env > + > + Input: > + > + None > + > + Output: > + > + None > + > +8. init_rx_ch > + > + Configure receive channel > + > + Input: > + > + -ID of VM on the other side of the channel > + > + Output: > + > + -0 (successful) or one of Standard Kernel errors > + > +9. init_tx_ch > + > + Configure transmit channel > + > + Input: > + > + -ID of VM on the other side of the channel > + > + Output: > + > + -0 (success) or one of Standard Kernel errors > + > +10. send_req > + > + Send message to other VM > + > + Input: > + > + -ID of VM that receives the message > + -Message > + > + Output: > + > + -0 (success) or one of Standard Kernel errors > + > +------------------------------------------------------------------------------- > +------------------------------------------------------------------------------- > [1] https://elixir.bootlin.com/linux/v4.16.1/source/include/xen/interface/io/kbdif.h From mboxrd@z Thu Jan 1 00:00:00 1970 From: Oleksandr Andrushchenko Subject: Re: [RFC, v2, 2/9] hyper_dmabuf: architecture specification and reference guide Date: Tue, 10 Apr 2018 12:52:49 +0300 Message-ID: <8d262b12-a73c-1ba1-4b08-b82b75a37b14@gmail.com> References: <20180214015008.9513-3-dongwon.kim@intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8"; Format="flowed" Content-Transfer-Encoding: base64 Return-path: Received: from mail-lf0-x234.google.com (mail-lf0-x234.google.com [IPv6:2a00:1450:4010:c07::234]) by gabe.freedesktop.org (Postfix) with ESMTPS id E84776E3B9 for ; Tue, 10 Apr 2018 09:52:53 +0000 (UTC) Received: by mail-lf0-x234.google.com with SMTP id v207-v6so10762084lfa.10 for ; Tue, 10 Apr 2018 02:52:53 -0700 (PDT) In-Reply-To: <20180214015008.9513-3-dongwon.kim@intel.com> Content-Language: en-US List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: Dongwon Kim , linux-kernel@vger.kernel.org, linaro-mm-sig@lists.linaro.org, xen-devel@lists.xenproject.org Cc: mateuszx.potrola@intel.com, dri-devel@lists.freedesktop.org List-Id: dri-devel@lists.freedesktop.org U29ycnkgZm9yIHRvcC1wb3N0aW5nCgpDYW4gd2UgaGF2ZSBhbGwgdGhpcyBnbyBpbnRvIHNvbWUg aGVhZGVyIGZpbGUgd2hpY2gKCndpbGwgbm90IG9ubHkgZGVzY3JpYmUgdGhlIHN0cnVjdHVyZXMv Y29tbWFuZHMvcmVzcG9uc2VzL2V0YywKCmJ1dCB3aWxsIGFsc28gYWxsb3cgZHJpdmVycyB0byB1 c2UgdGhvc2UgZGlyZWN0bHkgd2l0aG91dAoKZGVmaW5pbmcgdGhlIHNhbWUgb25lIG1vcmUgdGlt ZSBpbiB0aGUgY29kZT8gRm9yIGV4YW1wbGUsCgp0aGlzIGlzIGhvdyBpdCBpcyBkb25lIGluIFhl biBbMV0uIFRoaXMgd2F5LCB5b3UgY2FuIGtlZXAKCmRvY3VtZW50YXRpb24gYW5kIHRoZSBwcm90 b2NvbCBpbXBsZW1lbnRhdGlvbiBpbiBzeW5jIGVhc2lseQoKCk9uIDAyLzE0LzIwMTggMDM6NTAg QU0sIERvbmd3b24gS2ltIHdyb3RlOgo+IFJlZmVyZW5jZSBkb2N1bWVudCBmb3IgaHlwZXJfRE1B QlVGIGRyaXZlcgo+Cj4gRG9jdW1lbnRhdGlvbi9oeXBlci1kbWFidWYtc2hhcmluZy50eHQKPgo+ IFNpZ25lZC1vZmYtYnk6IERvbmd3b24gS2ltIDxkb25nd29uLmtpbUBpbnRlbC5jb20+Cj4gLS0t Cj4gICBEb2N1bWVudGF0aW9uL2h5cGVyLWRtYWJ1Zi1zaGFyaW5nLnR4dCB8IDczNCArKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysKPiAgIDEgZmlsZSBjaGFuZ2VkLCA3MzQgaW5zZXJ0 aW9ucygrKQo+ICAgY3JlYXRlIG1vZGUgMTAwNjQ0IERvY3VtZW50YXRpb24vaHlwZXItZG1hYnVm LXNoYXJpbmcudHh0Cj4KPiBkaWZmIC0tZ2l0IGEvRG9jdW1lbnRhdGlvbi9oeXBlci1kbWFidWYt c2hhcmluZy50eHQgYi9Eb2N1bWVudGF0aW9uL2h5cGVyLWRtYWJ1Zi1zaGFyaW5nLnR4dAo+IG5l dyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMDAwMDAwLi45MjhlNDExOTMxZTMKPiAt LS0gL2Rldi9udWxsCj4gKysrIGIvRG9jdW1lbnRhdGlvbi9oeXBlci1kbWFidWYtc2hhcmluZy50 eHQKPiBAQCAtMCwwICsxLDczNCBAQAo+ICtMaW51eCBIeXBlciBETUFCVUYgRHJpdmVyCj4gKwo+ ICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KPiArU2VjdGlvbiAxLiBPdmVydmlldwo+ICstLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0KPiArCj4gK0h5cGVyX0RNQUJVRiBkcml2ZXIgaXMgYSBMaW51eCBkZXZp Y2UgZHJpdmVyIHJ1bm5pbmcgb24gbXVsdGlwbGUgVmlydHVhbAo+ICthY2hpbmVzIChWTXMpLCB3 aGljaCBleHBhbmRzIERNQS1CVUYgc2hhcmluZyBjYXBhYmlsaXR5IHRvIHRoZSBWTSBlbnZpcm9u bWVudAo+ICt3aGVyZSBtdWx0aXBsZSBkaWZmZXJlbnQgT1MgaW5zdGFuY2VzIG5lZWQgdG8gc2hh cmUgc2FtZSBwaHlzaWNhbCBkYXRhIHdpdGhvdXQKPiArZGF0YS1jb3B5IGFjcm9zcyBWTXMuCj4g Kwo+ICtUbyBzaGFyZSBhIERNQV9CVUYgYWNyb3NzIFZNcywgYW4gaW5zdGFuY2Ugb2YgdGhlIEh5 cGVyX0RNQUJVRiBkcnYgb24gdGhlCj4gK2V4cG9ydGluZyBWTSAoc28gY2FsbGVkLCDigJxleHBv cnRlcuKAnSkgaW1wb3J0cyBhIGxvY2FsIERNQV9CVUYgZnJvbSB0aGUgb3JpZ2luYWwKPiArcHJv ZHVjZXIgb2YgdGhlIGJ1ZmZlciwgdGhlbiByZS1leHBvcnRzIGl0IHdpdGggYW4gdW5pcXVlIElE LCBoeXBlcl9kbWFidWZfaWQKPiArZm9yIHRoZSBidWZmZXIgdG8gdGhlIGltcG9ydGluZyBWTSAo c28gY2FsbGVkLCDigJxpbXBvcnRlcuKAnSkuCj4gKwo+ICtBbm90aGVyIGluc3RhbmNlIG9mIHRo ZSBIeXBlcl9ETUFCVUYgZHJpdmVyIG9uIGltcG9ydGVyIHJlZ2lzdGVycwo+ICthIGh5cGVyX2Rt YWJ1Zl9pZCB0b2dldGhlciB3aXRoIHJlZmVyZW5jZSBpbmZvcm1hdGlvbiBmb3IgdGhlIHNoYXJl ZCBwaHlzaWNhbAo+ICtwYWdlcyBhc3NvY2lhdGVkIHdpdGggdGhlIERNQV9CVUYgdG8gaXRzIGRh dGFiYXNlIHdoZW4gdGhlIGV4cG9ydCBoYXBwZW5zLgo+ICsKPiArVGhlIGFjdHVhbCBtYXBwaW5n IG9mIHRoZSBETUFfQlVGIG9uIHRoZSBpbXBvcnRlcuKAmXMgc2lkZSBpcyBkb25lIGJ5Cj4gK3Ro ZSBIeXBlcl9ETUFCVUYgZHJpdmVyIHdoZW4gdXNlciBzcGFjZSBpc3N1ZXMgdGhlIElPQ1RMIGNv bW1hbmQgdG8gYWNjZXNzCj4gK3RoZSBzaGFyZWQgRE1BX0JVRi4gVGhlIEh5cGVyX0RNQUJVRiBk cml2ZXIgd29ya3MgYXMgYm90aCBhbiBpbXBvcnRpbmcgYW5kCj4gK2V4cG9ydGluZyBkcml2ZXIg YXMgaXMsIHRoYXQgaXMsIG5vIHNwZWNpYWwgY29uZmlndXJhdGlvbiBpcyByZXF1aXJlZC4KPiAr Q29uc2VxdWVudGx5LCBvbmx5IGEgc2luZ2xlIG1vZHVsZSBwZXIgVk0gaXMgbmVlZGVkIHRvIGVu YWJsZSBjcm9zcy1WTSBETUFfQlVGCj4gK2V4Y2hhbmdlLgo+ICsKPiArLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tCj4gK1NlY3Rpb24gMi4gQXJjaGl0ZWN0dXJlCj4gKy0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LQo+ICsKPiArMS4gSHlwZXJfRE1BQlVGIElECj4gKwo+ICtoeXBlcl9kbWFidWZfaWQgaXMgYSBn bG9iYWwgaGFuZGxlIGZvciBzaGFyZWQgRE1BIEJVRnMsIHdoaWNoIGlzIGNvbXBhdGlibGUKPiAr YWNyb3NzIFZNcy4gSXQgaXMgYSBrZXkgdXNlZCBieSB0aGUgaW1wb3J0ZXIgdG8gcmV0cmlldmUg aW5mb3JtYXRpb24gYWJvdXQKPiArc2hhcmVkIEtlcm5lbCBwYWdlcyBiZWhpbmQgdGhlIERNQV9C VUYgc3RydWN0dXJlIGZyb20gdGhlIElNUE9SVCBsaXN0LiBXaGVuCj4gK2EgRE1BX0JVRiBpcyBl eHBvcnRlZCB0byBhbm90aGVyIGRvbWFpbiwgaXRzIGh5cGVyX2RtYWJ1Zl9pZCBhbmQgTUVUQSBk YXRhCj4gK2FyZSBhbHNvIGtlcHQgaW4gdGhlIEVYUE9SVCBsaXN0IGJ5IHRoZSBleHBvcnRlciBm b3IgZnVydGhlciBzeW5jaHJvbml6YXRpb24KPiArb2YgY29udHJvbCBvdmVyIHRoZSBETUFfQlVG Lgo+ICsKPiAraHlwZXJfZG1hYnVmX2lkIGlzIOKAnHRhcmdldGVk4oCdLCBtZWFuaW5nIGl0IGlz IHZhbGlkIG9ubHkgaW4gZXhwb3J0aW5nIChvd25lciBvZgo+ICt0aGUgYnVmZmVyKSBhbmQgaW1w b3J0aW5nIFZNcywgd2hlcmUgdGhlIGNvcnJlc3BvbmRpbmcgaHlwZXJfZG1hYnVmX2lkIGlzCj4g K3N0b3JlZCBpbiB0aGVpciBkYXRhYmFzZSAoRVhQT1JUIGFuZCBJTVBPUlQgbGlzdHMpLgo+ICsK PiArQSB1c2VyLXNwYWNlIGFwcGxpY2F0aW9uIHNwZWNpZmllcyB0aGUgdGFyZ2V0ZWQgVk0gaWQg aW4gdGhlIHVzZXIgcGFyYW1ldGVyCj4gK3doZW4gaXQgY2FsbHMgdGhlIElPQ1RMIGNvbW1hbmQg dG8gZXhwb3J0IHNoYXJlZCBETUFfQlVGIHRvIGFub3RoZXIgVk0uCj4gKwo+ICtoeXBlcl9kbWFi dWZfaWRfdCBpcyBhIGRhdGEgdHlwZSBmb3IgaHlwZXJfZG1hYnVmX2lkLiBJdCBpcyBkZWZpbmVk IGFzIDE2LWJ5dGUKPiArZGF0YSBzdHJ1Y3R1cmUsIGFuZCBpdCBjb250YWlucyBpZCBhbmQgcm5n X2tleVszXSBhcyBlbGVtZW50cyBmb3IKPiArdGhlIHN0cnVjdHVyZS4KPiArCj4gK3R5cGVkZWYg c3RydWN0IHsKPiArICAgICAgICBpbnQgaWQ7Cj4gKyAgICAgICAgaW50IHJuZ19rZXlbM107IC8q IDEyYnl0ZXMgbG9uZyByYW5kb20gbnVtYmVyICovCj4gK30gaHlwZXJfZG1hYnVmX2lkX3Q7Cj4g Kwo+ICtUaGUgZmlyc3QgZWxlbWVudCBpbiB0aGUgaHlwZXJfZG1hYnVmX2lkIHN0cnVjdHVyZSwg aW50IGlkIGlzIGNvbWJpbmVkIGRhdGEgb2YKPiArYSBjb3VudCBudW1iZXIgZ2VuZXJhdGVkIGJ5 IHRoZSBkcml2ZXIgcnVubmluZyBvbiB0aGUgZXhwb3J0ZXIgYW5kCj4gK3RoZSBleHBvcnRlcuKA mXMgSUQuIFRoZSBWTeKAmXMgSUQgaXMgYSBvbmUgYnl0ZSB2YWx1ZSBhbmQgbG9jYXRlZCBhdCB0 aGUgZmllbGTigJlzCj4gK1NCIGluIGludCBpZC4gVGhlIHJlbWFpbmluZyB0aHJlZSBieXRlcyBp biBpbnQgaWQgYXJlIHJlc2VydmVkIGZvciBhIGNvdW50Cj4gK251bWJlci4KPiArCj4gK0hvd2V2 ZXIsIHRoZXJlIGlzIGEgbGltaXQgcmVsYXRlZCB0byB0aGlzIGNvdW50IG51bWJlciwgd2hpY2gg aXMgMTAwMC4KPiArVGhlcmVmb3JlLCBvbmx5IGxpdHRsZSBtb3JlIHRoYW4gYSBieXRlIHN0YXJ0 aW5nIGZyb20gdGhlIExTQiBpcyBhY3R1YWxseSB1c2VkCj4gK2ZvciBzdG9yaW5nIHRoaXMgY291 bnQgbnVtYmVyLgo+ICsKPiArI2RlZmluZSBIWVBFUl9ETUFCVUZfSURfQ1JFQVRFKGRvbWlkLCBp ZCkgXAo+ICsgICAgICAgICgoKChkb21pZCkgJiAweEZGKSA8PCAyNCkgfCAoKGlkKSAmIDB4RkZG RkZGKSkKPiArCj4gK1RoaXMgbGltaXQgb24gdGhlIGNvdW50IG51bWJlciBkaXJlY3RseSBtZWFu cyB0aGUgbWF4aW11bSBudW1iZXIgb2YgRE1BIEJVRnMKPiArdGhhdCAgY2FuIGJlIHNoYXJlZCBz aW11bHRhbmVvdXNseSBieSBvbmUgVk0uIFRoZSBzZWNvbmQgZWxlbWVudCBvZgo+ICtoeXBlcl9k bWFidWZfaWQsIHRoYXQgaXMgaW50IHJuZ19rZXlbM10sIGlzIGFuIGFycmF5IG9mIHRocmVlIGlu dGVnZXJzLiBUaGVzZQo+ICtudW1iZXJzIGFyZSBnZW5lcmF0ZWQgYnkgTGludXjigJlzIG5hdGl2 ZSByYW5kb20gbnVtYmVyIGdlbmVyYXRpb24gbWVjaGFuaXNtLgo+ICtUaGlzIGZpZWxkIGlzIGFk ZGVkIHRvIGVuaGFuY2UgdGhlIHNlY3VyaXR5IG9mIHRoZSBIeXBlciBETUFCVUYgZHJpdmVyIGJ5 Cj4gK21heGltaXppbmcgdGhlIGVudHJvcHkgb2YgaHlwZXJfZG1hYnVmX2lkICh0aGF0IGlzLCBw cmV2ZW50aW5nIGl0IGZyb20gYmVpbmcKPiArZ3Vlc3NlZCBieSBhIHNlY3VyaXR5IGF0dGFja2Vy KS4KPiArCj4gK09uY2UgRE1BX0JVRiBpcyBubyBsb25nZXIgc2hhcmVkLCB0aGUgaHlwZXJfZG1h YnVmX2lkIGFzc29jaWF0ZWQgd2l0aAo+ICt0aGUgRE1BX0JVRiBpcyByZWxlYXNlZCwgYnV0IHRo ZSBjb3VudCBudW1iZXIgaW4gaHlwZXJfZG1hYnVmX2lkIGlzIHNhdmVkIGluCj4gK3RoZSBJRCBs aXN0IGZvciByZXVzZS4gSG93ZXZlciwgcmFuZG9tIGtleXMgc3RvcmVkIGluIGludCBybmdfa2V5 WzNdIGFyZSBub3QKPiArcmV1c2VkLiBJbnN0ZWFkLCB0aG9zZSBrZXlzIGFyZSBhbHdheXMgZmls bGVkIHdpdGggZnJlc2hseSBnZW5lcmF0ZWQgcmFuZG9tCj4gK2tleXMgZm9yIHNlY3VyaXR5Lgo+ ICsKPiArMi4gSU9DVExzCj4gKwo+ICthLiBJT0NUTF9IWVBFUl9ETUFCVUZfVFhfQ0hfU0VUVVAK PiArCj4gK1RoaXMgdHlwZSBvZiBJT0NUTCBpcyB1c2VkIGZvciBpbml0aWFsaXphdGlvbiBvZiBh IG9uZS1kaXJlY3Rpb25hbCB0cmFuc21pdAo+ICtjb21tdW5pY2F0aW9uIGNoYW5uZWwgd2l0aCBh IHJlbW90ZSBkb21haW4uCj4gKwo+ICtUaGUgdXNlciBzcGFjZSBhcmd1bWVudCBmb3IgdGhpcyB0 eXBlIG9mIElPQ1RMIGlzIGRlZmluZWQgYXM6Cj4gKwo+ICtzdHJ1Y3QgaW9jdGxfaHlwZXJfZG1h YnVmX3R4X2NoX3NldHVwIHsKPiArICAgIC8qIElOIHBhcmFtZXRlcnMgKi8KPiArICAgIC8qIFJl bW90ZSBkb21haW4gaWQgKi8KPiArICAgIGludCByZW1vdGVfZG9tYWluOwo+ICt9Owo+ICsKPiAr Yi4gSU9DVExfSFlQRVJfRE1BQlVGX1JYX0NIX1NFVFVQCj4gKwo+ICtUaGlzIHR5cGUgb2YgSU9D VEwgaXMgdXNlZCBmb3IgaW5pdGlhbGl6YXRpb24gb2YgYSBvbmUtZGlyZWN0aW9uYWwgcmVjZWl2 ZQo+ICtjb21tdW5pY2F0aW9uIGNoYW5uZWwgd2l0aCBhIHJlbW90ZSBkb21haW4uCj4gKwo+ICtU aGUgdXNlciBzcGFjZSBhcmd1bWVudCBmb3IgdGhpcyB0eXBlIG9mIElPQ1RMIGlzIGRlZmluZWQg YXM6Cj4gKwo+ICtzdHJ1Y3QgaW9jdGxfaHlwZXJfZG1hYnVmX3J4X2NoX3NldHVwIHsKPiArICAg IC8qIElOIHBhcmFtZXRlcnMgKi8KPiArICAgIC8qIFNvdXJjZSBkb21haW4gaWQgKi8KPiArICAg IGludCBzb3VyY2VfZG9tYWluOwo+ICt9Owo+ICsKPiArYy4gSU9DVExfSFlQRVJfRE1BQlVGX0VY UE9SVF9SRU1PVEUKPiArCj4gK1RoaXMgdHlwZSBvZiBJT0NUTCBpcyB1c2VkIHRvIGV4cG9ydCBh IERNQSBCVUYgdG8gYW5vdGhlciBWTS4gV2hlbiBhIHVzZXIKPiArc3BhY2UgYXBwbGljYXRpb24g bWFrZXMgdGhpcyBjYWxsIHRvIHRoZSBkcml2ZXIsIGl0IGV4dHJhY3RzIEtlcm5lbCBwYWdlcwo+ ICthc3NvY2lhdGVkIHdpdGggdGhlIERNQV9CVUYsIHRoZW4gbWFrZXMgdGhvc2Ugc2hhcmVkIHdp dGggdGhlIGltcG9ydGluZyBWTS4KPiArCj4gK0FsbCByZWZlcmVuY2UgaW5mb3JtYXRpb24gZm9y IHRoaXMgc2hhcmVkIHBhZ2VzIGFuZCBoeXBlcl9kbWFidWZfaWQgaXMKPiArY3JlYXRlZCwgdGhl biBwYXNzZWQgdG8gdGhlIGltcG9ydGluZyBkb21haW4gdGhyb3VnaCBhIGNvbW11bmljYXRpb25z Cj4gK2NoYW5uZWwgZm9yIHN5bmNocm9ub3VzIHJlZ2lzdHJhdGlvbi4gSW4gdGhlIG1lYW50aW1l LCB0aGUgaHlwZXJfZG1hYnVmX2lkCj4gK2ZvciB0aGUgc2hhcmVkIERNQV9CVUYgaXMgYWxzbyBy ZXR1cm5lZCB0byB1c2VyLXNwYWNlIGFwcGxpY2F0aW9uLgo+ICsKPiArVGhpcyBJT0NUTCBjYW4g YWNjZXB0IGEgcmVmZXJlbmNlIHRvIOKAnHVzZXItZGVmaW5lZOKAnSBkYXRhIGFzIHdlbGwgYXMg YSBGRAo+ICtmb3IgdGhlIERNQSBCVUYuIFRoaXMgcHJpdmF0ZSBkYXRhIGlzIHRoZW4gYXR0YWNo ZWQgdG8gdGhlIERNQSBCVUYgYW5kCj4gK2V4cG9ydGVkIHRvZ2V0aGVyIHdpdGggaXQuCj4gKwo+ ICtNb3JlIGRldGFpbHMgcmVnYXJkaW5nIHRoaXMgcHJpdmF0ZSBkYXRhIGNhbiBiZSBmb3VuZCBp biBjaGFwdGVyIGZvcgo+ICvigJxIeXBlcl9ETUFCVUYgUHJpdmF0ZSBEYXRh4oCdLgo+ICsKPiAr VGhlIHVzZXIgc3BhY2UgYXJndW1lbnQgZm9yIHRoaXMgdHlwZSBvZiBJT0NUTCBpcyBkZWZpbmVk IGFzOgo+ICsKPiArc3RydWN0IGlvY3RsX2h5cGVyX2RtYWJ1Zl9leHBvcnRfcmVtb3RlIHsKPiAr ICAgIC8qIElOIHBhcmFtZXRlcnMgKi8KPiArICAgIC8qIERNQSBidWYgZmQgdG8gYmUgZXhwb3J0 ZWQgKi8KPiArICAgIGludCBkbWFidWZfZmQ7Cj4gKyAgICAvKiBEb21haW4gaWQgdG8gd2hpY2gg YnVmZmVyIHNob3VsZCBiZSBleHBvcnRlZCAqLwo+ICsgICAgaW50IHJlbW90ZV9kb21haW47Cj4g KyAgICAvKiBleHBvcnRlZCBkbWEgYnVmIGlkICovCj4gKyAgICBoeXBlcl9kbWFidWZfaWRfdCBo aWQ7Cj4gKyAgICAvKiBzaXplIG9mIHByaXZhdGUgZGF0YSAqLwo+ICsgICAgaW50IHN6X3ByaXY7 Cj4gKyAgICAvKiBwdHIgdG8gdGhlIHByaXZhdGUgZGF0YSBmb3IgSHlwZXJfRE1BQlVGICovCj4g KyAgICBjaGFyICpwcml2Owo+ICt9Owo+ICsKPiArZC4gSU9DVExfSFlQRVJfRE1BQlVGX0VYUE9S VF9GRAo+ICsKPiArVGhlIGltcG9ydGluZyBWTSB1c2VzIHRoaXMgSU9DVEwgdG8gaW1wb3J0IGFu ZCByZS1leHBvcnQgYSBzaGFyZWQgRE1BX0JVRgo+ICtsb2NhbGx5IHRvIHRoZSBlbmQtY29uc3Vt ZXIgdXNpbmcgdGhlIHN0YW5kYXJkIExpbnV4IERNQV9CVUYgZnJhbWV3b3JrLgo+ICtVcG9uIElP Q1RMIGNhbGwsIHRoZSBIeXBlcl9ETUFCVUYgZHJpdmVyIGZpbmRzIHRoZSByZWZlcmVuY2UgaW5m b3JtYXRpb24KPiArb2YgdGhlIHNoYXJlZCBETUFfQlVGIHdpdGggdGhlIGdpdmVuIGh5cGVyX2Rt YWJ1Zl9pZCwgdGhlbiBtYXBzIGFsbCBzaGFyZWQKPiArcGFnZXMgaW4gaXRzIG93biBLZXJuZWwg c3BhY2UuIFRoZSBkcml2ZXIgdGhlbiBjb25zdHJ1Y3RzIGEgc2NhdHRlci1nYXRoZXIKPiArbGlz dCB3aXRoIHRob3NlIG1hcHBlZCBwYWdlcyBhbmQgY3JlYXRlcyBhIGJyYW5kLW5ldyBETUFfQlVG IHdpdGggdGhlIGxpc3QsCj4gK3doaWNoIGlzIGV2ZW50dWFsbHkgZXhwb3J0ZWQgd2l0aCBhIGZp bGUgZGVzY3JpcHRvciB0byB0aGUgbG9jYWwgY29uc3VtZXIuCj4gKwo+ICtUaGUgdXNlciBzcGFj ZSBhcmd1bWVudCBmb3IgdGhpcyB0eXBlIG9mIElPQ1RMIGlzIGRlZmluZWQgYXM6Cj4gKwo+ICtz dHJ1Y3QgaW9jdGxfaHlwZXJfZG1hYnVmX2V4cG9ydF9mZCB7Cj4gKyAgICAvKiBJTiBwYXJhbWV0 ZXJzICovCj4gKyAgICAvKiBoeXBlciBkbWFidWYgaWQgdG8gYmUgaW1wb3J0ZWQgKi8KPiArICAg IGludCBoeXBlcl9kbWFidWZfaWQ7Cj4gKyAgICAvKiBmbGFncyAqLwo+ICsgICAgaW50IGZsYWdz Owo+ICsgICAgLyogT1VUIHBhcmFtZXRlcnMgKi8KPiArICAgIC8qIGV4cG9ydGVkIGRtYSBidWYg ZmQgKi8KPiArICAgIGludCBmZDsKPiArfTsKPiArCj4gK2UuIElPQ1RMX0hZUEVSX0RNQUJVRl9V TkVYUE9SVAo+ICsKPiArVGhpcyB0eXBlIG9mIElPQ1RMIGlzIHVzZWQgd2hlbiBpdCBpcyBuZWNl c3NhcnkgdG8gdGVybWluYXRlIHRoZSBjdXJyZW50Cj4gK3NoYXJpbmcgb2YgYSBETUFfQlVGLiBX aGVuIGNhbGxlZCwgdGhlIGRyaXZlciBmaXJzdCBjaGVja3MgaWYgdGhlcmUgYXJlIGFueQo+ICtj b25zdW1lcnMgYWN0aXZlbHkgdXNpbmcgdGhlIERNQV9CVUYuIFRoZW4sIGl0IHVuZXhwb3J0cyBp dCBpZiBpdCBpcyBub3QKPiArbWFwcGVkIG9yIHVzZWQgYnkgYW55IGNvbnN1bWVycy4gT3RoZXJ3 aXNlLCBpdCBwb3N0cG9uZXMgdW5leHBvcnRpbmcsIGJ1dAo+ICttYWtlcyB0aGUgYnVmZmVyIGlu dmFsaWQgdG8gcHJldmVudCBhbnkgZnVydGhlciBpbXBvcnQgb2YgdGhlIHNhbWUgRE1BX0JVRi4K PiArRE1BX0JVRiBpcyBjb21wbGV0ZWx5IHVuZXhwb3J0ZWQgYWZ0ZXIgdGhlIGxhc3QgY29uc3Vt ZXIgcmVsZWFzZXMgaXQuCj4gKwo+ICvigJ1VbmV4cG9ydOKAnSBtZWFucyByZW1vdmluZyBhbGwg cmVmZXJlbmNlIGluZm9ybWF0aW9uIGFib3V0IHRoZSBETUFfQlVGIGZyb20gdGhlCj4gK0xJU1Rz IGFuZCBtYWtlIGFsbCBwYWdlcyBwcml2YXRlIGFnYWluLgo+ICsKPiArVGhlIHVzZXIgc3BhY2Ug YXJndW1lbnQgZm9yIHRoaXMgdHlwZSBvZiBJT0NUTCBpcyBkZWZpbmVkIGFzOgo+ICsKPiArc3Ry dWN0IGlvY3RsX2h5cGVyX2RtYWJ1Zl91bmV4cG9ydCB7Cj4gKyAgICAvKiBJTiBwYXJhbWV0ZXJz ICovCj4gKyAgICAvKiBoeXBlciBkbWFidWYgaWQgdG8gYmUgdW5leHBvcnRlZCAqLwo+ICsgICAg aW50IGh5cGVyX2RtYWJ1Zl9pZDsKPiArICAgIC8qIGRlbGF5IGluIG1zIGJ5IHdoaWNoIHVuZXhw b3J0IHByb2Nlc3Npbmcgd2lsbCBiZSBwb3N0cG9uZWQgKi8KPiArICAgIGludCBkZWxheV9tczsK PiArICAgIC8qIE9VVCBwYXJhbWV0ZXJzICovCj4gKyAgICAvKiBTdGF0dXMgb2YgcmVxdWVzdCAq Lwo+ICsgICAgaW50IHN0YXR1czsKPiArfTsKPiArCj4gK2YuIElPQ1RMX0hZUEVSX0RNQUJVRl9R VUVSWQo+ICsKPiArVGhpcyBJT0NUTCBpcyB1c2VkIHRvIHJldHJpZXZlIHNwZWNpZmljIGluZm9y bWF0aW9uIGFib3V0IGEgRE1BX0JVRiB0aGF0Cj4gK2lzIGJlaW5nIHNoYXJlZC4KPiArCj4gK1Ro ZSB1c2VyIHNwYWNlIGFyZ3VtZW50IGZvciB0aGlzIHR5cGUgb2YgSU9DVEwgaXMgZGVmaW5lZCBh czoKPiArCj4gK3N0cnVjdCBpb2N0bF9oeXBlcl9kbWFidWZfcXVlcnkgewo+ICsgICAgLyogaW4g cGFyYW1ldGVycyAqLwo+ICsgICAgLyogaHlwZXIgZG1hYnVmIGlkIHRvIGJlIHF1ZXJpZWQgKi8K PiArICAgIGludCBoeXBlcl9kbWFidWZfaWQ7Cj4gKyAgICAvKiBpdGVtIHRvIGJlIHF1ZXJpZWQg Ki8KPiArICAgIGludCBpdGVtOwo+ICsgICAgLyogT1VUIHBhcmFtZXRlcnMgKi8KPiArICAgIC8q IG91dHB1dCBvZiBxdWVyeSAqLwo+ICsgICAgLyogaW5mbyBjYW4gYmUgZWl0aGVyIHZhbHVlIG9y IHJlZmVyZW5jZSAqLwo+ICsgICAgdW5zaWduZWQgbG9uZyBpbmZvOwo+ICt9Owo+ICsKPiArPEF2 YWlsYWJsZSBRdWVyaWVzPgo+ICsKPiArSFlQRVJfRE1BQlVGX1FVRVJZX1RZUEUKPiArIC0gUmV0 dXJuIHRoZSB0eXBlIG9mIERNQV9CVUYgZnJvbSB0aGUgY3VycmVudCBkb21haW4sIEV4cG9ydGVk IG9yIEltcG9ydGVkLgo+ICsKPiArSFlQRVJfRE1BQlVGX1FVRVJZX0VYUE9SVEVSCj4gKyAtIFJl dHVybiB0aGUgZXhwb3J0aW5nIGRvbWFpbuKAmXMgSUQgb2YgYSBzaGFyZWQgRE1BX0JVRi4KPiAr Cj4gK0hZUEVSX0RNQUJVRl9RVUVSWV9JTVBPUlRFUgo+ICsgLSBSZXR1cm4gdGhlIGltcG9ydGlu ZyBkb21haW7igJlzIElEIG9mIGEgc2hhcmVkIERNQV9CVUYuCj4gKwo+ICtIWVBFUl9ETUFCVUZf UVVFUllfU0laRQo+ICsgLSBSZXR1cm4gdGhlIHNpemUgb2YgYSBzaGFyZWQgRE1BX0JVRiBpbiBi eXRlcy4KPiArCj4gK0hZUEVSX0RNQUJVRl9RVUVSWV9CVVNZCj4gKyAtIFJldHVybiDigJh0cnVl 4oCZIGlmIGEgc2hhcmVkIERNQV9CVUYgaXMgY3VycmVudGx5IHVzZWQKPiArICAgKG1hcHBlZCBi eSB0aGUgZW5kLWNvbnN1bWVyKS4KPiArCj4gK0hZUEVSX0RNQUJVRl9RVUVSWV9VTkVYUE9SVEVE Cj4gKyAtIFJldHVybiDigJh0cnVl4oCZIGlmIGEgc2hhcmVkIERNQV9CVUYgaXMgbm90IHZhbGlk IGFueW1vcmUKPiArICAgKHNvIGl0IGRvZXMgbm90IGFsbG93IGEgbmV3IGNvbnN1bWVyIHRvIG1h cCBpdCkuCj4gKwo+ICtIWVBFUl9ETUFCVUZfUVVFUllfREVMQVlFRF9VTkVYUE9SVEVECj4gKyAt IFJldHVybiDigJh0cnVl4oCZIGlmIGEgc2hhcmVkIERNQV9CVUYgaXMgc2NoZWR1bGVkIHRvIGJl IHVuZXhwb3J0ZWQKPiArICAgKGJ1dCBpcyBzdGlsbCB2YWxpZCkgd2l0aGluIGEgZml4ZWQgdGlt ZS4KPiArCj4gK0hZUEVSX0RNQUJVRl9RVUVSWV9QUklWX0lORk8KPiArIC0gUmV0dXJuIOKAmHBy aXZhdGXigJkgZGF0YSBhdHRhY2hlZCB0byBzaGFyZWQgRE1BX0JVRiB0byB0aGUgdXNlciBzcGFj ZS4KPiArICAg4oCYdW5zaWduZWQgbG9uZyBpbmZv4oCZIGlzIHRoZSB1c2VyIHNwYWNlIHBvaW50 ZXIgZm9yIHRoZSBidWZmZXIsIHdoZXJlCj4gKyAgIHByaXZhdGUgZGF0YSB3aWxsIGJlIGNvcGll ZCB0by4KPiArCj4gK0hZUEVSX0RNQUJVRl9RVUVSWV9QUklWX0lORk9fU0laRQo+ICsgLSBSZXR1 cm4gdGhlIHNpemUgb2YgdGhlIHByaXZhdGUgZGF0YSBhdHRhY2hlZCB0byB0aGUgc2hhcmVkIERN QV9CVUYuCj4gKwo+ICszLiBFdmVudCBQb2xsaW5nCj4gKwo+ICtFdmVudC1wb2xsaW5nIGNhbiBi ZSBlbmFibGVkIG9wdGlvbmFsbHkgYnkgc2VsZWN0aW5nIHRoZSBLZXJuZWwgY29uZmlnIG9wdGlv biwKPiArRW5hYmxlIGV2ZW50LWdlbmVyYXRpb24gYW5kIHBvbGxpbmcgb3BlcmF0aW9uIHVuZGVy IHhlbi9oeXBlcnZpc29yIGluIEtlcm5lbOKAmXMKPiArbWVudWNvbmZpZy4gVGhlIGV2ZW50LXBv bGxpbmcgbWVjaGFuaXNtIGluY2x1ZGVzIHRoZSBnZW5lcmF0aW9uIG9mCj4gK2FuIGltcG9ydC1l dmVudCwgYWRkaW5nIGl0IHRvIHRoZSBldmVudC1xdWV1ZSBhbmQgcHJvdmlkaW5nIGEgbm90aWZp Y2F0aW9uIHRvCj4gK3RoZSBhcHBsaWNhdGlvbiBzbyB0aGF0IGl0IGNhbiByZXRyaWV2ZSB0aGUg ZXZlbnQgZGF0YSBmcm9tIHRoZSBxdWV1ZS4KPiArCj4gK0ZvciB0aGlzIG1lY2hhbmlzbSwg4oCc UG9sbOKAnSBhbmQg4oCcUmVhZOKAnSBvcGVyYXRpb25zIGFyZSBhZGRlZCB0byB0aGUgSHlwZXJf RE1BQlVGCj4gK2RyaXZlci4gQSB1c2VyIGFwcGxpY2F0aW9uIHRoYXQgcG9sbHMgdGhlIGRyaXZl ciBnb2VzIGludG8gYSBzbGVlcCBzdGF0ZSB1bnRpbAo+ICt0aGVyZSBpcyBhIG5ldyBldmVudCBh ZGRlZCB0byB0aGUgcXVldWUuIEFuIGFwcGxpY2F0aW9uIHVzZXMg4oCcUmVhZOKAnSB0byByZXRy aWV2ZQo+ICtldmVudCBkYXRhIGZyb20gdGhlIGV2ZW50IHF1ZXVlLiBFdmVudCBkYXRhIGNvbnRh aW5zIHRoZSBoeXBlcl9kbWFidWZfaWQgYW5kCj4gK3RoZSBwcml2YXRlIGRhdGEgb2YgdGhlIGJ1 ZmZlciB0aGF0IGhhcyBiZWVuIHJlY2VpdmVkIGJ5IHRoZSBpbXBvcnRlci4KPiArCj4gK0ZvciBt b3JlIGluZm9ybWF0aW9uIG9uIHByaXZhdGUgZGF0YSwgcmVmZXIgdG8gU2VjdGlvbiAzLjUpLgo+ ICtVc2luZyB0aGlzIG1ldGhvZCwgaXQgaXMgcG9zc2libGUgdG8gbG93ZXIgdGhlIHJpc2sgb2Yg dGhlIGh5cGVyX2RtYWJ1Zl9pZCBhbmQKPiArb3RoZXIgc2Vuc2l0aXZlIGluZm9ybWF0aW9uIGFi b3V0IHRoZSBzaGFyZWQgYnVmZmVyIChmb3IgZXhhbXBsZSwgbWV0YS1kYXRhCj4gK2ZvciBzaGFy ZWQgaW1hZ2VzKSBiZWluZyBsZWFrZWQgd2hpbGUgYmVpbmcgdHJhbnNmZXJyZWQgdG8gdGhlIGlt cG9ydGVyIGJlY2F1c2UKPiArYWxsIG9mIHRoaXMgZGF0YSBpcyBzaGFyZWQgYXMg4oCccHJpdmF0 ZSBpbmZv4oCdIGF0IHRoZSBkcml2ZXIgbGV2ZWwuIEhvd2V2ZXIsCj4gK3BsZWFzZSBub3RlIHRo ZXJlIHNob3VsZCBiZSBhIHdheSBmb3IgdGhlIGltcG9ydGVyIHRvIGZpbmQgdGhlIGNvcnJlY3Qg RE1BX0JVRgo+ICtpbiB0aGlzIGNhc2Ugd2hlbiB0aGVyZSBhcmUgbXVsdGlwbGUgSHlwZXJfRE1B QlVGcyBiZWluZyBzaGFyZWQgc2ltdWx0YW5lb3VzbHkuCj4gK0ZvciBleGFtcGxlLCB0aGUgc3Vy ZmFjZSBuYW1lIG9yIHRoZSBzdXJmYWNlIElEIG9mIGEgc3BlY2lmaWMgcmVuZGVyaW5nIHN1cmZh Y2UKPiArbmVlZHMgdG8gYmUgc2VudCB0byB0aGUgaW1wb3J0ZXIgaW4gYWR2YW5jZSBiZWZvcmUg aXQgaXMgZXhwb3J0ZWQgaW4gYSBzdXJmYWNlLQo+ICtzaGFyaW5nIHVzZS1jYXNlLgo+ICsKPiAr RWFjaCBldmVudCBkYXRhIGdpdmVuIHRvIHRoZSB1c2VyLXNwYWNlIGNvbnNpc3RzIG9mIGEgaGVh ZGVyIGFuZCB0aGUgcHJpdmF0ZQo+ICtpbmZvcm1hdGlvbiBvZiB0aGUgYnVmZmVyLiBUaGUgZGF0 YSB0eXBlIGlzIGRlZmluZWQgYXMgZm9sbG93czoKPiArCj4gK3N0cnVjdCBoeXBlcl9kbWFidWZf ZXZlbnRfaGRyIHsKPiArICAgICAgICBpbnQgZXZlbnRfdHlwZTsgLyogb25lIHR5cGUgb25seSBm b3Igbm93IC0gbmV3IGltcG9ydCAqLwo+ICsgICAgICAgIGh5cGVyX2RtYWJ1Zl9pZF90IGhpZDsg LyogaHlwZXJfZG1hYnVmX2lkIG9mIHNwZWNpZmljIGh5cGVyX2RtYWJ1ZiAqLwo+ICsgICAgICAg IGludCBzaXplOyAvKiBzaXplIG9mIGRhdGEgKi8KPiArfTsKPiArCj4gK3N0cnVjdCBoeXBlcl9k bWFidWZfZXZlbnRfZGF0YSB7Cj4gKyAgICAgICAgc3RydWN0IGh5cGVyX2RtYWJ1Zl9ldmVudF9o ZHIgaGRyOwo+ICsgICAgICAgIHZvaWQgKmRhdGE7IC8qIHByaXZhdGUgZGF0YSAqLwo+ICt9Owo+ ICsKPiArNC4gSHlwZXJfRE1BQlVGIFByaXZhdGUgRGF0YQo+ICsKPiArRWFjaCBIeXBlcl9ETUFC VUYgY2FuIGNvbWUgd2l0aCBwcml2YXRlIGRhdGEsIHRoZSBzaXplIG9mIHdoaWNoIGNhbiBiZSB1 cCB0bwo+ICtBWF9TSVpFX1BSSVZfREFUQSAoY3VycmVudGx5IDE5MiBieXRlKS4gVGhpcyBwcml2 YXRlIGRhdGEgaXMganVzdCBhIGNodW5rIG9mCj4gK3BsYWluIGRhdGEgYXR0YWNoZWQgdG8gZXZl cnkgSHlwZXJfRE1BQlVGLiBJdCBpcyBndWFyYW50ZWVkIHRvIGJlIHN5bmNocm9uaXplZAo+ICth Y3Jvc3MgVk1zLCBleHBvcnRlciBhbmQgaW1wb3J0ZXIuIFRoaXMgcHJpdmF0ZSBkYXRhIGRvZXMg bm90IGhhdmUgYW55IHNwZWNpZmljCj4gK3N0cnVjdHVyZSBkZWZpbmVkIGF0IHRoZSBkcml2ZXIg bGV2ZWwsIHNvIGFueSDigJx1c2VyLWRlZmluZWTigJ0gZm9ybWF0IG9yCj4gK3N0cnVjdHVyZSBj YW4gYmUgdXNlZC4gSW4gYWRkaXRpb24sIHRoZXJlIGlzIG5vIGRlZGljYXRlZCB1c2UtY2FzZSBm b3IgdGhpcwo+ICtkYXRhLiBJdCBjYW4gYmUgdXNlZCB2aXJ0dWFsbHkgZm9yIGFueSBwdXJwb3Nl LiBGb3IgZXhhbXBsZSwgaXQgY2FuIGJlIHVzZWQgdG8KPiArc2hhcmUgbWV0YS1kYXRhIHN1Y2gg YXMgZGltZW5zaW9uIGFuZCBjb2xvciBmb3JtYXRzIGZvciBzaGFyZWQgaW1hZ2VzIGluCj4gK2Eg c3VyZmFjZSBzaGFyaW5nIG1vZGVsLiBBbm90aGVyIGV4YW1wbGUgaXMgd2hlbiB3ZSBzaGFyZSBw cm90ZWN0ZWQgbWVkaWEKPiArY29udGVudHMuCj4gKwo+ICtUaGlzIHByaXZhdGUgZGF0YSBjYW4g YmUgdXNlZCB0byB0cmFuc2ZlciBmbGFncyByZWxhdGVkIHRvIGNvbnRlbnQgcHJvdGVjdGlvbgo+ ICtpbmZvcm1hdGlvbiBvbiBzdHJlYW1lZCBtZWRpYSB0byB0aGUgaW1wb3J0ZXIuCj4gKwo+ICtQ cml2YXRlIGRhdGEgaXMgaW5pdGlhbGx5IGdlbmVyYXRlZCB3aGVuIGEgYnVmZmVyIGlzIGV4cG9y dGVkIGZvciB0aGUgZmlyc3QKPiArdGltZS4gVGhlbiwgaXQgaXMgdXBkYXRlZCB3aGVuZXZlciB0 aGUgc2FtZSBidWZmZXIgaXMgcmUtZXhwb3J0ZWQuIER1cmluZyB0aGUKPiArcmUtZXhwb3J0aW5n IHByb2Nlc3MsIHRoZSBIeXBlcl9ETUFCVUYgZHJpdmVyIG9ubHkgdXBkYXRlcyBwcml2YXRlIGRh dGEgb24KPiArYm90aCBzaWRlcyB3aXRoIG5ldyBkYXRhIGZyb20gdXNlci1zcGFjZSBzaW5jZSB0 aGUgc2FtZSBidWZmZXIgYWxyZWFkeSBleGlzdHMKPiArb24gYm90aCB0aGUgSU1QT1JUIExJU1Qg YW5kIEVYUE9SVCBMSVNULgo+ICsKPiArVGhlcmUgYXJlIHR3byBkaWZmZXJlbnQgd2F5cyB0byBy ZXRyaWV2ZSB0aGlzIHByaXZhdGUgZGF0YSBmcm9tIHVzZXItc3BhY2UuCj4gK1RoZSBmaXJzdCB3 YXkgaXMgdG8gdXNlIOKAnFJlYWTigJ0gb24gdGhlIEh5cGVyX0RNQUJVRiBkcml2ZXIuIOKAnFJl YWTigJ0gcmV0dXJucyB0aGUKPiArZGF0YSBvZiBldmVudHMgY29udGFpbmluZyBwcml2YXRlIGRh dGEgb2YgdGhlIGJ1ZmZlci4gVGhlIHNlY29uZCB3YXkgaXMgdG8KPiArbWFrZSBhIHF1ZXJ5IHRv IEh5cGVyX0RNQUJVRi4gVGhlcmUgYXJlIHR3byBxdWVyeSBpdGVtcywKPiArSFlQRVJfRE1BQlVG X1FVRVJZX1BSSVZfSU5GTyBhbmQgSFlQRVJfRE1BQlVGX1FVRVJZX1BSSVZfSU5GT19TSVpFIGF2 YWlsYWJsZQo+ICtmb3IgcmV0cmlldmluZyBwcml2YXRlIGRhdGEgYW5kIGl0cyBzaXplLgo+ICsK PiArNS4gU2NhdHRlci1HYXRoZXIgTGlzdCBUYWJsZSAoU0dUKSBNYW5hZ2VtZW50Cj4gKwo+ICtT R1QgbWFuYWdlbWVudCBpcyB0aGUgY29yZSBwYXJ0IG9mIHRoZSBIeXBlcl9ETUFCVUYgZHJpdmVy IHRoYXQgbWFuYWdlcyBhbgo+ICtTR1QsIGEgcmVwcmVzZW50YXRpb24gb2YgdGhlIGdyb3VwIG9m IGtlcm5lbCBwYWdlcyBhc3NvY2lhdGVkIHdpdGggYSBETUFfQlVGLgo+ICtUaGlzIGJsb2NrIGlu Y2x1ZGVzIGZvdXIgZGlmZmVyZW50IHN1Yi1ibG9ja3M6Cj4gKwo+ICthLiBIeXBlcl9ETUFCVUZf aWQgTWFuYWdlcgo+ICsKPiArVGhpcyBJRCBtYW5hZ2VyIGlzIHJlc3BvbnNpYmxlIGZvciBnZW5l cmF0aW5nIGEgaHlwZXJfZG1hYnVmX2lkIGZvciBhbgo+ICtleHBvcnRlZCBETUFfQlVGLiBXaGVu IGFuIElEIGlzIHJlcXVlc3RlZCwgdGhlIElEIE1hbmFnZXIgZmlyc3QgY2hlY2tzIGlmCj4gK3Ro ZXJlIGFyZSBhbnkgcmV1c2FibGUgSURzIGxlZnQgaW4gdGhlIGxpc3QgYW5kIHJldHVybnMgb25l IG9mIHRob3NlLAo+ICtpZiBhdmFpbGFibGUuIE90aGVyd2lzZSwgaXQgY3JlYXRlcyB0aGUgbmV4 dCBjb3VudCBudW1iZXIgYW5kIHJldHVybnMgaXQKPiArdG8gdGhlIGNhbGxlci4KPiArCj4gK2Iu IFNHVCBDcmVhdG9yCj4gKwo+ICtUaGUgU0dUIChzdHJ1Y3Qgc2dfdGFibGUpIGNvbnRhaW5zIGlu Zm9ybWF0aW9uIGFib3V0IHRoZSBETUFfQlVGIHN1Y2ggYXMKPiArcmVmZXJlbmNlcyB0byBhbGwg a2VybmVsIHBhZ2VzIGZvciB0aGUgYnVmZmVyIGFuZCB0aGVpciBjb25uZWN0aW9ucy4gVGhlCj4g K1NHVCBDcmVhdG9yIGNyZWF0ZXMgYSBuZXcgU0dUIG9uIHRoZSBpbXBvcnRlciBzaWRlIHdpdGgg cGFnZXMgc2hhcmVkIGJ5Cj4gK3RoZSBoeXBlcnZpc29yLgo+ICsKPiArYy4gS2VybmVsIFBhZ2Ug RXh0cmFjdG9yCj4gKwo+ICtUaGUgUGFnZSBFeHRyYWN0b3IgZXh0cmFjdHMgcGFnZXMgZnJvbSBh IGdpdmVuIFNHVCBiZWZvcmUgdGhvc2UgcGFnZXMKPiArYXJlIHNoYXJlZC4KPiArCj4gK2QuIExp c3QgTWFuYWdlciBJbnRlcmZhY2UKPiArCj4gK1RoZSBTR1QgbWFuZ2VyIGFsc28gaW50ZXJhY3Rz IHdpdGggZXhwb3J0IGFuZCBpbXBvcnQgbGlzdCBtYW5hZ2Vycy4gSXQKPiArc2VuZHMgb3V0IGlu Zm9ybWF0aW9uIChmb3IgZXhhbXBsZSwgaHlwZXJfZG1hYnVmX2lkLCByZWZlcmVuY2UsIGFuZAo+ ICtETUFfQlVGIGluZm9ybWF0aW9uKSBhYm91dCB0aGUgZXhwb3J0ZWQgb3IgaW1wb3J0ZWQgRE1B X0JVRnMgdG8gdGhlCj4gK2xpc3QgbWFuYWdlci4gQWxzbywgb24gSU9DVEwgcmVxdWVzdCwgaXQg YXNrcyB0aGUgbGlzdCBtYW5hZ2VyIHRvIGZpbmQKPiArYW5kIHJldHVybiB0aGUgaW5mb3JtYXRp b24gZm9yIGEgY29ycmVzcG9uZGluZyBETUFfQlVGIGluIHRoZSBsaXN0Lgo+ICsKPiArNi4gRE1B LUJVRiBJbnRlcmZhY2UKPiArCj4gK1RoZSBETUEtQlVGIGludGVyZmFjZSBwcm92aWRlcyBzdGFu ZGFyZCBtZXRob2RzIHRvIG1hbmFnZSBETUFfQlVGcwo+ICtyZWNvbnN0cnVjdGVkIGJ5IHRoZSBI eXBlcl9ETUFCVUYgZHJpdmVyIGZyb20gc2hhcmVkIHBhZ2VzLiBBbGwgb2YgdGhlCj4gK3JlbGV2 YW50IG9wZXJhdGlvbnMgYXJlIGxpc3RlZCBpbiBzdHJ1Y3QgZG1hX2J1Zl9vcHMuIFRoZXNlIG9w ZXJhdGlvbnMKPiArYXJlIHN0YW5kYXJkIERNQV9CVUYgb3BlcmF0aW9ucywgdGhlcmVmb3JlIHRo ZXkgZm9sbG93IHN0YW5kYXJkIERNQSBCVUYKPiArcHJvdG9jb2xzLgo+ICsKPiArRWFjaCBETUFf QlVGIG9wZXJhdGlvbiBjb21tdW5pY2F0ZXMgd2l0aCB0aGUgZXhwb3J0ZXIgYXQgdGhlIGVuZCBv ZiB0aGUKPiArcm91dGluZSBmb3Ig4oCcaW5kaXJlY3QgRE1BX0JVRiBzeW5jaHJvbml6YXRpb27i gJ0uCj4gKwo+ICs3LiBFeHBvcnQvSW1wb3J0IExpc3QgTWFuYWdlbWVudAo+ICsKPiArV2hlbmV2 ZXIgYSBETUFfQlVGIGlzIHNoYXJlZCBhbmQgZXhwb3J0ZWQsIGl0cyBpbmZvcm1hdGlvbiBpcyBh ZGRlZCB0byB0aGUKPiArZGF0YWJhc2UgKEVYUE9SVC1saXN0KSBvbiB0aGUgZXhwb3J0aW5nIFZN LiBTaW1pbGFybHksIGluZm9ybWF0aW9uIGFib3V0IGFuCj4gK2ltcG9ydGVkIERNQV9CVUYgaXMg YWRkZWQgdG8gdGhlIGltcG9ydGluZyBkYXRhYmFzZSAoSU1QT1JUIGxpc3QpIG9uIHRoZQo+ICtp bXBvcnRpbmcgVk0sIHdoZW4gdGhlIGV4cG9ydCBoYXBwZW5zLgo+ICsKPiArQWxsIG9mIHRoZSBl bnRyaWVzIGluIHRoZSBsaXN0cyBhcmUgbmVlZGVkIHRvIG1hbmFnZSB0aGUgZXhwb3J0ZWQvaW1w b3J0ZWQKPiArRE1BX0JVRiBtb3JlIGVmZmljaWVudGx5LiBCb3RoIGxpc3RzIGFyZSBpbXBsZW1l bnRlZCBhcyBMaW51eCBoYXNoIHRhYmxlcy4KPiArVGhlIGtleSB0byB0aGUgbGlzdCBpcyBoeXBl cl9kbWFidWZfaWQgYW5kIHRoZSBvdXRwdXQgaXMgdGhlIGluZm9ybWF0aW9uIG9mCj4gK3RoZSBE TUFfQlVGLiBUaGUgTGlzdCBNYW5hZ2VyIG1hbmFnZXMgYWxsIHJlcXVlc3RzIGZyb20gb3RoZXIg YmxvY2tzIGFuZAo+ICt0cmFuc2FjdGlvbnMgd2l0aGluIGxpc3RzIHRvIGVuc3VyZSB0aGF0IGFs bCBlbnRyaWVzIGFyZSB1cC10by1kYXRlIGFuZAo+ICt0aGF0IHRoZSBsaXN0IHN0cnVjdHVyZSBp cyBjb25zaXN0ZW50Lgo+ICsKPiArVGhlIExpc3QgTWFuYWdlciBwcm92aWRlcyBiYXNpYyBmdW5j dGlvbmFsaXR5LCBzdWNoIGFzOgo+ICsKPiArLSBBZGRpbmcgdG8gdGhlIExpc3QKPiArLSBSZW1v dmFsIGZyb20gdGhlIExpc3QKPiArLSBGaW5kaW5nIGluZm9ybWF0aW9uIGFib3V0IGEgRE1BX0JV RiwgZ2l2ZW4gdGhlIGh5cGVyX2RtYWJ1Zl9pZAo+ICsKPiArOC4gUGFnZSBTaGFyaW5nIGJ5IEh5 cGVyY2FsbHMKPiArCj4gK1RoZSBIeXBlcl9ETUFCVUYgZHJpdmVyIGFzc3VtZXMgdGhhdCB0aGVy ZSBpcyBhIG5hdGl2ZSBwYWdlLWJ5LXBhZ2UgbWVtb3J5Cj4gK3NoYXJpbmcgbWVjaGFuaXNtIGF2 YWlsYWJsZSBvbiB0aGUgaHlwZXJ2aXNvci4gUmVmZXJlbmNpbmcgYSBncm91cCBvZiBwYWdlcwo+ ICt0aGF0IGFyZSBiZWluZyBzaGFyZWQgaXMgd2hhdCB0aGUgZHJpdmVyIGV4cGVjdHMgZnJvbSDi gJxiYWNrZW5k4oCdIEFQSXMgb3IgdGhlCj4gK2h5cGVydmlzb3IgaXRzZWxmLgo+ICsKPiArRm9y IHRoZSBleGFtcGxlLCB4ZW4gYmFja2VuZCBpbnRlZ3JhdGVkIGluIGN1cnJlbnQgY29kZSBiYXNl IHV0aWxpemVzIFhlbuKAmXMKPiArZ3JhbnQtdGFibGUgaW50ZXJmYWNlIGZvciBzaGFyaW5nIHRo ZSB1bmRlcmx5aW5nIGtlcm5lbCBwYWdlcyAoc3RydWN0ICpwYWdlKS4KPiArCj4gK01vcmUgZGV0 YWlscyBhYm91dCBncmFudC10YWJsZSBpbnRlcmZhY2UgY2FuIGJlIGZvdW5kIGF0IHRoZSBmb2xs b3dpbmcgbG9jYXRpb25zOgo+ICsKPiAraHR0cHM6Ly93aWtpLnhlbi5vcmcvd2lraS9HcmFudF9U YWJsZQo+ICtodHRwczovL3hlbmJpdHMueGVuLm9yZy9kb2NzLzQuNi10ZXN0aW5nL21pc2MvZ3Jh bnQtdGFibGVzLnR4dAo+ICsKPiArOS4gTWVzc2FnZSBIYW5kbGluZwo+ICsKPiArVGhlIGV4cG9y dGVyIGFuZCBpbXBvcnRlciBjYW4gZWFjaCBjcmVhdGUgYSBtZXNzYWdlIHRoYXQgY29uc2lzdHMg b2YgYW4gb3Bjb2RlCj4gKyhjb21tYW5kKSBhbmQgb3BlcmFuZHMgKHBhcmFtZXRlcnMpIGFuZCBz ZW5kIGl0IHRvIGVhY2ggb3RoZXIuCj4gKwo+ICtUaGUgbWVzc2FnZSBmb3JtYXQgaXMgZGVmaW5l ZCBhczoKPiArCj4gK3N0cnVjdCBoeXBlcl9kbWFidWZfcmVxIHsKPiArICAgICAgICB1bnNpZ25l ZCBpbnQgcmVxX2lkOyAvKiBTZXF1ZW5jZSBudW1iZXIuIFVzZWQgZm9yIFJJTkcgQlVGCj4gKyAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3luY2hyb25pemF0aW9uICovCj4gKyAgICAg ICAgdW5zaWduZWQgaW50IHN0YXQ7IC8qIFN0YXR1cy5SZXNwb25zZSBmcm9tIHJlY2VpdmVyLiAq Lwo+ICsgICAgICAgIHVuc2lnbmVkIGludCBjbWQ7ICAvKiBPcGNvZGUgKi8KPiArICAgICAgICB1 bnNpZ25lZCBpbnQgb3BbTUFYX05VTUJFUl9PRl9PUEVSQU5EU107IC8qIE9wZXJhbmRzICovCj4g K307Cj4gKwo+ICtUaGUgZm9sbG93aW5nIHRhYmxlIGdpdmVzIHRoZSBsaXN0IG9mIG9wY29kZXM6 Cj4gKwo+ICs8T3Bjb2RlcyBpbiBNZXNzYWdlIHRvIEV4cG9ydGVyL0ltcG9ydGVyPgo+ICsKPiAr SFlQRVJfRE1BQlVGX0VYUE9SVCAoZXhwb3J0ZXIgLS0+IGltcG9ydGVyKQo+ICsgLSBFeHBvcnQg YSBETUFfQlVGIHRvIHRoZSBpbXBvcnRlci4gVGhlIGltcG9ydGVyIHJlZ2lzdGVycyB0aGUgY29y cmVzcG9uZGluZwo+ICsgICBETUFfQlVGIGluIGl0cyBJTVBPUlQgTElTVCB3aGVuIHRoZSBtZXNz YWdlIGlzIHJlY2VpdmVkLgo+ICsKPiArSFlQRVJfRE1BQlVGX0VYUE9SVF9GRCAoaW1wb3J0ZXIg LS0+IGV4cG9ydGVyKQo+ICsgLSBMb2NhbGx5IGV4cG9ydGVkIGFzIEZELiBUaGUgaW1wb3J0ZXIg c2VuZHMgb3V0IHRoaXMgY29tbWFuZCB0byB0aGUgZXhwb3J0ZXIKPiArICAgdG8gbm90aWZ5IHRo YXQgdGhlIGJ1ZmZlciBpcyBub3cgbG9jYWxseSBleHBvcnRlZCAobWFwcGVkIGFuZCB1c2VkKS4K PiArCj4gK0hZUEVSX0RNQUJVRl9FWFBPUlRfRkRfRkFJTEVEIChpbXBvcnRlciAtLT4gZXhwb3J0 ZXIpCj4gKyAtIEZhaWxlZCB3aGlsZSBleHBvcnRpbmcgbG9jYWxseS4gVGhlIGltcG9ydGVyIHNl bmRzIG91dCB0aGlzIGNvbW1hbmQgdG8gdGhlCj4gKyAgIGV4cG9ydGVyIHRvIG5vdGlmeSB0aGUg ZXhwb3J0ZXIgdGhhdCB0aGUgRVhQT1JUX0ZEIGZhaWxlZC4KPiArCj4gK0hZUEVSX0RNQUJVRl9O T1RJRllfVU5FWFBPUlQgKGV4cG9ydGVyIC0tPiBpbXBvcnRlcikKPiArIC0gVGVybWluYXRpb24g b2Ygc2hhcmluZy4gVGhlIGV4cG9ydGVyIG5vdGlmaWVzIHRoZSBpbXBvcnRlciB0aGF0IHRoZSBE TUFfQlVGCj4gKyAgIGhhcyBiZWVuIHVuZXhwb3J0ZWQuCj4gKwo+ICtIWVBFUl9ETUFCVUZfT1BT X1RPX1JFTU9URSAoaW1wb3J0ZXIgLS0+IGV4cG9ydGVyKQo+ICsgLSBOb3QgaW1wbGVtZW50ZWQg eWV0Lgo+ICsKPiArSFlQRVJfRE1BQlVGX09QU19UT19TT1VSQ0UgKGV4cG9ydGVyIC0tPiBpbXBv cnRlcikKPiArIC0gRE1BX0JVRiBvcHMgdG8gdGhlIGV4cG9ydGVyLCBmb3IgRE1BX0JVRiB1cHN0 cmVhbSBzeW5jaHJvbml6YXRpb24uCj4gKyAgIE5vdGU6IEltcGxlbWVudGVkIGJ1dCBpdCBpcyBk b25lIGFzeW5jaHJvbm91c2x5IGR1ZSB0byBwZXJmb3JtYW5jZSBpc3N1ZXMuCj4gKwo+ICtUaGUg Zm9sbG93aW5nIHRhYmxlIHNob3dzIHRoZSBsaXN0IG9mIG9wZXJhbmRzIGZvciBlYWNoIG9wY29k ZS4KPiArCj4gKzxPcGVyYW5kcyBpbiBNZXNzYWdlIHRvIEV4cG9ydGVyL0ltcG9ydGVyPgo+ICsK PiArLSBIWVBFUl9ETUFCVUZfRVhQT1JUCj4gKwo+ICtvcDAgdG8gb3AzIOKAkyBoeXBlcl9kbWFi dWZfaWQKPiArb3A0IOKAkyBudW1iZXIgb2YgcGFnZXMgdG8gYmUgc2hhcmVkCj4gK29wNSDigJMg b2Zmc2V0IG9mIGRhdGEgaW4gdGhlIGZpcnN0IHBhZ2UKPiArb3A2IOKAkyBsZW5ndGggb2YgZGF0 YSBpbiB0aGUgbGFzdCBwYWdlCj4gK29wNyDigJMgcmVmZXJlbmNlIG51bWJlciBmb3IgdGhlIGdy b3VwIG9mIHNoYXJlZCBwYWdlcwo+ICtvcDgg4oCTIHNpemUgb2YgcHJpdmF0ZSBkYXRhCj4gK29w OSB0byAob3A5K29wOCkgIOKAkyBwcml2YXRlIGRhdGEKPiArCj4gKy0gSFlQRVJfRE1BQlVGX0VY UE9SVF9GRAo+ICsKPiArb3AwIHRvIG9wMyDigJMgaHlwZXJfZG1hYnVmX2lkCj4gKwo+ICstIEhZ UEVSX0RNQUJVRl9FWFBPUlRfRkRfRkFJTEVECj4gKwo+ICtvcDAgdG8gb3AzIOKAkyBoeXBlcl9k bWFidWZfaWQKPiArCj4gKy0gSFlQRVJfRE1BQlVGX05PVElGWV9VTkVYUE9SVAo+ICsKPiArb3Aw IHRvIG9wMyDigJMgaHlwZXJfZG1hYnVmX2lkCj4gKwo+ICstIEhZUEVSX0RNQUJVRl9PUFNfVE9f UkVNT1RFKE5vdCBpbXBsZW1lbnRlZCkKPiArCj4gKy0gSFlQRVJfRE1BQlVGX09QU19UT19TT1VS Q0UKPiArCj4gK29wMCB0byBvcDMg4oCTIGh5cGVyX2RtYWJ1Zl9pZAo+ICtvcDQg4oCTIHR5cGUg b2YgRE1BX0JVRiBvcGVyYXRpb24KPiArCj4gKzkuIEludGVyIFZNIChEb21haW4pIENvbW11bmlj YXRpb24KPiArCj4gK1R3byBkaWZmZXJlbnQgdHlwZXMgb2YgaW50ZXItZG9tYWluIGNvbW11bmlj YXRpb24gY2hhbm5lbHMgYXJlIHJlcXVpcmVkLAo+ICtvbmUgaW4ga2VybmVsIHNwYWNlIGFuZCB0 aGUgb3RoZXIgaW4gdXNlciBzcGFjZS4gVGhlIGNvbW11bmljYXRpb24gY2hhbm5lbAo+ICtpbiB1 c2VyIHNwYWNlIGlzIGZvciB0cmFuc21pdHRpbmcgb3IgcmVjZWl2aW5nIHRoZSBoeXBlcl9kbWFi dWZfaWQuIFNpbmNlCj4gK3RoZXJlIGlzIG5vIHNwZWNpZmljIHNlY3VyaXR5IChmb3IgZXhhbXBs ZSwgZW5jcnlwdGlvbikgaW52b2x2ZWQgaW4gdGhlCj4gK2dlbmVyYXRpb24gb2YgYSBnbG9iYWwg aWQgYXQgdGhlIGRyaXZlciBsZXZlbCwgaXQgaXMgaGlnaGx5IHJlY29tbWVuZGVkIHRoYXQKPiAr dGhlIGN1c3RvbWVy4oCZcyB1c2VyIGFwcGxpY2F0aW9uIHNldCB1cCBhIHZlcnkgc2VjdXJlIGNo YW5uZWwgZm9yIGV4Y2hhbmdpbmcKPiAraHlwZXJfZG1hYnVmX2lkIGJldHdlZW4gVk1zLgo+ICsK PiArVGhlIGNvbW11bmljYXRpb24gY2hhbm5lbCBpbiBrZXJuZWwgc3BhY2UgaXMgcmVxdWlyZWQg Zm9yIGV4Y2hhbmdpbmcgbWVzc2FnZXMKPiArZnJvbSDigJxtZXNzYWdlIG1hbmFnZW1lbnTigJ0g YmxvY2sgYmV0d2VlbiB0d28gVk1zLiBJbiB0aGUgY3VycmVudCByZWZlcmVuY2UKPiArYmFja2Vu ZCBmb3IgWGVuIGh5cGVydmlzb3IsIFhlbiByaW5nLWJ1ZmZlciBhbmQgZXZlbnQtY2hhbm5lbCBt ZWNoYW5pc21zIGFyZQo+ICt1c2VkIGZvciBtZXNzYWdlIGV4Y2hhbmdlIGJldHdlZW4gaW1wb3Rl ciBhbmQgZXhwb3J0ZXIuCj4gKwo+ICsxMC4gV2hhdCBhcmUgcmVxdWlyZWQgaW4gaHlwZXJ2aXNv cgo+ICsKPiArZW1vcnkgc2hhcmluZyBhbmQgbWVzc2FnZSBjb21tdW5pY2F0aW9uIGJldHdlZW4g Vk1zCj4gKwo+ICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KPiArU2VjdGlvbiAzLiBIeXBlciBETUFC VUYgU2hhcmluZyBGbG93Cj4gKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQo+ICsKPiArMS4gRXhwb3J0 aW5nCj4gKwo+ICtUbyBleHBvcnQgYSBETUFfQlVGIHRvIGFub3RoZXIgVk0sIHVzZXIgc3BhY2Ug aGFzIHRvIGNhbGwgYW4gSU9DVEwKPiArKElPQ1RMX0hZUEVSX0RNQUJVRl9FWFBPUlRfUkVNT1RF KSB3aXRoIGEgZmlsZSBkZXNjcmlwdG9yIGZvciB0aGUgYnVmZmVyIGdpdmVuCj4gK2J5IHRoZSBv cmlnaW5hbCBleHBvcnRlci4gVGhlIEh5cGVyX0RNQUJVRiBkcml2ZXIgbWFwcyBhIERNQV9CVUYg bG9jYWxseSwgdGhlbgo+ICtpc3N1ZXMgYSBoeXBlcl9kbWFidWZfaWQgYW5kIFNHVCBmb3IgdGhl IERNQV9CVUYsIHdoaWNoIGlzIHJlZ2lzdGVyZWQgdG8gdGhlCj4gK0VYUE9SVCBsaXN0LiBUaGVu LCBhbGwgcGFnZXMgZm9yIHRoZSBTR1QgYXJlIGV4dHJhY3RlZCBhbmQgZWFjaCBpbmRpdmlkdWFs Cj4gK3BhZ2UgaXMgc2hhcmVkIHZpYSBhIGh5cGVydmlzb3Itc3BlY2lmaWMgbWVtb3J5IHNoYXJp bmcgbWVjaGFuaXNtCj4gKyhmb3IgZXhhbXBsZSwgaW4gWGVuIHRoaXMgaXMgZ3JhbnQtdGFibGUp Lgo+ICsKPiArT25lIGltcG9ydGFudCByZXF1aXJlbWVudCBvbiB0aGlzIG1lbW9yeSBzaGFyaW5n IG1ldGhvZCBpcyB0aGF0IGl0IG5lZWRzIHRvCj4gK2NyZWF0ZSBhIHNpbmdsZSBpbnRlZ2VyIHZh bHVlIHRoYXQgcmVwcmVzZW50cyB0aGUgbGlzdCBvZiBwYWdlcywgd2hpY2ggY2FuCj4gK3RoZW4g YmUgdXNlZCBieSB0aGUgaW1wb3J0ZXIgZm9yIHJldHJpZXZpbmcgdGhlIGdyb3VwIG9mIHNoYXJl ZCBwYWdlcy4gIEZvcgo+ICt0aGlzLCB0aGUg4oCcQmFja2VuZOKAnSBpbiB0aGUgcmVmZXJlbmNl IGRyaXZlciB1dGlsaXplcyB0aGUgbXVsdGlwbGUgbGV2ZWwKPiArYWRkcmVzc2luZyBtZWNoYW5p c20uCj4gKwo+ICtPbmNlIHRoZSBpbnRlZ2VyIHJlZmVyZW5jZSB0byB0aGUgbGlzdCBvZiBwYWdl cyBpcyBjcmVhdGVkLCB0aGUgZXhwb3J0ZXIKPiArYnVpbGRzIHRoZSDigJxleHBvcnTigJ0gY29t bWFuZCBhbmQgc2VuZHMgaXQgdG8gdGhlIGltcG9ydGVyLCB0aGVuIG5vdGlmaWVzIHRoZQo+ICtp bXBvcnRlci4KPiArCj4gKzIuIEltcG9ydGluZwo+ICsKPiArVGhlIEltcG9ydCBwcm9jZXNzIGlz IGRpdmlkZWQgaW50byB0d28gc2VjdGlvbnMuIE9uZSBpcyB0aGUgcmVnaXN0cmF0aW9uCj4gK29m IERNQV9CVUYgZnJvbSB0aGUgZXhwb3J0ZXIuIFRoZSBvdGhlciBpcyB0aGUgYWN0dWFsIG1hcHBp bmcgb2YgdGhlIGJ1ZmZlcgo+ICtiZWZvcmUgYWNjZXNzaW5nIHRoZSBkYXRhIGluIHRoZSBidWZm ZXIuIFRoZSBmb3JtZXIgKHRlcm1lZCDigJxSZWdpc3RyYXRpb27igJ0pCj4gK2hhcHBlbnMgb24g YW4gZXhwb3J0IGV2ZW50ICh0aGF0IGlzLCB0aGUgZXhwb3J0IGNvbW1hbmQgd2l0aCBhbiBpbnRl cnJ1cHQpCj4gK2luIHRoZSBleHBvcnRlci4KPiArCj4gK1RoZSBsYXR0ZXIgKHRlcm1lZCDigJxN YXBwaW5n4oCdKSBpcyBkb25lIGFzeW5jaHJvbm91c2x5IHdoZW4gdGhlIGRyaXZlciBnZXRzIHRo ZQo+ICtJT0NUTCBjYWxsIGZyb20gdXNlciBzcGFjZS4gV2hlbiB0aGUgaW1wb3J0ZXIgZ2V0cyBh biBpbnRlcnJ1cHQgZnJvbSB0aGUKPiArZXhwb3J0ZXIsIGl0IGNoZWNrcyB0aGUgY29tbWFuZCBp biB0aGUgcmVjZWl2aW5nIHF1ZXVlIGFuZCBpZiBpdCBpcyBhbgo+ICvigJxleHBvcnTigJ0gY29t bWFuZCwgdGhlIHJlZ2lzdHJhdGlvbiBwcm9jZXNzIGlzIHN0YXJ0ZWQuIEl0IGZpcnN0IGZpbmRz Cj4gK2h5cGVyX2RtYWJ1Zl9pZCBhbmQgdGhlIGludGVnZXIgcmVmZXJlbmNlIGZvciB0aGUgc2hh cmVkIHBhZ2VzLCB0aGVuIHN0b3Jlcwo+ICthbGwgb2YgdGhhdCBpbmZvcm1hdGlvbiB0b2dldGhl ciB3aXRoIHRoZSDigJxkb21haW4gaWTigJ0gb2YgdGhlIGV4cG9ydGluZyBkb21haW4KPiAraW4g dGhlIElNUE9SVCBMSVNULgo+ICsKPiArSW4gdGhlIGNhc2Ugd2hlcmUg4oCcZXZlbnQtcG9sbGlu Z+KAnSBpcyBlbmFibGVkIChLZXJuZWwgQ29uZmlnIC0gRW5hYmxlIGV2ZW50LQo+ICtnZW5lcmF0 aW9uIGFuZCBwb2xsaW5nIG9wZXJhdGlvbiksIGEg4oCcbmV3IHNoYXJpbmcgYXZhaWxhYmxl4oCd IGV2ZW50IGlzCj4gK2dlbmVyYXRlZCByaWdodCBhZnRlciB0aGUgcmVmZXJlbmNlIGluZm8gZm9y IHRoZSBuZXcgc2hhcmVkIERNQV9CVUYgaXMKPiArcmVnaXN0ZXJlZCB0byB0aGUgSU1QT1JUIExJ U1QuIFRoaXMgZXZlbnQgaXMgYWRkZWQgdG8gdGhlIGV2ZW50LXF1ZXVlLgo+ICsKPiArVGhlIHVz ZXIgcHJvY2VzcyB0aGF0IHBvbGxzIEh5cGVyX0RNQUJVRiBkcml2ZXIgd2FrZXMgdXAgd2hlbiB0 aGlzIGV2ZW50LXF1ZXVlCj4gK2lzIG5vdCBlbXB0eSBhbmQgaXMgYWJsZSB0byByZWFkIGJhY2sg ZXZlbnQgZGF0YSBmcm9tIHRoZSBxdWV1ZSB1c2luZyB0aGUKPiArZHJpdmVy4oCZcyDigJxSZWFk 4oCdIGZ1bmN0aW9uLiBPbmNlIHRoZSB1c2VyLWFwcGxpY2F0aW9uIGNhbGxzIEVYUE9SVF9GRCBJ T0NUTCB3aXRoCj4gK3RoZSBwcm9wZXIgcGFyYW1ldGVycyBpbmNsdWRpbmcgaHlwZXJfZG1hYnVm X2lkLCB0aGUgSHlwZXJfRE1BQlVGIGRyaXZlcgo+ICtyZXRyaWV2ZXMgaW5mb3JtYXRpb24gYWJv dXQgdGhlIG1hdGNoZWQgRE1BX0JVRiBmcm9tIHRoZSBJTVBPUlQgTElTVC4gVGhlbiwgaXQKPiAr bWFwcyBhbGwgcGFnZXMgc2hhcmVkIChyZWZlcmVuY2VkIGJ5IHRoZSBpbnRlZ2VyIHJlZmVyZW5j ZSkgaW4gaXRzIGtlcm5lbAo+ICtzcGFjZSBhbmQgY3JlYXRlcyBpdHMgb3duIERNQV9CVUYgcmVm ZXJlbmNpbmcgdGhlIHNhbWUgc2hhcmVkIHBhZ2VzLiBBZnRlcgo+ICt0aGlzLCBpdCBleHBvcnRz IHRoaXMgbmV3IERNQV9CVUYgdG8gdGhlIG90aGVyIGRyaXZlcnMgd2l0aCBhIGZpbGUgZGVzY3Jp cHRvci4KPiArRE1BX0JVRiBjYW4gdGhlbiBiZSB1c2VkIGp1c3QgaW4gdGhlIHNhbWUgd2F5IGEg bG9jYWwgRE1BX0JVRiBpcy4KPiArCj4gKzMuIEluZGlyZWN0IFN5bmNocm9uaXphdGlvbiBvZiBE TUFfQlVGCj4gKwo+ICtTeW5jaHJvbml6YXRpb24gb2YgYSBETUFfQlVGIHdpdGhpbiBhIHNpbmds ZSBPUyBpcyBhdXRvbWF0aWNhbGx5IGFjaGlldmVkCj4gK2JlY2F1c2UgYWxsIG9mIGltcG9ydGVy 4oCZcyBETUFfQlVGIG9wZXJhdGlvbnMgYXJlIGRvbmUgdXNpbmcgZnVuY3Rpb25zIGRlZmluZWQK PiArb24gdGhlIGV4cG9ydGVy4oCZcyBzaWRlLCB3aGljaCBtZWFucyB0aGVyZSBpcyBvbmUgY2Vu dHJhbCBwbGFjZSB0aGF0IGhhcyBmdWxsCj4gK2NvbnRyb2wgb3ZlciB0aGUgRE1BX0JVRi4gSW4g b3RoZXIgd29yZHMsIGFueSBwcmltYXJ5IGFjdGl2aXRpZXMgc3VjaCBhcwo+ICthdHRhY2hpbmcv ZGV0YWNoaW5nIGFuZCBtYXBwaW5nL3VuLW1hcHBpbmcgYXJlIGFsbCBjYXB0dXJlZCBieSB0aGUg ZXhwb3J0ZXIsCj4gK21lYW5pbmcgdGhhdCB0aGUgZXhwb3J0ZXIga25vd3MgYmFzaWMgaW5mb3Jt YXRpb24gc3VjaCBhcyB3aG8gaXMgdXNpbmcgdGhlCj4gK0RNQV9CVUYgYW5kIGhvdyBpdCBpcyBi ZWluZyB1c2VkLiBUaGlzLCBob3dldmVyLCBpcyBub3QgYXBwbGljYWJsZSBpZiB0aGlzCj4gK3No YXJpbmcgaXMgZG9uZSBiZXlvbmQgYSBzaW5nbGUgT1MgYmVjYXVzZSBrZXJuZWwgc3BhY2UgKHdo ZXJlIHRoZSBleHBvcnRlcuKAmXMKPiArRE1BX0JVRiBvcGVyYXRpb25zIHJlc2lkZSkgaXMgc2lt cGx5IG5vdCB2aXNpYmxlIHRvIHRoZSBpbXBvcnRpbmcgVk0uCj4gKwo+ICtUaGVyZWZvcmUsIOKA nGluZGlyZWN0IHN5bmNocm9uaXphdGlvbuKAnSB3YXMgaW50cm9kdWNlZCBhcyBhbiBhbHRlcm5h dGl2ZSBzb2x1dGlvbiwKPiArd2hpY2ggaXMgbm93IGltcGxlbWVudGVkIGluIHRoZSBIeXBlcl9E TUFCVUYgZHJpdmVyLiBUaGlzIHRlY2huaXF1ZSBtYWtlcwo+ICt0aGUgZXhwb3J0ZXIgY3JlYXRl IGEgc2hhZG93IERNQV9CVUYgd2hlbiB0aGUgZW5kLWNvbnN1bWVyIG9mIHRoZSBidWZmZXIgbWFw cwo+ICt0aGUgRE1BX0JVRiwgdGhlbiBkdXBsaWNhdGVzIGFueSBETUFfQlVGIG9wZXJhdGlvbnMg cGVyZm9ybWVkIG9uCj4gK3RoZSBpbXBvcnRlcuKAmXMgc2lkZS4gVGhyb3VnaCB0aGlzIOKAnGlu ZGlyZWN0IHN5bmNocm9uaXphdGlvbuKAnSwgdGhlIGV4cG9ydGVyIGlzCj4gK2FibGUgdG8gdmly dHVhbGx5IHRyYWNrIGFsbCBhY3Rpdml0aWVzIGRvbmUgYnkgdGhlIGNvbnN1bWVyIChtb3N0bHkg cmVmZXJlbmNlCj4gK2NvdW50ZXIpIGFzIGlmIHRob3NlIGFyZSBkb25lIGluIGV4cG9ydGVy4oCZ cyBsb2NhbCBzeXN0ZW0uCj4gKwo+ICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KPiArU2VjdGlvbiA0 LiBIeXBlcnZpc29yIEJhY2tlbmQgSW50ZXJmYWNlCj4gKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQo+ ICsKPiArVGhlIEh5cGVyX0RNQUJVRiBkcml2ZXIgaGFzIGEgc3RhbmRhcmQg4oCcQmFja2VuZOKA nSBzdHJ1Y3R1cmUgdGhhdCBjb250YWlucwo+ICttYXBwaW5ncyB0byB2YXJpb3VzIGZ1bmN0aW9u cyBkZXNpZ25lZCBmb3IgYSBzcGVjaWZpYyBIeXBlcnZpc29yLiBNb3N0IG9mCj4gK3RoZXNlIEFQ SSBmdW5jdGlvbnMgc2hvdWxkIHByb3ZpZGUgYSBsb3ctbGV2ZWwgaW1wbGVtZW50YXRpb24gb2Yg Y29tbXVuaWNhdGlvbgo+ICthbmQgbWVtb3J5IHNoYXJpbmcgY2FwYWJpbGl0eSB0aGF0IHV0aWxp emUgYSBIeXBlcnZpc29y4oCZcyBuYXRpdmUgbWVjaGFuaXNtcy4KPiArCj4gK3N0cnVjdCBoeXBl cl9kbWFidWZfYmFja2VuZF9vcHMgewo+ICsgICAgICAgIC8qIHJldHJlaXZpbmcgaWQgb2YgY3Vy cmVudCB2aXJ0dWFsIG1hY2hpbmUgKi8KPiArICAgICAgICBpbnQgKCpnZXRfdm1faWQpKHZvaWQp Owo+ICsgICAgICAgIC8qIGdldCBwYWdlcyBzaGFyZWQgdmlhIGh5cGVydmlzb3Itc3BlY2lmaWMg bWV0aG9kICovCj4gKyAgICAgICAgaW50ICgqc2hhcmVfcGFnZXMpKHN0cnVjdCBwYWdlICoqLCBp bnQsIGludCwgdm9pZCAqKik7Cj4gKyAgICAgICAgLyogbWFrZSBzaGFyZWQgcGFnZXMgdW5zaGFy ZWQgdmlhIGh5cGVydmlzb3Igc3BlY2lmaWMgbWV0aG9kICovCj4gKyAgICAgICAgaW50ICgqdW5z aGFyZV9wYWdlcykodm9pZCAqKiwgaW50KTsKPiArICAgICAgICAvKiBtYXAgcmVtb3RlbHkgc2hh cmVkIHBhZ2VzIG9uIGltcG9ydGVyJ3Mgc2lkZSB2aWEKPiArICAgICAgICAgKiAgaHlwZXJ2aXNv ci1zcGVjaWZpYyBtZXRob2QKPiArICAgICAgICAgKi8KPiArICAgICAgICBzdHJ1Y3QgcGFnZSAq KiAoKm1hcF9zaGFyZWRfcGFnZXMpKGludCwgaW50LCBpbnQsIHZvaWQgKiopOwo+ICsgICAgICAg IC8qIHVubWFwIGFuZCBmcmVlIHNoYXJlZCBwYWdlcyBvbiBpbXBvcnRlcidzIHNpZGUgdmlhCj4g KyAgICAgICAgICogIGh5cGVydmlzb3Itc3BlY2lmaWMgbWV0aG9kCj4gKyAgICAgICAgICovCj4g KyAgICAgICAgaW50ICgqdW5tYXBfc2hhcmVkX3BhZ2VzKSh2b2lkICoqLCBpbnQpOwo+ICsgICAg ICAgIC8qIGluaXRpYWxpemUgY29tbXVuaWNhdGlvbiBlbnZpcm9ubWVudCAqLwo+ICsgICAgICAg IGludCAoKmluaXRfY29tbV9lbnYpKHZvaWQpOwo+ICsgICAgICAgIC8qIGRlc3Ryb3kgY29tbXVu aWNhdGlvbiBjaGFubmVsICovCj4gKyAgICAgICAgdm9pZCAoKmRlc3Ryb3lfY29tbSkodm9pZCk7 Cj4gKyAgICAgICAgLyogdXBzdHJlYW0gY2ggc2V0dXAgKHJlY2VpdmluZyBhbmQgcmVzcG9uZGlu ZykgKi8KPiArICAgICAgICBpbnQgKCppbml0X3J4X2NoKShpbnQpOwo+ICsgICAgICAgIC8qIGRv d25zdHJlYW0gY2ggc2V0dXAgKHRyYW5zbWl0dGluZyBhbmQgcGFyc2luZyByZXNwb25zZXMpICov Cj4gKyAgICAgICAgaW50ICgqaW5pdF90eF9jaCkoaW50KTsKPiArICAgICAgICAvKiBzZW5kIG1z ZyB2aWEgY29tbXVuaWNhdGlvbiBjaCAqLwo+ICsgICAgICAgIGludCAoKnNlbmRfcmVxKShpbnQs IHN0cnVjdCBoeXBlcl9kbWFidWZfcmVxICosIGludCk7Cj4gK307Cj4gKwo+ICs8SHlwZXJ2aXNv ci1zcGVjaWZpYyBCYWNrZW5kIFN0cnVjdHVyZT4KPiArCj4gKzEuIGdldF92bV9pZAo+ICsKPiAr CVJldHVybnMgdGhlIFZNIChkb21haW4pIElECj4gKwo+ICsJSW5wdXQ6Cj4gKwo+ICsJCS1JRCBv ZiB0aGUgY3VycmVudCBkb21haW4KPiArCj4gKwlPdXRwdXQ6Cj4gKwo+ICsJCU5vbmUKPiArCj4g KzIuIHNoYXJlX3BhZ2VzCj4gKwo+ICsJR2V0IHBhZ2VzIHNoYXJlZCB2aWEgaHlwZXJ2aXNvci1z cGVjaWZpYyBtZXRob2QgYW5kIHJldHVybiBvbmUgcmVmZXJlbmNlCj4gKwlJRCB0aGF0IHJlcHJl c2VudHMgdGhlIGNvbXBsZXRlIGxpc3Qgb2Ygc2hhcmVkIHBhZ2VzCj4gKwo+ICsJSW5wdXQ6Cj4g Kwo+ICsJCS1BcnJheSBvZiBwYWdlcwo+ICsJCS1JRCBvZiBpbXBvcnRpbmcgVk0KPiArCQktTnVt YmVyIG9mIHBhZ2VzCj4gKwkJLUh5cGVydmlzb3Igc3BlY2lmaWMgUmVwcmVzZW50YXRpb24gb2Yg cmVmZXJlbmNlIGluZm8gb2Ygc2hhcmVkCj4gKwkJIHBhZ2VzCj4gKwo+ICsJT3V0cHV0Ogo+ICsK PiArCQktSHlwZXJ2aXNvciBzcGVjaWZpYyBpbnRlZ2VyIHZhbHVlIHRoYXQgcmVwcmVzZW50cyBh bGwgb2YKPiArCQkgdGhlIHNoYXJlZCBwYWdlcwo+ICsKPiArMy4gdW5zaGFyZV9wYWdlcwo+ICsK PiArCVN0b3Agc2hhcmluZyBwYWdlcwo+ICsKPiArCUlucHV0Ogo+ICsKPiArCQktSHlwZXJ2aXNv ciBzcGVjaWZpYyBSZXByZXNlbnRhdGlvbiBvZiByZWZlcmVuY2UgaW5mbyBvZiBzaGFyZWQKPiAr CQkgcGFnZXMKPiArCQktTnVtYmVyIG9mIHNoYXJlZCBwYWdlcwo+ICsKPiArCU91dHB1dDoKPiAr Cj4gKwkJMAo+ICsKPiArNC4gbWFwX3NoYXJlZF9wYWdlcwo+ICsKPiArCU1hcCBzaGFyZWQgcGFn ZXMgbG9jYWxseSB1c2luZyBhIGh5cGVydmlzb3Itc3BlY2lmaWMgbWV0aG9kCj4gKwo+ICsJSW5w dXQ6Cj4gKwo+ICsJCS1SZWZlcmVuY2UgbnVtYmVyIHRoYXQgcmVwcmVzZW50cyBhbGwgb2Ygc2hh cmVkIHBhZ2VzCj4gKwkJLUlEIG9mIGV4cG9ydGluZyBWTSwgTnVtYmVyIG9mIHBhZ2VzCj4gKwkJ LVJlZmVyZW5jZSBpbmZvcm1hdGlvbiBmb3IgYW55IHB1cnBvc2UKPiArCj4gKwlPdXRwdXQ6Cj4g Kwo+ICsJCS1BbiBhcnJheSBvZiBzaGFyZWQgcGFnZXMgKHN0cnVjdCBwYWdlKiopCj4gKwo+ICs1 LiB1bm1hcF9zaGFyZWRfcGFnZXMKPiArCj4gKwlVbm1hcCBzaGFyZWQgcGFnZXMKPiArCj4gKwlJ bnB1dDoKPiArCj4gKwkJLUh5cGVydmlzb3Igc3BlY2lmaWMgUmVwcmVzZW50YXRpb24gb2YgcmVm ZXJlbmNlIGluZm8gb2Ygc2hhcmVkIHBhZ2VzCj4gKwo+ICsJT3V0cHV0Ogo+ICsKPiArCQktMCAo c3VjY2Vzc2Z1bCkgb3Igb25lIG9mIFN0YW5kYXJkIEtlcm5lbCBlcnJvcnMKPiArCj4gKzYuIGlu aXRfY29tbV9lbnYKPiArCj4gKwlTZXR1cCBpbmZyYXN0cnVjdHVyZSBuZWVkZWQgZm9yIGNvbW11 bmljYXRpb24gY2hhbm5lbAo+ICsKPiArCUlucHV0Ogo+ICsKPiArCQlOb25lCj4gKwo+ICsJT3V0 cHV0Ogo+ICsKPiArCQlOb25lCj4gKwo+ICs3LiBkZXN0cm95X2NvbW0KPiArCj4gKwlDbGVhbnVw IGV2ZXJ5dGhpbmcgZG9uZSB2aWEgaW5pdF9jb21tX2Vudgo+ICsKPiArCUlucHV0Ogo+ICsKPiAr CQlOb25lCj4gKwo+ICsJT3V0cHV0Ogo+ICsKPiArCQlOb25lCj4gKwo+ICs4LiBpbml0X3J4X2No Cj4gKwo+ICsJQ29uZmlndXJlIHJlY2VpdmUgY2hhbm5lbAo+ICsKPiArCUlucHV0Ogo+ICsKPiAr CQktSUQgb2YgVk0gb24gdGhlIG90aGVyIHNpZGUgb2YgdGhlIGNoYW5uZWwKPiArCj4gKwlPdXRw dXQ6Cj4gKwo+ICsJCS0wIChzdWNjZXNzZnVsKSBvciBvbmUgb2YgU3RhbmRhcmQgS2VybmVsIGVy cm9ycwo+ICsKPiArOS4gaW5pdF90eF9jaAo+ICsKPiArCUNvbmZpZ3VyZSB0cmFuc21pdCBjaGFu bmVsCj4gKwo+ICsJSW5wdXQ6Cj4gKwo+ICsJCS1JRCBvZiBWTSBvbiB0aGUgb3RoZXIgc2lkZSBv ZiB0aGUgY2hhbm5lbAo+ICsKPiArCU91dHB1dDoKPiArCj4gKwkJLTAgKHN1Y2Nlc3MpIG9yIG9u ZSBvZiBTdGFuZGFyZCBLZXJuZWwgZXJyb3JzCj4gKwo+ICsxMC4gc2VuZF9yZXEKPiArCj4gKwlT ZW5kIG1lc3NhZ2UgdG8gb3RoZXIgVk0KPiArCj4gKwlJbnB1dDoKPiArCj4gKwkJLUlEIG9mIFZN IHRoYXQgcmVjZWl2ZXMgdGhlIG1lc3NhZ2UKPiArCQktTWVzc2FnZQo+ICsKPiArCU91dHB1dDoK PiArCj4gKwkJLTAgKHN1Y2Nlc3MpIG9yIG9uZSBvZiBTdGFuZGFyZCBLZXJuZWwgZXJyb3JzCj4g Kwo+ICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCj4gKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KPgoK WzFdIApodHRwczovL2VsaXhpci5ib290bGluLmNvbS9saW51eC92NC4xNi4xL3NvdXJjZS9pbmNs dWRlL3hlbi9pbnRlcmZhY2UvaW8va2JkaWYuaApfX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fXwpkcmktZGV2ZWwgbWFpbGluZyBsaXN0CmRyaS1kZXZlbEBsaXN0 cy5mcmVlZGVza3RvcC5vcmcKaHR0cHM6Ly9saXN0cy5mcmVlZGVza3RvcC5vcmcvbWFpbG1hbi9s aXN0aW5mby9kcmktZGV2ZWwK