From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E844A38CFE8; Fri, 19 Jun 2026 16:06:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781885168; cv=none; b=rIsmaL9xgcu8+yabhe160egfRxMJ/opB3j2HU82M6ikpmBGRGJDtmg/Jpa2gbojQVv73zIOU6PV1Mh9i2u0AWb+jdeEtM/hKGqepKxzx+Vr0M0ttK9AQfZA5dMrdP5CPxpMALu4F9QMRYVvzWEwn/HuBF1owh9ijCnmz2BGXrEU= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781885168; c=relaxed/simple; bh=owUbC3NqokjsRp0DsNk4Yj7gPkr3ROamMdSUq9Ovs1w=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=Aiq3UxEF1o7MardQQzjNaefQe87hkVRR2XvDnwkfv2GevLDOqMz7s96yvsCCwlZIMuwD+kFFfYypZXVL6fgvvsR47NPLFEmH7fi5euGaQUXQU6G3K8t5DERYZ+SfHamifjMMUXx0Jlmi6r2+EUylfxZC7YR+pN7n0hUOHBb8E0k= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CfVf/r6D; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="CfVf/r6D" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A43221F00A3A; Fri, 19 Jun 2026 16:05:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1781885166; bh=DEGh5iV5dIARgxSi3rH+BC9tT08sN9phT2LdvTATjBw=; h=Date:From:To:Cc:Subject:References:In-Reply-To; b=CfVf/r6D5S+1ew/rB8pwmgyKUzM0fI1G/KmEVATb6MSlyV8ygGvmLHJCIqiYMUOxB Jm21Noq8EtdRgMeo98LGNtYV62KQnBIuf+V4h3sm3YT8I9/RT0Pe+FMdKfUjeTgTs+ BVIG3dYFGuWuQZKMp+r1VOmOFh4ex5zFvmQRzbnA0F/lPrEOIkSIHcNNEg1f3iso1J zf8AcHFFLNNfUSqHhYn1pOrtBrVvhPK57ScHrXRAn66vy8i4M3V4zIJbE2iyVL7c6u BMF7BdrAxZOTfNKo1hiKol5zUIdh5voo0gCeHLT0+x0NktI7BVy1o6w0SEXfqJh8Hp +AnZfwDtsUlcA== Date: Fri, 19 Jun 2026 12:05:51 -0400 From: Guo Ren To: Zong Li , David Laight Cc: tjeznach@rivosinc.com, joro@8bytes.org, will@kernel.org, robin.murphy@arm.com, robh@kernel.org, pjw@kernel.org, palmer@dabbelt.com, aou@eecs.berkeley.edu, alex@ghiti.fr, mark.rutland@arm.com, conor+dt@kernel.org, krzk@kernel.org, guoyaxing@bosc.ac.cn, luxu.kernel@bytedance.com, lv.zheng@linux.spacemit.com, andrew.jones@oss.qualcomm.com, linux-kernel@vger.kernel.org, iommu@lists.linux.dev, linux-riscv@lists.infradead.org, linux-perf-users@vger.kernel.org Subject: Re: [PATCH v2 1/2] drivers/perf: riscv-iommu: add risc-v iommu pmu driver Message-ID: References: <20260208063848.3547817-1-zong.li@sifive.com> <20260208063848.3547817-2-zong.li@sifive.com> Precedence: bulk X-Mailing-List: iommu@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20260208063848.3547817-2-zong.li@sifive.com> On Sat, Feb 07, 2026 at 10:38:35PM -0800, Zong Li wrote: > Add a new driver to support the RISC-V IOMMU PMU. This is an auxiliary > device driver created by the parent RISC-V IOMMU driver. > > The RISC-V IOMMU PMU separates the cycle counter from the event counters. > The cycle counter is not associated with iohpmevt0, so a software-defined > cycle event is required for the perf subsystem. > > The number and width of the counters are hardware-implemented and must > be detected at runtime. > > The performance monitor provides counters with filtering support to > collect events for specific device ID/process ID, or GSCID/PSCID. > > PMU-related definitions are moved into the perf driver, where they are > used exclusively. > > Signed-off-by: Zong Li > --- > drivers/iommu/riscv/iommu-bits.h | 61 --- > drivers/perf/Kconfig | 12 + > drivers/perf/Makefile | 1 + > drivers/perf/riscv_iommu_pmu.c | 661 +++++++++++++++++++++++++++++++ > 4 files changed, 674 insertions(+), 61 deletions(-) > create mode 100644 drivers/perf/riscv_iommu_pmu.c > > diff --git a/drivers/iommu/riscv/iommu-bits.h b/drivers/iommu/riscv/iommu-bits.h > index 98daf0e1a306..746cd11f4938 100644 > --- a/drivers/iommu/riscv/iommu-bits.h > +++ b/drivers/iommu/riscv/iommu-bits.h > @@ -189,67 +189,6 @@ enum riscv_iommu_ddtp_modes { > #define RISCV_IOMMU_IPSR_PMIP BIT(RISCV_IOMMU_INTR_PM) > #define RISCV_IOMMU_IPSR_PIP BIT(RISCV_IOMMU_INTR_PQ) > > -/* 5.19 Performance monitoring counter overflow status (32bits) */ > -#define RISCV_IOMMU_REG_IOCOUNTOVF 0x0058 > -#define RISCV_IOMMU_IOCOUNTOVF_CY BIT(0) > -#define RISCV_IOMMU_IOCOUNTOVF_HPM GENMASK_ULL(31, 1) > - > -/* 5.20 Performance monitoring counter inhibits (32bits) */ > -#define RISCV_IOMMU_REG_IOCOUNTINH 0x005C > -#define RISCV_IOMMU_IOCOUNTINH_CY BIT(0) > -#define RISCV_IOMMU_IOCOUNTINH_HPM GENMASK(31, 1) > - > -/* 5.21 Performance monitoring cycles counter (64bits) */ > -#define RISCV_IOMMU_REG_IOHPMCYCLES 0x0060 > -#define RISCV_IOMMU_IOHPMCYCLES_COUNTER GENMASK_ULL(62, 0) > -#define RISCV_IOMMU_IOHPMCYCLES_OF BIT_ULL(63) > - > -/* 5.22 Performance monitoring event counters (31 * 64bits) */ > -#define RISCV_IOMMU_REG_IOHPMCTR_BASE 0x0068 > -#define RISCV_IOMMU_REG_IOHPMCTR(_n) (RISCV_IOMMU_REG_IOHPMCTR_BASE + ((_n) * 0x8)) > - > -/* 5.23 Performance monitoring event selectors (31 * 64bits) */ > -#define RISCV_IOMMU_REG_IOHPMEVT_BASE 0x0160 > -#define RISCV_IOMMU_REG_IOHPMEVT(_n) (RISCV_IOMMU_REG_IOHPMEVT_BASE + ((_n) * 0x8)) > -#define RISCV_IOMMU_IOHPMEVT_EVENTID GENMASK_ULL(14, 0) > -#define RISCV_IOMMU_IOHPMEVT_DMASK BIT_ULL(15) > -#define RISCV_IOMMU_IOHPMEVT_PID_PSCID GENMASK_ULL(35, 16) > -#define RISCV_IOMMU_IOHPMEVT_DID_GSCID GENMASK_ULL(59, 36) > -#define RISCV_IOMMU_IOHPMEVT_PV_PSCV BIT_ULL(60) > -#define RISCV_IOMMU_IOHPMEVT_DV_GSCV BIT_ULL(61) > -#define RISCV_IOMMU_IOHPMEVT_IDT BIT_ULL(62) > -#define RISCV_IOMMU_IOHPMEVT_OF BIT_ULL(63) > - > -/* Number of defined performance-monitoring event selectors */ > -#define RISCV_IOMMU_IOHPMEVT_CNT 31 > - > -/** > - * enum riscv_iommu_hpmevent_id - Performance-monitoring event identifier > - * > - * @RISCV_IOMMU_HPMEVENT_INVALID: Invalid event, do not count > - * @RISCV_IOMMU_HPMEVENT_URQ: Untranslated requests > - * @RISCV_IOMMU_HPMEVENT_TRQ: Translated requests > - * @RISCV_IOMMU_HPMEVENT_ATS_RQ: ATS translation requests > - * @RISCV_IOMMU_HPMEVENT_TLB_MISS: TLB misses > - * @RISCV_IOMMU_HPMEVENT_DD_WALK: Device directory walks > - * @RISCV_IOMMU_HPMEVENT_PD_WALK: Process directory walks > - * @RISCV_IOMMU_HPMEVENT_S_VS_WALKS: First-stage page table walks > - * @RISCV_IOMMU_HPMEVENT_G_WALKS: Second-stage page table walks > - * @RISCV_IOMMU_HPMEVENT_MAX: Value to denote maximum Event IDs > - */ > -enum riscv_iommu_hpmevent_id { > - RISCV_IOMMU_HPMEVENT_INVALID = 0, > - RISCV_IOMMU_HPMEVENT_URQ = 1, > - RISCV_IOMMU_HPMEVENT_TRQ = 2, > - RISCV_IOMMU_HPMEVENT_ATS_RQ = 3, > - RISCV_IOMMU_HPMEVENT_TLB_MISS = 4, > - RISCV_IOMMU_HPMEVENT_DD_WALK = 5, > - RISCV_IOMMU_HPMEVENT_PD_WALK = 6, > - RISCV_IOMMU_HPMEVENT_S_VS_WALKS = 7, > - RISCV_IOMMU_HPMEVENT_G_WALKS = 8, > - RISCV_IOMMU_HPMEVENT_MAX = 9 > -}; > - > /* 5.24 Translation request IOVA (64bits) */ > #define RISCV_IOMMU_REG_TR_REQ_IOVA 0x0258 > #define RISCV_IOMMU_TR_REQ_IOVA_VPN GENMASK_ULL(63, 12) > diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig > index 638321fc9800..6d0ece827501 100644 > --- a/drivers/perf/Kconfig > +++ b/drivers/perf/Kconfig > @@ -105,6 +105,18 @@ config RISCV_PMU_SBI > full perf feature support i.e. counter overflow, privilege mode > filtering, counter configuration. > > +config RISCV_IOMMU_PMU > + depends on RISCV || COMPILE_TEST > + depends on RISCV_IOMMU > + bool "RISC-V IOMMU Hardware Performance Monitor" > + default y > + help > + Say Y if you want to use the RISC-V IOMMU performance monitor > + implementation. The performance monitor is an optional hardware > + feature, and whether it is actually enabled depends on IOMMU > + hardware support. If the underlying hardware does not implement > + the PMU, this option will have no effect. > + > config STARFIVE_STARLINK_PMU > depends on ARCH_STARFIVE || COMPILE_TEST > depends on 64BIT > diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile > index ea52711a87e3..f64f7dc046f1 100644 > --- a/drivers/perf/Makefile > +++ b/drivers/perf/Makefile > @@ -20,6 +20,7 @@ obj-$(CONFIG_QCOM_L3_PMU) += qcom_l3_pmu.o > obj-$(CONFIG_RISCV_PMU) += riscv_pmu.o > obj-$(CONFIG_RISCV_PMU_LEGACY) += riscv_pmu_legacy.o > obj-$(CONFIG_RISCV_PMU_SBI) += riscv_pmu_sbi.o > +obj-$(CONFIG_RISCV_IOMMU_PMU) += riscv_iommu_pmu.o > obj-$(CONFIG_STARFIVE_STARLINK_PMU) += starfive_starlink_pmu.o > obj-$(CONFIG_THUNDERX2_PMU) += thunderx2_pmu.o > obj-$(CONFIG_XGENE_PMU) += xgene_pmu.o > diff --git a/drivers/perf/riscv_iommu_pmu.c b/drivers/perf/riscv_iommu_pmu.c > new file mode 100644 > index 000000000000..72fc4341b165 > --- /dev/null > +++ b/drivers/perf/riscv_iommu_pmu.c > @@ -0,0 +1,661 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Copyright (C) 2026 SiFive > + * > + * Authors > + * Zong Li > + */ > + > +#include > +#include > +#include > + > +#include "../iommu/riscv/iommu.h" > + > +/* 5.19 Performance monitoring counter overflow status (32bits) */ > +#define RISCV_IOMMU_REG_IOCOUNTOVF 0x0058 > +#define RISCV_IOMMU_IOCOUNTOVF_CY BIT(0) > +#define RISCV_IOMMU_IOCOUNTOVF_HPM GENMASK_ULL(31, 1) > + > +/* 5.20 Performance monitoring counter inhibits (32bits) */ > +#define RISCV_IOMMU_REG_IOCOUNTINH 0x005C > +#define RISCV_IOMMU_IOCOUNTINH_CY BIT(0) > +#define RISCV_IOMMU_IOCOUNTINH_HPM GENMASK(31, 0) > + > +/* 5.21 Performance monitoring cycles counter (64bits) */ > +#define RISCV_IOMMU_REG_IOHPMCYCLES 0x0060 > +#define RISCV_IOMMU_IOHPMCYCLES_COUNTER GENMASK_ULL(62, 0) > +#define RISCV_IOMMU_IOHPMCYCLES_OF BIT_ULL(63) > +#define RISCV_IOMMU_REG_IOHPMCTR(_n) (RISCV_IOMMU_REG_IOHPMCYCLES + ((_n) * 0x8)) > + > +/* 5.22 Performance monitoring event counters (31 * 64bits) */ > +#define RISCV_IOMMU_REG_IOHPMCTR_BASE 0x0068 > +#define RISCV_IOMMU_IOHPMCTR_COUNTER GENMASK_ULL(63, 0) > + > +/* 5.23 Performance monitoring event selectors (31 * 64bits) */ > +#define RISCV_IOMMU_REG_IOHPMEVT_BASE 0x0160 > +#define RISCV_IOMMU_REG_IOHPMEVT(_n) (RISCV_IOMMU_REG_IOHPMEVT_BASE + ((_n) * 0x8)) > +#define RISCV_IOMMU_IOHPMEVT_EVENTID GENMASK_ULL(14, 0) > +#define RISCV_IOMMU_IOHPMEVT_DMASK BIT_ULL(15) > +#define RISCV_IOMMU_IOHPMEVT_PID_PSCID GENMASK_ULL(35, 16) > +#define RISCV_IOMMU_IOHPMEVT_DID_GSCID GENMASK_ULL(59, 36) > +#define RISCV_IOMMU_IOHPMEVT_PV_PSCV BIT_ULL(60) > +#define RISCV_IOMMU_IOHPMEVT_DV_GSCV BIT_ULL(61) > +#define RISCV_IOMMU_IOHPMEVT_IDT BIT_ULL(62) > +#define RISCV_IOMMU_IOHPMEVT_OF BIT_ULL(63) > +#define RISCV_IOMMU_IOHPMEVT_EVENT GENMASK_ULL(62, 0) > + > +/* The total number of counters is 31 event counters plus 1 cycle counter */ > +#define RISCV_IOMMU_HPM_COUNTER_NUM 32 > + > +static int cpuhp_state; > + > +/** > + * enum riscv_iommu_hpmevent_id - Performance-monitoring event identifier > + * > + * @RISCV_IOMMU_HPMEVENT_CYCLE: Clock cycle counter > + * @RISCV_IOMMU_HPMEVENT_URQ: Untranslated requests > + * @RISCV_IOMMU_HPMEVENT_TRQ: Translated requests > + * @RISCV_IOMMU_HPMEVENT_ATS_RQ: ATS translation requests > + * @RISCV_IOMMU_HPMEVENT_TLB_MISS: TLB misses > + * @RISCV_IOMMU_HPMEVENT_DD_WALK: Device directory walks > + * @RISCV_IOMMU_HPMEVENT_PD_WALK: Process directory walks > + * @RISCV_IOMMU_HPMEVENT_S_VS_WALKS: First-stage page table walks > + * @RISCV_IOMMU_HPMEVENT_G_WALKS: Second-stage page table walks > + * @RISCV_IOMMU_HPMEVENT_MAX: Value to denote maximum Event IDs > + * > + * The specification does not define an event ID for counting the > + * number of clock cycles, meaning there is no associated 'iohpmevt0'. > + * Event ID 0 is an invalid event and does not overlap with any valid > + * event ID. Let's repurpose ID 0 as the cycle for perf, the cycle > + * event is not actually written into any register, it serves solely > + * as an identifier. > + */ > +enum riscv_iommu_hpmevent_id { > + RISCV_IOMMU_HPMEVENT_CYCLE = 0, > + RISCV_IOMMU_HPMEVENT_URQ = 1, > + RISCV_IOMMU_HPMEVENT_TRQ = 2, > + RISCV_IOMMU_HPMEVENT_ATS_RQ = 3, > + RISCV_IOMMU_HPMEVENT_TLB_MISS = 4, > + RISCV_IOMMU_HPMEVENT_DD_WALK = 5, > + RISCV_IOMMU_HPMEVENT_PD_WALK = 6, > + RISCV_IOMMU_HPMEVENT_S_VS_WALKS = 7, > + RISCV_IOMMU_HPMEVENT_G_WALKS = 8, > + RISCV_IOMMU_HPMEVENT_MAX = 9 > +}; > + > +struct riscv_iommu_pmu { > + struct pmu pmu; > + struct hlist_node node; > + void __iomem *reg; > + unsigned int on_cpu; > + int num_counters; > + u64 cycle_cntr_mask; > + u64 event_cntr_mask; > + struct perf_event *events[RISCV_IOMMU_HPM_COUNTER_NUM]; > + DECLARE_BITMAP(used_counters, RISCV_IOMMU_HPM_COUNTER_NUM); > +}; > + > +#define to_riscv_iommu_pmu(p) (container_of(p, struct riscv_iommu_pmu, pmu)) > + > +#define RISCV_IOMMU_PMU_ATTR_EXTRACTOR(_name, _mask) \ > + static inline u32 get_##_name(struct perf_event *event) \ > + { \ > + return FIELD_GET(_mask, event->attr.config); \ > + } \ > + > +RISCV_IOMMU_PMU_ATTR_EXTRACTOR(event, RISCV_IOMMU_IOHPMEVT_EVENTID); > +RISCV_IOMMU_PMU_ATTR_EXTRACTOR(partial_matching, RISCV_IOMMU_IOHPMEVT_DMASK); > +RISCV_IOMMU_PMU_ATTR_EXTRACTOR(pid_pscid, RISCV_IOMMU_IOHPMEVT_PID_PSCID); > +RISCV_IOMMU_PMU_ATTR_EXTRACTOR(did_gscid, RISCV_IOMMU_IOHPMEVT_DID_GSCID); > +RISCV_IOMMU_PMU_ATTR_EXTRACTOR(filter_pid_pscid, RISCV_IOMMU_IOHPMEVT_PV_PSCV); > +RISCV_IOMMU_PMU_ATTR_EXTRACTOR(filter_did_gscid, RISCV_IOMMU_IOHPMEVT_DV_GSCV); > +RISCV_IOMMU_PMU_ATTR_EXTRACTOR(filter_id_type, RISCV_IOMMU_IOHPMEVT_IDT); > + > +/* Formats */ > +PMU_FORMAT_ATTR(event, "config:0-14"); > +PMU_FORMAT_ATTR(partial_matching, "config:15"); > +PMU_FORMAT_ATTR(pid_pscid, "config:16-35"); > +PMU_FORMAT_ATTR(did_gscid, "config:36-59"); > +PMU_FORMAT_ATTR(filter_pid_pscid, "config:60"); > +PMU_FORMAT_ATTR(filter_did_gscid, "config:61"); > +PMU_FORMAT_ATTR(filter_id_type, "config:62"); > + > +static struct attribute *riscv_iommu_pmu_formats[] = { > + &format_attr_event.attr, > + &format_attr_partial_matching.attr, > + &format_attr_pid_pscid.attr, > + &format_attr_did_gscid.attr, > + &format_attr_filter_pid_pscid.attr, > + &format_attr_filter_did_gscid.attr, > + &format_attr_filter_id_type.attr, > + NULL, > +}; > + > +static const struct attribute_group riscv_iommu_pmu_format_group = { > + .name = "format", > + .attrs = riscv_iommu_pmu_formats, > +}; > + > +/* Events */ > +static ssize_t riscv_iommu_pmu_event_show(struct device *dev, > + struct device_attribute *attr, > + char *page) > +{ > + struct perf_pmu_events_attr *pmu_attr; > + > + pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr); > + > + return sysfs_emit(page, "event=0x%02llx\n", pmu_attr->id); > +} > + > +#define RISCV_IOMMU_PMU_EVENT_ATTR(name, id) \ > + PMU_EVENT_ATTR_ID(name, riscv_iommu_pmu_event_show, id) > + > +static struct attribute *riscv_iommu_pmu_events[] = { > + RISCV_IOMMU_PMU_EVENT_ATTR(cycle, RISCV_IOMMU_HPMEVENT_CYCLE), > + RISCV_IOMMU_PMU_EVENT_ATTR(untranslated_req, RISCV_IOMMU_HPMEVENT_URQ), > + RISCV_IOMMU_PMU_EVENT_ATTR(translated_req, RISCV_IOMMU_HPMEVENT_TRQ), > + RISCV_IOMMU_PMU_EVENT_ATTR(ats_trans_req, RISCV_IOMMU_HPMEVENT_ATS_RQ), > + RISCV_IOMMU_PMU_EVENT_ATTR(tlb_miss, RISCV_IOMMU_HPMEVENT_TLB_MISS), > + RISCV_IOMMU_PMU_EVENT_ATTR(ddt_walks, RISCV_IOMMU_HPMEVENT_DD_WALK), > + RISCV_IOMMU_PMU_EVENT_ATTR(pdt_walks, RISCV_IOMMU_HPMEVENT_PD_WALK), > + RISCV_IOMMU_PMU_EVENT_ATTR(s_vs_pt_walks, RISCV_IOMMU_HPMEVENT_S_VS_WALKS), > + RISCV_IOMMU_PMU_EVENT_ATTR(g_pt_walks, RISCV_IOMMU_HPMEVENT_G_WALKS), > + NULL, > +}; > + > +static const struct attribute_group riscv_iommu_pmu_events_group = { > + .name = "events", > + .attrs = riscv_iommu_pmu_events, > +}; > + > +/* cpumask */ > +static ssize_t riscv_iommu_cpumask_show(struct device *dev, > + struct device_attribute *attr, > + char *buf) > +{ > + struct riscv_iommu_pmu *pmu = to_riscv_iommu_pmu(dev_get_drvdata(dev)); > + > + return cpumap_print_to_pagebuf(true, buf, cpumask_of(pmu->on_cpu)); > +} > + > +static struct device_attribute riscv_iommu_cpumask_attr = > + __ATTR(cpumask, 0444, riscv_iommu_cpumask_show, NULL); > + > +static struct attribute *riscv_iommu_cpumask_attrs[] = { > + &riscv_iommu_cpumask_attr.attr, > + NULL > +}; > + > +static const struct attribute_group riscv_iommu_pmu_cpumask_group = { > + .attrs = riscv_iommu_cpumask_attrs, > +}; > + > +static const struct attribute_group *riscv_iommu_pmu_attr_grps[] = { > + &riscv_iommu_pmu_cpumask_group, > + &riscv_iommu_pmu_format_group, > + &riscv_iommu_pmu_events_group, > + NULL, > +}; > + > +/* PMU Operations */ > +static void riscv_iommu_pmu_set_counter(struct riscv_iommu_pmu *pmu, u32 idx, > + u64 value) > +{ > + u64 counter_mask = idx ? pmu->event_cntr_mask : pmu->cycle_cntr_mask; > + > + writeq(value & counter_mask, pmu->reg + RISCV_IOMMU_REG_IOHPMCTR(idx)); > +} > + > +static u64 riscv_iommu_pmu_get_counter(struct riscv_iommu_pmu *pmu, u32 idx) > +{ > + u64 value, counter_mask = idx ? pmu->event_cntr_mask : pmu->cycle_cntr_mask; > + > + /* Use readq to read counter would be imprecise on 32-bits system */ > + value = readq(pmu->reg + RISCV_IOMMU_REG_IOHPMCTR(idx)) & counter_mask; As stated in the RISC-V IOMMU Specification, Chapter 6: Whether an 8-byte access to an IOMMU register is single-copy atomic is UNSPECIFIED, and such an access may appear, internally to the IOMMU, as if two separate 4-byte accesses — first to the high half and second to the low half — were performed. Therefore, the atomicity of 64-bit MMIO accesses is UNSPECIFIED and not clearly defined in the current ratified RISC-V IOMMU specification. To handle this correctly, the Linux RISC-V IOMMU driver should fall back to 32-bit MMIO accesses when reading 64-bit HPM counter register. Additionally, David Laight has proposed an optimization using the hi-lo-hi read pattern with multiple 32-bit MMIO accesses [1], no retry loop. [1]: https://lore.kernel.org/linux-riscv/20260618143634.7f3dd6c5@pumpkin/ > + > + /* The bit 63 of cycle counter (i.e., idx == 0) is OF bit */ > + return idx ? value : (value & ~RISCV_IOMMU_IOHPMCYCLES_OF); > +} > + > +static bool is_cycle_event(u64 event) > +{ > + return event == RISCV_IOMMU_HPMEVENT_CYCLE; > +} > + > +static void riscv_iommu_pmu_set_event(struct riscv_iommu_pmu *pmu, u32 idx, > + u64 value) > +{ > + /* There is no associtated IOHPMEVT0 for IOHPMCYCLES */ > + if (is_cycle_event(value)) > + return; > + > + /* Event counter start from idx 1 */ > + writeq(FIELD_GET(RISCV_IOMMU_IOHPMEVT_EVENT, value), > + pmu->reg + RISCV_IOMMU_REG_IOHPMEVT(idx - 1)); > +} > + > +static void riscv_iommu_pmu_enable_counter(struct riscv_iommu_pmu *pmu, u32 idx) > +{ > + void __iomem *addr = pmu->reg + RISCV_IOMMU_REG_IOCOUNTINH; > + u32 value = readl(addr); > + > + writel(value & ~BIT(idx), addr); > +} > + > +static void riscv_iommu_pmu_disable_counter(struct riscv_iommu_pmu *pmu, u32 idx) > +{ > + void __iomem *addr = pmu->reg + RISCV_IOMMU_REG_IOCOUNTINH; > + u32 value = readl(addr); > + > + writel(value | BIT(idx), addr); > +} > + > +static void riscv_iommu_pmu_start_all(struct riscv_iommu_pmu *pmu) > +{ > + void __iomem *addr = pmu->reg + RISCV_IOMMU_REG_IOCOUNTINH; > + u32 used_cntr = 0; > + > + /* The performance-monitoring counter inhibits is a 32-bit WARL register */ > + bitmap_to_arr32(&used_cntr, pmu->used_counters, pmu->num_counters); > + > + writel(~used_cntr, addr); > +} > + > +static void riscv_iommu_pmu_stop_all(struct riscv_iommu_pmu *pmu) > +{ > + writel(GENMASK_ULL(pmu->num_counters - 1, 0), > + pmu->reg + RISCV_IOMMU_REG_IOCOUNTINH); > +} > + > +/* PMU APIs */ > +static void riscv_iommu_pmu_set_period(struct perf_event *event) > +{ > + struct riscv_iommu_pmu *pmu = to_riscv_iommu_pmu(event->pmu); > + struct hw_perf_event *hwc = &event->hw; > + u64 counter_mask = hwc->idx ? pmu->event_cntr_mask : pmu->cycle_cntr_mask; > + u64 period; > + > + /* > + * Limit the maximum period to prevent the counter value > + * from overtaking the one we are about to program. > + * In effect we are reducing max_period to account for > + * interrupt latency (and we are being very conservative). > + */ > + period = counter_mask >> 1; > + riscv_iommu_pmu_set_counter(pmu, hwc->idx, period); > + local64_set(&hwc->prev_count, period); > +} > + > +static int riscv_iommu_pmu_event_init(struct perf_event *event) > +{ > + struct riscv_iommu_pmu *pmu = to_riscv_iommu_pmu(event->pmu); > + struct hw_perf_event *hwc = &event->hw; > + struct perf_event *sibling; > + int total_event_counters = pmu->num_counters - 1; > + int counters = 0; > + > + if (event->attr.type != event->pmu->type) > + return -ENOENT; > + > + if (hwc->sample_period) > + return -EOPNOTSUPP; > + > + if (event->cpu < 0) > + return -EOPNOTSUPP; > + > + event->cpu = pmu->on_cpu; > + > + hwc->idx = -1; > + hwc->config = event->attr.config; > + > + if (event->group_leader == event) > + return 0; > + > + if (is_cycle_event(get_event(event->group_leader))) > + if (++counters > total_event_counters) > + return -EINVAL; > + > + for_each_sibling_event(sibling, event->group_leader) { > + if (is_cycle_event(get_event(sibling))) > + continue; > + > + if (sibling->pmu != event->pmu && !is_software_event(sibling)) > + return -EINVAL; > + > + if (++counters > total_event_counters) > + return -EINVAL; > + } > + > + return 0; > +} > + > +static void riscv_iommu_pmu_update(struct perf_event *event) > +{ > + struct hw_perf_event *hwc = &event->hw; > + struct riscv_iommu_pmu *pmu = to_riscv_iommu_pmu(event->pmu); > + u64 delta, prev, now; > + u32 idx = hwc->idx; > + u64 counter_mask = idx ? pmu->event_cntr_mask : pmu->cycle_cntr_mask; > + > + do { > + prev = local64_read(&hwc->prev_count); > + now = riscv_iommu_pmu_get_counter(pmu, idx); > + } while (local64_cmpxchg(&hwc->prev_count, prev, now) != prev); > + > + delta = (now - prev) & counter_mask; > + local64_add(delta, &event->count); > +} > + > +static void riscv_iommu_pmu_start(struct perf_event *event, int flags) > +{ > + struct riscv_iommu_pmu *pmu = to_riscv_iommu_pmu(event->pmu); > + struct hw_perf_event *hwc = &event->hw; > + > + if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED))) > + return; > + > + if (flags & PERF_EF_RELOAD) > + WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE)); > + > + hwc->state = 0; > + riscv_iommu_pmu_set_period(event); > + riscv_iommu_pmu_set_event(pmu, hwc->idx, hwc->config); > + riscv_iommu_pmu_enable_counter(pmu, hwc->idx); > + > + perf_event_update_userpage(event); > +} > + > +static void riscv_iommu_pmu_stop(struct perf_event *event, int flags) > +{ > + struct riscv_iommu_pmu *pmu = to_riscv_iommu_pmu(event->pmu); > + struct hw_perf_event *hwc = &event->hw; > + int idx = hwc->idx; > + > + if (hwc->state & PERF_HES_STOPPED) > + return; > + > + riscv_iommu_pmu_disable_counter(pmu, idx); > + > + if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) > + riscv_iommu_pmu_update(event); > + > + hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE; > +} > + > +static int riscv_iommu_pmu_add(struct perf_event *event, int flags) > +{ > + struct riscv_iommu_pmu *pmu = to_riscv_iommu_pmu(event->pmu); > + struct hw_perf_event *hwc = &event->hw; > + unsigned int num_counters = pmu->num_counters; > + int idx; > + > + /* Reserve index zero for iohpmcycles */ > + if (is_cycle_event(get_event(event))) > + idx = 0; > + else > + idx = find_next_zero_bit(pmu->used_counters, num_counters, 1); > + > + /* All event counters or cycle counter are in use */ > + if (idx == num_counters || pmu->events[idx]) > + return -EAGAIN; > + > + set_bit(idx, pmu->used_counters); > + > + pmu->events[idx] = event; > + hwc->idx = idx; > + hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; > + local64_set(&hwc->prev_count, 0); > + > + if (flags & PERF_EF_START) > + riscv_iommu_pmu_start(event, flags); > + > + /* Propagate changes to the userspace mapping. */ > + perf_event_update_userpage(event); > + > + return 0; > +} > + > +static void riscv_iommu_pmu_read(struct perf_event *event) > +{ > + riscv_iommu_pmu_update(event); > +} > + > +static void riscv_iommu_pmu_del(struct perf_event *event, int flags) > +{ > + struct riscv_iommu_pmu *pmu = to_riscv_iommu_pmu(event->pmu); > + struct hw_perf_event *hwc = &event->hw; > + int idx = hwc->idx; > + > + riscv_iommu_pmu_stop(event, PERF_EF_UPDATE); > + pmu->events[idx] = NULL; > + clear_bit(idx, pmu->used_counters); > + > + perf_event_update_userpage(event); > +} > + > +static int riscv_iommu_pmu_online_cpu(unsigned int cpu, struct hlist_node *node) > +{ > + struct riscv_iommu_pmu *iommu_pmu; > + > + iommu_pmu = hlist_entry_safe(node, struct riscv_iommu_pmu, node); > + > + if (iommu_pmu->on_cpu == -1) > + iommu_pmu->on_cpu = cpu; > + > + return 0; > +} > + > +static int riscv_iommu_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node) > +{ > + struct riscv_iommu_pmu *iommu_pmu; > + unsigned int target_cpu; > + > + iommu_pmu = hlist_entry_safe(node, struct riscv_iommu_pmu, node); > + > + if (cpu != iommu_pmu->on_cpu) > + return 0; > + > + iommu_pmu->on_cpu = -1; > + > + target_cpu = cpumask_any_but(cpu_online_mask, cpu); > + if (target_cpu >= nr_cpu_ids) > + return 0; > + > + perf_pmu_migrate_context(&iommu_pmu->pmu, cpu, target_cpu); > + iommu_pmu->on_cpu = target_cpu; > + > + return 0; > +} > + > +static irqreturn_t riscv_iommu_pmu_handle_irq(struct riscv_iommu_pmu *pmu) > +{ > + u32 ovf = readl(pmu->reg + RISCV_IOMMU_REG_IOCOUNTOVF); > + int idx; > + > + if (!ovf) > + return IRQ_NONE; > + > + riscv_iommu_pmu_stop_all(pmu); > + > + for_each_set_bit(idx, (unsigned long *)&ovf, pmu->num_counters) { > + struct perf_event *event = pmu->events[idx]; > + > + if (WARN_ON_ONCE(!event)) > + continue; > + > + riscv_iommu_pmu_update(event); > + riscv_iommu_pmu_set_period(event); > + } > + > + riscv_iommu_pmu_start_all(pmu); > + > + return IRQ_HANDLED; > +} > + > +static irqreturn_t riscv_iommu_pmu_irq_handler(int irq, void *dev_id) > +{ > + struct riscv_iommu_pmu *pmu = (struct riscv_iommu_pmu *)dev_id; > + irqreturn_t ret; > + > + /* Check whether this interrupt is for PMU */ > + if (!(readl_relaxed(pmu->reg + RISCV_IOMMU_REG_IPSR) & RISCV_IOMMU_IPSR_PMIP)) > + return IRQ_NONE; > + > + /* Process PMU IRQ */ > + ret = riscv_iommu_pmu_handle_irq(pmu); > + > + /* Clear performance monitoring interrupt pending bit */ > + writel_relaxed(RISCV_IOMMU_IPSR_PMIP, pmu->reg + RISCV_IOMMU_REG_IPSR); > + > + return ret; > +} > + > +static unsigned int riscv_iommu_pmu_get_irq_num(struct riscv_iommu_device *iommu) > +{ > + /* Reuse ICVEC.CIV mask for all interrupt vectors mapping */ > + int vec = (iommu->icvec >> (RISCV_IOMMU_IPSR_PMIP * 4)) & RISCV_IOMMU_ICVEC_CIV; > + > + return iommu->irqs[vec]; > +} > + > +static int riscv_iommu_pmu_request_irq(struct riscv_iommu_device *iommu, > + struct riscv_iommu_pmu *pmu) > +{ > + unsigned int irq = riscv_iommu_pmu_get_irq_num(iommu); > + > + /* > + * Set the IRQF_ONESHOT flag because this IRQ can be shared with > + * other threaded IRQs by other queues. > + */ > + return devm_request_irq(iommu->dev, irq, riscv_iommu_pmu_irq_handler, > + IRQF_ONESHOT | IRQF_SHARED, dev_name(iommu->dev), pmu); > +} > + > +static void riscv_iommu_pmu_free_irq(struct riscv_iommu_device *iommu, > + struct riscv_iommu_pmu *pmu) > +{ > + unsigned int irq = riscv_iommu_pmu_get_irq_num(iommu); > + > + free_irq(irq, pmu); > +} > + > +static int riscv_iommu_pmu_probe(struct auxiliary_device *auxdev, > + const struct auxiliary_device_id *id) > +{ > + struct riscv_iommu_device *iommu_dev = dev_get_platdata(&auxdev->dev); > + struct riscv_iommu_pmu *iommu_pmu; > + void __iomem *addr; > + char *name; > + int ret; > + > + iommu_pmu = devm_kzalloc(&auxdev->dev, sizeof(*iommu_pmu), GFP_KERNEL); > + if (!iommu_pmu) > + return -ENOMEM; > + > + iommu_pmu->reg = iommu_dev->reg; > + > + /* Counter number and width are hardware-implemented. Detect them by write 1s */ > + addr = iommu_pmu->reg + RISCV_IOMMU_REG_IOCOUNTINH; > + writel(RISCV_IOMMU_IOCOUNTINH_HPM, addr); > + iommu_pmu->num_counters = hweight32(readl(addr)); > + > + addr = iommu_pmu->reg + RISCV_IOMMU_REG_IOHPMCYCLES; > + writeq(RISCV_IOMMU_IOHPMCYCLES_COUNTER, addr); > + iommu_pmu->cycle_cntr_mask = readq(addr); > + > + /* Assume the width of all event counters are the same */ > + addr = iommu_pmu->reg + RISCV_IOMMU_REG_IOHPMCTR_BASE; > + writeq(RISCV_IOMMU_IOHPMCTR_COUNTER, addr); > + iommu_pmu->event_cntr_mask = readq(addr); > + > + iommu_pmu->pmu = (struct pmu) { > + .module = THIS_MODULE, > + .parent = &auxdev->dev, > + .task_ctx_nr = perf_invalid_context, > + .event_init = riscv_iommu_pmu_event_init, > + .add = riscv_iommu_pmu_add, > + .del = riscv_iommu_pmu_del, > + .start = riscv_iommu_pmu_start, > + .stop = riscv_iommu_pmu_stop, > + .read = riscv_iommu_pmu_read, > + .attr_groups = riscv_iommu_pmu_attr_grps, > + .capabilities = PERF_PMU_CAP_NO_EXCLUDE, > + }; > + > + auxiliary_set_drvdata(auxdev, iommu_pmu); > + > + name = devm_kasprintf(&auxdev->dev, GFP_KERNEL, > + "riscv_iommu_pmu_%s", dev_name(iommu_dev->dev)); > + if (!name) { > + dev_err(&auxdev->dev, "Failed to create name riscv_iommu_pmu_%s\n", > + dev_name(iommu_dev->dev)); > + return -ENOMEM; > + } > + > + /* Bind all events to the same cpu context to avoid race enabling */ > + iommu_pmu->on_cpu = raw_smp_processor_id(); > + > + ret = cpuhp_state_add_instance_nocalls(cpuhp_state, &iommu_pmu->node); > + if (ret) { > + dev_err(&auxdev->dev, "Failed to register hotplug %s: %d\n", name, ret); > + return ret; > + } > + > + ret = riscv_iommu_pmu_request_irq(iommu_dev, iommu_pmu); > + if (ret) { > + dev_err(&auxdev->dev, "Failed to request irq %s: %d\n", name, ret); > + goto err_cpuhp_remove; > + } > + > + ret = perf_pmu_register(&iommu_pmu->pmu, name, -1); > + if (ret) { > + dev_err(&auxdev->dev, "Failed to registe %s: %d\n", name, ret); > + goto err_free_irq; > + } > + > + dev_info(&auxdev->dev, "%s: Registered with %d counters\n", > + name, iommu_pmu->num_counters); > + > + return 0; > + > +err_free_irq: > + riscv_iommu_pmu_free_irq(iommu_dev, iommu_pmu); > +err_cpuhp_remove: > + cpuhp_state_remove_instance_nocalls(cpuhp_state, &iommu_pmu->node); > + return ret; > +} > + > +static const struct auxiliary_device_id riscv_iommu_pmu_id_table[] = { > + { .name = "iommu.pmu" }, > + {} > +}; > +MODULE_DEVICE_TABLE(auxiliary, riscv_iommu_pmu_id_table); > + > +static struct auxiliary_driver iommu_pmu_driver = { > + .probe = riscv_iommu_pmu_probe, > + .id_table = riscv_iommu_pmu_id_table, > +}; > + > +static int __init riscv_iommu_pmu_init(void) > +{ > + int ret; > + > + cpuhp_state = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, > + "perf/riscv/iommu:online", > + riscv_iommu_pmu_online_cpu, > + riscv_iommu_pmu_offline_cpu); > + if (cpuhp_state < 0) > + return cpuhp_state; > + > + ret = auxiliary_driver_register(&iommu_pmu_driver); > + if (ret) > + cpuhp_remove_multi_state(cpuhp_state); > + > + return ret; > +} > +module_init(riscv_iommu_pmu_init); > + > +MODULE_DESCRIPTION("RISC-V IOMMU PMU"); > +MODULE_LICENSE("GPL"); > -- > 2.43.7 > > > _______________________________________________ > linux-riscv mailing list > linux-riscv@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-riscv > From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id AEC9CCD4F26 for ; Fri, 19 Jun 2026 16:06:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:References: Message-ID:Subject:Cc:To:From:Date:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=hXb+PysgiadH+GQLCbdATgdv1/YBgQzR7kTChMFrbys=; b=ANikQMlzW28mgI utoPUjxresrs6bF8r4IgIcndOxAeSP0KmTOVHl0bj2S7ACZfa3f4i2WxosSqfCC3utMIXnhVMm49/ 45wyVfGGIaG+xymavz/kTFIwACJuQ8fTgQoy72JFZGh669xPnyjOVcPpIkWEcAqEVVC8GWKoasDXO OTl3dtjYKVAeE1io3oa2FiNOvBzALbbnDdizgtKn+2KHDaWRrLLUz/vCgGmxDGNw/mefD+yedI2+y zXgaNpr8xjzKJW6vKvS3YULlZ2URmoR26Ie91qXtB8ZYixoXBK++tZeve7peGxN5UflocUjIFr6G1 gxqkP2RKF6jXZFw3oPJA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1wabjM-00000002kic-24XR; Fri, 19 Jun 2026 16:06:08 +0000 Received: from sea.source.kernel.org ([172.234.252.31]) by bombadil.infradead.org with esmtps (Exim 4.99.1 #2 (Red Hat Linux)) id 1wabjL-00000002kiI-1IzU for linux-riscv@lists.infradead.org; Fri, 19 Jun 2026 16:06:07 +0000 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) by sea.source.kernel.org (Postfix) with ESMTP id B15A64322E; Fri, 19 Jun 2026 16:06:06 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id A43221F00A3A; Fri, 19 Jun 2026 16:05:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1781885166; bh=DEGh5iV5dIARgxSi3rH+BC9tT08sN9phT2LdvTATjBw=; h=Date:From:To:Cc:Subject:References:In-Reply-To; b=CfVf/r6D5S+1ew/rB8pwmgyKUzM0fI1G/KmEVATb6MSlyV8ygGvmLHJCIqiYMUOxB Jm21Noq8EtdRgMeo98LGNtYV62KQnBIuf+V4h3sm3YT8I9/RT0Pe+FMdKfUjeTgTs+ BVIG3dYFGuWuQZKMp+r1VOmOFh4ex5zFvmQRzbnA0F/lPrEOIkSIHcNNEg1f3iso1J zf8AcHFFLNNfUSqHhYn1pOrtBrVvhPK57ScHrXRAn66vy8i4M3V4zIJbE2iyVL7c6u BMF7BdrAxZOTfNKo1hiKol5zUIdh5voo0gCeHLT0+x0NktI7BVy1o6w0SEXfqJh8Hp +AnZfwDtsUlcA== Date: Fri, 19 Jun 2026 12:05:51 -0400 From: Guo Ren To: Zong Li , David Laight Cc: tjeznach@rivosinc.com, joro@8bytes.org, will@kernel.org, robin.murphy@arm.com, robh@kernel.org, pjw@kernel.org, palmer@dabbelt.com, aou@eecs.berkeley.edu, alex@ghiti.fr, mark.rutland@arm.com, conor+dt@kernel.org, krzk@kernel.org, guoyaxing@bosc.ac.cn, luxu.kernel@bytedance.com, lv.zheng@linux.spacemit.com, andrew.jones@oss.qualcomm.com, linux-kernel@vger.kernel.org, iommu@lists.linux.dev, linux-riscv@lists.infradead.org, linux-perf-users@vger.kernel.org Subject: Re: [PATCH v2 1/2] drivers/perf: riscv-iommu: add risc-v iommu pmu driver Message-ID: References: <20260208063848.3547817-1-zong.li@sifive.com> <20260208063848.3547817-2-zong.li@sifive.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20260208063848.3547817-2-zong.li@sifive.com> X-BeenThere: linux-riscv@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-riscv" Errors-To: linux-riscv-bounces+linux-riscv=archiver.kernel.org@lists.infradead.org T24gU2F0LCBGZWIgMDcsIDIwMjYgYXQgMTA6Mzg6MzVQTSAtMDgwMCwgWm9uZyBMaSB3cm90ZToK PiBBZGQgYSBuZXcgZHJpdmVyIHRvIHN1cHBvcnQgdGhlIFJJU0MtViBJT01NVSBQTVUuIFRoaXMg aXMgYW4gYXV4aWxpYXJ5Cj4gZGV2aWNlIGRyaXZlciBjcmVhdGVkIGJ5IHRoZSBwYXJlbnQgUklT Qy1WIElPTU1VIGRyaXZlci4KPiAKPiBUaGUgUklTQy1WIElPTU1VIFBNVSBzZXBhcmF0ZXMgdGhl IGN5Y2xlIGNvdW50ZXIgZnJvbSB0aGUgZXZlbnQgY291bnRlcnMuCj4gVGhlIGN5Y2xlIGNvdW50 ZXIgaXMgbm90IGFzc29jaWF0ZWQgd2l0aCBpb2hwbWV2dDAsIHNvIGEgc29mdHdhcmUtZGVmaW5l ZAo+IGN5Y2xlIGV2ZW50IGlzIHJlcXVpcmVkIGZvciB0aGUgcGVyZiBzdWJzeXN0ZW0uCj4gCj4g VGhlIG51bWJlciBhbmQgd2lkdGggb2YgdGhlIGNvdW50ZXJzIGFyZSBoYXJkd2FyZS1pbXBsZW1l bnRlZCBhbmQgbXVzdAo+IGJlIGRldGVjdGVkIGF0IHJ1bnRpbWUuCj4gCj4gVGhlIHBlcmZvcm1h bmNlIG1vbml0b3IgcHJvdmlkZXMgY291bnRlcnMgd2l0aCBmaWx0ZXJpbmcgc3VwcG9ydCB0bwo+ IGNvbGxlY3QgZXZlbnRzIGZvciBzcGVjaWZpYyBkZXZpY2UgSUQvcHJvY2VzcyBJRCwgb3IgR1ND SUQvUFNDSUQuCj4gCj4gUE1VLXJlbGF0ZWQgZGVmaW5pdGlvbnMgYXJlIG1vdmVkIGludG8gdGhl IHBlcmYgZHJpdmVyLCB3aGVyZSB0aGV5IGFyZQo+IHVzZWQgZXhjbHVzaXZlbHkuCj4gCj4gU2ln bmVkLW9mZi1ieTogWm9uZyBMaSA8em9uZy5saUBzaWZpdmUuY29tPgo+IC0tLQo+ICBkcml2ZXJz L2lvbW11L3Jpc2N2L2lvbW11LWJpdHMuaCB8ICA2MSAtLS0KPiAgZHJpdmVycy9wZXJmL0tjb25m aWcgICAgICAgICAgICAgfCAgMTIgKwo+ICBkcml2ZXJzL3BlcmYvTWFrZWZpbGUgICAgICAgICAg ICB8ICAgMSArCj4gIGRyaXZlcnMvcGVyZi9yaXNjdl9pb21tdV9wbXUuYyAgIHwgNjYxICsrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysKPiAgNCBmaWxlcyBjaGFuZ2VkLCA2NzQgaW5zZXJ0 aW9ucygrKSwgNjEgZGVsZXRpb25zKC0pCj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL3Bl cmYvcmlzY3ZfaW9tbXVfcG11LmMKPiAKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9pb21tdS9yaXNj di9pb21tdS1iaXRzLmggYi9kcml2ZXJzL2lvbW11L3Jpc2N2L2lvbW11LWJpdHMuaAo+IGluZGV4 IDk4ZGFmMGUxYTMwNi4uNzQ2Y2QxMWY0OTM4IDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvaW9tbXUv cmlzY3YvaW9tbXUtYml0cy5oCj4gKysrIGIvZHJpdmVycy9pb21tdS9yaXNjdi9pb21tdS1iaXRz LmgKPiBAQCAtMTg5LDY3ICsxODksNiBAQCBlbnVtIHJpc2N2X2lvbW11X2RkdHBfbW9kZXMgewo+ ICAjZGVmaW5lIFJJU0NWX0lPTU1VX0lQU1JfUE1JUAkJQklUKFJJU0NWX0lPTU1VX0lOVFJfUE0p Cj4gICNkZWZpbmUgUklTQ1ZfSU9NTVVfSVBTUl9QSVAJCUJJVChSSVNDVl9JT01NVV9JTlRSX1BR KQo+ICAKPiAtLyogNS4xOSBQZXJmb3JtYW5jZSBtb25pdG9yaW5nIGNvdW50ZXIgb3ZlcmZsb3cg c3RhdHVzICgzMmJpdHMpICovCj4gLSNkZWZpbmUgUklTQ1ZfSU9NTVVfUkVHX0lPQ09VTlRPVkYJ MHgwMDU4Cj4gLSNkZWZpbmUgUklTQ1ZfSU9NTVVfSU9DT1VOVE9WRl9DWQlCSVQoMCkKPiAtI2Rl ZmluZSBSSVNDVl9JT01NVV9JT0NPVU5UT1ZGX0hQTQlHRU5NQVNLX1VMTCgzMSwgMSkKPiAtCj4g LS8qIDUuMjAgUGVyZm9ybWFuY2UgbW9uaXRvcmluZyBjb3VudGVyIGluaGliaXRzICgzMmJpdHMp ICovCj4gLSNkZWZpbmUgUklTQ1ZfSU9NTVVfUkVHX0lPQ09VTlRJTkgJMHgwMDVDCj4gLSNkZWZp bmUgUklTQ1ZfSU9NTVVfSU9DT1VOVElOSF9DWQlCSVQoMCkKPiAtI2RlZmluZSBSSVNDVl9JT01N VV9JT0NPVU5USU5IX0hQTQlHRU5NQVNLKDMxLCAxKQo+IC0KPiAtLyogNS4yMSBQZXJmb3JtYW5j ZSBtb25pdG9yaW5nIGN5Y2xlcyBjb3VudGVyICg2NGJpdHMpICovCj4gLSNkZWZpbmUgUklTQ1Zf SU9NTVVfUkVHX0lPSFBNQ1lDTEVTICAgICAweDAwNjAKPiAtI2RlZmluZSBSSVNDVl9JT01NVV9J T0hQTUNZQ0xFU19DT1VOVEVSCUdFTk1BU0tfVUxMKDYyLCAwKQo+IC0jZGVmaW5lIFJJU0NWX0lP TU1VX0lPSFBNQ1lDTEVTX09GCUJJVF9VTEwoNjMpCj4gLQo+IC0vKiA1LjIyIFBlcmZvcm1hbmNl IG1vbml0b3JpbmcgZXZlbnQgY291bnRlcnMgKDMxICogNjRiaXRzKSAqLwo+IC0jZGVmaW5lIFJJ U0NWX0lPTU1VX1JFR19JT0hQTUNUUl9CQVNFCTB4MDA2OAo+IC0jZGVmaW5lIFJJU0NWX0lPTU1V X1JFR19JT0hQTUNUUihfbikJKFJJU0NWX0lPTU1VX1JFR19JT0hQTUNUUl9CQVNFICsgKChfbikg KiAweDgpKQo+IC0KPiAtLyogNS4yMyBQZXJmb3JtYW5jZSBtb25pdG9yaW5nIGV2ZW50IHNlbGVj dG9ycyAoMzEgKiA2NGJpdHMpICovCj4gLSNkZWZpbmUgUklTQ1ZfSU9NTVVfUkVHX0lPSFBNRVZU X0JBU0UJMHgwMTYwCj4gLSNkZWZpbmUgUklTQ1ZfSU9NTVVfUkVHX0lPSFBNRVZUKF9uKQkoUklT Q1ZfSU9NTVVfUkVHX0lPSFBNRVZUX0JBU0UgKyAoKF9uKSAqIDB4OCkpCj4gLSNkZWZpbmUgUklT Q1ZfSU9NTVVfSU9IUE1FVlRfRVZFTlRJRAlHRU5NQVNLX1VMTCgxNCwgMCkKPiAtI2RlZmluZSBS SVNDVl9JT01NVV9JT0hQTUVWVF9ETUFTSwlCSVRfVUxMKDE1KQo+IC0jZGVmaW5lIFJJU0NWX0lP TU1VX0lPSFBNRVZUX1BJRF9QU0NJRAlHRU5NQVNLX1VMTCgzNSwgMTYpCj4gLSNkZWZpbmUgUklT Q1ZfSU9NTVVfSU9IUE1FVlRfRElEX0dTQ0lECUdFTk1BU0tfVUxMKDU5LCAzNikKPiAtI2RlZmlu ZSBSSVNDVl9JT01NVV9JT0hQTUVWVF9QVl9QU0NWCUJJVF9VTEwoNjApCj4gLSNkZWZpbmUgUklT Q1ZfSU9NTVVfSU9IUE1FVlRfRFZfR1NDVglCSVRfVUxMKDYxKQo+IC0jZGVmaW5lIFJJU0NWX0lP TU1VX0lPSFBNRVZUX0lEVAlCSVRfVUxMKDYyKQo+IC0jZGVmaW5lIFJJU0NWX0lPTU1VX0lPSFBN RVZUX09GCQlCSVRfVUxMKDYzKQo+IC0KPiAtLyogTnVtYmVyIG9mIGRlZmluZWQgcGVyZm9ybWFu Y2UtbW9uaXRvcmluZyBldmVudCBzZWxlY3RvcnMgKi8KPiAtI2RlZmluZSBSSVNDVl9JT01NVV9J T0hQTUVWVF9DTlQJMzEKPiAtCj4gLS8qKgo+IC0gKiBlbnVtIHJpc2N2X2lvbW11X2hwbWV2ZW50 X2lkIC0gUGVyZm9ybWFuY2UtbW9uaXRvcmluZyBldmVudCBpZGVudGlmaWVyCj4gLSAqCj4gLSAq IEBSSVNDVl9JT01NVV9IUE1FVkVOVF9JTlZBTElEOiBJbnZhbGlkIGV2ZW50LCBkbyBub3QgY291 bnQKPiAtICogQFJJU0NWX0lPTU1VX0hQTUVWRU5UX1VSUTogVW50cmFuc2xhdGVkIHJlcXVlc3Rz Cj4gLSAqIEBSSVNDVl9JT01NVV9IUE1FVkVOVF9UUlE6IFRyYW5zbGF0ZWQgcmVxdWVzdHMKPiAt ICogQFJJU0NWX0lPTU1VX0hQTUVWRU5UX0FUU19SUTogQVRTIHRyYW5zbGF0aW9uIHJlcXVlc3Rz Cj4gLSAqIEBSSVNDVl9JT01NVV9IUE1FVkVOVF9UTEJfTUlTUzogVExCIG1pc3Nlcwo+IC0gKiBA UklTQ1ZfSU9NTVVfSFBNRVZFTlRfRERfV0FMSzogRGV2aWNlIGRpcmVjdG9yeSB3YWxrcwo+IC0g KiBAUklTQ1ZfSU9NTVVfSFBNRVZFTlRfUERfV0FMSzogUHJvY2VzcyBkaXJlY3Rvcnkgd2Fsa3MK PiAtICogQFJJU0NWX0lPTU1VX0hQTUVWRU5UX1NfVlNfV0FMS1M6IEZpcnN0LXN0YWdlIHBhZ2Ug dGFibGUgd2Fsa3MKPiAtICogQFJJU0NWX0lPTU1VX0hQTUVWRU5UX0dfV0FMS1M6IFNlY29uZC1z dGFnZSBwYWdlIHRhYmxlIHdhbGtzCj4gLSAqIEBSSVNDVl9JT01NVV9IUE1FVkVOVF9NQVg6IFZh bHVlIHRvIGRlbm90ZSBtYXhpbXVtIEV2ZW50IElEcwo+IC0gKi8KPiAtZW51bSByaXNjdl9pb21t dV9ocG1ldmVudF9pZCB7Cj4gLQlSSVNDVl9JT01NVV9IUE1FVkVOVF9JTlZBTElEICAgID0gMCwK PiAtCVJJU0NWX0lPTU1VX0hQTUVWRU5UX1VSUSAgICAgICAgPSAxLAo+IC0JUklTQ1ZfSU9NTVVf SFBNRVZFTlRfVFJRICAgICAgICA9IDIsCj4gLQlSSVNDVl9JT01NVV9IUE1FVkVOVF9BVFNfUlEg ICAgID0gMywKPiAtCVJJU0NWX0lPTU1VX0hQTUVWRU5UX1RMQl9NSVNTICAgPSA0LAo+IC0JUklT Q1ZfSU9NTVVfSFBNRVZFTlRfRERfV0FMSyAgICA9IDUsCj4gLQlSSVNDVl9JT01NVV9IUE1FVkVO VF9QRF9XQUxLICAgID0gNiwKPiAtCVJJU0NWX0lPTU1VX0hQTUVWRU5UX1NfVlNfV0FMS1MgPSA3 LAo+IC0JUklTQ1ZfSU9NTVVfSFBNRVZFTlRfR19XQUxLUyAgICA9IDgsCj4gLQlSSVNDVl9JT01N VV9IUE1FVkVOVF9NQVggICAgICAgID0gOQo+IC19Owo+IC0KPiAgLyogNS4yNCBUcmFuc2xhdGlv biByZXF1ZXN0IElPVkEgKDY0Yml0cykgKi8KPiAgI2RlZmluZSBSSVNDVl9JT01NVV9SRUdfVFJf UkVRX0lPVkEgICAgIDB4MDI1OAo+ICAjZGVmaW5lIFJJU0NWX0lPTU1VX1RSX1JFUV9JT1ZBX1ZQ TglHRU5NQVNLX1VMTCg2MywgMTIpCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvcGVyZi9LY29uZmln IGIvZHJpdmVycy9wZXJmL0tjb25maWcKPiBpbmRleCA2MzgzMjFmYzk4MDAuLjZkMGVjZTgyNzUw MSAxMDA2NDQKPiAtLS0gYS9kcml2ZXJzL3BlcmYvS2NvbmZpZwo+ICsrKyBiL2RyaXZlcnMvcGVy Zi9LY29uZmlnCj4gQEAgLTEwNSw2ICsxMDUsMTggQEAgY29uZmlnIFJJU0NWX1BNVV9TQkkKPiAg CSAgZnVsbCBwZXJmIGZlYXR1cmUgc3VwcG9ydCBpLmUuIGNvdW50ZXIgb3ZlcmZsb3csIHByaXZp bGVnZSBtb2RlCj4gIAkgIGZpbHRlcmluZywgY291bnRlciBjb25maWd1cmF0aW9uLgo+ICAKPiAr Y29uZmlnIFJJU0NWX0lPTU1VX1BNVQo+ICsJZGVwZW5kcyBvbiBSSVNDViB8fCBDT01QSUxFX1RF U1QKPiArCWRlcGVuZHMgb24gUklTQ1ZfSU9NTVUKPiArCWJvb2wgIlJJU0MtViBJT01NVSBIYXJk d2FyZSBQZXJmb3JtYW5jZSBNb25pdG9yIgo+ICsJZGVmYXVsdCB5Cj4gKwloZWxwCj4gKwkgIFNh eSBZIGlmIHlvdSB3YW50IHRvIHVzZSB0aGUgUklTQy1WIElPTU1VIHBlcmZvcm1hbmNlIG1vbml0 b3IKPiArCSAgaW1wbGVtZW50YXRpb24uIFRoZSBwZXJmb3JtYW5jZSBtb25pdG9yIGlzIGFuIG9w dGlvbmFsIGhhcmR3YXJlCj4gKwkgIGZlYXR1cmUsIGFuZCB3aGV0aGVyIGl0IGlzIGFjdHVhbGx5 IGVuYWJsZWQgZGVwZW5kcyBvbiBJT01NVQo+ICsJICBoYXJkd2FyZSBzdXBwb3J0LiBJZiB0aGUg dW5kZXJseWluZyBoYXJkd2FyZSBkb2VzIG5vdCBpbXBsZW1lbnQKPiArCSAgdGhlIFBNVSwgdGhp cyBvcHRpb24gd2lsbCBoYXZlIG5vIGVmZmVjdC4KPiArCj4gIGNvbmZpZyBTVEFSRklWRV9TVEFS TElOS19QTVUKPiAgCWRlcGVuZHMgb24gQVJDSF9TVEFSRklWRSB8fCBDT01QSUxFX1RFU1QKPiAg CWRlcGVuZHMgb24gNjRCSVQKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9wZXJmL01ha2VmaWxlIGIv ZHJpdmVycy9wZXJmL01ha2VmaWxlCj4gaW5kZXggZWE1MjcxMWE4N2UzLi5mNjRmN2RjMDQ2ZjEg MTAwNjQ0Cj4gLS0tIGEvZHJpdmVycy9wZXJmL01ha2VmaWxlCj4gKysrIGIvZHJpdmVycy9wZXJm L01ha2VmaWxlCj4gQEAgLTIwLDYgKzIwLDcgQEAgb2JqLSQoQ09ORklHX1FDT01fTDNfUE1VKSAr PSBxY29tX2wzX3BtdS5vCj4gIG9iai0kKENPTkZJR19SSVNDVl9QTVUpICs9IHJpc2N2X3BtdS5v Cj4gIG9iai0kKENPTkZJR19SSVNDVl9QTVVfTEVHQUNZKSArPSByaXNjdl9wbXVfbGVnYWN5Lm8K PiAgb2JqLSQoQ09ORklHX1JJU0NWX1BNVV9TQkkpICs9IHJpc2N2X3BtdV9zYmkubwo+ICtvYmot JChDT05GSUdfUklTQ1ZfSU9NTVVfUE1VKSArPSByaXNjdl9pb21tdV9wbXUubwo+ICBvYmotJChD T05GSUdfU1RBUkZJVkVfU1RBUkxJTktfUE1VKSArPSBzdGFyZml2ZV9zdGFybGlua19wbXUubwo+ ICBvYmotJChDT05GSUdfVEhVTkRFUlgyX1BNVSkgKz0gdGh1bmRlcngyX3BtdS5vCj4gIG9iai0k KENPTkZJR19YR0VORV9QTVUpICs9IHhnZW5lX3BtdS5vCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMv cGVyZi9yaXNjdl9pb21tdV9wbXUuYyBiL2RyaXZlcnMvcGVyZi9yaXNjdl9pb21tdV9wbXUuYwo+ IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMDAwMDAwLi43MmZjNDM0MWIxNjUK PiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy9wZXJmL3Jpc2N2X2lvbW11X3BtdS5jCj4g QEAgLTAsMCArMSw2NjEgQEAKPiArLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAt b25seQo+ICsvKgo+ICsgKiBDb3B5cmlnaHQgKEMpIDIwMjYgU2lGaXZlCj4gKyAqCj4gKyAqIEF1 dGhvcnMKPiArICoJWm9uZyBMaSA8em9uZy5saUBzaWZpdmUuY29tPgo+ICsgKi8KPiArCj4gKyNp bmNsdWRlIDxsaW51eC9hdXhpbGlhcnlfYnVzLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9pby02NC1u b25hdG9taWMtaGktbG8uaD4KPiArI2luY2x1ZGUgPGxpbnV4L3BlcmZfZXZlbnQuaD4KPiArCj4g KyNpbmNsdWRlICIuLi9pb21tdS9yaXNjdi9pb21tdS5oIgo+ICsKPiArLyogNS4xOSBQZXJmb3Jt YW5jZSBtb25pdG9yaW5nIGNvdW50ZXIgb3ZlcmZsb3cgc3RhdHVzICgzMmJpdHMpICovCj4gKyNk ZWZpbmUgUklTQ1ZfSU9NTVVfUkVHX0lPQ09VTlRPVkYJMHgwMDU4Cj4gKyNkZWZpbmUgUklTQ1Zf SU9NTVVfSU9DT1VOVE9WRl9DWQlCSVQoMCkKPiArI2RlZmluZSBSSVNDVl9JT01NVV9JT0NPVU5U T1ZGX0hQTQlHRU5NQVNLX1VMTCgzMSwgMSkKPiArCj4gKy8qIDUuMjAgUGVyZm9ybWFuY2UgbW9u aXRvcmluZyBjb3VudGVyIGluaGliaXRzICgzMmJpdHMpICovCj4gKyNkZWZpbmUgUklTQ1ZfSU9N TVVfUkVHX0lPQ09VTlRJTkgJMHgwMDVDCj4gKyNkZWZpbmUgUklTQ1ZfSU9NTVVfSU9DT1VOVElO SF9DWQlCSVQoMCkKPiArI2RlZmluZSBSSVNDVl9JT01NVV9JT0NPVU5USU5IX0hQTQlHRU5NQVNL KDMxLCAwKQo+ICsKPiArLyogNS4yMSBQZXJmb3JtYW5jZSBtb25pdG9yaW5nIGN5Y2xlcyBjb3Vu dGVyICg2NGJpdHMpICovCj4gKyNkZWZpbmUgUklTQ1ZfSU9NTVVfUkVHX0lPSFBNQ1lDTEVTCTB4 MDA2MAo+ICsjZGVmaW5lIFJJU0NWX0lPTU1VX0lPSFBNQ1lDTEVTX0NPVU5URVIJR0VOTUFTS19V TEwoNjIsIDApCj4gKyNkZWZpbmUgUklTQ1ZfSU9NTVVfSU9IUE1DWUNMRVNfT0YJQklUX1VMTCg2 MykKPiArI2RlZmluZSBSSVNDVl9JT01NVV9SRUdfSU9IUE1DVFIoX24pCShSSVNDVl9JT01NVV9S RUdfSU9IUE1DWUNMRVMgKyAoKF9uKSAqIDB4OCkpCj4gKwo+ICsvKiA1LjIyIFBlcmZvcm1hbmNl IG1vbml0b3JpbmcgZXZlbnQgY291bnRlcnMgKDMxICogNjRiaXRzKSAqLwo+ICsjZGVmaW5lIFJJ U0NWX0lPTU1VX1JFR19JT0hQTUNUUl9CQVNFCTB4MDA2OAo+ICsjZGVmaW5lIFJJU0NWX0lPTU1V X0lPSFBNQ1RSX0NPVU5URVIJR0VOTUFTS19VTEwoNjMsIDApCj4gKwo+ICsvKiA1LjIzIFBlcmZv cm1hbmNlIG1vbml0b3JpbmcgZXZlbnQgc2VsZWN0b3JzICgzMSAqIDY0Yml0cykgKi8KPiArI2Rl ZmluZSBSSVNDVl9JT01NVV9SRUdfSU9IUE1FVlRfQkFTRQkweDAxNjAKPiArI2RlZmluZSBSSVND Vl9JT01NVV9SRUdfSU9IUE1FVlQoX24pCShSSVNDVl9JT01NVV9SRUdfSU9IUE1FVlRfQkFTRSAr ICgoX24pICogMHg4KSkKPiArI2RlZmluZSBSSVNDVl9JT01NVV9JT0hQTUVWVF9FVkVOVElECUdF Tk1BU0tfVUxMKDE0LCAwKQo+ICsjZGVmaW5lIFJJU0NWX0lPTU1VX0lPSFBNRVZUX0RNQVNLCUJJ VF9VTEwoMTUpCj4gKyNkZWZpbmUgUklTQ1ZfSU9NTVVfSU9IUE1FVlRfUElEX1BTQ0lECUdFTk1B U0tfVUxMKDM1LCAxNikKPiArI2RlZmluZSBSSVNDVl9JT01NVV9JT0hQTUVWVF9ESURfR1NDSUQJ R0VOTUFTS19VTEwoNTksIDM2KQo+ICsjZGVmaW5lIFJJU0NWX0lPTU1VX0lPSFBNRVZUX1BWX1BT Q1YJQklUX1VMTCg2MCkKPiArI2RlZmluZSBSSVNDVl9JT01NVV9JT0hQTUVWVF9EVl9HU0NWCUJJ VF9VTEwoNjEpCj4gKyNkZWZpbmUgUklTQ1ZfSU9NTVVfSU9IUE1FVlRfSURUCUJJVF9VTEwoNjIp Cj4gKyNkZWZpbmUgUklTQ1ZfSU9NTVVfSU9IUE1FVlRfT0YJCUJJVF9VTEwoNjMpCj4gKyNkZWZp bmUgUklTQ1ZfSU9NTVVfSU9IUE1FVlRfRVZFTlQJR0VOTUFTS19VTEwoNjIsIDApCj4gKwo+ICsv KiBUaGUgdG90YWwgbnVtYmVyIG9mIGNvdW50ZXJzIGlzIDMxIGV2ZW50IGNvdW50ZXJzIHBsdXMg MSBjeWNsZSBjb3VudGVyICovCj4gKyNkZWZpbmUgUklTQ1ZfSU9NTVVfSFBNX0NPVU5URVJfTlVN CTMyCj4gKwo+ICtzdGF0aWMgaW50IGNwdWhwX3N0YXRlOwo+ICsKPiArLyoqCj4gKyAqIGVudW0g cmlzY3ZfaW9tbXVfaHBtZXZlbnRfaWQgLSBQZXJmb3JtYW5jZS1tb25pdG9yaW5nIGV2ZW50IGlk ZW50aWZpZXIKPiArICoKPiArICogQFJJU0NWX0lPTU1VX0hQTUVWRU5UX0NZQ0xFOiBDbG9jayBj eWNsZSBjb3VudGVyCj4gKyAqIEBSSVNDVl9JT01NVV9IUE1FVkVOVF9VUlE6IFVudHJhbnNsYXRl ZCByZXF1ZXN0cwo+ICsgKiBAUklTQ1ZfSU9NTVVfSFBNRVZFTlRfVFJROiBUcmFuc2xhdGVkIHJl cXVlc3RzCj4gKyAqIEBSSVNDVl9JT01NVV9IUE1FVkVOVF9BVFNfUlE6IEFUUyB0cmFuc2xhdGlv biByZXF1ZXN0cwo+ICsgKiBAUklTQ1ZfSU9NTVVfSFBNRVZFTlRfVExCX01JU1M6IFRMQiBtaXNz ZXMKPiArICogQFJJU0NWX0lPTU1VX0hQTUVWRU5UX0REX1dBTEs6IERldmljZSBkaXJlY3Rvcnkg d2Fsa3MKPiArICogQFJJU0NWX0lPTU1VX0hQTUVWRU5UX1BEX1dBTEs6IFByb2Nlc3MgZGlyZWN0 b3J5IHdhbGtzCj4gKyAqIEBSSVNDVl9JT01NVV9IUE1FVkVOVF9TX1ZTX1dBTEtTOiBGaXJzdC1z dGFnZSBwYWdlIHRhYmxlIHdhbGtzCj4gKyAqIEBSSVNDVl9JT01NVV9IUE1FVkVOVF9HX1dBTEtT OiBTZWNvbmQtc3RhZ2UgcGFnZSB0YWJsZSB3YWxrcwo+ICsgKiBAUklTQ1ZfSU9NTVVfSFBNRVZF TlRfTUFYOiBWYWx1ZSB0byBkZW5vdGUgbWF4aW11bSBFdmVudCBJRHMKPiArICoKPiArICogVGhl IHNwZWNpZmljYXRpb24gZG9lcyBub3QgZGVmaW5lIGFuIGV2ZW50IElEIGZvciBjb3VudGluZyB0 aGUKPiArICogbnVtYmVyIG9mIGNsb2NrIGN5Y2xlcywgbWVhbmluZyB0aGVyZSBpcyBubyBhc3Nv Y2lhdGVkICdpb2hwbWV2dDAnLgo+ICsgKiBFdmVudCBJRCAwIGlzIGFuIGludmFsaWQgZXZlbnQg YW5kIGRvZXMgbm90IG92ZXJsYXAgd2l0aCBhbnkgdmFsaWQKPiArICogZXZlbnQgSUQuIExldCdz IHJlcHVycG9zZSBJRCAwIGFzIHRoZSBjeWNsZSBmb3IgcGVyZiwgdGhlIGN5Y2xlCj4gKyAqIGV2 ZW50IGlzIG5vdCBhY3R1YWxseSB3cml0dGVuIGludG8gYW55IHJlZ2lzdGVyLCBpdCBzZXJ2ZXMg c29sZWx5Cj4gKyAqIGFzIGFuIGlkZW50aWZpZXIuCj4gKyAqLwo+ICtlbnVtIHJpc2N2X2lvbW11 X2hwbWV2ZW50X2lkIHsKPiArCVJJU0NWX0lPTU1VX0hQTUVWRU5UX0NZQ0xFCT0gMCwKPiArCVJJ U0NWX0lPTU1VX0hQTUVWRU5UX1VSUSAgICAgICAgPSAxLAo+ICsJUklTQ1ZfSU9NTVVfSFBNRVZF TlRfVFJRICAgICAgICA9IDIsCj4gKwlSSVNDVl9JT01NVV9IUE1FVkVOVF9BVFNfUlEgICAgID0g MywKPiArCVJJU0NWX0lPTU1VX0hQTUVWRU5UX1RMQl9NSVNTICAgPSA0LAo+ICsJUklTQ1ZfSU9N TVVfSFBNRVZFTlRfRERfV0FMSyAgICA9IDUsCj4gKwlSSVNDVl9JT01NVV9IUE1FVkVOVF9QRF9X QUxLICAgID0gNiwKPiArCVJJU0NWX0lPTU1VX0hQTUVWRU5UX1NfVlNfV0FMS1MgPSA3LAo+ICsJ UklTQ1ZfSU9NTVVfSFBNRVZFTlRfR19XQUxLUyAgICA9IDgsCj4gKwlSSVNDVl9JT01NVV9IUE1F VkVOVF9NQVggICAgICAgID0gOQo+ICt9Owo+ICsKPiArc3RydWN0IHJpc2N2X2lvbW11X3BtdSB7 Cj4gKwlzdHJ1Y3QgcG11IHBtdTsKPiArCXN0cnVjdCBobGlzdF9ub2RlIG5vZGU7Cj4gKwl2b2lk IF9faW9tZW0gKnJlZzsKPiArCXVuc2lnbmVkIGludCBvbl9jcHU7Cj4gKwlpbnQgbnVtX2NvdW50 ZXJzOwo+ICsJdTY0IGN5Y2xlX2NudHJfbWFzazsKPiArCXU2NCBldmVudF9jbnRyX21hc2s7Cj4g KwlzdHJ1Y3QgcGVyZl9ldmVudCAqZXZlbnRzW1JJU0NWX0lPTU1VX0hQTV9DT1VOVEVSX05VTV07 Cj4gKwlERUNMQVJFX0JJVE1BUCh1c2VkX2NvdW50ZXJzLCBSSVNDVl9JT01NVV9IUE1fQ09VTlRF Ul9OVU0pOwo+ICt9Owo+ICsKPiArI2RlZmluZSB0b19yaXNjdl9pb21tdV9wbXUocCkgKGNvbnRh aW5lcl9vZihwLCBzdHJ1Y3QgcmlzY3ZfaW9tbXVfcG11LCBwbXUpKQo+ICsKPiArI2RlZmluZSBS SVNDVl9JT01NVV9QTVVfQVRUUl9FWFRSQUNUT1IoX25hbWUsIF9tYXNrKQkJCVwKPiArCXN0YXRp YyBpbmxpbmUgdTMyIGdldF8jI19uYW1lKHN0cnVjdCBwZXJmX2V2ZW50ICpldmVudCkJCVwKPiAr CXsJCQkJCQkJCVwKPiArCQlyZXR1cm4gRklFTERfR0VUKF9tYXNrLCBldmVudC0+YXR0ci5jb25m aWcpOwkJXAo+ICsJfQkJCQkJCQkJXAo+ICsKPiArUklTQ1ZfSU9NTVVfUE1VX0FUVFJfRVhUUkFD VE9SKGV2ZW50LCBSSVNDVl9JT01NVV9JT0hQTUVWVF9FVkVOVElEKTsKPiArUklTQ1ZfSU9NTVVf UE1VX0FUVFJfRVhUUkFDVE9SKHBhcnRpYWxfbWF0Y2hpbmcsIFJJU0NWX0lPTU1VX0lPSFBNRVZU X0RNQVNLKTsKPiArUklTQ1ZfSU9NTVVfUE1VX0FUVFJfRVhUUkFDVE9SKHBpZF9wc2NpZCwgUklT Q1ZfSU9NTVVfSU9IUE1FVlRfUElEX1BTQ0lEKTsKPiArUklTQ1ZfSU9NTVVfUE1VX0FUVFJfRVhU UkFDVE9SKGRpZF9nc2NpZCwgUklTQ1ZfSU9NTVVfSU9IUE1FVlRfRElEX0dTQ0lEKTsKPiArUklT Q1ZfSU9NTVVfUE1VX0FUVFJfRVhUUkFDVE9SKGZpbHRlcl9waWRfcHNjaWQsIFJJU0NWX0lPTU1V X0lPSFBNRVZUX1BWX1BTQ1YpOwo+ICtSSVNDVl9JT01NVV9QTVVfQVRUUl9FWFRSQUNUT1IoZmls dGVyX2RpZF9nc2NpZCwgUklTQ1ZfSU9NTVVfSU9IUE1FVlRfRFZfR1NDVik7Cj4gK1JJU0NWX0lP TU1VX1BNVV9BVFRSX0VYVFJBQ1RPUihmaWx0ZXJfaWRfdHlwZSwgUklTQ1ZfSU9NTVVfSU9IUE1F VlRfSURUKTsKPiArCj4gKy8qIEZvcm1hdHMgKi8KPiArUE1VX0ZPUk1BVF9BVFRSKGV2ZW50LCAg ICAgICAgICAgICJjb25maWc6MC0xNCIpOwo+ICtQTVVfRk9STUFUX0FUVFIocGFydGlhbF9tYXRj aGluZywgImNvbmZpZzoxNSIpOwo+ICtQTVVfRk9STUFUX0FUVFIocGlkX3BzY2lkLCAgICAgICAg ImNvbmZpZzoxNi0zNSIpOwo+ICtQTVVfRk9STUFUX0FUVFIoZGlkX2dzY2lkLCAgICAgICAgImNv bmZpZzozNi01OSIpOwo+ICtQTVVfRk9STUFUX0FUVFIoZmlsdGVyX3BpZF9wc2NpZCwgImNvbmZp Zzo2MCIpOwo+ICtQTVVfRk9STUFUX0FUVFIoZmlsdGVyX2RpZF9nc2NpZCwgImNvbmZpZzo2MSIp Owo+ICtQTVVfRk9STUFUX0FUVFIoZmlsdGVyX2lkX3R5cGUsICAgImNvbmZpZzo2MiIpOwo+ICsK PiArc3RhdGljIHN0cnVjdCBhdHRyaWJ1dGUgKnJpc2N2X2lvbW11X3BtdV9mb3JtYXRzW10gPSB7 Cj4gKwkmZm9ybWF0X2F0dHJfZXZlbnQuYXR0ciwKPiArCSZmb3JtYXRfYXR0cl9wYXJ0aWFsX21h dGNoaW5nLmF0dHIsCj4gKwkmZm9ybWF0X2F0dHJfcGlkX3BzY2lkLmF0dHIsCj4gKwkmZm9ybWF0 X2F0dHJfZGlkX2dzY2lkLmF0dHIsCj4gKwkmZm9ybWF0X2F0dHJfZmlsdGVyX3BpZF9wc2NpZC5h dHRyLAo+ICsJJmZvcm1hdF9hdHRyX2ZpbHRlcl9kaWRfZ3NjaWQuYXR0ciwKPiArCSZmb3JtYXRf YXR0cl9maWx0ZXJfaWRfdHlwZS5hdHRyLAo+ICsJTlVMTCwKPiArfTsKPiArCj4gK3N0YXRpYyBj b25zdCBzdHJ1Y3QgYXR0cmlidXRlX2dyb3VwIHJpc2N2X2lvbW11X3BtdV9mb3JtYXRfZ3JvdXAg PSB7Cj4gKwkubmFtZSA9ICJmb3JtYXQiLAo+ICsJLmF0dHJzID0gcmlzY3ZfaW9tbXVfcG11X2Zv cm1hdHMsCj4gK307Cj4gKwo+ICsvKiBFdmVudHMgKi8KPiArc3RhdGljIHNzaXplX3QgcmlzY3Zf aW9tbXVfcG11X2V2ZW50X3Nob3coc3RydWN0IGRldmljZSAqZGV2LAo+ICsJCQkJCSAgc3RydWN0 IGRldmljZV9hdHRyaWJ1dGUgKmF0dHIsCj4gKwkJCQkJICBjaGFyICpwYWdlKQo+ICt7Cj4gKwlz dHJ1Y3QgcGVyZl9wbXVfZXZlbnRzX2F0dHIgKnBtdV9hdHRyOwo+ICsKPiArCXBtdV9hdHRyID0g Y29udGFpbmVyX29mKGF0dHIsIHN0cnVjdCBwZXJmX3BtdV9ldmVudHNfYXR0ciwgYXR0cik7Cj4g Kwo+ICsJcmV0dXJuIHN5c2ZzX2VtaXQocGFnZSwgImV2ZW50PTB4JTAybGx4XG4iLCBwbXVfYXR0 ci0+aWQpOwo+ICt9Cj4gKwo+ICsjZGVmaW5lIFJJU0NWX0lPTU1VX1BNVV9FVkVOVF9BVFRSKG5h bWUsIGlkKQkJCVwKPiArCVBNVV9FVkVOVF9BVFRSX0lEKG5hbWUsIHJpc2N2X2lvbW11X3BtdV9l dmVudF9zaG93LCBpZCkKPiArCj4gK3N0YXRpYyBzdHJ1Y3QgYXR0cmlidXRlICpyaXNjdl9pb21t dV9wbXVfZXZlbnRzW10gPSB7Cj4gKwlSSVNDVl9JT01NVV9QTVVfRVZFTlRfQVRUUihjeWNsZSwg UklTQ1ZfSU9NTVVfSFBNRVZFTlRfQ1lDTEUpLAo+ICsJUklTQ1ZfSU9NTVVfUE1VX0VWRU5UX0FU VFIodW50cmFuc2xhdGVkX3JlcSwgUklTQ1ZfSU9NTVVfSFBNRVZFTlRfVVJRKSwKPiArCVJJU0NW X0lPTU1VX1BNVV9FVkVOVF9BVFRSKHRyYW5zbGF0ZWRfcmVxLCBSSVNDVl9JT01NVV9IUE1FVkVO VF9UUlEpLAo+ICsJUklTQ1ZfSU9NTVVfUE1VX0VWRU5UX0FUVFIoYXRzX3RyYW5zX3JlcSwgUklT Q1ZfSU9NTVVfSFBNRVZFTlRfQVRTX1JRKSwKPiArCVJJU0NWX0lPTU1VX1BNVV9FVkVOVF9BVFRS KHRsYl9taXNzLCBSSVNDVl9JT01NVV9IUE1FVkVOVF9UTEJfTUlTUyksCj4gKwlSSVNDVl9JT01N VV9QTVVfRVZFTlRfQVRUUihkZHRfd2Fsa3MsIFJJU0NWX0lPTU1VX0hQTUVWRU5UX0REX1dBTEsp LAo+ICsJUklTQ1ZfSU9NTVVfUE1VX0VWRU5UX0FUVFIocGR0X3dhbGtzLCBSSVNDVl9JT01NVV9I UE1FVkVOVF9QRF9XQUxLKSwKPiArCVJJU0NWX0lPTU1VX1BNVV9FVkVOVF9BVFRSKHNfdnNfcHRf d2Fsa3MsIFJJU0NWX0lPTU1VX0hQTUVWRU5UX1NfVlNfV0FMS1MpLAo+ICsJUklTQ1ZfSU9NTVVf UE1VX0VWRU5UX0FUVFIoZ19wdF93YWxrcywgUklTQ1ZfSU9NTVVfSFBNRVZFTlRfR19XQUxLUyks Cj4gKwlOVUxMLAo+ICt9Owo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBhdHRyaWJ1dGVfZ3Jv dXAgcmlzY3ZfaW9tbXVfcG11X2V2ZW50c19ncm91cCA9IHsKPiArCS5uYW1lID0gImV2ZW50cyIs Cj4gKwkuYXR0cnMgPSByaXNjdl9pb21tdV9wbXVfZXZlbnRzLAo+ICt9Owo+ICsKPiArLyogY3B1 bWFzayAqLwo+ICtzdGF0aWMgc3NpemVfdCByaXNjdl9pb21tdV9jcHVtYXNrX3Nob3coc3RydWN0 IGRldmljZSAqZGV2LAo+ICsJCQkJCXN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICphdHRyLAo+ICsJ CQkJCWNoYXIgKmJ1ZikKPiArewo+ICsJc3RydWN0IHJpc2N2X2lvbW11X3BtdSAqcG11ID0gdG9f cmlzY3ZfaW9tbXVfcG11KGRldl9nZXRfZHJ2ZGF0YShkZXYpKTsKPiArCj4gKwlyZXR1cm4gY3B1 bWFwX3ByaW50X3RvX3BhZ2VidWYodHJ1ZSwgYnVmLCBjcHVtYXNrX29mKHBtdS0+b25fY3B1KSk7 Cj4gK30KPiArCj4gK3N0YXRpYyBzdHJ1Y3QgZGV2aWNlX2F0dHJpYnV0ZSByaXNjdl9pb21tdV9j cHVtYXNrX2F0dHIgPQo+ICsJX19BVFRSKGNwdW1hc2ssIDA0NDQsIHJpc2N2X2lvbW11X2NwdW1h c2tfc2hvdywgTlVMTCk7Cj4gKwo+ICtzdGF0aWMgc3RydWN0IGF0dHJpYnV0ZSAqcmlzY3ZfaW9t bXVfY3B1bWFza19hdHRyc1tdID0gewo+ICsJJnJpc2N2X2lvbW11X2NwdW1hc2tfYXR0ci5hdHRy LAo+ICsJTlVMTAo+ICt9Owo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBhdHRyaWJ1dGVfZ3Jv dXAgcmlzY3ZfaW9tbXVfcG11X2NwdW1hc2tfZ3JvdXAgPSB7Cj4gKwkuYXR0cnMgPSByaXNjdl9p b21tdV9jcHVtYXNrX2F0dHJzLAo+ICt9Owo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBhdHRy aWJ1dGVfZ3JvdXAgKnJpc2N2X2lvbW11X3BtdV9hdHRyX2dycHNbXSA9IHsKPiArCSZyaXNjdl9p b21tdV9wbXVfY3B1bWFza19ncm91cCwKPiArCSZyaXNjdl9pb21tdV9wbXVfZm9ybWF0X2dyb3Vw LAo+ICsJJnJpc2N2X2lvbW11X3BtdV9ldmVudHNfZ3JvdXAsCj4gKwlOVUxMLAo+ICt9Owo+ICsK PiArLyogUE1VIE9wZXJhdGlvbnMgKi8KPiArc3RhdGljIHZvaWQgcmlzY3ZfaW9tbXVfcG11X3Nl dF9jb3VudGVyKHN0cnVjdCByaXNjdl9pb21tdV9wbXUgKnBtdSwgdTMyIGlkeCwKPiArCQkJCQl1 NjQgdmFsdWUpCj4gK3sKPiArCXU2NCBjb3VudGVyX21hc2sgPSBpZHggPyBwbXUtPmV2ZW50X2Nu dHJfbWFzayA6IHBtdS0+Y3ljbGVfY250cl9tYXNrOwo+ICsKPiArCXdyaXRlcSh2YWx1ZSAmIGNv dW50ZXJfbWFzaywgcG11LT5yZWcgKyBSSVNDVl9JT01NVV9SRUdfSU9IUE1DVFIoaWR4KSk7Cj4g K30KPiArCj4gK3N0YXRpYyB1NjQgcmlzY3ZfaW9tbXVfcG11X2dldF9jb3VudGVyKHN0cnVjdCBy aXNjdl9pb21tdV9wbXUgKnBtdSwgdTMyIGlkeCkKPiArewo+ICsJdTY0IHZhbHVlLCBjb3VudGVy X21hc2sgPSBpZHggPyBwbXUtPmV2ZW50X2NudHJfbWFzayA6IHBtdS0+Y3ljbGVfY250cl9tYXNr Owo+ICsKPiArCS8qIFVzZSByZWFkcSB0byByZWFkIGNvdW50ZXIgd291bGQgYmUgaW1wcmVjaXNl IG9uIDMyLWJpdHMgc3lzdGVtICovCj4gKwl2YWx1ZSA9IHJlYWRxKHBtdS0+cmVnICsgUklTQ1Zf SU9NTVVfUkVHX0lPSFBNQ1RSKGlkeCkpICYgY291bnRlcl9tYXNrOwpBcyBzdGF0ZWQgaW4gdGhl IFJJU0MtViBJT01NVSBTcGVjaWZpY2F0aW9uLCBDaGFwdGVyIDY6CiAgV2hldGhlciBhbiA4LWJ5 dGUgYWNjZXNzIHRvIGFuIElPTU1VIHJlZ2lzdGVyIGlzIHNpbmdsZS1jb3B5IGF0b21pYyBpcwog IFVOU1BFQ0lGSUVELCBhbmQgc3VjaCBhbiBhY2Nlc3MgbWF5IGFwcGVhciwgaW50ZXJuYWxseSB0 byB0aGUgSU9NTVUsCiAgYXMgaWYgdHdvIHNlcGFyYXRlIDQtYnl0ZSBhY2Nlc3NlcyDigJQgZmly c3QgdG8gdGhlIGhpZ2ggaGFsZiBhbmQgc2Vjb25kCiAgdG8gdGhlIGxvdyBoYWxmIOKAlCB3ZXJl IHBlcmZvcm1lZC4KClRoZXJlZm9yZSwgdGhlIGF0b21pY2l0eSBvZiA2NC1iaXQgTU1JTyBhY2Nl c3NlcyBpcyBVTlNQRUNJRklFRCBhbmQKbm90IGNsZWFybHkgZGVmaW5lZCBpbiB0aGUgY3VycmVu dCByYXRpZmllZCBSSVNDLVYgSU9NTVUKc3BlY2lmaWNhdGlvbi4gVG8gaGFuZGxlIHRoaXMgY29y cmVjdGx5LCB0aGUgTGludXggUklTQy1WIElPTU1VIGRyaXZlcgpzaG91bGQgZmFsbCBiYWNrIHRv IDMyLWJpdCBNTUlPIGFjY2Vzc2VzIHdoZW4gcmVhZGluZyA2NC1iaXQgSFBNIGNvdW50ZXIKcmVn aXN0ZXIuCgpBZGRpdGlvbmFsbHksIERhdmlkIExhaWdodCBoYXMgcHJvcG9zZWQgYW4gb3B0aW1p emF0aW9uIHVzaW5nIHRoZQpoaS1sby1oaSByZWFkIHBhdHRlcm4gd2l0aCBtdWx0aXBsZSAzMi1i aXQgTU1JTyBhY2Nlc3NlcyBbMV0sIG5vIHJldHJ5Cmxvb3AuCgpbMV06IGh0dHBzOi8vbG9yZS5r ZXJuZWwub3JnL2xpbnV4LXJpc2N2LzIwMjYwNjE4MTQzNjM0LjdmM2RkNmM1QHB1bXBraW4vCgo+ ICsKPiArCS8qIFRoZSBiaXQgNjMgb2YgY3ljbGUgY291bnRlciAoaS5lLiwgaWR4ID09IDApIGlz IE9GIGJpdCAqLwo+ICsJcmV0dXJuIGlkeCA/IHZhbHVlIDogKHZhbHVlICYgflJJU0NWX0lPTU1V X0lPSFBNQ1lDTEVTX09GKTsKPiArfQo+ICsKPiArc3RhdGljIGJvb2wgaXNfY3ljbGVfZXZlbnQo dTY0IGV2ZW50KQo+ICt7Cj4gKwlyZXR1cm4gZXZlbnQgPT0gUklTQ1ZfSU9NTVVfSFBNRVZFTlRf Q1lDTEU7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIHJpc2N2X2lvbW11X3BtdV9zZXRfZXZlbnQo c3RydWN0IHJpc2N2X2lvbW11X3BtdSAqcG11LCB1MzIgaWR4LAo+ICsJCQkJICAgICAgdTY0IHZh bHVlKQo+ICt7Cj4gKwkvKiBUaGVyZSBpcyBubyBhc3NvY2l0YXRlZCBJT0hQTUVWVDAgZm9yIElP SFBNQ1lDTEVTICovCj4gKwlpZiAoaXNfY3ljbGVfZXZlbnQodmFsdWUpKQo+ICsJCXJldHVybjsK PiArCj4gKwkvKiBFdmVudCBjb3VudGVyIHN0YXJ0IGZyb20gaWR4IDEgKi8KPiArCXdyaXRlcShG SUVMRF9HRVQoUklTQ1ZfSU9NTVVfSU9IUE1FVlRfRVZFTlQsIHZhbHVlKSwKPiArCSAgICAgICBw bXUtPnJlZyArIFJJU0NWX0lPTU1VX1JFR19JT0hQTUVWVChpZHggLSAxKSk7Cj4gK30KPiArCj4g K3N0YXRpYyB2b2lkIHJpc2N2X2lvbW11X3BtdV9lbmFibGVfY291bnRlcihzdHJ1Y3QgcmlzY3Zf aW9tbXVfcG11ICpwbXUsIHUzMiBpZHgpCj4gK3sKPiArCXZvaWQgX19pb21lbSAqYWRkciA9IHBt dS0+cmVnICsgUklTQ1ZfSU9NTVVfUkVHX0lPQ09VTlRJTkg7Cj4gKwl1MzIgdmFsdWUgPSByZWFk bChhZGRyKTsKPiArCj4gKwl3cml0ZWwodmFsdWUgJiB+QklUKGlkeCksIGFkZHIpOwo+ICt9Cj4g Kwo+ICtzdGF0aWMgdm9pZCByaXNjdl9pb21tdV9wbXVfZGlzYWJsZV9jb3VudGVyKHN0cnVjdCBy aXNjdl9pb21tdV9wbXUgKnBtdSwgdTMyIGlkeCkKPiArewo+ICsJdm9pZCBfX2lvbWVtICphZGRy ID0gcG11LT5yZWcgKyBSSVNDVl9JT01NVV9SRUdfSU9DT1VOVElOSDsKPiArCXUzMiB2YWx1ZSA9 IHJlYWRsKGFkZHIpOwo+ICsKPiArCXdyaXRlbCh2YWx1ZSB8IEJJVChpZHgpLCBhZGRyKTsKPiAr fQo+ICsKPiArc3RhdGljIHZvaWQgcmlzY3ZfaW9tbXVfcG11X3N0YXJ0X2FsbChzdHJ1Y3Qgcmlz Y3ZfaW9tbXVfcG11ICpwbXUpCj4gK3sKPiArCXZvaWQgX19pb21lbSAqYWRkciA9IHBtdS0+cmVn ICsgUklTQ1ZfSU9NTVVfUkVHX0lPQ09VTlRJTkg7Cj4gKwl1MzIgdXNlZF9jbnRyID0gMDsKPiAr Cj4gKwkvKiBUaGUgcGVyZm9ybWFuY2UtbW9uaXRvcmluZyBjb3VudGVyIGluaGliaXRzIGlzIGEg MzItYml0IFdBUkwgcmVnaXN0ZXIgKi8KPiArCWJpdG1hcF90b19hcnIzMigmdXNlZF9jbnRyLCBw bXUtPnVzZWRfY291bnRlcnMsIHBtdS0+bnVtX2NvdW50ZXJzKTsKPiArCj4gKwl3cml0ZWwofnVz ZWRfY250ciwgYWRkcik7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIHJpc2N2X2lvbW11X3BtdV9z dG9wX2FsbChzdHJ1Y3QgcmlzY3ZfaW9tbXVfcG11ICpwbXUpCj4gK3sKPiArCXdyaXRlbChHRU5N QVNLX1VMTChwbXUtPm51bV9jb3VudGVycyAtIDEsIDApLAo+ICsJICAgICAgIHBtdS0+cmVnICsg UklTQ1ZfSU9NTVVfUkVHX0lPQ09VTlRJTkgpOwo+ICt9Cj4gKwo+ICsvKiBQTVUgQVBJcyAqLwo+ ICtzdGF0aWMgdm9pZCByaXNjdl9pb21tdV9wbXVfc2V0X3BlcmlvZChzdHJ1Y3QgcGVyZl9ldmVu dCAqZXZlbnQpCj4gK3sKPiArCXN0cnVjdCByaXNjdl9pb21tdV9wbXUgKnBtdSA9IHRvX3Jpc2N2 X2lvbW11X3BtdShldmVudC0+cG11KTsKPiArCXN0cnVjdCBod19wZXJmX2V2ZW50ICpod2MgPSAm ZXZlbnQtPmh3Owo+ICsJdTY0IGNvdW50ZXJfbWFzayA9IGh3Yy0+aWR4ID8gcG11LT5ldmVudF9j bnRyX21hc2sgOiBwbXUtPmN5Y2xlX2NudHJfbWFzazsKPiArCXU2NCBwZXJpb2Q7Cj4gKwo+ICsJ LyoKPiArCSAqIExpbWl0IHRoZSBtYXhpbXVtIHBlcmlvZCB0byBwcmV2ZW50IHRoZSBjb3VudGVy IHZhbHVlCj4gKwkgKiBmcm9tIG92ZXJ0YWtpbmcgdGhlIG9uZSB3ZSBhcmUgYWJvdXQgdG8gcHJv Z3JhbS4KPiArCSAqIEluIGVmZmVjdCB3ZSBhcmUgcmVkdWNpbmcgbWF4X3BlcmlvZCB0byBhY2Nv dW50IGZvcgo+ICsJICogaW50ZXJydXB0IGxhdGVuY3kgKGFuZCB3ZSBhcmUgYmVpbmcgdmVyeSBj b25zZXJ2YXRpdmUpLgo+ICsJICovCj4gKwlwZXJpb2QgPSBjb3VudGVyX21hc2sgPj4gMTsKPiAr CXJpc2N2X2lvbW11X3BtdV9zZXRfY291bnRlcihwbXUsIGh3Yy0+aWR4LCBwZXJpb2QpOwo+ICsJ bG9jYWw2NF9zZXQoJmh3Yy0+cHJldl9jb3VudCwgcGVyaW9kKTsKPiArfQo+ICsKPiArc3RhdGlj IGludCByaXNjdl9pb21tdV9wbXVfZXZlbnRfaW5pdChzdHJ1Y3QgcGVyZl9ldmVudCAqZXZlbnQp Cj4gK3sKPiArCXN0cnVjdCByaXNjdl9pb21tdV9wbXUgKnBtdSA9IHRvX3Jpc2N2X2lvbW11X3Bt dShldmVudC0+cG11KTsKPiArCXN0cnVjdCBod19wZXJmX2V2ZW50ICpod2MgPSAmZXZlbnQtPmh3 Owo+ICsJc3RydWN0IHBlcmZfZXZlbnQgKnNpYmxpbmc7Cj4gKwlpbnQgdG90YWxfZXZlbnRfY291 bnRlcnMgPSBwbXUtPm51bV9jb3VudGVycyAtIDE7Cj4gKwlpbnQgY291bnRlcnMgPSAwOwo+ICsK PiArCWlmIChldmVudC0+YXR0ci50eXBlICE9IGV2ZW50LT5wbXUtPnR5cGUpCj4gKwkJcmV0dXJu IC1FTk9FTlQ7Cj4gKwo+ICsJaWYgKGh3Yy0+c2FtcGxlX3BlcmlvZCkKPiArCQlyZXR1cm4gLUVP UE5PVFNVUFA7Cj4gKwo+ICsJaWYgKGV2ZW50LT5jcHUgPCAwKQo+ICsJCXJldHVybiAtRU9QTk9U U1VQUDsKPiArCj4gKwlldmVudC0+Y3B1ID0gcG11LT5vbl9jcHU7Cj4gKwo+ICsJaHdjLT5pZHgg PSAtMTsKPiArCWh3Yy0+Y29uZmlnID0gZXZlbnQtPmF0dHIuY29uZmlnOwo+ICsKPiArCWlmIChl dmVudC0+Z3JvdXBfbGVhZGVyID09IGV2ZW50KQo+ICsJCXJldHVybiAwOwo+ICsKPiArCWlmIChp c19jeWNsZV9ldmVudChnZXRfZXZlbnQoZXZlbnQtPmdyb3VwX2xlYWRlcikpKQo+ICsJCWlmICgr K2NvdW50ZXJzID4gdG90YWxfZXZlbnRfY291bnRlcnMpCj4gKwkJCXJldHVybiAtRUlOVkFMOwo+ ICsKPiArCWZvcl9lYWNoX3NpYmxpbmdfZXZlbnQoc2libGluZywgZXZlbnQtPmdyb3VwX2xlYWRl cikgewo+ICsJCWlmIChpc19jeWNsZV9ldmVudChnZXRfZXZlbnQoc2libGluZykpKQo+ICsJCQlj b250aW51ZTsKPiArCj4gKwkJaWYgKHNpYmxpbmctPnBtdSAhPSBldmVudC0+cG11ICYmICFpc19z b2Z0d2FyZV9ldmVudChzaWJsaW5nKSkKPiArCQkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJCWlm ICgrK2NvdW50ZXJzID4gdG90YWxfZXZlbnRfY291bnRlcnMpCj4gKwkJCXJldHVybiAtRUlOVkFM Owo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCByaXNjdl9p b21tdV9wbXVfdXBkYXRlKHN0cnVjdCBwZXJmX2V2ZW50ICpldmVudCkKPiArewo+ICsJc3RydWN0 IGh3X3BlcmZfZXZlbnQgKmh3YyA9ICZldmVudC0+aHc7Cj4gKwlzdHJ1Y3QgcmlzY3ZfaW9tbXVf cG11ICpwbXUgPSB0b19yaXNjdl9pb21tdV9wbXUoZXZlbnQtPnBtdSk7Cj4gKwl1NjQgZGVsdGEs IHByZXYsIG5vdzsKPiArCXUzMiBpZHggPSBod2MtPmlkeDsKPiArCXU2NCBjb3VudGVyX21hc2sg PSBpZHggPyBwbXUtPmV2ZW50X2NudHJfbWFzayA6IHBtdS0+Y3ljbGVfY250cl9tYXNrOwo+ICsK PiArCWRvIHsKPiArCQlwcmV2ID0gbG9jYWw2NF9yZWFkKCZod2MtPnByZXZfY291bnQpOwo+ICsJ CW5vdyA9IHJpc2N2X2lvbW11X3BtdV9nZXRfY291bnRlcihwbXUsIGlkeCk7Cj4gKwl9IHdoaWxl IChsb2NhbDY0X2NtcHhjaGcoJmh3Yy0+cHJldl9jb3VudCwgcHJldiwgbm93KSAhPSBwcmV2KTsK PiArCj4gKwlkZWx0YSA9IChub3cgLSBwcmV2KSAmIGNvdW50ZXJfbWFzazsKPiArCWxvY2FsNjRf YWRkKGRlbHRhLCAmZXZlbnQtPmNvdW50KTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgcmlzY3Zf aW9tbXVfcG11X3N0YXJ0KHN0cnVjdCBwZXJmX2V2ZW50ICpldmVudCwgaW50IGZsYWdzKQo+ICt7 Cj4gKwlzdHJ1Y3QgcmlzY3ZfaW9tbXVfcG11ICpwbXUgPSB0b19yaXNjdl9pb21tdV9wbXUoZXZl bnQtPnBtdSk7Cj4gKwlzdHJ1Y3QgaHdfcGVyZl9ldmVudCAqaHdjID0gJmV2ZW50LT5odzsKPiAr Cj4gKwlpZiAoV0FSTl9PTl9PTkNFKCEoZXZlbnQtPmh3LnN0YXRlICYgUEVSRl9IRVNfU1RPUFBF RCkpKQo+ICsJCXJldHVybjsKPiArCj4gKwlpZiAoZmxhZ3MgJiBQRVJGX0VGX1JFTE9BRCkKPiAr CQlXQVJOX09OX09OQ0UoIShldmVudC0+aHcuc3RhdGUgJiBQRVJGX0hFU19VUFRPREFURSkpOwo+ ICsKPiArCWh3Yy0+c3RhdGUgPSAwOwo+ICsJcmlzY3ZfaW9tbXVfcG11X3NldF9wZXJpb2QoZXZl bnQpOwo+ICsJcmlzY3ZfaW9tbXVfcG11X3NldF9ldmVudChwbXUsIGh3Yy0+aWR4LCBod2MtPmNv bmZpZyk7Cj4gKwlyaXNjdl9pb21tdV9wbXVfZW5hYmxlX2NvdW50ZXIocG11LCBod2MtPmlkeCk7 Cj4gKwo+ICsJcGVyZl9ldmVudF91cGRhdGVfdXNlcnBhZ2UoZXZlbnQpOwo+ICt9Cj4gKwo+ICtz dGF0aWMgdm9pZCByaXNjdl9pb21tdV9wbXVfc3RvcChzdHJ1Y3QgcGVyZl9ldmVudCAqZXZlbnQs IGludCBmbGFncykKPiArewo+ICsJc3RydWN0IHJpc2N2X2lvbW11X3BtdSAqcG11ID0gdG9fcmlz Y3ZfaW9tbXVfcG11KGV2ZW50LT5wbXUpOwo+ICsJc3RydWN0IGh3X3BlcmZfZXZlbnQgKmh3YyA9 ICZldmVudC0+aHc7Cj4gKwlpbnQgaWR4ID0gaHdjLT5pZHg7Cj4gKwo+ICsJaWYgKGh3Yy0+c3Rh dGUgJiBQRVJGX0hFU19TVE9QUEVEKQo+ICsJCXJldHVybjsKPiArCj4gKwlyaXNjdl9pb21tdV9w bXVfZGlzYWJsZV9jb3VudGVyKHBtdSwgaWR4KTsKPiArCj4gKwlpZiAoKGZsYWdzICYgUEVSRl9F Rl9VUERBVEUpICYmICEoaHdjLT5zdGF0ZSAmIFBFUkZfSEVTX1VQVE9EQVRFKSkKPiArCQlyaXNj dl9pb21tdV9wbXVfdXBkYXRlKGV2ZW50KTsKPiArCj4gKwlod2MtPnN0YXRlIHw9IFBFUkZfSEVT X1NUT1BQRUQgfCBQRVJGX0hFU19VUFRPREFURTsKPiArfQo+ICsKPiArc3RhdGljIGludCByaXNj dl9pb21tdV9wbXVfYWRkKHN0cnVjdCBwZXJmX2V2ZW50ICpldmVudCwgaW50IGZsYWdzKQo+ICt7 Cj4gKwlzdHJ1Y3QgcmlzY3ZfaW9tbXVfcG11ICpwbXUgPSB0b19yaXNjdl9pb21tdV9wbXUoZXZl bnQtPnBtdSk7Cj4gKwlzdHJ1Y3QgaHdfcGVyZl9ldmVudCAqaHdjID0gJmV2ZW50LT5odzsKPiAr CXVuc2lnbmVkIGludCBudW1fY291bnRlcnMgPSBwbXUtPm51bV9jb3VudGVyczsKPiArCWludCBp ZHg7Cj4gKwo+ICsJLyogUmVzZXJ2ZSBpbmRleCB6ZXJvIGZvciBpb2hwbWN5Y2xlcyAqLwo+ICsJ aWYgKGlzX2N5Y2xlX2V2ZW50KGdldF9ldmVudChldmVudCkpKQo+ICsJCWlkeCA9IDA7Cj4gKwll bHNlCj4gKwkJaWR4ID0gZmluZF9uZXh0X3plcm9fYml0KHBtdS0+dXNlZF9jb3VudGVycywgbnVt X2NvdW50ZXJzLCAxKTsKPiArCj4gKwkvKiBBbGwgZXZlbnQgY291bnRlcnMgb3IgY3ljbGUgY291 bnRlciBhcmUgaW4gdXNlICovCj4gKwlpZiAoaWR4ID09IG51bV9jb3VudGVycyB8fCBwbXUtPmV2 ZW50c1tpZHhdKQo+ICsJCXJldHVybiAtRUFHQUlOOwo+ICsKPiArCXNldF9iaXQoaWR4LCBwbXUt PnVzZWRfY291bnRlcnMpOwo+ICsKPiArCXBtdS0+ZXZlbnRzW2lkeF0gPSBldmVudDsKPiArCWh3 Yy0+aWR4ID0gaWR4Owo+ICsJaHdjLT5zdGF0ZSA9IFBFUkZfSEVTX1NUT1BQRUQgfCBQRVJGX0hF U19VUFRPREFURTsKPiArCWxvY2FsNjRfc2V0KCZod2MtPnByZXZfY291bnQsIDApOwo+ICsKPiAr CWlmIChmbGFncyAmIFBFUkZfRUZfU1RBUlQpCj4gKwkJcmlzY3ZfaW9tbXVfcG11X3N0YXJ0KGV2 ZW50LCBmbGFncyk7Cj4gKwo+ICsJLyogUHJvcGFnYXRlIGNoYW5nZXMgdG8gdGhlIHVzZXJzcGFj ZSBtYXBwaW5nLiAqLwo+ICsJcGVyZl9ldmVudF91cGRhdGVfdXNlcnBhZ2UoZXZlbnQpOwo+ICsK PiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCByaXNjdl9pb21tdV9wbXVfcmVh ZChzdHJ1Y3QgcGVyZl9ldmVudCAqZXZlbnQpCj4gK3sKPiArCXJpc2N2X2lvbW11X3BtdV91cGRh dGUoZXZlbnQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCByaXNjdl9pb21tdV9wbXVfZGVsKHN0 cnVjdCBwZXJmX2V2ZW50ICpldmVudCwgaW50IGZsYWdzKQo+ICt7Cj4gKwlzdHJ1Y3QgcmlzY3Zf aW9tbXVfcG11ICpwbXUgPSB0b19yaXNjdl9pb21tdV9wbXUoZXZlbnQtPnBtdSk7Cj4gKwlzdHJ1 Y3QgaHdfcGVyZl9ldmVudCAqaHdjID0gJmV2ZW50LT5odzsKPiArCWludCBpZHggPSBod2MtPmlk eDsKPiArCj4gKwlyaXNjdl9pb21tdV9wbXVfc3RvcChldmVudCwgUEVSRl9FRl9VUERBVEUpOwo+ ICsJcG11LT5ldmVudHNbaWR4XSA9IE5VTEw7Cj4gKwljbGVhcl9iaXQoaWR4LCBwbXUtPnVzZWRf Y291bnRlcnMpOwo+ICsKPiArCXBlcmZfZXZlbnRfdXBkYXRlX3VzZXJwYWdlKGV2ZW50KTsKPiAr fQo+ICsKPiArc3RhdGljIGludCByaXNjdl9pb21tdV9wbXVfb25saW5lX2NwdSh1bnNpZ25lZCBp bnQgY3B1LCBzdHJ1Y3QgaGxpc3Rfbm9kZSAqbm9kZSkKPiArewo+ICsJc3RydWN0IHJpc2N2X2lv bW11X3BtdSAqaW9tbXVfcG11Owo+ICsKPiArCWlvbW11X3BtdSA9IGhsaXN0X2VudHJ5X3NhZmUo bm9kZSwgc3RydWN0IHJpc2N2X2lvbW11X3BtdSwgbm9kZSk7Cj4gKwo+ICsJaWYgKGlvbW11X3Bt dS0+b25fY3B1ID09IC0xKQo+ICsJCWlvbW11X3BtdS0+b25fY3B1ID0gY3B1Owo+ICsKPiArCXJl dHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHJpc2N2X2lvbW11X3BtdV9vZmZsaW5lX2Nw dSh1bnNpZ25lZCBpbnQgY3B1LCBzdHJ1Y3QgaGxpc3Rfbm9kZSAqbm9kZSkKPiArewo+ICsJc3Ry dWN0IHJpc2N2X2lvbW11X3BtdSAqaW9tbXVfcG11Owo+ICsJdW5zaWduZWQgaW50IHRhcmdldF9j cHU7Cj4gKwo+ICsJaW9tbXVfcG11ID0gaGxpc3RfZW50cnlfc2FmZShub2RlLCBzdHJ1Y3Qgcmlz Y3ZfaW9tbXVfcG11LCBub2RlKTsKPiArCj4gKwlpZiAoY3B1ICE9IGlvbW11X3BtdS0+b25fY3B1 KQo+ICsJCXJldHVybiAwOwo+ICsKPiArCWlvbW11X3BtdS0+b25fY3B1ID0gLTE7Cj4gKwo+ICsJ dGFyZ2V0X2NwdSA9IGNwdW1hc2tfYW55X2J1dChjcHVfb25saW5lX21hc2ssIGNwdSk7Cj4gKwlp ZiAodGFyZ2V0X2NwdSA+PSBucl9jcHVfaWRzKQo+ICsJCXJldHVybiAwOwo+ICsKPiArCXBlcmZf cG11X21pZ3JhdGVfY29udGV4dCgmaW9tbXVfcG11LT5wbXUsIGNwdSwgdGFyZ2V0X2NwdSk7Cj4g Kwlpb21tdV9wbXUtPm9uX2NwdSA9IHRhcmdldF9jcHU7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30K PiArCj4gK3N0YXRpYyBpcnFyZXR1cm5fdCByaXNjdl9pb21tdV9wbXVfaGFuZGxlX2lycShzdHJ1 Y3QgcmlzY3ZfaW9tbXVfcG11ICpwbXUpCj4gK3sKPiArCXUzMiBvdmYgPSByZWFkbChwbXUtPnJl ZyArIFJJU0NWX0lPTU1VX1JFR19JT0NPVU5UT1ZGKTsKPiArCWludCBpZHg7Cj4gKwo+ICsJaWYg KCFvdmYpCj4gKwkJcmV0dXJuIElSUV9OT05FOwo+ICsKPiArCXJpc2N2X2lvbW11X3BtdV9zdG9w X2FsbChwbXUpOwo+ICsKPiArCWZvcl9lYWNoX3NldF9iaXQoaWR4LCAodW5zaWduZWQgbG9uZyAq KSZvdmYsIHBtdS0+bnVtX2NvdW50ZXJzKSB7Cj4gKwkJc3RydWN0IHBlcmZfZXZlbnQgKmV2ZW50 ID0gcG11LT5ldmVudHNbaWR4XTsKPiArCj4gKwkJaWYgKFdBUk5fT05fT05DRSghZXZlbnQpKQo+ ICsJCQljb250aW51ZTsKPiArCj4gKwkJcmlzY3ZfaW9tbXVfcG11X3VwZGF0ZShldmVudCk7Cj4g KwkJcmlzY3ZfaW9tbXVfcG11X3NldF9wZXJpb2QoZXZlbnQpOwo+ICsJfQo+ICsKPiArCXJpc2N2 X2lvbW11X3BtdV9zdGFydF9hbGwocG11KTsKPiArCj4gKwlyZXR1cm4gSVJRX0hBTkRMRUQ7Cj4g K30KPiArCj4gK3N0YXRpYyBpcnFyZXR1cm5fdCByaXNjdl9pb21tdV9wbXVfaXJxX2hhbmRsZXIo aW50IGlycSwgdm9pZCAqZGV2X2lkKQo+ICt7Cj4gKwlzdHJ1Y3QgcmlzY3ZfaW9tbXVfcG11ICpw bXUgPSAoc3RydWN0IHJpc2N2X2lvbW11X3BtdSAqKWRldl9pZDsKPiArCWlycXJldHVybl90IHJl dDsKPiArCj4gKwkvKiBDaGVjayB3aGV0aGVyIHRoaXMgaW50ZXJydXB0IGlzIGZvciBQTVUgKi8K PiArCWlmICghKHJlYWRsX3JlbGF4ZWQocG11LT5yZWcgKyBSSVNDVl9JT01NVV9SRUdfSVBTUikg JiBSSVNDVl9JT01NVV9JUFNSX1BNSVApKQo+ICsJCXJldHVybiBJUlFfTk9ORTsKPiArCj4gKwkv KiBQcm9jZXNzIFBNVSBJUlEgKi8KPiArCXJldCA9IHJpc2N2X2lvbW11X3BtdV9oYW5kbGVfaXJx KHBtdSk7Cj4gKwo+ICsJLyogQ2xlYXIgcGVyZm9ybWFuY2UgbW9uaXRvcmluZyBpbnRlcnJ1cHQg cGVuZGluZyBiaXQgKi8KPiArCXdyaXRlbF9yZWxheGVkKFJJU0NWX0lPTU1VX0lQU1JfUE1JUCwg cG11LT5yZWcgKyBSSVNDVl9JT01NVV9SRUdfSVBTUik7Cj4gKwo+ICsJcmV0dXJuIHJldDsKPiAr fQo+ICsKPiArc3RhdGljIHVuc2lnbmVkIGludCByaXNjdl9pb21tdV9wbXVfZ2V0X2lycV9udW0o c3RydWN0IHJpc2N2X2lvbW11X2RldmljZSAqaW9tbXUpCj4gK3sKPiArCS8qIFJldXNlIElDVkVD LkNJViBtYXNrIGZvciBhbGwgaW50ZXJydXB0IHZlY3RvcnMgbWFwcGluZyAqLwo+ICsJaW50IHZl YyA9IChpb21tdS0+aWN2ZWMgPj4gKFJJU0NWX0lPTU1VX0lQU1JfUE1JUCAqIDQpKSAmIFJJU0NW X0lPTU1VX0lDVkVDX0NJVjsKPiArCj4gKwlyZXR1cm4gaW9tbXUtPmlycXNbdmVjXTsKPiArfQo+ ICsKPiArc3RhdGljIGludCByaXNjdl9pb21tdV9wbXVfcmVxdWVzdF9pcnEoc3RydWN0IHJpc2N2 X2lvbW11X2RldmljZSAqaW9tbXUsCj4gKwkJCQkgICAgICAgc3RydWN0IHJpc2N2X2lvbW11X3Bt dSAqcG11KQo+ICt7Cj4gKwl1bnNpZ25lZCBpbnQgaXJxID0gcmlzY3ZfaW9tbXVfcG11X2dldF9p cnFfbnVtKGlvbW11KTsKPiArCj4gKwkvKgo+ICsJICogU2V0IHRoZSBJUlFGX09ORVNIT1QgZmxh ZyBiZWNhdXNlIHRoaXMgSVJRIGNhbiBiZSBzaGFyZWQgd2l0aAo+ICsJICogb3RoZXIgdGhyZWFk ZWQgSVJRcyBieSBvdGhlciBxdWV1ZXMuCj4gKwkgKi8KPiArCXJldHVybiBkZXZtX3JlcXVlc3Rf aXJxKGlvbW11LT5kZXYsIGlycSwgcmlzY3ZfaW9tbXVfcG11X2lycV9oYW5kbGVyLAo+ICsJCQkJ SVJRRl9PTkVTSE9UIHwgSVJRRl9TSEFSRUQsIGRldl9uYW1lKGlvbW11LT5kZXYpLCBwbXUpOwo+ ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCByaXNjdl9pb21tdV9wbXVfZnJlZV9pcnEoc3RydWN0IHJp c2N2X2lvbW11X2RldmljZSAqaW9tbXUsCj4gKwkJCQkgICAgIHN0cnVjdCByaXNjdl9pb21tdV9w bXUgKnBtdSkKPiArewo+ICsJdW5zaWduZWQgaW50IGlycSA9IHJpc2N2X2lvbW11X3BtdV9nZXRf aXJxX251bShpb21tdSk7Cj4gKwo+ICsJZnJlZV9pcnEoaXJxLCBwbXUpOwo+ICt9Cj4gKwo+ICtz dGF0aWMgaW50IHJpc2N2X2lvbW11X3BtdV9wcm9iZShzdHJ1Y3QgYXV4aWxpYXJ5X2RldmljZSAq YXV4ZGV2LAo+ICsJCQkJIGNvbnN0IHN0cnVjdCBhdXhpbGlhcnlfZGV2aWNlX2lkICppZCkKPiAr ewo+ICsJc3RydWN0ICByaXNjdl9pb21tdV9kZXZpY2UgKmlvbW11X2RldiA9IGRldl9nZXRfcGxh dGRhdGEoJmF1eGRldi0+ZGV2KTsKPiArCXN0cnVjdCByaXNjdl9pb21tdV9wbXUgKmlvbW11X3Bt dTsKPiArCXZvaWQgX19pb21lbSAqYWRkcjsKPiArCWNoYXIgKm5hbWU7Cj4gKwlpbnQgcmV0Owo+ ICsKPiArCWlvbW11X3BtdSA9IGRldm1fa3phbGxvYygmYXV4ZGV2LT5kZXYsIHNpemVvZigqaW9t bXVfcG11KSwgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIWlvbW11X3BtdSkKPiArCQlyZXR1cm4gLUVO T01FTTsKPiArCj4gKwlpb21tdV9wbXUtPnJlZyA9IGlvbW11X2Rldi0+cmVnOwo+ICsKPiArCS8q IENvdW50ZXIgbnVtYmVyIGFuZCB3aWR0aCBhcmUgaGFyZHdhcmUtaW1wbGVtZW50ZWQuIERldGVj dCB0aGVtIGJ5IHdyaXRlIDFzICovCj4gKwlhZGRyID0gaW9tbXVfcG11LT5yZWcgKyBSSVNDVl9J T01NVV9SRUdfSU9DT1VOVElOSDsKPiArCXdyaXRlbChSSVNDVl9JT01NVV9JT0NPVU5USU5IX0hQ TSwgYWRkcik7Cj4gKwlpb21tdV9wbXUtPm51bV9jb3VudGVycyA9IGh3ZWlnaHQzMihyZWFkbChh ZGRyKSk7Cj4gKwo+ICsJYWRkciA9IGlvbW11X3BtdS0+cmVnICsgUklTQ1ZfSU9NTVVfUkVHX0lP SFBNQ1lDTEVTOwo+ICsJd3JpdGVxKFJJU0NWX0lPTU1VX0lPSFBNQ1lDTEVTX0NPVU5URVIsIGFk ZHIpOwo+ICsJaW9tbXVfcG11LT5jeWNsZV9jbnRyX21hc2sgPSByZWFkcShhZGRyKTsKPiArCj4g KwkvKiBBc3N1bWUgdGhlIHdpZHRoIG9mIGFsbCBldmVudCBjb3VudGVycyBhcmUgdGhlIHNhbWUg Ki8KPiArCWFkZHIgPSBpb21tdV9wbXUtPnJlZyArIFJJU0NWX0lPTU1VX1JFR19JT0hQTUNUUl9C QVNFOwo+ICsJd3JpdGVxKFJJU0NWX0lPTU1VX0lPSFBNQ1RSX0NPVU5URVIsIGFkZHIpOwo+ICsJ aW9tbXVfcG11LT5ldmVudF9jbnRyX21hc2sgPSByZWFkcShhZGRyKTsKPiArCj4gKwlpb21tdV9w bXUtPnBtdSA9IChzdHJ1Y3QgcG11KSB7Cj4gKwkJLm1vZHVsZQkJPSBUSElTX01PRFVMRSwKPiAr CQkucGFyZW50CQk9ICZhdXhkZXYtPmRldiwKPiArCQkudGFza19jdHhfbnIJPSBwZXJmX2ludmFs aWRfY29udGV4dCwKPiArCQkuZXZlbnRfaW5pdAk9IHJpc2N2X2lvbW11X3BtdV9ldmVudF9pbml0 LAo+ICsJCS5hZGQJCT0gcmlzY3ZfaW9tbXVfcG11X2FkZCwKPiArCQkuZGVsCQk9IHJpc2N2X2lv bW11X3BtdV9kZWwsCj4gKwkJLnN0YXJ0CQk9IHJpc2N2X2lvbW11X3BtdV9zdGFydCwKPiArCQku c3RvcAkJPSByaXNjdl9pb21tdV9wbXVfc3RvcCwKPiArCQkucmVhZAkJPSByaXNjdl9pb21tdV9w bXVfcmVhZCwKPiArCQkuYXR0cl9ncm91cHMJPSByaXNjdl9pb21tdV9wbXVfYXR0cl9ncnBzLAo+ ICsJCS5jYXBhYmlsaXRpZXMJPSBQRVJGX1BNVV9DQVBfTk9fRVhDTFVERSwKPiArCX07Cj4gKwo+ ICsJYXV4aWxpYXJ5X3NldF9kcnZkYXRhKGF1eGRldiwgaW9tbXVfcG11KTsKPiArCj4gKwluYW1l ID0gZGV2bV9rYXNwcmludGYoJmF1eGRldi0+ZGV2LCBHRlBfS0VSTkVMLAo+ICsJCQkgICAgICAi cmlzY3ZfaW9tbXVfcG11XyVzIiwgZGV2X25hbWUoaW9tbXVfZGV2LT5kZXYpKTsKPiArCWlmICgh bmFtZSkgewo+ICsJCWRldl9lcnIoJmF1eGRldi0+ZGV2LCAiRmFpbGVkIHRvIGNyZWF0ZSBuYW1l IHJpc2N2X2lvbW11X3BtdV8lc1xuIiwKPiArCQkJZGV2X25hbWUoaW9tbXVfZGV2LT5kZXYpKTsK PiArCQlyZXR1cm4gLUVOT01FTTsKPiArCX0KPiArCj4gKwkvKiBCaW5kIGFsbCBldmVudHMgdG8g dGhlIHNhbWUgY3B1IGNvbnRleHQgdG8gYXZvaWQgcmFjZSBlbmFibGluZyAqLwo+ICsJaW9tbXVf cG11LT5vbl9jcHUgPSByYXdfc21wX3Byb2Nlc3Nvcl9pZCgpOwo+ICsKPiArCXJldCA9IGNwdWhw X3N0YXRlX2FkZF9pbnN0YW5jZV9ub2NhbGxzKGNwdWhwX3N0YXRlLCAmaW9tbXVfcG11LT5ub2Rl KTsKPiArCWlmIChyZXQpIHsKPiArCQlkZXZfZXJyKCZhdXhkZXYtPmRldiwgIkZhaWxlZCB0byBy ZWdpc3RlciBob3RwbHVnICVzOiAlZFxuIiwgbmFtZSwgcmV0KTsKPiArCQlyZXR1cm4gcmV0Owo+ ICsJfQo+ICsKPiArCXJldCA9IHJpc2N2X2lvbW11X3BtdV9yZXF1ZXN0X2lycShpb21tdV9kZXYs IGlvbW11X3BtdSk7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJZGV2X2VycigmYXV4ZGV2LT5kZXYsICJG YWlsZWQgdG8gcmVxdWVzdCBpcnEgJXM6ICVkXG4iLCBuYW1lLCByZXQpOwo+ICsJCWdvdG8gZXJy X2NwdWhwX3JlbW92ZTsKPiArCX0KPiArCj4gKwlyZXQgPSBwZXJmX3BtdV9yZWdpc3RlcigmaW9t bXVfcG11LT5wbXUsIG5hbWUsIC0xKTsKPiArCWlmIChyZXQpIHsKPiArCQlkZXZfZXJyKCZhdXhk ZXYtPmRldiwgIkZhaWxlZCB0byByZWdpc3RlICVzOiAlZFxuIiwgbmFtZSwgcmV0KTsKPiArCQln b3RvIGVycl9mcmVlX2lycTsKPiArCX0KPiArCj4gKwlkZXZfaW5mbygmYXV4ZGV2LT5kZXYsICIl czogUmVnaXN0ZXJlZCB3aXRoICVkIGNvdW50ZXJzXG4iLAo+ICsJCSBuYW1lLCBpb21tdV9wbXUt Pm51bV9jb3VudGVycyk7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gKwo+ICtlcnJfZnJlZV9pcnE6Cj4g KwlyaXNjdl9pb21tdV9wbXVfZnJlZV9pcnEoaW9tbXVfZGV2LCBpb21tdV9wbXUpOwo+ICtlcnJf Y3B1aHBfcmVtb3ZlOgo+ICsJY3B1aHBfc3RhdGVfcmVtb3ZlX2luc3RhbmNlX25vY2FsbHMoY3B1 aHBfc3RhdGUsICZpb21tdV9wbXUtPm5vZGUpOwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiAr c3RhdGljIGNvbnN0IHN0cnVjdCBhdXhpbGlhcnlfZGV2aWNlX2lkIHJpc2N2X2lvbW11X3BtdV9p ZF90YWJsZVtdID0gewo+ICsJeyAubmFtZSA9ICJpb21tdS5wbXUiIH0sCj4gKwl7fQo+ICt9Owo+ ICtNT0RVTEVfREVWSUNFX1RBQkxFKGF1eGlsaWFyeSwgcmlzY3ZfaW9tbXVfcG11X2lkX3RhYmxl KTsKPiArCj4gK3N0YXRpYyBzdHJ1Y3QgYXV4aWxpYXJ5X2RyaXZlciBpb21tdV9wbXVfZHJpdmVy ID0gewo+ICsJLnByb2JlCQk9IHJpc2N2X2lvbW11X3BtdV9wcm9iZSwKPiArCS5pZF90YWJsZQk9 IHJpc2N2X2lvbW11X3BtdV9pZF90YWJsZSwKPiArfTsKPiArCj4gK3N0YXRpYyBpbnQgX19pbml0 IHJpc2N2X2lvbW11X3BtdV9pbml0KHZvaWQpCj4gK3sKPiArCWludCByZXQ7Cj4gKwo+ICsJY3B1 aHBfc3RhdGUgPSBjcHVocF9zZXR1cF9zdGF0ZV9tdWx0aShDUFVIUF9BUF9PTkxJTkVfRFlOLAo+ ICsJCQkJCSAgICAgICJwZXJmL3Jpc2N2L2lvbW11Om9ubGluZSIsCj4gKwkJCQkJICAgICAgcmlz Y3ZfaW9tbXVfcG11X29ubGluZV9jcHUsCj4gKwkJCQkJICAgICAgcmlzY3ZfaW9tbXVfcG11X29m ZmxpbmVfY3B1KTsKPiArCWlmIChjcHVocF9zdGF0ZSA8IDApCj4gKwkJcmV0dXJuIGNwdWhwX3N0 YXRlOwo+ICsKPiArCXJldCA9IGF1eGlsaWFyeV9kcml2ZXJfcmVnaXN0ZXIoJmlvbW11X3BtdV9k cml2ZXIpOwo+ICsJaWYgKHJldCkKPiArCQljcHVocF9yZW1vdmVfbXVsdGlfc3RhdGUoY3B1aHBf c3RhdGUpOwo+ICsKPiArCXJldHVybiByZXQ7Cj4gK30KPiArbW9kdWxlX2luaXQocmlzY3ZfaW9t bXVfcG11X2luaXQpOwo+ICsKPiArTU9EVUxFX0RFU0NSSVBUSU9OKCJSSVNDLVYgSU9NTVUgUE1V Iik7Cj4gK01PRFVMRV9MSUNFTlNFKCJHUEwiKTsKPiAtLSAKPiAyLjQzLjcKPiAKPiAKPiBfX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwo+IGxpbnV4LXJpc2N2 IG1haWxpbmcgbGlzdAo+IGxpbnV4LXJpc2N2QGxpc3RzLmluZnJhZGVhZC5vcmcKPiBodHRwOi8v bGlzdHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LXJpc2N2Cj4gCgpfX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpsaW51eC1yaXNjdiBt YWlsaW5nIGxpc3QKbGludXgtcmlzY3ZAbGlzdHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMu aW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LXJpc2N2Cg==