From mboxrd@z Thu Jan 1 00:00:00 1970 From: Atish Patra Date: Wed, 3 Apr 2024 00:36:41 -0700 Subject: [PATCH v4 08/15] RISC-V: KVM: Implement SBI PMU Snapshot feature In-Reply-To: References: <20240229010130.1380926-1-atishp@rivosinc.com> <20240229010130.1380926-9-atishp@rivosinc.com> <20240302-6ae8fe37b90f127bc9be737f@orel> Message-ID: List-Id: To: kvm-riscv@lists.infradead.org MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit On 4/1/24 15:36, Atish Patra wrote: > On Sat, Mar 2, 2024 at 1:49?AM Andrew Jones wrote: >> >> On Wed, Feb 28, 2024 at 05:01:23PM -0800, Atish Patra wrote: >>> PMU Snapshot function allows to minimize the number of traps when the >>> guest access configures/access the hpmcounters. If the snapshot feature >>> is enabled, the hypervisor updates the shared memory with counter >>> data and state of overflown counters. The guest can just read the >>> shared memory instead of trap & emulate done by the hypervisor. >>> >>> This patch doesn't implement the counter overflow yet. >>> >>> Reviewed-by: Anup Patel >>> Signed-off-by: Atish Patra >>> --- >>> arch/riscv/include/asm/kvm_vcpu_pmu.h | 7 ++ >>> arch/riscv/kvm/vcpu_pmu.c | 120 +++++++++++++++++++++++++- >>> arch/riscv/kvm/vcpu_sbi_pmu.c | 3 + >>> drivers/perf/riscv_pmu_sbi.c | 2 +- >>> 4 files changed, 129 insertions(+), 3 deletions(-) >>> >>> diff --git a/arch/riscv/include/asm/kvm_vcpu_pmu.h b/arch/riscv/include/asm/kvm_vcpu_pmu.h >>> index 395518a1664e..586bab84be35 100644 >>> --- a/arch/riscv/include/asm/kvm_vcpu_pmu.h >>> +++ b/arch/riscv/include/asm/kvm_vcpu_pmu.h >>> @@ -50,6 +50,10 @@ struct kvm_pmu { >>> bool init_done; >>> /* Bit map of all the virtual counter used */ >>> DECLARE_BITMAP(pmc_in_use, RISCV_KVM_MAX_COUNTERS); >>> + /* The address of the counter snapshot area (guest physical address) */ >>> + gpa_t snapshot_addr; >>> + /* The actual data of the snapshot */ >>> + struct riscv_pmu_snapshot_data *sdata; >>> }; >>> >>> #define vcpu_to_pmu(vcpu) (&(vcpu)->arch.pmu_context) >>> @@ -85,6 +89,9 @@ int kvm_riscv_vcpu_pmu_ctr_cfg_match(struct kvm_vcpu *vcpu, unsigned long ctr_ba >>> int kvm_riscv_vcpu_pmu_ctr_read(struct kvm_vcpu *vcpu, unsigned long cidx, >>> struct kvm_vcpu_sbi_return *retdata); >>> void kvm_riscv_vcpu_pmu_init(struct kvm_vcpu *vcpu); >>> +int kvm_riscv_vcpu_pmu_setup_snapshot(struct kvm_vcpu *vcpu, unsigned long saddr_low, >>> + unsigned long saddr_high, unsigned long flags, >>> + struct kvm_vcpu_sbi_return *retdata); >> >> I prefer to name this function >> >> kvm_riscv_vcpu_pmu_snapshot_set_shmem >> > > Sure. > >>> void kvm_riscv_vcpu_pmu_deinit(struct kvm_vcpu *vcpu); >>> void kvm_riscv_vcpu_pmu_reset(struct kvm_vcpu *vcpu); >>> >>> diff --git a/arch/riscv/kvm/vcpu_pmu.c b/arch/riscv/kvm/vcpu_pmu.c >>> index 29bf4ca798cb..74865e6050a1 100644 >>> --- a/arch/riscv/kvm/vcpu_pmu.c >>> +++ b/arch/riscv/kvm/vcpu_pmu.c >>> @@ -311,6 +311,81 @@ int kvm_riscv_vcpu_pmu_read_hpm(struct kvm_vcpu *vcpu, unsigned int csr_num, >>> return ret; >>> } >>> >>> +static void kvm_pmu_clear_snapshot_area(struct kvm_vcpu *vcpu) >>> +{ >>> + struct kvm_pmu *kvpmu = vcpu_to_pmu(vcpu); >>> + int snapshot_area_size = sizeof(struct riscv_pmu_snapshot_data); >>> + >>> + if (kvpmu->sdata) { >>> + memset(kvpmu->sdata, 0, snapshot_area_size); >>> + if (kvpmu->snapshot_addr != INVALID_GPA) >> >> It's a KVM bug if we have non-null sdata but snapshot_addr is INVALID_GPA, >> right? Maybe we should warn if we see that. We can also move the memset >> inside the if block. >> > > Added a warning. > >>> + kvm_vcpu_write_guest(vcpu, kvpmu->snapshot_addr, >>> + kvpmu->sdata, snapshot_area_size); >>> + kfree(kvpmu->sdata); >>> + kvpmu->sdata = NULL; >>> + } >>> + kvpmu->snapshot_addr = INVALID_GPA; >>> +} >>> + >>> +int kvm_riscv_vcpu_pmu_setup_snapshot(struct kvm_vcpu *vcpu, unsigned long saddr_low, >>> + unsigned long saddr_high, unsigned long flags, >>> + struct kvm_vcpu_sbi_return *retdata) >>> +{ >>> + struct kvm_pmu *kvpmu = vcpu_to_pmu(vcpu); >>> + int snapshot_area_size = sizeof(struct riscv_pmu_snapshot_data); >>> + int sbiret = 0; >>> + gpa_t saddr; >>> + unsigned long hva; >>> + bool writable; >>> + >>> + if (!kvpmu) { >>> + sbiret = SBI_ERR_INVALID_PARAM; >>> + goto out; >>> + } >> >> Need to check that flags is zero or return SBI_ERR_INVALID_PARAM. >> > > Fixed. > >>> + >>> + if (saddr_low == -1 && saddr_high == -1) { >> >> We introduced SBI_STA_SHMEM_DISABLE for these magic -1's for STA. Since >> SBI is using the -1 approach for all its shmem, then maybe we should >> rename SBI_STA_SHMEM_DISABLE to SBI_SHMEM_DISABLE and then use them here >> too. >> > > Fixed > >>> + kvm_pmu_clear_snapshot_area(vcpu); >>> + return 0; >>> + } >>> + >>> + saddr = saddr_low; >>> + >>> + if (saddr_high != 0) { >>> + if (IS_ENABLED(CONFIG_32BIT)) >>> + saddr |= ((gpa_t)saddr << 32); >>> + else >>> + sbiret = SBI_ERR_INVALID_ADDRESS; >>> + goto out; >>> + } >>> + >>> + if (kvm_is_error_gpa(vcpu->kvm, saddr)) { >>> + sbiret = SBI_ERR_INVALID_PARAM; >>> + goto out; >>> + } >> >> Does the check above provide anything more than what the check below does? >> > You are correct. I have removed the check > >>> + >>> + hva = kvm_vcpu_gfn_to_hva_prot(vcpu, saddr >> PAGE_SHIFT, &writable); >>> + if (kvm_is_error_hva(hva) || !writable) { >>> + sbiret = SBI_ERR_INVALID_ADDRESS; >>> + goto out; >>> + } >>> + >>> + kvpmu->snapshot_addr = saddr; >>> + kvpmu->sdata = kzalloc(snapshot_area_size, GFP_ATOMIC); >>> + if (!kvpmu->sdata) >> >> Should reset snapshot_addr to INVALID_GPA here on error. Or maybe we >> should just set snapshot_addr to saddr at the bottom of this function if >> we make it. >> > > Done. > >>> + return -ENOMEM; >>> + >>> + if (kvm_vcpu_write_guest(vcpu, saddr, kvpmu->sdata, snapshot_area_size)) { >>> + kfree(kvpmu->sdata); >>> + kvpmu->snapshot_addr = INVALID_GPA; >>> + sbiret = SBI_ERR_FAILURE; >> >> I agree we should return this SBI error for this case, but unfortunately >> the spec is missing the >> >> SBI_ERR_FAILED - The request failed for unspecified or unknown other reasons. >> >> that we have for other SBI functions. I guess we should keep the code like >> this and open a PR to the spec. >> > > I have created a blanket github issue for now. I will send a PR. > >>> + } >>> + >>> +out: >>> + retdata->err_val = sbiret; >>> + >>> + return 0; >>> +} >>> + >>> int kvm_riscv_vcpu_pmu_num_ctrs(struct kvm_vcpu *vcpu, >>> struct kvm_vcpu_sbi_return *retdata) >>> { >>> @@ -344,20 +419,33 @@ int kvm_riscv_vcpu_pmu_ctr_start(struct kvm_vcpu *vcpu, unsigned long ctr_base, >>> int i, pmc_index, sbiret = 0; >>> struct kvm_pmc *pmc; >>> int fevent_code; >>> + bool snap_flag_set = flags & SBI_PMU_START_FLAG_INIT_FROM_SNAPSHOT; >> >> This function should confirm no undefined bits are set in flags and the >> spec should specify that the reserved flags must be zero otherwise an >> invalid param will be returned. >> >> Also here would should confirm that only one of the two flags is set, >> otherwise return invalid param, as they've specified to be mutually >> exclusive. >> > > That makes sense. Update the same github issue. > (https://github.com/riscv-non-isa/riscv-sbi-doc/issues/145) > > I will make the necessary changes in a separate series after the spec is merged. > >> Regarding the spec, the note about the counter value not being modified >> unless SBI_PMU_START_SET_INIT_VALUE is set should be modified to state >> unless either of the two flags are set (so I think we need another spec >> PR). >> >> (The same flags checking/specifying comments apply to the other functions >> with flags too.) >> > > Noted (https://github.com/riscv-non-isa/riscv-sbi-doc/issues/146). > >>> >>> if (kvm_pmu_validate_counter_mask(kvpmu, ctr_base, ctr_mask) < 0) { >>> sbiret = SBI_ERR_INVALID_PARAM; >>> goto out; >>> } >>> >>> + if (snap_flag_set && kvpmu->snapshot_addr == INVALID_GPA) { >>> + sbiret = SBI_ERR_NO_SHMEM; >>> + goto out; >>> + } >>> + >>> /* Start the counters that have been configured and requested by the guest */ >>> for_each_set_bit(i, &ctr_mask, RISCV_MAX_COUNTERS) { >>> pmc_index = i + ctr_base; >>> if (!test_bit(pmc_index, kvpmu->pmc_in_use)) >>> continue; >>> pmc = &kvpmu->pmc[pmc_index]; >>> - if (flags & SBI_PMU_START_FLAG_SET_INIT_VALUE) >>> + if (flags & SBI_PMU_START_FLAG_SET_INIT_VALUE) { >>> pmc->counter_val = ival; >>> + } else if (snap_flag_set) { >>> + kvm_vcpu_read_guest(vcpu, kvpmu->snapshot_addr, kvpmu->sdata, >>> + sizeof(struct riscv_pmu_snapshot_data)); >> >> The snapshot read should be outside the for_each_set_bit() loop and we >> should warn and abort the counter starting if the read fails. >> > > Fixed. This should also fall under the SBI_ERR_FAILURE category. > >>> + /* The counter index in the snapshot are relative to the counter base */ >>> + pmc->counter_val = kvpmu->sdata->ctr_values[i]; >>> + } >>> + >>> if (pmc->cinfo.type == SBI_PMU_CTR_TYPE_FW) { >>> fevent_code = get_event_code(pmc->event_idx); >>> if (fevent_code >= SBI_PMU_FW_MAX) { >>> @@ -398,14 +486,21 @@ int kvm_riscv_vcpu_pmu_ctr_stop(struct kvm_vcpu *vcpu, unsigned long ctr_base, >>> { >>> struct kvm_pmu *kvpmu = vcpu_to_pmu(vcpu); >>> int i, pmc_index, sbiret = 0; >>> + u64 enabled, running; >>> struct kvm_pmc *pmc; >>> int fevent_code; >>> + bool snap_flag_set = flags & SBI_PMU_STOP_FLAG_TAKE_SNAPSHOT; >>> >>> - if (kvm_pmu_validate_counter_mask(kvpmu, ctr_base, ctr_mask) < 0) { >>> + if ((kvm_pmu_validate_counter_mask(kvpmu, ctr_base, ctr_mask) < 0)) { >> >> Added unnecessary () here. >> > > Fixed. > >>> sbiret = SBI_ERR_INVALID_PARAM; >>> goto out; >>> } >>> >>> + if (snap_flag_set && kvpmu->snapshot_addr == INVALID_GPA) { >>> + sbiret = SBI_ERR_NO_SHMEM; >>> + goto out; >>> + } >>> + >>> /* Stop the counters that have been configured and requested by the guest */ >>> for_each_set_bit(i, &ctr_mask, RISCV_MAX_COUNTERS) { >>> pmc_index = i + ctr_base; >>> @@ -438,9 +533,28 @@ int kvm_riscv_vcpu_pmu_ctr_stop(struct kvm_vcpu *vcpu, unsigned long ctr_base, >>> } else { >>> sbiret = SBI_ERR_INVALID_PARAM; >>> } >>> + >>> + if (snap_flag_set && !sbiret) { >>> + if (pmc->cinfo.type == SBI_PMU_CTR_TYPE_FW) >>> + pmc->counter_val = kvpmu->fw_event[fevent_code].value; >>> + else if (pmc->perf_event) >>> + pmc->counter_val += perf_event_read_value(pmc->perf_event, >>> + &enabled, &running); >>> + /* TODO: Add counter overflow support when sscofpmf support is added */ >>> + kvpmu->sdata->ctr_values[i] = pmc->counter_val; >>> + kvm_vcpu_write_guest(vcpu, kvpmu->snapshot_addr, kvpmu->sdata, >>> + sizeof(struct riscv_pmu_snapshot_data)); >> >> Should just set a boolean here saying that the snapshot needs an update >> and then do the update outside the for_each_set_bit loop. >> > > Done. > >>> + } >>> + >>> if (flags & SBI_PMU_STOP_FLAG_RESET) { >>> pmc->event_idx = SBI_PMU_EVENT_IDX_INVALID; >>> clear_bit(pmc_index, kvpmu->pmc_in_use); >>> + if (snap_flag_set) { >>> + /* Clear the snapshot area for the upcoming deletion event */ >>> + kvpmu->sdata->ctr_values[i] = 0; >>> + kvm_vcpu_write_guest(vcpu, kvpmu->snapshot_addr, kvpmu->sdata, >>> + sizeof(struct riscv_pmu_snapshot_data)); >> >> The spec isn't clear on this (so we should clarify it), but I'd expect >> that a caller who set both the reset and the snapshot flag would want >> the snapshot from before the reset when this call completes and then >> assume that when they start counting again, and look at the snapshot >> again, that those new counts would be from the reset values. Or maybe >> not :-) Maybe they want to do a reset and take a snapshot in order to >> look at the snapshot and confirm the reset happened? Either way, it >> seems we should only do one of the two here. Either update the snapshot >> before resetting, and not again after reset, or reset and then update >> the snapshot (with no need to update before). >> > > The reset call should happen when the event is deleted by the perf > framework in supervisor. > If we don't clear the values, the shared memory may have stale data of > last read counters > which is not ideal. That's why, I am clearing it upon resetting. Thinking about it more, I think having stale values in the shared memory would be similar expected behavior to hardware counters after reset. We don't need to clear the shared memory during the reset. If both SBI_PMU_STOP_FLAG_TAKE_SNAPSHOT and SBI_PMU_STOP_FLAG_RESET are set, may be we should just write it to the shared memory again without assuming the intention of the caller ? > The actual counter value should be read while stopping the counters. > > I thought the current description is clear enough as it says > > "SBI_PMU_STOP_FLAG_RESET - Reset the counter to event mapping." > > Do you feel we should be more explicit about this ? > >>> + } >>> } >>> } >>> >>> @@ -566,6 +680,7 @@ void kvm_riscv_vcpu_pmu_init(struct kvm_vcpu *vcpu) >>> kvpmu->num_hw_ctrs = num_hw_ctrs + 1; >>> kvpmu->num_fw_ctrs = SBI_PMU_FW_MAX; >>> memset(&kvpmu->fw_event, 0, SBI_PMU_FW_MAX * sizeof(struct kvm_fw_event)); >>> + kvpmu->snapshot_addr = INVALID_GPA; >>> >>> if (kvpmu->num_hw_ctrs > RISCV_KVM_MAX_HW_CTRS) { >>> pr_warn_once("Limiting the hardware counters to 32 as specified by the ISA"); >>> @@ -625,6 +740,7 @@ void kvm_riscv_vcpu_pmu_deinit(struct kvm_vcpu *vcpu) >>> } >>> bitmap_zero(kvpmu->pmc_in_use, RISCV_MAX_COUNTERS); >>> memset(&kvpmu->fw_event, 0, SBI_PMU_FW_MAX * sizeof(struct kvm_fw_event)); >>> + kvm_pmu_clear_snapshot_area(vcpu); >>> } >>> >>> void kvm_riscv_vcpu_pmu_reset(struct kvm_vcpu *vcpu) >>> diff --git a/arch/riscv/kvm/vcpu_sbi_pmu.c b/arch/riscv/kvm/vcpu_sbi_pmu.c >>> index b70179e9e875..9f61136e4bb1 100644 >>> --- a/arch/riscv/kvm/vcpu_sbi_pmu.c >>> +++ b/arch/riscv/kvm/vcpu_sbi_pmu.c >>> @@ -64,6 +64,9 @@ static int kvm_sbi_ext_pmu_handler(struct kvm_vcpu *vcpu, struct kvm_run *run, >>> case SBI_EXT_PMU_COUNTER_FW_READ: >>> ret = kvm_riscv_vcpu_pmu_ctr_read(vcpu, cp->a0, retdata); >>> break; >>> + case SBI_EXT_PMU_SNAPSHOT_SET_SHMEM: >>> + ret = kvm_riscv_vcpu_pmu_setup_snapshot(vcpu, cp->a0, cp->a1, cp->a2, retdata); >>> + break; >>> default: >>> retdata->err_val = SBI_ERR_NOT_SUPPORTED; >>> } >>> diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c >>> index 8de5721e8019..1a22ce1ff8c8 100644 >>> --- a/drivers/perf/riscv_pmu_sbi.c >>> +++ b/drivers/perf/riscv_pmu_sbi.c >>> @@ -802,7 +802,7 @@ static noinline void pmu_sbi_start_ovf_ctrs_snapshot(struct cpu_hw_events *cpu_h >>> struct riscv_pmu_snapshot_data *sdata = cpu_hw_evt->snapshot_addr; >>> >>> for_each_set_bit(idx, cpu_hw_evt->used_hw_ctrs, RISCV_MAX_COUNTERS) { >>> - if (ctr_ovf_mask & (1 << idx)) { >>> + if (ctr_ovf_mask & (BIT(idx))) { >>> event = cpu_hw_evt->events[idx]; >>> hwc = &event->hw; >>> max_period = riscv_pmu_ctr_get_width_mask(event); >>> -- >>> 2.34.1 >>> >> >> Thanks, >> drew > > > From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f181.google.com (mail-pl1-f181.google.com [209.85.214.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 533205D737 for ; Wed, 3 Apr 2024 07:36:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.181 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712129808; cv=none; b=aEuLTiiP2lwKanBO97tpguVl5mqW6psc0Zf+xtVKpNTHtWR/Ov4Wud1cRQnpp2+wsaJKr2rnVlInRZFzLlDlDZBJ0ANJius3dFiHBq6AXOYuLw1ggX7d7HrdLcFiQ06XX+iOfUNOmejUlbmGMHr/gju2/V8094v4qelTTlvoZe0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712129808; c=relaxed/simple; bh=N12r8/H2ZijzxzI5R47jV6U/5E389Ca2qn74O6uFp5Y=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=JB6VwxApS6P4CKQ81oQjGC54Jhr1OqXyxEFKRClmh1DXRIqUu4g9Pgmk5TkWoZB14fsW9RRqZ9Cu5NpVNq/aDB4hphfOZ+JGbgGJ1peMnkF2KRLT9vjhgTl7tJ/JqULqpbCyR3YCWOWahsWcIO4ImhcKngiTNkmczeIOh1VAKjA= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rivosinc.com; spf=pass smtp.mailfrom=rivosinc.com; dkim=pass (2048-bit key) header.d=rivosinc-com.20230601.gappssmtp.com header.i=@rivosinc-com.20230601.gappssmtp.com header.b=mRIdH7tr; arc=none smtp.client-ip=209.85.214.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rivosinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rivosinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rivosinc-com.20230601.gappssmtp.com header.i=@rivosinc-com.20230601.gappssmtp.com header.b="mRIdH7tr" Received: by mail-pl1-f181.google.com with SMTP id d9443c01a7336-1e2987e9d67so906425ad.1 for ; Wed, 03 Apr 2024 00:36:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rivosinc-com.20230601.gappssmtp.com; s=20230601; t=1712129805; x=1712734605; darn=vger.kernel.org; h=content-transfer-encoding:in-reply-to:from:references:cc:to :content-language:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=IQpzZArlGfJYBuSfWBUhzl7YP9oA2MCeqdxxTvwKJ6o=; b=mRIdH7trmqLXO80rXn+tiE+ESXOBWk6XCK1jvOcYlg4+XsYFehsAgB0cNWxB0/lEKe bVxB5caWMC3XwvEnW67bhSCMQKQ7n0WygzxWstwmUrzMacFs/LYUKzDzvxq+KY6uGG47 aIaR7TgNE3h6Sf1t77zgg/sZ6YyjtRfw3q0ZWXAWjTAwgjfnAM3xUkA9GA6l9koPVTax zrsRPp+T1KVKB2s7dceV9UNNXqrq0vPdRFQxYYWNQucobcYTE6m6KLk0tAzgz1cS8VdA LvdVAPXTkCJDuBRl+kZ5tQpVL4xS2Ysk2n7yk6qvexH9oZ/7WkmjceE780L33hwLpVuh hSFg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712129805; x=1712734605; h=content-transfer-encoding:in-reply-to:from:references:cc:to :content-language:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=IQpzZArlGfJYBuSfWBUhzl7YP9oA2MCeqdxxTvwKJ6o=; b=k7RzGsaGv1WN/il8CcyDw6VuNN9ed3ha1+oXyMDtVBGDv5bemnOP+b8xQ9zECC5wr/ aUsVtoagtv06wQhXtw+pQAX9L8j6SFFrnZElqOTzGUQeU2dElUIEZXgD8JMZgD9xsbH5 JKC1O+VTianPl+m7dBk0jllUCDqKq5KV6Q5kljm3IX1L1bMRqQs5E6sJLc5MdiO38iOi vOzQTl/n3XAOm26E6kKhk5uUYpx3CEO9QBYFYhy4gPwV1vqsyHYK2o/K82AQHrUG2rJQ zIMynqV04WbzF/nS8NM5pow1f+wE/ym8G9CBZRJCedFlem/sGmk68gPzt5e3SZqwAhIk HTzg== X-Forwarded-Encrypted: i=1; AJvYcCVxUk8kLw/x8aL4/RcLI1QWk+ohAt37hcU/dFIM2Q4rohKoxdq23r45V5oHD+UjEUIKlBm3L3cSmKw1gwj9IiMysCKVh4rO/cFaXCiKHbQh X-Gm-Message-State: AOJu0YxDhclYHd3H9KeJEsMZHGN3J8RzyiPbdM+7GRfk7ywp4SN4NblY KoYhTMGSKcqccD4po5KsrwGSB8KYuJH0m7OQy8jtc5oZFBwUaOWBFnnVyrgXh7o= X-Google-Smtp-Source: AGHT+IGQfpT5TIhYfq9vwX/P51mdnd9ta2F0BiVCWL7etleJQIhV4I+MyTUSgLsbE8QKwJSMbVGPKg== X-Received: by 2002:a17:903:1c1:b0:1e0:188c:ad4f with SMTP id e1-20020a17090301c100b001e0188cad4fmr2405697plh.26.1712129804531; Wed, 03 Apr 2024 00:36:44 -0700 (PDT) Received: from ?IPV6:2601:647:4180:9630::406? ([2601:647:4180:9630::406]) by smtp.gmail.com with ESMTPSA id u4-20020a17090341c400b001e2967ec100sm587265ple.58.2024.04.03.00.36.42 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 03 Apr 2024 00:36:44 -0700 (PDT) Message-ID: Date: Wed, 3 Apr 2024 00:36:41 -0700 Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v4 08/15] RISC-V: KVM: Implement SBI PMU Snapshot feature Content-Language: en-US To: Atish Patra , Andrew Jones Cc: linux-kernel@vger.kernel.org, Anup Patel , Albert Ou , Alexandre Ghiti , Conor Dooley , Guo Ren , Icenowy Zheng , kvm-riscv@lists.infradead.org, kvm@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-riscv@lists.infradead.org, Mark Rutland , Palmer Dabbelt , Paolo Bonzini , Paul Walmsley , Shuah Khan , Will Deacon References: <20240229010130.1380926-1-atishp@rivosinc.com> <20240229010130.1380926-9-atishp@rivosinc.com> <20240302-6ae8fe37b90f127bc9be737f@orel> From: Atish Patra In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit On 4/1/24 15:36, Atish Patra wrote: > On Sat, Mar 2, 2024 at 1:49 AM Andrew Jones wrote: >> >> On Wed, Feb 28, 2024 at 05:01:23PM -0800, Atish Patra wrote: >>> PMU Snapshot function allows to minimize the number of traps when the >>> guest access configures/access the hpmcounters. If the snapshot feature >>> is enabled, the hypervisor updates the shared memory with counter >>> data and state of overflown counters. The guest can just read the >>> shared memory instead of trap & emulate done by the hypervisor. >>> >>> This patch doesn't implement the counter overflow yet. >>> >>> Reviewed-by: Anup Patel >>> Signed-off-by: Atish Patra >>> --- >>> arch/riscv/include/asm/kvm_vcpu_pmu.h | 7 ++ >>> arch/riscv/kvm/vcpu_pmu.c | 120 +++++++++++++++++++++++++- >>> arch/riscv/kvm/vcpu_sbi_pmu.c | 3 + >>> drivers/perf/riscv_pmu_sbi.c | 2 +- >>> 4 files changed, 129 insertions(+), 3 deletions(-) >>> >>> diff --git a/arch/riscv/include/asm/kvm_vcpu_pmu.h b/arch/riscv/include/asm/kvm_vcpu_pmu.h >>> index 395518a1664e..586bab84be35 100644 >>> --- a/arch/riscv/include/asm/kvm_vcpu_pmu.h >>> +++ b/arch/riscv/include/asm/kvm_vcpu_pmu.h >>> @@ -50,6 +50,10 @@ struct kvm_pmu { >>> bool init_done; >>> /* Bit map of all the virtual counter used */ >>> DECLARE_BITMAP(pmc_in_use, RISCV_KVM_MAX_COUNTERS); >>> + /* The address of the counter snapshot area (guest physical address) */ >>> + gpa_t snapshot_addr; >>> + /* The actual data of the snapshot */ >>> + struct riscv_pmu_snapshot_data *sdata; >>> }; >>> >>> #define vcpu_to_pmu(vcpu) (&(vcpu)->arch.pmu_context) >>> @@ -85,6 +89,9 @@ int kvm_riscv_vcpu_pmu_ctr_cfg_match(struct kvm_vcpu *vcpu, unsigned long ctr_ba >>> int kvm_riscv_vcpu_pmu_ctr_read(struct kvm_vcpu *vcpu, unsigned long cidx, >>> struct kvm_vcpu_sbi_return *retdata); >>> void kvm_riscv_vcpu_pmu_init(struct kvm_vcpu *vcpu); >>> +int kvm_riscv_vcpu_pmu_setup_snapshot(struct kvm_vcpu *vcpu, unsigned long saddr_low, >>> + unsigned long saddr_high, unsigned long flags, >>> + struct kvm_vcpu_sbi_return *retdata); >> >> I prefer to name this function >> >> kvm_riscv_vcpu_pmu_snapshot_set_shmem >> > > Sure. > >>> void kvm_riscv_vcpu_pmu_deinit(struct kvm_vcpu *vcpu); >>> void kvm_riscv_vcpu_pmu_reset(struct kvm_vcpu *vcpu); >>> >>> diff --git a/arch/riscv/kvm/vcpu_pmu.c b/arch/riscv/kvm/vcpu_pmu.c >>> index 29bf4ca798cb..74865e6050a1 100644 >>> --- a/arch/riscv/kvm/vcpu_pmu.c >>> +++ b/arch/riscv/kvm/vcpu_pmu.c >>> @@ -311,6 +311,81 @@ int kvm_riscv_vcpu_pmu_read_hpm(struct kvm_vcpu *vcpu, unsigned int csr_num, >>> return ret; >>> } >>> >>> +static void kvm_pmu_clear_snapshot_area(struct kvm_vcpu *vcpu) >>> +{ >>> + struct kvm_pmu *kvpmu = vcpu_to_pmu(vcpu); >>> + int snapshot_area_size = sizeof(struct riscv_pmu_snapshot_data); >>> + >>> + if (kvpmu->sdata) { >>> + memset(kvpmu->sdata, 0, snapshot_area_size); >>> + if (kvpmu->snapshot_addr != INVALID_GPA) >> >> It's a KVM bug if we have non-null sdata but snapshot_addr is INVALID_GPA, >> right? Maybe we should warn if we see that. We can also move the memset >> inside the if block. >> > > Added a warning. > >>> + kvm_vcpu_write_guest(vcpu, kvpmu->snapshot_addr, >>> + kvpmu->sdata, snapshot_area_size); >>> + kfree(kvpmu->sdata); >>> + kvpmu->sdata = NULL; >>> + } >>> + kvpmu->snapshot_addr = INVALID_GPA; >>> +} >>> + >>> +int kvm_riscv_vcpu_pmu_setup_snapshot(struct kvm_vcpu *vcpu, unsigned long saddr_low, >>> + unsigned long saddr_high, unsigned long flags, >>> + struct kvm_vcpu_sbi_return *retdata) >>> +{ >>> + struct kvm_pmu *kvpmu = vcpu_to_pmu(vcpu); >>> + int snapshot_area_size = sizeof(struct riscv_pmu_snapshot_data); >>> + int sbiret = 0; >>> + gpa_t saddr; >>> + unsigned long hva; >>> + bool writable; >>> + >>> + if (!kvpmu) { >>> + sbiret = SBI_ERR_INVALID_PARAM; >>> + goto out; >>> + } >> >> Need to check that flags is zero or return SBI_ERR_INVALID_PARAM. >> > > Fixed. > >>> + >>> + if (saddr_low == -1 && saddr_high == -1) { >> >> We introduced SBI_STA_SHMEM_DISABLE for these magic -1's for STA. Since >> SBI is using the -1 approach for all its shmem, then maybe we should >> rename SBI_STA_SHMEM_DISABLE to SBI_SHMEM_DISABLE and then use them here >> too. >> > > Fixed > >>> + kvm_pmu_clear_snapshot_area(vcpu); >>> + return 0; >>> + } >>> + >>> + saddr = saddr_low; >>> + >>> + if (saddr_high != 0) { >>> + if (IS_ENABLED(CONFIG_32BIT)) >>> + saddr |= ((gpa_t)saddr << 32); >>> + else >>> + sbiret = SBI_ERR_INVALID_ADDRESS; >>> + goto out; >>> + } >>> + >>> + if (kvm_is_error_gpa(vcpu->kvm, saddr)) { >>> + sbiret = SBI_ERR_INVALID_PARAM; >>> + goto out; >>> + } >> >> Does the check above provide anything more than what the check below does? >> > You are correct. I have removed the check > >>> + >>> + hva = kvm_vcpu_gfn_to_hva_prot(vcpu, saddr >> PAGE_SHIFT, &writable); >>> + if (kvm_is_error_hva(hva) || !writable) { >>> + sbiret = SBI_ERR_INVALID_ADDRESS; >>> + goto out; >>> + } >>> + >>> + kvpmu->snapshot_addr = saddr; >>> + kvpmu->sdata = kzalloc(snapshot_area_size, GFP_ATOMIC); >>> + if (!kvpmu->sdata) >> >> Should reset snapshot_addr to INVALID_GPA here on error. Or maybe we >> should just set snapshot_addr to saddr at the bottom of this function if >> we make it. >> > > Done. > >>> + return -ENOMEM; >>> + >>> + if (kvm_vcpu_write_guest(vcpu, saddr, kvpmu->sdata, snapshot_area_size)) { >>> + kfree(kvpmu->sdata); >>> + kvpmu->snapshot_addr = INVALID_GPA; >>> + sbiret = SBI_ERR_FAILURE; >> >> I agree we should return this SBI error for this case, but unfortunately >> the spec is missing the >> >> SBI_ERR_FAILED - The request failed for unspecified or unknown other reasons. >> >> that we have for other SBI functions. I guess we should keep the code like >> this and open a PR to the spec. >> > > I have created a blanket github issue for now. I will send a PR. > >>> + } >>> + >>> +out: >>> + retdata->err_val = sbiret; >>> + >>> + return 0; >>> +} >>> + >>> int kvm_riscv_vcpu_pmu_num_ctrs(struct kvm_vcpu *vcpu, >>> struct kvm_vcpu_sbi_return *retdata) >>> { >>> @@ -344,20 +419,33 @@ int kvm_riscv_vcpu_pmu_ctr_start(struct kvm_vcpu *vcpu, unsigned long ctr_base, >>> int i, pmc_index, sbiret = 0; >>> struct kvm_pmc *pmc; >>> int fevent_code; >>> + bool snap_flag_set = flags & SBI_PMU_START_FLAG_INIT_FROM_SNAPSHOT; >> >> This function should confirm no undefined bits are set in flags and the >> spec should specify that the reserved flags must be zero otherwise an >> invalid param will be returned. >> >> Also here would should confirm that only one of the two flags is set, >> otherwise return invalid param, as they've specified to be mutually >> exclusive. >> > > That makes sense. Update the same github issue. > (https://github.com/riscv-non-isa/riscv-sbi-doc/issues/145) > > I will make the necessary changes in a separate series after the spec is merged. > >> Regarding the spec, the note about the counter value not being modified >> unless SBI_PMU_START_SET_INIT_VALUE is set should be modified to state >> unless either of the two flags are set (so I think we need another spec >> PR). >> >> (The same flags checking/specifying comments apply to the other functions >> with flags too.) >> > > Noted (https://github.com/riscv-non-isa/riscv-sbi-doc/issues/146). > >>> >>> if (kvm_pmu_validate_counter_mask(kvpmu, ctr_base, ctr_mask) < 0) { >>> sbiret = SBI_ERR_INVALID_PARAM; >>> goto out; >>> } >>> >>> + if (snap_flag_set && kvpmu->snapshot_addr == INVALID_GPA) { >>> + sbiret = SBI_ERR_NO_SHMEM; >>> + goto out; >>> + } >>> + >>> /* Start the counters that have been configured and requested by the guest */ >>> for_each_set_bit(i, &ctr_mask, RISCV_MAX_COUNTERS) { >>> pmc_index = i + ctr_base; >>> if (!test_bit(pmc_index, kvpmu->pmc_in_use)) >>> continue; >>> pmc = &kvpmu->pmc[pmc_index]; >>> - if (flags & SBI_PMU_START_FLAG_SET_INIT_VALUE) >>> + if (flags & SBI_PMU_START_FLAG_SET_INIT_VALUE) { >>> pmc->counter_val = ival; >>> + } else if (snap_flag_set) { >>> + kvm_vcpu_read_guest(vcpu, kvpmu->snapshot_addr, kvpmu->sdata, >>> + sizeof(struct riscv_pmu_snapshot_data)); >> >> The snapshot read should be outside the for_each_set_bit() loop and we >> should warn and abort the counter starting if the read fails. >> > > Fixed. This should also fall under the SBI_ERR_FAILURE category. > >>> + /* The counter index in the snapshot are relative to the counter base */ >>> + pmc->counter_val = kvpmu->sdata->ctr_values[i]; >>> + } >>> + >>> if (pmc->cinfo.type == SBI_PMU_CTR_TYPE_FW) { >>> fevent_code = get_event_code(pmc->event_idx); >>> if (fevent_code >= SBI_PMU_FW_MAX) { >>> @@ -398,14 +486,21 @@ int kvm_riscv_vcpu_pmu_ctr_stop(struct kvm_vcpu *vcpu, unsigned long ctr_base, >>> { >>> struct kvm_pmu *kvpmu = vcpu_to_pmu(vcpu); >>> int i, pmc_index, sbiret = 0; >>> + u64 enabled, running; >>> struct kvm_pmc *pmc; >>> int fevent_code; >>> + bool snap_flag_set = flags & SBI_PMU_STOP_FLAG_TAKE_SNAPSHOT; >>> >>> - if (kvm_pmu_validate_counter_mask(kvpmu, ctr_base, ctr_mask) < 0) { >>> + if ((kvm_pmu_validate_counter_mask(kvpmu, ctr_base, ctr_mask) < 0)) { >> >> Added unnecessary () here. >> > > Fixed. > >>> sbiret = SBI_ERR_INVALID_PARAM; >>> goto out; >>> } >>> >>> + if (snap_flag_set && kvpmu->snapshot_addr == INVALID_GPA) { >>> + sbiret = SBI_ERR_NO_SHMEM; >>> + goto out; >>> + } >>> + >>> /* Stop the counters that have been configured and requested by the guest */ >>> for_each_set_bit(i, &ctr_mask, RISCV_MAX_COUNTERS) { >>> pmc_index = i + ctr_base; >>> @@ -438,9 +533,28 @@ int kvm_riscv_vcpu_pmu_ctr_stop(struct kvm_vcpu *vcpu, unsigned long ctr_base, >>> } else { >>> sbiret = SBI_ERR_INVALID_PARAM; >>> } >>> + >>> + if (snap_flag_set && !sbiret) { >>> + if (pmc->cinfo.type == SBI_PMU_CTR_TYPE_FW) >>> + pmc->counter_val = kvpmu->fw_event[fevent_code].value; >>> + else if (pmc->perf_event) >>> + pmc->counter_val += perf_event_read_value(pmc->perf_event, >>> + &enabled, &running); >>> + /* TODO: Add counter overflow support when sscofpmf support is added */ >>> + kvpmu->sdata->ctr_values[i] = pmc->counter_val; >>> + kvm_vcpu_write_guest(vcpu, kvpmu->snapshot_addr, kvpmu->sdata, >>> + sizeof(struct riscv_pmu_snapshot_data)); >> >> Should just set a boolean here saying that the snapshot needs an update >> and then do the update outside the for_each_set_bit loop. >> > > Done. > >>> + } >>> + >>> if (flags & SBI_PMU_STOP_FLAG_RESET) { >>> pmc->event_idx = SBI_PMU_EVENT_IDX_INVALID; >>> clear_bit(pmc_index, kvpmu->pmc_in_use); >>> + if (snap_flag_set) { >>> + /* Clear the snapshot area for the upcoming deletion event */ >>> + kvpmu->sdata->ctr_values[i] = 0; >>> + kvm_vcpu_write_guest(vcpu, kvpmu->snapshot_addr, kvpmu->sdata, >>> + sizeof(struct riscv_pmu_snapshot_data)); >> >> The spec isn't clear on this (so we should clarify it), but I'd expect >> that a caller who set both the reset and the snapshot flag would want >> the snapshot from before the reset when this call completes and then >> assume that when they start counting again, and look at the snapshot >> again, that those new counts would be from the reset values. Or maybe >> not :-) Maybe they want to do a reset and take a snapshot in order to >> look at the snapshot and confirm the reset happened? Either way, it >> seems we should only do one of the two here. Either update the snapshot >> before resetting, and not again after reset, or reset and then update >> the snapshot (with no need to update before). >> > > The reset call should happen when the event is deleted by the perf > framework in supervisor. > If we don't clear the values, the shared memory may have stale data of > last read counters > which is not ideal. That's why, I am clearing it upon resetting. Thinking about it more, I think having stale values in the shared memory would be similar expected behavior to hardware counters after reset. We don't need to clear the shared memory during the reset. If both SBI_PMU_STOP_FLAG_TAKE_SNAPSHOT and SBI_PMU_STOP_FLAG_RESET are set, may be we should just write it to the shared memory again without assuming the intention of the caller ? > The actual counter value should be read while stopping the counters. > > I thought the current description is clear enough as it says > > "SBI_PMU_STOP_FLAG_RESET - Reset the counter to event mapping." > > Do you feel we should be more explicit about this ? > >>> + } >>> } >>> } >>> >>> @@ -566,6 +680,7 @@ void kvm_riscv_vcpu_pmu_init(struct kvm_vcpu *vcpu) >>> kvpmu->num_hw_ctrs = num_hw_ctrs + 1; >>> kvpmu->num_fw_ctrs = SBI_PMU_FW_MAX; >>> memset(&kvpmu->fw_event, 0, SBI_PMU_FW_MAX * sizeof(struct kvm_fw_event)); >>> + kvpmu->snapshot_addr = INVALID_GPA; >>> >>> if (kvpmu->num_hw_ctrs > RISCV_KVM_MAX_HW_CTRS) { >>> pr_warn_once("Limiting the hardware counters to 32 as specified by the ISA"); >>> @@ -625,6 +740,7 @@ void kvm_riscv_vcpu_pmu_deinit(struct kvm_vcpu *vcpu) >>> } >>> bitmap_zero(kvpmu->pmc_in_use, RISCV_MAX_COUNTERS); >>> memset(&kvpmu->fw_event, 0, SBI_PMU_FW_MAX * sizeof(struct kvm_fw_event)); >>> + kvm_pmu_clear_snapshot_area(vcpu); >>> } >>> >>> void kvm_riscv_vcpu_pmu_reset(struct kvm_vcpu *vcpu) >>> diff --git a/arch/riscv/kvm/vcpu_sbi_pmu.c b/arch/riscv/kvm/vcpu_sbi_pmu.c >>> index b70179e9e875..9f61136e4bb1 100644 >>> --- a/arch/riscv/kvm/vcpu_sbi_pmu.c >>> +++ b/arch/riscv/kvm/vcpu_sbi_pmu.c >>> @@ -64,6 +64,9 @@ static int kvm_sbi_ext_pmu_handler(struct kvm_vcpu *vcpu, struct kvm_run *run, >>> case SBI_EXT_PMU_COUNTER_FW_READ: >>> ret = kvm_riscv_vcpu_pmu_ctr_read(vcpu, cp->a0, retdata); >>> break; >>> + case SBI_EXT_PMU_SNAPSHOT_SET_SHMEM: >>> + ret = kvm_riscv_vcpu_pmu_setup_snapshot(vcpu, cp->a0, cp->a1, cp->a2, retdata); >>> + break; >>> default: >>> retdata->err_val = SBI_ERR_NOT_SUPPORTED; >>> } >>> diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c >>> index 8de5721e8019..1a22ce1ff8c8 100644 >>> --- a/drivers/perf/riscv_pmu_sbi.c >>> +++ b/drivers/perf/riscv_pmu_sbi.c >>> @@ -802,7 +802,7 @@ static noinline void pmu_sbi_start_ovf_ctrs_snapshot(struct cpu_hw_events *cpu_h >>> struct riscv_pmu_snapshot_data *sdata = cpu_hw_evt->snapshot_addr; >>> >>> for_each_set_bit(idx, cpu_hw_evt->used_hw_ctrs, RISCV_MAX_COUNTERS) { >>> - if (ctr_ovf_mask & (1 << idx)) { >>> + if (ctr_ovf_mask & (BIT(idx))) { >>> event = cpu_hw_evt->events[idx]; >>> hwc = &event->hw; >>> max_period = riscv_pmu_ctr_get_width_mask(event); >>> -- >>> 2.34.1 >>> >> >> Thanks, >> drew > > > 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 516F6C6FD1F for ; Wed, 3 Apr 2024 07:37:04 +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-Type: Content-Transfer-Encoding:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:In-Reply-To:From:References:To:Subject:MIME-Version: Date:Message-ID:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=6ikQVMw67LLm2yi4MMchHQYyRPLoaYoj0sAeezC7jMg=; b=egI+3Fz6jt74KqhUDt8m7xt50I KxtnkWKalhQKtOkw1n9Oy2m5A38wd+5EoQrkRScsJdt9AEIG9bTzjIxUKYXJdD81N566hNbjd6pP+ PAlkTqJ2BIiv/5LrFcs+J/ChDserNdVe6FlvSsPDWyhbKDntFy0jWF63Yj8Xq1KecJHqyAqtDQrLw 1Y4jVLQBM+8QEd9Vk1JvExFlcZcj+K4NeuKF4jMD67dXPerV6F/51uyCQ0Ty49aI7rbvfH/QX5zV4 E1en/wIEulf1DwgXGZhu2fFvZsw3lqIjT+FL5ZzmGkkrFmJCiEboFVxvFO/nMTaq//qS/GGIbDg+c 1dIgXMRA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rrvB3-0000000EYwf-3YUy; Wed, 03 Apr 2024 07:36:57 +0000 Received: from mail-pl1-x630.google.com ([2607:f8b0:4864:20::630]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rrvAy-0000000EYps-3k0y for linux-riscv@lists.infradead.org; Wed, 03 Apr 2024 07:36:55 +0000 Received: by mail-pl1-x630.google.com with SMTP id d9443c01a7336-1e267238375so4875825ad.1 for ; Wed, 03 Apr 2024 00:36:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rivosinc-com.20230601.gappssmtp.com; s=20230601; t=1712129805; x=1712734605; darn=lists.infradead.org; h=content-transfer-encoding:in-reply-to:from:references:cc:to :content-language:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=IQpzZArlGfJYBuSfWBUhzl7YP9oA2MCeqdxxTvwKJ6o=; b=15wvPegv2UA88hZUULfBB9xS9PbBsELvn/34k1PHdXSMCgmER//I6bHMD0t6oOyeaN zyC+W7g4t9PrD+HOCr7ULsff/bTQ41G4SwaTFu1nfDqEBC5dfQt6VVUWvKsrmPu7dH8I kW0wj6/bOb6Tprg/iVYNCbvHUgq/5fWeejADeaJBG6dDLG8urMo33zxmSNAVJKEEjXEt jZeH7T96NqD1HayeiIV10VwKwlSLlEzCXbSBE09YvkCyuFq42mWU+osQMOWh5gU/29yU RhmEMtDP5qkaE7iYej73GAmsNqSfIgk8Bxv3XkVv7AedpDQ3NhzX5m67CbG1TD4XTeBs jzlg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712129805; x=1712734605; h=content-transfer-encoding:in-reply-to:from:references:cc:to :content-language:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=IQpzZArlGfJYBuSfWBUhzl7YP9oA2MCeqdxxTvwKJ6o=; b=D00G3nT5a1z3EE9zxAZI3pVTKTsmN9WmGfsCZfx1mU4RS9qNSa9YaJD4rLk7lVTx5X NW4kq3LVNYg6mVemwss3GXOATnzSE2aI7VUtIE7LruFbIdu+BDqtE9s61r3myDAyZKwD HJPYAVv9ZEbBksU9UAExO6s8XJv2BXO18H5u72iavH+UJaCl1czT4YnGK049J1nZy/ps L/Us0matYypYRl2rbtE0oXHnlggUEWBgHwe2hhsYujwZm7F0OSPrH1FnKd46t71T9U/I 4k77Jp1MjeuV0Zdc1vZu7vhn6ZuXogKsXvNI6V61clWXGpFEGEp/Y5Py96CNShgJArXV e0sA== X-Forwarded-Encrypted: i=1; AJvYcCWGtRmv9C63QGoRJ4fpCwjPEXtQvbWYeoQ7Mvz9EKbSAygcc59Tlfs6g0IMKjgUgDyW5O2DR0/SKp5JqtiAoyuPyyTsr3SFxwrPYEyz0GPx X-Gm-Message-State: AOJu0YwlKrZmsvtGbjbMkLEzfrMsat5mYKn8IpMYY+mf3xzO5VJq+3Jn JT1iuhH5RGA2zMGbm095s81Sb2o5XxJmbxoUzLjDpvKX/fj3a8JhsVbzGkMx8QQ= X-Google-Smtp-Source: AGHT+IGQfpT5TIhYfq9vwX/P51mdnd9ta2F0BiVCWL7etleJQIhV4I+MyTUSgLsbE8QKwJSMbVGPKg== X-Received: by 2002:a17:903:1c1:b0:1e0:188c:ad4f with SMTP id e1-20020a17090301c100b001e0188cad4fmr2405697plh.26.1712129804531; Wed, 03 Apr 2024 00:36:44 -0700 (PDT) Received: from ?IPV6:2601:647:4180:9630::406? ([2601:647:4180:9630::406]) by smtp.gmail.com with ESMTPSA id u4-20020a17090341c400b001e2967ec100sm587265ple.58.2024.04.03.00.36.42 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 03 Apr 2024 00:36:44 -0700 (PDT) Message-ID: Date: Wed, 3 Apr 2024 00:36:41 -0700 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v4 08/15] RISC-V: KVM: Implement SBI PMU Snapshot feature Content-Language: en-US To: Atish Patra , Andrew Jones References: <20240229010130.1380926-1-atishp@rivosinc.com> <20240229010130.1380926-9-atishp@rivosinc.com> <20240302-6ae8fe37b90f127bc9be737f@orel> From: Atish Patra In-Reply-To: X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240403_003653_477277_A5C2EC5C X-CRM114-Status: GOOD ( 39.12 ) 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: , Cc: Mark Rutland , linux-kselftest@vger.kernel.org, Albert Ou , Alexandre Ghiti , kvm@vger.kernel.org, Anup Patel , Paul Walmsley , Will Deacon , linux-kernel@vger.kernel.org, Conor Dooley , Guo Ren , kvm-riscv@lists.infradead.org, Paolo Bonzini , Palmer Dabbelt , linux-riscv@lists.infradead.org, Shuah Khan Content-Transfer-Encoding: base64 Content-Type: text/plain; charset="utf-8"; Format="flowed" Sender: "linux-riscv" Errors-To: linux-riscv-bounces+linux-riscv=archiver.kernel.org@lists.infradead.org T24gNC8xLzI0IDE1OjM2LCBBdGlzaCBQYXRyYSB3cm90ZToKPiBPbiBTYXQsIE1hciAyLCAyMDI0 IGF0IDE6NDnigK9BTSBBbmRyZXcgSm9uZXMgPGFqb25lc0B2ZW50YW5hbWljcm8uY29tPiB3cm90 ZToKPj4KPj4gT24gV2VkLCBGZWIgMjgsIDIwMjQgYXQgMDU6MDE6MjNQTSAtMDgwMCwgQXRpc2gg UGF0cmEgd3JvdGU6Cj4+PiBQTVUgU25hcHNob3QgZnVuY3Rpb24gYWxsb3dzIHRvIG1pbmltaXpl IHRoZSBudW1iZXIgb2YgdHJhcHMgd2hlbiB0aGUKPj4+IGd1ZXN0IGFjY2VzcyBjb25maWd1cmVz L2FjY2VzcyB0aGUgaHBtY291bnRlcnMuIElmIHRoZSBzbmFwc2hvdCBmZWF0dXJlCj4+PiBpcyBl bmFibGVkLCB0aGUgaHlwZXJ2aXNvciB1cGRhdGVzIHRoZSBzaGFyZWQgbWVtb3J5IHdpdGggY291 bnRlcgo+Pj4gZGF0YSBhbmQgc3RhdGUgb2Ygb3ZlcmZsb3duIGNvdW50ZXJzLiBUaGUgZ3Vlc3Qg Y2FuIGp1c3QgcmVhZCB0aGUKPj4+IHNoYXJlZCBtZW1vcnkgaW5zdGVhZCBvZiB0cmFwICYgZW11 bGF0ZSBkb25lIGJ5IHRoZSBoeXBlcnZpc29yLgo+Pj4KPj4+IFRoaXMgcGF0Y2ggZG9lc24ndCBp bXBsZW1lbnQgdGhlIGNvdW50ZXIgb3ZlcmZsb3cgeWV0Lgo+Pj4KPj4+IFJldmlld2VkLWJ5OiBB bnVwIFBhdGVsIDxhbnVwQGJyYWluZmF1bHQub3JnPgo+Pj4gU2lnbmVkLW9mZi1ieTogQXRpc2gg UGF0cmEgPGF0aXNocEByaXZvc2luYy5jb20+Cj4+PiAtLS0KPj4+ICAgYXJjaC9yaXNjdi9pbmNs dWRlL2FzbS9rdm1fdmNwdV9wbXUuaCB8ICAgNyArKwo+Pj4gICBhcmNoL3Jpc2N2L2t2bS92Y3B1 X3BtdS5jICAgICAgICAgICAgIHwgMTIwICsrKysrKysrKysrKysrKysrKysrKysrKystCj4+PiAg IGFyY2gvcmlzY3Yva3ZtL3ZjcHVfc2JpX3BtdS5jICAgICAgICAgfCAgIDMgKwo+Pj4gICBkcml2 ZXJzL3BlcmYvcmlzY3ZfcG11X3NiaS5jICAgICAgICAgIHwgICAyICstCj4+PiAgIDQgZmlsZXMg Y2hhbmdlZCwgMTI5IGluc2VydGlvbnMoKyksIDMgZGVsZXRpb25zKC0pCj4+Pgo+Pj4gZGlmZiAt LWdpdCBhL2FyY2gvcmlzY3YvaW5jbHVkZS9hc20va3ZtX3ZjcHVfcG11LmggYi9hcmNoL3Jpc2N2 L2luY2x1ZGUvYXNtL2t2bV92Y3B1X3BtdS5oCj4+PiBpbmRleCAzOTU1MThhMTY2NGUuLjU4NmJh Yjg0YmUzNSAxMDA2NDQKPj4+IC0tLSBhL2FyY2gvcmlzY3YvaW5jbHVkZS9hc20va3ZtX3ZjcHVf cG11LmgKPj4+ICsrKyBiL2FyY2gvcmlzY3YvaW5jbHVkZS9hc20va3ZtX3ZjcHVfcG11LmgKPj4+ IEBAIC01MCw2ICs1MCwxMCBAQCBzdHJ1Y3Qga3ZtX3BtdSB7Cj4+PiAgICAgICAgYm9vbCBpbml0 X2RvbmU7Cj4+PiAgICAgICAgLyogQml0IG1hcCBvZiBhbGwgdGhlIHZpcnR1YWwgY291bnRlciB1 c2VkICovCj4+PiAgICAgICAgREVDTEFSRV9CSVRNQVAocG1jX2luX3VzZSwgUklTQ1ZfS1ZNX01B WF9DT1VOVEVSUyk7Cj4+PiArICAgICAvKiBUaGUgYWRkcmVzcyBvZiB0aGUgY291bnRlciBzbmFw c2hvdCBhcmVhIChndWVzdCBwaHlzaWNhbCBhZGRyZXNzKSAqLwo+Pj4gKyAgICAgZ3BhX3Qgc25h cHNob3RfYWRkcjsKPj4+ICsgICAgIC8qIFRoZSBhY3R1YWwgZGF0YSBvZiB0aGUgc25hcHNob3Qg Ki8KPj4+ICsgICAgIHN0cnVjdCByaXNjdl9wbXVfc25hcHNob3RfZGF0YSAqc2RhdGE7Cj4+PiAg IH07Cj4+Pgo+Pj4gICAjZGVmaW5lIHZjcHVfdG9fcG11KHZjcHUpICgmKHZjcHUpLT5hcmNoLnBt dV9jb250ZXh0KQo+Pj4gQEAgLTg1LDYgKzg5LDkgQEAgaW50IGt2bV9yaXNjdl92Y3B1X3BtdV9j dHJfY2ZnX21hdGNoKHN0cnVjdCBrdm1fdmNwdSAqdmNwdSwgdW5zaWduZWQgbG9uZyBjdHJfYmEK Pj4+ICAgaW50IGt2bV9yaXNjdl92Y3B1X3BtdV9jdHJfcmVhZChzdHJ1Y3Qga3ZtX3ZjcHUgKnZj cHUsIHVuc2lnbmVkIGxvbmcgY2lkeCwKPj4+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICBzdHJ1Y3Qga3ZtX3ZjcHVfc2JpX3JldHVybiAqcmV0ZGF0YSk7Cj4+PiAgIHZvaWQga3ZtX3Jp c2N2X3ZjcHVfcG11X2luaXQoc3RydWN0IGt2bV92Y3B1ICp2Y3B1KTsKPj4+ICtpbnQga3ZtX3Jp c2N2X3ZjcHVfcG11X3NldHVwX3NuYXBzaG90KHN0cnVjdCBrdm1fdmNwdSAqdmNwdSwgdW5zaWdu ZWQgbG9uZyBzYWRkcl9sb3csCj4+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICB1bnNpZ25lZCBsb25nIHNhZGRyX2hpZ2gsIHVuc2lnbmVkIGxvbmcgZmxhZ3MsCj4+PiArICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJ1Y3Qga3ZtX3ZjcHVfc2JpX3JldHVy biAqcmV0ZGF0YSk7Cj4+Cj4+IEkgcHJlZmVyIHRvIG5hbWUgdGhpcyBmdW5jdGlvbgo+Pgo+PiBr dm1fcmlzY3ZfdmNwdV9wbXVfc25hcHNob3Rfc2V0X3NobWVtCj4+Cj4gCj4gU3VyZS4KPiAKPj4+ ICAgdm9pZCBrdm1fcmlzY3ZfdmNwdV9wbXVfZGVpbml0KHN0cnVjdCBrdm1fdmNwdSAqdmNwdSk7 Cj4+PiAgIHZvaWQga3ZtX3Jpc2N2X3ZjcHVfcG11X3Jlc2V0KHN0cnVjdCBrdm1fdmNwdSAqdmNw dSk7Cj4+Pgo+Pj4gZGlmZiAtLWdpdCBhL2FyY2gvcmlzY3Yva3ZtL3ZjcHVfcG11LmMgYi9hcmNo L3Jpc2N2L2t2bS92Y3B1X3BtdS5jCj4+PiBpbmRleCAyOWJmNGNhNzk4Y2IuLjc0ODY1ZTYwNTBh MSAxMDA2NDQKPj4+IC0tLSBhL2FyY2gvcmlzY3Yva3ZtL3ZjcHVfcG11LmMKPj4+ICsrKyBiL2Fy Y2gvcmlzY3Yva3ZtL3ZjcHVfcG11LmMKPj4+IEBAIC0zMTEsNiArMzExLDgxIEBAIGludCBrdm1f cmlzY3ZfdmNwdV9wbXVfcmVhZF9ocG0oc3RydWN0IGt2bV92Y3B1ICp2Y3B1LCB1bnNpZ25lZCBp bnQgY3NyX251bSwKPj4+ICAgICAgICByZXR1cm4gcmV0Owo+Pj4gICB9Cj4+Pgo+Pj4gK3N0YXRp YyB2b2lkIGt2bV9wbXVfY2xlYXJfc25hcHNob3RfYXJlYShzdHJ1Y3Qga3ZtX3ZjcHUgKnZjcHUp Cj4+PiArewo+Pj4gKyAgICAgc3RydWN0IGt2bV9wbXUgKmt2cG11ID0gdmNwdV90b19wbXUodmNw dSk7Cj4+PiArICAgICBpbnQgc25hcHNob3RfYXJlYV9zaXplID0gc2l6ZW9mKHN0cnVjdCByaXNj dl9wbXVfc25hcHNob3RfZGF0YSk7Cj4+PiArCj4+PiArICAgICBpZiAoa3ZwbXUtPnNkYXRhKSB7 Cj4+PiArICAgICAgICAgICAgIG1lbXNldChrdnBtdS0+c2RhdGEsIDAsIHNuYXBzaG90X2FyZWFf c2l6ZSk7Cj4+PiArICAgICAgICAgICAgIGlmIChrdnBtdS0+c25hcHNob3RfYWRkciAhPSBJTlZB TElEX0dQQSkKPj4KPj4gSXQncyBhIEtWTSBidWcgaWYgd2UgaGF2ZSBub24tbnVsbCBzZGF0YSBi dXQgc25hcHNob3RfYWRkciBpcyBJTlZBTElEX0dQQSwKPj4gcmlnaHQ/IE1heWJlIHdlIHNob3Vs ZCB3YXJuIGlmIHdlIHNlZSB0aGF0LiBXZSBjYW4gYWxzbyBtb3ZlIHRoZSBtZW1zZXQKPj4gaW5z aWRlIHRoZSBpZiBibG9jay4KPj4KPiAKPiBBZGRlZCBhIHdhcm5pbmcuCj4gCj4+PiArICAgICAg ICAgICAgICAgICAgICAga3ZtX3ZjcHVfd3JpdGVfZ3Vlc3QodmNwdSwga3ZwbXUtPnNuYXBzaG90 X2FkZHIsCj4+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga3Zw bXUtPnNkYXRhLCBzbmFwc2hvdF9hcmVhX3NpemUpOwo+Pj4gKyAgICAgICAgICAgICBrZnJlZShr dnBtdS0+c2RhdGEpOwo+Pj4gKyAgICAgICAgICAgICBrdnBtdS0+c2RhdGEgPSBOVUxMOwo+Pj4g KyAgICAgfQo+Pj4gKyAgICAga3ZwbXUtPnNuYXBzaG90X2FkZHIgPSBJTlZBTElEX0dQQTsKPj4+ ICt9Cj4+PiArCj4+PiAraW50IGt2bV9yaXNjdl92Y3B1X3BtdV9zZXR1cF9zbmFwc2hvdChzdHJ1 Y3Qga3ZtX3ZjcHUgKnZjcHUsIHVuc2lnbmVkIGxvbmcgc2FkZHJfbG93LAo+Pj4gKyAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5zaWduZWQgbG9uZyBzYWRkcl9oaWdoLCB1bnNp Z25lZCBsb25nIGZsYWdzLAo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg c3RydWN0IGt2bV92Y3B1X3NiaV9yZXR1cm4gKnJldGRhdGEpCj4+PiArewo+Pj4gKyAgICAgc3Ry dWN0IGt2bV9wbXUgKmt2cG11ID0gdmNwdV90b19wbXUodmNwdSk7Cj4+PiArICAgICBpbnQgc25h cHNob3RfYXJlYV9zaXplID0gc2l6ZW9mKHN0cnVjdCByaXNjdl9wbXVfc25hcHNob3RfZGF0YSk7 Cj4+PiArICAgICBpbnQgc2JpcmV0ID0gMDsKPj4+ICsgICAgIGdwYV90IHNhZGRyOwo+Pj4gKyAg ICAgdW5zaWduZWQgbG9uZyBodmE7Cj4+PiArICAgICBib29sIHdyaXRhYmxlOwo+Pj4gKwo+Pj4g KyAgICAgaWYgKCFrdnBtdSkgewo+Pj4gKyAgICAgICAgICAgICBzYmlyZXQgPSBTQklfRVJSX0lO VkFMSURfUEFSQU07Cj4+PiArICAgICAgICAgICAgIGdvdG8gb3V0Owo+Pj4gKyAgICAgfQo+Pgo+ PiBOZWVkIHRvIGNoZWNrIHRoYXQgZmxhZ3MgaXMgemVybyBvciByZXR1cm4gU0JJX0VSUl9JTlZB TElEX1BBUkFNLgo+Pgo+IAo+IEZpeGVkLgo+IAo+Pj4gKwo+Pj4gKyAgICAgaWYgKHNhZGRyX2xv dyA9PSAtMSAmJiBzYWRkcl9oaWdoID09IC0xKSB7Cj4+Cj4+IFdlIGludHJvZHVjZWQgU0JJX1NU QV9TSE1FTV9ESVNBQkxFIGZvciB0aGVzZSBtYWdpYyAtMSdzIGZvciBTVEEuIFNpbmNlCj4+IFNC SSBpcyB1c2luZyB0aGUgLTEgYXBwcm9hY2ggZm9yIGFsbCBpdHMgc2htZW0sIHRoZW4gbWF5YmUg d2Ugc2hvdWxkCj4+IHJlbmFtZSBTQklfU1RBX1NITUVNX0RJU0FCTEUgdG8gU0JJX1NITUVNX0RJ U0FCTEUgYW5kIHRoZW4gdXNlIHRoZW0gaGVyZQo+PiB0b28uCj4+Cj4gCj4gRml4ZWQKPiAKPj4+ ICsgICAgICAgICAgICAga3ZtX3BtdV9jbGVhcl9zbmFwc2hvdF9hcmVhKHZjcHUpOwo+Pj4gKyAg ICAgICAgICAgICByZXR1cm4gMDsKPj4+ICsgICAgIH0KPj4+ICsKPj4+ICsgICAgIHNhZGRyID0g c2FkZHJfbG93Owo+Pj4gKwo+Pj4gKyAgICAgaWYgKHNhZGRyX2hpZ2ggIT0gMCkgewo+Pj4gKyAg ICAgICAgICAgICBpZiAoSVNfRU5BQkxFRChDT05GSUdfMzJCSVQpKQo+Pj4gKyAgICAgICAgICAg ICAgICAgICAgIHNhZGRyIHw9ICgoZ3BhX3Qpc2FkZHIgPDwgMzIpOwo+Pj4gKyAgICAgICAgICAg ICBlbHNlCj4+PiArICAgICAgICAgICAgICAgICAgICAgc2JpcmV0ID0gU0JJX0VSUl9JTlZBTElE X0FERFJFU1M7Cj4+PiArICAgICAgICAgICAgIGdvdG8gb3V0Owo+Pj4gKyAgICAgfQo+Pj4gKwo+ Pj4gKyAgICAgaWYgKGt2bV9pc19lcnJvcl9ncGEodmNwdS0+a3ZtLCBzYWRkcikpIHsKPj4+ICsg ICAgICAgICAgICAgc2JpcmV0ID0gU0JJX0VSUl9JTlZBTElEX1BBUkFNOwo+Pj4gKyAgICAgICAg ICAgICBnb3RvIG91dDsKPj4+ICsgICAgIH0KPj4KPj4gRG9lcyB0aGUgY2hlY2sgYWJvdmUgcHJv dmlkZSBhbnl0aGluZyBtb3JlIHRoYW4gd2hhdCB0aGUgY2hlY2sgYmVsb3cgZG9lcz8KPj4KPiBZ b3UgYXJlIGNvcnJlY3QuIEkgaGF2ZSByZW1vdmVkIHRoZSBjaGVjawo+IAo+Pj4gKwo+Pj4gKyAg ICAgaHZhID0ga3ZtX3ZjcHVfZ2ZuX3RvX2h2YV9wcm90KHZjcHUsIHNhZGRyID4+IFBBR0VfU0hJ RlQsICZ3cml0YWJsZSk7Cj4+PiArICAgICBpZiAoa3ZtX2lzX2Vycm9yX2h2YShodmEpIHx8ICF3 cml0YWJsZSkgewo+Pj4gKyAgICAgICAgICAgICBzYmlyZXQgPSBTQklfRVJSX0lOVkFMSURfQURE UkVTUzsKPj4+ICsgICAgICAgICAgICAgZ290byBvdXQ7Cj4+PiArICAgICB9Cj4+PiArCj4+PiAr ICAgICBrdnBtdS0+c25hcHNob3RfYWRkciA9IHNhZGRyOwo+Pj4gKyAgICAga3ZwbXUtPnNkYXRh ID0ga3phbGxvYyhzbmFwc2hvdF9hcmVhX3NpemUsIEdGUF9BVE9NSUMpOwo+Pj4gKyAgICAgaWYg KCFrdnBtdS0+c2RhdGEpCj4+Cj4+IFNob3VsZCByZXNldCBzbmFwc2hvdF9hZGRyIHRvIElOVkFM SURfR1BBIGhlcmUgb24gZXJyb3IuIE9yIG1heWJlIHdlCj4+IHNob3VsZCBqdXN0IHNldCBzbmFw c2hvdF9hZGRyIHRvIHNhZGRyIGF0IHRoZSBib3R0b20gb2YgdGhpcyBmdW5jdGlvbiBpZgo+PiB3 ZSBtYWtlIGl0Lgo+Pgo+IAo+IERvbmUuCj4gCj4+PiArICAgICAgICAgICAgIHJldHVybiAtRU5P TUVNOwo+Pj4gKwo+Pj4gKyAgICAgaWYgKGt2bV92Y3B1X3dyaXRlX2d1ZXN0KHZjcHUsIHNhZGRy LCBrdnBtdS0+c2RhdGEsIHNuYXBzaG90X2FyZWFfc2l6ZSkpIHsKPj4+ICsgICAgICAgICAgICAg a2ZyZWUoa3ZwbXUtPnNkYXRhKTsKPj4+ICsgICAgICAgICAgICAga3ZwbXUtPnNuYXBzaG90X2Fk ZHIgPSBJTlZBTElEX0dQQTsKPj4+ICsgICAgICAgICAgICAgc2JpcmV0ID0gU0JJX0VSUl9GQUlM VVJFOwo+Pgo+PiBJIGFncmVlIHdlIHNob3VsZCByZXR1cm4gdGhpcyBTQkkgZXJyb3IgZm9yIHRo aXMgY2FzZSwgYnV0IHVuZm9ydHVuYXRlbHkKPj4gdGhlIHNwZWMgaXMgbWlzc2luZyB0aGUKPj4K Pj4gICBTQklfRVJSX0ZBSUxFRCAtIFRoZSByZXF1ZXN0IGZhaWxlZCBmb3IgdW5zcGVjaWZpZWQg b3IgdW5rbm93biBvdGhlciByZWFzb25zLgo+Pgo+PiB0aGF0IHdlIGhhdmUgZm9yIG90aGVyIFNC SSBmdW5jdGlvbnMuIEkgZ3Vlc3Mgd2Ugc2hvdWxkIGtlZXAgdGhlIGNvZGUgbGlrZQo+PiB0aGlz IGFuZCBvcGVuIGEgUFIgdG8gdGhlIHNwZWMuCj4+Cj4gCj4gSSBoYXZlIGNyZWF0ZWQgYSBibGFu a2V0IGdpdGh1YiBpc3N1ZSBmb3Igbm93LiBJIHdpbGwgc2VuZCBhIFBSLgo+IAo+Pj4gKyAgICAg fQo+Pj4gKwo+Pj4gK291dDoKPj4+ICsgICAgIHJldGRhdGEtPmVycl92YWwgPSBzYmlyZXQ7Cj4+ PiArCj4+PiArICAgICByZXR1cm4gMDsKPj4+ICt9Cj4+PiArCj4+PiAgIGludCBrdm1fcmlzY3Zf dmNwdV9wbXVfbnVtX2N0cnMoc3RydWN0IGt2bV92Y3B1ICp2Y3B1LAo+Pj4gICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgIHN0cnVjdCBrdm1fdmNwdV9zYmlfcmV0dXJuICpyZXRkYXRhKQo+ Pj4gICB7Cj4+PiBAQCAtMzQ0LDIwICs0MTksMzMgQEAgaW50IGt2bV9yaXNjdl92Y3B1X3BtdV9j dHJfc3RhcnQoc3RydWN0IGt2bV92Y3B1ICp2Y3B1LCB1bnNpZ25lZCBsb25nIGN0cl9iYXNlLAo+ Pj4gICAgICAgIGludCBpLCBwbWNfaW5kZXgsIHNiaXJldCA9IDA7Cj4+PiAgICAgICAgc3RydWN0 IGt2bV9wbWMgKnBtYzsKPj4+ICAgICAgICBpbnQgZmV2ZW50X2NvZGU7Cj4+PiArICAgICBib29s IHNuYXBfZmxhZ19zZXQgPSBmbGFncyAmIFNCSV9QTVVfU1RBUlRfRkxBR19JTklUX0ZST01fU05B UFNIT1Q7Cj4+Cj4+IFRoaXMgZnVuY3Rpb24gc2hvdWxkIGNvbmZpcm0gbm8gdW5kZWZpbmVkIGJp dHMgYXJlIHNldCBpbiBmbGFncyBhbmQgdGhlCj4+IHNwZWMgc2hvdWxkIHNwZWNpZnkgdGhhdCB0 aGUgcmVzZXJ2ZWQgZmxhZ3MgbXVzdCBiZSB6ZXJvIG90aGVyd2lzZSBhbgo+PiBpbnZhbGlkIHBh cmFtIHdpbGwgYmUgcmV0dXJuZWQuCj4+Cj4+IEFsc28gaGVyZSB3b3VsZCBzaG91bGQgY29uZmly bSB0aGF0IG9ubHkgb25lIG9mIHRoZSB0d28gZmxhZ3MgaXMgc2V0LAo+PiBvdGhlcndpc2UgcmV0 dXJuIGludmFsaWQgcGFyYW0sIGFzIHRoZXkndmUgc3BlY2lmaWVkIHRvIGJlIG11dHVhbGx5Cj4+ IGV4Y2x1c2l2ZS4KPj4KPiAKPiBUaGF0IG1ha2VzIHNlbnNlLiBVcGRhdGUgdGhlIHNhbWUgZ2l0 aHViIGlzc3VlLgo+IChodHRwczovL2dpdGh1Yi5jb20vcmlzY3Ytbm9uLWlzYS9yaXNjdi1zYmkt ZG9jL2lzc3Vlcy8xNDUpCj4gCj4gSSB3aWxsIG1ha2UgdGhlIG5lY2Vzc2FyeSBjaGFuZ2VzIGlu IGEgc2VwYXJhdGUgc2VyaWVzIGFmdGVyIHRoZSBzcGVjIGlzIG1lcmdlZC4KPiAKPj4gUmVnYXJk aW5nIHRoZSBzcGVjLCB0aGUgbm90ZSBhYm91dCB0aGUgY291bnRlciB2YWx1ZSBub3QgYmVpbmcg bW9kaWZpZWQKPj4gdW5sZXNzIFNCSV9QTVVfU1RBUlRfU0VUX0lOSVRfVkFMVUUgaXMgc2V0IHNo b3VsZCBiZSBtb2RpZmllZCB0byBzdGF0ZQo+PiB1bmxlc3MgZWl0aGVyIG9mIHRoZSB0d28gZmxh Z3MgYXJlIHNldCAoc28gSSB0aGluayB3ZSBuZWVkIGFub3RoZXIgc3BlYwo+PiBQUikuCj4+Cj4+ IChUaGUgc2FtZSBmbGFncyBjaGVja2luZy9zcGVjaWZ5aW5nIGNvbW1lbnRzIGFwcGx5IHRvIHRo ZSBvdGhlciBmdW5jdGlvbnMKPj4gd2l0aCBmbGFncyB0b28uKQo+Pgo+IAo+IE5vdGVkIChodHRw czovL2dpdGh1Yi5jb20vcmlzY3Ytbm9uLWlzYS9yaXNjdi1zYmktZG9jL2lzc3Vlcy8xNDYpLgo+ IAo+Pj4KPj4+ICAgICAgICBpZiAoa3ZtX3BtdV92YWxpZGF0ZV9jb3VudGVyX21hc2soa3ZwbXUs IGN0cl9iYXNlLCBjdHJfbWFzaykgPCAwKSB7Cj4+PiAgICAgICAgICAgICAgICBzYmlyZXQgPSBT QklfRVJSX0lOVkFMSURfUEFSQU07Cj4+PiAgICAgICAgICAgICAgICBnb3RvIG91dDsKPj4+ICAg ICAgICB9Cj4+Pgo+Pj4gKyAgICAgaWYgKHNuYXBfZmxhZ19zZXQgJiYga3ZwbXUtPnNuYXBzaG90 X2FkZHIgPT0gSU5WQUxJRF9HUEEpIHsKPj4+ICsgICAgICAgICAgICAgc2JpcmV0ID0gU0JJX0VS Ul9OT19TSE1FTTsKPj4+ICsgICAgICAgICAgICAgZ290byBvdXQ7Cj4+PiArICAgICB9Cj4+PiAr Cj4+PiAgICAgICAgLyogU3RhcnQgdGhlIGNvdW50ZXJzIHRoYXQgaGF2ZSBiZWVuIGNvbmZpZ3Vy ZWQgYW5kIHJlcXVlc3RlZCBieSB0aGUgZ3Vlc3QgKi8KPj4+ICAgICAgICBmb3JfZWFjaF9zZXRf Yml0KGksICZjdHJfbWFzaywgUklTQ1ZfTUFYX0NPVU5URVJTKSB7Cj4+PiAgICAgICAgICAgICAg ICBwbWNfaW5kZXggPSBpICsgY3RyX2Jhc2U7Cj4+PiAgICAgICAgICAgICAgICBpZiAoIXRlc3Rf Yml0KHBtY19pbmRleCwga3ZwbXUtPnBtY19pbl91c2UpKQo+Pj4gICAgICAgICAgICAgICAgICAg ICAgICBjb250aW51ZTsKPj4+ICAgICAgICAgICAgICAgIHBtYyA9ICZrdnBtdS0+cG1jW3BtY19p bmRleF07Cj4+PiAtICAgICAgICAgICAgIGlmIChmbGFncyAmIFNCSV9QTVVfU1RBUlRfRkxBR19T RVRfSU5JVF9WQUxVRSkKPj4+ICsgICAgICAgICAgICAgaWYgKGZsYWdzICYgU0JJX1BNVV9TVEFS VF9GTEFHX1NFVF9JTklUX1ZBTFVFKSB7Cj4+PiAgICAgICAgICAgICAgICAgICAgICAgIHBtYy0+ Y291bnRlcl92YWwgPSBpdmFsOwo+Pj4gKyAgICAgICAgICAgICB9IGVsc2UgaWYgKHNuYXBfZmxh Z19zZXQpIHsKPj4+ICsgICAgICAgICAgICAgICAgICAgICBrdm1fdmNwdV9yZWFkX2d1ZXN0KHZj cHUsIGt2cG11LT5zbmFwc2hvdF9hZGRyLCBrdnBtdS0+c2RhdGEsCj4+PiArICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplb2Yoc3RydWN0IHJpc2N2X3BtdV9zbmFw c2hvdF9kYXRhKSk7Cj4+Cj4+IFRoZSBzbmFwc2hvdCByZWFkIHNob3VsZCBiZSBvdXRzaWRlIHRo ZSBmb3JfZWFjaF9zZXRfYml0KCkgbG9vcCBhbmQgd2UKPj4gc2hvdWxkIHdhcm4gYW5kIGFib3J0 IHRoZSBjb3VudGVyIHN0YXJ0aW5nIGlmIHRoZSByZWFkIGZhaWxzLgo+Pgo+IAo+IEZpeGVkLiBU aGlzIHNob3VsZCBhbHNvIGZhbGwgdW5kZXIgdGhlIFNCSV9FUlJfRkFJTFVSRSBjYXRlZ29yeS4K PiAKPj4+ICsgICAgICAgICAgICAgICAgICAgICAvKiBUaGUgY291bnRlciBpbmRleCBpbiB0aGUg c25hcHNob3QgYXJlIHJlbGF0aXZlIHRvIHRoZSBjb3VudGVyIGJhc2UgKi8KPj4+ICsgICAgICAg ICAgICAgICAgICAgICBwbWMtPmNvdW50ZXJfdmFsID0ga3ZwbXUtPnNkYXRhLT5jdHJfdmFsdWVz W2ldOwo+Pj4gKyAgICAgICAgICAgICB9Cj4+PiArCj4+PiAgICAgICAgICAgICAgICBpZiAocG1j LT5jaW5mby50eXBlID09IFNCSV9QTVVfQ1RSX1RZUEVfRlcpIHsKPj4+ICAgICAgICAgICAgICAg ICAgICAgICAgZmV2ZW50X2NvZGUgPSBnZXRfZXZlbnRfY29kZShwbWMtPmV2ZW50X2lkeCk7Cj4+ PiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmZXZlbnRfY29kZSA+PSBTQklfUE1VX0ZXX01B WCkgewo+Pj4gQEAgLTM5OCwxNCArNDg2LDIxIEBAIGludCBrdm1fcmlzY3ZfdmNwdV9wbXVfY3Ry X3N0b3Aoc3RydWN0IGt2bV92Y3B1ICp2Y3B1LCB1bnNpZ25lZCBsb25nIGN0cl9iYXNlLAo+Pj4g ICB7Cj4+PiAgICAgICAgc3RydWN0IGt2bV9wbXUgKmt2cG11ID0gdmNwdV90b19wbXUodmNwdSk7 Cj4+PiAgICAgICAgaW50IGksIHBtY19pbmRleCwgc2JpcmV0ID0gMDsKPj4+ICsgICAgIHU2NCBl bmFibGVkLCBydW5uaW5nOwo+Pj4gICAgICAgIHN0cnVjdCBrdm1fcG1jICpwbWM7Cj4+PiAgICAg ICAgaW50IGZldmVudF9jb2RlOwo+Pj4gKyAgICAgYm9vbCBzbmFwX2ZsYWdfc2V0ID0gZmxhZ3Mg JiBTQklfUE1VX1NUT1BfRkxBR19UQUtFX1NOQVBTSE9UOwo+Pj4KPj4+IC0gICAgIGlmIChrdm1f cG11X3ZhbGlkYXRlX2NvdW50ZXJfbWFzayhrdnBtdSwgY3RyX2Jhc2UsIGN0cl9tYXNrKSA8IDAp IHsKPj4+ICsgICAgIGlmICgoa3ZtX3BtdV92YWxpZGF0ZV9jb3VudGVyX21hc2soa3ZwbXUsIGN0 cl9iYXNlLCBjdHJfbWFzaykgPCAwKSkgewo+Pgo+PiBBZGRlZCB1bm5lY2Vzc2FyeSAoKSBoZXJl Lgo+Pgo+IAo+IEZpeGVkLgo+IAo+Pj4gICAgICAgICAgICAgICAgc2JpcmV0ID0gU0JJX0VSUl9J TlZBTElEX1BBUkFNOwo+Pj4gICAgICAgICAgICAgICAgZ290byBvdXQ7Cj4+PiAgICAgICAgfQo+ Pj4KPj4+ICsgICAgIGlmIChzbmFwX2ZsYWdfc2V0ICYmIGt2cG11LT5zbmFwc2hvdF9hZGRyID09 IElOVkFMSURfR1BBKSB7Cj4+PiArICAgICAgICAgICAgIHNiaXJldCA9IFNCSV9FUlJfTk9fU0hN RU07Cj4+PiArICAgICAgICAgICAgIGdvdG8gb3V0Owo+Pj4gKyAgICAgfQo+Pj4gKwo+Pj4gICAg ICAgIC8qIFN0b3AgdGhlIGNvdW50ZXJzIHRoYXQgaGF2ZSBiZWVuIGNvbmZpZ3VyZWQgYW5kIHJl cXVlc3RlZCBieSB0aGUgZ3Vlc3QgKi8KPj4+ICAgICAgICBmb3JfZWFjaF9zZXRfYml0KGksICZj dHJfbWFzaywgUklTQ1ZfTUFYX0NPVU5URVJTKSB7Cj4+PiAgICAgICAgICAgICAgICBwbWNfaW5k ZXggPSBpICsgY3RyX2Jhc2U7Cj4+PiBAQCAtNDM4LDkgKzUzMywyOCBAQCBpbnQga3ZtX3Jpc2N2 X3ZjcHVfcG11X2N0cl9zdG9wKHN0cnVjdCBrdm1fdmNwdSAqdmNwdSwgdW5zaWduZWQgbG9uZyBj dHJfYmFzZSwKPj4+ICAgICAgICAgICAgICAgIH0gZWxzZSB7Cj4+PiAgICAgICAgICAgICAgICAg ICAgICAgIHNiaXJldCA9IFNCSV9FUlJfSU5WQUxJRF9QQVJBTTsKPj4+ICAgICAgICAgICAgICAg IH0KPj4+ICsKPj4+ICsgICAgICAgICAgICAgaWYgKHNuYXBfZmxhZ19zZXQgJiYgIXNiaXJldCkg ewo+Pj4gKyAgICAgICAgICAgICAgICAgICAgIGlmIChwbWMtPmNpbmZvLnR5cGUgPT0gU0JJX1BN VV9DVFJfVFlQRV9GVykKPj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBtYy0+Y291 bnRlcl92YWwgPSBrdnBtdS0+ZndfZXZlbnRbZmV2ZW50X2NvZGVdLnZhbHVlOwo+Pj4gKyAgICAg ICAgICAgICAgICAgICAgIGVsc2UgaWYgKHBtYy0+cGVyZl9ldmVudCkKPj4+ICsgICAgICAgICAg ICAgICAgICAgICAgICAgICAgIHBtYy0+Y291bnRlcl92YWwgKz0gcGVyZl9ldmVudF9yZWFkX3Zh bHVlKHBtYy0+cGVyZl9ldmVudCwKPj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICZlbmFibGVkLCAmcnVubmlu Zyk7Cj4+PiArICAgICAgICAgICAgICAgICAgICAgLyogVE9ETzogQWRkIGNvdW50ZXIgb3ZlcmZs b3cgc3VwcG9ydCB3aGVuIHNzY29mcG1mIHN1cHBvcnQgaXMgYWRkZWQgKi8KPj4+ICsgICAgICAg ICAgICAgICAgICAgICBrdnBtdS0+c2RhdGEtPmN0cl92YWx1ZXNbaV0gPSBwbWMtPmNvdW50ZXJf dmFsOwo+Pj4gKyAgICAgICAgICAgICAgICAgICAgIGt2bV92Y3B1X3dyaXRlX2d1ZXN0KHZjcHUs IGt2cG11LT5zbmFwc2hvdF9hZGRyLCBrdnBtdS0+c2RhdGEsCj4+PiArICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZW9mKHN0cnVjdCByaXNjdl9wbXVfc25hcHNo b3RfZGF0YSkpOwo+Pgo+PiBTaG91bGQganVzdCBzZXQgYSBib29sZWFuIGhlcmUgc2F5aW5nIHRo YXQgdGhlIHNuYXBzaG90IG5lZWRzIGFuIHVwZGF0ZQo+PiBhbmQgdGhlbiBkbyB0aGUgdXBkYXRl IG91dHNpZGUgdGhlIGZvcl9lYWNoX3NldF9iaXQgbG9vcC4KPj4KPiAKPiBEb25lLgo+IAo+Pj4g KyAgICAgICAgICAgICB9Cj4+PiArCj4+PiAgICAgICAgICAgICAgICBpZiAoZmxhZ3MgJiBTQklf UE1VX1NUT1BfRkxBR19SRVNFVCkgewo+Pj4gICAgICAgICAgICAgICAgICAgICAgICBwbWMtPmV2 ZW50X2lkeCA9IFNCSV9QTVVfRVZFTlRfSURYX0lOVkFMSUQ7Cj4+PiAgICAgICAgICAgICAgICAg ICAgICAgIGNsZWFyX2JpdChwbWNfaW5kZXgsIGt2cG11LT5wbWNfaW5fdXNlKTsKPj4+ICsgICAg ICAgICAgICAgICAgICAgICBpZiAoc25hcF9mbGFnX3NldCkgewo+Pj4gKyAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgLyogQ2xlYXIgdGhlIHNuYXBzaG90IGFyZWEgZm9yIHRoZSB1cGNvbWlu ZyBkZWxldGlvbiBldmVudCAqLwo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAga3Zw bXUtPnNkYXRhLT5jdHJfdmFsdWVzW2ldID0gMDsKPj4+ICsgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIGt2bV92Y3B1X3dyaXRlX2d1ZXN0KHZjcHUsIGt2cG11LT5zbmFwc2hvdF9hZGRyLCBr dnBtdS0+c2RhdGEsCj4+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICBzaXplb2Yoc3RydWN0IHJpc2N2X3BtdV9zbmFwc2hvdF9kYXRhKSk7Cj4+Cj4+ IFRoZSBzcGVjIGlzbid0IGNsZWFyIG9uIHRoaXMgKHNvIHdlIHNob3VsZCBjbGFyaWZ5IGl0KSwg YnV0IEknZCBleHBlY3QKPj4gdGhhdCBhIGNhbGxlciB3aG8gc2V0IGJvdGggdGhlIHJlc2V0IGFu ZCB0aGUgc25hcHNob3QgZmxhZyB3b3VsZCB3YW50Cj4+IHRoZSBzbmFwc2hvdCBmcm9tIGJlZm9y ZSB0aGUgcmVzZXQgd2hlbiB0aGlzIGNhbGwgY29tcGxldGVzIGFuZCB0aGVuCj4+IGFzc3VtZSB0 aGF0IHdoZW4gdGhleSBzdGFydCBjb3VudGluZyBhZ2FpbiwgYW5kIGxvb2sgYXQgdGhlIHNuYXBz aG90Cj4+IGFnYWluLCB0aGF0IHRob3NlIG5ldyBjb3VudHMgd291bGQgYmUgZnJvbSB0aGUgcmVz ZXQgdmFsdWVzLiBPciBtYXliZQo+PiBub3QgOi0pIE1heWJlIHRoZXkgd2FudCB0byBkbyBhIHJl c2V0IGFuZCB0YWtlIGEgc25hcHNob3QgaW4gb3JkZXIgdG8KPj4gbG9vayBhdCB0aGUgc25hcHNo b3QgYW5kIGNvbmZpcm0gdGhlIHJlc2V0IGhhcHBlbmVkPyBFaXRoZXIgd2F5LCBpdAo+PiBzZWVt cyB3ZSBzaG91bGQgb25seSBkbyBvbmUgb2YgdGhlIHR3byBoZXJlLiBFaXRoZXIgdXBkYXRlIHRo ZSBzbmFwc2hvdAo+PiBiZWZvcmUgcmVzZXR0aW5nLCBhbmQgbm90IGFnYWluIGFmdGVyIHJlc2V0 LCBvciByZXNldCBhbmQgdGhlbiB1cGRhdGUKPj4gdGhlIHNuYXBzaG90ICh3aXRoIG5vIG5lZWQg dG8gdXBkYXRlIGJlZm9yZSkuCj4+Cj4gCj4gVGhlIHJlc2V0IGNhbGwgc2hvdWxkIGhhcHBlbiB3 aGVuIHRoZSBldmVudCBpcyBkZWxldGVkIGJ5IHRoZSBwZXJmCj4gZnJhbWV3b3JrIGluIHN1cGVy dmlzb3IuCj4gSWYgd2UgZG9uJ3QgY2xlYXIgdGhlIHZhbHVlcywgdGhlIHNoYXJlZCBtZW1vcnkg bWF5IGhhdmUgc3RhbGUgZGF0YSBvZgo+IGxhc3QgcmVhZCBjb3VudGVycwo+IHdoaWNoIGlzIG5v dCBpZGVhbC4gVGhhdCdzIHdoeSwgSSBhbSBjbGVhcmluZyBpdCB1cG9uIHJlc2V0dGluZy4KClRo aW5raW5nIGFib3V0IGl0IG1vcmUsIEkgdGhpbmsgaGF2aW5nIHN0YWxlIHZhbHVlcyBpbiB0aGUg c2hhcmVkIG1lbW9yeQp3b3VsZCBiZSBzaW1pbGFyIGV4cGVjdGVkIGJlaGF2aW9yIHRvIGhhcmR3 YXJlIGNvdW50ZXJzIGFmdGVyIHJlc2V0LiBXZSAKZG9uJ3QgbmVlZCB0byBjbGVhciB0aGUgc2hh cmVkIG1lbW9yeSBkdXJpbmcgdGhlIHJlc2V0LgoKSWYgYm90aCBTQklfUE1VX1NUT1BfRkxBR19U QUtFX1NOQVBTSE9UIGFuZCBTQklfUE1VX1NUT1BfRkxBR19SRVNFVCBhcmUgCnNldCwgbWF5IGJl IHdlIHNob3VsZCBqdXN0IHdyaXRlIGl0IHRvIHRoZSBzaGFyZWQgbWVtb3J5IGFnYWluIHdpdGhv dXQgCmFzc3VtaW5nIHRoZSBpbnRlbnRpb24gb2YgdGhlIGNhbGxlciA/Cgo+IFRoZSBhY3R1YWwg Y291bnRlciB2YWx1ZSBzaG91bGQgYmUgcmVhZCB3aGlsZSBzdG9wcGluZyB0aGUgY291bnRlcnMu Cj4gCj4gSSB0aG91Z2h0IHRoZSBjdXJyZW50IGRlc2NyaXB0aW9uIGlzIGNsZWFyIGVub3VnaCBh cyBpdCBzYXlzCj4gCj4gIlNCSV9QTVVfU1RPUF9GTEFHX1JFU0VUIC0gUmVzZXQgdGhlIGNvdW50 ZXIgdG8gZXZlbnQgbWFwcGluZy4iCj4gCj4gRG8geW91IGZlZWwgd2Ugc2hvdWxkIGJlIG1vcmUg ZXhwbGljaXQgYWJvdXQgdGhpcyA/Cj4gCj4+PiArICAgICAgICAgICAgICAgICAgICAgfQo+Pj4g ICAgICAgICAgICAgICAgfQo+Pj4gICAgICAgIH0KPj4+Cj4+PiBAQCAtNTY2LDYgKzY4MCw3IEBA IHZvaWQga3ZtX3Jpc2N2X3ZjcHVfcG11X2luaXQoc3RydWN0IGt2bV92Y3B1ICp2Y3B1KQo+Pj4g ICAgICAgIGt2cG11LT5udW1faHdfY3RycyA9IG51bV9od19jdHJzICsgMTsKPj4+ICAgICAgICBr dnBtdS0+bnVtX2Z3X2N0cnMgPSBTQklfUE1VX0ZXX01BWDsKPj4+ICAgICAgICBtZW1zZXQoJmt2 cG11LT5md19ldmVudCwgMCwgU0JJX1BNVV9GV19NQVggKiBzaXplb2Yoc3RydWN0IGt2bV9md19l dmVudCkpOwo+Pj4gKyAgICAga3ZwbXUtPnNuYXBzaG90X2FkZHIgPSBJTlZBTElEX0dQQTsKPj4+ Cj4+PiAgICAgICAgaWYgKGt2cG11LT5udW1faHdfY3RycyA+IFJJU0NWX0tWTV9NQVhfSFdfQ1RS Uykgewo+Pj4gICAgICAgICAgICAgICAgcHJfd2Fybl9vbmNlKCJMaW1pdGluZyB0aGUgaGFyZHdh cmUgY291bnRlcnMgdG8gMzIgYXMgc3BlY2lmaWVkIGJ5IHRoZSBJU0EiKTsKPj4+IEBAIC02MjUs NiArNzQwLDcgQEAgdm9pZCBrdm1fcmlzY3ZfdmNwdV9wbXVfZGVpbml0KHN0cnVjdCBrdm1fdmNw dSAqdmNwdSkKPj4+ICAgICAgICB9Cj4+PiAgICAgICAgYml0bWFwX3plcm8oa3ZwbXUtPnBtY19p bl91c2UsIFJJU0NWX01BWF9DT1VOVEVSUyk7Cj4+PiAgICAgICAgbWVtc2V0KCZrdnBtdS0+Zndf ZXZlbnQsIDAsIFNCSV9QTVVfRldfTUFYICogc2l6ZW9mKHN0cnVjdCBrdm1fZndfZXZlbnQpKTsK Pj4+ICsgICAgIGt2bV9wbXVfY2xlYXJfc25hcHNob3RfYXJlYSh2Y3B1KTsKPj4+ICAgfQo+Pj4K Pj4+ICAgdm9pZCBrdm1fcmlzY3ZfdmNwdV9wbXVfcmVzZXQoc3RydWN0IGt2bV92Y3B1ICp2Y3B1 KQo+Pj4gZGlmZiAtLWdpdCBhL2FyY2gvcmlzY3Yva3ZtL3ZjcHVfc2JpX3BtdS5jIGIvYXJjaC9y aXNjdi9rdm0vdmNwdV9zYmlfcG11LmMKPj4+IGluZGV4IGI3MDE3OWU5ZTg3NS4uOWY2MTEzNmU0 YmIxIDEwMDY0NAo+Pj4gLS0tIGEvYXJjaC9yaXNjdi9rdm0vdmNwdV9zYmlfcG11LmMKPj4+ICsr KyBiL2FyY2gvcmlzY3Yva3ZtL3ZjcHVfc2JpX3BtdS5jCj4+PiBAQCAtNjQsNiArNjQsOSBAQCBz dGF0aWMgaW50IGt2bV9zYmlfZXh0X3BtdV9oYW5kbGVyKHN0cnVjdCBrdm1fdmNwdSAqdmNwdSwg c3RydWN0IGt2bV9ydW4gKnJ1biwKPj4+ICAgICAgICBjYXNlIFNCSV9FWFRfUE1VX0NPVU5URVJf RldfUkVBRDoKPj4+ICAgICAgICAgICAgICAgIHJldCA9IGt2bV9yaXNjdl92Y3B1X3BtdV9jdHJf cmVhZCh2Y3B1LCBjcC0+YTAsIHJldGRhdGEpOwo+Pj4gICAgICAgICAgICAgICAgYnJlYWs7Cj4+ PiArICAgICBjYXNlIFNCSV9FWFRfUE1VX1NOQVBTSE9UX1NFVF9TSE1FTToKPj4+ICsgICAgICAg ICAgICAgcmV0ID0ga3ZtX3Jpc2N2X3ZjcHVfcG11X3NldHVwX3NuYXBzaG90KHZjcHUsIGNwLT5h MCwgY3AtPmExLCBjcC0+YTIsIHJldGRhdGEpOwo+Pj4gKyAgICAgICAgICAgICBicmVhazsKPj4+ ICAgICAgICBkZWZhdWx0Ogo+Pj4gICAgICAgICAgICAgICAgcmV0ZGF0YS0+ZXJyX3ZhbCA9IFNC SV9FUlJfTk9UX1NVUFBPUlRFRDsKPj4+ICAgICAgICB9Cj4+PiBkaWZmIC0tZ2l0IGEvZHJpdmVy cy9wZXJmL3Jpc2N2X3BtdV9zYmkuYyBiL2RyaXZlcnMvcGVyZi9yaXNjdl9wbXVfc2JpLmMKPj4+ IGluZGV4IDhkZTU3MjFlODAxOS4uMWEyMmNlMWZmOGM4IDEwMDY0NAo+Pj4gLS0tIGEvZHJpdmVy cy9wZXJmL3Jpc2N2X3BtdV9zYmkuYwo+Pj4gKysrIGIvZHJpdmVycy9wZXJmL3Jpc2N2X3BtdV9z YmkuYwo+Pj4gQEAgLTgwMiw3ICs4MDIsNyBAQCBzdGF0aWMgbm9pbmxpbmUgdm9pZCBwbXVfc2Jp X3N0YXJ0X292Zl9jdHJzX3NuYXBzaG90KHN0cnVjdCBjcHVfaHdfZXZlbnRzICpjcHVfaAo+Pj4g ICAgICAgIHN0cnVjdCByaXNjdl9wbXVfc25hcHNob3RfZGF0YSAqc2RhdGEgPSBjcHVfaHdfZXZ0 LT5zbmFwc2hvdF9hZGRyOwo+Pj4KPj4+ICAgICAgICBmb3JfZWFjaF9zZXRfYml0KGlkeCwgY3B1 X2h3X2V2dC0+dXNlZF9od19jdHJzLCBSSVNDVl9NQVhfQ09VTlRFUlMpIHsKPj4+IC0gICAgICAg ICAgICAgaWYgKGN0cl9vdmZfbWFzayAmICgxIDw8IGlkeCkpIHsKPj4+ICsgICAgICAgICAgICAg aWYgKGN0cl9vdmZfbWFzayAmIChCSVQoaWR4KSkpIHsKPj4+ICAgICAgICAgICAgICAgICAgICAg ICAgZXZlbnQgPSBjcHVfaHdfZXZ0LT5ldmVudHNbaWR4XTsKPj4+ICAgICAgICAgICAgICAgICAg ICAgICAgaHdjID0gJmV2ZW50LT5odzsKPj4+ICAgICAgICAgICAgICAgICAgICAgICAgbWF4X3Bl cmlvZCA9IHJpc2N2X3BtdV9jdHJfZ2V0X3dpZHRoX21hc2soZXZlbnQpOwo+Pj4gLS0KPj4+IDIu MzQuMQo+Pj4KPj4KPj4gVGhhbmtzLAo+PiBkcmV3Cj4gCj4gCj4gCgoKX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KbGludXgtcmlzY3YgbWFpbGluZyBsaXN0 CmxpbnV4LXJpc2N2QGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5v cmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1yaXNjdgo=