From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752673AbdLSTgJ (ORCPT ); Tue, 19 Dec 2017 14:36:09 -0500 Received: from mga02.intel.com ([134.134.136.20]:20196 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752330AbdLSTgH (ORCPT ); Tue, 19 Dec 2017 14:36:07 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.45,428,1508828400"; d="scan'208";a="4018333" From: Dongwon Kim To: linux-kernel@vger.kernel.org Cc: dri-devel@lists.freedesktop.org, xen-devel@lists.xenproject.org, mateuszx.potrola@intel.com, dongwon.kim@intel.com Subject: [RFC PATCH 01/60] hyper_dmabuf: initial working version of hyper_dmabuf drv Date: Tue, 19 Dec 2017 11:29:17 -0800 Message-Id: <1513711816-2618-1-git-send-email-dongwon.kim@intel.com> X-Mailer: git-send-email 2.7.4 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Upload of intial version of hyper_DMABUF driver enabling DMA_BUF exchange between two different VMs in virtualized platform based on hypervisor such as KVM or XEN. Hyper_DMABUF drv's primary role is to import a DMA_BUF from originator then re-export it to another Linux VM so that it can be mapped and accessed by it. The functionality of this driver highly depends on Hypervisor's native page sharing mechanism and inter-VM communication support. This driver has two layers, one is main hyper_DMABUF framework for scatter-gather list management that handles actual import and export of DMA_BUF. Lower layer is about actual memory sharing and communication between two VMs, which is hypervisor-specific interface. This driver is initially designed to enable DMA_BUF sharing across VMs in Xen environment, so currently working with Xen only. This also adds Kernel configuration for hyper_DMABUF drv under Device Drivers->Xen driver support->hyper_dmabuf options. To give some brief information about each source file, hyper_dmabuf/hyper_dmabuf_conf.h : configuration info hyper_dmabuf/hyper_dmabuf_drv.c : driver interface and initialization hyper_dmabuf/hyper_dmabuf_imp.c : scatter-gather list generation and management. DMA_BUF ops for DMA_BUF reconstructed from hyper_DMABUF hyper_dmabuf/hyper_dmabuf_ioctl.c : IOCTLs calls for export/import and comm channel creation unexport. hyper_dmabuf/hyper_dmabuf_list.c : Database (linked-list) for exported and imported hyper_DMABUF hyper_dmabuf/hyper_dmabuf_msg.c : creation and management of messages between exporter and importer hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c : comm ch management and ISRs for incoming messages. hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c : Database (linked-list) for keeping information about existing comm channels among VMs Signed-off-by: Dongwon Kim Signed-off-by: Mateusz Polrola --- drivers/xen/Kconfig | 2 + drivers/xen/Makefile | 1 + drivers/xen/hyper_dmabuf/Kconfig | 14 + drivers/xen/hyper_dmabuf/Makefile | 34 + drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h | 2 + drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c | 54 ++ drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h | 101 +++ drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c | 852 +++++++++++++++++++++ drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h | 31 + drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c | 462 +++++++++++ drivers/xen/hyper_dmabuf/hyper_dmabuf_list.c | 119 +++ drivers/xen/hyper_dmabuf/hyper_dmabuf_list.h | 40 + drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c | 212 +++++ drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h | 45 ++ drivers/xen/hyper_dmabuf/hyper_dmabuf_query.h | 16 + drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h | 70 ++ .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c | 328 ++++++++ .../xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h | 62 ++ .../hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c | 106 +++ .../hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h | 35 + 20 files changed, 2586 insertions(+) create mode 100644 drivers/xen/hyper_dmabuf/Kconfig create mode 100644 drivers/xen/hyper_dmabuf/Makefile create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_list.c create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_list.h create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_query.h create mode 100644 drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h create mode 100644 drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c create mode 100644 drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h create mode 100644 drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c create mode 100644 drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index d8dd546..b59b0e3 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -321,4 +321,6 @@ config XEN_SYMS config XEN_HAVE_VPMU bool +source "drivers/xen/hyper_dmabuf/Kconfig" + endmenu diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 451e833..a6e253a 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_X86) += fallback.o obj-y += grant-table.o features.o balloon.o manage.o preempt.o time.o obj-y += events/ obj-y += xenbus/ +obj-y += hyper_dmabuf/ nostackp := $(call cc-option, -fno-stack-protector) CFLAGS_features.o := $(nostackp) diff --git a/drivers/xen/hyper_dmabuf/Kconfig b/drivers/xen/hyper_dmabuf/Kconfig new file mode 100644 index 0000000..75e1f96 --- /dev/null +++ b/drivers/xen/hyper_dmabuf/Kconfig @@ -0,0 +1,14 @@ +menu "hyper_dmabuf options" + +config HYPER_DMABUF + tristate "Enables hyper dmabuf driver" + default y + +config HYPER_DMABUF_XEN + bool "Configure hyper_dmabuf for XEN hypervisor" + default y + depends on HYPER_DMABUF + help + Configuring hyper_dmabuf driver for XEN hypervisor + +endmenu diff --git a/drivers/xen/hyper_dmabuf/Makefile b/drivers/xen/hyper_dmabuf/Makefile new file mode 100644 index 0000000..0be7445 --- /dev/null +++ b/drivers/xen/hyper_dmabuf/Makefile @@ -0,0 +1,34 @@ +TARGET_MODULE:=hyper_dmabuf + +# If we running by kernel building system +ifneq ($(KERNELRELEASE),) + $(TARGET_MODULE)-objs := hyper_dmabuf_drv.o \ + hyper_dmabuf_ioctl.o \ + hyper_dmabuf_list.o \ + hyper_dmabuf_imp.o \ + hyper_dmabuf_msg.o \ + xen/hyper_dmabuf_xen_comm.o \ + xen/hyper_dmabuf_xen_comm_list.o + +obj-$(CONFIG_HYPER_DMABUF) := $(TARGET_MODULE).o + +# If we are running without kernel build system +else +BUILDSYSTEM_DIR?=../../../ +PWD:=$(shell pwd) + +all : +# run kernel build system to make module +$(MAKE) -C $(BUILDSYSTEM_DIR) M=$(PWD) modules + +clean: +# run kernel build system to cleanup in current directory +$(MAKE) -C $(BUILDSYSTEM_DIR) M=$(PWD) clean + +load: + insmod ./$(TARGET_MODULE).ko + +unload: + rmmod ./$(TARGET_MODULE).ko + +endif diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h new file mode 100644 index 0000000..3d9b2d6 --- /dev/null +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_conf.h @@ -0,0 +1,2 @@ +#define CURRENT_TARGET XEN +#define INTER_DOMAIN_DMABUF_SYNCHRONIZATION diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c new file mode 100644 index 0000000..0698327 --- /dev/null +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.c @@ -0,0 +1,54 @@ +#include /* module_init, module_exit */ +#include /* version info, MODULE_LICENSE, MODULE_AUTHOR, printk() */ +#include "hyper_dmabuf_conf.h" +#include "hyper_dmabuf_list.h" +#include "xen/hyper_dmabuf_xen_comm_list.h" + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("IOTG-PED, INTEL"); + +int register_device(void); +int unregister_device(void); + +/*===============================================================================================*/ +static int hyper_dmabuf_drv_init(void) +{ + int ret = 0; + + printk( KERN_NOTICE "hyper_dmabuf_starting: Initialization started" ); + + ret = register_device(); + if (ret < 0) { + return -EINVAL; + } + + printk( KERN_NOTICE "initializing database for imported/exported dmabufs\n"); + + ret = hyper_dmabuf_table_init(); + if (ret < 0) { + return -EINVAL; + } + + ret = hyper_dmabuf_ring_table_init(); + if (ret < 0) { + return -EINVAL; + } + + /* interrupt for comm should be registered here: */ + return ret; +} + +/*-----------------------------------------------------------------------------------------------*/ +static void hyper_dmabuf_drv_exit(void) +{ + /* hash tables for export/import entries and ring_infos */ + hyper_dmabuf_table_destroy(); + hyper_dmabuf_ring_table_init(); + + printk( KERN_NOTICE "dma_buf-src_sink model: Exiting" ); + unregister_device(); +} +/*===============================================================================================*/ + +module_init(hyper_dmabuf_drv_init); +module_exit(hyper_dmabuf_drv_exit); diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h new file mode 100644 index 0000000..2dad9a6 --- /dev/null +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_drv.h @@ -0,0 +1,101 @@ +#ifndef __LINUX_PUBLIC_HYPER_DMABUF_DRV_H__ +#define __LINUX_PUBLIC_HYPER_DMABUF_DRV_H__ + +typedef int (*hyper_dmabuf_ioctl_t)(void *data); + +struct hyper_dmabuf_ioctl_desc { + unsigned int cmd; + int flags; + hyper_dmabuf_ioctl_t func; + const char *name; +}; + +#define HYPER_DMABUF_IOCTL_DEF(ioctl, _func, _flags) \ + [_IOC_NR(ioctl)] = { \ + .cmd = ioctl, \ + .func = _func, \ + .flags = _flags, \ + .name = #ioctl \ + } + +#define IOCTL_HYPER_DMABUF_EXPORTER_RING_SETUP \ +_IOC(_IOC_NONE, 'G', 0, sizeof(struct ioctl_hyper_dmabuf_exporter_ring_setup)) +struct ioctl_hyper_dmabuf_exporter_ring_setup { + /* IN parameters */ + /* Remote domain id */ + uint32_t remote_domain; + grant_ref_t ring_refid; /* assigned by driver, copied to userspace after initialization */ + uint32_t port; /* assigned by driver, copied to userspace after initialization */ +}; + +#define IOCTL_HYPER_DMABUF_IMPORTER_RING_SETUP \ +_IOC(_IOC_NONE, 'G', 1, sizeof(struct ioctl_hyper_dmabuf_importer_ring_setup)) +struct ioctl_hyper_dmabuf_importer_ring_setup { + /* IN parameters */ + /* Source domain id */ + uint32_t source_domain; + /* Ring shared page refid */ + grant_ref_t ring_refid; + /* Port number */ + uint32_t port; +}; + +#define IOCTL_HYPER_DMABUF_EXPORT_REMOTE \ +_IOC(_IOC_NONE, 'G', 2, sizeof(struct ioctl_hyper_dmabuf_export_remote)) +struct ioctl_hyper_dmabuf_export_remote { + /* IN parameters */ + /* DMA buf fd to be exported */ + uint32_t dmabuf_fd; + /* Domain id to which buffer should be exported */ + uint32_t remote_domain; + /* exported dma buf id */ + uint32_t hyper_dmabuf_id; + uint32_t private[4]; +}; + +#define IOCTL_HYPER_DMABUF_EXPORT_FD \ +_IOC(_IOC_NONE, 'G', 3, sizeof(struct ioctl_hyper_dmabuf_export_fd)) +struct ioctl_hyper_dmabuf_export_fd { + /* IN parameters */ + /* hyper dmabuf id to be imported */ + uint32_t hyper_dmabuf_id; + /* flags */ + uint32_t flags; + /* OUT parameters */ + /* exported dma buf fd */ + uint32_t fd; +}; + +#define IOCTL_HYPER_DMABUF_DESTROY \ +_IOC(_IOC_NONE, 'G', 4, sizeof(struct ioctl_hyper_dmabuf_destroy)) +struct ioctl_hyper_dmabuf_destroy { + /* IN parameters */ + /* hyper dmabuf id to be destroyed */ + uint32_t hyper_dmabuf_id; + /* OUT parameters */ + /* Status of request */ + uint32_t status; +}; + +#define IOCTL_HYPER_DMABUF_QUERY \ +_IOC(_IOC_NONE, 'G', 5, sizeof(struct ioctl_hyper_dmabuf_query)) +struct ioctl_hyper_dmabuf_query { + /* in parameters */ + /* hyper dmabuf id to be queried */ + uint32_t hyper_dmabuf_id; + /* item to be queried */ + uint32_t item; + /* OUT parameters */ + /* Value of queried item */ + uint32_t info; +}; + +#define IOCTL_HYPER_DMABUF_REMOTE_EXPORTER_RING_SETUP \ +_IOC(_IOC_NONE, 'G', 6, sizeof(struct ioctl_hyper_dmabuf_remote_exporter_ring_setup)) +struct ioctl_hyper_dmabuf_remote_exporter_ring_setup { + /* in parameters */ + uint32_t rdomain; /* id of remote domain where exporter's ring need to be setup */ + uint32_t info; +}; + +#endif //__LINUX_PUBLIC_HYPER_DMABUF_DRV_H__ diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c new file mode 100644 index 0000000..faa5c1b --- /dev/null +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.c @@ -0,0 +1,852 @@ +#include +#include +#include +#include +#include +#include +#include +#include "hyper_dmabuf_struct.h" +#include "hyper_dmabuf_imp.h" +#include "xen/hyper_dmabuf_xen_comm.h" +#include "hyper_dmabuf_msg.h" + +#define REFS_PER_PAGE (PAGE_SIZE/sizeof(grant_ref_t)) + +/* return total number of pages referecned by a sgt + * for pre-calculation of # of pages behind a given sgt + */ +static int hyper_dmabuf_get_num_pgs(struct sg_table *sgt) +{ + struct scatterlist *sgl; + int length, i; + /* at least one page */ + int num_pages = 1; + + sgl = sgt->sgl; + + length = sgl->length - PAGE_SIZE + sgl->offset; + num_pages += ((length + PAGE_SIZE - 1)/PAGE_SIZE); /* round-up */ + + for (i = 1; i < sgt->nents; i++) { + sgl = sg_next(sgl); + num_pages += ((sgl->length + PAGE_SIZE - 1) / PAGE_SIZE); /* round-up */ + } + + return num_pages; +} + +/* extract pages directly from struct sg_table */ +struct hyper_dmabuf_pages_info *hyper_dmabuf_ext_pgs(struct sg_table *sgt) +{ + struct hyper_dmabuf_pages_info *pinfo; + int i, j; + int length; + struct scatterlist *sgl; + + pinfo = kmalloc(sizeof(*pinfo), GFP_KERNEL); + if (pinfo == NULL) + return NULL; + + pinfo->pages = kmalloc(sizeof(struct page *)*hyper_dmabuf_get_num_pgs(sgt), GFP_KERNEL); + if (pinfo->pages == NULL) + return NULL; + + sgl = sgt->sgl; + + pinfo->nents = 1; + pinfo->frst_ofst = sgl->offset; + pinfo->pages[0] = sg_page(sgl); + length = sgl->length - PAGE_SIZE + sgl->offset; + i=1; + + while (length > 0) { + pinfo->pages[i] = nth_page(sg_page(sgl), i); + length -= PAGE_SIZE; + pinfo->nents++; + i++; + } + + for (j = 1; j < sgt->nents; j++) { + sgl = sg_next(sgl); + pinfo->pages[i++] = sg_page(sgl); + length = sgl->length - PAGE_SIZE; + pinfo->nents++; + + while (length > 0) { + pinfo->pages[i] = nth_page(sg_page(sgl), i); + length -= PAGE_SIZE; + pinfo->nents++; + i++; + } + } + + /* + * lenght at that point will be 0 or negative, + * so to calculate last page size just add it to PAGE_SIZE + */ + pinfo->last_len = PAGE_SIZE + length; + + return pinfo; +} + +/* create sg_table with given pages and other parameters */ +struct sg_table* hyper_dmabuf_create_sgt(struct page **pages, + int frst_ofst, int last_len, int nents) +{ + struct sg_table *sgt; + struct scatterlist *sgl; + int i, ret; + + sgt = kmalloc(sizeof(struct sg_table), GFP_KERNEL); + if (sgt == NULL) { + return NULL; + } + + ret = sg_alloc_table(sgt, nents, GFP_KERNEL); + if (ret) { + kfree(sgt); + return NULL; + } + + sgl = sgt->sgl; + + sg_set_page(sgl, pages[0], PAGE_SIZE-frst_ofst, frst_ofst); + + for (i=1; i 1) /* more than one page */ { + sgl = sg_next(sgl); + sg_set_page(sgl, pages[i], last_len, 0); + } + + return sgt; +} + +/* + * Creates 2 level page directory structure for referencing shared pages. + * Top level page is a single page that contains up to 1024 refids that + * point to 2nd level pages. + * Each 2nd level page contains up to 1024 refids that point to shared + * data pages. + * There will always be one top level page and number of 2nd level pages + * depends on number of shared data pages. + * + * Top level page 2nd level pages Data pages + * +-------------------------+ ┌>+--------------------+ ┌--->+------------+ + * |2nd level page 0 refid |---┘ |Data page 0 refid |-┘ |Data page 0 | + * |2nd level page 1 refid |---┐ |Data page 1 refid |-┐ +------------+ + * | ... | | | .... | | + * |2nd level page 1023 refid|-┐ | |Data page 1023 refid| └--->+------------+ + * +-------------------------+ | | +--------------------+ |Data page 1 | + * | | +------------+ + * | └>+--------------------+ + * | |Data page 1024 refid| + * | |Data page 1025 refid| + * | | ... | + * | |Data page 2047 refid| + * | +--------------------+ + * | + * | ..... + * └-->+-----------------------+ + * |Data page 1047552 refid| + * |Data page 1047553 refid| + * | ... | + * |Data page 1048575 refid|-->+------------------+ + * +-----------------------+ |Data page 1048575 | + * +------------------+ + * + * Using such 2 level structure it is possible to reference up to 4GB of + * shared data using single refid pointing to top level page. + * + * Returns refid of top level page. + */ +grant_ref_t hyper_dmabuf_create_addressing_tables(grant_ref_t *data_refs, int nents, int rdomain, + struct hyper_dmabuf_shared_pages_info *shared_pages_info) +{ + /* + * Calculate number of pages needed for 2nd level addresing: + */ + int n_2nd_level_pages = (nents/REFS_PER_PAGE + ((nents % REFS_PER_PAGE) ? 1: 0));/* rounding */ + int i; + unsigned long gref_page_start; + grant_ref_t *tmp_page; + grant_ref_t top_level_ref; + grant_ref_t * addr_refs; + addr_refs = kcalloc(sizeof(grant_ref_t), n_2nd_level_pages, GFP_KERNEL); + + gref_page_start = __get_free_pages(GFP_KERNEL, n_2nd_level_pages); + tmp_page = (grant_ref_t *)gref_page_start; + + /* Store 2nd level pages to be freed later */ + shared_pages_info->addr_pages = tmp_page; + + /*TODO: make sure that allocated memory is filled with 0*/ + + /* Share 2nd level addressing pages in readonly mode*/ + for (i=0; i< n_2nd_level_pages; i++) { + addr_refs[i] = gnttab_grant_foreign_access(rdomain, virt_to_mfn((unsigned long)tmp_page+i*PAGE_SIZE ), 1); + } + + /* + * fill second level pages with data refs + */ + for (i = 0; i < nents; i++) { + tmp_page[i] = data_refs[i]; + } + + + /* allocate top level page */ + gref_page_start = __get_free_pages(GFP_KERNEL, 1); + tmp_page = (grant_ref_t *)gref_page_start; + + /* Store top level page to be freed later */ + shared_pages_info->top_level_page = tmp_page; + + /* + * fill top level page with reference numbers of second level pages refs. + */ + for (i=0; i< n_2nd_level_pages; i++) { + tmp_page[i] = addr_refs[i]; + } + + /* Share top level addressing page in readonly mode*/ + top_level_ref = gnttab_grant_foreign_access(rdomain, virt_to_mfn((unsigned long)tmp_page), 1); + + kfree(addr_refs); + + return top_level_ref; +} + +/* + * Maps provided top level ref id and then return array of pages containing data refs. + */ +struct page** hyper_dmabuf_get_data_refs(grant_ref_t top_level_ref, int domid, int nents, + struct hyper_dmabuf_shared_pages_info *shared_pages_info) +{ + struct page *top_level_page; + struct page **level2_pages; + + grant_ref_t *top_level_refs; + + struct gnttab_map_grant_ref top_level_map_ops; + struct gnttab_unmap_grant_ref top_level_unmap_ops; + + struct gnttab_map_grant_ref *map_ops; + struct gnttab_unmap_grant_ref *unmap_ops; + + unsigned long addr; + int n_level2_refs = 0; + int i; + + n_level2_refs = (nents / REFS_PER_PAGE) + ((nents % REFS_PER_PAGE) ? 1 : 0); + + level2_pages = kcalloc(sizeof(struct page*), n_level2_refs, GFP_KERNEL); + + map_ops = kcalloc(sizeof(map_ops[0]), REFS_PER_PAGE, GFP_KERNEL); + unmap_ops = kcalloc(sizeof(unmap_ops[0]), REFS_PER_PAGE, GFP_KERNEL); + + /* Map top level addressing page */ + if (gnttab_alloc_pages(1, &top_level_page)) { + printk("Cannot allocate pages\n"); + return NULL; + } + + addr = (unsigned long)pfn_to_kaddr(page_to_pfn(top_level_page)); + gnttab_set_map_op(&top_level_map_ops, addr, GNTMAP_host_map | GNTMAP_readonly, top_level_ref, domid); + gnttab_set_unmap_op(&top_level_unmap_ops, addr, GNTMAP_host_map | GNTMAP_readonly, -1); + + if (gnttab_map_refs(&top_level_map_ops, NULL, &top_level_page, 1)) { + printk("\nxen: dom0: HYPERVISOR map grant ref failed"); + return NULL; + } + + if (top_level_map_ops.status) { + printk("\nxen: dom0: HYPERVISOR map grant ref failed status = %d", + top_level_map_ops.status); + return NULL; + } else { + top_level_unmap_ops.handle = top_level_map_ops.handle; + } + + /* Parse contents of top level addressing page to find how many second level pages is there*/ + top_level_refs = pfn_to_kaddr(page_to_pfn(top_level_page)); + + /* Map all second level pages */ + if (gnttab_alloc_pages(n_level2_refs, level2_pages)) { + printk("Cannot allocate pages\n"); + return NULL; + } + + for (i = 0; i < n_level2_refs; i++) { + addr = (unsigned long)pfn_to_kaddr(page_to_pfn(level2_pages[i])); + gnttab_set_map_op(&map_ops[i], addr, GNTMAP_host_map | GNTMAP_readonly, top_level_refs[i], domid); + gnttab_set_unmap_op(&unmap_ops[i], addr, GNTMAP_host_map | GNTMAP_readonly, -1); + } + + if (gnttab_map_refs(map_ops, NULL, level2_pages, n_level2_refs)) { + printk("\nxen: dom0: HYPERVISOR map grant ref failed"); + return NULL; + } + + /* Checks if pages were mapped correctly and at the same time is calculating total number of data refids*/ + for (i = 0; i < n_level2_refs; i++) { + if (map_ops[i].status) { + printk("\nxen: dom0: HYPERVISOR map grant ref failed status = %d", + map_ops[i].status); + return NULL; + } else { + unmap_ops[i].handle = map_ops[i].handle; + } + } + + /* Unmap top level page, as it won't be needed any longer */ + if (gnttab_unmap_refs(&top_level_unmap_ops, NULL, &top_level_page, 1)) { + printk("\xen: cannot unmap top level page\n"); + return NULL; + } + + gnttab_free_pages(1, &top_level_page); + kfree(map_ops); + shared_pages_info->unmap_ops = unmap_ops; + + return level2_pages; +} + + +/* This collects all reference numbers for 2nd level shared pages and create a table + * with those in 1st level shared pages then return reference numbers for this top level + * table. */ +grant_ref_t hyper_dmabuf_create_gref_table(struct page **pages, int rdomain, int nents, + struct hyper_dmabuf_shared_pages_info *shared_pages_info) +{ + int i = 0; + grant_ref_t *data_refs; + grant_ref_t top_level_ref; + + /* allocate temp array for refs of shared data pages */ + data_refs = kcalloc(nents, sizeof(grant_ref_t), GFP_KERNEL); + + /* share data pages in rw mode*/ + for (i=0; idata_refs = data_refs; + shared_pages_info->top_level_ref = top_level_ref; + + return top_level_ref; +} + +int hyper_dmabuf_cleanup_gref_table(struct hyper_dmabuf_sgt_info *sgt_info) { + uint32_t i = 0; + struct hyper_dmabuf_shared_pages_info *shared_pages_info = &sgt_info->shared_pages_info; + + grant_ref_t *ref = shared_pages_info->top_level_page; + int n_2nd_level_pages = (sgt_info->sgt->nents/REFS_PER_PAGE + ((sgt_info->sgt->nents % REFS_PER_PAGE) ? 1: 0));/* rounding */ + + + if (shared_pages_info->data_refs == NULL || + shared_pages_info->addr_pages == NULL || + shared_pages_info->top_level_page == NULL || + shared_pages_info->top_level_ref == -1) { + printk("gref table for hyper_dmabuf already cleaned up\n"); + return 0; + } + + /* End foreign access for 2nd level addressing pages */ + while(ref[i] != 0 && i < n_2nd_level_pages) { + if (gnttab_query_foreign_access(ref[i])) { + printk("refid not shared !!\n"); + } + if (!gnttab_end_foreign_access_ref(ref[i], 1)) { + printk("refid still in use!!!\n"); + } + i++; + } + free_pages((unsigned long)shared_pages_info->addr_pages, i); + + /* End foreign access for top level addressing page */ + if (gnttab_query_foreign_access(shared_pages_info->top_level_ref)) { + printk("refid not shared !!\n"); + } + if (!gnttab_end_foreign_access_ref(shared_pages_info->top_level_ref, 1)) { + printk("refid still in use!!!\n"); + } + gnttab_end_foreign_access_ref(shared_pages_info->top_level_ref, 1); + free_pages((unsigned long)shared_pages_info->top_level_page, 1); + + /* End foreign access for data pages, but do not free them */ + for (i = 0; i < sgt_info->sgt->nents; i++) { + if (gnttab_query_foreign_access(shared_pages_info->data_refs[i])) { + printk("refid not shared !!\n"); + } + gnttab_end_foreign_access_ref(shared_pages_info->data_refs[i], 0); + } + + kfree(shared_pages_info->data_refs); + + shared_pages_info->data_refs = NULL; + shared_pages_info->addr_pages = NULL; + shared_pages_info->top_level_page = NULL; + shared_pages_info->top_level_ref = -1; + + return 0; +} + +int hyper_dmabuf_cleanup_imported_pages(struct hyper_dmabuf_imported_sgt_info *sgt_info) { + struct hyper_dmabuf_shared_pages_info *shared_pages_info = &sgt_info->shared_pages_info; + + if(shared_pages_info->unmap_ops == NULL || shared_pages_info->data_pages == NULL) { + printk("Imported pages already cleaned up or buffer was not imported yet\n"); + return 0; + } + + if (gnttab_unmap_refs(shared_pages_info->unmap_ops, NULL, shared_pages_info->data_pages, sgt_info->nents) ) { + printk("Cannot unmap data pages\n"); + return -EINVAL; + } + + gnttab_free_pages(sgt_info->nents, shared_pages_info->data_pages); + kfree(shared_pages_info->data_pages); + kfree(shared_pages_info->unmap_ops); + shared_pages_info->unmap_ops = NULL; + shared_pages_info->data_pages = NULL; + + return 0; +} + +/* map and construct sg_lists from reference numbers */ +struct sg_table* hyper_dmabuf_map_pages(grant_ref_t top_level_gref, int frst_ofst, int last_len, int nents, int sdomain, + struct hyper_dmabuf_shared_pages_info *shared_pages_info) +{ + struct sg_table *st; + struct page **pages; + struct gnttab_map_grant_ref *ops; + struct gnttab_unmap_grant_ref *unmap_ops; + unsigned long addr; + grant_ref_t *refs; + int i; + int n_level2_refs = (nents / REFS_PER_PAGE) + ((nents % REFS_PER_PAGE) ? 1 : 0); + + /* Get data refids */ + struct page** refid_pages = hyper_dmabuf_get_data_refs(top_level_gref, sdomain, nents, + shared_pages_info); + + pages = kcalloc(sizeof(struct page*), nents, GFP_KERNEL); + if (pages == NULL) { + return NULL; + } + + /* allocate new pages that are mapped to shared pages via grant-table */ + if (gnttab_alloc_pages(nents, pages)) { + printk("Cannot allocate pages\n"); + return NULL; + } + + ops = (struct gnttab_map_grant_ref *)kcalloc(nents, sizeof(struct gnttab_map_grant_ref), GFP_KERNEL); + unmap_ops = (struct gnttab_unmap_grant_ref *)kcalloc(nents, sizeof(struct gnttab_unmap_grant_ref), GFP_KERNEL); + + for (i=0; iunmap_ops, NULL, refid_pages, n_level2_refs) ) { + printk("Cannot unmap 2nd level refs\n"); + return NULL; + } + + gnttab_free_pages(n_level2_refs, refid_pages); + kfree(refid_pages); + + kfree(shared_pages_info->unmap_ops); + shared_pages_info->unmap_ops = unmap_ops; + shared_pages_info->data_pages = pages; + kfree(ops); + + return st; +} + +inline int hyper_dmabuf_sync_request_and_wait(int id, int ops) +{ + struct hyper_dmabuf_ring_rq *req; + int operands[2]; + int ret; + + operands[0] = id; + operands[1] = ops; + + req = kcalloc(1, sizeof(*req), GFP_KERNEL); + + hyper_dmabuf_create_request(req, HYPER_DMABUF_OPS_TO_SOURCE, &operands[0]); + + /* send request */ + ret = hyper_dmabuf_send_request(id, req); + + /* TODO: wait until it gets response.. or can we just move on? */ + + kfree(req); + + return ret; +} + +static int hyper_dmabuf_ops_attach(struct dma_buf* dmabuf, struct device* dev, + struct dma_buf_attachment *attach) +{ + struct hyper_dmabuf_imported_sgt_info *sgt_info; + int ret; + + if (!attach->dmabuf->priv) + return -EINVAL; + + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)attach->dmabuf->priv; + + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), + HYPER_DMABUF_OPS_ATTACH); + + if (ret < 0) { + printk("send dmabuf sync request failed\n"); + } + + return ret; +} + +static void hyper_dmabuf_ops_detach(struct dma_buf* dmabuf, struct dma_buf_attachment *attach) +{ + struct hyper_dmabuf_imported_sgt_info *sgt_info; + int ret; + + if (!attach->dmabuf->priv) + return; + + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)attach->dmabuf->priv; + + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), + HYPER_DMABUF_OPS_DETACH); + + if (ret < 0) { + printk("send dmabuf sync request failed\n"); + } +} + +static struct sg_table* hyper_dmabuf_ops_map(struct dma_buf_attachment *attachment, + enum dma_data_direction dir) +{ + struct sg_table *st; + struct hyper_dmabuf_imported_sgt_info *sgt_info; + struct hyper_dmabuf_pages_info *page_info; + int ret; + + if (!attachment->dmabuf->priv) + return NULL; + + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)attachment->dmabuf->priv; + + /* extract pages from sgt */ + page_info = hyper_dmabuf_ext_pgs(sgt_info->sgt); + + /* create a new sg_table with extracted pages */ + st = hyper_dmabuf_create_sgt(page_info->pages, page_info->frst_ofst, + page_info->last_len, page_info->nents); + if (st == NULL) + goto err_free_sg; + + if (!dma_map_sg(attachment->dev, st->sgl, st->nents, dir)) { + goto err_free_sg; + } + + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), + HYPER_DMABUF_OPS_MAP); + + if (ret < 0) { + printk("send dmabuf sync request failed\n"); + } + + return st; + +err_free_sg: + sg_free_table(st); + kfree(st); + return NULL; +} + +static void hyper_dmabuf_ops_unmap(struct dma_buf_attachment *attachment, + struct sg_table *sg, + enum dma_data_direction dir) +{ + struct hyper_dmabuf_imported_sgt_info *sgt_info; + int ret; + + if (!attachment->dmabuf->priv) + return; + + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)attachment->dmabuf->priv; + + dma_unmap_sg(attachment->dev, sg->sgl, sg->nents, dir); + + sg_free_table(sg); + kfree(sg); + + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), + HYPER_DMABUF_OPS_UNMAP); + + if (ret < 0) { + printk("send dmabuf sync request failed\n"); + } +} + +static void hyper_dmabuf_ops_release(struct dma_buf *dmabuf) +{ + struct hyper_dmabuf_imported_sgt_info *sgt_info; + int ret; + + if (!dmabuf->priv) + return; + + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv; + + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), + HYPER_DMABUF_OPS_RELEASE); + + if (ret < 0) { + printk("send dmabuf sync request failed\n"); + } +} + +static int hyper_dmabuf_ops_begin_cpu_access(struct dma_buf *dmabuf, enum dma_data_direction dir) +{ + struct hyper_dmabuf_imported_sgt_info *sgt_info; + int ret; + + if (!dmabuf->priv) + return -EINVAL; + + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv; + + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), + HYPER_DMABUF_OPS_BEGIN_CPU_ACCESS); + if (ret < 0) { + printk("send dmabuf sync request failed\n"); + } + + return ret; +} + +static int hyper_dmabuf_ops_end_cpu_access(struct dma_buf *dmabuf, enum dma_data_direction dir) +{ + struct hyper_dmabuf_imported_sgt_info *sgt_info; + int ret; + + if (!dmabuf->priv) + return -EINVAL; + + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv; + + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), + HYPER_DMABUF_OPS_END_CPU_ACCESS); + if (ret < 0) { + printk("send dmabuf sync request failed\n"); + } + + return 0; +} + +static void *hyper_dmabuf_ops_kmap_atomic(struct dma_buf *dmabuf, unsigned long pgnum) +{ + struct hyper_dmabuf_imported_sgt_info *sgt_info; + int ret; + + if (!dmabuf->priv) + return NULL; + + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv; + + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), + HYPER_DMABUF_OPS_KMAP_ATOMIC); + if (ret < 0) { + printk("send dmabuf sync request failed\n"); + } + + return NULL; /* for now NULL.. need to return the address of mapped region */ +} + +static void hyper_dmabuf_ops_kunmap_atomic(struct dma_buf *dmabuf, unsigned long pgnum, void *vaddr) +{ + struct hyper_dmabuf_imported_sgt_info *sgt_info; + int ret; + + if (!dmabuf->priv) + return; + + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv; + + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), + HYPER_DMABUF_OPS_KUNMAP_ATOMIC); + if (ret < 0) { + printk("send dmabuf sync request failed\n"); + } +} + +static void *hyper_dmabuf_ops_kmap(struct dma_buf *dmabuf, unsigned long pgnum) +{ + struct hyper_dmabuf_imported_sgt_info *sgt_info; + int ret; + + if (!dmabuf->priv) + return NULL; + + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv; + + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), + HYPER_DMABUF_OPS_KMAP); + if (ret < 0) { + printk("send dmabuf sync request failed\n"); + } + + return NULL; /* for now NULL.. need to return the address of mapped region */ +} + +static void hyper_dmabuf_ops_kunmap(struct dma_buf *dmabuf, unsigned long pgnum, void *vaddr) +{ + struct hyper_dmabuf_imported_sgt_info *sgt_info; + int ret; + + if (!dmabuf->priv) + return; + + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv; + + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), + HYPER_DMABUF_OPS_KUNMAP); + if (ret < 0) { + printk("send dmabuf sync request failed\n"); + } +} + +static int hyper_dmabuf_ops_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) +{ + struct hyper_dmabuf_imported_sgt_info *sgt_info; + int ret; + + if (!dmabuf->priv) + return -EINVAL; + + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv; + + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), + HYPER_DMABUF_OPS_MMAP); + if (ret < 0) { + printk("send dmabuf sync request failed\n"); + } + + return ret; +} + +static void *hyper_dmabuf_ops_vmap(struct dma_buf *dmabuf) +{ + struct hyper_dmabuf_imported_sgt_info *sgt_info; + int ret; + + if (!dmabuf->priv) + return NULL; + + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv; + + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), + HYPER_DMABUF_OPS_VMAP); + if (ret < 0) { + printk("send dmabuf sync request failed\n"); + } + + return NULL; +} + +static void hyper_dmabuf_ops_vunmap(struct dma_buf *dmabuf, void *vaddr) +{ + struct hyper_dmabuf_imported_sgt_info *sgt_info; + int ret; + + if (!dmabuf->priv) + return; + + sgt_info = (struct hyper_dmabuf_imported_sgt_info *)dmabuf->priv; + + ret = hyper_dmabuf_sync_request_and_wait(HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(sgt_info->hyper_dmabuf_id), + HYPER_DMABUF_OPS_VUNMAP); + if (ret < 0) { + printk("send dmabuf sync request failed\n"); + } +} + +static const struct dma_buf_ops hyper_dmabuf_ops = { + .attach = hyper_dmabuf_ops_attach, + .detach = hyper_dmabuf_ops_detach, + .map_dma_buf = hyper_dmabuf_ops_map, + .unmap_dma_buf = hyper_dmabuf_ops_unmap, + .release = hyper_dmabuf_ops_release, + .begin_cpu_access = (void*)hyper_dmabuf_ops_begin_cpu_access, + .end_cpu_access = (void*)hyper_dmabuf_ops_end_cpu_access, + .map_atomic = hyper_dmabuf_ops_kmap_atomic, + .unmap_atomic = hyper_dmabuf_ops_kunmap_atomic, + .map = hyper_dmabuf_ops_kmap, + .unmap = hyper_dmabuf_ops_kunmap, + .mmap = hyper_dmabuf_ops_mmap, + .vmap = hyper_dmabuf_ops_vmap, + .vunmap = hyper_dmabuf_ops_vunmap, +}; + +/* exporting dmabuf as fd */ +int hyper_dmabuf_export_fd(struct hyper_dmabuf_imported_sgt_info *dinfo, int flags) +{ + int fd; + + struct dma_buf* dmabuf; + +/* call hyper_dmabuf_export_dmabuf and create and bind a handle for it + * then release */ + + dmabuf = hyper_dmabuf_export_dma_buf(dinfo); + + fd = dma_buf_fd(dmabuf, flags); + + return fd; +} + +struct dma_buf* hyper_dmabuf_export_dma_buf(struct hyper_dmabuf_imported_sgt_info *dinfo) +{ + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + + exp_info.ops = &hyper_dmabuf_ops; + exp_info.size = dinfo->sgt->nents * PAGE_SIZE; /* multiple of PAGE_SIZE, not considering offset */ + exp_info.flags = /* not sure about flag */0; + exp_info.priv = dinfo; + + return dma_buf_export(&exp_info); +}; diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h new file mode 100644 index 0000000..003c158 --- /dev/null +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_imp.h @@ -0,0 +1,31 @@ +#ifndef __HYPER_DMABUF_IMP_H__ +#define __HYPER_DMABUF_IMP_H__ + +#include "hyper_dmabuf_struct.h" + +/* extract pages directly from struct sg_table */ +struct hyper_dmabuf_pages_info *hyper_dmabuf_ext_pgs(struct sg_table *sgt); + +/* create sg_table with given pages and other parameters */ +struct sg_table* hyper_dmabuf_create_sgt(struct page **pages, + int frst_ofst, int last_len, int nents); + +grant_ref_t hyper_dmabuf_create_gref_table(struct page **pages, int rdomain, int nents, + struct hyper_dmabuf_shared_pages_info *shared_pages_info); + +int hyper_dmabuf_cleanup_gref_table(struct hyper_dmabuf_sgt_info *sgt_info); + +int hyper_dmabuf_cleanup_imported_pages(struct hyper_dmabuf_imported_sgt_info *sgt_info); + +/* map first level tables that contains reference numbers for actual shared pages */ +grant_ref_t *hyper_dmabuf_map_gref_table(grant_ref_t *gref_table, int n_pages_table); + +/* map and construct sg_lists from reference numbers */ +struct sg_table* hyper_dmabuf_map_pages(grant_ref_t gref, int frst_ofst, int last_len, int nents, int sdomain, + struct hyper_dmabuf_shared_pages_info *shared_pages_info); + +int hyper_dmabuf_export_fd(struct hyper_dmabuf_imported_sgt_info *dinfo, int flags); + +struct dma_buf* hyper_dmabuf_export_dma_buf(struct hyper_dmabuf_imported_sgt_info *dinfo); + +#endif /* __HYPER_DMABUF_IMP_H__ */ diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c new file mode 100644 index 0000000..5e50908 --- /dev/null +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_ioctl.c @@ -0,0 +1,462 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "hyper_dmabuf_struct.h" +#include "hyper_dmabuf_imp.h" +#include "hyper_dmabuf_list.h" +#include "hyper_dmabuf_drv.h" +#include "hyper_dmabuf_query.h" +#include "xen/hyper_dmabuf_xen_comm.h" +#include "hyper_dmabuf_msg.h" + +struct hyper_dmabuf_private { + struct device *device; +} hyper_dmabuf_private; + +static uint32_t hyper_dmabuf_id_gen(void) { + /* TODO: add proper implementation */ + static uint32_t id = 0; + static int32_t domid = -1; + if (domid == -1) { + domid = hyper_dmabuf_get_domid(); + } + return HYPER_DMABUF_ID_IMPORTER(domid, id++); +} + +static int hyper_dmabuf_exporter_ring_setup(void *data) +{ + struct ioctl_hyper_dmabuf_exporter_ring_setup *ring_attr; + int ret = 0; + + if (!data) { + printk("user data is NULL\n"); + return -1; + } + ring_attr = (struct ioctl_hyper_dmabuf_exporter_ring_setup *)data; + + ret = hyper_dmabuf_exporter_ringbuf_init(ring_attr->remote_domain, + &ring_attr->ring_refid, + &ring_attr->port); + + return ret; +} + +static int hyper_dmabuf_importer_ring_setup(void *data) +{ + struct ioctl_hyper_dmabuf_importer_ring_setup *setup_imp_ring_attr; + int ret = 0; + + if (!data) { + printk("user data is NULL\n"); + return -1; + } + + setup_imp_ring_attr = (struct ioctl_hyper_dmabuf_importer_ring_setup *)data; + + /* user need to provide a port number and ref # for the page used as ring buffer */ + ret = hyper_dmabuf_importer_ringbuf_init(setup_imp_ring_attr->source_domain, + setup_imp_ring_attr->ring_refid, + setup_imp_ring_attr->port); + + return ret; +} + +static int hyper_dmabuf_export_remote(void *data) +{ + struct ioctl_hyper_dmabuf_export_remote *export_remote_attr; + struct dma_buf *dma_buf; + struct dma_buf_attachment *attachment; + struct sg_table *sgt; + struct hyper_dmabuf_pages_info *page_info; + struct hyper_dmabuf_sgt_info *sgt_info; + struct hyper_dmabuf_ring_rq *req; + int operands[9]; + int ret = 0; + + if (!data) { + printk("user data is NULL\n"); + return -1; + } + + export_remote_attr = (struct ioctl_hyper_dmabuf_export_remote *)data; + + dma_buf = dma_buf_get(export_remote_attr->dmabuf_fd); + if (!dma_buf) { + printk("Cannot get dma buf\n"); + return -1; + } + + attachment = dma_buf_attach(dma_buf, hyper_dmabuf_private.device); + if (!attachment) { + printk("Cannot get attachment\n"); + return -1; + } + + /* we check if this specific attachment was already exported + * to the same domain and if yes, it returns hyper_dmabuf_id + * of pre-exported sgt */ + ret = hyper_dmabuf_find_id(attachment, export_remote_attr->remote_domain); + if (ret != -1) { + dma_buf_detach(dma_buf, attachment); + dma_buf_put(dma_buf); + export_remote_attr->hyper_dmabuf_id = ret; + return 0; + } + /* Clear ret, as that will cause whole ioctl to return failure to userspace, which is not true */ + ret = 0; + + sgt = dma_buf_map_attachment(attachment, DMA_BIDIRECTIONAL); + + sgt_info = kmalloc(sizeof(*sgt_info), GFP_KERNEL); + + sgt_info->hyper_dmabuf_id = hyper_dmabuf_id_gen(); + /* TODO: We might need to consider using port number on event channel? */ + sgt_info->hyper_dmabuf_rdomain = export_remote_attr->remote_domain; + sgt_info->sgt = sgt; + sgt_info->attachment = attachment; + sgt_info->dma_buf = dma_buf; + + page_info = hyper_dmabuf_ext_pgs(sgt); + if (page_info == NULL) + goto fail_export; + + /* now register it to export list */ + hyper_dmabuf_register_exported(sgt_info); + + page_info->hyper_dmabuf_rdomain = sgt_info->hyper_dmabuf_rdomain; + page_info->hyper_dmabuf_id = sgt_info->hyper_dmabuf_id; /* may not be needed */ + + export_remote_attr->hyper_dmabuf_id = sgt_info->hyper_dmabuf_id; + + /* now create table of grefs for shared pages and */ + + /* now create request for importer via ring */ + operands[0] = page_info->hyper_dmabuf_id; + operands[1] = page_info->nents; + operands[2] = page_info->frst_ofst; + operands[3] = page_info->last_len; + operands[4] = hyper_dmabuf_create_gref_table(page_info->pages, export_remote_attr->remote_domain, + page_info->nents, &sgt_info->shared_pages_info); + /* driver/application specific private info, max 32 bytes */ + operands[5] = export_remote_attr->private[0]; + operands[6] = export_remote_attr->private[1]; + operands[7] = export_remote_attr->private[2]; + operands[8] = export_remote_attr->private[3]; + + req = kcalloc(1, sizeof(*req), GFP_KERNEL); + + /* composing a message to the importer */ + hyper_dmabuf_create_request(req, HYPER_DMABUF_EXPORT, &operands[0]); + if(hyper_dmabuf_send_request(export_remote_attr->remote_domain, req)) + goto fail_send_request; + + /* free msg */ + kfree(req); + /* free page_info */ + kfree(page_info); + + return ret; + +fail_send_request: + kfree(req); + hyper_dmabuf_remove_exported(sgt_info->hyper_dmabuf_id); + +fail_export: + dma_buf_unmap_attachment(sgt_info->attachment, sgt_info->sgt, DMA_BIDIRECTIONAL); + dma_buf_detach(sgt_info->dma_buf, sgt_info->attachment); + dma_buf_put(sgt_info->dma_buf); + + return -EINVAL; +} + +static int hyper_dmabuf_export_fd_ioctl(void *data) +{ + struct ioctl_hyper_dmabuf_export_fd *export_fd_attr; + struct hyper_dmabuf_imported_sgt_info *imported_sgt_info; + int ret = 0; + + if (!data) { + printk("user data is NULL\n"); + return -1; + } + + export_fd_attr = (struct ioctl_hyper_dmabuf_export_fd *)data; + + /* look for dmabuf for the id */ + imported_sgt_info = hyper_dmabuf_find_imported(export_fd_attr->hyper_dmabuf_id); + if (imported_sgt_info == NULL) /* can't find sgt from the table */ + return -1; + + printk("%s Found buffer gref %d off %d last len %d nents %d domain %d\n", __func__, + imported_sgt_info->gref, imported_sgt_info->frst_ofst, + imported_sgt_info->last_len, imported_sgt_info->nents, + HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(imported_sgt_info->hyper_dmabuf_id)); + + imported_sgt_info->sgt = hyper_dmabuf_map_pages(imported_sgt_info->gref, + imported_sgt_info->frst_ofst, + imported_sgt_info->last_len, + imported_sgt_info->nents, + HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(imported_sgt_info->hyper_dmabuf_id), + &imported_sgt_info->shared_pages_info); + + if (!imported_sgt_info->sgt) { + return -1; + } + + export_fd_attr->fd = hyper_dmabuf_export_fd(imported_sgt_info, export_fd_attr->flags); + if (export_fd_attr < 0) { + ret = export_fd_attr->fd; + } + + return ret; +} + +/* removing dmabuf from the database and send int req to the source domain +* to unmap it. */ +static int hyper_dmabuf_destroy(void *data) +{ + struct ioctl_hyper_dmabuf_destroy *destroy_attr; + struct hyper_dmabuf_sgt_info *sgt_info; + struct hyper_dmabuf_ring_rq *req; + int ret; + + if (!data) { + printk("user data is NULL\n"); + return -EINVAL; + } + + destroy_attr = (struct ioctl_hyper_dmabuf_destroy *)data; + + /* find dmabuf in export list */ + sgt_info = hyper_dmabuf_find_exported(destroy_attr->hyper_dmabuf_id); + if (sgt_info == NULL) { /* failed to find corresponding entry in export list */ + destroy_attr->status = -EINVAL; + return -EFAULT; + } + + req = kcalloc(1, sizeof(*req), GFP_KERNEL); + + hyper_dmabuf_create_request(req, HYPER_DMABUF_DESTROY, &destroy_attr->hyper_dmabuf_id); + + /* now send destroy request to remote domain + * currently assuming there's only one importer exist */ + ret = hyper_dmabuf_send_request(sgt_info->hyper_dmabuf_rdomain, req); + if (ret < 0) { + kfree(req); + return -EFAULT; + } + + /* free msg */ + kfree(req); + destroy_attr->status = ret; + + /* Rest of cleanup will follow when importer will free it's buffer, + * current implementation assumes that there is only one importer + */ + + return ret; +} + +static int hyper_dmabuf_query(void *data) +{ + struct ioctl_hyper_dmabuf_query *query_attr; + struct hyper_dmabuf_sgt_info *sgt_info; + struct hyper_dmabuf_imported_sgt_info *imported_sgt_info; + int ret = 0; + + if (!data) { + printk("user data is NULL\n"); + return -EINVAL; + } + + query_attr = (struct ioctl_hyper_dmabuf_query *)data; + + sgt_info = hyper_dmabuf_find_exported(query_attr->hyper_dmabuf_id); + imported_sgt_info = hyper_dmabuf_find_imported(query_attr->hyper_dmabuf_id); + + /* if dmabuf can't be found in both lists, return */ + if (!(sgt_info && imported_sgt_info)) { + printk("can't find entry anywhere\n"); + return -EINVAL; + } + + /* not considering the case where a dmabuf is found on both queues + * in one domain */ + switch (query_attr->item) + { + case DMABUF_QUERY_TYPE_LIST: + if (sgt_info) { + query_attr->info = EXPORTED; + } else { + query_attr->info = IMPORTED; + } + break; + + /* exporting domain of this specific dmabuf*/ + case DMABUF_QUERY_EXPORTER: + if (sgt_info) { + query_attr->info = 0xFFFFFFFF; /* myself */ + } else { + query_attr->info = (HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(imported_sgt_info->hyper_dmabuf_id)); + } + break; + + /* importing domain of this specific dmabuf */ + case DMABUF_QUERY_IMPORTER: + if (sgt_info) { + query_attr->info = sgt_info->hyper_dmabuf_rdomain; + } else { +#if 0 /* TODO: a global variable, current_domain does not exist yet*/ + query_attr->info = current_domain; +#endif + } + break; + + /* size of dmabuf in byte */ + case DMABUF_QUERY_SIZE: + if (sgt_info) { +#if 0 /* TODO: hyper_dmabuf_buf_size is not implemented yet */ + query_attr->info = hyper_dmabuf_buf_size(sgt_info->sgt); +#endif + } else { + query_attr->info = imported_sgt_info->nents * 4096 - + imported_sgt_info->frst_ofst - 4096 + + imported_sgt_info->last_len; + } + break; + } + + return ret; +} + +static int hyper_dmabuf_remote_exporter_ring_setup(void *data) +{ + struct ioctl_hyper_dmabuf_remote_exporter_ring_setup *remote_exporter_ring_setup; + struct hyper_dmabuf_ring_rq *req; + + remote_exporter_ring_setup = (struct ioctl_hyper_dmabuf_remote_exporter_ring_setup *)data; + + req = kcalloc(1, sizeof(*req), GFP_KERNEL); + hyper_dmabuf_create_request(req, HYPER_DMABUF_EXPORTER_RING_SETUP, NULL); + + /* requesting remote domain to set-up exporter's ring */ + if(hyper_dmabuf_send_request(remote_exporter_ring_setup->rdomain, req) < 0) { + kfree(req); + return -EINVAL; + } + + kfree(req); + return 0; +} + +static const struct hyper_dmabuf_ioctl_desc hyper_dmabuf_ioctls[] = { + HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_EXPORTER_RING_SETUP, hyper_dmabuf_exporter_ring_setup, 0), + HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_IMPORTER_RING_SETUP, hyper_dmabuf_importer_ring_setup, 0), + HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_EXPORT_REMOTE, hyper_dmabuf_export_remote, 0), + HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_EXPORT_FD, hyper_dmabuf_export_fd_ioctl, 0), + HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_DESTROY, hyper_dmabuf_destroy, 0), + HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_QUERY, hyper_dmabuf_query, 0), + HYPER_DMABUF_IOCTL_DEF(IOCTL_HYPER_DMABUF_REMOTE_EXPORTER_RING_SETUP, hyper_dmabuf_remote_exporter_ring_setup, 0), +}; + +static long hyper_dmabuf_ioctl(struct file *filp, + unsigned int cmd, unsigned long param) +{ + const struct hyper_dmabuf_ioctl_desc *ioctl = NULL; + unsigned int nr = _IOC_NR(cmd); + int ret = -EINVAL; + hyper_dmabuf_ioctl_t func; + char *kdata; + + ioctl = &hyper_dmabuf_ioctls[nr]; + + func = ioctl->func; + + if (unlikely(!func)) { + printk("no function\n"); + return -EINVAL; + } + + kdata = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); + if (!kdata) { + printk("no memory\n"); + return -ENOMEM; + } + + if (copy_from_user(kdata, (void __user *)param, _IOC_SIZE(cmd)) != 0) { + printk("failed to copy from user arguments\n"); + return -EFAULT; + } + + ret = func(kdata); + + if (copy_to_user((void __user *)param, kdata, _IOC_SIZE(cmd)) != 0) { + printk("failed to copy to user arguments\n"); + return -EFAULT; + } + + kfree(kdata); + + return ret; +} + +struct device_info { + int curr_domain; +}; + +/*===============================================================================================*/ +static struct file_operations hyper_dmabuf_driver_fops = +{ + .owner = THIS_MODULE, + .unlocked_ioctl = hyper_dmabuf_ioctl, +}; + +static struct miscdevice hyper_dmabuf_miscdev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "xen/hyper_dmabuf", + .fops = &hyper_dmabuf_driver_fops, +}; + +static const char device_name[] = "hyper_dmabuf"; + +/*===============================================================================================*/ +int register_device(void) +{ + int result = 0; + + result = misc_register(&hyper_dmabuf_miscdev); + + if (result != 0) { + printk(KERN_WARNING "hyper_dmabuf: driver can't be registered\n"); + return result; + } + + hyper_dmabuf_private.device = hyper_dmabuf_miscdev.this_device; + + /* TODO: Check if there is a different way to initialize dma mask nicely */ + dma_coerce_mask_and_coherent(hyper_dmabuf_private.device, 0xFFFFFFFF); + + /* TODO find a way to provide parameters for below function or move that to ioctl */ +/* err = bind_interdomain_evtchn_to_irqhandler(rdomain, evtchn, + src_sink_isr, PORT_NUM, "remote_domain", &info); + if (err < 0) { + printk("hyper_dmabuf: can't register interrupt handlers\n"); + return -EFAULT; + } + + info.irq = err; +*/ + return result; +} + +/*-----------------------------------------------------------------------------------------------*/ +void unregister_device(void) +{ + printk( KERN_NOTICE "hyper_dmabuf: unregister_device() is called" ); + misc_deregister(&hyper_dmabuf_miscdev); +} diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.c new file mode 100644 index 0000000..77a7e65 --- /dev/null +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "hyper_dmabuf_list.h" + +DECLARE_HASHTABLE(hyper_dmabuf_hash_imported, MAX_ENTRY_IMPORTED); +DECLARE_HASHTABLE(hyper_dmabuf_hash_exported, MAX_ENTRY_EXPORTED); + +int hyper_dmabuf_table_init() +{ + hash_init(hyper_dmabuf_hash_imported); + hash_init(hyper_dmabuf_hash_exported); + return 0; +} + +int hyper_dmabuf_table_destroy() +{ + /* TODO: cleanup hyper_dmabuf_hash_imported and hyper_dmabuf_hash_exported */ + return 0; +} + +int hyper_dmabuf_register_exported(struct hyper_dmabuf_sgt_info *info) +{ + struct hyper_dmabuf_info_entry_exported *info_entry; + + info_entry = kmalloc(sizeof(*info_entry), GFP_KERNEL); + + info_entry->info = info; + + hash_add(hyper_dmabuf_hash_exported, &info_entry->node, + info_entry->info->hyper_dmabuf_id); + + return 0; +} + +int hyper_dmabuf_register_imported(struct hyper_dmabuf_imported_sgt_info* info) +{ + struct hyper_dmabuf_info_entry_imported *info_entry; + + info_entry = kmalloc(sizeof(*info_entry), GFP_KERNEL); + + info_entry->info = info; + + hash_add(hyper_dmabuf_hash_imported, &info_entry->node, + info_entry->info->hyper_dmabuf_id); + + return 0; +} + +struct hyper_dmabuf_sgt_info *hyper_dmabuf_find_exported(int id) +{ + struct hyper_dmabuf_info_entry_exported *info_entry; + int bkt; + + hash_for_each(hyper_dmabuf_hash_exported, bkt, info_entry, node) + if(info_entry->info->hyper_dmabuf_id == id) + return info_entry->info; + + return NULL; +} + +/* search for pre-exported sgt and return id of it if it exist */ +int hyper_dmabuf_find_id(struct dma_buf_attachment *attach, int domid) +{ + struct hyper_dmabuf_info_entry_exported *info_entry; + int bkt; + + hash_for_each(hyper_dmabuf_hash_exported, bkt, info_entry, node) + if(info_entry->info->attachment == attach && + info_entry->info->hyper_dmabuf_rdomain == domid) + return info_entry->info->hyper_dmabuf_id; + + return -1; +} + +struct hyper_dmabuf_imported_sgt_info *hyper_dmabuf_find_imported(int id) +{ + struct hyper_dmabuf_info_entry_imported *info_entry; + int bkt; + + hash_for_each(hyper_dmabuf_hash_imported, bkt, info_entry, node) + if(info_entry->info->hyper_dmabuf_id == id) + return info_entry->info; + + return NULL; +} + +int hyper_dmabuf_remove_exported(int id) +{ + struct hyper_dmabuf_info_entry_exported *info_entry; + int bkt; + + hash_for_each(hyper_dmabuf_hash_exported, bkt, info_entry, node) + if(info_entry->info->hyper_dmabuf_id == id) { + hash_del(&info_entry->node); + return 0; + } + + return -1; +} + +int hyper_dmabuf_remove_imported(int id) +{ + struct hyper_dmabuf_info_entry_imported *info_entry; + int bkt; + + hash_for_each(hyper_dmabuf_hash_imported, bkt, info_entry, node) + if(info_entry->info->hyper_dmabuf_id == id) { + hash_del(&info_entry->node); + return 0; + } + + return -1; +} diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.h new file mode 100644 index 0000000..869cd9a --- /dev/null +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_list.h @@ -0,0 +1,40 @@ +#ifndef __HYPER_DMABUF_LIST_H__ +#define __HYPER_DMABUF_LIST_H__ + +#include "hyper_dmabuf_struct.h" + +/* number of bits to be used for exported dmabufs hash table */ +#define MAX_ENTRY_EXPORTED 7 +/* number of bits to be used for imported dmabufs hash table */ +#define MAX_ENTRY_IMPORTED 7 + +struct hyper_dmabuf_info_entry_exported { + struct hyper_dmabuf_sgt_info *info; + struct hlist_node node; +}; + +struct hyper_dmabuf_info_entry_imported { + struct hyper_dmabuf_imported_sgt_info *info; + struct hlist_node node; +}; + +int hyper_dmabuf_table_init(void); + +int hyper_dmabuf_table_destroy(void); + +int hyper_dmabuf_register_exported(struct hyper_dmabuf_sgt_info *info); + +/* search for pre-exported sgt and return id of it if it exist */ +int hyper_dmabuf_find_id(struct dma_buf_attachment *attach, int domid); + +int hyper_dmabuf_register_imported(struct hyper_dmabuf_imported_sgt_info* info); + +struct hyper_dmabuf_sgt_info *hyper_dmabuf_find_exported(int id); + +struct hyper_dmabuf_imported_sgt_info *hyper_dmabuf_find_imported(int id); + +int hyper_dmabuf_remove_exported(int id); + +int hyper_dmabuf_remove_imported(int id); + +#endif // __HYPER_DMABUF_LIST_H__ diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c new file mode 100644 index 0000000..3237e50 --- /dev/null +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.c @@ -0,0 +1,212 @@ +#include +#include +#include +#include +#include +#include "hyper_dmabuf_imp.h" +//#include "hyper_dmabuf_remote_sync.h" +#include "xen/hyper_dmabuf_xen_comm.h" +#include "hyper_dmabuf_msg.h" +#include "hyper_dmabuf_list.h" + +void hyper_dmabuf_create_request(struct hyper_dmabuf_ring_rq *request, + enum hyper_dmabuf_command command, int *operands) +{ + int i; + + request->request_id = hyper_dmabuf_next_req_id_export(); + request->status = HYPER_DMABUF_REQ_NOT_RESPONDED; + request->command = command; + + switch(command) { + /* as exporter, commands to importer */ + case HYPER_DMABUF_EXPORT: + /* exporting pages for dmabuf */ + /* command : HYPER_DMABUF_EXPORT, + * operands0 : hyper_dmabuf_id + * operands1 : number of pages to be shared + * operands2 : offset of data in the first page + * operands3 : length of data in the last page + * operands4 : top-level reference number for shared pages + * operands5~8 : Driver-specific private data (e.g. graphic buffer's meta info) + */ + for (i=0; i < 8; i++) + request->operands[i] = operands[i]; + break; + + case HYPER_DMABUF_DESTROY: + /* destroy sg_list for hyper_dmabuf_id on remote side */ + /* command : DMABUF_DESTROY, + * operands0 : hyper_dmabuf_id + */ + request->operands[0] = operands[0]; + break; + + case HYPER_DMABUF_OPS_TO_REMOTE: + /* notifying dmabuf map/unmap to importer (probably not needed) */ + /* for dmabuf synchronization */ + break; + + /* as importer, command to exporter */ + case HYPER_DMABUF_OPS_TO_SOURCE: + /* notifying dmabuf map/unmap to exporter, map will make the driver to do shadow mapping + * or unmapping for synchronization with original exporter (e.g. i915) */ + /* command : DMABUF_OPS_TO_SOURCE. + * operands0 : hyper_dmabuf_id + * operands1 : map(=1)/unmap(=2)/attach(=3)/detach(=4) + */ + for (i=0; i<2; i++) + request->operands[i] = operands[i]; + break; + + /* requesting the other side to setup another ring channel for reverse direction */ + case HYPER_DMABUF_EXPORTER_RING_SETUP: + /* command : HYPER_DMABUF_EXPORTER_RING_SETUP */ + /* no operands needed */ + break; + + default: + /* no command found */ + return; + } +} + +int hyper_dmabuf_msg_parse(int domid, struct hyper_dmabuf_ring_rq *req) +{ + uint32_t i, ret; + struct hyper_dmabuf_imported_sgt_info *imported_sgt_info; + struct hyper_dmabuf_sgt_info *sgt_info; + + /* make sure req is not NULL (may not be needed) */ + if (!req) { + return -EINVAL; + } + + req->status = HYPER_DMABUF_REQ_PROCESSED; + + switch (req->command) { + case HYPER_DMABUF_EXPORT: + /* exporting pages for dmabuf */ + /* command : HYPER_DMABUF_EXPORT, + * operands0 : hyper_dmabuf_id + * operands1 : number of pages to be shared + * operands2 : offset of data in the first page + * operands3 : length of data in the last page + * operands4 : top-level reference number for shared pages + * operands5~8 : Driver-specific private data (e.g. graphic buffer's meta info) + */ + imported_sgt_info = (struct hyper_dmabuf_imported_sgt_info*)kcalloc(1, sizeof(*imported_sgt_info), GFP_KERNEL); + imported_sgt_info->hyper_dmabuf_id = req->operands[0]; + imported_sgt_info->frst_ofst = req->operands[2]; + imported_sgt_info->last_len = req->operands[3]; + imported_sgt_info->nents = req->operands[1]; + imported_sgt_info->gref = req->operands[4]; + + printk("DMABUF was exported\n"); + printk("\thyper_dmabuf_id %d\n", req->operands[0]); + printk("\tnents %d\n", req->operands[1]); + printk("\tfirst offset %d\n", req->operands[2]); + printk("\tlast len %d\n", req->operands[3]); + printk("\tgrefid %d\n", req->operands[4]); + + for (i=0; i<4; i++) + imported_sgt_info->private[i] = req->operands[5+i]; + + hyper_dmabuf_register_imported(imported_sgt_info); + break; + + case HYPER_DMABUF_DESTROY: + /* destroy sg_list for hyper_dmabuf_id on remote side */ + /* command : DMABUF_DESTROY, + * operands0 : hyper_dmabuf_id + */ + + imported_sgt_info = + hyper_dmabuf_find_imported(req->operands[0]); + + if (imported_sgt_info) { + hyper_dmabuf_cleanup_imported_pages(imported_sgt_info); + + hyper_dmabuf_remove_imported(req->operands[0]); + + /* TODO: cleanup sgt on importer side etc */ + } + + /* Notify exporter that buffer is freed and it can cleanup it */ + req->status = HYPER_DMABUF_REQ_NEEDS_FOLLOW_UP; + req->command = HYPER_DMABUF_DESTROY_FINISH; + +#if 0 /* function is not implemented yet */ + + ret = hyper_dmabuf_destroy_sgt(req->hyper_dmabuf_id); +#endif + break; + + case HYPER_DMABUF_DESTROY_FINISH: + /* destroy sg_list for hyper_dmabuf_id on local side */ + /* command : DMABUF_DESTROY_FINISH, + * operands0 : hyper_dmabuf_id + */ + + /* TODO: that should be done on workqueue, when received ack from all importers that buffer is no longer used */ + sgt_info = + hyper_dmabuf_find_exported(req->operands[0]); + + if (sgt_info) { + hyper_dmabuf_cleanup_gref_table(sgt_info); + + /* unmap dmabuf */ + dma_buf_unmap_attachment(sgt_info->attachment, sgt_info->sgt, DMA_BIDIRECTIONAL); + dma_buf_detach(sgt_info->dma_buf, sgt_info->attachment); + dma_buf_put(sgt_info->dma_buf); + + /* TODO: Rest of cleanup, sgt cleanup etc */ + } + + break; + + case HYPER_DMABUF_OPS_TO_REMOTE: + /* notifying dmabuf map/unmap to importer (probably not needed) */ + /* for dmabuf synchronization */ + break; + + /* as importer, command to exporter */ + case HYPER_DMABUF_OPS_TO_SOURCE: + /* notifying dmabuf map/unmap to exporter, map will make the driver to do shadow mapping + * or unmapping for synchronization with original exporter (e.g. i915) */ + /* command : DMABUF_OPS_TO_SOURCE. + * operands0 : hyper_dmabuf_id + * operands1 : map(=1)/unmap(=2)/attach(=3)/detach(=4) + */ + break; + + /* requesting the other side to setup another ring channel for reverse direction */ + case HYPER_DMABUF_EXPORTER_RING_SETUP: + /* command: HYPER_DMABUF_EXPORTER_RING_SETUP + * no operands needed */ + ret = hyper_dmabuf_exporter_ringbuf_init(domid, &req->operands[0], &req->operands[1]); + if (ret < 0) { + req->status = HYPER_DMABUF_REQ_ERROR; + return -EINVAL; + } + + req->status = HYPER_DMABUF_REQ_NEEDS_FOLLOW_UP; + req->command = HYPER_DMABUF_IMPORTER_RING_SETUP; + break; + + case HYPER_DMABUF_IMPORTER_RING_SETUP: + /* command: HYPER_DMABUF_IMPORTER_RING_SETUP */ + /* no operands needed */ + ret = hyper_dmabuf_importer_ringbuf_init(domid, req->operands[0], req->operands[1]); + if (ret < 0) + return -EINVAL; + + break; + + default: + /* no matched command, nothing to do.. just return error */ + return -EINVAL; + } + + return req->command; +} diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h new file mode 100644 index 0000000..44bfb70 --- /dev/null +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_msg.h @@ -0,0 +1,45 @@ +#ifndef __HYPER_DMABUF_MSG_H__ +#define __HYPER_DMABUF_MSG_H__ + +enum hyper_dmabuf_command { + HYPER_DMABUF_EXPORT = 0x10, + HYPER_DMABUF_DESTROY, + HYPER_DMABUF_DESTROY_FINISH, + HYPER_DMABUF_OPS_TO_REMOTE, + HYPER_DMABUF_OPS_TO_SOURCE, + HYPER_DMABUF_EXPORTER_RING_SETUP, /* requesting remote domain to set up exporter's ring */ + HYPER_DMABUF_IMPORTER_RING_SETUP, /* requesting remote domain to set up importer's ring */ +}; + +enum hyper_dmabuf_ops { + HYPER_DMABUF_OPS_ATTACH = 0x1000, + HYPER_DMABUF_OPS_DETACH, + HYPER_DMABUF_OPS_MAP, + HYPER_DMABUF_OPS_UNMAP, + HYPER_DMABUF_OPS_RELEASE, + HYPER_DMABUF_OPS_BEGIN_CPU_ACCESS, + HYPER_DMABUF_OPS_END_CPU_ACCESS, + HYPER_DMABUF_OPS_KMAP_ATOMIC, + HYPER_DMABUF_OPS_KUNMAP_ATOMIC, + HYPER_DMABUF_OPS_KMAP, + HYPER_DMABUF_OPS_KUNMAP, + HYPER_DMABUF_OPS_MMAP, + HYPER_DMABUF_OPS_VMAP, + HYPER_DMABUF_OPS_VUNMAP, +}; + +enum hyper_dmabuf_req_feedback { + HYPER_DMABUF_REQ_PROCESSED = 0x100, + HYPER_DMABUF_REQ_NEEDS_FOLLOW_UP, + HYPER_DMABUF_REQ_ERROR, + HYPER_DMABUF_REQ_NOT_RESPONDED +}; + +/* create a request packet with given command and operands */ +void hyper_dmabuf_create_request(struct hyper_dmabuf_ring_rq *request, + enum hyper_dmabuf_command command, int *operands); + +/* parse incoming request packet (or response) and take appropriate actions for those */ +int hyper_dmabuf_msg_parse(int domid, struct hyper_dmabuf_ring_rq *req); + +#endif // __HYPER_DMABUF_MSG_H__ diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_query.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_query.h new file mode 100644 index 0000000..a577167 --- /dev/null +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_query.h @@ -0,0 +1,16 @@ +#ifndef __HYPER_DMABUF_QUERY_H__ +#define __HYPER_DMABUF_QUERY_H__ + +enum hyper_dmabuf_query { + DMABUF_QUERY_TYPE_LIST = 0x10, + DMABUF_QUERY_EXPORTER, + DMABUF_QUERY_IMPORTER, + DMABUF_QUERY_SIZE +}; + +enum hyper_dmabuf_status { + EXPORTED = 0x01, + IMPORTED +}; + +#endif /* __HYPER_DMABUF_QUERY_H__ */ diff --git a/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h b/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h new file mode 100644 index 0000000..c8a2f4d --- /dev/null +++ b/drivers/xen/hyper_dmabuf/hyper_dmabuf_struct.h @@ -0,0 +1,70 @@ +#ifndef __HYPER_DMABUF_STRUCT_H__ +#define __HYPER_DMABUF_STRUCT_H__ + +#include + +/* Importer combine source domain id with given hyper_dmabuf_id + * to make it unique in case there are multiple exporters */ + +#define HYPER_DMABUF_ID_IMPORTER(sdomain, id) \ + ((((sdomain) & 0xFF) << 24) | ((id) & 0xFFFFFF)) + +#define HYPER_DMABUF_ID_IMPORTER_GET_SDOMAIN_ID(id) \ + (((id) >> 24) & 0xFF) + +/* each grant_ref_t is 4 bytes, so total 4096 grant_ref_t can be + * in this block meaning we can share 4KB*4096 = 16MB of buffer + * (needs to be increased for large buffer use-cases such as 4K + * frame buffer) */ +#define MAX_ALLOWED_NUM_PAGES_FOR_GREF_NUM_ARRAYS 4 + +struct hyper_dmabuf_shared_pages_info { + grant_ref_t *data_refs; /* table with shared buffer pages refid */ + grant_ref_t *addr_pages; /* pages of 2nd level addressing */ + grant_ref_t *top_level_page; /* page of top level addressing, it contains refids of 2nd level pages */ + grant_ref_t top_level_ref; /* top level refid */ + struct gnttab_unmap_grant_ref* unmap_ops; /* unmap ops for mapped pages */ + struct page **data_pages; /* data pages to be unmapped */ +}; + +/* Exporter builds pages_info before sharing pages */ +struct hyper_dmabuf_pages_info { + int hyper_dmabuf_id; /* unique id to reference dmabuf in source domain */ + int hyper_dmabuf_rdomain; /* currenting considering just one remote domain access it */ + int frst_ofst; /* offset of data in the first page */ + int last_len; /* length of data in the last page */ + int nents; /* # of pages */ + struct page **pages; /* pages that contains reference numbers of shared pages*/ +}; + +/* Both importer and exporter use this structure to point to sg lists + * + * Exporter stores references to sgt in a hash table + * Exporter keeps these references for synchronization and tracking purposes + * + * Importer use this structure exporting to other drivers in the same domain */ +struct hyper_dmabuf_sgt_info { + int hyper_dmabuf_id; /* unique id to reference dmabuf in remote domain */ + int hyper_dmabuf_rdomain; /* domain importing this sgt */ + struct sg_table *sgt; /* pointer to sgt */ + struct dma_buf *dma_buf; /* needed to store this for freeing it later */ + struct dma_buf_attachment *attachment; /* needed to store this for freeing this later */ + struct hyper_dmabuf_shared_pages_info shared_pages_info; + int private[4]; /* device specific info (e.g. image's meta info?) */ +}; + +/* Importer store references (before mapping) on shared pages + * Importer store these references in the table and map it in + * its own memory map once userspace asks for reference for the buffer */ +struct hyper_dmabuf_imported_sgt_info { + int hyper_dmabuf_id; /* unique id to reference dmabuf (HYPER_DMABUF_ID_IMPORTER(source domain id, exporter's hyper_dmabuf_id */ + int frst_ofst; /* start offset in shared page #1 */ + int last_len; /* length of data in the last shared page */ + int nents; /* number of pages to be shared */ + grant_ref_t gref; /* reference number of top level addressing page of shared pages */ + struct sg_table *sgt; /* sgt pointer after importing buffer */ + struct hyper_dmabuf_shared_pages_info shared_pages_info; + int private[4]; /* device specific info (e.g. image's meta info?) */ +}; + +#endif /* __HYPER_DMABUF_STRUCT_H__ */ diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c new file mode 100644 index 0000000..22f2ef0 --- /dev/null +++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.c @@ -0,0 +1,328 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hyper_dmabuf_xen_comm.h" +#include "hyper_dmabuf_xen_comm_list.h" +#include "../hyper_dmabuf_imp.h" +#include "../hyper_dmabuf_list.h" +#include "../hyper_dmabuf_msg.h" + +static int export_req_id = 0; +static int import_req_id = 0; + +int32_t hyper_dmabuf_get_domid(void) +{ + struct xenbus_transaction xbt; + int32_t domid; + + xenbus_transaction_start(&xbt); + + if (!xenbus_scanf(xbt, "domid","", "%d", &domid)) { + domid = -1; + } + xenbus_transaction_end(xbt, 0); + + return domid; +} + +int hyper_dmabuf_next_req_id_export(void) +{ + export_req_id++; + return export_req_id; +} + +int hyper_dmabuf_next_req_id_import(void) +{ + import_req_id++; + return import_req_id; +} + +/* For now cache latast rings as global variables TODO: keep them in list*/ +static irqreturn_t hyper_dmabuf_front_ring_isr(int irq, void *dev_id); +static irqreturn_t hyper_dmabuf_back_ring_isr(int irq, void *dev_id); + +/* exporter needs to generated info for page sharing */ +int hyper_dmabuf_exporter_ringbuf_init(int rdomain, grant_ref_t *refid, int *port) +{ + struct hyper_dmabuf_ring_info_export *ring_info; + struct hyper_dmabuf_sring *sring; + struct evtchn_alloc_unbound alloc_unbound; + struct evtchn_close close; + + void *shared_ring; + int ret; + + ring_info = (struct hyper_dmabuf_ring_info_export*) + kmalloc(sizeof(*ring_info), GFP_KERNEL); + + /* from exporter to importer */ + shared_ring = (void *)__get_free_pages(GFP_KERNEL, 1); + if (shared_ring == 0) { + return -EINVAL; + } + + sring = (struct hyper_dmabuf_sring *) shared_ring; + + SHARED_RING_INIT(sring); + + FRONT_RING_INIT(&(ring_info->ring_front), sring, PAGE_SIZE); + + ring_info->gref_ring = gnttab_grant_foreign_access(rdomain, + virt_to_mfn(shared_ring), 0); + if (ring_info->gref_ring < 0) { + return -EINVAL; /* fail to get gref */ + } + + alloc_unbound.dom = DOMID_SELF; + alloc_unbound.remote_dom = rdomain; + ret = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &alloc_unbound); + if (ret != 0) { + printk("Cannot allocate event channel\n"); + return -EINVAL; + } + + /* setting up interrupt */ + ret = bind_evtchn_to_irqhandler(alloc_unbound.port, + hyper_dmabuf_front_ring_isr, 0, + NULL, (void*) ring_info); + + if (ret < 0) { + printk("Failed to setup event channel\n"); + close.port = alloc_unbound.port; + HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); + gnttab_end_foreign_access(ring_info->gref_ring, 0, virt_to_mfn(shared_ring)); + return -EINVAL; + } + + ring_info->rdomain = rdomain; + ring_info->irq = ret; + ring_info->port = alloc_unbound.port; + + /* store refid and port numbers for userspace's use */ + *refid = ring_info->gref_ring; + *port = ring_info->port; + + printk("%s: allocated eventchannel gref %d port: %d irq: %d\n", __func__, + ring_info->gref_ring, + ring_info->port, + ring_info->irq); + + /* register ring info */ + ret = hyper_dmabuf_register_exporter_ring(ring_info); + + return ret; +} + +/* importer needs to know about shared page and port numbers for ring buffer and event channel */ +int hyper_dmabuf_importer_ringbuf_init(int sdomain, grant_ref_t gref, int port) +{ + struct hyper_dmabuf_ring_info_import *ring_info; + struct hyper_dmabuf_sring *sring; + + struct page *shared_ring; + + struct gnttab_map_grant_ref *ops; + struct gnttab_unmap_grant_ref *unmap_ops; + int ret; + + ring_info = (struct hyper_dmabuf_ring_info_import *) + kmalloc(sizeof(*ring_info), GFP_KERNEL); + + ring_info->sdomain = sdomain; + ring_info->evtchn = port; + + ops = (struct gnttab_map_grant_ref*)kmalloc(sizeof(*ops), GFP_KERNEL); + unmap_ops = (struct gnttab_unmap_grant_ref*)kmalloc(sizeof(*unmap_ops), GFP_KERNEL); + + if (gnttab_alloc_pages(1, &shared_ring)) { + return -EINVAL; + } + + gnttab_set_map_op(&ops[0], (unsigned long)pfn_to_kaddr(page_to_pfn(shared_ring)), + GNTMAP_host_map, gref, sdomain); + + ret = gnttab_map_refs(ops, NULL, &shared_ring, 1); + if (ret < 0) { + printk("Cannot map ring\n"); + return -EINVAL; + } + + if (ops[0].status) { + printk("Ring mapping failed\n"); + return -EINVAL; + } + + sring = (struct hyper_dmabuf_sring*) pfn_to_kaddr(page_to_pfn(shared_ring)); + + BACK_RING_INIT(&ring_info->ring_back, sring, PAGE_SIZE); + + ret = bind_interdomain_evtchn_to_irqhandler(sdomain, port, hyper_dmabuf_back_ring_isr, 0, + NULL, (void*)ring_info); + if (ret < 0) { + return -EINVAL; + } + + ring_info->irq = ret; + + printk("%s: bound to eventchannel port: %d irq: %d\n", __func__, + port, + ring_info->irq); + + ret = hyper_dmabuf_register_importer_ring(ring_info); + + return ret; +} + +int hyper_dmabuf_send_request(int domain, struct hyper_dmabuf_ring_rq *req) +{ + struct hyper_dmabuf_front_ring *ring; + struct hyper_dmabuf_ring_rq *new_req; + struct hyper_dmabuf_ring_info_export *ring_info; + int notify; + + /* find a ring info for the channel */ + ring_info = hyper_dmabuf_find_exporter_ring(domain); + if (!ring_info) { + printk("Can't find ring info for the channel\n"); + return -EINVAL; + } + + ring = &ring_info->ring_front; + + if (RING_FULL(ring)) + return -EBUSY; + + new_req = RING_GET_REQUEST(ring, ring->req_prod_pvt); + if (!new_req) { + printk("NULL REQUEST\n"); + return -EIO; + } + + memcpy(new_req, req, sizeof(*new_req)); + + ring->req_prod_pvt++; + + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(ring, notify); + if (notify) { + notify_remote_via_irq(ring_info->irq); + } + + return 0; +} + +/* called by interrupt (WORKQUEUE) */ +int hyper_dmabuf_send_response(struct hyper_dmabuf_ring_rp* response, int domain) +{ + /* as a importer and as a exporter */ + return 0; +} + +/* ISR for request from exporter (as an importer) */ +static irqreturn_t hyper_dmabuf_back_ring_isr(int irq, void *dev_id) +{ + RING_IDX rc, rp; + struct hyper_dmabuf_ring_rq request; + struct hyper_dmabuf_ring_rp response; + int notify, more_to_do; + int ret; +// struct hyper_dmabuf_work *work; + + struct hyper_dmabuf_ring_info_import *ring_info = (struct hyper_dmabuf_ring_info_import *)dev_id; + struct hyper_dmabuf_back_ring *ring; + + ring = &ring_info->ring_back; + + do { + rc = ring->req_cons; + rp = ring->sring->req_prod; + + while (rc != rp) { + if (RING_REQUEST_CONS_OVERFLOW(ring, rc)) + break; + + memcpy(&request, RING_GET_REQUEST(ring, rc), sizeof(request)); + printk("Got request\n"); + ring->req_cons = ++rc; + + /* TODO: probably using linked list for multiple requests then let + * a task in a workqueue to process those is better idea becuase + * we do not want to stay in ISR for long. + */ + ret = hyper_dmabuf_msg_parse(ring_info->sdomain, &request); + + if (ret > 0) { + /* build response */ + memcpy(&response, &request, sizeof(response)); + + /* we sent back modified request as a response.. we might just need to have request only..*/ + memcpy(RING_GET_RESPONSE(ring, ring->rsp_prod_pvt), &response, sizeof(response)); + ring->rsp_prod_pvt++; + + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(ring, notify); + + if (notify) { + printk("Notyfing\n"); + notify_remote_via_irq(ring_info->irq); + } + } + + RING_FINAL_CHECK_FOR_REQUESTS(ring, more_to_do); + printk("Final check for requests %d\n", more_to_do); + } + } while (more_to_do); + + return IRQ_HANDLED; +} + +/* ISR for responses from importer */ +static irqreturn_t hyper_dmabuf_front_ring_isr(int irq, void *dev_id) +{ + /* front ring only care about response from back */ + struct hyper_dmabuf_ring_rp *response; + RING_IDX i, rp; + int more_to_do, ret; + + struct hyper_dmabuf_ring_info_export *ring_info = (struct hyper_dmabuf_ring_info_export *)dev_id; + struct hyper_dmabuf_front_ring *ring; + ring = &ring_info->ring_front; + + do { + more_to_do = 0; + rp = ring->sring->rsp_prod; + for (i = ring->rsp_cons; i != rp; i++) { + unsigned long id; + + response = RING_GET_RESPONSE(ring, i); + id = response->response_id; + + if (response->status == HYPER_DMABUF_REQ_NEEDS_FOLLOW_UP) { + /* parsing response */ + ret = hyper_dmabuf_msg_parse(ring_info->rdomain, (struct hyper_dmabuf_ring_rq*)response); + + if (ret < 0) { + printk("getting error while parsing response\n"); + } + } else if (response->status == HYPER_DMABUF_REQ_ERROR) { + printk("remote domain %d couldn't process request %d\n", ring_info->rdomain, response->command); + } + + } + + ring->rsp_cons = i; + + if (i != ring->req_prod_pvt) { + RING_FINAL_CHECK_FOR_RESPONSES(ring, more_to_do); + printk("more to do %d\n", more_to_do); + } else { + ring->sring->rsp_event = i+1; + } + } while (more_to_do); + + return IRQ_HANDLED; +} diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h new file mode 100644 index 0000000..2754917 --- /dev/null +++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm.h @@ -0,0 +1,62 @@ +#ifndef __HYPER_DMABUF_XEN_COMM_H__ +#define __HYPER_DMABUF_XEN_COMM_H__ + +#include "xen/interface/io/ring.h" + +#define MAX_NUMBER_OF_OPERANDS 9 + +struct hyper_dmabuf_ring_rq { + unsigned int request_id; + unsigned int status; + unsigned int command; + unsigned int operands[MAX_NUMBER_OF_OPERANDS]; +}; + +struct hyper_dmabuf_ring_rp { + unsigned int response_id; + unsigned int status; + unsigned int command; + unsigned int operands[MAX_NUMBER_OF_OPERANDS]; +}; + +DEFINE_RING_TYPES(hyper_dmabuf, struct hyper_dmabuf_ring_rq, struct hyper_dmabuf_ring_rp); + +struct hyper_dmabuf_ring_info_export { + struct hyper_dmabuf_front_ring ring_front; + int rdomain; + int gref_ring; + int irq; + int port; +}; + +struct hyper_dmabuf_ring_info_import { + int sdomain; + int irq; + int evtchn; + struct hyper_dmabuf_back_ring ring_back; +}; + +//struct hyper_dmabuf_work { +// hyper_dmabuf_ring_rq requrest; +// struct work_struct msg_parse; +//}; + +int32_t hyper_dmabuf_get_domid(void); + +int hyper_dmabuf_next_req_id_export(void); + +int hyper_dmabuf_next_req_id_import(void); + +/* exporter needs to generated info for page sharing */ +int hyper_dmabuf_exporter_ringbuf_init(int rdomain, grant_ref_t *gref, int *port); + +/* importer needs to know about shared page and port numbers for ring buffer and event channel */ +int hyper_dmabuf_importer_ringbuf_init(int sdomain, grant_ref_t gref, int port); + +/* send request to the remote domain */ +int hyper_dmabuf_send_request(int domain, struct hyper_dmabuf_ring_rq *req); + +/* called by interrupt (WORKQUEUE) */ +int hyper_dmabuf_send_response(struct hyper_dmabuf_ring_rp* response, int domain); + +#endif // __HYPER_DMABUF_XEN_COMM_H__ diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c new file mode 100644 index 0000000..15c9d29 --- /dev/null +++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.c @@ -0,0 +1,106 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "hyper_dmabuf_xen_comm.h" +#include "hyper_dmabuf_xen_comm_list.h" + +DECLARE_HASHTABLE(hyper_dmabuf_hash_importer_ring, MAX_ENTRY_IMPORT_RING); +DECLARE_HASHTABLE(hyper_dmabuf_hash_exporter_ring, MAX_ENTRY_EXPORT_RING); + +int hyper_dmabuf_ring_table_init() +{ + hash_init(hyper_dmabuf_hash_importer_ring); + hash_init(hyper_dmabuf_hash_exporter_ring); + return 0; +} + +int hyper_dmabuf_ring_table_destroy() +{ + /* TODO: cleanup tables*/ + return 0; +} + +int hyper_dmabuf_register_exporter_ring(struct hyper_dmabuf_ring_info_export *ring_info) +{ + struct hyper_dmabuf_exporter_ring_info *info_entry; + + info_entry = kmalloc(sizeof(*info_entry), GFP_KERNEL); + + info_entry->info = ring_info; + + hash_add(hyper_dmabuf_hash_exporter_ring, &info_entry->node, + info_entry->info->rdomain); + + return 0; +} + +int hyper_dmabuf_register_importer_ring(struct hyper_dmabuf_ring_info_import *ring_info) +{ + struct hyper_dmabuf_importer_ring_info *info_entry; + + info_entry = kmalloc(sizeof(*info_entry), GFP_KERNEL); + + info_entry->info = ring_info; + + hash_add(hyper_dmabuf_hash_importer_ring, &info_entry->node, + info_entry->info->sdomain); + + return 0; +} + +struct hyper_dmabuf_ring_info_export *hyper_dmabuf_find_exporter_ring(int domid) +{ + struct hyper_dmabuf_exporter_ring_info *info_entry; + int bkt; + + hash_for_each(hyper_dmabuf_hash_exporter_ring, bkt, info_entry, node) + if(info_entry->info->rdomain == domid) + return info_entry->info; + + return NULL; +} + +struct hyper_dmabuf_ring_info_import *hyper_dmabuf_find_importer_ring(int domid) +{ + struct hyper_dmabuf_importer_ring_info *info_entry; + int bkt; + + hash_for_each(hyper_dmabuf_hash_importer_ring, bkt, info_entry, node) + if(info_entry->info->sdomain == domid) + return info_entry->info; + + return NULL; +} + +int hyper_dmabuf_remove_exporter_ring(int domid) +{ + struct hyper_dmabuf_exporter_ring_info *info_entry; + int bkt; + + hash_for_each(hyper_dmabuf_hash_exporter_ring, bkt, info_entry, node) + if(info_entry->info->rdomain == domid) { + hash_del(&info_entry->node); + return 0; + } + + return -1; +} + +int hyper_dmabuf_remove_importer_ring(int domid) +{ + struct hyper_dmabuf_importer_ring_info *info_entry; + int bkt; + + hash_for_each(hyper_dmabuf_hash_importer_ring, bkt, info_entry, node) + if(info_entry->info->sdomain == domid) { + hash_del(&info_entry->node); + return 0; + } + + return -1; +} diff --git a/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h new file mode 100644 index 0000000..5929f99 --- /dev/null +++ b/drivers/xen/hyper_dmabuf/xen/hyper_dmabuf_xen_comm_list.h @@ -0,0 +1,35 @@ +#ifndef __HYPER_DMABUF_XEN_COMM_LIST_H__ +#define __HYPER_DMABUF_XEN_COMM_LIST_H__ + +/* number of bits to be used for exported dmabufs hash table */ +#define MAX_ENTRY_EXPORT_RING 7 +/* number of bits to be used for imported dmabufs hash table */ +#define MAX_ENTRY_IMPORT_RING 7 + +struct hyper_dmabuf_exporter_ring_info { + struct hyper_dmabuf_ring_info_export *info; + struct hlist_node node; +}; + +struct hyper_dmabuf_importer_ring_info { + struct hyper_dmabuf_ring_info_import *info; + struct hlist_node node; +}; + +int hyper_dmabuf_ring_table_init(void); + +int hyper_dmabuf_ring_table_destroy(void); + +int hyper_dmabuf_register_exporter_ring(struct hyper_dmabuf_ring_info_export *ring_info); + +int hyper_dmabuf_register_importer_ring(struct hyper_dmabuf_ring_info_import *ring_info); + +struct hyper_dmabuf_ring_info_export *hyper_dmabuf_find_exporter_ring(int domid); + +struct hyper_dmabuf_ring_info_import *hyper_dmabuf_find_importer_ring(int domid); + +int hyper_dmabuf_remove_exporter_ring(int domid); + +int hyper_dmabuf_remove_importer_ring(int domid); + +#endif // __HYPER_DMABUF_XEN_COMM_LIST_H__ -- 2.7.4 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dongwon Kim Subject: [RFC PATCH 01/60] hyper_dmabuf: initial working version of hyper_dmabuf drv Date: Tue, 19 Dec 2017 11:29:17 -0800 Message-ID: <1513711816-2618-1-git-send-email-dongwon.kim@intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by gabe.freedesktop.org (Postfix) with ESMTPS id 5212E6E31D for ; Tue, 19 Dec 2017 19:36:08 +0000 (UTC) List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: linux-kernel@vger.kernel.org Cc: xen-devel@lists.xenproject.org, mateuszx.potrola@intel.com, dri-devel@lists.freedesktop.org, dongwon.kim@intel.com List-Id: dri-devel@lists.freedesktop.org VXBsb2FkIG9mIGludGlhbCB2ZXJzaW9uIG9mIGh5cGVyX0RNQUJVRiBkcml2ZXIgZW5hYmxpbmcK RE1BX0JVRiBleGNoYW5nZSBiZXR3ZWVuIHR3byBkaWZmZXJlbnQgVk1zIGluIHZpcnR1YWxpemVk CnBsYXRmb3JtIGJhc2VkIG9uIGh5cGVydmlzb3Igc3VjaCBhcyBLVk0gb3IgWEVOLgoKSHlwZXJf RE1BQlVGIGRydidzIHByaW1hcnkgcm9sZSBpcyB0byBpbXBvcnQgYSBETUFfQlVGCmZyb20gb3Jp Z2luYXRvciB0aGVuIHJlLWV4cG9ydCBpdCB0byBhbm90aGVyIExpbnV4IFZNCnNvIHRoYXQgaXQg Y2FuIGJlIG1hcHBlZCBhbmQgYWNjZXNzZWQgYnkgaXQuCgpUaGUgZnVuY3Rpb25hbGl0eSBvZiB0 aGlzIGRyaXZlciBoaWdobHkgZGVwZW5kcyBvbgpIeXBlcnZpc29yJ3MgbmF0aXZlIHBhZ2Ugc2hh cmluZyBtZWNoYW5pc20gYW5kIGludGVyLVZNCmNvbW11bmljYXRpb24gc3VwcG9ydC4KClRoaXMg ZHJpdmVyIGhhcyB0d28gbGF5ZXJzLCBvbmUgaXMgbWFpbiBoeXBlcl9ETUFCVUYKZnJhbWV3b3Jr IGZvciBzY2F0dGVyLWdhdGhlciBsaXN0IG1hbmFnZW1lbnQgdGhhdCBoYW5kbGVzCmFjdHVhbCBp bXBvcnQgYW5kIGV4cG9ydCBvZiBETUFfQlVGLiBMb3dlciBsYXllciBpcyBhYm91dAphY3R1YWwg bWVtb3J5IHNoYXJpbmcgYW5kIGNvbW11bmljYXRpb24gYmV0d2VlbiB0d28gVk1zLAp3aGljaCBp cyBoeXBlcnZpc29yLXNwZWNpZmljIGludGVyZmFjZS4KClRoaXMgZHJpdmVyIGlzIGluaXRpYWxs eSBkZXNpZ25lZCB0byBlbmFibGUgRE1BX0JVRgpzaGFyaW5nIGFjcm9zcyBWTXMgaW4gWGVuIGVu dmlyb25tZW50LCBzbyBjdXJyZW50bHkgd29ya2luZwp3aXRoIFhlbiBvbmx5LgoKVGhpcyBhbHNv IGFkZHMgS2VybmVsIGNvbmZpZ3VyYXRpb24gZm9yIGh5cGVyX0RNQUJVRiBkcnYKdW5kZXIgRGV2 aWNlIERyaXZlcnMtPlhlbiBkcml2ZXIgc3VwcG9ydC0+aHlwZXJfZG1hYnVmCm9wdGlvbnMuCgpU byBnaXZlIHNvbWUgYnJpZWYgaW5mb3JtYXRpb24gYWJvdXQgZWFjaCBzb3VyY2UgZmlsZSwKCmh5 cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfY29uZi5oCjogY29uZmlndXJhdGlvbiBpbmZvCgpoeXBl cl9kbWFidWYvaHlwZXJfZG1hYnVmX2Rydi5jCjogZHJpdmVyIGludGVyZmFjZSBhbmQgaW5pdGlh bGl6YXRpb24KCmh5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfaW1wLmMKOiBzY2F0dGVyLWdhdGhl ciBsaXN0IGdlbmVyYXRpb24gYW5kIG1hbmFnZW1lbnQuIERNQV9CVUYKb3BzIGZvciBETUFfQlVG IHJlY29uc3RydWN0ZWQgZnJvbSBoeXBlcl9ETUFCVUYKCmh5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFi dWZfaW9jdGwuYwo6IElPQ1RMcyBjYWxscyBmb3IgZXhwb3J0L2ltcG9ydCBhbmQgY29tbSBjaGFu bmVsIGNyZWF0aW9uCnVuZXhwb3J0LgoKaHlwZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9saXN0LmMK OiBEYXRhYmFzZSAobGlua2VkLWxpc3QpIGZvciBleHBvcnRlZCBhbmQgaW1wb3J0ZWQKaHlwZXJf RE1BQlVGCgpoeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX21zZy5jCjogY3JlYXRpb24gYW5kIG1h bmFnZW1lbnQgb2YgbWVzc2FnZXMgYmV0d2VlbiBleHBvcnRlciBhbmQKaW1wb3J0ZXIKCmh5cGVy X2RtYWJ1Zi94ZW4vaHlwZXJfZG1hYnVmX3hlbl9jb21tLmMKOiBjb21tIGNoIG1hbmFnZW1lbnQg YW5kIElTUnMgZm9yIGluY29taW5nIG1lc3NhZ2VzLgoKaHlwZXJfZG1hYnVmL3hlbi9oeXBlcl9k bWFidWZfeGVuX2NvbW1fbGlzdC5jCjogRGF0YWJhc2UgKGxpbmtlZC1saXN0KSBmb3Iga2VlcGlu ZyBpbmZvcm1hdGlvbiBhYm91dApleGlzdGluZyBjb21tIGNoYW5uZWxzIGFtb25nIFZNcwoKU2ln bmVkLW9mZi1ieTogRG9uZ3dvbiBLaW0gPGRvbmd3b24ua2ltQGludGVsLmNvbT4KU2lnbmVkLW9m Zi1ieTogTWF0ZXVzeiBQb2xyb2xhIDxtYXRldXN6eC5wb3Ryb2xhQGludGVsLmNvbT4KLS0tCiBk cml2ZXJzL3hlbi9LY29uZmlnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgMiAr CiBkcml2ZXJzL3hlbi9NYWtlZmlsZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAg MSArCiBkcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvS2NvbmZpZyAgICAgICAgICAgICAgICAgICB8 ICAxNCArCiBkcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvTWFrZWZpbGUgICAgICAgICAgICAgICAg ICB8ICAzNCArCiBkcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX2NvbmYuaCAg ICAgICB8ICAgMiArCiBkcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX2Rydi5j ICAgICAgICB8ICA1NCArKwogZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9k cnYuaCAgICAgICAgfCAxMDEgKysrCiBkcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1h YnVmX2ltcC5jICAgICAgICB8IDg1MiArKysrKysrKysrKysrKysrKysrKysKIGRyaXZlcnMveGVu L2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfaW1wLmggICAgICAgIHwgIDMxICsKIGRyaXZlcnMv eGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfaW9jdGwuYyAgICAgIHwgNDYyICsrKysrKysr KysrCiBkcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX2xpc3QuYyAgICAgICB8 IDExOSArKysKIGRyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfbGlzdC5oICAg ICAgIHwgIDQwICsKIGRyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfbXNnLmMg ICAgICAgIHwgMjEyICsrKysrCiBkcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVm X21zZy5oICAgICAgICB8ICA0NSArKwogZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5cGVyX2Rt YWJ1Zl9xdWVyeS5oICAgICAgfCAgMTYgKwogZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5cGVy X2RtYWJ1Zl9zdHJ1Y3QuaCAgICAgfCAgNzAgKysKIC4uLi94ZW4vaHlwZXJfZG1hYnVmL3hlbi9o eXBlcl9kbWFidWZfeGVuX2NvbW0uYyAgIHwgMzI4ICsrKysrKysrCiAuLi4veGVuL2h5cGVyX2Rt YWJ1Zi94ZW4vaHlwZXJfZG1hYnVmX3hlbl9jb21tLmggICB8ICA2MiArKwogLi4uL2h5cGVyX2Rt YWJ1Zi94ZW4vaHlwZXJfZG1hYnVmX3hlbl9jb21tX2xpc3QuYyAgfCAxMDYgKysrCiAuLi4vaHlw ZXJfZG1hYnVmL3hlbi9oeXBlcl9kbWFidWZfeGVuX2NvbW1fbGlzdC5oICB8ICAzNSArCiAyMCBm aWxlcyBjaGFuZ2VkLCAyNTg2IGluc2VydGlvbnMoKykKIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2 ZXJzL3hlbi9oeXBlcl9kbWFidWYvS2NvbmZpZwogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMv eGVuL2h5cGVyX2RtYWJ1Zi9NYWtlZmlsZQogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMveGVu L2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfY29uZi5oCiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJp dmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9kcnYuYwogY3JlYXRlIG1vZGUgMTAw NjQ0IGRyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfZHJ2LmgKIGNyZWF0ZSBt b2RlIDEwMDY0NCBkcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX2ltcC5jCiBj cmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9p bXAuaAogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9k bWFidWZfaW9jdGwuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMveGVuL2h5cGVyX2RtYWJ1 Zi9oeXBlcl9kbWFidWZfbGlzdC5jCiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy94ZW4vaHlw ZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9saXN0LmgKIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJz L3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX21zZy5jCiBjcmVhdGUgbW9kZSAxMDA2NDQg ZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9tc2cuaAogY3JlYXRlIG1vZGUg MTAwNjQ0IGRyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfcXVlcnkuaAogY3Jl YXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfc3Ry dWN0LmgKIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYveGVuL2h5 cGVyX2RtYWJ1Zl94ZW5fY29tbS5jCiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy94ZW4vaHlw ZXJfZG1hYnVmL3hlbi9oeXBlcl9kbWFidWZfeGVuX2NvbW0uaAogY3JlYXRlIG1vZGUgMTAwNjQ0 IGRyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi94ZW4vaHlwZXJfZG1hYnVmX3hlbl9jb21tX2xpc3Qu YwogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi94ZW4vaHlwZXJf ZG1hYnVmX3hlbl9jb21tX2xpc3QuaAoKZGlmZiAtLWdpdCBhL2RyaXZlcnMveGVuL0tjb25maWcg Yi9kcml2ZXJzL3hlbi9LY29uZmlnCmluZGV4IGQ4ZGQ1NDYuLmI1OWIwZTMgMTAwNjQ0Ci0tLSBh L2RyaXZlcnMveGVuL0tjb25maWcKKysrIGIvZHJpdmVycy94ZW4vS2NvbmZpZwpAQCAtMzIxLDQg KzMyMSw2IEBAIGNvbmZpZyBYRU5fU1lNUwogY29uZmlnIFhFTl9IQVZFX1ZQTVUKICAgICAgICBi b29sCiAKK3NvdXJjZSAiZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL0tjb25maWciCisKIGVuZG1l bnUKZGlmZiAtLWdpdCBhL2RyaXZlcnMveGVuL01ha2VmaWxlIGIvZHJpdmVycy94ZW4vTWFrZWZp bGUKaW5kZXggNDUxZTgzMy4uYTZlMjUzYSAxMDA2NDQKLS0tIGEvZHJpdmVycy94ZW4vTWFrZWZp bGUKKysrIGIvZHJpdmVycy94ZW4vTWFrZWZpbGUKQEAgLTQsNiArNCw3IEBAIG9iai0kKENPTkZJ R19YODYpCQkJKz0gZmFsbGJhY2subwogb2JqLXkJKz0gZ3JhbnQtdGFibGUubyBmZWF0dXJlcy5v IGJhbGxvb24ubyBtYW5hZ2UubyBwcmVlbXB0Lm8gdGltZS5vCiBvYmoteQkrPSBldmVudHMvCiBv YmoteQkrPSB4ZW5idXMvCitvYmoteQkrPSBoeXBlcl9kbWFidWYvCiAKIG5vc3RhY2twIDo9ICQo Y2FsbCBjYy1vcHRpb24sIC1mbm8tc3RhY2stcHJvdGVjdG9yKQogQ0ZMQUdTX2ZlYXR1cmVzLm8J CQk6PSAkKG5vc3RhY2twKQpkaWZmIC0tZ2l0IGEvZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL0tj b25maWcgYi9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvS2NvbmZpZwpuZXcgZmlsZSBtb2RlIDEw MDY0NAppbmRleCAwMDAwMDAwLi43NWUxZjk2Ci0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy94 ZW4vaHlwZXJfZG1hYnVmL0tjb25maWcKQEAgLTAsMCArMSwxNCBAQAorbWVudSAiaHlwZXJfZG1h YnVmIG9wdGlvbnMiCisKK2NvbmZpZyBIWVBFUl9ETUFCVUYKKwl0cmlzdGF0ZSAiRW5hYmxlcyBo eXBlciBkbWFidWYgZHJpdmVyIgorCWRlZmF1bHQgeQorCitjb25maWcgSFlQRVJfRE1BQlVGX1hF TgorCWJvb2wgIkNvbmZpZ3VyZSBoeXBlcl9kbWFidWYgZm9yIFhFTiBoeXBlcnZpc29yIgorCWRl ZmF1bHQgeQorCWRlcGVuZHMgb24gSFlQRVJfRE1BQlVGCisJaGVscAorCSAgQ29uZmlndXJpbmcg aHlwZXJfZG1hYnVmIGRyaXZlciBmb3IgWEVOIGh5cGVydmlzb3IKKworZW5kbWVudQpkaWZmIC0t Z2l0IGEvZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL01ha2VmaWxlIGIvZHJpdmVycy94ZW4vaHlw ZXJfZG1hYnVmL01ha2VmaWxlCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLjBi ZTc0NDUKLS0tIC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvTWFrZWZp bGUKQEAgLTAsMCArMSwzNCBAQAorVEFSR0VUX01PRFVMRTo9aHlwZXJfZG1hYnVmCisKKyMgSWYg d2UgcnVubmluZyBieSBrZXJuZWwgYnVpbGRpbmcgc3lzdGVtCitpZm5lcSAoJChLRVJORUxSRUxF QVNFKSwpCisJJChUQVJHRVRfTU9EVUxFKS1vYmpzIDo9IGh5cGVyX2RtYWJ1Zl9kcnYubyBcCisg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoeXBlcl9kbWFidWZfaW9jdGwubyBcCisg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoeXBlcl9kbWFidWZfbGlzdC5vIFwKKwkJ CQkgaHlwZXJfZG1hYnVmX2ltcC5vIFwKKwkJCQkgaHlwZXJfZG1hYnVmX21zZy5vIFwKKwkJCQkg eGVuL2h5cGVyX2RtYWJ1Zl94ZW5fY29tbS5vIFwKKwkJCQkgeGVuL2h5cGVyX2RtYWJ1Zl94ZW5f Y29tbV9saXN0Lm8KKworb2JqLSQoQ09ORklHX0hZUEVSX0RNQUJVRikgOj0gJChUQVJHRVRfTU9E VUxFKS5vCisKKyMgSWYgd2UgYXJlIHJ1bm5pbmcgd2l0aG91dCBrZXJuZWwgYnVpbGQgc3lzdGVt CitlbHNlCitCVUlMRFNZU1RFTV9ESVI/PS4uLy4uLy4uLworUFdEOj0kKHNoZWxsIHB3ZCkKKwor YWxsIDoKKyMgcnVuIGtlcm5lbCBidWlsZCBzeXN0ZW0gdG8gbWFrZSBtb2R1bGUKKyQoTUFLRSkg LUMgJChCVUlMRFNZU1RFTV9ESVIpIE09JChQV0QpIG1vZHVsZXMKKworY2xlYW46CisjIHJ1biBr ZXJuZWwgYnVpbGQgc3lzdGVtIHRvIGNsZWFudXAgaW4gY3VycmVudCBkaXJlY3RvcnkKKyQoTUFL RSkgLUMgJChCVUlMRFNZU1RFTV9ESVIpIE09JChQV0QpIGNsZWFuCisKK2xvYWQ6CisJaW5zbW9k IC4vJChUQVJHRVRfTU9EVUxFKS5rbworCit1bmxvYWQ6CisJcm1tb2QgLi8kKFRBUkdFVF9NT0RV TEUpLmtvCisKK2VuZGlmCmRpZmYgLS1naXQgYS9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlw ZXJfZG1hYnVmX2NvbmYuaCBiL2RyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZf Y29uZi5oCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLjNkOWIyZDYKLS0tIC9k ZXYvbnVsbAorKysgYi9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX2NvbmYu aApAQCAtMCwwICsxLDIgQEAKKyNkZWZpbmUgQ1VSUkVOVF9UQVJHRVQgWEVOCisjZGVmaW5lIElO VEVSX0RPTUFJTl9ETUFCVUZfU1lOQ0hST05JWkFUSU9OCmRpZmYgLS1naXQgYS9kcml2ZXJzL3hl bi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX2Rydi5jIGIvZHJpdmVycy94ZW4vaHlwZXJfZG1h YnVmL2h5cGVyX2RtYWJ1Zl9kcnYuYwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAw Li4wNjk4MzI3Ci0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5 cGVyX2RtYWJ1Zl9kcnYuYwpAQCAtMCwwICsxLDU0IEBACisjaW5jbHVkZSA8bGludXgvaW5pdC5o PiAgICAgICAvKiBtb2R1bGVfaW5pdCwgbW9kdWxlX2V4aXQgKi8KKyNpbmNsdWRlIDxsaW51eC9t b2R1bGUuaD4gLyogdmVyc2lvbiBpbmZvLCBNT0RVTEVfTElDRU5TRSwgTU9EVUxFX0FVVEhPUiwg cHJpbnRrKCkgKi8KKyNpbmNsdWRlICJoeXBlcl9kbWFidWZfY29uZi5oIgorI2luY2x1ZGUgImh5 cGVyX2RtYWJ1Zl9saXN0LmgiCisjaW5jbHVkZSAieGVuL2h5cGVyX2RtYWJ1Zl94ZW5fY29tbV9s aXN0LmgiCisKK01PRFVMRV9MSUNFTlNFKCJEdWFsIEJTRC9HUEwiKTsKK01PRFVMRV9BVVRIT1Io IklPVEctUEVELCBJTlRFTCIpOworCitpbnQgcmVnaXN0ZXJfZGV2aWNlKHZvaWQpOworaW50IHVu cmVnaXN0ZXJfZGV2aWNlKHZvaWQpOworCisvKj09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09Ki8KK3N0YXRpYyBpbnQgaHlwZXJfZG1hYnVmX2Rydl9pbml0KHZvaWQpCit7CisJ aW50IHJldCA9IDA7CisKKwlwcmludGsoIEtFUk5fTk9USUNFICJoeXBlcl9kbWFidWZfc3RhcnRp bmc6IEluaXRpYWxpemF0aW9uIHN0YXJ0ZWQiICk7CisKKwlyZXQgPSByZWdpc3Rlcl9kZXZpY2Uo KTsKKwlpZiAocmV0IDwgMCkgeworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisKKwlwcmludGsoIEtF Uk5fTk9USUNFICJpbml0aWFsaXppbmcgZGF0YWJhc2UgZm9yIGltcG9ydGVkL2V4cG9ydGVkIGRt YWJ1ZnNcbiIpOworCisJcmV0ID0gaHlwZXJfZG1hYnVmX3RhYmxlX2luaXQoKTsKKwlpZiAocmV0 IDwgMCkgeworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisKKwlyZXQgPSBoeXBlcl9kbWFidWZfcmlu Z190YWJsZV9pbml0KCk7CisJaWYgKHJldCA8IDApIHsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQor CisJLyogaW50ZXJydXB0IGZvciBjb21tIHNob3VsZCBiZSByZWdpc3RlcmVkIGhlcmU6ICovCisJ cmV0dXJuIHJldDsKK30KKworLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LSovCitzdGF0aWMgdm9pZCBoeXBlcl9kbWFidWZfZHJ2X2V4aXQodm9pZCkKK3sKKwkvKiBoYXNo IHRhYmxlcyBmb3IgZXhwb3J0L2ltcG9ydCBlbnRyaWVzIGFuZCByaW5nX2luZm9zICovCisJaHlw ZXJfZG1hYnVmX3RhYmxlX2Rlc3Ryb3koKTsKKwloeXBlcl9kbWFidWZfcmluZ190YWJsZV9pbml0 KCk7CisKKwlwcmludGsoIEtFUk5fTk9USUNFICJkbWFfYnVmLXNyY19zaW5rIG1vZGVsOiBFeGl0 aW5nIiApOworCXVucmVnaXN0ZXJfZGV2aWNlKCk7Cit9CisvKj09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09Ki8KKworbW9kdWxlX2luaXQoaHlwZXJfZG1hYnVmX2Rydl9pbml0 KTsKK21vZHVsZV9leGl0KGh5cGVyX2RtYWJ1Zl9kcnZfZXhpdCk7CmRpZmYgLS1naXQgYS9kcml2 ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX2Rydi5oIGIvZHJpdmVycy94ZW4vaHlw ZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9kcnYuaApuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAw MDAwMDAwLi4yZGFkOWE2Ci0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy94ZW4vaHlwZXJfZG1h YnVmL2h5cGVyX2RtYWJ1Zl9kcnYuaApAQCAtMCwwICsxLDEwMSBAQAorI2lmbmRlZiBfX0xJTlVY X1BVQkxJQ19IWVBFUl9ETUFCVUZfRFJWX0hfXworI2RlZmluZSBfX0xJTlVYX1BVQkxJQ19IWVBF Ul9ETUFCVUZfRFJWX0hfXworCit0eXBlZGVmIGludCAoKmh5cGVyX2RtYWJ1Zl9pb2N0bF90KSh2 b2lkICpkYXRhKTsKKworc3RydWN0IGh5cGVyX2RtYWJ1Zl9pb2N0bF9kZXNjIHsKKwl1bnNpZ25l ZCBpbnQgY21kOworCWludCBmbGFnczsKKwloeXBlcl9kbWFidWZfaW9jdGxfdCBmdW5jOworCWNv bnN0IGNoYXIgKm5hbWU7Cit9OworCisjZGVmaW5lIEhZUEVSX0RNQUJVRl9JT0NUTF9ERUYoaW9j dGwsIF9mdW5jLCBfZmxhZ3MpIAlcCisJW19JT0NfTlIoaW9jdGwpXSA9IHsJCQkJXAorCQkJLmNt ZCA9IGlvY3RsLAkJCVwKKwkJCS5mdW5jID0gX2Z1bmMsCQkJXAorCQkJLmZsYWdzID0gX2ZsYWdz LAkJXAorCQkJLm5hbWUgPSAjaW9jdGwJCQlcCisJfQorCisjZGVmaW5lIElPQ1RMX0hZUEVSX0RN QUJVRl9FWFBPUlRFUl9SSU5HX1NFVFVQIFwKK19JT0MoX0lPQ19OT05FLCAnRycsIDAsIHNpemVv ZihzdHJ1Y3QgaW9jdGxfaHlwZXJfZG1hYnVmX2V4cG9ydGVyX3Jpbmdfc2V0dXApKQorc3RydWN0 IGlvY3RsX2h5cGVyX2RtYWJ1Zl9leHBvcnRlcl9yaW5nX3NldHVwIHsKKwkvKiBJTiBwYXJhbWV0 ZXJzICovCisJLyogUmVtb3RlIGRvbWFpbiBpZCAqLworCXVpbnQzMl90IHJlbW90ZV9kb21haW47 CisJZ3JhbnRfcmVmX3QgcmluZ19yZWZpZDsgLyogYXNzaWduZWQgYnkgZHJpdmVyLCBjb3BpZWQg dG8gdXNlcnNwYWNlIGFmdGVyIGluaXRpYWxpemF0aW9uICovCisJdWludDMyX3QgcG9ydDsgLyog YXNzaWduZWQgYnkgZHJpdmVyLCBjb3BpZWQgdG8gdXNlcnNwYWNlIGFmdGVyIGluaXRpYWxpemF0 aW9uICovCit9OworCisjZGVmaW5lIElPQ1RMX0hZUEVSX0RNQUJVRl9JTVBPUlRFUl9SSU5HX1NF VFVQIFwKK19JT0MoX0lPQ19OT05FLCAnRycsIDEsIHNpemVvZihzdHJ1Y3QgaW9jdGxfaHlwZXJf ZG1hYnVmX2ltcG9ydGVyX3Jpbmdfc2V0dXApKQorc3RydWN0IGlvY3RsX2h5cGVyX2RtYWJ1Zl9p bXBvcnRlcl9yaW5nX3NldHVwIHsKKwkvKiBJTiBwYXJhbWV0ZXJzICovCisJLyogU291cmNlIGRv bWFpbiBpZCAqLworCXVpbnQzMl90IHNvdXJjZV9kb21haW47CisJLyogUmluZyBzaGFyZWQgcGFn ZSByZWZpZCAqLworCWdyYW50X3JlZl90IHJpbmdfcmVmaWQ7CisJLyogUG9ydCBudW1iZXIgKi8K Kwl1aW50MzJfdCBwb3J0OworfTsKKworI2RlZmluZSBJT0NUTF9IWVBFUl9ETUFCVUZfRVhQT1JU X1JFTU9URSBcCitfSU9DKF9JT0NfTk9ORSwgJ0cnLCAyLCBzaXplb2Yoc3RydWN0IGlvY3RsX2h5 cGVyX2RtYWJ1Zl9leHBvcnRfcmVtb3RlKSkKK3N0cnVjdCBpb2N0bF9oeXBlcl9kbWFidWZfZXhw b3J0X3JlbW90ZSB7CisJLyogSU4gcGFyYW1ldGVycyAqLworCS8qIERNQSBidWYgZmQgdG8gYmUg ZXhwb3J0ZWQgKi8KKwl1aW50MzJfdCBkbWFidWZfZmQ7CisJLyogRG9tYWluIGlkIHRvIHdoaWNo IGJ1ZmZlciBzaG91bGQgYmUgZXhwb3J0ZWQgKi8KKwl1aW50MzJfdCByZW1vdGVfZG9tYWluOwor CS8qIGV4cG9ydGVkIGRtYSBidWYgaWQgKi8KKwl1aW50MzJfdCBoeXBlcl9kbWFidWZfaWQ7CisJ dWludDMyX3QgcHJpdmF0ZVs0XTsKK307CisKKyNkZWZpbmUgSU9DVExfSFlQRVJfRE1BQlVGX0VY UE9SVF9GRCBcCitfSU9DKF9JT0NfTk9ORSwgJ0cnLCAzLCBzaXplb2Yoc3RydWN0IGlvY3RsX2h5 cGVyX2RtYWJ1Zl9leHBvcnRfZmQpKQorc3RydWN0IGlvY3RsX2h5cGVyX2RtYWJ1Zl9leHBvcnRf ZmQgeworCS8qIElOIHBhcmFtZXRlcnMgKi8KKwkvKiBoeXBlciBkbWFidWYgaWQgdG8gYmUgaW1w b3J0ZWQgKi8KKwl1aW50MzJfdCBoeXBlcl9kbWFidWZfaWQ7CisJLyogZmxhZ3MgKi8KKwl1aW50 MzJfdCBmbGFnczsKKwkvKiBPVVQgcGFyYW1ldGVycyAqLworCS8qIGV4cG9ydGVkIGRtYSBidWYg ZmQgKi8KKwl1aW50MzJfdCBmZDsKK307CisKKyNkZWZpbmUgSU9DVExfSFlQRVJfRE1BQlVGX0RF U1RST1kgXAorX0lPQyhfSU9DX05PTkUsICdHJywgNCwgc2l6ZW9mKHN0cnVjdCBpb2N0bF9oeXBl cl9kbWFidWZfZGVzdHJveSkpCitzdHJ1Y3QgaW9jdGxfaHlwZXJfZG1hYnVmX2Rlc3Ryb3kgewor CS8qIElOIHBhcmFtZXRlcnMgKi8KKwkvKiBoeXBlciBkbWFidWYgaWQgdG8gYmUgZGVzdHJveWVk ICovCisJdWludDMyX3QgaHlwZXJfZG1hYnVmX2lkOworCS8qIE9VVCBwYXJhbWV0ZXJzICovCisJ LyogU3RhdHVzIG9mIHJlcXVlc3QgKi8KKwl1aW50MzJfdCBzdGF0dXM7Cit9OworCisjZGVmaW5l IElPQ1RMX0hZUEVSX0RNQUJVRl9RVUVSWSBcCitfSU9DKF9JT0NfTk9ORSwgJ0cnLCA1LCBzaXpl b2Yoc3RydWN0IGlvY3RsX2h5cGVyX2RtYWJ1Zl9xdWVyeSkpCitzdHJ1Y3QgaW9jdGxfaHlwZXJf ZG1hYnVmX3F1ZXJ5IHsKKwkvKiBpbiBwYXJhbWV0ZXJzICovCisJLyogaHlwZXIgZG1hYnVmIGlk IHRvIGJlIHF1ZXJpZWQgKi8KKwl1aW50MzJfdCBoeXBlcl9kbWFidWZfaWQ7CisJLyogaXRlbSB0 byBiZSBxdWVyaWVkICovCisJdWludDMyX3QgaXRlbTsKKwkvKiBPVVQgcGFyYW1ldGVycyAqLwor CS8qIFZhbHVlIG9mIHF1ZXJpZWQgaXRlbSAqLworCXVpbnQzMl90IGluZm87Cit9OworCisjZGVm aW5lIElPQ1RMX0hZUEVSX0RNQUJVRl9SRU1PVEVfRVhQT1JURVJfUklOR19TRVRVUCBcCitfSU9D KF9JT0NfTk9ORSwgJ0cnLCA2LCBzaXplb2Yoc3RydWN0IGlvY3RsX2h5cGVyX2RtYWJ1Zl9yZW1v dGVfZXhwb3J0ZXJfcmluZ19zZXR1cCkpCitzdHJ1Y3QgaW9jdGxfaHlwZXJfZG1hYnVmX3JlbW90 ZV9leHBvcnRlcl9yaW5nX3NldHVwIHsKKwkvKiBpbiBwYXJhbWV0ZXJzICovCisJdWludDMyX3Qg cmRvbWFpbjsgLyogaWQgb2YgcmVtb3RlIGRvbWFpbiB3aGVyZSBleHBvcnRlcidzIHJpbmcgbmVl ZCB0byBiZSBzZXR1cCAqLworCXVpbnQzMl90IGluZm87Cit9OworCisjZW5kaWYgLy9fX0xJTlVY X1BVQkxJQ19IWVBFUl9ETUFCVUZfRFJWX0hfXwpkaWZmIC0tZ2l0IGEvZHJpdmVycy94ZW4vaHlw ZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9pbXAuYyBiL2RyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9o eXBlcl9kbWFidWZfaW1wLmMKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uZmFh NWMxYgotLS0gL2Rldi9udWxsCisrKyBiL2RyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9k bWFidWZfaW1wLmMKQEAgLTAsMCArMSw4NTIgQEAKKyNpbmNsdWRlIDxsaW51eC9rZXJuZWwuaD4K KyNpbmNsdWRlIDxsaW51eC9lcnJuby5oPgorI2luY2x1ZGUgPGxpbnV4L3NsYWIuaD4KKyNpbmNs dWRlIDxsaW51eC9tb2R1bGUuaD4KKyNpbmNsdWRlIDxsaW51eC9kbWEtYnVmLmg+CisjaW5jbHVk ZSA8eGVuL2dyYW50X3RhYmxlLmg+CisjaW5jbHVkZSA8YXNtL3hlbi9wYWdlLmg+CisjaW5jbHVk ZSAiaHlwZXJfZG1hYnVmX3N0cnVjdC5oIgorI2luY2x1ZGUgImh5cGVyX2RtYWJ1Zl9pbXAuaCIK KyNpbmNsdWRlICJ4ZW4vaHlwZXJfZG1hYnVmX3hlbl9jb21tLmgiCisjaW5jbHVkZSAiaHlwZXJf ZG1hYnVmX21zZy5oIgorCisjZGVmaW5lIFJFRlNfUEVSX1BBR0UgKFBBR0VfU0laRS9zaXplb2Yo Z3JhbnRfcmVmX3QpKQorCisvKiByZXR1cm4gdG90YWwgbnVtYmVyIG9mIHBhZ2VzIHJlZmVyZWNu ZWQgYnkgYSBzZ3QKKyAqIGZvciBwcmUtY2FsY3VsYXRpb24gb2YgIyBvZiBwYWdlcyBiZWhpbmQg YSBnaXZlbiBzZ3QKKyAqLworc3RhdGljIGludCBoeXBlcl9kbWFidWZfZ2V0X251bV9wZ3Moc3Ry dWN0IHNnX3RhYmxlICpzZ3QpCit7CisJc3RydWN0IHNjYXR0ZXJsaXN0ICpzZ2w7CisJaW50IGxl bmd0aCwgaTsKKwkvKiBhdCBsZWFzdCBvbmUgcGFnZSAqLworCWludCBudW1fcGFnZXMgPSAxOwor CisJc2dsID0gc2d0LT5zZ2w7CisKKwlsZW5ndGggPSBzZ2wtPmxlbmd0aCAtIFBBR0VfU0laRSAr IHNnbC0+b2Zmc2V0OworCW51bV9wYWdlcyArPSAoKGxlbmd0aCArIFBBR0VfU0laRSAtIDEpL1BB R0VfU0laRSk7IC8qIHJvdW5kLXVwICovCisKKwlmb3IgKGkgPSAxOyBpIDwgc2d0LT5uZW50czsg aSsrKSB7CisJCXNnbCA9IHNnX25leHQoc2dsKTsKKwkJbnVtX3BhZ2VzICs9ICgoc2dsLT5sZW5n dGggKyBQQUdFX1NJWkUgLSAxKSAvIFBBR0VfU0laRSk7IC8qIHJvdW5kLXVwICovCisJfQorCisJ cmV0dXJuIG51bV9wYWdlczsKK30KKworLyogZXh0cmFjdCBwYWdlcyBkaXJlY3RseSBmcm9tIHN0 cnVjdCBzZ190YWJsZSAqLworc3RydWN0IGh5cGVyX2RtYWJ1Zl9wYWdlc19pbmZvICpoeXBlcl9k bWFidWZfZXh0X3BncyhzdHJ1Y3Qgc2dfdGFibGUgKnNndCkKK3sKKwlzdHJ1Y3QgaHlwZXJfZG1h YnVmX3BhZ2VzX2luZm8gKnBpbmZvOworCWludCBpLCBqOworCWludCBsZW5ndGg7CisJc3RydWN0 IHNjYXR0ZXJsaXN0ICpzZ2w7CisKKwlwaW5mbyA9IGttYWxsb2Moc2l6ZW9mKCpwaW5mbyksIEdG UF9LRVJORUwpOworCWlmIChwaW5mbyA9PSBOVUxMKQorCQlyZXR1cm4gTlVMTDsKKworCXBpbmZv LT5wYWdlcyA9IGttYWxsb2Moc2l6ZW9mKHN0cnVjdCBwYWdlICopKmh5cGVyX2RtYWJ1Zl9nZXRf bnVtX3BncyhzZ3QpLCBHRlBfS0VSTkVMKTsKKwlpZiAocGluZm8tPnBhZ2VzID09IE5VTEwpCisJ CXJldHVybiBOVUxMOworCisJc2dsID0gc2d0LT5zZ2w7CisKKwlwaW5mby0+bmVudHMgPSAxOwor CXBpbmZvLT5mcnN0X29mc3QgPSBzZ2wtPm9mZnNldDsKKwlwaW5mby0+cGFnZXNbMF0gPSBzZ19w YWdlKHNnbCk7CisJbGVuZ3RoID0gc2dsLT5sZW5ndGggLSBQQUdFX1NJWkUgKyBzZ2wtPm9mZnNl dDsKKwlpPTE7CisKKwl3aGlsZSAobGVuZ3RoID4gMCkgeworCQlwaW5mby0+cGFnZXNbaV0gPSBu dGhfcGFnZShzZ19wYWdlKHNnbCksIGkpOworCQlsZW5ndGggLT0gUEFHRV9TSVpFOworCQlwaW5m by0+bmVudHMrKzsKKwkJaSsrOworCX0KKworCWZvciAoaiA9IDE7IGogPCBzZ3QtPm5lbnRzOyBq KyspIHsKKwkJc2dsID0gc2dfbmV4dChzZ2wpOworCQlwaW5mby0+cGFnZXNbaSsrXSA9IHNnX3Bh Z2Uoc2dsKTsKKwkJbGVuZ3RoID0gc2dsLT5sZW5ndGggLSBQQUdFX1NJWkU7CisJCXBpbmZvLT5u ZW50cysrOworCisJCXdoaWxlIChsZW5ndGggPiAwKSB7CisJCQlwaW5mby0+cGFnZXNbaV0gPSBu dGhfcGFnZShzZ19wYWdlKHNnbCksIGkpOworCQkJbGVuZ3RoIC09IFBBR0VfU0laRTsKKwkJCXBp bmZvLT5uZW50cysrOworCQkJaSsrOworCQl9CisJfQorCisJLyoKKwkgKiBsZW5naHQgYXQgdGhh dCBwb2ludCB3aWxsIGJlIDAgb3IgbmVnYXRpdmUsCisJICogc28gdG8gY2FsY3VsYXRlIGxhc3Qg cGFnZSBzaXplIGp1c3QgYWRkIGl0IHRvIFBBR0VfU0laRQorCSAqLworCXBpbmZvLT5sYXN0X2xl biA9IFBBR0VfU0laRSArIGxlbmd0aDsKKworCXJldHVybiBwaW5mbzsKK30KKworLyogY3JlYXRl IHNnX3RhYmxlIHdpdGggZ2l2ZW4gcGFnZXMgYW5kIG90aGVyIHBhcmFtZXRlcnMgKi8KK3N0cnVj dCBzZ190YWJsZSogaHlwZXJfZG1hYnVmX2NyZWF0ZV9zZ3Qoc3RydWN0IHBhZ2UgKipwYWdlcywK KwkJCQlpbnQgZnJzdF9vZnN0LCBpbnQgbGFzdF9sZW4sIGludCBuZW50cykKK3sKKwlzdHJ1Y3Qg c2dfdGFibGUgKnNndDsKKwlzdHJ1Y3Qgc2NhdHRlcmxpc3QgKnNnbDsKKwlpbnQgaSwgcmV0Owor CisJc2d0ID0ga21hbGxvYyhzaXplb2Yoc3RydWN0IHNnX3RhYmxlKSwgR0ZQX0tFUk5FTCk7CisJ aWYgKHNndCA9PSBOVUxMKSB7CisJCXJldHVybiBOVUxMOworCX0KKworCXJldCA9IHNnX2FsbG9j X3RhYmxlKHNndCwgbmVudHMsIEdGUF9LRVJORUwpOworCWlmIChyZXQpIHsKKwkJa2ZyZWUoc2d0 KTsKKwkJcmV0dXJuIE5VTEw7CisJfQorCisJc2dsID0gc2d0LT5zZ2w7CisKKwlzZ19zZXRfcGFn ZShzZ2wsIHBhZ2VzWzBdLCBQQUdFX1NJWkUtZnJzdF9vZnN0LCBmcnN0X29mc3QpOworCisJZm9y IChpPTE7IGk8bmVudHMtMTsgaSsrKSB7CisJCXNnbCA9IHNnX25leHQoc2dsKTsKKwkJc2dfc2V0 X3BhZ2Uoc2dsLCBwYWdlc1tpXSwgUEFHRV9TSVpFLCAwKTsKKwl9CisKKwlpZiAoaSA+IDEpIC8q IG1vcmUgdGhhbiBvbmUgcGFnZSAqLyB7CisJCXNnbCA9IHNnX25leHQoc2dsKTsKKwkJc2dfc2V0 X3BhZ2Uoc2dsLCBwYWdlc1tpXSwgbGFzdF9sZW4sIDApOworCX0KKworCXJldHVybiBzZ3Q7Cit9 CisKKy8qCisgKiBDcmVhdGVzIDIgbGV2ZWwgcGFnZSBkaXJlY3Rvcnkgc3RydWN0dXJlIGZvciBy ZWZlcmVuY2luZyBzaGFyZWQgcGFnZXMuCisgKiBUb3AgbGV2ZWwgcGFnZSBpcyBhIHNpbmdsZSBw YWdlIHRoYXQgY29udGFpbnMgdXAgdG8gMTAyNCByZWZpZHMgdGhhdAorICogcG9pbnQgdG8gMm5k IGxldmVsIHBhZ2VzLgorICogRWFjaCAybmQgbGV2ZWwgcGFnZSBjb250YWlucyB1cCB0byAxMDI0 IHJlZmlkcyB0aGF0IHBvaW50IHRvIHNoYXJlZAorICogZGF0YSBwYWdlcy4KKyAqIFRoZXJlIHdp bGwgYWx3YXlzIGJlIG9uZSB0b3AgbGV2ZWwgcGFnZSBhbmQgbnVtYmVyIG9mIDJuZCBsZXZlbCBw YWdlcworICogZGVwZW5kcyBvbiBudW1iZXIgb2Ygc2hhcmVkIGRhdGEgcGFnZXMuCisgKgorICog ICAgICBUb3AgbGV2ZWwgcGFnZSAgICAgICAgICAgICAgICAybmQgbGV2ZWwgcGFnZXMgICAgICAg ICAgICBEYXRhIHBhZ2VzCisgKiArLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsgICDilIw+Ky0t LS0tLS0tLS0tLS0tLS0tLS0tKyDilIwtLS0+Ky0tLS0tLS0tLS0tLSsKKyAqIHwybmQgbGV2ZWwg cGFnZSAwIHJlZmlkICAgfC0tLeKUmCB8RGF0YSBwYWdlIDAgcmVmaWQgICB8LeKUmCAgICB8RGF0 YSBwYWdlIDAgfAorICogfDJuZCBsZXZlbCBwYWdlIDEgcmVmaWQgICB8LS0t4pSQIHxEYXRhIHBh Z2UgMSByZWZpZCAgIHwt4pSQICAgICstLS0tLS0tLS0tLS0rCisgKiB8ICAgICAgICAgICAuLi4g ICAgICAgICAgIHwgICB8IHwgICAgIC4uLi4gICAgICAgICAgIHwgfAorICogfDJuZCBsZXZlbCBw YWdlIDEwMjMgcmVmaWR8LeKUkCB8IHxEYXRhIHBhZ2UgMTAyMyByZWZpZHwg4pSULS0tPistLS0t LS0tLS0tLS0rCisgKiArLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsgfCB8ICstLS0tLS0tLS0t LS0tLS0tLS0tLSsgICAgICB8RGF0YSBwYWdlIDEgfAorICogICAgICAgICAgICAgICAgICAgICAg ICAgICAgIHwgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKy0tLS0tLS0tLS0tLSsKKyAq ICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IOKUlD4rLS0tLS0tLS0tLS0tLS0tLS0tLS0r CisgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAgIHxEYXRhIHBhZ2UgMTAyNCByZWZp ZHwKKyAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgfERhdGEgcGFnZSAxMDI1IHJl ZmlkfAorICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICB8ICAgICAgIC4uLiAgICAg ICAgICB8CisgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAgIHxEYXRhIHBhZ2UgMjA0 NyByZWZpZHwKKyAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgKy0tLS0tLS0tLS0t LS0tLS0tLS0tKworICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKKyAqICAgICAgICAg ICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAuLi4uLgorICogICAgICAgICAgICAgICAgICAg ICAgICAgICAgIOKUlC0tPistLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKKyAqICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgfERhdGEgcGFnZSAxMDQ3NTUyIHJlZmlkfAorICogICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICB8RGF0YSBwYWdlIDEwNDc1NTMgcmVmaWR8CisgKiAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgLi4uICAgICAgICAgICAgIHwK KyAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfERhdGEgcGFnZSAxMDQ4NTc1IHJl ZmlkfC0tPistLS0tLS0tLS0tLS0tLS0tLS0rCisgKiAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsgICB8RGF0YSBwYWdlIDEwNDg1NzUgfAor ICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgKy0tLS0tLS0tLS0tLS0tLS0tLSsKKyAqCisgKiBVc2luZyBzdWNoIDIgbGV2ZWwgc3Ry dWN0dXJlIGl0IGlzIHBvc3NpYmxlIHRvIHJlZmVyZW5jZSB1cCB0byA0R0Igb2YKKyAqIHNoYXJl ZCBkYXRhIHVzaW5nIHNpbmdsZSByZWZpZCBwb2ludGluZyB0byB0b3AgbGV2ZWwgcGFnZS4KKyAq CisgKiBSZXR1cm5zIHJlZmlkIG9mIHRvcCBsZXZlbCBwYWdlLgorICovCitncmFudF9yZWZfdCBo eXBlcl9kbWFidWZfY3JlYXRlX2FkZHJlc3NpbmdfdGFibGVzKGdyYW50X3JlZl90ICpkYXRhX3Jl ZnMsIGludCBuZW50cywgaW50IHJkb21haW4sCisJCQkJCQkgIHN0cnVjdCBoeXBlcl9kbWFidWZf c2hhcmVkX3BhZ2VzX2luZm8gKnNoYXJlZF9wYWdlc19pbmZvKQoreworCS8qCisJICogQ2FsY3Vs YXRlIG51bWJlciBvZiBwYWdlcyBuZWVkZWQgZm9yIDJuZCBsZXZlbCBhZGRyZXNpbmc6CisJICov CisJaW50IG5fMm5kX2xldmVsX3BhZ2VzID0gKG5lbnRzL1JFRlNfUEVSX1BBR0UgKyAoKG5lbnRz ICUgUkVGU19QRVJfUEFHRSkgPyAxOiAwKSk7Lyogcm91bmRpbmcgKi8KKwlpbnQgaTsKKwl1bnNp Z25lZCBsb25nIGdyZWZfcGFnZV9zdGFydDsKKwlncmFudF9yZWZfdCAqdG1wX3BhZ2U7CisJZ3Jh bnRfcmVmX3QgdG9wX2xldmVsX3JlZjsKKwlncmFudF9yZWZfdCAqIGFkZHJfcmVmczsKKwlhZGRy X3JlZnMgPSBrY2FsbG9jKHNpemVvZihncmFudF9yZWZfdCksIG5fMm5kX2xldmVsX3BhZ2VzLCBH RlBfS0VSTkVMKTsKKworCWdyZWZfcGFnZV9zdGFydCA9IF9fZ2V0X2ZyZWVfcGFnZXMoR0ZQX0tF Uk5FTCwgbl8ybmRfbGV2ZWxfcGFnZXMpOworCXRtcF9wYWdlID0gKGdyYW50X3JlZl90ICopZ3Jl Zl9wYWdlX3N0YXJ0OworCisJLyogU3RvcmUgMm5kIGxldmVsIHBhZ2VzIHRvIGJlIGZyZWVkIGxh dGVyICovCisJc2hhcmVkX3BhZ2VzX2luZm8tPmFkZHJfcGFnZXMgPSB0bXBfcGFnZTsKKworCS8q VE9ETzogbWFrZSBzdXJlIHRoYXQgYWxsb2NhdGVkIG1lbW9yeSBpcyBmaWxsZWQgd2l0aCAwKi8K KworCS8qIFNoYXJlIDJuZCBsZXZlbCBhZGRyZXNzaW5nIHBhZ2VzIGluIHJlYWRvbmx5IG1vZGUq LworCWZvciAoaT0wOyBpPCBuXzJuZF9sZXZlbF9wYWdlczsgaSsrKSB7CisJCWFkZHJfcmVmc1tp XSA9IGdudHRhYl9ncmFudF9mb3JlaWduX2FjY2VzcyhyZG9tYWluLCB2aXJ0X3RvX21mbigodW5z aWduZWQgbG9uZyl0bXBfcGFnZStpKlBBR0VfU0laRSApLCAxKTsKKwl9CisKKwkvKgorCSAqIGZp bGwgc2Vjb25kIGxldmVsIHBhZ2VzIHdpdGggZGF0YSByZWZzCisJICovCisJZm9yIChpID0gMDsg aSA8IG5lbnRzOyBpKyspIHsKKwkJdG1wX3BhZ2VbaV0gPSBkYXRhX3JlZnNbaV07CisJfQorCisK KwkvKiBhbGxvY2F0ZSB0b3AgbGV2ZWwgcGFnZSAqLworCWdyZWZfcGFnZV9zdGFydCA9IF9fZ2V0 X2ZyZWVfcGFnZXMoR0ZQX0tFUk5FTCwgMSk7CisJdG1wX3BhZ2UgPSAoZ3JhbnRfcmVmX3QgKiln cmVmX3BhZ2Vfc3RhcnQ7CisKKwkvKiBTdG9yZSB0b3AgbGV2ZWwgcGFnZSB0byBiZSBmcmVlZCBs YXRlciAqLworCXNoYXJlZF9wYWdlc19pbmZvLT50b3BfbGV2ZWxfcGFnZSA9IHRtcF9wYWdlOwor CisJLyoKKwkgKiBmaWxsIHRvcCBsZXZlbCBwYWdlIHdpdGggcmVmZXJlbmNlIG51bWJlcnMgb2Yg c2Vjb25kIGxldmVsIHBhZ2VzIHJlZnMuCisJICovCisJZm9yIChpPTA7IGk8IG5fMm5kX2xldmVs X3BhZ2VzOyBpKyspIHsKKwkJdG1wX3BhZ2VbaV0gPSAgYWRkcl9yZWZzW2ldOworCX0KKworCS8q IFNoYXJlIHRvcCBsZXZlbCBhZGRyZXNzaW5nIHBhZ2UgaW4gcmVhZG9ubHkgbW9kZSovCisJdG9w X2xldmVsX3JlZiA9IGdudHRhYl9ncmFudF9mb3JlaWduX2FjY2VzcyhyZG9tYWluLCB2aXJ0X3Rv X21mbigodW5zaWduZWQgbG9uZyl0bXBfcGFnZSksIDEpOworCisJa2ZyZWUoYWRkcl9yZWZzKTsK KworCXJldHVybiB0b3BfbGV2ZWxfcmVmOworfQorCisvKgorICogTWFwcyBwcm92aWRlZCB0b3Ag bGV2ZWwgcmVmIGlkIGFuZCB0aGVuIHJldHVybiBhcnJheSBvZiBwYWdlcyBjb250YWluaW5nIGRh dGEgcmVmcy4KKyAqLworc3RydWN0IHBhZ2UqKiBoeXBlcl9kbWFidWZfZ2V0X2RhdGFfcmVmcyhn cmFudF9yZWZfdCB0b3BfbGV2ZWxfcmVmLCBpbnQgZG9taWQsIGludCBuZW50cywKKwkJCQkJIHN0 cnVjdCBoeXBlcl9kbWFidWZfc2hhcmVkX3BhZ2VzX2luZm8gKnNoYXJlZF9wYWdlc19pbmZvKQor eworCXN0cnVjdCBwYWdlICp0b3BfbGV2ZWxfcGFnZTsKKwlzdHJ1Y3QgcGFnZSAqKmxldmVsMl9w YWdlczsKKworCWdyYW50X3JlZl90ICp0b3BfbGV2ZWxfcmVmczsKKworCXN0cnVjdCBnbnR0YWJf bWFwX2dyYW50X3JlZiB0b3BfbGV2ZWxfbWFwX29wczsKKwlzdHJ1Y3QgZ250dGFiX3VubWFwX2dy YW50X3JlZiB0b3BfbGV2ZWxfdW5tYXBfb3BzOworCisJc3RydWN0IGdudHRhYl9tYXBfZ3JhbnRf cmVmICptYXBfb3BzOworCXN0cnVjdCBnbnR0YWJfdW5tYXBfZ3JhbnRfcmVmICp1bm1hcF9vcHM7 CisKKwl1bnNpZ25lZCBsb25nIGFkZHI7CisJaW50IG5fbGV2ZWwyX3JlZnMgPSAwOworCWludCBp OworCisJbl9sZXZlbDJfcmVmcyA9IChuZW50cyAvIFJFRlNfUEVSX1BBR0UpICsgKChuZW50cyAl IFJFRlNfUEVSX1BBR0UpID8gMSA6IDApOworCisJbGV2ZWwyX3BhZ2VzID0ga2NhbGxvYyhzaXpl b2Yoc3RydWN0IHBhZ2UqKSwgbl9sZXZlbDJfcmVmcywgR0ZQX0tFUk5FTCk7CisKKwltYXBfb3Bz ID0ga2NhbGxvYyhzaXplb2YobWFwX29wc1swXSksIFJFRlNfUEVSX1BBR0UsIEdGUF9LRVJORUwp OworCXVubWFwX29wcyA9IGtjYWxsb2Moc2l6ZW9mKHVubWFwX29wc1swXSksIFJFRlNfUEVSX1BB R0UsIEdGUF9LRVJORUwpOworCisJLyogTWFwIHRvcCBsZXZlbCBhZGRyZXNzaW5nIHBhZ2UgKi8K KwlpZiAoZ250dGFiX2FsbG9jX3BhZ2VzKDEsICZ0b3BfbGV2ZWxfcGFnZSkpIHsKKwkJcHJpbnRr KCJDYW5ub3QgYWxsb2NhdGUgcGFnZXNcbiIpOworCQlyZXR1cm4gTlVMTDsKKwl9CisKKwlhZGRy ID0gKHVuc2lnbmVkIGxvbmcpcGZuX3RvX2thZGRyKHBhZ2VfdG9fcGZuKHRvcF9sZXZlbF9wYWdl KSk7CisJZ250dGFiX3NldF9tYXBfb3AoJnRvcF9sZXZlbF9tYXBfb3BzLCBhZGRyLCBHTlRNQVBf aG9zdF9tYXAgfCBHTlRNQVBfcmVhZG9ubHksIHRvcF9sZXZlbF9yZWYsIGRvbWlkKTsKKwlnbnR0 YWJfc2V0X3VubWFwX29wKCZ0b3BfbGV2ZWxfdW5tYXBfb3BzLCBhZGRyLCBHTlRNQVBfaG9zdF9t YXAgfCBHTlRNQVBfcmVhZG9ubHksIC0xKTsKKworCWlmIChnbnR0YWJfbWFwX3JlZnMoJnRvcF9s ZXZlbF9tYXBfb3BzLCBOVUxMLCAmdG9wX2xldmVsX3BhZ2UsIDEpKSB7CisJCXByaW50aygiXG54 ZW46IGRvbTA6IEhZUEVSVklTT1IgbWFwIGdyYW50IHJlZiBmYWlsZWQiKTsKKwkJcmV0dXJuIE5V TEw7CisJfQorCisJaWYgKHRvcF9sZXZlbF9tYXBfb3BzLnN0YXR1cykgeworCQlwcmludGsoIlxu eGVuOiBkb20wOiBIWVBFUlZJU09SIG1hcCBncmFudCByZWYgZmFpbGVkIHN0YXR1cyA9ICVkIiwK KwkJCQl0b3BfbGV2ZWxfbWFwX29wcy5zdGF0dXMpOworCQlyZXR1cm4gTlVMTDsKKwl9IGVsc2Ug eworCQl0b3BfbGV2ZWxfdW5tYXBfb3BzLmhhbmRsZSA9IHRvcF9sZXZlbF9tYXBfb3BzLmhhbmRs ZTsKKwl9CisKKwkvKiBQYXJzZSBjb250ZW50cyBvZiB0b3AgbGV2ZWwgYWRkcmVzc2luZyBwYWdl IHRvIGZpbmQgaG93IG1hbnkgc2Vjb25kIGxldmVsIHBhZ2VzIGlzIHRoZXJlKi8KKwl0b3BfbGV2 ZWxfcmVmcyA9IHBmbl90b19rYWRkcihwYWdlX3RvX3Bmbih0b3BfbGV2ZWxfcGFnZSkpOworCisJ LyogTWFwIGFsbCBzZWNvbmQgbGV2ZWwgcGFnZXMgKi8KKwlpZiAoZ250dGFiX2FsbG9jX3BhZ2Vz KG5fbGV2ZWwyX3JlZnMsIGxldmVsMl9wYWdlcykpIHsKKwkJcHJpbnRrKCJDYW5ub3QgYWxsb2Nh dGUgcGFnZXNcbiIpOworCQlyZXR1cm4gTlVMTDsKKwl9CisKKwlmb3IgKGkgPSAwOyBpIDwgbl9s ZXZlbDJfcmVmczsgaSsrKSB7CisJCWFkZHIgPSAodW5zaWduZWQgbG9uZylwZm5fdG9fa2FkZHIo cGFnZV90b19wZm4obGV2ZWwyX3BhZ2VzW2ldKSk7CisJCWdudHRhYl9zZXRfbWFwX29wKCZtYXBf b3BzW2ldLCBhZGRyLCBHTlRNQVBfaG9zdF9tYXAgfCBHTlRNQVBfcmVhZG9ubHksIHRvcF9sZXZl bF9yZWZzW2ldLCBkb21pZCk7CisJCWdudHRhYl9zZXRfdW5tYXBfb3AoJnVubWFwX29wc1tpXSwg YWRkciwgR05UTUFQX2hvc3RfbWFwIHwgR05UTUFQX3JlYWRvbmx5LCAtMSk7CisJfQorCisJaWYg KGdudHRhYl9tYXBfcmVmcyhtYXBfb3BzLCBOVUxMLCBsZXZlbDJfcGFnZXMsIG5fbGV2ZWwyX3Jl ZnMpKSB7CisJCXByaW50aygiXG54ZW46IGRvbTA6IEhZUEVSVklTT1IgbWFwIGdyYW50IHJlZiBm YWlsZWQiKTsKKwkJcmV0dXJuIE5VTEw7CisJfQorCisJLyogQ2hlY2tzIGlmIHBhZ2VzIHdlcmUg bWFwcGVkIGNvcnJlY3RseSBhbmQgYXQgdGhlIHNhbWUgdGltZSBpcyBjYWxjdWxhdGluZyB0b3Rh bCBudW1iZXIgb2YgZGF0YSByZWZpZHMqLworCWZvciAoaSA9IDA7IGkgPCBuX2xldmVsMl9yZWZz OyBpKyspIHsKKwkJaWYgKG1hcF9vcHNbaV0uc3RhdHVzKSB7CisJCQlwcmludGsoIlxueGVuOiBk b20wOiBIWVBFUlZJU09SIG1hcCBncmFudCByZWYgZmFpbGVkIHN0YXR1cyA9ICVkIiwKKwkJCQkJ bWFwX29wc1tpXS5zdGF0dXMpOworCQkJcmV0dXJuIE5VTEw7CisJCX0gZWxzZSB7CisJCQl1bm1h cF9vcHNbaV0uaGFuZGxlID0gbWFwX29wc1tpXS5oYW5kbGU7CisJCX0KKwl9CisKKwkvKiBVbm1h cCB0b3AgbGV2ZWwgcGFnZSwgYXMgaXQgd29uJ3QgYmUgbmVlZGVkIGFueSBsb25nZXIgKi8KKwlp ZiAoZ250dGFiX3VubWFwX3JlZnMoJnRvcF9sZXZlbF91bm1hcF9vcHMsIE5VTEwsICZ0b3BfbGV2 ZWxfcGFnZSwgMSkpIHsKKwkJcHJpbnRrKCJceGVuOiBjYW5ub3QgdW5tYXAgdG9wIGxldmVsIHBh Z2VcbiIpOworCQlyZXR1cm4gTlVMTDsKKwl9CisKKwlnbnR0YWJfZnJlZV9wYWdlcygxLCAmdG9w X2xldmVsX3BhZ2UpOworCWtmcmVlKG1hcF9vcHMpOworCXNoYXJlZF9wYWdlc19pbmZvLT51bm1h cF9vcHMgPSB1bm1hcF9vcHM7CisKKwlyZXR1cm4gbGV2ZWwyX3BhZ2VzOworfQorCisKKy8qIFRo aXMgY29sbGVjdHMgYWxsIHJlZmVyZW5jZSBudW1iZXJzIGZvciAybmQgbGV2ZWwgc2hhcmVkIHBh Z2VzIGFuZCBjcmVhdGUgYSB0YWJsZQorICogd2l0aCB0aG9zZSBpbiAxc3QgbGV2ZWwgc2hhcmVk IHBhZ2VzIHRoZW4gcmV0dXJuIHJlZmVyZW5jZSBudW1iZXJzIGZvciB0aGlzIHRvcCBsZXZlbAor ICogdGFibGUuICovCitncmFudF9yZWZfdCBoeXBlcl9kbWFidWZfY3JlYXRlX2dyZWZfdGFibGUo c3RydWN0IHBhZ2UgKipwYWdlcywgaW50IHJkb21haW4sIGludCBuZW50cywKKwkJCQkJICAgc3Ry dWN0IGh5cGVyX2RtYWJ1Zl9zaGFyZWRfcGFnZXNfaW5mbyAqc2hhcmVkX3BhZ2VzX2luZm8pCit7 CisJaW50IGkgPSAwOworCWdyYW50X3JlZl90ICpkYXRhX3JlZnM7CisJZ3JhbnRfcmVmX3QgdG9w X2xldmVsX3JlZjsKKworCS8qIGFsbG9jYXRlIHRlbXAgYXJyYXkgZm9yIHJlZnMgb2Ygc2hhcmVk IGRhdGEgcGFnZXMgKi8KKwlkYXRhX3JlZnMgPSBrY2FsbG9jKG5lbnRzLCBzaXplb2YoZ3JhbnRf cmVmX3QpLCBHRlBfS0VSTkVMKTsKKworCS8qIHNoYXJlIGRhdGEgcGFnZXMgaW4gcncgbW9kZSov CisJZm9yIChpPTA7IGk8bmVudHM7IGkrKykgeworCQlkYXRhX3JlZnNbaV0gPSBnbnR0YWJfZ3Jh bnRfZm9yZWlnbl9hY2Nlc3MocmRvbWFpbiwgcGZuX3RvX21mbihwYWdlX3RvX3BmbihwYWdlc1tp XSkpLCAwKTsKKwl9CisKKwkvKiBjcmVhdGUgYWRkaXRpb25hbCBzaGFyZWQgcGFnZXMgd2l0aCAy IGxldmVsIGFkZHJlc3Npbmcgb2YgZGF0YSBwYWdlcyAqLworCXRvcF9sZXZlbF9yZWYgPSBoeXBl cl9kbWFidWZfY3JlYXRlX2FkZHJlc3NpbmdfdGFibGVzKGRhdGFfcmVmcywgbmVudHMsIHJkb21h aW4sCisJCQkJCQkJICAgICAgc2hhcmVkX3BhZ2VzX2luZm8pOworCisJLyogU3RvcmUgZXhwb3J0 ZWQgcGFnZXMgcmVmaWQgdG8gYmUgdW5zaGFyZWQgbGF0ZXIgKi8KKwlzaGFyZWRfcGFnZXNfaW5m by0+ZGF0YV9yZWZzID0gZGF0YV9yZWZzOworCXNoYXJlZF9wYWdlc19pbmZvLT50b3BfbGV2ZWxf cmVmID0gdG9wX2xldmVsX3JlZjsKKworCXJldHVybiB0b3BfbGV2ZWxfcmVmOworfQorCitpbnQg aHlwZXJfZG1hYnVmX2NsZWFudXBfZ3JlZl90YWJsZShzdHJ1Y3QgaHlwZXJfZG1hYnVmX3NndF9p bmZvICpzZ3RfaW5mbykgeworCXVpbnQzMl90IGkgPSAwOworCXN0cnVjdCBoeXBlcl9kbWFidWZf c2hhcmVkX3BhZ2VzX2luZm8gKnNoYXJlZF9wYWdlc19pbmZvID0gJnNndF9pbmZvLT5zaGFyZWRf cGFnZXNfaW5mbzsKKworCWdyYW50X3JlZl90ICpyZWYgPSBzaGFyZWRfcGFnZXNfaW5mby0+dG9w X2xldmVsX3BhZ2U7CisJaW50IG5fMm5kX2xldmVsX3BhZ2VzID0gKHNndF9pbmZvLT5zZ3QtPm5l bnRzL1JFRlNfUEVSX1BBR0UgKyAoKHNndF9pbmZvLT5zZ3QtPm5lbnRzICUgUkVGU19QRVJfUEFH RSkgPyAxOiAwKSk7Lyogcm91bmRpbmcgKi8KKworCisJaWYgKHNoYXJlZF9wYWdlc19pbmZvLT5k YXRhX3JlZnMgPT0gTlVMTCB8fAorCSAgICBzaGFyZWRfcGFnZXNfaW5mby0+YWRkcl9wYWdlcyA9 PSAgTlVMTCB8fAorCSAgICBzaGFyZWRfcGFnZXNfaW5mby0+dG9wX2xldmVsX3BhZ2UgPT0gTlVM TCB8fAorCSAgICBzaGFyZWRfcGFnZXNfaW5mby0+dG9wX2xldmVsX3JlZiA9PSAtMSkgeworCQlw cmludGsoImdyZWYgdGFibGUgZm9yIGh5cGVyX2RtYWJ1ZiBhbHJlYWR5IGNsZWFuZWQgdXBcbiIp OworCQlyZXR1cm4gMDsKKwl9CisKKwkvKiBFbmQgZm9yZWlnbiBhY2Nlc3MgZm9yIDJuZCBsZXZl bCBhZGRyZXNzaW5nIHBhZ2VzICovCisJd2hpbGUocmVmW2ldICE9IDAgJiYgaSA8IG5fMm5kX2xl dmVsX3BhZ2VzKSB7CisJCWlmIChnbnR0YWJfcXVlcnlfZm9yZWlnbl9hY2Nlc3MocmVmW2ldKSkg eworCQkJcHJpbnRrKCJyZWZpZCBub3Qgc2hhcmVkICEhXG4iKTsKKwkJfQorCQlpZiAoIWdudHRh Yl9lbmRfZm9yZWlnbl9hY2Nlc3NfcmVmKHJlZltpXSwgMSkpIHsKKwkJCXByaW50aygicmVmaWQg c3RpbGwgaW4gdXNlISEhXG4iKTsKKwkJfQorCQlpKys7CisJfQorCWZyZWVfcGFnZXMoKHVuc2ln bmVkIGxvbmcpc2hhcmVkX3BhZ2VzX2luZm8tPmFkZHJfcGFnZXMsIGkpOworCisJLyogRW5kIGZv cmVpZ24gYWNjZXNzIGZvciB0b3AgbGV2ZWwgYWRkcmVzc2luZyBwYWdlICovCisJaWYgKGdudHRh Yl9xdWVyeV9mb3JlaWduX2FjY2VzcyhzaGFyZWRfcGFnZXNfaW5mby0+dG9wX2xldmVsX3JlZikp IHsKKwkJcHJpbnRrKCJyZWZpZCBub3Qgc2hhcmVkICEhXG4iKTsKKwl9CisJaWYgKCFnbnR0YWJf ZW5kX2ZvcmVpZ25fYWNjZXNzX3JlZihzaGFyZWRfcGFnZXNfaW5mby0+dG9wX2xldmVsX3JlZiwg MSkpIHsKKwkJcHJpbnRrKCJyZWZpZCBzdGlsbCBpbiB1c2UhISFcbiIpOworCX0KKwlnbnR0YWJf ZW5kX2ZvcmVpZ25fYWNjZXNzX3JlZihzaGFyZWRfcGFnZXNfaW5mby0+dG9wX2xldmVsX3JlZiwg MSk7CisJZnJlZV9wYWdlcygodW5zaWduZWQgbG9uZylzaGFyZWRfcGFnZXNfaW5mby0+dG9wX2xl dmVsX3BhZ2UsIDEpOworCisJLyogRW5kIGZvcmVpZ24gYWNjZXNzIGZvciBkYXRhIHBhZ2VzLCBi dXQgZG8gbm90IGZyZWUgdGhlbSAqLworCWZvciAoaSA9IDA7IGkgPCBzZ3RfaW5mby0+c2d0LT5u ZW50czsgaSsrKSB7CisJCWlmIChnbnR0YWJfcXVlcnlfZm9yZWlnbl9hY2Nlc3Moc2hhcmVkX3Bh Z2VzX2luZm8tPmRhdGFfcmVmc1tpXSkpIHsKKwkJCXByaW50aygicmVmaWQgbm90IHNoYXJlZCAh IVxuIik7CisJCX0KKwkJZ250dGFiX2VuZF9mb3JlaWduX2FjY2Vzc19yZWYoc2hhcmVkX3BhZ2Vz X2luZm8tPmRhdGFfcmVmc1tpXSwgMCk7CisJfQorCisJa2ZyZWUoc2hhcmVkX3BhZ2VzX2luZm8t PmRhdGFfcmVmcyk7CisKKwlzaGFyZWRfcGFnZXNfaW5mby0+ZGF0YV9yZWZzID0gTlVMTDsKKwlz aGFyZWRfcGFnZXNfaW5mby0+YWRkcl9wYWdlcyA9IE5VTEw7CisJc2hhcmVkX3BhZ2VzX2luZm8t PnRvcF9sZXZlbF9wYWdlID0gTlVMTDsKKwlzaGFyZWRfcGFnZXNfaW5mby0+dG9wX2xldmVsX3Jl ZiA9IC0xOworCisJcmV0dXJuIDA7Cit9CisKK2ludCBoeXBlcl9kbWFidWZfY2xlYW51cF9pbXBv cnRlZF9wYWdlcyhzdHJ1Y3QgaHlwZXJfZG1hYnVmX2ltcG9ydGVkX3NndF9pbmZvICpzZ3RfaW5m bykgeworCXN0cnVjdCBoeXBlcl9kbWFidWZfc2hhcmVkX3BhZ2VzX2luZm8gKnNoYXJlZF9wYWdl c19pbmZvID0gJnNndF9pbmZvLT5zaGFyZWRfcGFnZXNfaW5mbzsKKworCWlmKHNoYXJlZF9wYWdl c19pbmZvLT51bm1hcF9vcHMgPT0gTlVMTCB8fCBzaGFyZWRfcGFnZXNfaW5mby0+ZGF0YV9wYWdl cyA9PSBOVUxMKSB7CisJCXByaW50aygiSW1wb3J0ZWQgcGFnZXMgYWxyZWFkeSBjbGVhbmVkIHVw IG9yIGJ1ZmZlciB3YXMgbm90IGltcG9ydGVkIHlldFxuIik7CisJCXJldHVybiAwOworCX0KKwor CWlmIChnbnR0YWJfdW5tYXBfcmVmcyhzaGFyZWRfcGFnZXNfaW5mby0+dW5tYXBfb3BzLCBOVUxM LCBzaGFyZWRfcGFnZXNfaW5mby0+ZGF0YV9wYWdlcywgc2d0X2luZm8tPm5lbnRzKSApIHsKKwkJ cHJpbnRrKCJDYW5ub3QgdW5tYXAgZGF0YSBwYWdlc1xuIik7CisJCXJldHVybiAtRUlOVkFMOwor CX0KKworCWdudHRhYl9mcmVlX3BhZ2VzKHNndF9pbmZvLT5uZW50cywgc2hhcmVkX3BhZ2VzX2lu Zm8tPmRhdGFfcGFnZXMpOworCWtmcmVlKHNoYXJlZF9wYWdlc19pbmZvLT5kYXRhX3BhZ2VzKTsK KwlrZnJlZShzaGFyZWRfcGFnZXNfaW5mby0+dW5tYXBfb3BzKTsKKwlzaGFyZWRfcGFnZXNfaW5m by0+dW5tYXBfb3BzID0gTlVMTDsKKwlzaGFyZWRfcGFnZXNfaW5mby0+ZGF0YV9wYWdlcyA9IE5V TEw7CisKKwlyZXR1cm4gMDsKK30KKworLyogbWFwIGFuZCBjb25zdHJ1Y3Qgc2dfbGlzdHMgZnJv bSByZWZlcmVuY2UgbnVtYmVycyAqLworc3RydWN0IHNnX3RhYmxlKiBoeXBlcl9kbWFidWZfbWFw X3BhZ2VzKGdyYW50X3JlZl90IHRvcF9sZXZlbF9ncmVmLCBpbnQgZnJzdF9vZnN0LCBpbnQgbGFz dF9sZW4sIGludCBuZW50cywgaW50IHNkb21haW4sCisJCQkJCXN0cnVjdCBoeXBlcl9kbWFidWZf c2hhcmVkX3BhZ2VzX2luZm8gKnNoYXJlZF9wYWdlc19pbmZvKQoreworCXN0cnVjdCBzZ190YWJs ZSAqc3Q7CisJc3RydWN0IHBhZ2UgKipwYWdlczsKKwlzdHJ1Y3QgZ250dGFiX21hcF9ncmFudF9y ZWYgKm9wczsKKwlzdHJ1Y3QgZ250dGFiX3VubWFwX2dyYW50X3JlZiAqdW5tYXBfb3BzOworCXVu c2lnbmVkIGxvbmcgYWRkcjsKKwlncmFudF9yZWZfdCAqcmVmczsKKwlpbnQgaTsKKwlpbnQgbl9s ZXZlbDJfcmVmcyA9IChuZW50cyAvIFJFRlNfUEVSX1BBR0UpICsgKChuZW50cyAlIFJFRlNfUEVS X1BBR0UpID8gMSA6IDApOworCisJLyogR2V0IGRhdGEgcmVmaWRzICovCisJc3RydWN0IHBhZ2Uq KiByZWZpZF9wYWdlcyA9IGh5cGVyX2RtYWJ1Zl9nZXRfZGF0YV9yZWZzKHRvcF9sZXZlbF9ncmVm LCBzZG9tYWluLCBuZW50cywKKwkJCQkJCQkgICAgICAgc2hhcmVkX3BhZ2VzX2luZm8pOworCisJ cGFnZXMgPSBrY2FsbG9jKHNpemVvZihzdHJ1Y3QgcGFnZSopLCBuZW50cywgR0ZQX0tFUk5FTCk7 CisJaWYgKHBhZ2VzID09IE5VTEwpIHsKKwkJcmV0dXJuIE5VTEw7CisJfQorCisJLyogYWxsb2Nh dGUgbmV3IHBhZ2VzIHRoYXQgYXJlIG1hcHBlZCB0byBzaGFyZWQgcGFnZXMgdmlhIGdyYW50LXRh YmxlICovCisJaWYgKGdudHRhYl9hbGxvY19wYWdlcyhuZW50cywgcGFnZXMpKSB7CisJCXByaW50 aygiQ2Fubm90IGFsbG9jYXRlIHBhZ2VzXG4iKTsKKwkJcmV0dXJuIE5VTEw7CisJfQorCisJb3Bz ID0gKHN0cnVjdCBnbnR0YWJfbWFwX2dyYW50X3JlZiAqKWtjYWxsb2MobmVudHMsIHNpemVvZihz dHJ1Y3QgZ250dGFiX21hcF9ncmFudF9yZWYpLCBHRlBfS0VSTkVMKTsKKwl1bm1hcF9vcHMgPSAo c3RydWN0IGdudHRhYl91bm1hcF9ncmFudF9yZWYgKilrY2FsbG9jKG5lbnRzLCBzaXplb2Yoc3Ry dWN0IGdudHRhYl91bm1hcF9ncmFudF9yZWYpLCBHRlBfS0VSTkVMKTsKKworCWZvciAoaT0wOyBp PG5lbnRzOyBpKyspIHsKKwkJYWRkciA9ICh1bnNpZ25lZCBsb25nKXBmbl90b19rYWRkcihwYWdl X3RvX3BmbihwYWdlc1tpXSkpOworCQlyZWZzID0gcGZuX3RvX2thZGRyKHBhZ2VfdG9fcGZuKHJl ZmlkX3BhZ2VzW2kgLyBSRUZTX1BFUl9QQUdFXSkpOworCQlnbnR0YWJfc2V0X21hcF9vcCgmb3Bz W2ldLCBhZGRyLCBHTlRNQVBfaG9zdF9tYXAgfCBHTlRNQVBfcmVhZG9ubHksIHJlZnNbaSAlIFJF RlNfUEVSX1BBR0VdLCBzZG9tYWluKTsKKwkJZ250dGFiX3NldF91bm1hcF9vcCgmdW5tYXBfb3Bz W2ldLCBhZGRyLCBHTlRNQVBfaG9zdF9tYXAgfCBHTlRNQVBfcmVhZG9ubHksIC0xKTsKKwl9CisK KwlpZiAoZ250dGFiX21hcF9yZWZzKG9wcywgTlVMTCwgcGFnZXMsIG5lbnRzKSkgeworCQlwcmlu dGsoIlxueGVuOiBkb20wOiBIWVBFUlZJU09SIG1hcCBncmFudCByZWYgZmFpbGVkXG4iKTsKKwkJ cmV0dXJuIE5VTEw7CisJfQorCisJZm9yIChpPTA7IGk8bmVudHM7IGkrKykgeworCQlpZiAob3Bz W2ldLnN0YXR1cykgeworCQkJcHJpbnRrKCJcbnhlbjogZG9tMDogSFlQRVJWSVNPUiBtYXAgZ3Jh bnQgcmVmIGZhaWxlZCBzdGF0dXMgPSAlZFxuIiwKKwkJCQlvcHNbMF0uc3RhdHVzKTsKKwkJCXJl dHVybiBOVUxMOworCQl9IGVsc2UgeworCQkJdW5tYXBfb3BzW2ldLmhhbmRsZSA9IG9wc1tpXS5o YW5kbGU7CisJCX0KKwl9CisKKwlzdCA9IGh5cGVyX2RtYWJ1Zl9jcmVhdGVfc2d0KHBhZ2VzLCBm cnN0X29mc3QsIGxhc3RfbGVuLCBuZW50cyk7CisKKwlpZiAoZ250dGFiX3VubWFwX3JlZnMoc2hh cmVkX3BhZ2VzX2luZm8tPnVubWFwX29wcywgTlVMTCwgcmVmaWRfcGFnZXMsIG5fbGV2ZWwyX3Jl ZnMpICkgeworCQlwcmludGsoIkNhbm5vdCB1bm1hcCAybmQgbGV2ZWwgcmVmc1xuIik7CisJCXJl dHVybiBOVUxMOworCX0KKworCWdudHRhYl9mcmVlX3BhZ2VzKG5fbGV2ZWwyX3JlZnMsIHJlZmlk X3BhZ2VzKTsKKwlrZnJlZShyZWZpZF9wYWdlcyk7CisKKwlrZnJlZShzaGFyZWRfcGFnZXNfaW5m by0+dW5tYXBfb3BzKTsKKwlzaGFyZWRfcGFnZXNfaW5mby0+dW5tYXBfb3BzID0gdW5tYXBfb3Bz OworCXNoYXJlZF9wYWdlc19pbmZvLT5kYXRhX3BhZ2VzID0gcGFnZXM7CisJa2ZyZWUob3BzKTsK KworCXJldHVybiBzdDsKK30KKworaW5saW5lIGludCBoeXBlcl9kbWFidWZfc3luY19yZXF1ZXN0 X2FuZF93YWl0KGludCBpZCwgaW50IG9wcykKK3sKKwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX3Jpbmdf cnEgKnJlcTsKKwlpbnQgb3BlcmFuZHNbMl07CisJaW50IHJldDsKKworCW9wZXJhbmRzWzBdID0g aWQ7CisJb3BlcmFuZHNbMV0gPSBvcHM7CisKKwlyZXEgPSBrY2FsbG9jKDEsIHNpemVvZigqcmVx KSwgR0ZQX0tFUk5FTCk7CisKKwloeXBlcl9kbWFidWZfY3JlYXRlX3JlcXVlc3QocmVxLCBIWVBF Ul9ETUFCVUZfT1BTX1RPX1NPVVJDRSwgJm9wZXJhbmRzWzBdKTsKKworCS8qIHNlbmQgcmVxdWVz dCAqLworCXJldCA9IGh5cGVyX2RtYWJ1Zl9zZW5kX3JlcXVlc3QoaWQsIHJlcSk7CisKKwkvKiBU T0RPOiB3YWl0IHVudGlsIGl0IGdldHMgcmVzcG9uc2UuLiBvciBjYW4gd2UganVzdCBtb3ZlIG9u PyAqLworCisJa2ZyZWUocmVxKTsKKworCXJldHVybiByZXQ7Cit9CisKK3N0YXRpYyBpbnQgaHlw ZXJfZG1hYnVmX29wc19hdHRhY2goc3RydWN0IGRtYV9idWYqIGRtYWJ1Ziwgc3RydWN0IGRldmlj ZSogZGV2LAorCQkJc3RydWN0IGRtYV9idWZfYXR0YWNobWVudCAqYXR0YWNoKQoreworCXN0cnVj dCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKnNndF9pbmZvOworCWludCByZXQ7CisK KwlpZiAoIWF0dGFjaC0+ZG1hYnVmLT5wcml2KQorCQlyZXR1cm4gLUVJTlZBTDsKKworCXNndF9p bmZvID0gKHN0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKilhdHRhY2gtPmRt YWJ1Zi0+cHJpdjsKKworCXJldCA9IGh5cGVyX2RtYWJ1Zl9zeW5jX3JlcXVlc3RfYW5kX3dhaXQo SFlQRVJfRE1BQlVGX0lEX0lNUE9SVEVSX0dFVF9TRE9NQUlOX0lEKHNndF9pbmZvLT5oeXBlcl9k bWFidWZfaWQpLAorCQkJCQkJSFlQRVJfRE1BQlVGX09QU19BVFRBQ0gpOworCisJaWYgKHJldCA8 IDApIHsKKwkJcHJpbnRrKCJzZW5kIGRtYWJ1ZiBzeW5jIHJlcXVlc3QgZmFpbGVkXG4iKTsKKwl9 CisKKwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgdm9pZCBoeXBlcl9kbWFidWZfb3BzX2RldGFj aChzdHJ1Y3QgZG1hX2J1ZiogZG1hYnVmLCBzdHJ1Y3QgZG1hX2J1Zl9hdHRhY2htZW50ICphdHRh Y2gpCit7CisJc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBvcnRlZF9zZ3RfaW5mbyAqc2d0X2luZm87 CisJaW50IHJldDsKKworCWlmICghYXR0YWNoLT5kbWFidWYtPnByaXYpCisJCXJldHVybjsKKwor CXNndF9pbmZvID0gKHN0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKilhdHRh Y2gtPmRtYWJ1Zi0+cHJpdjsKKworCXJldCA9IGh5cGVyX2RtYWJ1Zl9zeW5jX3JlcXVlc3RfYW5k X3dhaXQoSFlQRVJfRE1BQlVGX0lEX0lNUE9SVEVSX0dFVF9TRE9NQUlOX0lEKHNndF9pbmZvLT5o eXBlcl9kbWFidWZfaWQpLAorCQkJCQkJSFlQRVJfRE1BQlVGX09QU19ERVRBQ0gpOworCisJaWYg KHJldCA8IDApIHsKKwkJcHJpbnRrKCJzZW5kIGRtYWJ1ZiBzeW5jIHJlcXVlc3QgZmFpbGVkXG4i KTsKKwl9Cit9CisKK3N0YXRpYyBzdHJ1Y3Qgc2dfdGFibGUqIGh5cGVyX2RtYWJ1Zl9vcHNfbWFw KHN0cnVjdCBkbWFfYnVmX2F0dGFjaG1lbnQgKmF0dGFjaG1lbnQsCisJCQkJCQllbnVtIGRtYV9k YXRhX2RpcmVjdGlvbiBkaXIpCit7CisJc3RydWN0IHNnX3RhYmxlICpzdDsKKwlzdHJ1Y3QgaHlw ZXJfZG1hYnVmX2ltcG9ydGVkX3NndF9pbmZvICpzZ3RfaW5mbzsKKwlzdHJ1Y3QgaHlwZXJfZG1h YnVmX3BhZ2VzX2luZm8gKnBhZ2VfaW5mbzsKKwlpbnQgcmV0OworCisJaWYgKCFhdHRhY2htZW50 LT5kbWFidWYtPnByaXYpCisJCXJldHVybiBOVUxMOworCisJc2d0X2luZm8gPSAoc3RydWN0IGh5 cGVyX2RtYWJ1Zl9pbXBvcnRlZF9zZ3RfaW5mbyAqKWF0dGFjaG1lbnQtPmRtYWJ1Zi0+cHJpdjsK KworCS8qIGV4dHJhY3QgcGFnZXMgZnJvbSBzZ3QgKi8KKwlwYWdlX2luZm8gPSBoeXBlcl9kbWFi dWZfZXh0X3BncyhzZ3RfaW5mby0+c2d0KTsKKworCS8qIGNyZWF0ZSBhIG5ldyBzZ190YWJsZSB3 aXRoIGV4dHJhY3RlZCBwYWdlcyAqLworCXN0ID0gaHlwZXJfZG1hYnVmX2NyZWF0ZV9zZ3QocGFn ZV9pbmZvLT5wYWdlcywgcGFnZV9pbmZvLT5mcnN0X29mc3QsCisJCQkJcGFnZV9pbmZvLT5sYXN0 X2xlbiwgcGFnZV9pbmZvLT5uZW50cyk7CisJaWYgKHN0ID09IE5VTEwpCisJCWdvdG8gZXJyX2Zy ZWVfc2c7CisKKyAgICAgICAgaWYgKCFkbWFfbWFwX3NnKGF0dGFjaG1lbnQtPmRldiwgc3QtPnNn bCwgc3QtPm5lbnRzLCBkaXIpKSB7CisgICAgICAgICAgICAgICAgZ290byBlcnJfZnJlZV9zZzsK KyAgICAgICAgfQorCisJcmV0ID0gaHlwZXJfZG1hYnVmX3N5bmNfcmVxdWVzdF9hbmRfd2FpdChI WVBFUl9ETUFCVUZfSURfSU1QT1JURVJfR0VUX1NET01BSU5fSUQoc2d0X2luZm8tPmh5cGVyX2Rt YWJ1Zl9pZCksCisJCQkJCQlIWVBFUl9ETUFCVUZfT1BTX01BUCk7CisKKwlpZiAocmV0IDwgMCkg eworCQlwcmludGsoInNlbmQgZG1hYnVmIHN5bmMgcmVxdWVzdCBmYWlsZWRcbiIpOworCX0KKwor CXJldHVybiBzdDsKKworZXJyX2ZyZWVfc2c6CisJc2dfZnJlZV90YWJsZShzdCk7CisJa2ZyZWUo c3QpOworCXJldHVybiBOVUxMOworfQorCitzdGF0aWMgdm9pZCBoeXBlcl9kbWFidWZfb3BzX3Vu bWFwKHN0cnVjdCBkbWFfYnVmX2F0dGFjaG1lbnQgKmF0dGFjaG1lbnQsCisJCQkJCQlzdHJ1Y3Qg c2dfdGFibGUgKnNnLAorCQkJCQkJZW51bSBkbWFfZGF0YV9kaXJlY3Rpb24gZGlyKQoreworCXN0 cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKnNndF9pbmZvOworCWludCByZXQ7 CisKKwlpZiAoIWF0dGFjaG1lbnQtPmRtYWJ1Zi0+cHJpdikKKwkJcmV0dXJuOworCisJc2d0X2lu Zm8gPSAoc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBvcnRlZF9zZ3RfaW5mbyAqKWF0dGFjaG1lbnQt PmRtYWJ1Zi0+cHJpdjsKKworCWRtYV91bm1hcF9zZyhhdHRhY2htZW50LT5kZXYsIHNnLT5zZ2ws IHNnLT5uZW50cywgZGlyKTsKKworCXNnX2ZyZWVfdGFibGUoc2cpOworCWtmcmVlKHNnKTsKKwor CXJldCA9IGh5cGVyX2RtYWJ1Zl9zeW5jX3JlcXVlc3RfYW5kX3dhaXQoSFlQRVJfRE1BQlVGX0lE X0lNUE9SVEVSX0dFVF9TRE9NQUlOX0lEKHNndF9pbmZvLT5oeXBlcl9kbWFidWZfaWQpLAorCQkJ CQkJSFlQRVJfRE1BQlVGX09QU19VTk1BUCk7CisKKwlpZiAocmV0IDwgMCkgeworCQlwcmludGso InNlbmQgZG1hYnVmIHN5bmMgcmVxdWVzdCBmYWlsZWRcbiIpOworCX0KK30KKworc3RhdGljIHZv aWQgaHlwZXJfZG1hYnVmX29wc19yZWxlYXNlKHN0cnVjdCBkbWFfYnVmICpkbWFidWYpCit7CisJ c3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBvcnRlZF9zZ3RfaW5mbyAqc2d0X2luZm87CisJaW50IHJl dDsKKworCWlmICghZG1hYnVmLT5wcml2KQorCQlyZXR1cm47CisKKwlzZ3RfaW5mbyA9IChzdHJ1 Y3QgaHlwZXJfZG1hYnVmX2ltcG9ydGVkX3NndF9pbmZvICopZG1hYnVmLT5wcml2OworCisJcmV0 ID0gaHlwZXJfZG1hYnVmX3N5bmNfcmVxdWVzdF9hbmRfd2FpdChIWVBFUl9ETUFCVUZfSURfSU1Q T1JURVJfR0VUX1NET01BSU5fSUQoc2d0X2luZm8tPmh5cGVyX2RtYWJ1Zl9pZCksCisJCQkJCQlI WVBFUl9ETUFCVUZfT1BTX1JFTEVBU0UpOworCisJaWYgKHJldCA8IDApIHsKKwkJcHJpbnRrKCJz ZW5kIGRtYWJ1ZiBzeW5jIHJlcXVlc3QgZmFpbGVkXG4iKTsKKwl9Cit9CisKK3N0YXRpYyBpbnQg aHlwZXJfZG1hYnVmX29wc19iZWdpbl9jcHVfYWNjZXNzKHN0cnVjdCBkbWFfYnVmICpkbWFidWYs IGVudW0gZG1hX2RhdGFfZGlyZWN0aW9uIGRpcikKK3sKKwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX2lt cG9ydGVkX3NndF9pbmZvICpzZ3RfaW5mbzsKKwlpbnQgcmV0OworCisJaWYgKCFkbWFidWYtPnBy aXYpCisJCXJldHVybiAtRUlOVkFMOworCisJc2d0X2luZm8gPSAoc3RydWN0IGh5cGVyX2RtYWJ1 Zl9pbXBvcnRlZF9zZ3RfaW5mbyAqKWRtYWJ1Zi0+cHJpdjsKKworCXJldCA9IGh5cGVyX2RtYWJ1 Zl9zeW5jX3JlcXVlc3RfYW5kX3dhaXQoSFlQRVJfRE1BQlVGX0lEX0lNUE9SVEVSX0dFVF9TRE9N QUlOX0lEKHNndF9pbmZvLT5oeXBlcl9kbWFidWZfaWQpLAorCQkJCQkJSFlQRVJfRE1BQlVGX09Q U19CRUdJTl9DUFVfQUNDRVNTKTsKKwlpZiAocmV0IDwgMCkgeworCQlwcmludGsoInNlbmQgZG1h YnVmIHN5bmMgcmVxdWVzdCBmYWlsZWRcbiIpOworCX0KKworCXJldHVybiByZXQ7Cit9CisKK3N0 YXRpYyBpbnQgaHlwZXJfZG1hYnVmX29wc19lbmRfY3B1X2FjY2VzcyhzdHJ1Y3QgZG1hX2J1ZiAq ZG1hYnVmLCBlbnVtIGRtYV9kYXRhX2RpcmVjdGlvbiBkaXIpCit7CisJc3RydWN0IGh5cGVyX2Rt YWJ1Zl9pbXBvcnRlZF9zZ3RfaW5mbyAqc2d0X2luZm87CisJaW50IHJldDsKKworCWlmICghZG1h YnVmLT5wcml2KQorCQlyZXR1cm4gLUVJTlZBTDsKKworCXNndF9pbmZvID0gKHN0cnVjdCBoeXBl cl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKilkbWFidWYtPnByaXY7CisKKwlyZXQgPSBoeXBl cl9kbWFidWZfc3luY19yZXF1ZXN0X2FuZF93YWl0KEhZUEVSX0RNQUJVRl9JRF9JTVBPUlRFUl9H RVRfU0RPTUFJTl9JRChzZ3RfaW5mby0+aHlwZXJfZG1hYnVmX2lkKSwKKwkJCQkJCUhZUEVSX0RN QUJVRl9PUFNfRU5EX0NQVV9BQ0NFU1MpOworCWlmIChyZXQgPCAwKSB7CisJCXByaW50aygic2Vu ZCBkbWFidWYgc3luYyByZXF1ZXN0IGZhaWxlZFxuIik7CisJfQorCisJcmV0dXJuIDA7Cit9CisK K3N0YXRpYyB2b2lkICpoeXBlcl9kbWFidWZfb3BzX2ttYXBfYXRvbWljKHN0cnVjdCBkbWFfYnVm ICpkbWFidWYsIHVuc2lnbmVkIGxvbmcgcGdudW0pCit7CisJc3RydWN0IGh5cGVyX2RtYWJ1Zl9p bXBvcnRlZF9zZ3RfaW5mbyAqc2d0X2luZm87CisJaW50IHJldDsKKworCWlmICghZG1hYnVmLT5w cml2KQorCQlyZXR1cm4gTlVMTDsKKworCXNndF9pbmZvID0gKHN0cnVjdCBoeXBlcl9kbWFidWZf aW1wb3J0ZWRfc2d0X2luZm8gKilkbWFidWYtPnByaXY7CisKKwlyZXQgPSBoeXBlcl9kbWFidWZf c3luY19yZXF1ZXN0X2FuZF93YWl0KEhZUEVSX0RNQUJVRl9JRF9JTVBPUlRFUl9HRVRfU0RPTUFJ Tl9JRChzZ3RfaW5mby0+aHlwZXJfZG1hYnVmX2lkKSwKKwkJCQkJCUhZUEVSX0RNQUJVRl9PUFNf S01BUF9BVE9NSUMpOworCWlmIChyZXQgPCAwKSB7CisJCXByaW50aygic2VuZCBkbWFidWYgc3lu YyByZXF1ZXN0IGZhaWxlZFxuIik7CisJfQorCisJcmV0dXJuIE5VTEw7IC8qIGZvciBub3cgTlVM TC4uIG5lZWQgdG8gcmV0dXJuIHRoZSBhZGRyZXNzIG9mIG1hcHBlZCByZWdpb24gKi8KK30KKwor c3RhdGljIHZvaWQgaHlwZXJfZG1hYnVmX29wc19rdW5tYXBfYXRvbWljKHN0cnVjdCBkbWFfYnVm ICpkbWFidWYsIHVuc2lnbmVkIGxvbmcgcGdudW0sIHZvaWQgKnZhZGRyKQoreworCXN0cnVjdCBo eXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKnNndF9pbmZvOworCWludCByZXQ7CisKKwlp ZiAoIWRtYWJ1Zi0+cHJpdikKKwkJcmV0dXJuOworCisJc2d0X2luZm8gPSAoc3RydWN0IGh5cGVy X2RtYWJ1Zl9pbXBvcnRlZF9zZ3RfaW5mbyAqKWRtYWJ1Zi0+cHJpdjsKKworCXJldCA9IGh5cGVy X2RtYWJ1Zl9zeW5jX3JlcXVlc3RfYW5kX3dhaXQoSFlQRVJfRE1BQlVGX0lEX0lNUE9SVEVSX0dF VF9TRE9NQUlOX0lEKHNndF9pbmZvLT5oeXBlcl9kbWFidWZfaWQpLAorCQkJCQkJSFlQRVJfRE1B QlVGX09QU19LVU5NQVBfQVRPTUlDKTsKKwlpZiAocmV0IDwgMCkgeworCQlwcmludGsoInNlbmQg ZG1hYnVmIHN5bmMgcmVxdWVzdCBmYWlsZWRcbiIpOworCX0KK30KKworc3RhdGljIHZvaWQgKmh5 cGVyX2RtYWJ1Zl9vcHNfa21hcChzdHJ1Y3QgZG1hX2J1ZiAqZG1hYnVmLCB1bnNpZ25lZCBsb25n IHBnbnVtKQoreworCXN0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKnNndF9p bmZvOworCWludCByZXQ7CisKKwlpZiAoIWRtYWJ1Zi0+cHJpdikKKwkJcmV0dXJuIE5VTEw7CisK KwlzZ3RfaW5mbyA9IChzdHJ1Y3QgaHlwZXJfZG1hYnVmX2ltcG9ydGVkX3NndF9pbmZvICopZG1h YnVmLT5wcml2OworCisJcmV0ID0gaHlwZXJfZG1hYnVmX3N5bmNfcmVxdWVzdF9hbmRfd2FpdChI WVBFUl9ETUFCVUZfSURfSU1QT1JURVJfR0VUX1NET01BSU5fSUQoc2d0X2luZm8tPmh5cGVyX2Rt YWJ1Zl9pZCksCisJCQkJCQlIWVBFUl9ETUFCVUZfT1BTX0tNQVApOworCWlmIChyZXQgPCAwKSB7 CisJCXByaW50aygic2VuZCBkbWFidWYgc3luYyByZXF1ZXN0IGZhaWxlZFxuIik7CisJfQorCisJ cmV0dXJuIE5VTEw7IC8qIGZvciBub3cgTlVMTC4uIG5lZWQgdG8gcmV0dXJuIHRoZSBhZGRyZXNz IG9mIG1hcHBlZCByZWdpb24gKi8KK30KKworc3RhdGljIHZvaWQgaHlwZXJfZG1hYnVmX29wc19r dW5tYXAoc3RydWN0IGRtYV9idWYgKmRtYWJ1ZiwgdW5zaWduZWQgbG9uZyBwZ251bSwgdm9pZCAq dmFkZHIpCit7CisJc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBvcnRlZF9zZ3RfaW5mbyAqc2d0X2lu Zm87CisJaW50IHJldDsKKworCWlmICghZG1hYnVmLT5wcml2KQorCQlyZXR1cm47CisKKwlzZ3Rf aW5mbyA9IChzdHJ1Y3QgaHlwZXJfZG1hYnVmX2ltcG9ydGVkX3NndF9pbmZvICopZG1hYnVmLT5w cml2OworCisJcmV0ID0gaHlwZXJfZG1hYnVmX3N5bmNfcmVxdWVzdF9hbmRfd2FpdChIWVBFUl9E TUFCVUZfSURfSU1QT1JURVJfR0VUX1NET01BSU5fSUQoc2d0X2luZm8tPmh5cGVyX2RtYWJ1Zl9p ZCksCisJCQkJCQlIWVBFUl9ETUFCVUZfT1BTX0tVTk1BUCk7CisJaWYgKHJldCA8IDApIHsKKwkJ cHJpbnRrKCJzZW5kIGRtYWJ1ZiBzeW5jIHJlcXVlc3QgZmFpbGVkXG4iKTsKKwl9Cit9CisKK3N0 YXRpYyBpbnQgaHlwZXJfZG1hYnVmX29wc19tbWFwKHN0cnVjdCBkbWFfYnVmICpkbWFidWYsIHN0 cnVjdCB2bV9hcmVhX3N0cnVjdCAqdm1hKQoreworCXN0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0 ZWRfc2d0X2luZm8gKnNndF9pbmZvOworCWludCByZXQ7CisKKwlpZiAoIWRtYWJ1Zi0+cHJpdikK KwkJcmV0dXJuIC1FSU5WQUw7CisKKwlzZ3RfaW5mbyA9IChzdHJ1Y3QgaHlwZXJfZG1hYnVmX2lt cG9ydGVkX3NndF9pbmZvICopZG1hYnVmLT5wcml2OworCisJcmV0ID0gaHlwZXJfZG1hYnVmX3N5 bmNfcmVxdWVzdF9hbmRfd2FpdChIWVBFUl9ETUFCVUZfSURfSU1QT1JURVJfR0VUX1NET01BSU5f SUQoc2d0X2luZm8tPmh5cGVyX2RtYWJ1Zl9pZCksCisJCQkJCQlIWVBFUl9ETUFCVUZfT1BTX01N QVApOworCWlmIChyZXQgPCAwKSB7CisJCXByaW50aygic2VuZCBkbWFidWYgc3luYyByZXF1ZXN0 IGZhaWxlZFxuIik7CisJfQorCisJcmV0dXJuIHJldDsKK30KKworc3RhdGljIHZvaWQgKmh5cGVy X2RtYWJ1Zl9vcHNfdm1hcChzdHJ1Y3QgZG1hX2J1ZiAqZG1hYnVmKQoreworCXN0cnVjdCBoeXBl cl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKnNndF9pbmZvOworCWludCByZXQ7CisKKwlpZiAo IWRtYWJ1Zi0+cHJpdikKKwkJcmV0dXJuIE5VTEw7CisKKwlzZ3RfaW5mbyA9IChzdHJ1Y3QgaHlw ZXJfZG1hYnVmX2ltcG9ydGVkX3NndF9pbmZvICopZG1hYnVmLT5wcml2OworCisJcmV0ID0gaHlw ZXJfZG1hYnVmX3N5bmNfcmVxdWVzdF9hbmRfd2FpdChIWVBFUl9ETUFCVUZfSURfSU1QT1JURVJf R0VUX1NET01BSU5fSUQoc2d0X2luZm8tPmh5cGVyX2RtYWJ1Zl9pZCksCisJCQkJCQlIWVBFUl9E TUFCVUZfT1BTX1ZNQVApOworCWlmIChyZXQgPCAwKSB7CisJCXByaW50aygic2VuZCBkbWFidWYg c3luYyByZXF1ZXN0IGZhaWxlZFxuIik7CisJfQorCisJcmV0dXJuIE5VTEw7Cit9CisKK3N0YXRp YyB2b2lkIGh5cGVyX2RtYWJ1Zl9vcHNfdnVubWFwKHN0cnVjdCBkbWFfYnVmICpkbWFidWYsIHZv aWQgKnZhZGRyKQoreworCXN0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKnNn dF9pbmZvOworCWludCByZXQ7CisKKwlpZiAoIWRtYWJ1Zi0+cHJpdikKKwkJcmV0dXJuOworCisJ c2d0X2luZm8gPSAoc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBvcnRlZF9zZ3RfaW5mbyAqKWRtYWJ1 Zi0+cHJpdjsKKworCXJldCA9IGh5cGVyX2RtYWJ1Zl9zeW5jX3JlcXVlc3RfYW5kX3dhaXQoSFlQ RVJfRE1BQlVGX0lEX0lNUE9SVEVSX0dFVF9TRE9NQUlOX0lEKHNndF9pbmZvLT5oeXBlcl9kbWFi dWZfaWQpLAorCQkJCQkJSFlQRVJfRE1BQlVGX09QU19WVU5NQVApOworCWlmIChyZXQgPCAwKSB7 CisJCXByaW50aygic2VuZCBkbWFidWYgc3luYyByZXF1ZXN0IGZhaWxlZFxuIik7CisJfQorfQor CitzdGF0aWMgY29uc3Qgc3RydWN0IGRtYV9idWZfb3BzIGh5cGVyX2RtYWJ1Zl9vcHMgPSB7CisJ CS5hdHRhY2ggPSBoeXBlcl9kbWFidWZfb3BzX2F0dGFjaCwKKwkJLmRldGFjaCA9IGh5cGVyX2Rt YWJ1Zl9vcHNfZGV0YWNoLAorCQkubWFwX2RtYV9idWYgPSBoeXBlcl9kbWFidWZfb3BzX21hcCwK KwkJLnVubWFwX2RtYV9idWYgPSBoeXBlcl9kbWFidWZfb3BzX3VubWFwLAorCQkucmVsZWFzZSA9 IGh5cGVyX2RtYWJ1Zl9vcHNfcmVsZWFzZSwKKwkJLmJlZ2luX2NwdV9hY2Nlc3MgPSAodm9pZCop aHlwZXJfZG1hYnVmX29wc19iZWdpbl9jcHVfYWNjZXNzLAorCQkuZW5kX2NwdV9hY2Nlc3MgPSAo dm9pZCopaHlwZXJfZG1hYnVmX29wc19lbmRfY3B1X2FjY2VzcywKKwkJLm1hcF9hdG9taWMgPSBo eXBlcl9kbWFidWZfb3BzX2ttYXBfYXRvbWljLAorCQkudW5tYXBfYXRvbWljID0gaHlwZXJfZG1h YnVmX29wc19rdW5tYXBfYXRvbWljLAorCQkubWFwID0gaHlwZXJfZG1hYnVmX29wc19rbWFwLAor CQkudW5tYXAgPSBoeXBlcl9kbWFidWZfb3BzX2t1bm1hcCwKKwkJLm1tYXAgPSBoeXBlcl9kbWFi dWZfb3BzX21tYXAsCisJCS52bWFwID0gaHlwZXJfZG1hYnVmX29wc192bWFwLAorCQkudnVubWFw ID0gaHlwZXJfZG1hYnVmX29wc192dW5tYXAsCit9OworCisvKiBleHBvcnRpbmcgZG1hYnVmIGFz IGZkICovCitpbnQgaHlwZXJfZG1hYnVmX2V4cG9ydF9mZChzdHJ1Y3QgaHlwZXJfZG1hYnVmX2lt cG9ydGVkX3NndF9pbmZvICpkaW5mbywgaW50IGZsYWdzKQoreworCWludCBmZDsKKworCXN0cnVj dCBkbWFfYnVmKiBkbWFidWY7CisKKy8qIGNhbGwgaHlwZXJfZG1hYnVmX2V4cG9ydF9kbWFidWYg YW5kIGNyZWF0ZSBhbmQgYmluZCBhIGhhbmRsZSBmb3IgaXQKKyAqIHRoZW4gcmVsZWFzZSAqLwor CisJZG1hYnVmID0gaHlwZXJfZG1hYnVmX2V4cG9ydF9kbWFfYnVmKGRpbmZvKTsKKworCWZkID0g ZG1hX2J1Zl9mZChkbWFidWYsIGZsYWdzKTsKKworCXJldHVybiBmZDsKK30KKworc3RydWN0IGRt YV9idWYqIGh5cGVyX2RtYWJ1Zl9leHBvcnRfZG1hX2J1ZihzdHJ1Y3QgaHlwZXJfZG1hYnVmX2lt cG9ydGVkX3NndF9pbmZvICpkaW5mbykKK3sKKwlERUZJTkVfRE1BX0JVRl9FWFBPUlRfSU5GTyhl eHBfaW5mbyk7CisKKwlleHBfaW5mby5vcHMgPSAmaHlwZXJfZG1hYnVmX29wczsKKwlleHBfaW5m by5zaXplID0gZGluZm8tPnNndC0+bmVudHMgKiBQQUdFX1NJWkU7IC8qIG11bHRpcGxlIG9mIFBB R0VfU0laRSwgbm90IGNvbnNpZGVyaW5nIG9mZnNldCAqLworCWV4cF9pbmZvLmZsYWdzID0gLyog bm90IHN1cmUgYWJvdXQgZmxhZyAqLzA7CisJZXhwX2luZm8ucHJpdiA9IGRpbmZvOworCisJcmV0 dXJuIGRtYV9idWZfZXhwb3J0KCZleHBfaW5mbyk7Cit9OwpkaWZmIC0tZ2l0IGEvZHJpdmVycy94 ZW4vaHlwZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9pbXAuaCBiL2RyaXZlcnMveGVuL2h5cGVyX2Rt YWJ1Zi9oeXBlcl9kbWFidWZfaW1wLmgKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAw MC4uMDAzYzE1OAotLS0gL2Rldi9udWxsCisrKyBiL2RyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9o eXBlcl9kbWFidWZfaW1wLmgKQEAgLTAsMCArMSwzMSBAQAorI2lmbmRlZiBfX0hZUEVSX0RNQUJV Rl9JTVBfSF9fCisjZGVmaW5lIF9fSFlQRVJfRE1BQlVGX0lNUF9IX18KKworI2luY2x1ZGUgImh5 cGVyX2RtYWJ1Zl9zdHJ1Y3QuaCIKKworLyogZXh0cmFjdCBwYWdlcyBkaXJlY3RseSBmcm9tIHN0 cnVjdCBzZ190YWJsZSAqLworc3RydWN0IGh5cGVyX2RtYWJ1Zl9wYWdlc19pbmZvICpoeXBlcl9k bWFidWZfZXh0X3BncyhzdHJ1Y3Qgc2dfdGFibGUgKnNndCk7CisKKy8qIGNyZWF0ZSBzZ190YWJs ZSB3aXRoIGdpdmVuIHBhZ2VzIGFuZCBvdGhlciBwYXJhbWV0ZXJzICovCitzdHJ1Y3Qgc2dfdGFi bGUqIGh5cGVyX2RtYWJ1Zl9jcmVhdGVfc2d0KHN0cnVjdCBwYWdlICoqcGFnZXMsCisgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgIGludCBmcnN0X29mc3QsIGludCBsYXN0X2xlbiwgaW50 IG5lbnRzKTsKKworZ3JhbnRfcmVmX3QgaHlwZXJfZG1hYnVmX2NyZWF0ZV9ncmVmX3RhYmxlKHN0 cnVjdCBwYWdlICoqcGFnZXMsIGludCByZG9tYWluLCBpbnQgbmVudHMsCisJCQkJCSAgIHN0cnVj dCBoeXBlcl9kbWFidWZfc2hhcmVkX3BhZ2VzX2luZm8gKnNoYXJlZF9wYWdlc19pbmZvKTsKKwor aW50IGh5cGVyX2RtYWJ1Zl9jbGVhbnVwX2dyZWZfdGFibGUoc3RydWN0IGh5cGVyX2RtYWJ1Zl9z Z3RfaW5mbyAqc2d0X2luZm8pOworCitpbnQgaHlwZXJfZG1hYnVmX2NsZWFudXBfaW1wb3J0ZWRf cGFnZXMoc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBvcnRlZF9zZ3RfaW5mbyAqc2d0X2luZm8pOwor CisvKiBtYXAgZmlyc3QgbGV2ZWwgdGFibGVzIHRoYXQgY29udGFpbnMgcmVmZXJlbmNlIG51bWJl cnMgZm9yIGFjdHVhbCBzaGFyZWQgcGFnZXMgKi8KK2dyYW50X3JlZl90ICpoeXBlcl9kbWFidWZf bWFwX2dyZWZfdGFibGUoZ3JhbnRfcmVmX3QgKmdyZWZfdGFibGUsIGludCBuX3BhZ2VzX3RhYmxl KTsKKworLyogbWFwIGFuZCBjb25zdHJ1Y3Qgc2dfbGlzdHMgZnJvbSByZWZlcmVuY2UgbnVtYmVy cyAqLworc3RydWN0IHNnX3RhYmxlKiBoeXBlcl9kbWFidWZfbWFwX3BhZ2VzKGdyYW50X3JlZl90 IGdyZWYsIGludCBmcnN0X29mc3QsIGludCBsYXN0X2xlbiwgaW50IG5lbnRzLCBpbnQgc2RvbWFp biwKKwkJCQkJc3RydWN0IGh5cGVyX2RtYWJ1Zl9zaGFyZWRfcGFnZXNfaW5mbyAqc2hhcmVkX3Bh Z2VzX2luZm8pOworCitpbnQgaHlwZXJfZG1hYnVmX2V4cG9ydF9mZChzdHJ1Y3QgaHlwZXJfZG1h YnVmX2ltcG9ydGVkX3NndF9pbmZvICpkaW5mbywgaW50IGZsYWdzKTsKKworc3RydWN0IGRtYV9i dWYqIGh5cGVyX2RtYWJ1Zl9leHBvcnRfZG1hX2J1ZihzdHJ1Y3QgaHlwZXJfZG1hYnVmX2ltcG9y dGVkX3NndF9pbmZvICpkaW5mbyk7CisKKyNlbmRpZiAvKiBfX0hZUEVSX0RNQUJVRl9JTVBfSF9f ICovCmRpZmYgLS1naXQgYS9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX2lv Y3RsLmMgYi9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX2lvY3RsLmMKbmV3 IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uNWU1MDkwOAotLS0gL2Rldi9udWxsCisr KyBiL2RyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfaW9jdGwuYwpAQCAtMCww ICsxLDQ2MiBAQAorI2luY2x1ZGUgPGxpbnV4L2tlcm5lbC5oPgorI2luY2x1ZGUgPGxpbnV4L2Vy cm5vLmg+CisjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+CisjaW5jbHVkZSA8bGludXgvc2xhYi5o PgorI2luY2x1ZGUgPGxpbnV4L21pc2NkZXZpY2UuaD4KKyNpbmNsdWRlIDxsaW51eC91YWNjZXNz Lmg+CisjaW5jbHVkZSA8bGludXgvZG1hLWJ1Zi5oPgorI2luY2x1ZGUgPGxpbnV4L2RlbGF5Lmg+ CisjaW5jbHVkZSAiaHlwZXJfZG1hYnVmX3N0cnVjdC5oIgorI2luY2x1ZGUgImh5cGVyX2RtYWJ1 Zl9pbXAuaCIKKyNpbmNsdWRlICJoeXBlcl9kbWFidWZfbGlzdC5oIgorI2luY2x1ZGUgImh5cGVy X2RtYWJ1Zl9kcnYuaCIKKyNpbmNsdWRlICJoeXBlcl9kbWFidWZfcXVlcnkuaCIKKyNpbmNsdWRl ICJ4ZW4vaHlwZXJfZG1hYnVmX3hlbl9jb21tLmgiCisjaW5jbHVkZSAiaHlwZXJfZG1hYnVmX21z Zy5oIgorCitzdHJ1Y3QgaHlwZXJfZG1hYnVmX3ByaXZhdGUgeworCXN0cnVjdCBkZXZpY2UgKmRl dmljZTsKK30gaHlwZXJfZG1hYnVmX3ByaXZhdGU7CisKK3N0YXRpYyB1aW50MzJfdCBoeXBlcl9k bWFidWZfaWRfZ2VuKHZvaWQpIHsKKwkvKiBUT0RPOiBhZGQgcHJvcGVyIGltcGxlbWVudGF0aW9u ICovCisJc3RhdGljIHVpbnQzMl90IGlkID0gMDsKKwlzdGF0aWMgaW50MzJfdCBkb21pZCA9IC0x OworCWlmIChkb21pZCA9PSAtMSkgeworCQlkb21pZCA9IGh5cGVyX2RtYWJ1Zl9nZXRfZG9taWQo KTsKKwl9CisJcmV0dXJuIEhZUEVSX0RNQUJVRl9JRF9JTVBPUlRFUihkb21pZCwgaWQrKyk7Cit9 CisKK3N0YXRpYyBpbnQgaHlwZXJfZG1hYnVmX2V4cG9ydGVyX3Jpbmdfc2V0dXAodm9pZCAqZGF0 YSkKK3sKKwlzdHJ1Y3QgaW9jdGxfaHlwZXJfZG1hYnVmX2V4cG9ydGVyX3Jpbmdfc2V0dXAgKnJp bmdfYXR0cjsKKwlpbnQgcmV0ID0gMDsKKworCWlmICghZGF0YSkgeworCQlwcmludGsoInVzZXIg ZGF0YSBpcyBOVUxMXG4iKTsKKwkJcmV0dXJuIC0xOworCX0KKwlyaW5nX2F0dHIgPSAoc3RydWN0 IGlvY3RsX2h5cGVyX2RtYWJ1Zl9leHBvcnRlcl9yaW5nX3NldHVwICopZGF0YTsKKworCXJldCA9 IGh5cGVyX2RtYWJ1Zl9leHBvcnRlcl9yaW5nYnVmX2luaXQocmluZ19hdHRyLT5yZW1vdGVfZG9t YWluLAorCQkJCQkJJnJpbmdfYXR0ci0+cmluZ19yZWZpZCwKKwkJCQkJCSZyaW5nX2F0dHItPnBv cnQpOworCisJcmV0dXJuIHJldDsKK30KKworc3RhdGljIGludCBoeXBlcl9kbWFidWZfaW1wb3J0 ZXJfcmluZ19zZXR1cCh2b2lkICpkYXRhKQoreworCXN0cnVjdCBpb2N0bF9oeXBlcl9kbWFidWZf aW1wb3J0ZXJfcmluZ19zZXR1cCAqc2V0dXBfaW1wX3JpbmdfYXR0cjsKKwlpbnQgcmV0ID0gMDsK KworCWlmICghZGF0YSkgeworCQlwcmludGsoInVzZXIgZGF0YSBpcyBOVUxMXG4iKTsKKwkJcmV0 dXJuIC0xOworCX0KKworCXNldHVwX2ltcF9yaW5nX2F0dHIgPSAoc3RydWN0IGlvY3RsX2h5cGVy X2RtYWJ1Zl9pbXBvcnRlcl9yaW5nX3NldHVwICopZGF0YTsKKworCS8qIHVzZXIgbmVlZCB0byBw cm92aWRlIGEgcG9ydCBudW1iZXIgYW5kIHJlZiAjIGZvciB0aGUgcGFnZSB1c2VkIGFzIHJpbmcg YnVmZmVyICovCisJcmV0ID0gaHlwZXJfZG1hYnVmX2ltcG9ydGVyX3JpbmdidWZfaW5pdChzZXR1 cF9pbXBfcmluZ19hdHRyLT5zb3VyY2VfZG9tYWluLAorCQkJCQkJIHNldHVwX2ltcF9yaW5nX2F0 dHItPnJpbmdfcmVmaWQsCisJCQkJCQkgc2V0dXBfaW1wX3JpbmdfYXR0ci0+cG9ydCk7CisKKwly ZXR1cm4gcmV0OworfQorCitzdGF0aWMgaW50IGh5cGVyX2RtYWJ1Zl9leHBvcnRfcmVtb3RlKHZv aWQgKmRhdGEpCit7CisJc3RydWN0IGlvY3RsX2h5cGVyX2RtYWJ1Zl9leHBvcnRfcmVtb3RlICpl eHBvcnRfcmVtb3RlX2F0dHI7CisJc3RydWN0IGRtYV9idWYgKmRtYV9idWY7CisJc3RydWN0IGRt YV9idWZfYXR0YWNobWVudCAqYXR0YWNobWVudDsKKwlzdHJ1Y3Qgc2dfdGFibGUgKnNndDsKKwlz dHJ1Y3QgaHlwZXJfZG1hYnVmX3BhZ2VzX2luZm8gKnBhZ2VfaW5mbzsKKwlzdHJ1Y3QgaHlwZXJf ZG1hYnVmX3NndF9pbmZvICpzZ3RfaW5mbzsKKwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX3JpbmdfcnEg KnJlcTsKKwlpbnQgb3BlcmFuZHNbOV07CisJaW50IHJldCA9IDA7CisKKwlpZiAoIWRhdGEpIHsK KwkJcHJpbnRrKCJ1c2VyIGRhdGEgaXMgTlVMTFxuIik7CisJCXJldHVybiAtMTsKKwl9CisKKwll eHBvcnRfcmVtb3RlX2F0dHIgPSAoc3RydWN0IGlvY3RsX2h5cGVyX2RtYWJ1Zl9leHBvcnRfcmVt b3RlICopZGF0YTsKKworCWRtYV9idWYgPSBkbWFfYnVmX2dldChleHBvcnRfcmVtb3RlX2F0dHIt PmRtYWJ1Zl9mZCk7CisJaWYgKCFkbWFfYnVmKSB7CisJCXByaW50aygiQ2Fubm90IGdldCBkbWEg YnVmXG4iKTsKKwkJcmV0dXJuIC0xOworCX0KKworCWF0dGFjaG1lbnQgPSBkbWFfYnVmX2F0dGFj aChkbWFfYnVmLCBoeXBlcl9kbWFidWZfcHJpdmF0ZS5kZXZpY2UpOworCWlmICghYXR0YWNobWVu dCkgeworCQlwcmludGsoIkNhbm5vdCBnZXQgYXR0YWNobWVudFxuIik7CisJCXJldHVybiAtMTsK Kwl9CisKKwkvKiB3ZSBjaGVjayBpZiB0aGlzIHNwZWNpZmljIGF0dGFjaG1lbnQgd2FzIGFscmVh ZHkgZXhwb3J0ZWQKKwkgKiB0byB0aGUgc2FtZSBkb21haW4gYW5kIGlmIHllcywgaXQgcmV0dXJu cyBoeXBlcl9kbWFidWZfaWQKKwkgKiBvZiBwcmUtZXhwb3J0ZWQgc2d0ICovCisJcmV0ID0gaHlw ZXJfZG1hYnVmX2ZpbmRfaWQoYXR0YWNobWVudCwgZXhwb3J0X3JlbW90ZV9hdHRyLT5yZW1vdGVf ZG9tYWluKTsKKwlpZiAocmV0ICE9IC0xKSB7CisJCWRtYV9idWZfZGV0YWNoKGRtYV9idWYsIGF0 dGFjaG1lbnQpOworCQlkbWFfYnVmX3B1dChkbWFfYnVmKTsKKwkJZXhwb3J0X3JlbW90ZV9hdHRy LT5oeXBlcl9kbWFidWZfaWQgPSByZXQ7CisJCXJldHVybiAwOworCX0KKwkvKiBDbGVhciByZXQs IGFzIHRoYXQgd2lsbCBjYXVzZSB3aG9sZSBpb2N0bCB0byByZXR1cm4gZmFpbHVyZSB0byB1c2Vy c3BhY2UsIHdoaWNoIGlzIG5vdCB0cnVlICovCisJcmV0ID0gMDsKKworCXNndCA9IGRtYV9idWZf bWFwX2F0dGFjaG1lbnQoYXR0YWNobWVudCwgRE1BX0JJRElSRUNUSU9OQUwpOworCisJc2d0X2lu Zm8gPSBrbWFsbG9jKHNpemVvZigqc2d0X2luZm8pLCBHRlBfS0VSTkVMKTsKKworCXNndF9pbmZv LT5oeXBlcl9kbWFidWZfaWQgPSBoeXBlcl9kbWFidWZfaWRfZ2VuKCk7CisJLyogVE9ETzogV2Ug bWlnaHQgbmVlZCB0byBjb25zaWRlciB1c2luZyBwb3J0IG51bWJlciBvbiBldmVudCBjaGFubmVs PyAqLworCXNndF9pbmZvLT5oeXBlcl9kbWFidWZfcmRvbWFpbiA9IGV4cG9ydF9yZW1vdGVfYXR0 ci0+cmVtb3RlX2RvbWFpbjsKKwlzZ3RfaW5mby0+c2d0ID0gc2d0OworCXNndF9pbmZvLT5hdHRh Y2htZW50ID0gYXR0YWNobWVudDsKKwlzZ3RfaW5mby0+ZG1hX2J1ZiA9IGRtYV9idWY7CisKKwlw YWdlX2luZm8gPSBoeXBlcl9kbWFidWZfZXh0X3BncyhzZ3QpOworCWlmIChwYWdlX2luZm8gPT0g TlVMTCkKKwkJZ290byBmYWlsX2V4cG9ydDsKKworCS8qIG5vdyByZWdpc3RlciBpdCB0byBleHBv cnQgbGlzdCAqLworCWh5cGVyX2RtYWJ1Zl9yZWdpc3Rlcl9leHBvcnRlZChzZ3RfaW5mbyk7CisK KwlwYWdlX2luZm8tPmh5cGVyX2RtYWJ1Zl9yZG9tYWluID0gc2d0X2luZm8tPmh5cGVyX2RtYWJ1 Zl9yZG9tYWluOworCXBhZ2VfaW5mby0+aHlwZXJfZG1hYnVmX2lkID0gc2d0X2luZm8tPmh5cGVy X2RtYWJ1Zl9pZDsgLyogbWF5IG5vdCBiZSBuZWVkZWQgKi8KKworCWV4cG9ydF9yZW1vdGVfYXR0 ci0+aHlwZXJfZG1hYnVmX2lkID0gc2d0X2luZm8tPmh5cGVyX2RtYWJ1Zl9pZDsKKworCS8qIG5v dyBjcmVhdGUgdGFibGUgb2YgZ3JlZnMgZm9yIHNoYXJlZCBwYWdlcyBhbmQgKi8KKworCS8qIG5v dyBjcmVhdGUgcmVxdWVzdCBmb3IgaW1wb3J0ZXIgdmlhIHJpbmcgKi8KKwlvcGVyYW5kc1swXSA9 IHBhZ2VfaW5mby0+aHlwZXJfZG1hYnVmX2lkOworCW9wZXJhbmRzWzFdID0gcGFnZV9pbmZvLT5u ZW50czsKKwlvcGVyYW5kc1syXSA9IHBhZ2VfaW5mby0+ZnJzdF9vZnN0OworCW9wZXJhbmRzWzNd ID0gcGFnZV9pbmZvLT5sYXN0X2xlbjsKKwlvcGVyYW5kc1s0XSA9IGh5cGVyX2RtYWJ1Zl9jcmVh dGVfZ3JlZl90YWJsZShwYWdlX2luZm8tPnBhZ2VzLCBleHBvcnRfcmVtb3RlX2F0dHItPnJlbW90 ZV9kb21haW4sCisJCQkJCQlwYWdlX2luZm8tPm5lbnRzLCAmc2d0X2luZm8tPnNoYXJlZF9wYWdl c19pbmZvKTsKKwkvKiBkcml2ZXIvYXBwbGljYXRpb24gc3BlY2lmaWMgcHJpdmF0ZSBpbmZvLCBt YXggMzIgYnl0ZXMgKi8KKwlvcGVyYW5kc1s1XSA9IGV4cG9ydF9yZW1vdGVfYXR0ci0+cHJpdmF0 ZVswXTsKKwlvcGVyYW5kc1s2XSA9IGV4cG9ydF9yZW1vdGVfYXR0ci0+cHJpdmF0ZVsxXTsKKwlv cGVyYW5kc1s3XSA9IGV4cG9ydF9yZW1vdGVfYXR0ci0+cHJpdmF0ZVsyXTsKKwlvcGVyYW5kc1s4 XSA9IGV4cG9ydF9yZW1vdGVfYXR0ci0+cHJpdmF0ZVszXTsKKworCXJlcSA9IGtjYWxsb2MoMSwg c2l6ZW9mKCpyZXEpLCBHRlBfS0VSTkVMKTsKKworCS8qIGNvbXBvc2luZyBhIG1lc3NhZ2UgdG8g dGhlIGltcG9ydGVyICovCisJaHlwZXJfZG1hYnVmX2NyZWF0ZV9yZXF1ZXN0KHJlcSwgSFlQRVJf RE1BQlVGX0VYUE9SVCwgJm9wZXJhbmRzWzBdKTsKKwlpZihoeXBlcl9kbWFidWZfc2VuZF9yZXF1 ZXN0KGV4cG9ydF9yZW1vdGVfYXR0ci0+cmVtb3RlX2RvbWFpbiwgcmVxKSkKKwkJZ290byBmYWls X3NlbmRfcmVxdWVzdDsKKworCS8qIGZyZWUgbXNnICovCisJa2ZyZWUocmVxKTsKKwkvKiBmcmVl IHBhZ2VfaW5mbyAqLworCWtmcmVlKHBhZ2VfaW5mbyk7CisKKwlyZXR1cm4gcmV0OworCitmYWls X3NlbmRfcmVxdWVzdDoKKwlrZnJlZShyZXEpOworCWh5cGVyX2RtYWJ1Zl9yZW1vdmVfZXhwb3J0 ZWQoc2d0X2luZm8tPmh5cGVyX2RtYWJ1Zl9pZCk7CisKK2ZhaWxfZXhwb3J0OgorCWRtYV9idWZf dW5tYXBfYXR0YWNobWVudChzZ3RfaW5mby0+YXR0YWNobWVudCwgc2d0X2luZm8tPnNndCwgRE1B X0JJRElSRUNUSU9OQUwpOworCWRtYV9idWZfZGV0YWNoKHNndF9pbmZvLT5kbWFfYnVmLCBzZ3Rf aW5mby0+YXR0YWNobWVudCk7CisJZG1hX2J1Zl9wdXQoc2d0X2luZm8tPmRtYV9idWYpOworCisJ cmV0dXJuIC1FSU5WQUw7Cit9CisKK3N0YXRpYyBpbnQgaHlwZXJfZG1hYnVmX2V4cG9ydF9mZF9p b2N0bCh2b2lkICpkYXRhKQoreworCXN0cnVjdCBpb2N0bF9oeXBlcl9kbWFidWZfZXhwb3J0X2Zk ICpleHBvcnRfZmRfYXR0cjsKKwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX2ltcG9ydGVkX3NndF9pbmZv ICppbXBvcnRlZF9zZ3RfaW5mbzsKKwlpbnQgcmV0ID0gMDsKKworCWlmICghZGF0YSkgeworCQlw cmludGsoInVzZXIgZGF0YSBpcyBOVUxMXG4iKTsKKwkJcmV0dXJuIC0xOworCX0KKworCWV4cG9y dF9mZF9hdHRyID0gKHN0cnVjdCBpb2N0bF9oeXBlcl9kbWFidWZfZXhwb3J0X2ZkICopZGF0YTsK KworCS8qIGxvb2sgZm9yIGRtYWJ1ZiBmb3IgdGhlIGlkICovCisJaW1wb3J0ZWRfc2d0X2luZm8g PSBoeXBlcl9kbWFidWZfZmluZF9pbXBvcnRlZChleHBvcnRfZmRfYXR0ci0+aHlwZXJfZG1hYnVm X2lkKTsKKwlpZiAoaW1wb3J0ZWRfc2d0X2luZm8gPT0gTlVMTCkgLyogY2FuJ3QgZmluZCBzZ3Qg ZnJvbSB0aGUgdGFibGUgKi8KKwkJcmV0dXJuIC0xOworCisJcHJpbnRrKCIlcyBGb3VuZCBidWZm ZXIgZ3JlZiAlZCAgb2ZmICVkIGxhc3QgbGVuICVkIG5lbnRzICVkIGRvbWFpbiAlZFxuIiwgX19m dW5jX18sCisJCWltcG9ydGVkX3NndF9pbmZvLT5ncmVmLCBpbXBvcnRlZF9zZ3RfaW5mby0+ZnJz dF9vZnN0LAorCQlpbXBvcnRlZF9zZ3RfaW5mby0+bGFzdF9sZW4sIGltcG9ydGVkX3NndF9pbmZv LT5uZW50cywKKwkJSFlQRVJfRE1BQlVGX0lEX0lNUE9SVEVSX0dFVF9TRE9NQUlOX0lEKGltcG9y dGVkX3NndF9pbmZvLT5oeXBlcl9kbWFidWZfaWQpKTsKKworCWltcG9ydGVkX3NndF9pbmZvLT5z Z3QgPSBoeXBlcl9kbWFidWZfbWFwX3BhZ2VzKGltcG9ydGVkX3NndF9pbmZvLT5ncmVmLAorCQkJ CQkJaW1wb3J0ZWRfc2d0X2luZm8tPmZyc3Rfb2ZzdCwKKwkJCQkJCWltcG9ydGVkX3NndF9pbmZv LT5sYXN0X2xlbiwKKwkJCQkJCWltcG9ydGVkX3NndF9pbmZvLT5uZW50cywKKwkJCQkJCUhZUEVS X0RNQUJVRl9JRF9JTVBPUlRFUl9HRVRfU0RPTUFJTl9JRChpbXBvcnRlZF9zZ3RfaW5mby0+aHlw ZXJfZG1hYnVmX2lkKSwKKwkJCQkJCSZpbXBvcnRlZF9zZ3RfaW5mby0+c2hhcmVkX3BhZ2VzX2lu Zm8pOworCisJaWYgKCFpbXBvcnRlZF9zZ3RfaW5mby0+c2d0KSB7CisJCXJldHVybiAtMTsKKwl9 CisKKwlleHBvcnRfZmRfYXR0ci0+ZmQgPSBoeXBlcl9kbWFidWZfZXhwb3J0X2ZkKGltcG9ydGVk X3NndF9pbmZvLCBleHBvcnRfZmRfYXR0ci0+ZmxhZ3MpOworCWlmIChleHBvcnRfZmRfYXR0ciA8 IDApIHsKKwkJcmV0ID0gZXhwb3J0X2ZkX2F0dHItPmZkOworCX0KKworCXJldHVybiByZXQ7Cit9 CisKKy8qIHJlbW92aW5nIGRtYWJ1ZiBmcm9tIHRoZSBkYXRhYmFzZSBhbmQgc2VuZCBpbnQgcmVx IHRvIHRoZSBzb3VyY2UgZG9tYWluCisqIHRvIHVubWFwIGl0LiAqLworc3RhdGljIGludCBoeXBl cl9kbWFidWZfZGVzdHJveSh2b2lkICpkYXRhKQoreworCXN0cnVjdCBpb2N0bF9oeXBlcl9kbWFi dWZfZGVzdHJveSAqZGVzdHJveV9hdHRyOworCXN0cnVjdCBoeXBlcl9kbWFidWZfc2d0X2luZm8g KnNndF9pbmZvOworCXN0cnVjdCBoeXBlcl9kbWFidWZfcmluZ19ycSAqcmVxOworCWludCByZXQ7 CisKKwlpZiAoIWRhdGEpIHsKKwkJcHJpbnRrKCJ1c2VyIGRhdGEgaXMgTlVMTFxuIik7CisJCXJl dHVybiAtRUlOVkFMOworCX0KKworCWRlc3Ryb3lfYXR0ciA9IChzdHJ1Y3QgaW9jdGxfaHlwZXJf ZG1hYnVmX2Rlc3Ryb3kgKilkYXRhOworCisJLyogZmluZCBkbWFidWYgaW4gZXhwb3J0IGxpc3Qg Ki8KKwlzZ3RfaW5mbyA9IGh5cGVyX2RtYWJ1Zl9maW5kX2V4cG9ydGVkKGRlc3Ryb3lfYXR0ci0+ aHlwZXJfZG1hYnVmX2lkKTsKKwlpZiAoc2d0X2luZm8gPT0gTlVMTCkgeyAvKiBmYWlsZWQgdG8g ZmluZCBjb3JyZXNwb25kaW5nIGVudHJ5IGluIGV4cG9ydCBsaXN0ICovCisJCWRlc3Ryb3lfYXR0 ci0+c3RhdHVzID0gLUVJTlZBTDsKKwkJcmV0dXJuIC1FRkFVTFQ7CisJfQorCisJcmVxID0ga2Nh bGxvYygxLCBzaXplb2YoKnJlcSksIEdGUF9LRVJORUwpOworCisJaHlwZXJfZG1hYnVmX2NyZWF0 ZV9yZXF1ZXN0KHJlcSwgSFlQRVJfRE1BQlVGX0RFU1RST1ksICZkZXN0cm95X2F0dHItPmh5cGVy X2RtYWJ1Zl9pZCk7CisKKwkvKiBub3cgc2VuZCBkZXN0cm95IHJlcXVlc3QgdG8gcmVtb3RlIGRv bWFpbgorCSAqIGN1cnJlbnRseSBhc3N1bWluZyB0aGVyZSdzIG9ubHkgb25lIGltcG9ydGVyIGV4 aXN0ICovCisJcmV0ID0gaHlwZXJfZG1hYnVmX3NlbmRfcmVxdWVzdChzZ3RfaW5mby0+aHlwZXJf ZG1hYnVmX3Jkb21haW4sIHJlcSk7CisJaWYgKHJldCA8IDApIHsKKwkJa2ZyZWUocmVxKTsKKwkJ cmV0dXJuIC1FRkFVTFQ7CisJfQorCisJLyogZnJlZSBtc2cgKi8KKwlrZnJlZShyZXEpOworCWRl c3Ryb3lfYXR0ci0+c3RhdHVzID0gcmV0OworCisJLyogUmVzdCBvZiBjbGVhbnVwIHdpbGwgZm9s bG93IHdoZW4gaW1wb3J0ZXIgd2lsbCBmcmVlIGl0J3MgYnVmZmVyLAorCSAqIGN1cnJlbnQgaW1w bGVtZW50YXRpb24gYXNzdW1lcyB0aGF0IHRoZXJlIGlzIG9ubHkgb25lIGltcG9ydGVyCisgICAg ICAgICAqLworCisJcmV0dXJuIHJldDsKK30KKworc3RhdGljIGludCBoeXBlcl9kbWFidWZfcXVl cnkodm9pZCAqZGF0YSkKK3sKKwlzdHJ1Y3QgaW9jdGxfaHlwZXJfZG1hYnVmX3F1ZXJ5ICpxdWVy eV9hdHRyOworCXN0cnVjdCBoeXBlcl9kbWFidWZfc2d0X2luZm8gKnNndF9pbmZvOworCXN0cnVj dCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gKmltcG9ydGVkX3NndF9pbmZvOworCWlu dCByZXQgPSAwOworCisJaWYgKCFkYXRhKSB7CisJCXByaW50aygidXNlciBkYXRhIGlzIE5VTExc biIpOworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisKKwlxdWVyeV9hdHRyID0gKHN0cnVjdCBpb2N0 bF9oeXBlcl9kbWFidWZfcXVlcnkgKilkYXRhOworCisJc2d0X2luZm8gPSBoeXBlcl9kbWFidWZf ZmluZF9leHBvcnRlZChxdWVyeV9hdHRyLT5oeXBlcl9kbWFidWZfaWQpOworCWltcG9ydGVkX3Nn dF9pbmZvID0gaHlwZXJfZG1hYnVmX2ZpbmRfaW1wb3J0ZWQocXVlcnlfYXR0ci0+aHlwZXJfZG1h YnVmX2lkKTsKKworCS8qIGlmIGRtYWJ1ZiBjYW4ndCBiZSBmb3VuZCBpbiBib3RoIGxpc3RzLCBy ZXR1cm4gKi8KKwlpZiAoIShzZ3RfaW5mbyAmJiBpbXBvcnRlZF9zZ3RfaW5mbykpIHsKKwkJcHJp bnRrKCJjYW4ndCBmaW5kIGVudHJ5IGFueXdoZXJlXG4iKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJ fQorCisJLyogbm90IGNvbnNpZGVyaW5nIHRoZSBjYXNlIHdoZXJlIGEgZG1hYnVmIGlzIGZvdW5k IG9uIGJvdGggcXVldWVzCisJICogaW4gb25lIGRvbWFpbiAqLworCXN3aXRjaCAocXVlcnlfYXR0 ci0+aXRlbSkKKwl7CisJCWNhc2UgRE1BQlVGX1FVRVJZX1RZUEVfTElTVDoKKwkJCWlmIChzZ3Rf aW5mbykgeworCQkJCXF1ZXJ5X2F0dHItPmluZm8gPSBFWFBPUlRFRDsKKwkJCX0gZWxzZSB7CisJ CQkJcXVlcnlfYXR0ci0+aW5mbyA9IElNUE9SVEVEOworCQkJfQorCQkJYnJlYWs7CisKKwkJLyog ZXhwb3J0aW5nIGRvbWFpbiBvZiB0aGlzIHNwZWNpZmljIGRtYWJ1ZiovCisJCWNhc2UgRE1BQlVG X1FVRVJZX0VYUE9SVEVSOgorCQkJaWYgKHNndF9pbmZvKSB7CisJCQkJcXVlcnlfYXR0ci0+aW5m byA9IDB4RkZGRkZGRkY7IC8qIG15c2VsZiAqLworCQkJfSBlbHNlIHsKKwkJCQlxdWVyeV9hdHRy LT5pbmZvID0gKEhZUEVSX0RNQUJVRl9JRF9JTVBPUlRFUl9HRVRfU0RPTUFJTl9JRChpbXBvcnRl ZF9zZ3RfaW5mby0+aHlwZXJfZG1hYnVmX2lkKSk7CisJCQl9CisJCQlicmVhazsKKworCQkvKiBp bXBvcnRpbmcgZG9tYWluIG9mIHRoaXMgc3BlY2lmaWMgZG1hYnVmICovCisJCWNhc2UgRE1BQlVG X1FVRVJZX0lNUE9SVEVSOgorCQkJaWYgKHNndF9pbmZvKSB7CisJCQkJcXVlcnlfYXR0ci0+aW5m byA9IHNndF9pbmZvLT5oeXBlcl9kbWFidWZfcmRvbWFpbjsKKwkJCX0gZWxzZSB7CisjaWYgMCAv KiBUT0RPOiBhIGdsb2JhbCB2YXJpYWJsZSwgY3VycmVudF9kb21haW4gZG9lcyBub3QgZXhpc3Qg eWV0Ki8KKwkJCQlxdWVyeV9hdHRyLT5pbmZvID0gY3VycmVudF9kb21haW47CisjZW5kaWYKKwkJ CX0KKwkJCWJyZWFrOworCisJCS8qIHNpemUgb2YgZG1hYnVmIGluIGJ5dGUgKi8KKwkJY2FzZSBE TUFCVUZfUVVFUllfU0laRToKKwkJCWlmIChzZ3RfaW5mbykgeworI2lmIDAgLyogVE9ETzogaHlw ZXJfZG1hYnVmX2J1Zl9zaXplIGlzIG5vdCBpbXBsZW1lbnRlZCB5ZXQgKi8KKwkJCQlxdWVyeV9h dHRyLT5pbmZvID0gaHlwZXJfZG1hYnVmX2J1Zl9zaXplKHNndF9pbmZvLT5zZ3QpOworI2VuZGlm CisJCQl9IGVsc2UgeworCQkJCXF1ZXJ5X2F0dHItPmluZm8gPSBpbXBvcnRlZF9zZ3RfaW5mby0+ bmVudHMgKiA0MDk2IC0KKwkJCQkJCSAgIGltcG9ydGVkX3NndF9pbmZvLT5mcnN0X29mc3QgLSA0 MDk2ICsKKwkJCQkJCSAgIGltcG9ydGVkX3NndF9pbmZvLT5sYXN0X2xlbjsKKwkJCX0KKwkJCWJy ZWFrOworCX0KKworCXJldHVybiByZXQ7Cit9CisKK3N0YXRpYyBpbnQgaHlwZXJfZG1hYnVmX3Jl bW90ZV9leHBvcnRlcl9yaW5nX3NldHVwKHZvaWQgKmRhdGEpCit7CisJc3RydWN0IGlvY3RsX2h5 cGVyX2RtYWJ1Zl9yZW1vdGVfZXhwb3J0ZXJfcmluZ19zZXR1cCAqcmVtb3RlX2V4cG9ydGVyX3Jp bmdfc2V0dXA7CisJc3RydWN0IGh5cGVyX2RtYWJ1Zl9yaW5nX3JxICpyZXE7CisKKwlyZW1vdGVf ZXhwb3J0ZXJfcmluZ19zZXR1cCA9IChzdHJ1Y3QgaW9jdGxfaHlwZXJfZG1hYnVmX3JlbW90ZV9l eHBvcnRlcl9yaW5nX3NldHVwICopZGF0YTsKKworCXJlcSA9IGtjYWxsb2MoMSwgc2l6ZW9mKCpy ZXEpLCBHRlBfS0VSTkVMKTsKKwloeXBlcl9kbWFidWZfY3JlYXRlX3JlcXVlc3QocmVxLCBIWVBF Ul9ETUFCVUZfRVhQT1JURVJfUklOR19TRVRVUCwgTlVMTCk7CisKKwkvKiByZXF1ZXN0aW5nIHJl bW90ZSBkb21haW4gdG8gc2V0LXVwIGV4cG9ydGVyJ3MgcmluZyAqLworCWlmKGh5cGVyX2RtYWJ1 Zl9zZW5kX3JlcXVlc3QocmVtb3RlX2V4cG9ydGVyX3Jpbmdfc2V0dXAtPnJkb21haW4sIHJlcSkg PCAwKSB7CisJCWtmcmVlKHJlcSk7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCWtmcmVlKHJl cSk7CisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3QgaHlwZXJfZG1hYnVmX2lv Y3RsX2Rlc2MgaHlwZXJfZG1hYnVmX2lvY3Rsc1tdID0geworCUhZUEVSX0RNQUJVRl9JT0NUTF9E RUYoSU9DVExfSFlQRVJfRE1BQlVGX0VYUE9SVEVSX1JJTkdfU0VUVVAsIGh5cGVyX2RtYWJ1Zl9l eHBvcnRlcl9yaW5nX3NldHVwLCAwKSwKKwlIWVBFUl9ETUFCVUZfSU9DVExfREVGKElPQ1RMX0hZ UEVSX0RNQUJVRl9JTVBPUlRFUl9SSU5HX1NFVFVQLCBoeXBlcl9kbWFidWZfaW1wb3J0ZXJfcmlu Z19zZXR1cCwgMCksCisJSFlQRVJfRE1BQlVGX0lPQ1RMX0RFRihJT0NUTF9IWVBFUl9ETUFCVUZf RVhQT1JUX1JFTU9URSwgaHlwZXJfZG1hYnVmX2V4cG9ydF9yZW1vdGUsIDApLAorCUhZUEVSX0RN QUJVRl9JT0NUTF9ERUYoSU9DVExfSFlQRVJfRE1BQlVGX0VYUE9SVF9GRCwgaHlwZXJfZG1hYnVm X2V4cG9ydF9mZF9pb2N0bCwgMCksCisJSFlQRVJfRE1BQlVGX0lPQ1RMX0RFRihJT0NUTF9IWVBF Ul9ETUFCVUZfREVTVFJPWSwgaHlwZXJfZG1hYnVmX2Rlc3Ryb3ksIDApLAorCUhZUEVSX0RNQUJV Rl9JT0NUTF9ERUYoSU9DVExfSFlQRVJfRE1BQlVGX1FVRVJZLCBoeXBlcl9kbWFidWZfcXVlcnks IDApLAorCUhZUEVSX0RNQUJVRl9JT0NUTF9ERUYoSU9DVExfSFlQRVJfRE1BQlVGX1JFTU9URV9F WFBPUlRFUl9SSU5HX1NFVFVQLCBoeXBlcl9kbWFidWZfcmVtb3RlX2V4cG9ydGVyX3Jpbmdfc2V0 dXAsIDApLAorfTsKKworc3RhdGljIGxvbmcgaHlwZXJfZG1hYnVmX2lvY3RsKHN0cnVjdCBmaWxl ICpmaWxwLAorCQkJdW5zaWduZWQgaW50IGNtZCwgdW5zaWduZWQgbG9uZyBwYXJhbSkKK3sKKwlj b25zdCBzdHJ1Y3QgaHlwZXJfZG1hYnVmX2lvY3RsX2Rlc2MgKmlvY3RsID0gTlVMTDsKKwl1bnNp Z25lZCBpbnQgbnIgPSBfSU9DX05SKGNtZCk7CisJaW50IHJldCA9IC1FSU5WQUw7CisJaHlwZXJf ZG1hYnVmX2lvY3RsX3QgZnVuYzsKKwljaGFyICprZGF0YTsKKworCWlvY3RsID0gJmh5cGVyX2Rt YWJ1Zl9pb2N0bHNbbnJdOworCisJZnVuYyA9IGlvY3RsLT5mdW5jOworCisJaWYgKHVubGlrZWx5 KCFmdW5jKSkgeworCQlwcmludGsoIm5vIGZ1bmN0aW9uXG4iKTsKKwkJcmV0dXJuIC1FSU5WQUw7 CisJfQorCisJa2RhdGEgPSBrbWFsbG9jKF9JT0NfU0laRShjbWQpLCBHRlBfS0VSTkVMKTsKKwlp ZiAoIWtkYXRhKSB7CisJCXByaW50aygibm8gbWVtb3J5XG4iKTsKKwkJcmV0dXJuIC1FTk9NRU07 CisJfQorCisJaWYgKGNvcHlfZnJvbV91c2VyKGtkYXRhLCAodm9pZCBfX3VzZXIgKilwYXJhbSwg X0lPQ19TSVpFKGNtZCkpICE9IDApIHsKKwkJcHJpbnRrKCJmYWlsZWQgdG8gY29weSBmcm9tIHVz ZXIgYXJndW1lbnRzXG4iKTsKKwkJcmV0dXJuIC1FRkFVTFQ7CisJfQorCisJcmV0ID0gZnVuYyhr ZGF0YSk7CisKKwlpZiAoY29weV90b191c2VyKCh2b2lkIF9fdXNlciAqKXBhcmFtLCBrZGF0YSwg X0lPQ19TSVpFKGNtZCkpICE9IDApIHsKKwkJcHJpbnRrKCJmYWlsZWQgdG8gY29weSB0byB1c2Vy IGFyZ3VtZW50c1xuIik7CisJCXJldHVybiAtRUZBVUxUOworCX0KKworCWtmcmVlKGtkYXRhKTsK KworCXJldHVybiByZXQ7Cit9CisKK3N0cnVjdCBkZXZpY2VfaW5mbyB7CisJaW50IGN1cnJfZG9t YWluOworfTsKKworLyo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSovCitz dGF0aWMgc3RydWN0IGZpbGVfb3BlcmF0aW9ucyBoeXBlcl9kbWFidWZfZHJpdmVyX2ZvcHMgPQor eworICAgLm93bmVyID0gVEhJU19NT0RVTEUsCisgICAudW5sb2NrZWRfaW9jdGwgPSBoeXBlcl9k bWFidWZfaW9jdGwsCit9OworCitzdGF0aWMgc3RydWN0IG1pc2NkZXZpY2UgaHlwZXJfZG1hYnVm X21pc2NkZXYgPSB7CisJLm1pbm9yID0gTUlTQ19EWU5BTUlDX01JTk9SLAorCS5uYW1lID0gInhl bi9oeXBlcl9kbWFidWYiLAorCS5mb3BzID0gJmh5cGVyX2RtYWJ1Zl9kcml2ZXJfZm9wcywKK307 CisKK3N0YXRpYyBjb25zdCBjaGFyIGRldmljZV9uYW1lW10gPSAiaHlwZXJfZG1hYnVmIjsKKwor Lyo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSovCitpbnQgcmVnaXN0ZXJf ZGV2aWNlKHZvaWQpCit7CisJaW50IHJlc3VsdCA9IDA7CisKKwlyZXN1bHQgPSBtaXNjX3JlZ2lz dGVyKCZoeXBlcl9kbWFidWZfbWlzY2Rldik7CisKKwlpZiAocmVzdWx0ICE9IDApIHsKKwkJcHJp bnRrKEtFUk5fV0FSTklORyAiaHlwZXJfZG1hYnVmOiBkcml2ZXIgY2FuJ3QgYmUgcmVnaXN0ZXJl ZFxuIik7CisJCXJldHVybiByZXN1bHQ7CisJfQorCisJaHlwZXJfZG1hYnVmX3ByaXZhdGUuZGV2 aWNlID0gaHlwZXJfZG1hYnVmX21pc2NkZXYudGhpc19kZXZpY2U7CisKKwkvKiBUT0RPOiBDaGVj ayBpZiB0aGVyZSBpcyBhIGRpZmZlcmVudCB3YXkgdG8gaW5pdGlhbGl6ZSBkbWEgbWFzayBuaWNl bHkgKi8KKwlkbWFfY29lcmNlX21hc2tfYW5kX2NvaGVyZW50KGh5cGVyX2RtYWJ1Zl9wcml2YXRl LmRldmljZSwgMHhGRkZGRkZGRik7CisKKwkvKiBUT0RPIGZpbmQgYSB3YXkgdG8gcHJvdmlkZSBw YXJhbWV0ZXJzIGZvciBiZWxvdyBmdW5jdGlvbiBvciBtb3ZlIHRoYXQgdG8gaW9jdGwgKi8KKy8q CWVyciA9IGJpbmRfaW50ZXJkb21haW5fZXZ0Y2huX3RvX2lycWhhbmRsZXIocmRvbWFpbiwgZXZ0 Y2huLAorCQkJCXNyY19zaW5rX2lzciwgUE9SVF9OVU0sICJyZW1vdGVfZG9tYWluIiwgJmluZm8p OworCWlmIChlcnIgPCAwKSB7CisJCXByaW50aygiaHlwZXJfZG1hYnVmOiBjYW4ndCByZWdpc3Rl ciBpbnRlcnJ1cHQgaGFuZGxlcnNcbiIpOworCQlyZXR1cm4gLUVGQVVMVDsKKwl9CisKKwlpbmZv LmlycSA9IGVycjsKKyovCisJcmV0dXJuIHJlc3VsdDsKK30KKworLyotLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovCit2b2lkIHVucmVnaXN0ZXJfZGV2aWNlKHZvaWQpCit7 CisJcHJpbnRrKCBLRVJOX05PVElDRSAiaHlwZXJfZG1hYnVmOiB1bnJlZ2lzdGVyX2RldmljZSgp IGlzIGNhbGxlZCIgKTsKKwltaXNjX2RlcmVnaXN0ZXIoJmh5cGVyX2RtYWJ1Zl9taXNjZGV2KTsK K30KZGlmZiAtLWdpdCBhL2RyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfbGlz dC5jIGIvZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9saXN0LmMKbmV3IGZp bGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uNzdhN2U2NQotLS0gL2Rldi9udWxsCisrKyBi L2RyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfbGlzdC5jCkBAIC0wLDAgKzEs MTE5IEBACisjaW5jbHVkZSA8bGludXgva2VybmVsLmg+CisjaW5jbHVkZSA8bGludXgvZXJybm8u aD4KKyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+Cisj aW5jbHVkZSA8bGludXgvY2Rldi5oPgorI2luY2x1ZGUgPGFzbS91YWNjZXNzLmg+CisjaW5jbHVk ZSA8bGludXgvaGFzaHRhYmxlLmg+CisjaW5jbHVkZSA8bGludXgvZG1hLWJ1Zi5oPgorI2luY2x1 ZGUgImh5cGVyX2RtYWJ1Zl9saXN0LmgiCisKK0RFQ0xBUkVfSEFTSFRBQkxFKGh5cGVyX2RtYWJ1 Zl9oYXNoX2ltcG9ydGVkLCBNQVhfRU5UUllfSU1QT1JURUQpOworREVDTEFSRV9IQVNIVEFCTEUo aHlwZXJfZG1hYnVmX2hhc2hfZXhwb3J0ZWQsIE1BWF9FTlRSWV9FWFBPUlRFRCk7CisKK2ludCBo eXBlcl9kbWFidWZfdGFibGVfaW5pdCgpCit7CisJaGFzaF9pbml0KGh5cGVyX2RtYWJ1Zl9oYXNo X2ltcG9ydGVkKTsKKwloYXNoX2luaXQoaHlwZXJfZG1hYnVmX2hhc2hfZXhwb3J0ZWQpOworCXJl dHVybiAwOworfQorCitpbnQgaHlwZXJfZG1hYnVmX3RhYmxlX2Rlc3Ryb3koKQoreworCS8qIFRP RE86IGNsZWFudXAgaHlwZXJfZG1hYnVmX2hhc2hfaW1wb3J0ZWQgYW5kIGh5cGVyX2RtYWJ1Zl9o YXNoX2V4cG9ydGVkICovCisJcmV0dXJuIDA7Cit9CisKK2ludCBoeXBlcl9kbWFidWZfcmVnaXN0 ZXJfZXhwb3J0ZWQoc3RydWN0IGh5cGVyX2RtYWJ1Zl9zZ3RfaW5mbyAqaW5mbykKK3sKKwlzdHJ1 Y3QgaHlwZXJfZG1hYnVmX2luZm9fZW50cnlfZXhwb3J0ZWQgKmluZm9fZW50cnk7CisKKwlpbmZv X2VudHJ5ID0ga21hbGxvYyhzaXplb2YoKmluZm9fZW50cnkpLCBHRlBfS0VSTkVMKTsKKworCWlu Zm9fZW50cnktPmluZm8gPSBpbmZvOworCisJaGFzaF9hZGQoaHlwZXJfZG1hYnVmX2hhc2hfZXhw b3J0ZWQsICZpbmZvX2VudHJ5LT5ub2RlLAorCQlpbmZvX2VudHJ5LT5pbmZvLT5oeXBlcl9kbWFi dWZfaWQpOworCisJcmV0dXJuIDA7Cit9CisKK2ludCBoeXBlcl9kbWFidWZfcmVnaXN0ZXJfaW1w b3J0ZWQoc3RydWN0IGh5cGVyX2RtYWJ1Zl9pbXBvcnRlZF9zZ3RfaW5mbyogaW5mbykKK3sKKwlz dHJ1Y3QgaHlwZXJfZG1hYnVmX2luZm9fZW50cnlfaW1wb3J0ZWQgKmluZm9fZW50cnk7CisKKwlp bmZvX2VudHJ5ID0ga21hbGxvYyhzaXplb2YoKmluZm9fZW50cnkpLCBHRlBfS0VSTkVMKTsKKwor CWluZm9fZW50cnktPmluZm8gPSBpbmZvOworCisJaGFzaF9hZGQoaHlwZXJfZG1hYnVmX2hhc2hf aW1wb3J0ZWQsICZpbmZvX2VudHJ5LT5ub2RlLAorCQlpbmZvX2VudHJ5LT5pbmZvLT5oeXBlcl9k bWFidWZfaWQpOworCisJcmV0dXJuIDA7Cit9CisKK3N0cnVjdCBoeXBlcl9kbWFidWZfc2d0X2lu Zm8gKmh5cGVyX2RtYWJ1Zl9maW5kX2V4cG9ydGVkKGludCBpZCkKK3sKKwlzdHJ1Y3QgaHlwZXJf ZG1hYnVmX2luZm9fZW50cnlfZXhwb3J0ZWQgKmluZm9fZW50cnk7CisJaW50IGJrdDsKKworCWhh c2hfZm9yX2VhY2goaHlwZXJfZG1hYnVmX2hhc2hfZXhwb3J0ZWQsIGJrdCwgaW5mb19lbnRyeSwg bm9kZSkKKwkJaWYoaW5mb19lbnRyeS0+aW5mby0+aHlwZXJfZG1hYnVmX2lkID09IGlkKQorCQkJ cmV0dXJuIGluZm9fZW50cnktPmluZm87CisKKwlyZXR1cm4gTlVMTDsKK30KKworLyogc2VhcmNo IGZvciBwcmUtZXhwb3J0ZWQgc2d0IGFuZCByZXR1cm4gaWQgb2YgaXQgaWYgaXQgZXhpc3QgKi8K K2ludCBoeXBlcl9kbWFidWZfZmluZF9pZChzdHJ1Y3QgZG1hX2J1Zl9hdHRhY2htZW50ICphdHRh Y2gsIGludCBkb21pZCkKK3sKKwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX2luZm9fZW50cnlfZXhwb3J0 ZWQgKmluZm9fZW50cnk7CisJaW50IGJrdDsKKworCWhhc2hfZm9yX2VhY2goaHlwZXJfZG1hYnVm X2hhc2hfZXhwb3J0ZWQsIGJrdCwgaW5mb19lbnRyeSwgbm9kZSkKKwkJaWYoaW5mb19lbnRyeS0+ aW5mby0+YXR0YWNobWVudCA9PSBhdHRhY2ggJiYKKwkJCWluZm9fZW50cnktPmluZm8tPmh5cGVy X2RtYWJ1Zl9yZG9tYWluID09IGRvbWlkKQorCQkJcmV0dXJuIGluZm9fZW50cnktPmluZm8tPmh5 cGVyX2RtYWJ1Zl9pZDsKKworCXJldHVybiAtMTsKK30KKworc3RydWN0IGh5cGVyX2RtYWJ1Zl9p bXBvcnRlZF9zZ3RfaW5mbyAqaHlwZXJfZG1hYnVmX2ZpbmRfaW1wb3J0ZWQoaW50IGlkKQorewor CXN0cnVjdCBoeXBlcl9kbWFidWZfaW5mb19lbnRyeV9pbXBvcnRlZCAqaW5mb19lbnRyeTsKKwlp bnQgYmt0OworCisJaGFzaF9mb3JfZWFjaChoeXBlcl9kbWFidWZfaGFzaF9pbXBvcnRlZCwgYmt0 LCBpbmZvX2VudHJ5LCBub2RlKQorCQlpZihpbmZvX2VudHJ5LT5pbmZvLT5oeXBlcl9kbWFidWZf aWQgPT0gaWQpCisJCQlyZXR1cm4gaW5mb19lbnRyeS0+aW5mbzsKKworCXJldHVybiBOVUxMOwor fQorCitpbnQgaHlwZXJfZG1hYnVmX3JlbW92ZV9leHBvcnRlZChpbnQgaWQpCit7CisJc3RydWN0 IGh5cGVyX2RtYWJ1Zl9pbmZvX2VudHJ5X2V4cG9ydGVkICppbmZvX2VudHJ5OworCWludCBia3Q7 CisKKwloYXNoX2Zvcl9lYWNoKGh5cGVyX2RtYWJ1Zl9oYXNoX2V4cG9ydGVkLCBia3QsIGluZm9f ZW50cnksIG5vZGUpCisJCWlmKGluZm9fZW50cnktPmluZm8tPmh5cGVyX2RtYWJ1Zl9pZCA9PSBp ZCkgeworCQkJaGFzaF9kZWwoJmluZm9fZW50cnktPm5vZGUpOworCQkJcmV0dXJuIDA7CisJCX0K KworCXJldHVybiAtMTsKK30KKworaW50IGh5cGVyX2RtYWJ1Zl9yZW1vdmVfaW1wb3J0ZWQoaW50 IGlkKQoreworCXN0cnVjdCBoeXBlcl9kbWFidWZfaW5mb19lbnRyeV9pbXBvcnRlZCAqaW5mb19l bnRyeTsKKwlpbnQgYmt0OworCisJaGFzaF9mb3JfZWFjaChoeXBlcl9kbWFidWZfaGFzaF9pbXBv cnRlZCwgYmt0LCBpbmZvX2VudHJ5LCBub2RlKQorCQlpZihpbmZvX2VudHJ5LT5pbmZvLT5oeXBl cl9kbWFidWZfaWQgPT0gaWQpIHsKKwkJCWhhc2hfZGVsKCZpbmZvX2VudHJ5LT5ub2RlKTsKKwkJ CXJldHVybiAwOworCQl9CisKKwlyZXR1cm4gLTE7Cit9CmRpZmYgLS1naXQgYS9kcml2ZXJzL3hl bi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX2xpc3QuaCBiL2RyaXZlcnMveGVuL2h5cGVyX2Rt YWJ1Zi9oeXBlcl9kbWFidWZfbGlzdC5oCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAw MDAuLjg2OWNkOWEKLS0tIC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYv aHlwZXJfZG1hYnVmX2xpc3QuaApAQCAtMCwwICsxLDQwIEBACisjaWZuZGVmIF9fSFlQRVJfRE1B QlVGX0xJU1RfSF9fCisjZGVmaW5lIF9fSFlQRVJfRE1BQlVGX0xJU1RfSF9fCisKKyNpbmNsdWRl ICJoeXBlcl9kbWFidWZfc3RydWN0LmgiCisKKy8qIG51bWJlciBvZiBiaXRzIHRvIGJlIHVzZWQg Zm9yIGV4cG9ydGVkIGRtYWJ1ZnMgaGFzaCB0YWJsZSAqLworI2RlZmluZSBNQVhfRU5UUllfRVhQ T1JURUQgNworLyogbnVtYmVyIG9mIGJpdHMgdG8gYmUgdXNlZCBmb3IgaW1wb3J0ZWQgZG1hYnVm cyBoYXNoIHRhYmxlICovCisjZGVmaW5lIE1BWF9FTlRSWV9JTVBPUlRFRCA3CisKK3N0cnVjdCBo eXBlcl9kbWFidWZfaW5mb19lbnRyeV9leHBvcnRlZCB7CisgICAgICAgIHN0cnVjdCBoeXBlcl9k bWFidWZfc2d0X2luZm8gKmluZm87CisgICAgICAgIHN0cnVjdCBobGlzdF9ub2RlIG5vZGU7Cit9 OworCitzdHJ1Y3QgaHlwZXJfZG1hYnVmX2luZm9fZW50cnlfaW1wb3J0ZWQgeworICAgICAgICBz dHJ1Y3QgaHlwZXJfZG1hYnVmX2ltcG9ydGVkX3NndF9pbmZvICppbmZvOworICAgICAgICBzdHJ1 Y3QgaGxpc3Rfbm9kZSBub2RlOworfTsKKworaW50IGh5cGVyX2RtYWJ1Zl90YWJsZV9pbml0KHZv aWQpOworCitpbnQgaHlwZXJfZG1hYnVmX3RhYmxlX2Rlc3Ryb3kodm9pZCk7CisKK2ludCBoeXBl cl9kbWFidWZfcmVnaXN0ZXJfZXhwb3J0ZWQoc3RydWN0IGh5cGVyX2RtYWJ1Zl9zZ3RfaW5mbyAq aW5mbyk7CisKKy8qIHNlYXJjaCBmb3IgcHJlLWV4cG9ydGVkIHNndCBhbmQgcmV0dXJuIGlkIG9m IGl0IGlmIGl0IGV4aXN0ICovCitpbnQgaHlwZXJfZG1hYnVmX2ZpbmRfaWQoc3RydWN0IGRtYV9i dWZfYXR0YWNobWVudCAqYXR0YWNoLCBpbnQgZG9taWQpOworCitpbnQgaHlwZXJfZG1hYnVmX3Jl Z2lzdGVyX2ltcG9ydGVkKHN0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8qIGlu Zm8pOworCitzdHJ1Y3QgaHlwZXJfZG1hYnVmX3NndF9pbmZvICpoeXBlcl9kbWFidWZfZmluZF9l eHBvcnRlZChpbnQgaWQpOworCitzdHJ1Y3QgaHlwZXJfZG1hYnVmX2ltcG9ydGVkX3NndF9pbmZv ICpoeXBlcl9kbWFidWZfZmluZF9pbXBvcnRlZChpbnQgaWQpOworCitpbnQgaHlwZXJfZG1hYnVm X3JlbW92ZV9leHBvcnRlZChpbnQgaWQpOworCitpbnQgaHlwZXJfZG1hYnVmX3JlbW92ZV9pbXBv cnRlZChpbnQgaWQpOworCisjZW5kaWYgLy8gX19IWVBFUl9ETUFCVUZfTElTVF9IX18KZGlmZiAt LWdpdCBhL2RyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfbXNnLmMgYi9kcml2 ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX21zZy5jCm5ldyBmaWxlIG1vZGUgMTAw NjQ0CmluZGV4IDAwMDAwMDAuLjMyMzdlNTAKLS0tIC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL3hl bi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX21zZy5jCkBAIC0wLDAgKzEsMjEyIEBACisjaW5j bHVkZSA8bGludXgva2VybmVsLmg+CisjaW5jbHVkZSA8bGludXgvZXJybm8uaD4KKyNpbmNsdWRl IDxsaW51eC9tb2R1bGUuaD4KKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+CisjaW5jbHVkZSA8bGlu dXgvZG1hLWJ1Zi5oPgorI2luY2x1ZGUgImh5cGVyX2RtYWJ1Zl9pbXAuaCIKKy8vI2luY2x1ZGUg Imh5cGVyX2RtYWJ1Zl9yZW1vdGVfc3luYy5oIgorI2luY2x1ZGUgInhlbi9oeXBlcl9kbWFidWZf eGVuX2NvbW0uaCIKKyNpbmNsdWRlICJoeXBlcl9kbWFidWZfbXNnLmgiCisjaW5jbHVkZSAiaHlw ZXJfZG1hYnVmX2xpc3QuaCIKKwordm9pZCBoeXBlcl9kbWFidWZfY3JlYXRlX3JlcXVlc3Qoc3Ry dWN0IGh5cGVyX2RtYWJ1Zl9yaW5nX3JxICpyZXF1ZXN0LAorCQkJCSAgICAgICAgZW51bSBoeXBl cl9kbWFidWZfY29tbWFuZCBjb21tYW5kLCBpbnQgKm9wZXJhbmRzKQoreworCWludCBpOworCisJ cmVxdWVzdC0+cmVxdWVzdF9pZCA9IGh5cGVyX2RtYWJ1Zl9uZXh0X3JlcV9pZF9leHBvcnQoKTsK KwlyZXF1ZXN0LT5zdGF0dXMgPSBIWVBFUl9ETUFCVUZfUkVRX05PVF9SRVNQT05ERUQ7CisJcmVx dWVzdC0+Y29tbWFuZCA9IGNvbW1hbmQ7CisKKwlzd2l0Y2goY29tbWFuZCkgeworCS8qIGFzIGV4 cG9ydGVyLCBjb21tYW5kcyB0byBpbXBvcnRlciAqLworCWNhc2UgSFlQRVJfRE1BQlVGX0VYUE9S VDoKKwkJLyogZXhwb3J0aW5nIHBhZ2VzIGZvciBkbWFidWYgKi8KKwkJLyogY29tbWFuZCA6IEhZ UEVSX0RNQUJVRl9FWFBPUlQsCisJCSAqIG9wZXJhbmRzMCA6IGh5cGVyX2RtYWJ1Zl9pZAorCQkg KiBvcGVyYW5kczEgOiBudW1iZXIgb2YgcGFnZXMgdG8gYmUgc2hhcmVkCisJCSAqIG9wZXJhbmRz MiA6IG9mZnNldCBvZiBkYXRhIGluIHRoZSBmaXJzdCBwYWdlCisJCSAqIG9wZXJhbmRzMyA6IGxl bmd0aCBvZiBkYXRhIGluIHRoZSBsYXN0IHBhZ2UKKwkJICogb3BlcmFuZHM0IDogdG9wLWxldmVs IHJlZmVyZW5jZSBudW1iZXIgZm9yIHNoYXJlZCBwYWdlcworCQkgKiBvcGVyYW5kczV+OCA6IERy aXZlci1zcGVjaWZpYyBwcml2YXRlIGRhdGEgKGUuZy4gZ3JhcGhpYyBidWZmZXIncyBtZXRhIGlu Zm8pCisJCSAqLworCQlmb3IgKGk9MDsgaSA8IDg7IGkrKykKKwkJCXJlcXVlc3QtPm9wZXJhbmRz W2ldID0gb3BlcmFuZHNbaV07CisJCWJyZWFrOworCisJY2FzZSBIWVBFUl9ETUFCVUZfREVTVFJP WToKKwkJLyogZGVzdHJveSBzZ19saXN0IGZvciBoeXBlcl9kbWFidWZfaWQgb24gcmVtb3RlIHNp ZGUgKi8KKwkJLyogY29tbWFuZCA6IERNQUJVRl9ERVNUUk9ZLAorCQkgKiBvcGVyYW5kczAgOiBo eXBlcl9kbWFidWZfaWQKKwkJICovCisJCXJlcXVlc3QtPm9wZXJhbmRzWzBdID0gb3BlcmFuZHNb MF07CisJCWJyZWFrOworCisJY2FzZSBIWVBFUl9ETUFCVUZfT1BTX1RPX1JFTU9URToKKwkJLyog bm90aWZ5aW5nIGRtYWJ1ZiBtYXAvdW5tYXAgdG8gaW1wb3J0ZXIgKHByb2JhYmx5IG5vdCBuZWVk ZWQpICovCisJCS8qIGZvciBkbWFidWYgc3luY2hyb25pemF0aW9uICovCisJCWJyZWFrOworCisJ LyogYXMgaW1wb3J0ZXIsIGNvbW1hbmQgdG8gZXhwb3J0ZXIgKi8KKwljYXNlIEhZUEVSX0RNQUJV Rl9PUFNfVE9fU09VUkNFOgorCQkvKiBub3RpZnlpbmcgZG1hYnVmIG1hcC91bm1hcCB0byBleHBv cnRlciwgbWFwIHdpbGwgbWFrZSB0aGUgZHJpdmVyIHRvIGRvIHNoYWRvdyBtYXBwaW5nCisJCSog b3IgdW5tYXBwaW5nIGZvciBzeW5jaHJvbml6YXRpb24gd2l0aCBvcmlnaW5hbCBleHBvcnRlciAo ZS5nLiBpOTE1KSAqLworCQkvKiBjb21tYW5kIDogRE1BQlVGX09QU19UT19TT1VSQ0UuCisJCSAq IG9wZXJhbmRzMCA6IGh5cGVyX2RtYWJ1Zl9pZAorCQkgKiBvcGVyYW5kczEgOiBtYXAoPTEpL3Vu bWFwKD0yKS9hdHRhY2goPTMpL2RldGFjaCg9NCkKKwkJICovCisJCWZvciAoaT0wOyBpPDI7IGkr KykKKwkJCXJlcXVlc3QtPm9wZXJhbmRzW2ldID0gb3BlcmFuZHNbaV07CisJCWJyZWFrOworCisJ LyogcmVxdWVzdGluZyB0aGUgb3RoZXIgc2lkZSB0byBzZXR1cCBhbm90aGVyIHJpbmcgY2hhbm5l bCBmb3IgcmV2ZXJzZSBkaXJlY3Rpb24gKi8KKwljYXNlIEhZUEVSX0RNQUJVRl9FWFBPUlRFUl9S SU5HX1NFVFVQOgorCQkvKiBjb21tYW5kIDogSFlQRVJfRE1BQlVGX0VYUE9SVEVSX1JJTkdfU0VU VVAgKi8KKwkJLyogbm8gb3BlcmFuZHMgbmVlZGVkICovCisJCWJyZWFrOworCisJZGVmYXVsdDoK KwkJLyogbm8gY29tbWFuZCBmb3VuZCAqLworCQlyZXR1cm47CisJfQorfQorCitpbnQgaHlwZXJf ZG1hYnVmX21zZ19wYXJzZShpbnQgZG9taWQsIHN0cnVjdCBoeXBlcl9kbWFidWZfcmluZ19ycSAq cmVxKQoreworCXVpbnQzMl90IGksIHJldDsKKwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX2ltcG9ydGVk X3NndF9pbmZvICppbXBvcnRlZF9zZ3RfaW5mbzsKKwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX3NndF9p bmZvICpzZ3RfaW5mbzsKKworCS8qIG1ha2Ugc3VyZSByZXEgaXMgbm90IE5VTEwgKG1heSBub3Qg YmUgbmVlZGVkKSAqLworCWlmICghcmVxKSB7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCXJl cS0+c3RhdHVzID0gSFlQRVJfRE1BQlVGX1JFUV9QUk9DRVNTRUQ7CisKKwlzd2l0Y2ggKHJlcS0+ Y29tbWFuZCkgeworCWNhc2UgSFlQRVJfRE1BQlVGX0VYUE9SVDoKKwkJLyogZXhwb3J0aW5nIHBh Z2VzIGZvciBkbWFidWYgKi8KKwkJLyogY29tbWFuZCA6IEhZUEVSX0RNQUJVRl9FWFBPUlQsCisJ CSAqIG9wZXJhbmRzMCA6IGh5cGVyX2RtYWJ1Zl9pZAorCQkgKiBvcGVyYW5kczEgOiBudW1iZXIg b2YgcGFnZXMgdG8gYmUgc2hhcmVkCisJCSAqIG9wZXJhbmRzMiA6IG9mZnNldCBvZiBkYXRhIGlu IHRoZSBmaXJzdCBwYWdlCisJCSAqIG9wZXJhbmRzMyA6IGxlbmd0aCBvZiBkYXRhIGluIHRoZSBs YXN0IHBhZ2UKKwkJICogb3BlcmFuZHM0IDogdG9wLWxldmVsIHJlZmVyZW5jZSBudW1iZXIgZm9y IHNoYXJlZCBwYWdlcworCQkgKiBvcGVyYW5kczV+OCA6IERyaXZlci1zcGVjaWZpYyBwcml2YXRl IGRhdGEgKGUuZy4gZ3JhcGhpYyBidWZmZXIncyBtZXRhIGluZm8pCisJCSAqLworCQlpbXBvcnRl ZF9zZ3RfaW5mbyA9IChzdHJ1Y3QgaHlwZXJfZG1hYnVmX2ltcG9ydGVkX3NndF9pbmZvKilrY2Fs bG9jKDEsIHNpemVvZigqaW1wb3J0ZWRfc2d0X2luZm8pLCBHRlBfS0VSTkVMKTsKKwkJaW1wb3J0 ZWRfc2d0X2luZm8tPmh5cGVyX2RtYWJ1Zl9pZCA9IHJlcS0+b3BlcmFuZHNbMF07CisJCWltcG9y dGVkX3NndF9pbmZvLT5mcnN0X29mc3QgPSByZXEtPm9wZXJhbmRzWzJdOworCQlpbXBvcnRlZF9z Z3RfaW5mby0+bGFzdF9sZW4gPSByZXEtPm9wZXJhbmRzWzNdOworCQlpbXBvcnRlZF9zZ3RfaW5m by0+bmVudHMgPSByZXEtPm9wZXJhbmRzWzFdOworCQlpbXBvcnRlZF9zZ3RfaW5mby0+Z3JlZiA9 IHJlcS0+b3BlcmFuZHNbNF07CisKKwkJcHJpbnRrKCJETUFCVUYgd2FzIGV4cG9ydGVkXG4iKTsK KwkJcHJpbnRrKCJcdGh5cGVyX2RtYWJ1Zl9pZCAlZFxuIiwgcmVxLT5vcGVyYW5kc1swXSk7CisJ CXByaW50aygiXHRuZW50cyAlZFxuIiwgcmVxLT5vcGVyYW5kc1sxXSk7CisJCXByaW50aygiXHRm aXJzdCBvZmZzZXQgJWRcbiIsIHJlcS0+b3BlcmFuZHNbMl0pOworCQlwcmludGsoIlx0bGFzdCBs ZW4gJWRcbiIsIHJlcS0+b3BlcmFuZHNbM10pOworCQlwcmludGsoIlx0Z3JlZmlkICVkXG4iLCBy ZXEtPm9wZXJhbmRzWzRdKTsKKworCQlmb3IgKGk9MDsgaTw0OyBpKyspCisJCQlpbXBvcnRlZF9z Z3RfaW5mby0+cHJpdmF0ZVtpXSA9IHJlcS0+b3BlcmFuZHNbNStpXTsKKworCQloeXBlcl9kbWFi dWZfcmVnaXN0ZXJfaW1wb3J0ZWQoaW1wb3J0ZWRfc2d0X2luZm8pOworCQlicmVhazsKKworCWNh c2UgSFlQRVJfRE1BQlVGX0RFU1RST1k6CisJCS8qIGRlc3Ryb3kgc2dfbGlzdCBmb3IgaHlwZXJf ZG1hYnVmX2lkIG9uIHJlbW90ZSBzaWRlICovCisJCS8qIGNvbW1hbmQgOiBETUFCVUZfREVTVFJP WSwKKwkJICogb3BlcmFuZHMwIDogaHlwZXJfZG1hYnVmX2lkCisJCSAqLworCisJCWltcG9ydGVk X3NndF9pbmZvID0KKwkJCWh5cGVyX2RtYWJ1Zl9maW5kX2ltcG9ydGVkKHJlcS0+b3BlcmFuZHNb MF0pOworCisJCWlmIChpbXBvcnRlZF9zZ3RfaW5mbykgeworCQkJaHlwZXJfZG1hYnVmX2NsZWFu dXBfaW1wb3J0ZWRfcGFnZXMoaW1wb3J0ZWRfc2d0X2luZm8pOworCisJCQloeXBlcl9kbWFidWZf cmVtb3ZlX2ltcG9ydGVkKHJlcS0+b3BlcmFuZHNbMF0pOworCisJCQkvKiBUT0RPOiBjbGVhbnVw IHNndCBvbiBpbXBvcnRlciBzaWRlIGV0YyAqLworCQl9CisKKwkJLyogTm90aWZ5IGV4cG9ydGVy IHRoYXQgYnVmZmVyIGlzIGZyZWVkIGFuZCBpdCBjYW4gY2xlYW51cCBpdCAqLworCQlyZXEtPnN0 YXR1cyA9IEhZUEVSX0RNQUJVRl9SRVFfTkVFRFNfRk9MTE9XX1VQOworCQlyZXEtPmNvbW1hbmQg PSBIWVBFUl9ETUFCVUZfREVTVFJPWV9GSU5JU0g7CisKKyNpZiAwIC8qIGZ1bmN0aW9uIGlzIG5v dCBpbXBsZW1lbnRlZCB5ZXQgKi8KKworCQlyZXQgPSBoeXBlcl9kbWFidWZfZGVzdHJveV9zZ3Qo cmVxLT5oeXBlcl9kbWFidWZfaWQpOworI2VuZGlmCisJCWJyZWFrOworCisJY2FzZSBIWVBFUl9E TUFCVUZfREVTVFJPWV9GSU5JU0g6CisJCS8qIGRlc3Ryb3kgc2dfbGlzdCBmb3IgaHlwZXJfZG1h YnVmX2lkIG9uIGxvY2FsIHNpZGUgKi8KKwkJLyogY29tbWFuZCA6IERNQUJVRl9ERVNUUk9ZX0ZJ TklTSCwKKwkJICogb3BlcmFuZHMwIDogaHlwZXJfZG1hYnVmX2lkCisJCSAqLworCisJCS8qIFRP RE86IHRoYXQgc2hvdWxkIGJlIGRvbmUgb24gd29ya3F1ZXVlLCB3aGVuIHJlY2VpdmVkIGFjayBm cm9tIGFsbCBpbXBvcnRlcnMgdGhhdCBidWZmZXIgaXMgbm8gbG9uZ2VyIHVzZWQgKi8KKwkJc2d0 X2luZm8gPQorCQkJaHlwZXJfZG1hYnVmX2ZpbmRfZXhwb3J0ZWQocmVxLT5vcGVyYW5kc1swXSk7 CisKKwkJaWYgKHNndF9pbmZvKSB7CisJCQloeXBlcl9kbWFidWZfY2xlYW51cF9ncmVmX3RhYmxl KHNndF9pbmZvKTsKKworCQkJLyogdW5tYXAgZG1hYnVmICovCisJCQlkbWFfYnVmX3VubWFwX2F0 dGFjaG1lbnQoc2d0X2luZm8tPmF0dGFjaG1lbnQsIHNndF9pbmZvLT5zZ3QsIERNQV9CSURJUkVD VElPTkFMKTsKKwkJCWRtYV9idWZfZGV0YWNoKHNndF9pbmZvLT5kbWFfYnVmLCBzZ3RfaW5mby0+ YXR0YWNobWVudCk7CisJCQlkbWFfYnVmX3B1dChzZ3RfaW5mby0+ZG1hX2J1Zik7CisKKwkJCS8q IFRPRE86IFJlc3Qgb2YgY2xlYW51cCwgc2d0IGNsZWFudXAgZXRjICovCisJCX0KKworCQlicmVh azsKKworCWNhc2UgSFlQRVJfRE1BQlVGX09QU19UT19SRU1PVEU6CisJCS8qIG5vdGlmeWluZyBk bWFidWYgbWFwL3VubWFwIHRvIGltcG9ydGVyIChwcm9iYWJseSBub3QgbmVlZGVkKSAqLworCQkv KiBmb3IgZG1hYnVmIHN5bmNocm9uaXphdGlvbiAqLworCQlicmVhazsKKworCS8qIGFzIGltcG9y dGVyLCBjb21tYW5kIHRvIGV4cG9ydGVyICovCisJY2FzZSBIWVBFUl9ETUFCVUZfT1BTX1RPX1NP VVJDRToKKwkJLyogbm90aWZ5aW5nIGRtYWJ1ZiBtYXAvdW5tYXAgdG8gZXhwb3J0ZXIsIG1hcCB3 aWxsIG1ha2UgdGhlIGRyaXZlciB0byBkbyBzaGFkb3cgbWFwcGluZworCQkqIG9yIHVubWFwcGlu ZyBmb3Igc3luY2hyb25pemF0aW9uIHdpdGggb3JpZ2luYWwgZXhwb3J0ZXIgKGUuZy4gaTkxNSkg Ki8KKwkJLyogY29tbWFuZCA6IERNQUJVRl9PUFNfVE9fU09VUkNFLgorCQkgKiBvcGVyYW5kczAg OiBoeXBlcl9kbWFidWZfaWQKKwkJICogb3BlcmFuZHMxIDogbWFwKD0xKS91bm1hcCg9MikvYXR0 YWNoKD0zKS9kZXRhY2goPTQpCisJCSAqLworCQlicmVhazsKKworCS8qIHJlcXVlc3RpbmcgdGhl IG90aGVyIHNpZGUgdG8gc2V0dXAgYW5vdGhlciByaW5nIGNoYW5uZWwgZm9yIHJldmVyc2UgZGly ZWN0aW9uICovCisJY2FzZSBIWVBFUl9ETUFCVUZfRVhQT1JURVJfUklOR19TRVRVUDoKKwkJLyog Y29tbWFuZDogSFlQRVJfRE1BQlVGX0VYUE9SVEVSX1JJTkdfU0VUVVAKKwkJICogbm8gb3BlcmFu ZHMgbmVlZGVkICovCisJCXJldCA9IGh5cGVyX2RtYWJ1Zl9leHBvcnRlcl9yaW5nYnVmX2luaXQo ZG9taWQsICZyZXEtPm9wZXJhbmRzWzBdLCAmcmVxLT5vcGVyYW5kc1sxXSk7CisJCWlmIChyZXQg PCAwKSB7CisJCQlyZXEtPnN0YXR1cyA9IEhZUEVSX0RNQUJVRl9SRVFfRVJST1I7CisJCQlyZXR1 cm4gLUVJTlZBTDsKKwkJfQorCisJCXJlcS0+c3RhdHVzID0gSFlQRVJfRE1BQlVGX1JFUV9ORUVE U19GT0xMT1dfVVA7CisJCXJlcS0+Y29tbWFuZCA9IEhZUEVSX0RNQUJVRl9JTVBPUlRFUl9SSU5H X1NFVFVQOworCQlicmVhazsKKworCWNhc2UgSFlQRVJfRE1BQlVGX0lNUE9SVEVSX1JJTkdfU0VU VVA6CisJCS8qIGNvbW1hbmQ6IEhZUEVSX0RNQUJVRl9JTVBPUlRFUl9SSU5HX1NFVFVQICovCisJ CS8qIG5vIG9wZXJhbmRzIG5lZWRlZCAqLworCQlyZXQgPSBoeXBlcl9kbWFidWZfaW1wb3J0ZXJf cmluZ2J1Zl9pbml0KGRvbWlkLCByZXEtPm9wZXJhbmRzWzBdLCByZXEtPm9wZXJhbmRzWzFdKTsK KwkJaWYgKHJldCA8IDApCisJCQlyZXR1cm4gLUVJTlZBTDsKKworCQlicmVhazsKKworCWRlZmF1 bHQ6CisJCS8qIG5vIG1hdGNoZWQgY29tbWFuZCwgbm90aGluZyB0byBkby4uIGp1c3QgcmV0dXJu IGVycm9yICovCisJCXJldHVybiAtRUlOVkFMOworCX0KKworCXJldHVybiByZXEtPmNvbW1hbmQ7 Cit9CmRpZmYgLS1naXQgYS9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX21z Zy5oIGIvZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9tc2cuaApuZXcgZmls ZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwLi40NGJmYjcwCi0tLSAvZGV2L251bGwKKysrIGIv ZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5cGVyX2RtYWJ1Zl9tc2cuaApAQCAtMCwwICsxLDQ1 IEBACisjaWZuZGVmIF9fSFlQRVJfRE1BQlVGX01TR19IX18KKyNkZWZpbmUgX19IWVBFUl9ETUFC VUZfTVNHX0hfXworCitlbnVtIGh5cGVyX2RtYWJ1Zl9jb21tYW5kIHsKKwlIWVBFUl9ETUFCVUZf RVhQT1JUID0gMHgxMCwKKwlIWVBFUl9ETUFCVUZfREVTVFJPWSwKKwlIWVBFUl9ETUFCVUZfREVT VFJPWV9GSU5JU0gsCisJSFlQRVJfRE1BQlVGX09QU19UT19SRU1PVEUsCisJSFlQRVJfRE1BQlVG X09QU19UT19TT1VSQ0UsCisJSFlQRVJfRE1BQlVGX0VYUE9SVEVSX1JJTkdfU0VUVVAsIC8qIHJl cXVlc3RpbmcgcmVtb3RlIGRvbWFpbiB0byBzZXQgdXAgZXhwb3J0ZXIncyByaW5nICovCisJSFlQ RVJfRE1BQlVGX0lNUE9SVEVSX1JJTkdfU0VUVVAsIC8qIHJlcXVlc3RpbmcgcmVtb3RlIGRvbWFp biB0byBzZXQgdXAgaW1wb3J0ZXIncyByaW5nICovCit9OworCitlbnVtIGh5cGVyX2RtYWJ1Zl9v cHMgeworCUhZUEVSX0RNQUJVRl9PUFNfQVRUQUNIID0gMHgxMDAwLAorCUhZUEVSX0RNQUJVRl9P UFNfREVUQUNILAorCUhZUEVSX0RNQUJVRl9PUFNfTUFQLAorCUhZUEVSX0RNQUJVRl9PUFNfVU5N QVAsCisJSFlQRVJfRE1BQlVGX09QU19SRUxFQVNFLAorCUhZUEVSX0RNQUJVRl9PUFNfQkVHSU5f Q1BVX0FDQ0VTUywKKwlIWVBFUl9ETUFCVUZfT1BTX0VORF9DUFVfQUNDRVNTLAorCUhZUEVSX0RN QUJVRl9PUFNfS01BUF9BVE9NSUMsCisJSFlQRVJfRE1BQlVGX09QU19LVU5NQVBfQVRPTUlDLAor CUhZUEVSX0RNQUJVRl9PUFNfS01BUCwKKwlIWVBFUl9ETUFCVUZfT1BTX0tVTk1BUCwKKwlIWVBF Ul9ETUFCVUZfT1BTX01NQVAsCisJSFlQRVJfRE1BQlVGX09QU19WTUFQLAorCUhZUEVSX0RNQUJV Rl9PUFNfVlVOTUFQLAorfTsKKworZW51bSBoeXBlcl9kbWFidWZfcmVxX2ZlZWRiYWNrIHsKKwlI WVBFUl9ETUFCVUZfUkVRX1BST0NFU1NFRCA9IDB4MTAwLAorCUhZUEVSX0RNQUJVRl9SRVFfTkVF RFNfRk9MTE9XX1VQLAorCUhZUEVSX0RNQUJVRl9SRVFfRVJST1IsCisJSFlQRVJfRE1BQlVGX1JF UV9OT1RfUkVTUE9OREVECit9OworCisvKiBjcmVhdGUgYSByZXF1ZXN0IHBhY2tldCB3aXRoIGdp dmVuIGNvbW1hbmQgYW5kIG9wZXJhbmRzICovCit2b2lkIGh5cGVyX2RtYWJ1Zl9jcmVhdGVfcmVx dWVzdChzdHJ1Y3QgaHlwZXJfZG1hYnVmX3JpbmdfcnEgKnJlcXVlc3QsCisgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgZW51bSBoeXBlcl9kbWFidWZfY29tbWFuZCBjb21t YW5kLCBpbnQgKm9wZXJhbmRzKTsKKworLyogcGFyc2UgaW5jb21pbmcgcmVxdWVzdCBwYWNrZXQg KG9yIHJlc3BvbnNlKSBhbmQgdGFrZSBhcHByb3ByaWF0ZSBhY3Rpb25zIGZvciB0aG9zZSAqLwor aW50IGh5cGVyX2RtYWJ1Zl9tc2dfcGFyc2UoaW50IGRvbWlkLCBzdHJ1Y3QgaHlwZXJfZG1hYnVm X3JpbmdfcnEgKnJlcSk7CisKKyNlbmRpZiAvLyBfX0hZUEVSX0RNQUJVRl9NU0dfSF9fCmRpZmYg LS1naXQgYS9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX3F1ZXJ5LmggYi9k cml2ZXJzL3hlbi9oeXBlcl9kbWFidWYvaHlwZXJfZG1hYnVmX3F1ZXJ5LmgKbmV3IGZpbGUgbW9k ZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uYTU3NzE2NwotLS0gL2Rldi9udWxsCisrKyBiL2RyaXZl cnMveGVuL2h5cGVyX2RtYWJ1Zi9oeXBlcl9kbWFidWZfcXVlcnkuaApAQCAtMCwwICsxLDE2IEBA CisjaWZuZGVmIF9fSFlQRVJfRE1BQlVGX1FVRVJZX0hfXworI2RlZmluZSBfX0hZUEVSX0RNQUJV Rl9RVUVSWV9IX18KKworZW51bSBoeXBlcl9kbWFidWZfcXVlcnkgeworCURNQUJVRl9RVUVSWV9U WVBFX0xJU1QgPSAweDEwLAorCURNQUJVRl9RVUVSWV9FWFBPUlRFUiwKKwlETUFCVUZfUVVFUllf SU1QT1JURVIsCisJRE1BQlVGX1FVRVJZX1NJWkUKK307CisKK2VudW0gaHlwZXJfZG1hYnVmX3N0 YXR1cyB7CisJRVhQT1JURUQgPSAweDAxLAorCUlNUE9SVEVECit9OworCisjZW5kaWYgLyogX19I WVBFUl9ETUFCVUZfUVVFUllfSF9fICovCmRpZmYgLS1naXQgYS9kcml2ZXJzL3hlbi9oeXBlcl9k bWFidWYvaHlwZXJfZG1hYnVmX3N0cnVjdC5oIGIvZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5 cGVyX2RtYWJ1Zl9zdHJ1Y3QuaApuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwLi5j OGEyZjRkCi0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy94ZW4vaHlwZXJfZG1hYnVmL2h5cGVy X2RtYWJ1Zl9zdHJ1Y3QuaApAQCAtMCwwICsxLDcwIEBACisjaWZuZGVmIF9fSFlQRVJfRE1BQlVG X1NUUlVDVF9IX18KKyNkZWZpbmUgX19IWVBFUl9ETUFCVUZfU1RSVUNUX0hfXworCisjaW5jbHVk ZSA8eGVuL2ludGVyZmFjZS9ncmFudF90YWJsZS5oPgorCisvKiBJbXBvcnRlciBjb21iaW5lIHNv dXJjZSBkb21haW4gaWQgd2l0aCBnaXZlbiBoeXBlcl9kbWFidWZfaWQKKyAqIHRvIG1ha2UgaXQg dW5pcXVlIGluIGNhc2UgdGhlcmUgYXJlIG11bHRpcGxlIGV4cG9ydGVycyAqLworCisjZGVmaW5l IEhZUEVSX0RNQUJVRl9JRF9JTVBPUlRFUihzZG9tYWluLCBpZCkgXAorCSgoKChzZG9tYWluKSAm IDB4RkYpIDw8IDI0KSB8ICgoaWQpICYgMHhGRkZGRkYpKQorCisjZGVmaW5lIEhZUEVSX0RNQUJV Rl9JRF9JTVBPUlRFUl9HRVRfU0RPTUFJTl9JRChpZCkgXAorCSgoKGlkKSA+PiAyNCkgJiAweEZG KQorCisvKiBlYWNoIGdyYW50X3JlZl90IGlzIDQgYnl0ZXMsIHNvIHRvdGFsIDQwOTYgZ3JhbnRf cmVmX3QgY2FuIGJlCisgKiBpbiB0aGlzIGJsb2NrIG1lYW5pbmcgd2UgY2FuIHNoYXJlIDRLQio0 MDk2ID0gMTZNQiBvZiBidWZmZXIKKyAqIChuZWVkcyB0byBiZSBpbmNyZWFzZWQgZm9yIGxhcmdl IGJ1ZmZlciB1c2UtY2FzZXMgc3VjaCBhcyA0SworICogZnJhbWUgYnVmZmVyKSAqLworI2RlZmlu ZSBNQVhfQUxMT1dFRF9OVU1fUEFHRVNfRk9SX0dSRUZfTlVNX0FSUkFZUyA0CisKK3N0cnVjdCBo eXBlcl9kbWFidWZfc2hhcmVkX3BhZ2VzX2luZm8geworCWdyYW50X3JlZl90ICpkYXRhX3JlZnM7 CS8qIHRhYmxlIHdpdGggc2hhcmVkIGJ1ZmZlciBwYWdlcyByZWZpZCAqLworCWdyYW50X3JlZl90 ICphZGRyX3BhZ2VzOyAvKiBwYWdlcyBvZiAybmQgbGV2ZWwgYWRkcmVzc2luZyAqLworCWdyYW50 X3JlZl90ICp0b3BfbGV2ZWxfcGFnZTsgLyogcGFnZSBvZiB0b3AgbGV2ZWwgYWRkcmVzc2luZywg aXQgY29udGFpbnMgcmVmaWRzIG9mIDJuZCBsZXZlbCBwYWdlcyAqLworCWdyYW50X3JlZl90IHRv cF9sZXZlbF9yZWY7IC8qIHRvcCBsZXZlbCByZWZpZCAqLworCXN0cnVjdCBnbnR0YWJfdW5tYXBf Z3JhbnRfcmVmKiB1bm1hcF9vcHM7IC8qIHVubWFwIG9wcyBmb3IgbWFwcGVkIHBhZ2VzICovCisJ c3RydWN0IHBhZ2UgKipkYXRhX3BhZ2VzOyAvKiBkYXRhIHBhZ2VzIHRvIGJlIHVubWFwcGVkICov Cit9OworCisvKiBFeHBvcnRlciBidWlsZHMgcGFnZXNfaW5mbyBiZWZvcmUgc2hhcmluZyBwYWdl cyAqLworc3RydWN0IGh5cGVyX2RtYWJ1Zl9wYWdlc19pbmZvIHsKKyAgICAgICAgaW50IGh5cGVy X2RtYWJ1Zl9pZDsgLyogdW5pcXVlIGlkIHRvIHJlZmVyZW5jZSBkbWFidWYgaW4gc291cmNlIGRv bWFpbiAqLworICAgICAgICBpbnQgaHlwZXJfZG1hYnVmX3Jkb21haW47IC8qIGN1cnJlbnRpbmcg Y29uc2lkZXJpbmcganVzdCBvbmUgcmVtb3RlIGRvbWFpbiBhY2Nlc3MgaXQgKi8KKyAgICAgICAg aW50IGZyc3Rfb2ZzdDsgLyogb2Zmc2V0IG9mIGRhdGEgaW4gdGhlIGZpcnN0IHBhZ2UgKi8KKyAg ICAgICAgaW50IGxhc3RfbGVuOyAvKiBsZW5ndGggb2YgZGF0YSBpbiB0aGUgbGFzdCBwYWdlICov CisgICAgICAgIGludCBuZW50czsgLyogIyBvZiBwYWdlcyAqLworICAgICAgICBzdHJ1Y3QgcGFn ZSAqKnBhZ2VzOyAvKiBwYWdlcyB0aGF0IGNvbnRhaW5zIHJlZmVyZW5jZSBudW1iZXJzIG9mIHNo YXJlZCBwYWdlcyovCit9OworCisvKiBCb3RoIGltcG9ydGVyIGFuZCBleHBvcnRlciB1c2UgdGhp cyBzdHJ1Y3R1cmUgdG8gcG9pbnQgdG8gc2cgbGlzdHMKKyAqCisgKiBFeHBvcnRlciBzdG9yZXMg cmVmZXJlbmNlcyB0byBzZ3QgaW4gYSBoYXNoIHRhYmxlCisgKiBFeHBvcnRlciBrZWVwcyB0aGVz ZSByZWZlcmVuY2VzIGZvciBzeW5jaHJvbml6YXRpb24gYW5kIHRyYWNraW5nIHB1cnBvc2VzCisg KgorICogSW1wb3J0ZXIgdXNlIHRoaXMgc3RydWN0dXJlIGV4cG9ydGluZyB0byBvdGhlciBkcml2 ZXJzIGluIHRoZSBzYW1lIGRvbWFpbiAqLworc3RydWN0IGh5cGVyX2RtYWJ1Zl9zZ3RfaW5mbyB7 CisgICAgICAgIGludCBoeXBlcl9kbWFidWZfaWQ7IC8qIHVuaXF1ZSBpZCB0byByZWZlcmVuY2Ug ZG1hYnVmIGluIHJlbW90ZSBkb21haW4gKi8KKwlpbnQgaHlwZXJfZG1hYnVmX3Jkb21haW47IC8q IGRvbWFpbiBpbXBvcnRpbmcgdGhpcyBzZ3QgKi8KKyAgICAgICAgc3RydWN0IHNnX3RhYmxlICpz Z3Q7IC8qIHBvaW50ZXIgdG8gc2d0ICovCisJc3RydWN0IGRtYV9idWYgKmRtYV9idWY7IC8qIG5l ZWRlZCB0byBzdG9yZSB0aGlzIGZvciBmcmVlaW5nIGl0IGxhdGVyICovCisJc3RydWN0IGRtYV9i dWZfYXR0YWNobWVudCAqYXR0YWNobWVudDsgLyogbmVlZGVkIHRvIHN0b3JlIHRoaXMgZm9yIGZy ZWVpbmcgdGhpcyBsYXRlciAqLworCXN0cnVjdCBoeXBlcl9kbWFidWZfc2hhcmVkX3BhZ2VzX2lu Zm8gc2hhcmVkX3BhZ2VzX2luZm87CisJaW50IHByaXZhdGVbNF07IC8qIGRldmljZSBzcGVjaWZp YyBpbmZvIChlLmcuIGltYWdlJ3MgbWV0YSBpbmZvPykgKi8KK307CisKKy8qIEltcG9ydGVyIHN0 b3JlIHJlZmVyZW5jZXMgKGJlZm9yZSBtYXBwaW5nKSBvbiBzaGFyZWQgcGFnZXMKKyAqIEltcG9y dGVyIHN0b3JlIHRoZXNlIHJlZmVyZW5jZXMgaW4gdGhlIHRhYmxlIGFuZCBtYXAgaXQgaW4KKyAq IGl0cyBvd24gbWVtb3J5IG1hcCBvbmNlIHVzZXJzcGFjZSBhc2tzIGZvciByZWZlcmVuY2UgZm9y IHRoZSBidWZmZXIgKi8KK3N0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZWRfc2d0X2luZm8gewor CWludCBoeXBlcl9kbWFidWZfaWQ7IC8qIHVuaXF1ZSBpZCB0byByZWZlcmVuY2UgZG1hYnVmIChI WVBFUl9ETUFCVUZfSURfSU1QT1JURVIoc291cmNlIGRvbWFpbiBpZCwgZXhwb3J0ZXIncyBoeXBl cl9kbWFidWZfaWQgKi8KKwlpbnQgZnJzdF9vZnN0OwkvKiBzdGFydCBvZmZzZXQgaW4gc2hhcmVk IHBhZ2UgIzEgKi8KKwlpbnQgbGFzdF9sZW47CS8qIGxlbmd0aCBvZiBkYXRhIGluIHRoZSBsYXN0 IHNoYXJlZCBwYWdlICovCisJaW50IG5lbnRzOwkvKiBudW1iZXIgb2YgcGFnZXMgdG8gYmUgc2hh cmVkICovCisJZ3JhbnRfcmVmX3QgZ3JlZjsgLyogcmVmZXJlbmNlIG51bWJlciBvZiB0b3AgbGV2 ZWwgYWRkcmVzc2luZyBwYWdlIG9mIHNoYXJlZCBwYWdlcyAqLworCXN0cnVjdCBzZ190YWJsZSAq c2d0OyAvKiBzZ3QgcG9pbnRlciBhZnRlciBpbXBvcnRpbmcgYnVmZmVyICovCisJc3RydWN0IGh5 cGVyX2RtYWJ1Zl9zaGFyZWRfcGFnZXNfaW5mbyBzaGFyZWRfcGFnZXNfaW5mbzsKKwlpbnQgcHJp dmF0ZVs0XTsgLyogZGV2aWNlIHNwZWNpZmljIGluZm8gKGUuZy4gaW1hZ2UncyBtZXRhIGluZm8/ KSAqLworfTsKKworI2VuZGlmIC8qIF9fSFlQRVJfRE1BQlVGX1NUUlVDVF9IX18gKi8KZGlmZiAt LWdpdCBhL2RyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi94ZW4vaHlwZXJfZG1hYnVmX3hlbl9jb21t LmMgYi9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYveGVuL2h5cGVyX2RtYWJ1Zl94ZW5fY29tbS5j Cm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLjIyZjJlZjAKLS0tIC9kZXYvbnVs bAorKysgYi9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYveGVuL2h5cGVyX2RtYWJ1Zl94ZW5fY29t bS5jCkBAIC0wLDAgKzEsMzI4IEBACisjaW5jbHVkZSA8bGludXgva2VybmVsLmg+CisjaW5jbHVk ZSA8bGludXgvZXJybm8uaD4KKyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KKyNpbmNsdWRlIDxs aW51eC9zbGFiLmg+CisjaW5jbHVkZSA8bGludXgvd29ya3F1ZXVlLmg+CisjaW5jbHVkZSA8eGVu L2dyYW50X3RhYmxlLmg+CisjaW5jbHVkZSA8eGVuL2V2ZW50cy5oPgorI2luY2x1ZGUgPHhlbi94 ZW5idXMuaD4KKyNpbmNsdWRlIDxhc20veGVuL3BhZ2UuaD4KKyNpbmNsdWRlICJoeXBlcl9kbWFi dWZfeGVuX2NvbW0uaCIKKyNpbmNsdWRlICJoeXBlcl9kbWFidWZfeGVuX2NvbW1fbGlzdC5oIgor I2luY2x1ZGUgIi4uL2h5cGVyX2RtYWJ1Zl9pbXAuaCIKKyNpbmNsdWRlICIuLi9oeXBlcl9kbWFi dWZfbGlzdC5oIgorI2luY2x1ZGUgIi4uL2h5cGVyX2RtYWJ1Zl9tc2cuaCIKKworc3RhdGljIGlu dCBleHBvcnRfcmVxX2lkID0gMDsKK3N0YXRpYyBpbnQgaW1wb3J0X3JlcV9pZCA9IDA7CisKK2lu dDMyX3QgaHlwZXJfZG1hYnVmX2dldF9kb21pZCh2b2lkKQoreworCXN0cnVjdCB4ZW5idXNfdHJh bnNhY3Rpb24geGJ0OworCWludDMyX3QgZG9taWQ7CisKKyAgICAgICAgeGVuYnVzX3RyYW5zYWN0 aW9uX3N0YXJ0KCZ4YnQpOworCisgICAgICAgIGlmICgheGVuYnVzX3NjYW5mKHhidCwgImRvbWlk IiwiIiwgIiVkIiwgJmRvbWlkKSkgeworCQlkb21pZCA9IC0xOworICAgICAgICB9CisgICAgICAg IHhlbmJ1c190cmFuc2FjdGlvbl9lbmQoeGJ0LCAwKTsKKworCXJldHVybiBkb21pZDsKK30KKwor aW50IGh5cGVyX2RtYWJ1Zl9uZXh0X3JlcV9pZF9leHBvcnQodm9pZCkKK3sKKyAgICAgICAgZXhw b3J0X3JlcV9pZCsrOworICAgICAgICByZXR1cm4gZXhwb3J0X3JlcV9pZDsKK30KKworaW50IGh5 cGVyX2RtYWJ1Zl9uZXh0X3JlcV9pZF9pbXBvcnQodm9pZCkKK3sKKyAgICAgICAgaW1wb3J0X3Jl cV9pZCsrOworICAgICAgICByZXR1cm4gaW1wb3J0X3JlcV9pZDsKK30KKworLyogRm9yIG5vdyBj YWNoZSBsYXRhc3QgcmluZ3MgYXMgZ2xvYmFsIHZhcmlhYmxlcyBUT0RPOiBrZWVwIHRoZW0gaW4g bGlzdCovCitzdGF0aWMgaXJxcmV0dXJuX3QgaHlwZXJfZG1hYnVmX2Zyb250X3JpbmdfaXNyKGlu dCBpcnEsIHZvaWQgKmRldl9pZCk7CitzdGF0aWMgaXJxcmV0dXJuX3QgaHlwZXJfZG1hYnVmX2Jh Y2tfcmluZ19pc3IoaW50IGlycSwgdm9pZCAqZGV2X2lkKTsKKworLyogZXhwb3J0ZXIgbmVlZHMg dG8gZ2VuZXJhdGVkIGluZm8gZm9yIHBhZ2Ugc2hhcmluZyAqLworaW50IGh5cGVyX2RtYWJ1Zl9l eHBvcnRlcl9yaW5nYnVmX2luaXQoaW50IHJkb21haW4sIGdyYW50X3JlZl90ICpyZWZpZCwgaW50 ICpwb3J0KQoreworCXN0cnVjdCBoeXBlcl9kbWFidWZfcmluZ19pbmZvX2V4cG9ydCAqcmluZ19p bmZvOworCXN0cnVjdCBoeXBlcl9kbWFidWZfc3JpbmcgKnNyaW5nOworCXN0cnVjdCBldnRjaG5f YWxsb2NfdW5ib3VuZCBhbGxvY191bmJvdW5kOworCXN0cnVjdCBldnRjaG5fY2xvc2UgY2xvc2U7 CisKKwl2b2lkICpzaGFyZWRfcmluZzsKKwlpbnQgcmV0OworCisJcmluZ19pbmZvID0gKHN0cnVj dCBoeXBlcl9kbWFidWZfcmluZ19pbmZvX2V4cG9ydCopCisJCQkJa21hbGxvYyhzaXplb2YoKnJp bmdfaW5mbyksIEdGUF9LRVJORUwpOworCisJLyogZnJvbSBleHBvcnRlciB0byBpbXBvcnRlciAq LworCXNoYXJlZF9yaW5nID0gKHZvaWQgKilfX2dldF9mcmVlX3BhZ2VzKEdGUF9LRVJORUwsIDEp OworCWlmIChzaGFyZWRfcmluZyA9PSAwKSB7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCXNy aW5nID0gKHN0cnVjdCBoeXBlcl9kbWFidWZfc3JpbmcgKikgc2hhcmVkX3Jpbmc7CisKKwlTSEFS RURfUklOR19JTklUKHNyaW5nKTsKKworCUZST05UX1JJTkdfSU5JVCgmKHJpbmdfaW5mby0+cmlu Z19mcm9udCksIHNyaW5nLCBQQUdFX1NJWkUpOworCisJcmluZ19pbmZvLT5ncmVmX3JpbmcgPSBn bnR0YWJfZ3JhbnRfZm9yZWlnbl9hY2Nlc3MocmRvbWFpbiwKKwkJCQkJCQl2aXJ0X3RvX21mbihz aGFyZWRfcmluZyksIDApOworCWlmIChyaW5nX2luZm8tPmdyZWZfcmluZyA8IDApIHsKKwkJcmV0 dXJuIC1FSU5WQUw7IC8qIGZhaWwgdG8gZ2V0IGdyZWYgKi8KKwl9CisKKwlhbGxvY191bmJvdW5k LmRvbSA9IERPTUlEX1NFTEY7CisJYWxsb2NfdW5ib3VuZC5yZW1vdGVfZG9tID0gcmRvbWFpbjsK KwlyZXQgPSBIWVBFUlZJU09SX2V2ZW50X2NoYW5uZWxfb3AoRVZUQ0hOT1BfYWxsb2NfdW5ib3Vu ZCwgJmFsbG9jX3VuYm91bmQpOworCWlmIChyZXQgIT0gMCkgeworCQlwcmludGsoIkNhbm5vdCBh bGxvY2F0ZSBldmVudCBjaGFubmVsXG4iKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJLyog c2V0dGluZyB1cCBpbnRlcnJ1cHQgKi8KKwlyZXQgPSBiaW5kX2V2dGNobl90b19pcnFoYW5kbGVy KGFsbG9jX3VuYm91bmQucG9ydCwKKwkJCQkJaHlwZXJfZG1hYnVmX2Zyb250X3JpbmdfaXNyLCAw LAorCQkJCQlOVUxMLCAodm9pZCopIHJpbmdfaW5mbyk7CisKKwlpZiAocmV0IDwgMCkgeworCQlw cmludGsoIkZhaWxlZCB0byBzZXR1cCBldmVudCBjaGFubmVsXG4iKTsKKwkJY2xvc2UucG9ydCA9 IGFsbG9jX3VuYm91bmQucG9ydDsKKwkJSFlQRVJWSVNPUl9ldmVudF9jaGFubmVsX29wKEVWVENI Tk9QX2Nsb3NlLCAmY2xvc2UpOworCQlnbnR0YWJfZW5kX2ZvcmVpZ25fYWNjZXNzKHJpbmdfaW5m by0+Z3JlZl9yaW5nLCAwLCB2aXJ0X3RvX21mbihzaGFyZWRfcmluZykpOworCQlyZXR1cm4gLUVJ TlZBTDsKKwl9CisKKwlyaW5nX2luZm8tPnJkb21haW4gPSByZG9tYWluOworCXJpbmdfaW5mby0+ aXJxID0gcmV0OworCXJpbmdfaW5mby0+cG9ydCA9IGFsbG9jX3VuYm91bmQucG9ydDsKKworCS8q IHN0b3JlIHJlZmlkIGFuZCBwb3J0IG51bWJlcnMgZm9yIHVzZXJzcGFjZSdzIHVzZSAqLworCSpy ZWZpZCA9IHJpbmdfaW5mby0+Z3JlZl9yaW5nOworCSpwb3J0ID0gcmluZ19pbmZvLT5wb3J0Owor CisJcHJpbnRrKCIlczogYWxsb2NhdGVkIGV2ZW50Y2hhbm5lbCBncmVmICVkICBwb3J0OiAlZCAg aXJxOiAlZFxuIiwgX19mdW5jX18sCisJCXJpbmdfaW5mby0+Z3JlZl9yaW5nLAorCQlyaW5nX2lu Zm8tPnBvcnQsCisJCXJpbmdfaW5mby0+aXJxKTsKKworCS8qIHJlZ2lzdGVyIHJpbmcgaW5mbyAq LworCXJldCA9IGh5cGVyX2RtYWJ1Zl9yZWdpc3Rlcl9leHBvcnRlcl9yaW5nKHJpbmdfaW5mbyk7 CisKKwlyZXR1cm4gcmV0OworfQorCisvKiBpbXBvcnRlciBuZWVkcyB0byBrbm93IGFib3V0IHNo YXJlZCBwYWdlIGFuZCBwb3J0IG51bWJlcnMgZm9yIHJpbmcgYnVmZmVyIGFuZCBldmVudCBjaGFu bmVsICovCitpbnQgaHlwZXJfZG1hYnVmX2ltcG9ydGVyX3JpbmdidWZfaW5pdChpbnQgc2RvbWFp biwgZ3JhbnRfcmVmX3QgZ3JlZiwgaW50IHBvcnQpCit7CisJc3RydWN0IGh5cGVyX2RtYWJ1Zl9y aW5nX2luZm9faW1wb3J0ICpyaW5nX2luZm87CisJc3RydWN0IGh5cGVyX2RtYWJ1Zl9zcmluZyAq c3Jpbmc7CisKKwlzdHJ1Y3QgcGFnZSAqc2hhcmVkX3Jpbmc7CisKKwlzdHJ1Y3QgZ250dGFiX21h cF9ncmFudF9yZWYgKm9wczsKKwlzdHJ1Y3QgZ250dGFiX3VubWFwX2dyYW50X3JlZiAqdW5tYXBf b3BzOworCWludCByZXQ7CisKKwlyaW5nX2luZm8gPSAoc3RydWN0IGh5cGVyX2RtYWJ1Zl9yaW5n X2luZm9faW1wb3J0ICopCisJCQlrbWFsbG9jKHNpemVvZigqcmluZ19pbmZvKSwgR0ZQX0tFUk5F TCk7CisKKwlyaW5nX2luZm8tPnNkb21haW4gPSBzZG9tYWluOworCXJpbmdfaW5mby0+ZXZ0Y2hu ID0gcG9ydDsKKworCW9wcyA9IChzdHJ1Y3QgZ250dGFiX21hcF9ncmFudF9yZWYqKWttYWxsb2Mo c2l6ZW9mKCpvcHMpLCBHRlBfS0VSTkVMKTsKKwl1bm1hcF9vcHMgPSAoc3RydWN0IGdudHRhYl91 bm1hcF9ncmFudF9yZWYqKWttYWxsb2Moc2l6ZW9mKCp1bm1hcF9vcHMpLCBHRlBfS0VSTkVMKTsK KworCWlmIChnbnR0YWJfYWxsb2NfcGFnZXMoMSwgJnNoYXJlZF9yaW5nKSkgeworCQlyZXR1cm4g LUVJTlZBTDsKKwl9CisKKwlnbnR0YWJfc2V0X21hcF9vcCgmb3BzWzBdLCAodW5zaWduZWQgbG9u ZylwZm5fdG9fa2FkZHIocGFnZV90b19wZm4oc2hhcmVkX3JpbmcpKSwKKwkJCUdOVE1BUF9ob3N0 X21hcCwgZ3JlZiwgc2RvbWFpbik7CisKKwlyZXQgPSBnbnR0YWJfbWFwX3JlZnMob3BzLCBOVUxM LCAmc2hhcmVkX3JpbmcsIDEpOworCWlmIChyZXQgPCAwKSB7CisJCXByaW50aygiQ2Fubm90IG1h cCByaW5nXG4iKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJaWYgKG9wc1swXS5zdGF0dXMp IHsKKwkJcHJpbnRrKCJSaW5nIG1hcHBpbmcgZmFpbGVkXG4iKTsKKwkJcmV0dXJuIC1FSU5WQUw7 CisJfQorCisJc3JpbmcgPSAoc3RydWN0IGh5cGVyX2RtYWJ1Zl9zcmluZyopIHBmbl90b19rYWRk cihwYWdlX3RvX3BmbihzaGFyZWRfcmluZykpOworCisJQkFDS19SSU5HX0lOSVQoJnJpbmdfaW5m by0+cmluZ19iYWNrLCBzcmluZywgUEFHRV9TSVpFKTsKKworCXJldCA9IGJpbmRfaW50ZXJkb21h aW5fZXZ0Y2huX3RvX2lycWhhbmRsZXIoc2RvbWFpbiwgcG9ydCwgaHlwZXJfZG1hYnVmX2JhY2tf cmluZ19pc3IsIDAsCisJCQkJCQkgICAgTlVMTCwgKHZvaWQqKXJpbmdfaW5mbyk7CisJaWYgKHJl dCA8IDApIHsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJcmluZ19pbmZvLT5pcnEgPSByZXQ7 CisKKwlwcmludGsoIiVzOiBib3VuZCB0byBldmVudGNoYW5uZWwgcG9ydDogJWQgIGlycTogJWRc biIsIF9fZnVuY19fLAorCQlwb3J0LAorCQlyaW5nX2luZm8tPmlycSk7CisKKwlyZXQgPSBoeXBl cl9kbWFidWZfcmVnaXN0ZXJfaW1wb3J0ZXJfcmluZyhyaW5nX2luZm8pOworCisJcmV0dXJuIHJl dDsKK30KKworaW50IGh5cGVyX2RtYWJ1Zl9zZW5kX3JlcXVlc3QoaW50IGRvbWFpbiwgc3RydWN0 IGh5cGVyX2RtYWJ1Zl9yaW5nX3JxICpyZXEpCit7CisJc3RydWN0IGh5cGVyX2RtYWJ1Zl9mcm9u dF9yaW5nICpyaW5nOworCXN0cnVjdCBoeXBlcl9kbWFidWZfcmluZ19ycSAqbmV3X3JlcTsKKwlz dHJ1Y3QgaHlwZXJfZG1hYnVmX3JpbmdfaW5mb19leHBvcnQgKnJpbmdfaW5mbzsKKwlpbnQgbm90 aWZ5OworCisJLyogZmluZCBhIHJpbmcgaW5mbyBmb3IgdGhlIGNoYW5uZWwgKi8KKwlyaW5nX2lu Zm8gPSBoeXBlcl9kbWFidWZfZmluZF9leHBvcnRlcl9yaW5nKGRvbWFpbik7CisJaWYgKCFyaW5n X2luZm8pIHsKKwkJcHJpbnRrKCJDYW4ndCBmaW5kIHJpbmcgaW5mbyBmb3IgdGhlIGNoYW5uZWxc biIpOworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisKKwlyaW5nID0gJnJpbmdfaW5mby0+cmluZ19m cm9udDsKKworCWlmIChSSU5HX0ZVTEwocmluZykpCisJCXJldHVybiAtRUJVU1k7CisKKwluZXdf cmVxID0gUklOR19HRVRfUkVRVUVTVChyaW5nLCByaW5nLT5yZXFfcHJvZF9wdnQpOworCWlmICgh bmV3X3JlcSkgeworCQlwcmludGsoIk5VTEwgUkVRVUVTVFxuIik7CisJCXJldHVybiAtRUlPOwor CX0KKworCW1lbWNweShuZXdfcmVxLCByZXEsIHNpemVvZigqbmV3X3JlcSkpOworCisJcmluZy0+ cmVxX3Byb2RfcHZ0Kys7CisKKwlSSU5HX1BVU0hfUkVRVUVTVFNfQU5EX0NIRUNLX05PVElGWShy aW5nLCBub3RpZnkpOworCWlmIChub3RpZnkpIHsKKwkJbm90aWZ5X3JlbW90ZV92aWFfaXJxKHJp bmdfaW5mby0+aXJxKTsKKwl9CisKKwlyZXR1cm4gMDsKK30KKworLyogY2FsbGVkIGJ5IGludGVy cnVwdCAoV09SS1FVRVVFKSAqLworaW50IGh5cGVyX2RtYWJ1Zl9zZW5kX3Jlc3BvbnNlKHN0cnVj dCBoeXBlcl9kbWFidWZfcmluZ19ycCogcmVzcG9uc2UsIGludCBkb21haW4pCit7CisJLyogYXMg YSBpbXBvcnRlciBhbmQgYXMgYSBleHBvcnRlciAqLworCXJldHVybiAwOworfQorCisvKiBJU1Ig Zm9yIHJlcXVlc3QgZnJvbSBleHBvcnRlciAoYXMgYW4gaW1wb3J0ZXIpICovCitzdGF0aWMgaXJx cmV0dXJuX3QgaHlwZXJfZG1hYnVmX2JhY2tfcmluZ19pc3IoaW50IGlycSwgdm9pZCAqZGV2X2lk KQoreworCVJJTkdfSURYIHJjLCBycDsKKwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX3JpbmdfcnEgcmVx dWVzdDsKKwlzdHJ1Y3QgaHlwZXJfZG1hYnVmX3JpbmdfcnAgcmVzcG9uc2U7CisJaW50IG5vdGlm eSwgbW9yZV90b19kbzsKKwlpbnQgcmV0OworLy8Jc3RydWN0IGh5cGVyX2RtYWJ1Zl93b3JrICp3 b3JrOworCisJc3RydWN0IGh5cGVyX2RtYWJ1Zl9yaW5nX2luZm9faW1wb3J0ICpyaW5nX2luZm8g PSAoc3RydWN0IGh5cGVyX2RtYWJ1Zl9yaW5nX2luZm9faW1wb3J0ICopZGV2X2lkOworCXN0cnVj dCBoeXBlcl9kbWFidWZfYmFja19yaW5nICpyaW5nOworCisJcmluZyA9ICZyaW5nX2luZm8tPnJp bmdfYmFjazsKKworCWRvIHsKKwkJcmMgPSByaW5nLT5yZXFfY29uczsKKwkJcnAgPSByaW5nLT5z cmluZy0+cmVxX3Byb2Q7CisKKwkJd2hpbGUgKHJjICE9IHJwKSB7CisJCQlpZiAoUklOR19SRVFV RVNUX0NPTlNfT1ZFUkZMT1cocmluZywgcmMpKQorCQkJCWJyZWFrOworCisJCQltZW1jcHkoJnJl cXVlc3QsIFJJTkdfR0VUX1JFUVVFU1QocmluZywgcmMpLCBzaXplb2YocmVxdWVzdCkpOworCQkJ cHJpbnRrKCJHb3QgcmVxdWVzdFxuIik7CisJCQlyaW5nLT5yZXFfY29ucyA9ICsrcmM7CisKKwkJ CS8qIFRPRE86IHByb2JhYmx5IHVzaW5nIGxpbmtlZCBsaXN0IGZvciBtdWx0aXBsZSByZXF1ZXN0 cyB0aGVuIGxldAorCQkJICogYSB0YXNrIGluIGEgd29ya3F1ZXVlIHRvIHByb2Nlc3MgdGhvc2Ug aXMgYmV0dGVyIGlkZWEgYmVjdWFzZQorCQkJICogd2UgZG8gbm90IHdhbnQgdG8gc3RheSBpbiBJ U1IgZm9yIGxvbmcuCisJCQkgKi8KKwkJCXJldCA9IGh5cGVyX2RtYWJ1Zl9tc2dfcGFyc2Uocmlu Z19pbmZvLT5zZG9tYWluLCAmcmVxdWVzdCk7CisKKwkJCWlmIChyZXQgPiAwKSB7CisJCQkJLyog YnVpbGQgcmVzcG9uc2UgKi8KKwkJCQltZW1jcHkoJnJlc3BvbnNlLCAmcmVxdWVzdCwgc2l6ZW9m KHJlc3BvbnNlKSk7CisKKwkJCQkvKiB3ZSBzZW50IGJhY2sgbW9kaWZpZWQgcmVxdWVzdCBhcyBh IHJlc3BvbnNlLi4gd2UgbWlnaHQganVzdCBuZWVkIHRvIGhhdmUgcmVxdWVzdCBvbmx5Li4qLwor CQkJCW1lbWNweShSSU5HX0dFVF9SRVNQT05TRShyaW5nLCByaW5nLT5yc3BfcHJvZF9wdnQpLCAm cmVzcG9uc2UsIHNpemVvZihyZXNwb25zZSkpOworCQkJCXJpbmctPnJzcF9wcm9kX3B2dCsrOwor CisJCQkJUklOR19QVVNIX1JFU1BPTlNFU19BTkRfQ0hFQ0tfTk9USUZZKHJpbmcsIG5vdGlmeSk7 CisKKwkJCQlpZiAobm90aWZ5KSB7CisJCQkJCXByaW50aygiTm90eWZpbmdcbiIpOworCQkJCQlu b3RpZnlfcmVtb3RlX3ZpYV9pcnEocmluZ19pbmZvLT5pcnEpOworCQkJCX0KKwkJCX0KKworCQkJ UklOR19GSU5BTF9DSEVDS19GT1JfUkVRVUVTVFMocmluZywgbW9yZV90b19kbyk7CisJCQlwcmlu dGsoIkZpbmFsIGNoZWNrIGZvciByZXF1ZXN0cyAlZFxuIiwgbW9yZV90b19kbyk7CisJCX0KKwl9 IHdoaWxlIChtb3JlX3RvX2RvKTsKKworCXJldHVybiBJUlFfSEFORExFRDsKK30KKworLyogSVNS IGZvciByZXNwb25zZXMgZnJvbSBpbXBvcnRlciAqLworc3RhdGljIGlycXJldHVybl90IGh5cGVy X2RtYWJ1Zl9mcm9udF9yaW5nX2lzcihpbnQgaXJxLCB2b2lkICpkZXZfaWQpCit7CisJLyogZnJv bnQgcmluZyBvbmx5IGNhcmUgYWJvdXQgcmVzcG9uc2UgZnJvbSBiYWNrICovCisJc3RydWN0IGh5 cGVyX2RtYWJ1Zl9yaW5nX3JwICpyZXNwb25zZTsKKwlSSU5HX0lEWCBpLCBycDsKKwlpbnQgbW9y ZV90b19kbywgcmV0OworCisJc3RydWN0IGh5cGVyX2RtYWJ1Zl9yaW5nX2luZm9fZXhwb3J0ICpy aW5nX2luZm8gPSAoc3RydWN0IGh5cGVyX2RtYWJ1Zl9yaW5nX2luZm9fZXhwb3J0ICopZGV2X2lk OworCXN0cnVjdCBoeXBlcl9kbWFidWZfZnJvbnRfcmluZyAqcmluZzsKKwlyaW5nID0gJnJpbmdf aW5mby0+cmluZ19mcm9udDsKKworCWRvIHsKKwkJbW9yZV90b19kbyA9IDA7CisJCXJwID0gcmlu Zy0+c3JpbmctPnJzcF9wcm9kOworCQlmb3IgKGkgPSByaW5nLT5yc3BfY29uczsgaSAhPSBycDsg aSsrKSB7CisJCQl1bnNpZ25lZCBsb25nIGlkOworCisJCQlyZXNwb25zZSA9IFJJTkdfR0VUX1JF U1BPTlNFKHJpbmcsIGkpOworCQkJaWQgPSByZXNwb25zZS0+cmVzcG9uc2VfaWQ7CisKKwkJCWlm IChyZXNwb25zZS0+c3RhdHVzID09IEhZUEVSX0RNQUJVRl9SRVFfTkVFRFNfRk9MTE9XX1VQKSB7 CisJCQkJLyogcGFyc2luZyByZXNwb25zZSAqLworCQkJCXJldCA9IGh5cGVyX2RtYWJ1Zl9tc2df cGFyc2UocmluZ19pbmZvLT5yZG9tYWluLCAoc3RydWN0IGh5cGVyX2RtYWJ1Zl9yaW5nX3JxKily ZXNwb25zZSk7CisKKwkJCQlpZiAocmV0IDwgMCkgeworCQkJCQlwcmludGsoImdldHRpbmcgZXJy b3Igd2hpbGUgcGFyc2luZyByZXNwb25zZVxuIik7CisJCQkJfQorCQkJfSBlbHNlIGlmIChyZXNw b25zZS0+c3RhdHVzID09IEhZUEVSX0RNQUJVRl9SRVFfRVJST1IpIHsKKwkJCQlwcmludGsoInJl bW90ZSBkb21haW4gJWQgY291bGRuJ3QgcHJvY2VzcyByZXF1ZXN0ICVkXG4iLCByaW5nX2luZm8t PnJkb21haW4sIHJlc3BvbnNlLT5jb21tYW5kKTsKKwkJCX0KKworCQl9CisKKwkJcmluZy0+cnNw X2NvbnMgPSBpOworCisJCWlmIChpICE9IHJpbmctPnJlcV9wcm9kX3B2dCkgeworCQkJUklOR19G SU5BTF9DSEVDS19GT1JfUkVTUE9OU0VTKHJpbmcsIG1vcmVfdG9fZG8pOworCQkJcHJpbnRrKCJt b3JlIHRvIGRvICVkXG4iLCBtb3JlX3RvX2RvKTsKKwkJfSBlbHNlIHsKKwkJCXJpbmctPnNyaW5n LT5yc3BfZXZlbnQgPSBpKzE7CisJCX0KKwl9IHdoaWxlIChtb3JlX3RvX2RvKTsKKworCXJldHVy biBJUlFfSEFORExFRDsKK30KZGlmZiAtLWdpdCBhL2RyaXZlcnMveGVuL2h5cGVyX2RtYWJ1Zi94 ZW4vaHlwZXJfZG1hYnVmX3hlbl9jb21tLmggYi9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYveGVu L2h5cGVyX2RtYWJ1Zl94ZW5fY29tbS5oCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAw MDAuLjI3NTQ5MTcKLS0tIC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL3hlbi9oeXBlcl9kbWFidWYv eGVuL2h5cGVyX2RtYWJ1Zl94ZW5fY29tbS5oCkBAIC0wLDAgKzEsNjIgQEAKKyNpZm5kZWYgX19I WVBFUl9ETUFCVUZfWEVOX0NPTU1fSF9fCisjZGVmaW5lIF9fSFlQRVJfRE1BQlVGX1hFTl9DT01N X0hfXworCisjaW5jbHVkZSAieGVuL2ludGVyZmFjZS9pby9yaW5nLmgiCisKKyNkZWZpbmUgTUFY X05VTUJFUl9PRl9PUEVSQU5EUyA5CisKK3N0cnVjdCBoeXBlcl9kbWFidWZfcmluZ19ycSB7Cisg ICAgICAgIHVuc2lnbmVkIGludCByZXF1ZXN0X2lkOworICAgICAgICB1bnNpZ25lZCBpbnQgc3Rh dHVzOworICAgICAgICB1bnNpZ25lZCBpbnQgY29tbWFuZDsKKyAgICAgICAgdW5zaWduZWQgaW50 IG9wZXJhbmRzW01BWF9OVU1CRVJfT0ZfT1BFUkFORFNdOworfTsKKworc3RydWN0IGh5cGVyX2Rt YWJ1Zl9yaW5nX3JwIHsKKyAgICAgICAgdW5zaWduZWQgaW50IHJlc3BvbnNlX2lkOworICAgICAg ICB1bnNpZ25lZCBpbnQgc3RhdHVzOworICAgICAgICB1bnNpZ25lZCBpbnQgY29tbWFuZDsKKyAg ICAgICAgdW5zaWduZWQgaW50IG9wZXJhbmRzW01BWF9OVU1CRVJfT0ZfT1BFUkFORFNdOworfTsK KworREVGSU5FX1JJTkdfVFlQRVMoaHlwZXJfZG1hYnVmLCBzdHJ1Y3QgaHlwZXJfZG1hYnVmX3Jp bmdfcnEsIHN0cnVjdCBoeXBlcl9kbWFidWZfcmluZ19ycCk7CisKK3N0cnVjdCBoeXBlcl9kbWFi dWZfcmluZ19pbmZvX2V4cG9ydCB7CisgICAgICAgIHN0cnVjdCBoeXBlcl9kbWFidWZfZnJvbnRf cmluZyByaW5nX2Zyb250OworCWludCByZG9tYWluOworICAgICAgICBpbnQgZ3JlZl9yaW5nOwor ICAgICAgICBpbnQgaXJxOworICAgICAgICBpbnQgcG9ydDsKK307CisKK3N0cnVjdCBoeXBlcl9k bWFidWZfcmluZ19pbmZvX2ltcG9ydCB7CisgICAgICAgIGludCBzZG9tYWluOworICAgICAgICBp bnQgaXJxOworICAgICAgICBpbnQgZXZ0Y2huOworICAgICAgICBzdHJ1Y3QgaHlwZXJfZG1hYnVm X2JhY2tfcmluZyByaW5nX2JhY2s7Cit9OworCisvL3N0cnVjdCBoeXBlcl9kbWFidWZfd29yayB7 CisvLwloeXBlcl9kbWFidWZfcmluZ19ycSByZXF1cmVzdDsKKy8vCXN0cnVjdCB3b3JrX3N0cnVj dCBtc2dfcGFyc2U7CisvL307CisKK2ludDMyX3QgaHlwZXJfZG1hYnVmX2dldF9kb21pZCh2b2lk KTsKKworaW50IGh5cGVyX2RtYWJ1Zl9uZXh0X3JlcV9pZF9leHBvcnQodm9pZCk7CisKK2ludCBo eXBlcl9kbWFidWZfbmV4dF9yZXFfaWRfaW1wb3J0KHZvaWQpOworCisvKiBleHBvcnRlciBuZWVk cyB0byBnZW5lcmF0ZWQgaW5mbyBmb3IgcGFnZSBzaGFyaW5nICovCitpbnQgaHlwZXJfZG1hYnVm X2V4cG9ydGVyX3JpbmdidWZfaW5pdChpbnQgcmRvbWFpbiwgZ3JhbnRfcmVmX3QgKmdyZWYsIGlu dCAqcG9ydCk7CisKKy8qIGltcG9ydGVyIG5lZWRzIHRvIGtub3cgYWJvdXQgc2hhcmVkIHBhZ2Ug YW5kIHBvcnQgbnVtYmVycyBmb3IgcmluZyBidWZmZXIgYW5kIGV2ZW50IGNoYW5uZWwgKi8KK2lu dCBoeXBlcl9kbWFidWZfaW1wb3J0ZXJfcmluZ2J1Zl9pbml0KGludCBzZG9tYWluLCBncmFudF9y ZWZfdCBncmVmLCBpbnQgcG9ydCk7CisKKy8qIHNlbmQgcmVxdWVzdCB0byB0aGUgcmVtb3RlIGRv bWFpbiAqLworaW50IGh5cGVyX2RtYWJ1Zl9zZW5kX3JlcXVlc3QoaW50IGRvbWFpbiwgc3RydWN0 IGh5cGVyX2RtYWJ1Zl9yaW5nX3JxICpyZXEpOworCisvKiBjYWxsZWQgYnkgaW50ZXJydXB0IChX T1JLUVVFVUUpICovCitpbnQgaHlwZXJfZG1hYnVmX3NlbmRfcmVzcG9uc2Uoc3RydWN0IGh5cGVy X2RtYWJ1Zl9yaW5nX3JwKiByZXNwb25zZSwgaW50IGRvbWFpbik7CisKKyNlbmRpZiAvLyBfX0hZ UEVSX0RNQUJVRl9YRU5fQ09NTV9IX18KZGlmZiAtLWdpdCBhL2RyaXZlcnMveGVuL2h5cGVyX2Rt YWJ1Zi94ZW4vaHlwZXJfZG1hYnVmX3hlbl9jb21tX2xpc3QuYyBiL2RyaXZlcnMveGVuL2h5cGVy X2RtYWJ1Zi94ZW4vaHlwZXJfZG1hYnVmX3hlbl9jb21tX2xpc3QuYwpuZXcgZmlsZSBtb2RlIDEw MDY0NAppbmRleCAwMDAwMDAwLi4xNWM5ZDI5Ci0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy94 ZW4vaHlwZXJfZG1hYnVmL3hlbi9oeXBlcl9kbWFidWZfeGVuX2NvbW1fbGlzdC5jCkBAIC0wLDAg KzEsMTA2IEBACisjaW5jbHVkZSA8bGludXgva2VybmVsLmg+CisjaW5jbHVkZSA8bGludXgvZXJy bm8uaD4KKyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+ CisjaW5jbHVkZSA8bGludXgvY2Rldi5oPgorI2luY2x1ZGUgPGFzbS91YWNjZXNzLmg+CisjaW5j bHVkZSA8bGludXgvaGFzaHRhYmxlLmg+CisjaW5jbHVkZSA8eGVuL2dyYW50X3RhYmxlLmg+Cisj aW5jbHVkZSAiaHlwZXJfZG1hYnVmX3hlbl9jb21tLmgiCisjaW5jbHVkZSAiaHlwZXJfZG1hYnVm X3hlbl9jb21tX2xpc3QuaCIKKworREVDTEFSRV9IQVNIVEFCTEUoaHlwZXJfZG1hYnVmX2hhc2hf aW1wb3J0ZXJfcmluZywgTUFYX0VOVFJZX0lNUE9SVF9SSU5HKTsKK0RFQ0xBUkVfSEFTSFRBQkxF KGh5cGVyX2RtYWJ1Zl9oYXNoX2V4cG9ydGVyX3JpbmcsIE1BWF9FTlRSWV9FWFBPUlRfUklORyk7 CisKK2ludCBoeXBlcl9kbWFidWZfcmluZ190YWJsZV9pbml0KCkKK3sKKwloYXNoX2luaXQoaHlw ZXJfZG1hYnVmX2hhc2hfaW1wb3J0ZXJfcmluZyk7CisJaGFzaF9pbml0KGh5cGVyX2RtYWJ1Zl9o YXNoX2V4cG9ydGVyX3JpbmcpOworCXJldHVybiAwOworfQorCitpbnQgaHlwZXJfZG1hYnVmX3Jp bmdfdGFibGVfZGVzdHJveSgpCit7CisJLyogVE9ETzogY2xlYW51cCB0YWJsZXMqLworCXJldHVy biAwOworfQorCitpbnQgaHlwZXJfZG1hYnVmX3JlZ2lzdGVyX2V4cG9ydGVyX3Jpbmcoc3RydWN0 IGh5cGVyX2RtYWJ1Zl9yaW5nX2luZm9fZXhwb3J0ICpyaW5nX2luZm8pCit7CisJc3RydWN0IGh5 cGVyX2RtYWJ1Zl9leHBvcnRlcl9yaW5nX2luZm8gKmluZm9fZW50cnk7CisKKwlpbmZvX2VudHJ5 ID0ga21hbGxvYyhzaXplb2YoKmluZm9fZW50cnkpLCBHRlBfS0VSTkVMKTsKKworCWluZm9fZW50 cnktPmluZm8gPSByaW5nX2luZm87CisKKwloYXNoX2FkZChoeXBlcl9kbWFidWZfaGFzaF9leHBv cnRlcl9yaW5nLCAmaW5mb19lbnRyeS0+bm9kZSwKKwkJaW5mb19lbnRyeS0+aW5mby0+cmRvbWFp bik7CisKKwlyZXR1cm4gMDsKK30KKworaW50IGh5cGVyX2RtYWJ1Zl9yZWdpc3Rlcl9pbXBvcnRl cl9yaW5nKHN0cnVjdCBoeXBlcl9kbWFidWZfcmluZ19pbmZvX2ltcG9ydCAqcmluZ19pbmZvKQor eworCXN0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZXJfcmluZ19pbmZvICppbmZvX2VudHJ5Owor CisJaW5mb19lbnRyeSA9IGttYWxsb2Moc2l6ZW9mKCppbmZvX2VudHJ5KSwgR0ZQX0tFUk5FTCk7 CisKKwlpbmZvX2VudHJ5LT5pbmZvID0gcmluZ19pbmZvOworCisJaGFzaF9hZGQoaHlwZXJfZG1h YnVmX2hhc2hfaW1wb3J0ZXJfcmluZywgJmluZm9fZW50cnktPm5vZGUsCisJCWluZm9fZW50cnkt PmluZm8tPnNkb21haW4pOworCisJcmV0dXJuIDA7Cit9CisKK3N0cnVjdCBoeXBlcl9kbWFidWZf cmluZ19pbmZvX2V4cG9ydCAqaHlwZXJfZG1hYnVmX2ZpbmRfZXhwb3J0ZXJfcmluZyhpbnQgZG9t aWQpCit7CisJc3RydWN0IGh5cGVyX2RtYWJ1Zl9leHBvcnRlcl9yaW5nX2luZm8gKmluZm9fZW50 cnk7CisJaW50IGJrdDsKKworCWhhc2hfZm9yX2VhY2goaHlwZXJfZG1hYnVmX2hhc2hfZXhwb3J0 ZXJfcmluZywgYmt0LCBpbmZvX2VudHJ5LCBub2RlKQorCQlpZihpbmZvX2VudHJ5LT5pbmZvLT5y ZG9tYWluID09IGRvbWlkKQorCQkJcmV0dXJuIGluZm9fZW50cnktPmluZm87CisKKwlyZXR1cm4g TlVMTDsKK30KKworc3RydWN0IGh5cGVyX2RtYWJ1Zl9yaW5nX2luZm9faW1wb3J0ICpoeXBlcl9k bWFidWZfZmluZF9pbXBvcnRlcl9yaW5nKGludCBkb21pZCkKK3sKKwlzdHJ1Y3QgaHlwZXJfZG1h YnVmX2ltcG9ydGVyX3JpbmdfaW5mbyAqaW5mb19lbnRyeTsKKwlpbnQgYmt0OworCisJaGFzaF9m b3JfZWFjaChoeXBlcl9kbWFidWZfaGFzaF9pbXBvcnRlcl9yaW5nLCBia3QsIGluZm9fZW50cnks IG5vZGUpCisJCWlmKGluZm9fZW50cnktPmluZm8tPnNkb21haW4gPT0gZG9taWQpCisJCQlyZXR1 cm4gaW5mb19lbnRyeS0+aW5mbzsKKworCXJldHVybiBOVUxMOworfQorCitpbnQgaHlwZXJfZG1h YnVmX3JlbW92ZV9leHBvcnRlcl9yaW5nKGludCBkb21pZCkKK3sKKwlzdHJ1Y3QgaHlwZXJfZG1h YnVmX2V4cG9ydGVyX3JpbmdfaW5mbyAqaW5mb19lbnRyeTsKKwlpbnQgYmt0OworCisJaGFzaF9m b3JfZWFjaChoeXBlcl9kbWFidWZfaGFzaF9leHBvcnRlcl9yaW5nLCBia3QsIGluZm9fZW50cnks IG5vZGUpCisJCWlmKGluZm9fZW50cnktPmluZm8tPnJkb21haW4gPT0gZG9taWQpIHsKKwkJCWhh c2hfZGVsKCZpbmZvX2VudHJ5LT5ub2RlKTsKKwkJCXJldHVybiAwOworCQl9CisKKwlyZXR1cm4g LTE7Cit9CisKK2ludCBoeXBlcl9kbWFidWZfcmVtb3ZlX2ltcG9ydGVyX3JpbmcoaW50IGRvbWlk KQoreworCXN0cnVjdCBoeXBlcl9kbWFidWZfaW1wb3J0ZXJfcmluZ19pbmZvICppbmZvX2VudHJ5 OworCWludCBia3Q7CisKKwloYXNoX2Zvcl9lYWNoKGh5cGVyX2RtYWJ1Zl9oYXNoX2ltcG9ydGVy X3JpbmcsIGJrdCwgaW5mb19lbnRyeSwgbm9kZSkKKwkJaWYoaW5mb19lbnRyeS0+aW5mby0+c2Rv bWFpbiA9PSBkb21pZCkgeworCQkJaGFzaF9kZWwoJmluZm9fZW50cnktPm5vZGUpOworCQkJcmV0 dXJuIDA7CisJCX0KKworCXJldHVybiAtMTsKK30KZGlmZiAtLWdpdCBhL2RyaXZlcnMveGVuL2h5 cGVyX2RtYWJ1Zi94ZW4vaHlwZXJfZG1hYnVmX3hlbl9jb21tX2xpc3QuaCBiL2RyaXZlcnMveGVu L2h5cGVyX2RtYWJ1Zi94ZW4vaHlwZXJfZG1hYnVmX3hlbl9jb21tX2xpc3QuaApuZXcgZmlsZSBt b2RlIDEwMDY0NAppbmRleCAwMDAwMDAwLi41OTI5Zjk5Ci0tLSAvZGV2L251bGwKKysrIGIvZHJp dmVycy94ZW4vaHlwZXJfZG1hYnVmL3hlbi9oeXBlcl9kbWFidWZfeGVuX2NvbW1fbGlzdC5oCkBA IC0wLDAgKzEsMzUgQEAKKyNpZm5kZWYgX19IWVBFUl9ETUFCVUZfWEVOX0NPTU1fTElTVF9IX18K KyNkZWZpbmUgX19IWVBFUl9ETUFCVUZfWEVOX0NPTU1fTElTVF9IX18KKworLyogbnVtYmVyIG9m IGJpdHMgdG8gYmUgdXNlZCBmb3IgZXhwb3J0ZWQgZG1hYnVmcyBoYXNoIHRhYmxlICovCisjZGVm aW5lIE1BWF9FTlRSWV9FWFBPUlRfUklORyA3CisvKiBudW1iZXIgb2YgYml0cyB0byBiZSB1c2Vk IGZvciBpbXBvcnRlZCBkbWFidWZzIGhhc2ggdGFibGUgKi8KKyNkZWZpbmUgTUFYX0VOVFJZX0lN UE9SVF9SSU5HIDcKKworc3RydWN0IGh5cGVyX2RtYWJ1Zl9leHBvcnRlcl9yaW5nX2luZm8gewor ICAgICAgICBzdHJ1Y3QgaHlwZXJfZG1hYnVmX3JpbmdfaW5mb19leHBvcnQgKmluZm87CisgICAg ICAgIHN0cnVjdCBobGlzdF9ub2RlIG5vZGU7Cit9OworCitzdHJ1Y3QgaHlwZXJfZG1hYnVmX2lt cG9ydGVyX3JpbmdfaW5mbyB7CisgICAgICAgIHN0cnVjdCBoeXBlcl9kbWFidWZfcmluZ19pbmZv X2ltcG9ydCAqaW5mbzsKKyAgICAgICAgc3RydWN0IGhsaXN0X25vZGUgbm9kZTsKK307CisKK2lu dCBoeXBlcl9kbWFidWZfcmluZ190YWJsZV9pbml0KHZvaWQpOworCitpbnQgaHlwZXJfZG1hYnVm X3JpbmdfdGFibGVfZGVzdHJveSh2b2lkKTsKKworaW50IGh5cGVyX2RtYWJ1Zl9yZWdpc3Rlcl9l eHBvcnRlcl9yaW5nKHN0cnVjdCBoeXBlcl9kbWFidWZfcmluZ19pbmZvX2V4cG9ydCAqcmluZ19p bmZvKTsKKworaW50IGh5cGVyX2RtYWJ1Zl9yZWdpc3Rlcl9pbXBvcnRlcl9yaW5nKHN0cnVjdCBo eXBlcl9kbWFidWZfcmluZ19pbmZvX2ltcG9ydCAqcmluZ19pbmZvKTsKKworc3RydWN0IGh5cGVy X2RtYWJ1Zl9yaW5nX2luZm9fZXhwb3J0ICpoeXBlcl9kbWFidWZfZmluZF9leHBvcnRlcl9yaW5n KGludCBkb21pZCk7CisKK3N0cnVjdCBoeXBlcl9kbWFidWZfcmluZ19pbmZvX2ltcG9ydCAqaHlw ZXJfZG1hYnVmX2ZpbmRfaW1wb3J0ZXJfcmluZyhpbnQgZG9taWQpOworCitpbnQgaHlwZXJfZG1h YnVmX3JlbW92ZV9leHBvcnRlcl9yaW5nKGludCBkb21pZCk7CisKK2ludCBoeXBlcl9kbWFidWZf cmVtb3ZlX2ltcG9ydGVyX3JpbmcoaW50IGRvbWlkKTsKKworI2VuZGlmIC8vIF9fSFlQRVJfRE1B QlVGX1hFTl9DT01NX0xJU1RfSF9fCi0tIAoyLjcuNAoKX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX18KZHJpLWRldmVsIG1haWxpbmcgbGlzdApkcmktZGV2ZWxA bGlzdHMuZnJlZWRlc2t0b3Aub3JnCmh0dHBzOi8vbGlzdHMuZnJlZWRlc2t0b3Aub3JnL21haWxt YW4vbGlzdGluZm8vZHJpLWRldmVsCg==