Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1220719 > unrolled thread

Re: [PATCH v3 1/2] perf,x86: add Intel Memory Bandwidth Monitoring (MBM) PMU

Started byMatt Fleming <matt.fleming@intel.com>
First post2015-09-08 13:50 +0200
Last post2015-09-08 22:00 +0200
Articles 7 — 5 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: [PATCH v3 1/2] perf,x86: add Intel Memory Bandwidth Monitoring  (MBM) PMU Matt Fleming <matt.fleming@intel.com> - 2015-09-08 13:50 +0200
    RE: [PATCH v3 1/2] perf,x86: add Intel Memory Bandwidth Monitoring  (MBM) PMU "Juvva, Kanaka D" <kanaka.d.juvva@intel.com> - 2015-09-08 18:20 +0200
    RE: [PATCH v3 1/2] perf,x86: add Intel Memory Bandwidth Monitoring  (MBM) PMU "Juvva, Kanaka D" <kanaka.d.juvva@intel.com> - 2015-09-08 19:10 +0200
      Re: [PATCH v3 1/2] perf,x86: add Intel Memory Bandwidth Monitoring  (MBM) PMU Matt Fleming <matt.fleming@intel.com> - 2015-09-10 16:00 +0200
        Re: [PATCH v3 1/2] perf,x86: add Intel Memory Bandwidth Monitoring  (MBM) PMU Kanaka Juvva <kanaka.d.juvva@intel.com> - 2015-09-10 23:20 +0200
          Re: [PATCH v3 1/2] perf,x86: add Intel Memory Bandwidth Monitoring  (MBM) PMU Matt Fleming <matt@codeblueprint.co.uk> - 2015-09-11 23:20 +0200
    Re: [PATCH v3 1/2] perf,      x86: add Intel Memory Bandwidth Monitoring (MBM) PMU kanaka.d.juvva@linux.intel.com - 2015-09-08 22:00 +0200

#1220719 — Re: [PATCH v3 1/2] perf,x86: add Intel Memory Bandwidth Monitoring (MBM) PMU

FromMatt Fleming <matt.fleming@intel.com>
Date2015-09-08 13:50 +0200
SubjectRe: [PATCH v3 1/2] perf,x86: add Intel Memory Bandwidth Monitoring (MBM) PMU
Message-ID<q6pzs-39Q-9@gated-at.bofh.it>
On Mon, 2015-09-07 at 20:22 +0100, Juvva, Kanaka D wrote:
> Hi Thomas,
>  
>    I'm sending updated patch(s). I have given details for each of
> these items below.
>  

Kanaka, this email is HTML formatted and so has been blocked by
vger.kernel.org where the linux-kernel mailing list is hosted.

Please configure outlook not to send html email, or use a different mail
agent for working with upstream.

> Regards,
> -Kanaka
>  
> > -----Original Message-----
> > From: Thomas Gleixner [mailto:tglx@linutronix.de]
> > Sent: Wednesday, August 19, 2015 1:50 PM
> > To: Kanaka Juvva
> > Cc: Juvva, Kanaka D; Williamson, Glenn P; Fleming, Matt; Auld, Will;
> Andi Kleen;
> > LKML; Luck, Tony; Peter Zijlstra; Tejun Heo; x86@kernel.org; Ingo
> Molnar; H.
> > Peter Anvin; Shivappa, Vikas
> > Subject: Re: [PATCH v3 1/2] perf,x86: add Intel Memory Bandwidth
> Monitoring
> > (MBM) PMU
> > 
> > On Fri, 7 Aug 2015, Kanaka Juvva wrote:
> > > +#define MBM_CNTR_MAX               0xffffff
> > > +#define MBM_SOCKET_MAX             8
> > > +#define MBM_TIME_DELTA_MAX 1000
> > > +#define MBM_TIME_DELTA_MIN 100
> > 
> > What are these constants for and how are they determined? Pulled out of thin
> > air?
> > 
>  
> /*                                                                                                                                 
> * MBM Counter is 24bits wide. MBM_CNTR_MAX defines max counter                                                                    
> * value                                                                                                                           
> */ 
> #define MBM_CNTR_MAX            0xffffff 
> /*                                                                                                                                 
> * Max #sockets supported                                                                                                          
> */ 
> #define MBM_SOCKET_MAX          8 

This seems like a constant we could get by without. Do we really need to
know this at compile time?

> /*                                                                                                                                 
> * Expected time interval between consecutive MSR reads for a given rmid                                                           
> */ 
> #define MBM_TIME_DELTA_MAX      1000 

"max" and "expected" are not the same thing.


> > >  #define QOS_L3_OCCUP_EVENT_ID      (1 << 0)
> > > +#define QOS_MBM_TOTAL_EVENT_ID     (1 << 1)
> > > +#define QOS_MBM_LOCAL_EVENT_ID_HW   0x3
> > > +#define QOS_MBM_LOCAL_EVENT_ID     (1 << 2)
> > 
> > So we have ID values which are built with (1 << X) and then this HW variant in the
> > middle with 0x3. Of course without any explanation what the heck this stuff is.
> > 
> > Last review:
> > 
> >      "So this wants a descriptive ID name and a comment."
> > 
> > 
>  
> /*                                                                                                                                 
> * MBM Event IDs as defined in SDM section 17.14.6                                                                                 
> * Event IDs used to program MSRs for reading counters                                                                             
> */ 
> #define QOS_MBM_TOTAL_EVENT_ID  (1 << 1) 
> #define QOS_MBM_LOCAL_EVENT_ID_HW        0x3 
> /*                                                                                                                                 
> * Perf needs event id to be 1 << x, hence we can't use 0x3 (HW EVENT ID)                                                          
> * for MBM_LOCAL_EVENT we use next 1 << x for MBM_LOCAL_EVENT_ID                                                                   
> */ 
> #define QOS_MBM_LOCAL_EVENT_ID  (1 << 2)

No, perf events do not need to be of the form (1 << X), that was just a
convention we used in the cqm code before we knew what values the MBM
events would take - you can change these to be whatever format you want,
but be sure to make it consistent.

The constants are very much supposed to be programmed into the MSRs,
take a look at __rmid_read().

I would suggest (as I already did privately) that you change the format
to be 0x0x for all of these event IDs.
 

> > > @@ static bool intel_cqm_sched_in_event(u32 rmid)
> > >      return false;
> > >  }
> > >
> > > +
> > > +static u32 bw_sum_calc(struct sample *bw_stat, int rmid) {
> > > +   u32 val = 0, i, j, index;
> > > +
> > > +   if (++bw_stat->fifoout >=  mbm_window_size)
> > > +           bw_stat->fifoout =  0;
> > > +   index =  bw_stat->fifoout;
> > > +   for (i = 0; i < mbm_window_size - 1; i++) {
> > > +           if (index + i >= mbm_window_size)
> > > +                   j = index + i - mbm_window_size;
> > > +           else
> > > +                   j = index + i;
> > > +           val += bw_stat->mbmfifo[j];
> > > +   }
> > 
> > This math wants a explanatory comment.
> > 
> /*                                                                                                                                 
> * Slide the window by 1 and calculate the sum of the last                                                                         
> * mbm_window_size-1  bandwidth  values.                                                                                           
> * fifoout is the current position of the window.                                                                                  
> * Increment the fifoout by 1 to slide the window by 1.                                                                            
> *                                                                                                                                 
> * Calcalute the bandwidth from ++fifiout  to ( ++fifoout + mbm_window_size -1)                                                    
> * e.g.fifoout =1;   Bandwidth1 Bandwidth2 ..... Bandwidthn are the                                                                
> * sliding window values where n is size of the sliding window                                                                     
> *  bandwidth sum:  val  =  Bandwidth2 + Bandwidth3 + .. Bandwidthn                                                                
> */

Instead of these large comment blocks please comment smaller,
logically-connected chunks of code, e.g.

	/* Slide the window by one */
	if (++bw_stat->fifoout >= mbm_window_size)
		bw_stat->fifoout = 0;

	/*
	 * Calculate the sum of last mbm_window_size-1 values.
	 */
	for (i = 0; i < mbm_window_size - 1; i++) {
		/* Handle wraparound at end of window */
		if (index + i >= mbm_window_size)
			j = index + i - mbm_window_size;
		else
			j = index + i;

		val += bw_stat->mbminfo[j];
	}
 
>  
>  
> > > +   return val;
> > > +}
> > > +
> > > +static u32 __mbm_fifo_sum_lastn_out(int rmid, bool is_localbw) {
> > > +   if (is_localbw)
> > > +           return bw_sum_calc(&mbm_local[rmid], rmid);
> > > +   else
> > > +           return bw_sum_calc(&mbm_total[rmid], rmid); }
> > > +
> > > +static void __mbm_fifo_in(struct sample *bw_stat, u32 val) {
> > > +   bw_stat->mbmfifo[bw_stat->fifoin] = val;
> > > +   if (++bw_stat->fifoin >= mbm_window_size)
> > 
> > How does that become greater than mbm_windowsize?
> > 
>  
> This is fixed by changing >= to ==
> Added a comment:
>  
> /*                                                                                                                                 
> * store current sample's bw value in sliding window at the                                                                        
> * index fifoin. Increment fifoin. Check if fifoin has reached                                                                     
> * max_window_size. If yes reset it to begining i.e. zero                                                                          
> * e.g.                                                                                                                            
> * mbm_window_size = 10                                                                                                            
> * mbmfifo is a circular fifo   0 1 2 3 4 5 6 7 8 9 10                                                                             
> *                                          ^                               |                                                                             
> *                                               |                               |                                                                             
> *                                                | _ _ _ _ _ _ _ _ _ _|                                                                             
> *                                                                                                                                 
> * So when fifoin becomes 10, then it is reset to zero                                                                             
> *                                                                                                                                 
> */

I'm not sure that this comment adds anything of value that isn't already
understood by reading the code. I don't think you need a comment for
this function, it seems pretty straight forward and Thomas' question was
about the boundary limits of ->fifoin.

> > > +           bw_stat->fifoin = 0;
> > > +}
> > 
> > > +/*
> > > + * __rmid_read_mbm checks whether it is LOCAL or GLOBAL MBM event and
> > > +reads
> > > + * its MSR counter. Check whether overflow occurred and handles it.
> > > +Calculates
> > > + * currenet  BW and updates  running average.
> > 
> > currenet? And please get rid of the double spaces
> > 
> This is fixed now.  Here is the updated comment:
>  
> /*                                                                                                                                                                                          
> * rmid_read_mbm checks whether it is LOCAL or Total MBM event and reads                                                                                                                    
> * its MSR counter. Check whether overflow occured and handles it. Calculates                                                                                                               
> * currenet  BW and updates  running average.                                                                                                                                               
> *            

^^^ You've still misspelled current.
>                                                                                                                                                                               
> * Overflow Handling:                                                                                                                                                                       
> * if (MSR current value < MSR previous value) it is an                                                                                                                                     
> * overflow. MSR values are increasing when bandwidth consumption for the thread                                                                                                            
> * is non-zero; When MSR values reaches MAX_COUNTER_VALUE it overflows. After overflow,                                                                                                     
> * MSR current value goes back to zero and starts increasing again at the rate of                                                                                                           
> * bandwidth.                                                                                                                                                                               
> *

You don't need to provide a definition of "overflow", most people will
be familiar with it. What is more important to document is how the
overflow is handled...
>                                                                                                                                                                                           
> * Overflow handling:                                                                                                                                                                       
> * Detect an overflow :  current read value > last read value  

Isn't this inverted? Overflow occurred if current < previous.

>                                                                                                                              
> * Overflow correction:  if (overflow)                                                                                                                                                      
> *                          Current value = (MAX_COUNTER_VALUE - prev read value) + current read value                                                                                      
> *                       else                                                                                                                                                               
> *                          Current value = current read value                                                                                                                              
> *                                                                

Please don't write pseudocode in the comments. Use English prose to
describe the important parts of the code.

>                                                                                                                           
> * Calculation of Current Bandwidth value:                                                                                                                                                  
> * If MSR is read within last 100ms, then then the smaple is ignored;                                                                                                                       
> * If the MSR was Read with in last 100ms, why  incur an extra overhead                                                                                                                     
> * of doing the MSR reads again. Anyway there'll be a negligible change or zero                                                                                                             
> * change in MSR readings in 100ms.                                                                                                                                                         
> *                                                                                                                                                                                          
> * Bandwidth is calculated as:                                                                                                                                                              
> * memory bandwidth = difference of last two msr counter values/time difference.                                                                                                            
> *                                                                                                                                                                                          
> * cum_avg = Running Average bandwidth of last 'n' bandwidth values for                                                                                                                     
> * the samples that are processed                                                                                                                                                           
> *                                     

Where 'n' is 'mbm_window_size' ? If so, please use 'mbm_window_size',
not 'n'.
>                                                                                                                                                      
> * Sliding window is used to save the last 'n' samples. Where,                                                                                                                              
> * n = sliding_window_size and results in sliding window duration of 'n' secs.

Hmm... this confuses me a lot. Is 'n' a size or a duration? The two are
not the same thing.

>                                                                                                               
> * The sliding window size by default set to                                                                                                                                                
> * MBM_FIFO_SIZE_MIN. User can configure it to the values in the range                                                                                                                      
> * (MBM_FIFO_SIZE_MIN,MBM_FIFO_SIZE_MAX). The range for sliding window                                                                                                                      
> * is chosen based on a general criteria for monitoring duration. Example                                                                                                                   
> * for a short lived application, 10sec monitoring period gives                                                                                                                             
> * good characterization of its bandwidth consumption. For an application     
> * that runs for longer duration, 300sec monitoring period gives better                                                                                                                     
> * characterization of its bandwidth consumption. Since the running average                                                                                                                 
> * calculated for total monitoring period, user gets the most accuracate                                                                                                                    
> * average bandwidth for the each monitoring period.                                                                                                                                        
> *                                                                                                                                                                                          
> * Scaling:                                                                                                                                                                                 
> * cum_avg is the raw bandwidth is Bytes/sec.                                                                                                                                               
> * cum_avg is converted to MB/sec by applying  MBM_CONVERSION_FACTOR and                                                                                                                    
> * rounded to nearest integer. User interface gets the Bandwidth values in MB/sec.                                                                                                          
> *                                                                                                                                                                                          
> */
> > > + *
> > > + * Overflow Handling:
> > > + * if (MSR current value < MSR previous value) it is an
> > > + * overflow. and overflow is handled.
> > 
> > Wow. That's informative as hell!
> > 
> Please look at the modified comment above 
> > > + *
> > > + * Calculation of Current BW value:
> > 
> > BW == Body Weight?
> > 
>  
> It is fixed now 
>  
> > > + * If MSR is read within last 100ms, then the value is ignored;
> > > + * this will suppress small deltas. We don't process MBM samples that
> > > + are
> > > + * within 100ms.
> > 
> > WHY?
> > 
> Explained in the comment. If mbm_read is called within in 100ms for the same rmid, we don’t 
> have to process the sample. 

The key piece of information you're missing here is that skipping these
small deltas is an optimization, because we avoid performing costly
operations for what would likely be a very minor change in the MBM data,
right?


> > > +{
> > > +   u64 val, tmp, diff_time, cma, bytes, index;
> > > +   bool overflow = false, first = false;
> > > +   ktime_t cur_time;
> > > +   u32 tmp32 = rmid;
> > > +   struct sample *mbm_current;
> > > +   u32 vrmid = topology_physical_package_id(smp_processor_id()) *
> > > +                                            cqm_max_rmid + rmid;
> > > +
> > > +   rmid = vrmid;
> > 
> > From my previous review:
> > 
> >   "This is completely backwards.
> > 
> >        tmp32 = rmid;
> >        rmid = vrmid;
> >        do_stuff(rmid);
> >        rmid = tmp32;
> >        do_other_stuff(rmid);
> > 
> >    Why can't you use vrmid for do_stuff() and leave rmid alone? Just
> >    because it would make the code simpler to read?"
> > 
> > Still applies.
> > 
>  
> This is now changed to 
> u64 val, currentmsr, currentbw, diff_time, cma, bytes, index;                                                                                                                       
>         bool overflow = false, first = false; 
>         ktime_t cur_time; 
>         u32 tmp32 = rmid, eventid; 
>         struct sample *mbm_current; 
>         u32 vrmid = rmid_2_index(rmid); 
>  
>         rmid = vrmid;
>         cur_time = ktime_get(); 
>         if (read_mbm_local) { 
>                 mbm_current = &mbm_local[vrmid]; 
>                 eventid     =  QOS_MBM_LOCAL_EVENT_ID_HW; 
>                 wrmsr(MSR_IA32_QM_EVTSEL, QOS_MBM_LOCAL_EVENT_ID_HW, rmid); 

You don't need to perform this wrmsr() here because it's taken care of
in the common code below.

>         } else { 
>                 mbm_current = &mbm_total[vrmid]; 
>                 eventid     = QOS_MBM_TOTAL_EVENT_ID; 
>         } 
>         rmid = tmp32; 

Why did you assign rmid to vrmid if you reassign it before it was used?


> > > +   /* if current msr value <  previous msr value ,  it means overflow */
> > > +   if (val < bytes) {
> > > +           val = MBM_CNTR_MAX - bytes + val;
> > > +           overflow = true;
> > > +   } else
> > > +           val = val - bytes;
> > > +
> > > +   val =  (val * MBM_TIME_DELTA_MAX) / diff_time;
> > > +
> > > +   if ((diff_time > MBM_TIME_DELTA_MAX) && (!cma))
> > > +           /* First sample */
> > > +           first = true;
> > > +
> > > +   rmid = vrmid;
> > 
> > And another time:
> > 
> >   "More obfuscation"
> > 
>  
>        /*                                                                                                                         
>          * MBM_TIME_DELTA_MAX is picked as per MBM specs. As specified in Intel Platform                                           
>          * Quality of Service Monitoring Implementer's Guide V1, Section 2.7.2. page 21,                                             
>          * overflow can occur maximum once in a second. So latest we want to read the MSR                                          
>          * counters is 1000ms. If it is less than 1000ms we can  ignore the sample. Then we                                        
>          * decide since when we should ignore. If the MSR was Read with in last 100ms, why                                         
>          * process the MSR reads again. Anyway there'll be small change or zero change.                                            
>          * So ignoring MSR Reads within 100ms or less is efficient. MBM_TIME_DELTA_MIN                                             
>          * is specified as 100ms as per this guideline.                                                                            
>          *                                                                                                                         
>          */ 

I suspect the document you're referring to above is only available under
NDA, which makes it unsuitable for mention in the kernel source since a
large number of people won't have access to it.

Just explain that the way the hardware is designed puts an upper limit
on how quickly the counter can overflow, which is once per second.


> > > +static void __intel_cqm_event_total_bw_count(void *info) {
> > > +   struct rmid_read *rr = info;
> > > +   u64 val;
> > > +
> > > +   val = __rmid_read_mbm(rr->rmid, false);
> > > +   if (val & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL))
> > > +           return;
> > > +   atomic64_add(val, &rr->value);
> > > +}
> > > +
> > > +static void __intel_cqm_event_local_bw_count(void *info) {
> > > +   struct rmid_read *rr = info;
> > > +   u64 val;
> > > +
> > > +   val = __rmid_read_mbm(rr->rmid, true);
> > > +   if (val & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL))
> > > +           return;
> > > +   atomic64_add(val, &rr->value);
> > > +}
> > 
> > And once more:
> > 
> >   "You're really a fan of copy and paste."
> > 
>  
> These functions are invoked indirectly. They were written keeping intel_cqm_event_count in  mind.
> I’ll change the arg to struct   mbm_read{
>                                                      struct rmid_read *rr;
>                                                      u32 eventid;
>                                                    }; 
> Intel_cqm_event_*_bw_count(….) needs eventid to call for decoding

No, please do not duplicate the rmid_read structure, that is not an
improvement, we don't need two different structs for reading the read
data.

Please add the event field to the existing struct rmid_read.


> > > @@ -1023,6 +1437,17 @@ static void intel_cqm_event_stop(struct
> > perf_event *event, int mode)
> > >      } else {
> > >              WARN_ON_ONCE(!state->rmid);
> > >      }
> > > +
> > > +   if (pmu) {
> > > +           if (pmu->n_active >  0) {
> > 
> > What's the purpose of this check? In the previous version there was a
> > WARN_ON(), which made sense. Did it trigger and you decided to "work"
> > around it?
> > 
>  
> We actually meant to check if there are active events

I don't follow this answer. Are you saying that the WARN_ON() doesn't
make sense here?



>  
> > > +EVENT_ATTR_STR(llc_total_bw.unit, intel_cqm_llc_total_bw_unit,
> > > +"KB/sec"); EVENT_ATTR_STR(llc_local_bw.unit,
> > > +intel_cqm_llc_local_bw_unit, "KB/sec"); #endif
> > 
> > > +static ssize_t
> > > +sliding_window_size_store(struct device *dev,
> > > +                     struct device_attribute *attr,
> > > +                     const char *buf, size_t count)
> > > +{
> > > +   unsigned int bytes;
> > > +   int ret;
> > > +
> > > +   ret = kstrtouint(buf, 0, &bytes);
> > > +   if (ret)
> > > +           return ret;
> > > +
> > > +   mutex_lock(&cache_mutex);
> > > +   if (bytes > 0 && bytes <= MBM_FIFO_SIZE_MAX)
> > > +           mbm_window_size = bytes;
> > 
> > So, it's valid to set the window to X where 0 < X < MBM_FIFO_SIZE_MIN.
> > What's the actual purpose of MBM_FIFO_SIZE_MIN?
> > 
> This is changed to 
> if (bytes >= MBM_FIFO_SIZE_MIN && bytes <= MBM_FIFO_SIZE_MAX)
>                 mbm_window_size = bytes;

Note that if the user passes a value outside of this range you should be
returning -EINVAL to indicate that.


> > > +           pmu->timer_interval = ms_to_ktime(MBM_TIME_DELTA_MAX);
> > > +           per_cpu(mbm_pmu, cpu) = pmu;
> > > +           per_cpu(mbm_pmu_to_free, cpu) = NULL;
> > 
> > What's the point of this? If there is still something to be free'd its leaked.
> > Otherwise that's redundant.
> per_cpu(mbm_pmu_to_free, cpu) = NULL; is removed
>  
> > > +           mbm_hrtimer_init(pmu);
> > > +   }
> > > +   return 0;
> > 
> > s/0/NOTIFY_OK/ because you return that value directly.
> > 
> You mean I return the ‘return code’

?

You should be using NOTIFY_OK here so that you follow the notifier API
convention.


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1220953

From"Juvva, Kanaka D" <kanaka.d.juvva@intel.com>
Date2015-09-08 18:20 +0200
Message-ID<q6tMJ-Vo-5@gated-at.bofh.it>
In reply to#1220719
SGkgTWF0dCwNCg0KICBUaGlzIGlzIHJlZ2FyZGluZyBFdmVudCBJRHMgIGZvciBwZXJmIGV2ZW50
Og0KDQpUaGVyZSBhcmUgdHdvIGFzcGVjdHM6DQoNCiAxKSBQcm9ncmFtbWluZyBNU1JzDQogMikg
RVZFTlRfQVRUUl9TVFIobGxjX2xvY2FsX2J3LCBpbnRlbF9jcW1fbGxjX2xvY2FsX2J3LCAiZXZl
bnQ9MHgwNCIpOw0KDQogMSBpcyB1c2VkIGZvciBwcm9ncmFtbWluZyBNU1JzDQogMiBldmVudCBh
dHRyaWJ1dGUgZm9yIHBlcmYNCiAgDQoNCiBGb3IgTUJNX0xPQ0FMX0VWRU5UIEhXIElEIGlzIDB4
My4gV2UgZG9uJ3Qgd2FudCB0byB1c2UgMHgzIGZvciBFVkVOVCBBVFRSLiANCg0KSWYgd2UgdXNl
IDB4MyBmb3IgZXZlbnRfYXR0cmlidXRlDQoNCldlIGNhbid0IGNsZWFybHkgZGlzdGluZ3Vpc2gg
d2hldGhlciBpcyBFVkVOVCAwMSAmIEVWRU5UIDAyIG9yIEVWRU5UIDAzIGFsb25lLg0KIEZvciBw
ZXJmIGV2ZW50IGF0dHJpYnV0ZSAgaXQgaGFzIHRvIGJlIDB4MDQuIEJlY2F1c2UgMHgwMSBhbmQg
MHgwMiBhcmUgdXNlZCBmb3Igb3RoZXIgdG93DQoNCiBUaGFua3MsDQotS2FuYWthDQoNCj4gLS0t
LS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogRmxlbWluZywgTWF0dA0KPiBTZW50OiBU
dWVzZGF5LCBTZXB0ZW1iZXIgOCwgMjAxNSA0OjQ3IEFNDQo+IFRvOiBKdXZ2YSwgS2FuYWthIEQN
Cj4gQ2M6IFRob21hcyBHbGVpeG5lcjsgS2FuYWthIEp1dnZhOyBXaWxsaWFtc29uLCBHbGVubiBQ
OyBBdWxkLCBXaWxsOyBBbmRpIEtsZWVuOw0KPiBMS01MOyBMdWNrLCBUb255OyBQZXRlciBaaWps
c3RyYTsgVGVqdW4gSGVvOyB4ODZAa2VybmVsLm9yZzsgSW5nbyBNb2xuYXI7IEguDQo+IFBldGVy
IEFudmluOyBTaGl2YXBwYSwgVmlrYXMNCj4gU3ViamVjdDogUmU6IFtQQVRDSCB2MyAxLzJdIHBl
cmYseDg2OiBhZGQgSW50ZWwgTWVtb3J5IEJhbmR3aWR0aCBNb25pdG9yaW5nDQo+IChNQk0pIFBN
VQ0KPiANCj4gT24gTW9uLCAyMDE1LTA5LTA3IGF0IDIwOjIyICswMTAwLCBKdXZ2YSwgS2FuYWth
IEQgd3JvdGU6DQo+ID4gSGkgVGhvbWFzLA0KPiA+DQo+ID4gICAgSSdtIHNlbmRpbmcgdXBkYXRl
ZCBwYXRjaChzKS4gSSBoYXZlIGdpdmVuIGRldGFpbHMgZm9yIGVhY2ggb2YNCj4gPiB0aGVzZSBp
dGVtcyBiZWxvdy4NCj4gPg0KPiANCj4gS2FuYWthLCB0aGlzIGVtYWlsIGlzIEhUTUwgZm9ybWF0
dGVkIGFuZCBzbyBoYXMgYmVlbiBibG9ja2VkIGJ5DQo+IHZnZXIua2VybmVsLm9yZyB3aGVyZSB0
aGUgbGludXgta2VybmVsIG1haWxpbmcgbGlzdCBpcyBob3N0ZWQuDQo+IA0KPiBQbGVhc2UgY29u
ZmlndXJlIG91dGxvb2sgbm90IHRvIHNlbmQgaHRtbCBlbWFpbCwgb3IgdXNlIGEgZGlmZmVyZW50
IG1haWwgYWdlbnQNCj4gZm9yIHdvcmtpbmcgd2l0aCB1cHN0cmVhbS4NCj4gDQo+ID4gUmVnYXJk
cywNCj4gPiAtS2FuYWthDQo+ID4NCj4gPiA+IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQo+
ID4gPiBGcm9tOiBUaG9tYXMgR2xlaXhuZXIgW21haWx0bzp0Z2x4QGxpbnV0cm9uaXguZGVdDQo+
ID4gPiBTZW50OiBXZWRuZXNkYXksIEF1Z3VzdCAxOSwgMjAxNSAxOjUwIFBNDQo+ID4gPiBUbzog
S2FuYWthIEp1dnZhDQo+ID4gPiBDYzogSnV2dmEsIEthbmFrYSBEOyBXaWxsaWFtc29uLCBHbGVu
biBQOyBGbGVtaW5nLCBNYXR0OyBBdWxkLCBXaWxsOw0KPiA+IEFuZGkgS2xlZW47DQo+ID4gPiBM
S01MOyBMdWNrLCBUb255OyBQZXRlciBaaWpsc3RyYTsgVGVqdW4gSGVvOyB4ODZAa2VybmVsLm9y
ZzsgSW5nbw0KPiA+IE1vbG5hcjsgSC4NCj4gPiA+IFBldGVyIEFudmluOyBTaGl2YXBwYSwgVmlr
YXMNCj4gPiA+IFN1YmplY3Q6IFJlOiBbUEFUQ0ggdjMgMS8yXSBwZXJmLHg4NjogYWRkIEludGVs
IE1lbW9yeSBCYW5kd2lkdGgNCj4gPiBNb25pdG9yaW5nDQo+ID4gPiAoTUJNKSBQTVUNCj4gPiA+
DQo+ID4gPiBPbiBGcmksIDcgQXVnIDIwMTUsIEthbmFrYSBKdXZ2YSB3cm90ZToNCj4gPiA+ID4g
KyNkZWZpbmUgTUJNX0NOVFJfTUFYICAgICAgICAgICAgICAgMHhmZmZmZmYNCj4gPiA+ID4gKyNk
ZWZpbmUgTUJNX1NPQ0tFVF9NQVggICAgICAgICAgICAgOA0KPiA+ID4gPiArI2RlZmluZSBNQk1f
VElNRV9ERUxUQV9NQVggMTAwMA0KPiA+ID4gPiArI2RlZmluZSBNQk1fVElNRV9ERUxUQV9NSU4g
MTAwDQo+ID4gPg0KPiA+ID4gV2hhdCBhcmUgdGhlc2UgY29uc3RhbnRzIGZvciBhbmQgaG93IGFy
ZSB0aGV5IGRldGVybWluZWQ/IFB1bGxlZCBvdXQNCj4gPiA+IG9mIHRoaW4gYWlyPw0KPiA+ID4N
Cj4gPg0KPiA+IC8qDQo+ID4gKiBNQk0gQ291bnRlciBpcyAyNGJpdHMgd2lkZS4gTUJNX0NOVFJf
TUFYIGRlZmluZXMgbWF4IGNvdW50ZXINCj4gPiAqIHZhbHVlDQo+ID4gKi8NCj4gPiAjZGVmaW5l
IE1CTV9DTlRSX01BWCAgICAgICAgICAgIDB4ZmZmZmZmDQo+ID4gLyoNCj4gPiAqIE1heCAjc29j
a2V0cyBzdXBwb3J0ZWQNCj4gPiAqLw0KPiA+ICNkZWZpbmUgTUJNX1NPQ0tFVF9NQVggICAgICAg
ICAgOA0KPiANCj4gVGhpcyBzZWVtcyBsaWtlIGEgY29uc3RhbnQgd2UgY291bGQgZ2V0IGJ5IHdp
dGhvdXQuIERvIHdlIHJlYWxseSBuZWVkIHRvIGtub3cNCj4gdGhpcyBhdCBjb21waWxlIHRpbWU/
DQo+IA0KPiA+IC8qDQo+ID4gKiBFeHBlY3RlZCB0aW1lIGludGVydmFsIGJldHdlZW4gY29uc2Vj
dXRpdmUgTVNSIHJlYWRzIGZvciBhIGdpdmVuIHJtaWQNCj4gPiAqLw0KPiA+ICNkZWZpbmUgTUJN
X1RJTUVfREVMVEFfTUFYICAgICAgMTAwMA0KPiANCj4gIm1heCIgYW5kICJleHBlY3RlZCIgYXJl
IG5vdCB0aGUgc2FtZSB0aGluZy4NCj4gDQo+IA0KPiA+ID4gPiAgI2RlZmluZSBRT1NfTDNfT0ND
VVBfRVZFTlRfSUQgICAgICAoMSA8PCAwKQ0KPiA+ID4gPiArI2RlZmluZSBRT1NfTUJNX1RPVEFM
X0VWRU5UX0lEICAgICAoMSA8PCAxKQ0KPiA+ID4gPiArI2RlZmluZSBRT1NfTUJNX0xPQ0FMX0VW
RU5UX0lEX0hXICAgMHgzDQo+ID4gPiA+ICsjZGVmaW5lIFFPU19NQk1fTE9DQUxfRVZFTlRfSUQg
ICAgICgxIDw8IDIpDQo+ID4gPg0KPiA+ID4gU28gd2UgaGF2ZSBJRCB2YWx1ZXMgd2hpY2ggYXJl
IGJ1aWx0IHdpdGggKDEgPDwgWCkgYW5kIHRoZW4gdGhpcyBIVw0KPiA+ID4gdmFyaWFudCBpbiB0
aGUgbWlkZGxlIHdpdGggMHgzLiBPZiBjb3Vyc2Ugd2l0aG91dCBhbnkgZXhwbGFuYXRpb24gd2hh
dCB0aGUNCj4gaGVjayB0aGlzIHN0dWZmIGlzLg0KPiA+ID4NCj4gPiA+IExhc3QgcmV2aWV3Og0K
PiA+ID4NCj4gPiA+ICAgICAgIlNvIHRoaXMgd2FudHMgYSBkZXNjcmlwdGl2ZSBJRCBuYW1lIGFu
ZCBhIGNvbW1lbnQuIg0KPiA+ID4NCj4gPiA+DQo+ID4NCj4gPiAvKg0KPiA+ICogTUJNIEV2ZW50
IElEcyBhcyBkZWZpbmVkIGluIFNETSBzZWN0aW9uIDE3LjE0LjYNCj4gPiAqIEV2ZW50IElEcyB1
c2VkIHRvIHByb2dyYW0gTVNScyBmb3IgcmVhZGluZyBjb3VudGVycw0KPiA+ICovDQo+ID4gI2Rl
ZmluZSBRT1NfTUJNX1RPVEFMX0VWRU5UX0lEICAoMSA8PCAxKQ0KPiA+ICNkZWZpbmUgUU9TX01C
TV9MT0NBTF9FVkVOVF9JRF9IVyAgICAgICAgMHgzDQo+ID4gLyoNCj4gPiAqIFBlcmYgbmVlZHMg
ZXZlbnQgaWQgdG8gYmUgMSA8PCB4LCBoZW5jZSB3ZSBjYW4ndCB1c2UgMHgzIChIVyBFVkVOVCBJ
RCkNCj4gPiAqIGZvciBNQk1fTE9DQUxfRVZFTlQgd2UgdXNlIG5leHQgMSA8PCB4IGZvciBNQk1f
TE9DQUxfRVZFTlRfSUQNCj4gPiAqLw0KPiA+ICNkZWZpbmUgUU9TX01CTV9MT0NBTF9FVkVOVF9J
RCAgKDEgPDwgMikNCj4gDQo+IE5vLCBwZXJmIGV2ZW50cyBkbyBub3QgbmVlZCB0byBiZSBvZiB0
aGUgZm9ybSAoMSA8PCBYKSwgdGhhdCB3YXMganVzdCBhDQo+IGNvbnZlbnRpb24gd2UgdXNlZCBp
biB0aGUgY3FtIGNvZGUgYmVmb3JlIHdlIGtuZXcgd2hhdCB2YWx1ZXMgdGhlIE1CTQ0KPiBldmVu
dHMgd291bGQgdGFrZSAtIHlvdSBjYW4gY2hhbmdlIHRoZXNlIHRvIGJlIHdoYXRldmVyIGZvcm1h
dCB5b3Ugd2FudCwgYnV0DQo+IGJlIHN1cmUgdG8gbWFrZSBpdCBjb25zaXN0ZW50Lg0KPiANCj4g
VGhlIGNvbnN0YW50cyBhcmUgdmVyeSBtdWNoIHN1cHBvc2VkIHRvIGJlIHByb2dyYW1tZWQgaW50
byB0aGUgTVNScywgdGFrZSBhDQo+IGxvb2sgYXQgX19ybWlkX3JlYWQoKS4NCj4gDQo+IEkgd291
bGQgc3VnZ2VzdCAoYXMgSSBhbHJlYWR5IGRpZCBwcml2YXRlbHkpIHRoYXQgeW91IGNoYW5nZSB0
aGUgZm9ybWF0IHRvIGJlDQo+IDB4MHggZm9yIGFsbCBvZiB0aGVzZSBldmVudCBJRHMuDQo+IA0K
PiANCj4gPiA+ID4gQEAgc3RhdGljIGJvb2wgaW50ZWxfY3FtX3NjaGVkX2luX2V2ZW50KHUzMiBy
bWlkKQ0KPiA+ID4gPiAgICAgIHJldHVybiBmYWxzZTsNCj4gPiA+ID4gIH0NCj4gPiA+ID4NCj4g
PiA+ID4gKw0KPiA+ID4gPiArc3RhdGljIHUzMiBid19zdW1fY2FsYyhzdHJ1Y3Qgc2FtcGxlICpi
d19zdGF0LCBpbnQgcm1pZCkgew0KPiA+ID4gPiArICAgdTMyIHZhbCA9IDAsIGksIGosIGluZGV4
Ow0KPiA+ID4gPiArDQo+ID4gPiA+ICsgICBpZiAoKytid19zdGF0LT5maWZvb3V0ID49ICBtYm1f
d2luZG93X3NpemUpDQo+ID4gPiA+ICsgICAgICAgICAgIGJ3X3N0YXQtPmZpZm9vdXQgPSAgMDsN
Cj4gPiA+ID4gKyAgIGluZGV4ID0gIGJ3X3N0YXQtPmZpZm9vdXQ7DQo+ID4gPiA+ICsgICBmb3Ig
KGkgPSAwOyBpIDwgbWJtX3dpbmRvd19zaXplIC0gMTsgaSsrKSB7DQo+ID4gPiA+ICsgICAgICAg
ICAgIGlmIChpbmRleCArIGkgPj0gbWJtX3dpbmRvd19zaXplKQ0KPiA+ID4gPiArICAgICAgICAg
ICAgICAgICAgIGogPSBpbmRleCArIGkgLSBtYm1fd2luZG93X3NpemU7DQo+ID4gPiA+ICsgICAg
ICAgICAgIGVsc2UNCj4gPiA+ID4gKyAgICAgICAgICAgICAgICAgICBqID0gaW5kZXggKyBpOw0K
PiA+ID4gPiArICAgICAgICAgICB2YWwgKz0gYndfc3RhdC0+bWJtZmlmb1tqXTsNCj4gPiA+ID4g
KyAgIH0NCj4gPiA+DQo+ID4gPiBUaGlzIG1hdGggd2FudHMgYSBleHBsYW5hdG9yeSBjb21tZW50
Lg0KPiA+ID4NCj4gPiAvKg0KPiA+ICogU2xpZGUgdGhlIHdpbmRvdyBieSAxIGFuZCBjYWxjdWxh
dGUgdGhlIHN1bSBvZiB0aGUgbGFzdA0KPiA+ICogbWJtX3dpbmRvd19zaXplLTEgIGJhbmR3aWR0
aCAgdmFsdWVzLg0KPiA+ICogZmlmb291dCBpcyB0aGUgY3VycmVudCBwb3NpdGlvbiBvZiB0aGUg
d2luZG93Lg0KPiA+ICogSW5jcmVtZW50IHRoZSBmaWZvb3V0IGJ5IDEgdG8gc2xpZGUgdGhlIHdp
bmRvdyBieSAxLg0KPiA+ICoNCj4gPiAqIENhbGNhbHV0ZSB0aGUgYmFuZHdpZHRoIGZyb20gKytm
aWZpb3V0ICB0byAoICsrZmlmb291dCArIG1ibV93aW5kb3dfc2l6ZSAtDQo+IDEpDQo+ID4gKiBl
LmcuZmlmb291dCA9MTsgICBCYW5kd2lkdGgxIEJhbmR3aWR0aDIgLi4uLi4gQmFuZHdpZHRobiBh
cmUgdGhlDQo+ID4gKiBzbGlkaW5nIHdpbmRvdyB2YWx1ZXMgd2hlcmUgbiBpcyBzaXplIG9mIHRo
ZSBzbGlkaW5nIHdpbmRvdw0KPiA+ICogIGJhbmR3aWR0aCBzdW06ICB2YWwgID0gIEJhbmR3aWR0
aDIgKyBCYW5kd2lkdGgzICsgLi4gQmFuZHdpZHRobg0KPiA+ICovDQo+IA0KPiBJbnN0ZWFkIG9m
IHRoZXNlIGxhcmdlIGNvbW1lbnQgYmxvY2tzIHBsZWFzZSBjb21tZW50IHNtYWxsZXIsIGxvZ2lj
YWxseS0NCj4gY29ubmVjdGVkIGNodW5rcyBvZiBjb2RlLCBlLmcuDQo+IA0KPiAJLyogU2xpZGUg
dGhlIHdpbmRvdyBieSBvbmUgKi8NCj4gCWlmICgrK2J3X3N0YXQtPmZpZm9vdXQgPj0gbWJtX3dp
bmRvd19zaXplKQ0KPiAJCWJ3X3N0YXQtPmZpZm9vdXQgPSAwOw0KPiANCj4gCS8qDQo+IAkgKiBD
YWxjdWxhdGUgdGhlIHN1bSBvZiBsYXN0IG1ibV93aW5kb3dfc2l6ZS0xIHZhbHVlcy4NCj4gCSAq
Lw0KPiAJZm9yIChpID0gMDsgaSA8IG1ibV93aW5kb3dfc2l6ZSAtIDE7IGkrKykgew0KPiAJCS8q
IEhhbmRsZSB3cmFwYXJvdW5kIGF0IGVuZCBvZiB3aW5kb3cgKi8NCj4gCQlpZiAoaW5kZXggKyBp
ID49IG1ibV93aW5kb3dfc2l6ZSkNCj4gCQkJaiA9IGluZGV4ICsgaSAtIG1ibV93aW5kb3dfc2l6
ZTsNCj4gCQllbHNlDQo+IAkJCWogPSBpbmRleCArIGk7DQo+IA0KPiAJCXZhbCArPSBid19zdGF0
LT5tYm1pbmZvW2pdOw0KPiAJfQ0KPiANCj4gPg0KPiA+DQo+ID4gPiA+ICsgICByZXR1cm4gdmFs
Ow0KPiA+ID4gPiArfQ0KPiA+ID4gPiArDQo+ID4gPiA+ICtzdGF0aWMgdTMyIF9fbWJtX2ZpZm9f
c3VtX2xhc3RuX291dChpbnQgcm1pZCwgYm9vbCBpc19sb2NhbGJ3KSB7DQo+ID4gPiA+ICsgICBp
ZiAoaXNfbG9jYWxidykNCj4gPiA+ID4gKyAgICAgICAgICAgcmV0dXJuIGJ3X3N1bV9jYWxjKCZt
Ym1fbG9jYWxbcm1pZF0sIHJtaWQpOw0KPiA+ID4gPiArICAgZWxzZQ0KPiA+ID4gPiArICAgICAg
ICAgICByZXR1cm4gYndfc3VtX2NhbGMoJm1ibV90b3RhbFtybWlkXSwgcm1pZCk7IH0NCj4gPiA+
ID4gKw0KPiA+ID4gPiArc3RhdGljIHZvaWQgX19tYm1fZmlmb19pbihzdHJ1Y3Qgc2FtcGxlICpi
d19zdGF0LCB1MzIgdmFsKSB7DQo+ID4gPiA+ICsgICBid19zdGF0LT5tYm1maWZvW2J3X3N0YXQt
PmZpZm9pbl0gPSB2YWw7DQo+ID4gPiA+ICsgICBpZiAoKytid19zdGF0LT5maWZvaW4gPj0gbWJt
X3dpbmRvd19zaXplKQ0KPiA+ID4NCj4gPiA+IEhvdyBkb2VzIHRoYXQgYmVjb21lIGdyZWF0ZXIg
dGhhbiBtYm1fd2luZG93c2l6ZT8NCj4gPiA+DQo+ID4NCj4gPiBUaGlzIGlzIGZpeGVkIGJ5IGNo
YW5naW5nID49IHRvID09DQo+ID4gQWRkZWQgYSBjb21tZW50Og0KPiA+DQo+ID4gLyoNCj4gPiAq
IHN0b3JlIGN1cnJlbnQgc2FtcGxlJ3MgYncgdmFsdWUgaW4gc2xpZGluZyB3aW5kb3cgYXQgdGhl
DQo+ID4gKiBpbmRleCBmaWZvaW4uIEluY3JlbWVudCBmaWZvaW4uIENoZWNrIGlmIGZpZm9pbiBo
YXMgcmVhY2hlZA0KPiA+ICogbWF4X3dpbmRvd19zaXplLiBJZiB5ZXMgcmVzZXQgaXQgdG8gYmVn
aW5pbmcgaS5lLiB6ZXJvDQo+ID4gKiBlLmcuDQo+ID4gKiBtYm1fd2luZG93X3NpemUgPSAxMA0K
PiA+ICogbWJtZmlmbyBpcyBhIGNpcmN1bGFyIGZpZm8gICAwIDEgMiAzIDQgNSA2IDcgOCA5IDEw
DQo+ID4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF4gICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgfA0KPiA+ICogICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0K
PiA+ICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IF8g
XyBfIF8gXyBfIF8gXyBfIF98DQo+ID4gKg0KPiA+ICogU28gd2hlbiBmaWZvaW4gYmVjb21lcyAx
MCwgdGhlbiBpdCBpcyByZXNldCB0byB6ZXJvDQo+ID4gKg0KPiA+ICovDQo+IA0KPiBJJ20gbm90
IHN1cmUgdGhhdCB0aGlzIGNvbW1lbnQgYWRkcyBhbnl0aGluZyBvZiB2YWx1ZSB0aGF0IGlzbid0
IGFscmVhZHkNCj4gdW5kZXJzdG9vZCBieSByZWFkaW5nIHRoZSBjb2RlLiBJIGRvbid0IHRoaW5r
IHlvdSBuZWVkIGEgY29tbWVudCBmb3IgdGhpcw0KPiBmdW5jdGlvbiwgaXQgc2VlbXMgcHJldHR5
IHN0cmFpZ2h0IGZvcndhcmQgYW5kIFRob21hcycgcXVlc3Rpb24gd2FzIGFib3V0IHRoZQ0KPiBi
b3VuZGFyeSBsaW1pdHMgb2YgLT5maWZvaW4uDQo+IA0KPiA+ID4gPiArICAgICAgICAgICBid19z
dGF0LT5maWZvaW4gPSAwOw0KPiA+ID4gPiArfQ0KPiA+ID4NCj4gPiA+ID4gKy8qDQo+ID4gPiA+
ICsgKiBfX3JtaWRfcmVhZF9tYm0gY2hlY2tzIHdoZXRoZXIgaXQgaXMgTE9DQUwgb3IgR0xPQkFM
IE1CTSBldmVudA0KPiA+ID4gPiArYW5kIHJlYWRzDQo+ID4gPiA+ICsgKiBpdHMgTVNSIGNvdW50
ZXIuIENoZWNrIHdoZXRoZXIgb3ZlcmZsb3cgb2NjdXJyZWQgYW5kIGhhbmRsZXMgaXQuDQo+ID4g
PiA+ICtDYWxjdWxhdGVzDQo+ID4gPiA+ICsgKiBjdXJyZW5ldCAgQlcgYW5kIHVwZGF0ZXMgIHJ1
bm5pbmcgYXZlcmFnZS4NCj4gPiA+DQo+ID4gPiBjdXJyZW5ldD8gQW5kIHBsZWFzZSBnZXQgcmlk
IG9mIHRoZSBkb3VibGUgc3BhY2VzDQo+ID4gPg0KPiA+IFRoaXMgaXMgZml4ZWQgbm93LiAgSGVy
ZSBpcyB0aGUgdXBkYXRlZCBjb21tZW50Og0KPiA+DQo+ID4gLyoNCj4gPiAqIHJtaWRfcmVhZF9t
Ym0gY2hlY2tzIHdoZXRoZXIgaXQgaXMgTE9DQUwgb3IgVG90YWwgTUJNIGV2ZW50IGFuZCByZWFk
cw0KPiA+ICogaXRzIE1TUiBjb3VudGVyLiBDaGVjayB3aGV0aGVyIG92ZXJmbG93IG9jY3VyZWQg
YW5kIGhhbmRsZXMgaXQuIENhbGN1bGF0ZXMNCj4gPiAqIGN1cnJlbmV0ICBCVyBhbmQgdXBkYXRl
cyAgcnVubmluZyBhdmVyYWdlLg0KPiA+ICoNCj4gDQo+IF5eXiBZb3UndmUgc3RpbGwgbWlzc3Bl
bGxlZCBjdXJyZW50Lg0KPiA+DQo+ID4gKiBPdmVyZmxvdyBIYW5kbGluZzoNCj4gPiAqIGlmIChN
U1IgY3VycmVudCB2YWx1ZSA8IE1TUiBwcmV2aW91cyB2YWx1ZSkgaXQgaXMgYW4NCj4gPiAqIG92
ZXJmbG93LiBNU1IgdmFsdWVzIGFyZSBpbmNyZWFzaW5nIHdoZW4gYmFuZHdpZHRoIGNvbnN1bXB0
aW9uIGZvciB0aGUNCj4gdGhyZWFkDQo+ID4gKiBpcyBub24temVybzsgV2hlbiBNU1IgdmFsdWVz
IHJlYWNoZXMgTUFYX0NPVU5URVJfVkFMVUUgaXQgb3ZlcmZsb3dzLg0KPiBBZnRlciBvdmVyZmxv
dywNCj4gPiAqIE1TUiBjdXJyZW50IHZhbHVlIGdvZXMgYmFjayB0byB6ZXJvIGFuZCBzdGFydHMg
aW5jcmVhc2luZyBhZ2FpbiBhdCB0aGUgcmF0ZQ0KPiBvZg0KPiA+ICogYmFuZHdpZHRoLg0KPiA+
ICoNCj4gDQo+IFlvdSBkb24ndCBuZWVkIHRvIHByb3ZpZGUgYSBkZWZpbml0aW9uIG9mICJvdmVy
ZmxvdyIsIG1vc3QgcGVvcGxlIHdpbGwgYmUNCj4gZmFtaWxpYXIgd2l0aCBpdC4gV2hhdCBpcyBt
b3JlIGltcG9ydGFudCB0byBkb2N1bWVudCBpcyBob3cgdGhlIG92ZXJmbG93IGlzDQo+IGhhbmRs
ZWQuLi4NCj4gPg0KPiA+ICogT3ZlcmZsb3cgaGFuZGxpbmc6DQo+ID4gKiBEZXRlY3QgYW4gb3Zl
cmZsb3cgOiAgY3VycmVudCByZWFkIHZhbHVlID4gbGFzdCByZWFkIHZhbHVlDQo+IA0KPiBJc24n
dCB0aGlzIGludmVydGVkPyBPdmVyZmxvdyBvY2N1cnJlZCBpZiBjdXJyZW50IDwgcHJldmlvdXMu
DQo+IA0KPiA+DQo+ID4gKiBPdmVyZmxvdyBjb3JyZWN0aW9uOiAgaWYgKG92ZXJmbG93KQ0KPiA+
ICogICAgICAgICAgICAgICAgICAgICAgICAgIEN1cnJlbnQgdmFsdWUgPSAoTUFYX0NPVU5URVJf
VkFMVUUgLSBwcmV2IHJlYWQgdmFsdWUpICsNCj4gY3VycmVudCByZWFkIHZhbHVlDQo+ID4gKiAg
ICAgICAgICAgICAgICAgICAgICAgZWxzZQ0KPiA+ICogICAgICAgICAgICAgICAgICAgICAgICAg
IEN1cnJlbnQgdmFsdWUgPSBjdXJyZW50IHJlYWQgdmFsdWUNCj4gPiAqDQo+IA0KPiBQbGVhc2Ug
ZG9uJ3Qgd3JpdGUgcHNldWRvY29kZSBpbiB0aGUgY29tbWVudHMuIFVzZSBFbmdsaXNoIHByb3Nl
IHRvIGRlc2NyaWJlDQo+IHRoZSBpbXBvcnRhbnQgcGFydHMgb2YgdGhlIGNvZGUuDQo+IA0KPiA+
DQo+ID4gKiBDYWxjdWxhdGlvbiBvZiBDdXJyZW50IEJhbmR3aWR0aCB2YWx1ZToNCj4gPiAqIElm
IE1TUiBpcyByZWFkIHdpdGhpbiBsYXN0IDEwMG1zLCB0aGVuIHRoZW4gdGhlIHNtYXBsZSBpcyBp
Z25vcmVkOw0KPiA+ICogSWYgdGhlIE1TUiB3YXMgUmVhZCB3aXRoIGluIGxhc3QgMTAwbXMsIHdo
eSAgaW5jdXIgYW4gZXh0cmEgb3ZlcmhlYWQNCj4gPiAqIG9mIGRvaW5nIHRoZSBNU1IgcmVhZHMg
YWdhaW4uIEFueXdheSB0aGVyZSdsbCBiZSBhIG5lZ2xpZ2libGUgY2hhbmdlIG9yIHplcm8NCj4g
PiAqIGNoYW5nZSBpbiBNU1IgcmVhZGluZ3MgaW4gMTAwbXMuDQo+ID4gKg0KPiA+ICogQmFuZHdp
ZHRoIGlzIGNhbGN1bGF0ZWQgYXM6DQo+ID4gKiBtZW1vcnkgYmFuZHdpZHRoID0gZGlmZmVyZW5j
ZSBvZiBsYXN0IHR3byBtc3IgY291bnRlciB2YWx1ZXMvdGltZQ0KPiBkaWZmZXJlbmNlLg0KPiA+
ICoNCj4gPiAqIGN1bV9hdmcgPSBSdW5uaW5nIEF2ZXJhZ2UgYmFuZHdpZHRoIG9mIGxhc3QgJ24n
IGJhbmR3aWR0aCB2YWx1ZXMgZm9yDQo+ID4gKiB0aGUgc2FtcGxlcyB0aGF0IGFyZSBwcm9jZXNz
ZWQNCj4gPiAqDQo+IA0KPiBXaGVyZSAnbicgaXMgJ21ibV93aW5kb3dfc2l6ZScgPyBJZiBzbywg
cGxlYXNlIHVzZSAnbWJtX3dpbmRvd19zaXplJywgbm90ICduJy4NCj4gPg0KPiA+ICogU2xpZGlu
ZyB3aW5kb3cgaXMgdXNlZCB0byBzYXZlIHRoZSBsYXN0ICduJyBzYW1wbGVzLiBXaGVyZSwNCj4g
PiAqIG4gPSBzbGlkaW5nX3dpbmRvd19zaXplIGFuZCByZXN1bHRzIGluIHNsaWRpbmcgd2luZG93
IGR1cmF0aW9uIG9mICduJyBzZWNzLg0KPiANCj4gSG1tLi4uIHRoaXMgY29uZnVzZXMgbWUgYSBs
b3QuIElzICduJyBhIHNpemUgb3IgYSBkdXJhdGlvbj8gVGhlIHR3byBhcmUgbm90IHRoZQ0KPiBz
YW1lIHRoaW5nLg0KPiANCj4gPg0KPiA+ICogVGhlIHNsaWRpbmcgd2luZG93IHNpemUgYnkgZGVm
YXVsdCBzZXQgdG8NCj4gPiAqIE1CTV9GSUZPX1NJWkVfTUlOLiBVc2VyIGNhbiBjb25maWd1cmUg
aXQgdG8gdGhlIHZhbHVlcyBpbiB0aGUgcmFuZ2UNCj4gPiAqIChNQk1fRklGT19TSVpFX01JTixN
Qk1fRklGT19TSVpFX01BWCkuIFRoZSByYW5nZSBmb3Igc2xpZGluZyB3aW5kb3cNCj4gPiAqIGlz
IGNob3NlbiBiYXNlZCBvbiBhIGdlbmVyYWwgY3JpdGVyaWEgZm9yIG1vbml0b3JpbmcgZHVyYXRp
b24uIEV4YW1wbGUNCj4gPiAqIGZvciBhIHNob3J0IGxpdmVkIGFwcGxpY2F0aW9uLCAxMHNlYyBt
b25pdG9yaW5nIHBlcmlvZCBnaXZlcw0KPiA+ICogZ29vZCBjaGFyYWN0ZXJpemF0aW9uIG9mIGl0
cyBiYW5kd2lkdGggY29uc3VtcHRpb24uIEZvciBhbiBhcHBsaWNhdGlvbg0KPiA+ICogdGhhdCBy
dW5zIGZvciBsb25nZXIgZHVyYXRpb24sIDMwMHNlYyBtb25pdG9yaW5nIHBlcmlvZCBnaXZlcyBi
ZXR0ZXINCj4gPiAqIGNoYXJhY3Rlcml6YXRpb24gb2YgaXRzIGJhbmR3aWR0aCBjb25zdW1wdGlv
bi4gU2luY2UgdGhlIHJ1bm5pbmcgYXZlcmFnZQ0KPiA+ICogY2FsY3VsYXRlZCBmb3IgdG90YWwg
bW9uaXRvcmluZyBwZXJpb2QsIHVzZXIgZ2V0cyB0aGUgbW9zdCBhY2N1cmFjYXRlDQo+ID4gKiBh
dmVyYWdlIGJhbmR3aWR0aCBmb3IgdGhlIGVhY2ggbW9uaXRvcmluZyBwZXJpb2QuDQo+ID4gKg0K
PiA+ICogU2NhbGluZzoNCj4gPiAqIGN1bV9hdmcgaXMgdGhlIHJhdyBiYW5kd2lkdGggaXMgQnl0
ZXMvc2VjLg0KPiA+ICogY3VtX2F2ZyBpcyBjb252ZXJ0ZWQgdG8gTUIvc2VjIGJ5IGFwcGx5aW5n
ICBNQk1fQ09OVkVSU0lPTl9GQUNUT1INCj4gYW5kDQo+ID4gKiByb3VuZGVkIHRvIG5lYXJlc3Qg
aW50ZWdlci4gVXNlciBpbnRlcmZhY2UgZ2V0cyB0aGUgQmFuZHdpZHRoIHZhbHVlcyBpbg0KPiBN
Qi9zZWMuDQo+ID4gKg0KPiA+ICovDQo+ID4gPiA+ICsgKg0KPiA+ID4gPiArICogT3ZlcmZsb3cg
SGFuZGxpbmc6DQo+ID4gPiA+ICsgKiBpZiAoTVNSIGN1cnJlbnQgdmFsdWUgPCBNU1IgcHJldmlv
dXMgdmFsdWUpIGl0IGlzIGFuDQo+ID4gPiA+ICsgKiBvdmVyZmxvdy4gYW5kIG92ZXJmbG93IGlz
IGhhbmRsZWQuDQo+ID4gPg0KPiA+ID4gV293LiBUaGF0J3MgaW5mb3JtYXRpdmUgYXMgaGVsbCEN
Cj4gPiA+DQo+ID4gUGxlYXNlIGxvb2sgYXQgdGhlIG1vZGlmaWVkIGNvbW1lbnQgYWJvdmUNCj4g
PiA+ID4gKyAqDQo+ID4gPiA+ICsgKiBDYWxjdWxhdGlvbiBvZiBDdXJyZW50IEJXIHZhbHVlOg0K
PiA+ID4NCj4gPiA+IEJXID09IEJvZHkgV2VpZ2h0Pw0KPiA+ID4NCj4gPg0KPiA+IEl0IGlzIGZp
eGVkIG5vdw0KPiA+DQo+ID4gPiA+ICsgKiBJZiBNU1IgaXMgcmVhZCB3aXRoaW4gbGFzdCAxMDBt
cywgdGhlbiB0aGUgdmFsdWUgaXMgaWdub3JlZDsNCj4gPiA+ID4gKyAqIHRoaXMgd2lsbCBzdXBw
cmVzcyBzbWFsbCBkZWx0YXMuIFdlIGRvbid0IHByb2Nlc3MgTUJNIHNhbXBsZXMNCj4gPiA+ID4g
KyB0aGF0IGFyZQ0KPiA+ID4gPiArICogd2l0aGluIDEwMG1zLg0KPiA+ID4NCj4gPiA+IFdIWT8N
Cj4gPiA+DQo+ID4gRXhwbGFpbmVkIGluIHRoZSBjb21tZW50LiBJZiBtYm1fcmVhZCBpcyBjYWxs
ZWQgd2l0aGluIGluIDEwMG1zIGZvcg0KPiA+IHRoZSBzYW1lIHJtaWQsIHdlIGRvbuKAmXQgaGF2
ZSB0byBwcm9jZXNzIHRoZSBzYW1wbGUuDQo+IA0KPiBUaGUga2V5IHBpZWNlIG9mIGluZm9ybWF0
aW9uIHlvdSdyZSBtaXNzaW5nIGhlcmUgaXMgdGhhdCBza2lwcGluZyB0aGVzZSBzbWFsbA0KPiBk
ZWx0YXMgaXMgYW4gb3B0aW1pemF0aW9uLCBiZWNhdXNlIHdlIGF2b2lkIHBlcmZvcm1pbmcgY29z
dGx5IG9wZXJhdGlvbnMgZm9yDQo+IHdoYXQgd291bGQgbGlrZWx5IGJlIGEgdmVyeSBtaW5vciBj
aGFuZ2UgaW4gdGhlIE1CTSBkYXRhLCByaWdodD8NCj4gDQo+IA0KPiA+ID4gPiArew0KPiA+ID4g
PiArICAgdTY0IHZhbCwgdG1wLCBkaWZmX3RpbWUsIGNtYSwgYnl0ZXMsIGluZGV4Ow0KPiA+ID4g
PiArICAgYm9vbCBvdmVyZmxvdyA9IGZhbHNlLCBmaXJzdCA9IGZhbHNlOw0KPiA+ID4gPiArICAg
a3RpbWVfdCBjdXJfdGltZTsNCj4gPiA+ID4gKyAgIHUzMiB0bXAzMiA9IHJtaWQ7DQo+ID4gPiA+
ICsgICBzdHJ1Y3Qgc2FtcGxlICptYm1fY3VycmVudDsNCj4gPiA+ID4gKyAgIHUzMiB2cm1pZCA9
IHRvcG9sb2d5X3BoeXNpY2FsX3BhY2thZ2VfaWQoc21wX3Byb2Nlc3Nvcl9pZCgpKSAqDQo+ID4g
PiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNxbV9tYXhf
cm1pZCArIHJtaWQ7DQo+ID4gPiA+ICsNCj4gPiA+ID4gKyAgIHJtaWQgPSB2cm1pZDsNCj4gPiA+
DQo+ID4gPiBGcm9tIG15IHByZXZpb3VzIHJldmlldzoNCj4gPiA+DQo+ID4gPiAgICJUaGlzIGlz
IGNvbXBsZXRlbHkgYmFja3dhcmRzLg0KPiA+ID4NCj4gPiA+ICAgICAgICB0bXAzMiA9IHJtaWQ7
DQo+ID4gPiAgICAgICAgcm1pZCA9IHZybWlkOw0KPiA+ID4gICAgICAgIGRvX3N0dWZmKHJtaWQp
Ow0KPiA+ID4gICAgICAgIHJtaWQgPSB0bXAzMjsNCj4gPiA+ICAgICAgICBkb19vdGhlcl9zdHVm
ZihybWlkKTsNCj4gPiA+DQo+ID4gPiAgICBXaHkgY2FuJ3QgeW91IHVzZSB2cm1pZCBmb3IgZG9f
c3R1ZmYoKSBhbmQgbGVhdmUgcm1pZCBhbG9uZT8gSnVzdA0KPiA+ID4gICAgYmVjYXVzZSBpdCB3
b3VsZCBtYWtlIHRoZSBjb2RlIHNpbXBsZXIgdG8gcmVhZD8iDQo+ID4gPg0KPiA+ID4gU3RpbGwg
YXBwbGllcy4NCj4gPiA+DQo+ID4NCj4gPiBUaGlzIGlzIG5vdyBjaGFuZ2VkIHRvDQo+ID4gdTY0
IHZhbCwgY3VycmVudG1zciwgY3VycmVudGJ3LCBkaWZmX3RpbWUsIGNtYSwgYnl0ZXMsIGluZGV4
Ow0KPiA+ICAgICAgICAgYm9vbCBvdmVyZmxvdyA9IGZhbHNlLCBmaXJzdCA9IGZhbHNlOw0KPiA+
ICAgICAgICAga3RpbWVfdCBjdXJfdGltZTsNCj4gPiAgICAgICAgIHUzMiB0bXAzMiA9IHJtaWQs
IGV2ZW50aWQ7DQo+ID4gICAgICAgICBzdHJ1Y3Qgc2FtcGxlICptYm1fY3VycmVudDsNCj4gPiAg
ICAgICAgIHUzMiB2cm1pZCA9IHJtaWRfMl9pbmRleChybWlkKTsNCj4gPg0KPiA+ICAgICAgICAg
cm1pZCA9IHZybWlkOw0KPiA+ICAgICAgICAgY3VyX3RpbWUgPSBrdGltZV9nZXQoKTsNCj4gPiAg
ICAgICAgIGlmIChyZWFkX21ibV9sb2NhbCkgew0KPiA+ICAgICAgICAgICAgICAgICBtYm1fY3Vy
cmVudCA9ICZtYm1fbG9jYWxbdnJtaWRdOw0KPiA+ICAgICAgICAgICAgICAgICBldmVudGlkICAg
ICA9ICBRT1NfTUJNX0xPQ0FMX0VWRU5UX0lEX0hXOw0KPiA+ICAgICAgICAgICAgICAgICB3cm1z
cihNU1JfSUEzMl9RTV9FVlRTRUwsIFFPU19NQk1fTE9DQUxfRVZFTlRfSURfSFcsDQo+ID4gcm1p
ZCk7DQo+IA0KPiBZb3UgZG9uJ3QgbmVlZCB0byBwZXJmb3JtIHRoaXMgd3Jtc3IoKSBoZXJlIGJl
Y2F1c2UgaXQncyB0YWtlbiBjYXJlIG9mIGluIHRoZQ0KPiBjb21tb24gY29kZSBiZWxvdy4NCj4g
DQo+ID4gICAgICAgICB9IGVsc2Ugew0KPiA+ICAgICAgICAgICAgICAgICBtYm1fY3VycmVudCA9
ICZtYm1fdG90YWxbdnJtaWRdOw0KPiA+ICAgICAgICAgICAgICAgICBldmVudGlkICAgICA9IFFP
U19NQk1fVE9UQUxfRVZFTlRfSUQ7DQo+ID4gICAgICAgICB9DQo+ID4gICAgICAgICBybWlkID0g
dG1wMzI7DQo+IA0KPiBXaHkgZGlkIHlvdSBhc3NpZ24gcm1pZCB0byB2cm1pZCBpZiB5b3UgcmVh
c3NpZ24gaXQgYmVmb3JlIGl0IHdhcyB1c2VkPw0KPiANCj4gDQo+ID4gPiA+ICsgICAvKiBpZiBj
dXJyZW50IG1zciB2YWx1ZSA8ICBwcmV2aW91cyBtc3IgdmFsdWUgLCAgaXQgbWVhbnMgb3ZlcmZs
b3cgKi8NCj4gPiA+ID4gKyAgIGlmICh2YWwgPCBieXRlcykgew0KPiA+ID4gPiArICAgICAgICAg
ICB2YWwgPSBNQk1fQ05UUl9NQVggLSBieXRlcyArIHZhbDsNCj4gPiA+ID4gKyAgICAgICAgICAg
b3ZlcmZsb3cgPSB0cnVlOw0KPiA+ID4gPiArICAgfSBlbHNlDQo+ID4gPiA+ICsgICAgICAgICAg
IHZhbCA9IHZhbCAtIGJ5dGVzOw0KPiA+ID4gPiArDQo+ID4gPiA+ICsgICB2YWwgPSAgKHZhbCAq
IE1CTV9USU1FX0RFTFRBX01BWCkgLyBkaWZmX3RpbWU7DQo+ID4gPiA+ICsNCj4gPiA+ID4gKyAg
IGlmICgoZGlmZl90aW1lID4gTUJNX1RJTUVfREVMVEFfTUFYKSAmJiAoIWNtYSkpDQo+ID4gPiA+
ICsgICAgICAgICAgIC8qIEZpcnN0IHNhbXBsZSAqLw0KPiA+ID4gPiArICAgICAgICAgICBmaXJz
dCA9IHRydWU7DQo+ID4gPiA+ICsNCj4gPiA+ID4gKyAgIHJtaWQgPSB2cm1pZDsNCj4gPiA+DQo+
ID4gPiBBbmQgYW5vdGhlciB0aW1lOg0KPiA+ID4NCj4gPiA+ICAgIk1vcmUgb2JmdXNjYXRpb24i
DQo+ID4gPg0KPiA+DQo+ID4gICAgICAgIC8qDQo+ID4gICAgICAgICAgKiBNQk1fVElNRV9ERUxU
QV9NQVggaXMgcGlja2VkIGFzIHBlciBNQk0gc3BlY3MuIEFzIHNwZWNpZmllZCBpbg0KPiBJbnRl
bCBQbGF0Zm9ybQ0KPiA+ICAgICAgICAgICogUXVhbGl0eSBvZiBTZXJ2aWNlIE1vbml0b3Jpbmcg
SW1wbGVtZW50ZXIncyBHdWlkZSBWMSwgU2VjdGlvbiAyLjcuMi4NCj4gcGFnZSAyMSwNCj4gPiAg
ICAgICAgICAqIG92ZXJmbG93IGNhbiBvY2N1ciBtYXhpbXVtIG9uY2UgaW4gYSBzZWNvbmQuIFNv
IGxhdGVzdCB3ZSB3YW50IHRvDQo+IHJlYWQgdGhlIE1TUg0KPiA+ICAgICAgICAgICogY291bnRl
cnMgaXMgMTAwMG1zLiBJZiBpdCBpcyBsZXNzIHRoYW4gMTAwMG1zIHdlIGNhbiAgaWdub3JlIHRo
ZSBzYW1wbGUuDQo+IFRoZW4gd2UNCj4gPiAgICAgICAgICAqIGRlY2lkZSBzaW5jZSB3aGVuIHdl
IHNob3VsZCBpZ25vcmUuIElmIHRoZSBNU1Igd2FzIFJlYWQgd2l0aCBpbiBsYXN0DQo+IDEwMG1z
LCB3aHkNCj4gPiAgICAgICAgICAqIHByb2Nlc3MgdGhlIE1TUiByZWFkcyBhZ2Fpbi4gQW55d2F5
IHRoZXJlJ2xsIGJlIHNtYWxsIGNoYW5nZSBvciB6ZXJvDQo+IGNoYW5nZS4NCj4gPiAgICAgICAg
ICAqIFNvIGlnbm9yaW5nIE1TUiBSZWFkcyB3aXRoaW4gMTAwbXMgb3IgbGVzcyBpcyBlZmZpY2ll
bnQuDQo+IE1CTV9USU1FX0RFTFRBX01JTg0KPiA+ICAgICAgICAgICogaXMgc3BlY2lmaWVkIGFz
IDEwMG1zIGFzIHBlciB0aGlzIGd1aWRlbGluZS4NCj4gPiAgICAgICAgICAqDQo+ID4gICAgICAg
ICAgKi8NCj4gDQo+IEkgc3VzcGVjdCB0aGUgZG9jdW1lbnQgeW91J3JlIHJlZmVycmluZyB0byBh
Ym92ZSBpcyBvbmx5IGF2YWlsYWJsZSB1bmRlciBOREEsDQo+IHdoaWNoIG1ha2VzIGl0IHVuc3Vp
dGFibGUgZm9yIG1lbnRpb24gaW4gdGhlIGtlcm5lbCBzb3VyY2Ugc2luY2UgYSBsYXJnZSBudW1i
ZXINCj4gb2YgcGVvcGxlIHdvbid0IGhhdmUgYWNjZXNzIHRvIGl0Lg0KPiANCj4gSnVzdCBleHBs
YWluIHRoYXQgdGhlIHdheSB0aGUgaGFyZHdhcmUgaXMgZGVzaWduZWQgcHV0cyBhbiB1cHBlciBs
aW1pdCBvbiBob3cNCj4gcXVpY2tseSB0aGUgY291bnRlciBjYW4gb3ZlcmZsb3csIHdoaWNoIGlz
IG9uY2UgcGVyIHNlY29uZC4NCj4gDQo+IA0KPiA+ID4gPiArc3RhdGljIHZvaWQgX19pbnRlbF9j
cW1fZXZlbnRfdG90YWxfYndfY291bnQodm9pZCAqaW5mbykgew0KPiA+ID4gPiArICAgc3RydWN0
IHJtaWRfcmVhZCAqcnIgPSBpbmZvOw0KPiA+ID4gPiArICAgdTY0IHZhbDsNCj4gPiA+ID4gKw0K
PiA+ID4gPiArICAgdmFsID0gX19ybWlkX3JlYWRfbWJtKHJyLT5ybWlkLCBmYWxzZSk7DQo+ID4g
PiA+ICsgICBpZiAodmFsICYgKFJNSURfVkFMX0VSUk9SIHwgUk1JRF9WQUxfVU5BVkFJTCkpDQo+
ID4gPiA+ICsgICAgICAgICAgIHJldHVybjsNCj4gPiA+ID4gKyAgIGF0b21pYzY0X2FkZCh2YWws
ICZyci0+dmFsdWUpOyB9DQo+ID4gPiA+ICsNCj4gPiA+ID4gK3N0YXRpYyB2b2lkIF9faW50ZWxf
Y3FtX2V2ZW50X2xvY2FsX2J3X2NvdW50KHZvaWQgKmluZm8pIHsNCj4gPiA+ID4gKyAgIHN0cnVj
dCBybWlkX3JlYWQgKnJyID0gaW5mbzsNCj4gPiA+ID4gKyAgIHU2NCB2YWw7DQo+ID4gPiA+ICsN
Cj4gPiA+ID4gKyAgIHZhbCA9IF9fcm1pZF9yZWFkX21ibShyci0+cm1pZCwgdHJ1ZSk7DQo+ID4g
PiA+ICsgICBpZiAodmFsICYgKFJNSURfVkFMX0VSUk9SIHwgUk1JRF9WQUxfVU5BVkFJTCkpDQo+
ID4gPiA+ICsgICAgICAgICAgIHJldHVybjsNCj4gPiA+ID4gKyAgIGF0b21pYzY0X2FkZCh2YWws
ICZyci0+dmFsdWUpOyB9DQo+ID4gPg0KPiA+ID4gQW5kIG9uY2UgbW9yZToNCj4gPiA+DQo+ID4g
PiAgICJZb3UncmUgcmVhbGx5IGEgZmFuIG9mIGNvcHkgYW5kIHBhc3RlLiINCj4gPiA+DQo+ID4N
Cj4gPiBUaGVzZSBmdW5jdGlvbnMgYXJlIGludm9rZWQgaW5kaXJlY3RseS4gVGhleSB3ZXJlIHdy
aXR0ZW4ga2VlcGluZw0KPiBpbnRlbF9jcW1fZXZlbnRfY291bnQgaW4gIG1pbmQuDQo+ID4gSeKA
mWxsIGNoYW5nZSB0aGUgYXJnIHRvIHN0cnVjdCAgIG1ibV9yZWFkew0KPiA+ICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RydWN0IHJtaWRfcmVh
ZCAqcnI7DQo+ID4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICB1MzIgZXZlbnRpZDsNCj4gPiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICB9Ow0KPiA+IEludGVsX2NxbV9ldmVudF8qX2J3X2NvdW50KOKA
pi4pIG5lZWRzIGV2ZW50aWQgdG8gY2FsbCBmb3IgZGVjb2RpbmcNCj4gDQo+IE5vLCBwbGVhc2Ug
ZG8gbm90IGR1cGxpY2F0ZSB0aGUgcm1pZF9yZWFkIHN0cnVjdHVyZSwgdGhhdCBpcyBub3QgYW4N
Cj4gaW1wcm92ZW1lbnQsIHdlIGRvbid0IG5lZWQgdHdvIGRpZmZlcmVudCBzdHJ1Y3RzIGZvciBy
ZWFkaW5nIHRoZSByZWFkIGRhdGEuDQo+IA0KPiBQbGVhc2UgYWRkIHRoZSBldmVudCBmaWVsZCB0
byB0aGUgZXhpc3Rpbmcgc3RydWN0IHJtaWRfcmVhZC4NCj4gDQo+IA0KPiA+ID4gPiBAQCAtMTAy
Myw2ICsxNDM3LDE3IEBAIHN0YXRpYyB2b2lkIGludGVsX2NxbV9ldmVudF9zdG9wKHN0cnVjdA0K
PiA+ID4gcGVyZl9ldmVudCAqZXZlbnQsIGludCBtb2RlKQ0KPiA+ID4gPiAgICAgIH0gZWxzZSB7
DQo+ID4gPiA+ICAgICAgICAgICAgICBXQVJOX09OX09OQ0UoIXN0YXRlLT5ybWlkKTsNCj4gPiA+
ID4gICAgICB9DQo+ID4gPiA+ICsNCj4gPiA+ID4gKyAgIGlmIChwbXUpIHsNCj4gPiA+ID4gKyAg
ICAgICAgICAgaWYgKHBtdS0+bl9hY3RpdmUgPiAgMCkgew0KPiA+ID4NCj4gPiA+IFdoYXQncyB0
aGUgcHVycG9zZSBvZiB0aGlzIGNoZWNrPyBJbiB0aGUgcHJldmlvdXMgdmVyc2lvbiB0aGVyZSB3
YXMNCj4gPiA+IGEgV0FSTl9PTigpLCB3aGljaCBtYWRlIHNlbnNlLiBEaWQgaXQgdHJpZ2dlciBh
bmQgeW91IGRlY2lkZWQgdG8gIndvcmsiDQo+ID4gPiBhcm91bmQgaXQ/DQo+ID4gPg0KPiA+DQo+
ID4gV2UgYWN0dWFsbHkgbWVhbnQgdG8gY2hlY2sgaWYgdGhlcmUgYXJlIGFjdGl2ZSBldmVudHMN
Cj4gDQo+IEkgZG9uJ3QgZm9sbG93IHRoaXMgYW5zd2VyLiBBcmUgeW91IHNheWluZyB0aGF0IHRo
ZSBXQVJOX09OKCkgZG9lc24ndCBtYWtlDQo+IHNlbnNlIGhlcmU/DQo+IA0KPiANCj4gDQo+ID4N
Cj4gPiA+ID4gK0VWRU5UX0FUVFJfU1RSKGxsY190b3RhbF9idy51bml0LCBpbnRlbF9jcW1fbGxj
X3RvdGFsX2J3X3VuaXQsDQo+ID4gPiA+ICsiS0Ivc2VjIik7IEVWRU5UX0FUVFJfU1RSKGxsY19s
b2NhbF9idy51bml0LA0KPiA+ID4gPiAraW50ZWxfY3FtX2xsY19sb2NhbF9id191bml0LCAiS0Iv
c2VjIik7ICNlbmRpZg0KPiA+ID4NCj4gPiA+ID4gK3N0YXRpYyBzc2l6ZV90DQo+ID4gPiA+ICtz
bGlkaW5nX3dpbmRvd19zaXplX3N0b3JlKHN0cnVjdCBkZXZpY2UgKmRldiwNCj4gPiA+ID4gKyAg
ICAgICAgICAgICAgICAgICAgIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICphdHRyLA0KPiA+ID4g
PiArICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2hhciAqYnVmLCBzaXplX3QgY291bnQpIHsN
Cj4gPiA+ID4gKyAgIHVuc2lnbmVkIGludCBieXRlczsNCj4gPiA+ID4gKyAgIGludCByZXQ7DQo+
ID4gPiA+ICsNCj4gPiA+ID4gKyAgIHJldCA9IGtzdHJ0b3VpbnQoYnVmLCAwLCAmYnl0ZXMpOw0K
PiA+ID4gPiArICAgaWYgKHJldCkNCj4gPiA+ID4gKyAgICAgICAgICAgcmV0dXJuIHJldDsNCj4g
PiA+ID4gKw0KPiA+ID4gPiArICAgbXV0ZXhfbG9jaygmY2FjaGVfbXV0ZXgpOw0KPiA+ID4gPiAr
ICAgaWYgKGJ5dGVzID4gMCAmJiBieXRlcyA8PSBNQk1fRklGT19TSVpFX01BWCkNCj4gPiA+ID4g
KyAgICAgICAgICAgbWJtX3dpbmRvd19zaXplID0gYnl0ZXM7DQo+ID4gPg0KPiA+ID4gU28sIGl0
J3MgdmFsaWQgdG8gc2V0IHRoZSB3aW5kb3cgdG8gWCB3aGVyZSAwIDwgWCA8IE1CTV9GSUZPX1NJ
WkVfTUlOLg0KPiA+ID4gV2hhdCdzIHRoZSBhY3R1YWwgcHVycG9zZSBvZiBNQk1fRklGT19TSVpF
X01JTj8NCj4gPiA+DQo+ID4gVGhpcyBpcyBjaGFuZ2VkIHRvDQo+ID4gaWYgKGJ5dGVzID49IE1C
TV9GSUZPX1NJWkVfTUlOICYmIGJ5dGVzIDw9IE1CTV9GSUZPX1NJWkVfTUFYKQ0KPiA+ICAgICAg
ICAgICAgICAgICBtYm1fd2luZG93X3NpemUgPSBieXRlczsNCj4gDQo+IE5vdGUgdGhhdCBpZiB0
aGUgdXNlciBwYXNzZXMgYSB2YWx1ZSBvdXRzaWRlIG9mIHRoaXMgcmFuZ2UgeW91IHNob3VsZCBi
ZSByZXR1cm5pbmcNCj4gLUVJTlZBTCB0byBpbmRpY2F0ZSB0aGF0Lg0KPiANCj4gDQo+ID4gPiA+
ICsgICAgICAgICAgIHBtdS0+dGltZXJfaW50ZXJ2YWwgPSBtc190b19rdGltZShNQk1fVElNRV9E
RUxUQV9NQVgpOw0KPiA+ID4gPiArICAgICAgICAgICBwZXJfY3B1KG1ibV9wbXUsIGNwdSkgPSBw
bXU7DQo+ID4gPiA+ICsgICAgICAgICAgIHBlcl9jcHUobWJtX3BtdV90b19mcmVlLCBjcHUpID0g
TlVMTDsNCj4gPiA+DQo+ID4gPiBXaGF0J3MgdGhlIHBvaW50IG9mIHRoaXM/IElmIHRoZXJlIGlz
IHN0aWxsIHNvbWV0aGluZyB0byBiZSBmcmVlJ2QgaXRzIGxlYWtlZC4NCj4gPiA+IE90aGVyd2lz
ZSB0aGF0J3MgcmVkdW5kYW50Lg0KPiA+IHBlcl9jcHUobWJtX3BtdV90b19mcmVlLCBjcHUpID0g
TlVMTDsgaXMgcmVtb3ZlZA0KPiA+DQo+ID4gPiA+ICsgICAgICAgICAgIG1ibV9ocnRpbWVyX2lu
aXQocG11KTsNCj4gPiA+ID4gKyAgIH0NCj4gPiA+ID4gKyAgIHJldHVybiAwOw0KPiA+ID4NCj4g
PiA+IHMvMC9OT1RJRllfT0svIGJlY2F1c2UgeW91IHJldHVybiB0aGF0IHZhbHVlIGRpcmVjdGx5
Lg0KPiA+ID4NCj4gPiBZb3UgbWVhbiBJIHJldHVybiB0aGUg4oCYcmV0dXJuIGNvZGXigJkNCj4g
DQo+ID8NCj4gDQo+IFlvdSBzaG91bGQgYmUgdXNpbmcgTk9USUZZX09LIGhlcmUgc28gdGhhdCB5
b3UgZm9sbG93IHRoZSBub3RpZmllciBBUEkNCj4gY29udmVudGlvbi4NCj4gDQoNCg==
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1221000

From"Juvva, Kanaka D" <kanaka.d.juvva@intel.com>
Date2015-09-08 19:10 +0200
Message-ID<q6uz7-26l-7@gated-at.bofh.it>
In reply to#1220719
SGkgTWF0dCwNCg0KICBIZXJlIGlzIGEgcmVzcG9uc2UgdG8gYWxsICB5b3VyIGNvbW1lbnRzIGRv
d24gYmVsb3cuDQoNClRoYW5rcywNCi1LYW5ha2EgDQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdl
LS0tLS0NCj4gRnJvbTogRmxlbWluZywgTWF0dA0KPiBTZW50OiBUdWVzZGF5LCBTZXB0ZW1iZXIg
OCwgMjAxNSA0OjQ3IEFNDQo+IFRvOiBKdXZ2YSwgS2FuYWthIEQNCj4gQ2M6IFRob21hcyBHbGVp
eG5lcjsgS2FuYWthIEp1dnZhOyBXaWxsaWFtc29uLCBHbGVubiBQOyBBdWxkLCBXaWxsOyBBbmRp
IEtsZWVuOw0KPiBMS01MOyBMdWNrLCBUb255OyBQZXRlciBaaWpsc3RyYTsgVGVqdW4gSGVvOyB4
ODZAa2VybmVsLm9yZzsgSW5nbyBNb2xuYXI7IEguDQo+IFBldGVyIEFudmluOyBTaGl2YXBwYSwg
VmlrYXMNCj4gU3ViamVjdDogUmU6IFtQQVRDSCB2MyAxLzJdIHBlcmYseDg2OiBhZGQgSW50ZWwg
TWVtb3J5IEJhbmR3aWR0aCBNb25pdG9yaW5nDQo+IChNQk0pIFBNVQ0KPiANCj4gT24gTW9uLCAy
MDE1LTA5LTA3IGF0IDIwOjIyICswMTAwLCBKdXZ2YSwgS2FuYWthIEQgd3JvdGU6DQo+ID4gSGkg
VGhvbWFzLA0KPiA+DQo+ID4gICAgSSdtIHNlbmRpbmcgdXBkYXRlZCBwYXRjaChzKS4gSSBoYXZl
IGdpdmVuIGRldGFpbHMgZm9yIGVhY2ggb2YNCj4gPiB0aGVzZSBpdGVtcyBiZWxvdy4NCj4gPg0K
PiANCj4gS2FuYWthLCB0aGlzIGVtYWlsIGlzIEhUTUwgZm9ybWF0dGVkIGFuZCBzbyBoYXMgYmVl
biBibG9ja2VkIGJ5DQo+IHZnZXIua2VybmVsLm9yZyB3aGVyZSB0aGUgbGludXgta2VybmVsIG1h
aWxpbmcgbGlzdCBpcyBob3N0ZWQuDQo+IA0KPiBQbGVhc2UgY29uZmlndXJlIG91dGxvb2sgbm90
IHRvIHNlbmQgaHRtbCBlbWFpbCwgb3IgdXNlIGEgZGlmZmVyZW50IG1haWwgYWdlbnQNCj4gZm9y
IHdvcmtpbmcgd2l0aCB1cHN0cmVhbS4NCj4gDQoNCkRvbmUuDQoNCj4gPiBSZWdhcmRzLA0KPiA+
IC1LYW5ha2ENCj4gPg0KPiA+ID4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gPiA+IEZy
b206IFRob21hcyBHbGVpeG5lciBbbWFpbHRvOnRnbHhAbGludXRyb25peC5kZV0NCj4gPiA+IFNl
bnQ6IFdlZG5lc2RheSwgQXVndXN0IDE5LCAyMDE1IDE6NTAgUE0NCj4gPiA+IFRvOiBLYW5ha2Eg
SnV2dmENCj4gPiA+IENjOiBKdXZ2YSwgS2FuYWthIEQ7IFdpbGxpYW1zb24sIEdsZW5uIFA7IEZs
ZW1pbmcsIE1hdHQ7IEF1bGQsIFdpbGw7DQo+ID4gQW5kaSBLbGVlbjsNCj4gPiA+IExLTUw7IEx1
Y2ssIFRvbnk7IFBldGVyIFppamxzdHJhOyBUZWp1biBIZW87IHg4NkBrZXJuZWwub3JnOyBJbmdv
DQo+ID4gTW9sbmFyOyBILg0KPiA+ID4gUGV0ZXIgQW52aW47IFNoaXZhcHBhLCBWaWthcw0KPiA+
ID4gU3ViamVjdDogUmU6IFtQQVRDSCB2MyAxLzJdIHBlcmYseDg2OiBhZGQgSW50ZWwgTWVtb3J5
IEJhbmR3aWR0aA0KPiA+IE1vbml0b3JpbmcNCj4gPiA+IChNQk0pIFBNVQ0KPiA+ID4NCj4gPiA+
IE9uIEZyaSwgNyBBdWcgMjAxNSwgS2FuYWthIEp1dnZhIHdyb3RlOg0KPiA+ID4gPiArI2RlZmlu
ZSBNQk1fQ05UUl9NQVggICAgICAgICAgICAgICAweGZmZmZmZg0KPiA+ID4gPiArI2RlZmluZSBN
Qk1fU09DS0VUX01BWCAgICAgICAgICAgICA4DQo+ID4gPiA+ICsjZGVmaW5lIE1CTV9USU1FX0RF
TFRBX01BWCAxMDAwDQo+ID4gPiA+ICsjZGVmaW5lIE1CTV9USU1FX0RFTFRBX01JTiAxMDANCj4g
PiA+DQo+ID4gPiBXaGF0IGFyZSB0aGVzZSBjb25zdGFudHMgZm9yIGFuZCBob3cgYXJlIHRoZXkg
ZGV0ZXJtaW5lZD8gUHVsbGVkIG91dA0KPiA+ID4gb2YgdGhpbiBhaXI/DQo+ID4gPg0KPiA+DQo+
ID4gLyoNCj4gPiAqIE1CTSBDb3VudGVyIGlzIDI0Yml0cyB3aWRlLiBNQk1fQ05UUl9NQVggZGVm
aW5lcyBtYXggY291bnRlcg0KPiA+ICogdmFsdWUNCj4gPiAqLw0KPiA+ICNkZWZpbmUgTUJNX0NO
VFJfTUFYICAgICAgICAgICAgMHhmZmZmZmYNCj4gPiAvKg0KPiA+ICogTWF4ICNzb2NrZXRzIHN1
cHBvcnRlZA0KPiA+ICovDQo+ID4gI2RlZmluZSBNQk1fU09DS0VUX01BWCAgICAgICAgICA4DQo+
IA0KPiBUaGlzIHNlZW1zIGxpa2UgYSBjb25zdGFudCB3ZSBjb3VsZCBnZXQgYnkgd2l0aG91dC4g
RG8gd2UgcmVhbGx5IG5lZWQgdG8ga25vdw0KPiB0aGlzIGF0IGNvbXBpbGUgdGltZT8NCj4NCg0K
SSBzcG9rZSB0byBBbmRpIEtsZWVuIHJlZ2FyZGluZyBob3cgbWFueSBzb2NrZXRzLiBXZSBkZWNp
ZGVkIHdlIGNvdWxkIGtlZXAgOC4NCg0KIA0KPiA+IC8qDQo+ID4gKiBFeHBlY3RlZCB0aW1lIGlu
dGVydmFsIGJldHdlZW4gY29uc2VjdXRpdmUgTVNSIHJlYWRzIGZvciBhIGdpdmVuIHJtaWQNCj4g
PiAqLw0KPiA+ICNkZWZpbmUgTUJNX1RJTUVfREVMVEFfTUFYICAgICAgMTAwMA0KPiANCj4gIm1h
eCIgYW5kICJleHBlY3RlZCIgYXJlIG5vdCB0aGUgc2FtZSB0aGluZy4NCj4gDQo+DQoNClRoaXMg
aXMgYmVpbmcgY2hhbmdlZCB0byAjZGVmaW5lIE1CTV9USU1FX0RFTFRBX0VYUCAgICAgMTAwMA0K
IA0KPiA+ID4gPiAgI2RlZmluZSBRT1NfTDNfT0NDVVBfRVZFTlRfSUQgICAgICAoMSA8PCAwKQ0K
PiA+ID4gPiArI2RlZmluZSBRT1NfTUJNX1RPVEFMX0VWRU5UX0lEICAgICAoMSA8PCAxKQ0KPiA+
ID4gPiArI2RlZmluZSBRT1NfTUJNX0xPQ0FMX0VWRU5UX0lEX0hXICAgMHgzDQo+ID4gPiA+ICsj
ZGVmaW5lIFFPU19NQk1fTE9DQUxfRVZFTlRfSUQgICAgICgxIDw8IDIpDQo+ID4gPg0KPiA+ID4g
U28gd2UgaGF2ZSBJRCB2YWx1ZXMgd2hpY2ggYXJlIGJ1aWx0IHdpdGggKDEgPDwgWCkgYW5kIHRo
ZW4gdGhpcyBIVw0KPiA+ID4gdmFyaWFudCBpbiB0aGUgbWlkZGxlIHdpdGggMHgzLiBPZiBjb3Vy
c2Ugd2l0aG91dCBhbnkgZXhwbGFuYXRpb24gd2hhdCB0aGUNCj4gaGVjayB0aGlzIHN0dWZmIGlz
Lg0KPiA+ID4NCj4gPiA+IExhc3QgcmV2aWV3Og0KPiA+ID4NCj4gPiA+ICAgICAgIlNvIHRoaXMg
d2FudHMgYSBkZXNjcmlwdGl2ZSBJRCBuYW1lIGFuZCBhIGNvbW1lbnQuIg0KPiA+ID4NCj4gPiA+
DQo+ID4NCj4gPiAvKg0KPiA+ICogTUJNIEV2ZW50IElEcyBhcyBkZWZpbmVkIGluIFNETSBzZWN0
aW9uIDE3LjE0LjYNCj4gPiAqIEV2ZW50IElEcyB1c2VkIHRvIHByb2dyYW0gTVNScyBmb3IgcmVh
ZGluZyBjb3VudGVycw0KPiA+ICovDQo+ID4gI2RlZmluZSBRT1NfTUJNX1RPVEFMX0VWRU5UX0lE
ICAoMSA8PCAxKQ0KPiA+ICNkZWZpbmUgUU9TX01CTV9MT0NBTF9FVkVOVF9JRF9IVyAgICAgICAg
MHgzDQo+ID4gLyoNCj4gPiAqIFBlcmYgbmVlZHMgZXZlbnQgaWQgdG8gYmUgMSA8PCB4LCBoZW5j
ZSB3ZSBjYW4ndCB1c2UgMHgzIChIVyBFVkVOVCBJRCkNCj4gPiAqIGZvciBNQk1fTE9DQUxfRVZF
TlQgd2UgdXNlIG5leHQgMSA8PCB4IGZvciBNQk1fTE9DQUxfRVZFTlRfSUQNCj4gPiAqLw0KPiA+
ICNkZWZpbmUgUU9TX01CTV9MT0NBTF9FVkVOVF9JRCAgKDEgPDwgMikNCj4gDQo+IE5vLCBwZXJm
IGV2ZW50cyBkbyBub3QgbmVlZCB0byBiZSBvZiB0aGUgZm9ybSAoMSA8PCBYKSwgdGhhdCB3YXMg
anVzdCBhDQo+IGNvbnZlbnRpb24gd2UgdXNlZCBpbiB0aGUgY3FtIGNvZGUgYmVmb3JlIHdlIGtu
ZXcgd2hhdCB2YWx1ZXMgdGhlIE1CTQ0KPiBldmVudHMgd291bGQgdGFrZSAtIHlvdSBjYW4gY2hh
bmdlIHRoZXNlIHRvIGJlIHdoYXRldmVyIGZvcm1hdCB5b3Ugd2FudCwgYnV0DQo+IGJlIHN1cmUg
dG8gbWFrZSBpdCBjb25zaXN0ZW50Lg0KPiANCj4gVGhlIGNvbnN0YW50cyBhcmUgdmVyeSBtdWNo
IHN1cHBvc2VkIHRvIGJlIHByb2dyYW1tZWQgaW50byB0aGUgTVNScywgdGFrZSBhDQo+IGxvb2sg
YXQgX19ybWlkX3JlYWQoKS4NCj4gDQo+IEkgd291bGQgc3VnZ2VzdCAoYXMgSSBhbHJlYWR5IGRp
ZCBwcml2YXRlbHkpIHRoYXQgeW91IGNoYW5nZSB0aGUgZm9ybWF0IHRvIGJlDQo+IDB4MHggZm9y
IGFsbCBvZiB0aGVzZSBldmVudCBJRHMuDQo+IA0KPiANCg0KVGhlcmUgYXJlIHR3byBhc3BlY3Rz
Og0KDQogMSkgUHJvZ3JhbW1pbmcgTVNScw0KIDIpIEVWRU5UX0FUVFJfU1RSKGxsY19sb2NhbF9i
dywgaW50ZWxfY3FtX2xsY19sb2NhbF9idywgImV2ZW50PTB4MDQiKTsNCg0KIDEgaXMgdXNlZCBm
b3IgcHJvZ3JhbW1pbmcgTVNScw0KIDIgZXZlbnQgYXR0cmlidXRlIGZvciBwZXJmDQogIA0KDQog
Rm9yIE1CTV9MT0NBTF9FVkVOVCBIVyBJRCBpcyAweDMuIFdlIGRvbid0IHdhbnQgdG8gdXNlIDB4
MyBmb3IgRVZFTlQgQVRUUi4gDQoNCklmIHdlIHVzZSAweDMgZm9yIGV2ZW50X2F0dHJpYnV0ZQ0K
DQpXZSBjYW4ndCBjbGVhcmx5IGRpc3Rpbmd1aXNoIHdoZXRoZXIgaXMgRVZFTlQgMDEgJiBFVkVO
VCAwMiBvciBFVkVOVCAwMyBhbG9uZS4NCiBGb3IgcGVyZiBldmVudCBhdHRyaWJ1dGUgIGl0IGhh
cyB0byBiZSAweDA0LiBCZWNhdXNlIDB4MDEgYW5kIDB4MDIgYXJlIHVzZWQgZm9yIG90aGVyIHR3
byBldmVudHMNCg0KPiA+ID4gPiBAQCBzdGF0aWMgYm9vbCBpbnRlbF9jcW1fc2NoZWRfaW5fZXZl
bnQodTMyIHJtaWQpDQo+ID4gPiA+ICAgICAgcmV0dXJuIGZhbHNlOw0KPiA+ID4gPiAgfQ0KPiA+
ID4gPg0KPiA+ID4gPiArDQo+ID4gPiA+ICtzdGF0aWMgdTMyIGJ3X3N1bV9jYWxjKHN0cnVjdCBz
YW1wbGUgKmJ3X3N0YXQsIGludCBybWlkKSB7DQo+ID4gPiA+ICsgICB1MzIgdmFsID0gMCwgaSwg
aiwgaW5kZXg7DQo+ID4gPiA+ICsNCj4gPiA+ID4gKyAgIGlmICgrK2J3X3N0YXQtPmZpZm9vdXQg
Pj0gIG1ibV93aW5kb3dfc2l6ZSkNCj4gPiA+ID4gKyAgICAgICAgICAgYndfc3RhdC0+Zmlmb291
dCA9ICAwOw0KPiA+ID4gPiArICAgaW5kZXggPSAgYndfc3RhdC0+Zmlmb291dDsNCj4gPiA+ID4g
KyAgIGZvciAoaSA9IDA7IGkgPCBtYm1fd2luZG93X3NpemUgLSAxOyBpKyspIHsNCj4gPiA+ID4g
KyAgICAgICAgICAgaWYgKGluZGV4ICsgaSA+PSBtYm1fd2luZG93X3NpemUpDQo+ID4gPiA+ICsg
ICAgICAgICAgICAgICAgICAgaiA9IGluZGV4ICsgaSAtIG1ibV93aW5kb3dfc2l6ZTsNCj4gPiA+
ID4gKyAgICAgICAgICAgZWxzZQ0KPiA+ID4gPiArICAgICAgICAgICAgICAgICAgIGogPSBpbmRl
eCArIGk7DQo+ID4gPiA+ICsgICAgICAgICAgIHZhbCArPSBid19zdGF0LT5tYm1maWZvW2pdOw0K
PiA+ID4gPiArICAgfQ0KPiA+ID4NCj4gPiA+IFRoaXMgbWF0aCB3YW50cyBhIGV4cGxhbmF0b3J5
IGNvbW1lbnQuDQo+ID4gPg0KPiA+IC8qDQo+ID4gKiBTbGlkZSB0aGUgd2luZG93IGJ5IDEgYW5k
IGNhbGN1bGF0ZSB0aGUgc3VtIG9mIHRoZSBsYXN0DQo+ID4gKiBtYm1fd2luZG93X3NpemUtMSAg
YmFuZHdpZHRoICB2YWx1ZXMuDQo+ID4gKiBmaWZvb3V0IGlzIHRoZSBjdXJyZW50IHBvc2l0aW9u
IG9mIHRoZSB3aW5kb3cuDQo+ID4gKiBJbmNyZW1lbnQgdGhlIGZpZm9vdXQgYnkgMSB0byBzbGlk
ZSB0aGUgd2luZG93IGJ5IDEuDQo+ID4gKg0KPiA+ICogQ2FsY2FsdXRlIHRoZSBiYW5kd2lkdGgg
ZnJvbSArK2ZpZmlvdXQgIHRvICggKytmaWZvb3V0ICsgbWJtX3dpbmRvd19zaXplIC0NCj4gMSkN
Cj4gPiAqIGUuZy5maWZvb3V0ID0xOyAgIEJhbmR3aWR0aDEgQmFuZHdpZHRoMiAuLi4uLiBCYW5k
d2lkdGhuIGFyZSB0aGUNCj4gPiAqIHNsaWRpbmcgd2luZG93IHZhbHVlcyB3aGVyZSBuIGlzIHNp
emUgb2YgdGhlIHNsaWRpbmcgd2luZG93DQo+ID4gKiAgYmFuZHdpZHRoIHN1bTogIHZhbCAgPSAg
QmFuZHdpZHRoMiArIEJhbmR3aWR0aDMgKyAuLiBCYW5kd2lkdGhuDQo+ID4gKi8NCj4gDQo+IElu
c3RlYWQgb2YgdGhlc2UgbGFyZ2UgY29tbWVudCBibG9ja3MgcGxlYXNlIGNvbW1lbnQgc21hbGxl
ciwgbG9naWNhbGx5LQ0KPiBjb25uZWN0ZWQgY2h1bmtzIG9mIGNvZGUsIGUuZy4NCj4NCg0KT0sN
Cg0KIA0KPiAJLyogU2xpZGUgdGhlIHdpbmRvdyBieSBvbmUgKi8NCj4gCWlmICgrK2J3X3N0YXQt
PmZpZm9vdXQgPj0gbWJtX3dpbmRvd19zaXplKQ0KPiAJCWJ3X3N0YXQtPmZpZm9vdXQgPSAwOw0K
PiANCj4gCS8qDQo+IAkgKiBDYWxjdWxhdGUgdGhlIHN1bSBvZiBsYXN0IG1ibV93aW5kb3dfc2l6
ZS0xIHZhbHVlcy4NCj4gCSAqLw0KPiAJZm9yIChpID0gMDsgaSA8IG1ibV93aW5kb3dfc2l6ZSAt
IDE7IGkrKykgew0KPiAJCS8qIEhhbmRsZSB3cmFwYXJvdW5kIGF0IGVuZCBvZiB3aW5kb3cgKi8N
Cj4gCQlpZiAoaW5kZXggKyBpID49IG1ibV93aW5kb3dfc2l6ZSkNCj4gCQkJaiA9IGluZGV4ICsg
aSAtIG1ibV93aW5kb3dfc2l6ZTsNCj4gCQllbHNlDQo+IAkJCWogPSBpbmRleCArIGk7DQo+IA0K
PiAJCXZhbCArPSBid19zdGF0LT5tYm1pbmZvW2pdOw0KPiAJfQ0KPiANCj4gPg0KPiA+DQo+ID4g
PiA+ICsgICByZXR1cm4gdmFsOw0KPiA+ID4gPiArfQ0KPiA+ID4gPiArDQo+ID4gPiA+ICtzdGF0
aWMgdTMyIF9fbWJtX2ZpZm9fc3VtX2xhc3RuX291dChpbnQgcm1pZCwgYm9vbCBpc19sb2NhbGJ3
KSB7DQo+ID4gPiA+ICsgICBpZiAoaXNfbG9jYWxidykNCj4gPiA+ID4gKyAgICAgICAgICAgcmV0
dXJuIGJ3X3N1bV9jYWxjKCZtYm1fbG9jYWxbcm1pZF0sIHJtaWQpOw0KPiA+ID4gPiArICAgZWxz
ZQ0KPiA+ID4gPiArICAgICAgICAgICByZXR1cm4gYndfc3VtX2NhbGMoJm1ibV90b3RhbFtybWlk
XSwgcm1pZCk7IH0NCj4gPiA+ID4gKw0KPiA+ID4gPiArc3RhdGljIHZvaWQgX19tYm1fZmlmb19p
bihzdHJ1Y3Qgc2FtcGxlICpid19zdGF0LCB1MzIgdmFsKSB7DQo+ID4gPiA+ICsgICBid19zdGF0
LT5tYm1maWZvW2J3X3N0YXQtPmZpZm9pbl0gPSB2YWw7DQo+ID4gPiA+ICsgICBpZiAoKytid19z
dGF0LT5maWZvaW4gPj0gbWJtX3dpbmRvd19zaXplKQ0KPiA+ID4NCj4gPiA+IEhvdyBkb2VzIHRo
YXQgYmVjb21lIGdyZWF0ZXIgdGhhbiBtYm1fd2luZG93c2l6ZT8NCj4gPiA+DQo+ID4NCj4gPiBU
aGlzIGlzIGZpeGVkIGJ5IGNoYW5naW5nID49IHRvID09DQo+ID4gQWRkZWQgYSBjb21tZW50Og0K
PiA+DQo+ID4gLyoNCj4gPiAqIHN0b3JlIGN1cnJlbnQgc2FtcGxlJ3MgYncgdmFsdWUgaW4gc2xp
ZGluZyB3aW5kb3cgYXQgdGhlDQo+ID4gKiBpbmRleCBmaWZvaW4uIEluY3JlbWVudCBmaWZvaW4u
IENoZWNrIGlmIGZpZm9pbiBoYXMgcmVhY2hlZA0KPiA+ICogbWF4X3dpbmRvd19zaXplLiBJZiB5
ZXMgcmVzZXQgaXQgdG8gYmVnaW5pbmcgaS5lLiB6ZXJvDQo+ID4gKiBlLmcuDQo+ID4gKiBtYm1f
d2luZG93X3NpemUgPSAxMA0KPiA+ICogbWJtZmlmbyBpcyBhIGNpcmN1bGFyIGZpZm8gICAwIDEg
MiAzIDQgNSA2IDcgOCA5IDEwDQo+ID4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgIF4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KPiA+ICogICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgfA0KPiA+ICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICB8IF8gXyBfIF8gXyBfIF8gXyBfIF98DQo+ID4gKg0KPiA+ICogU28gd2hl
biBmaWZvaW4gYmVjb21lcyAxMCwgdGhlbiBpdCBpcyByZXNldCB0byB6ZXJvDQo+ID4gKg0KPiA+
ICovDQo+IA0KPiBJJ20gbm90IHN1cmUgdGhhdCB0aGlzIGNvbW1lbnQgYWRkcyBhbnl0aGluZyBv
ZiB2YWx1ZSB0aGF0IGlzbid0IGFscmVhZHkNCj4gdW5kZXJzdG9vZCBieSByZWFkaW5nIHRoZSBj
b2RlLiBJIGRvbid0IHRoaW5rIHlvdSBuZWVkIGEgY29tbWVudCBmb3IgdGhpcw0KPiBmdW5jdGlv
biwgaXQgc2VlbXMgcHJldHR5IHN0cmFpZ2h0IGZvcndhcmQgYW5kIFRob21hcycgcXVlc3Rpb24g
d2FzIGFib3V0IHRoZQ0KPiBib3VuZGFyeSBsaW1pdHMgb2YgLT5maWZvaW4uDQo+IA0KDQpUaG9t
YXMgcXVlc3Rpb24gd2FzICBhZGRyZXNzZWQgYnkgdGhlIGNoYW5nZSBpbiBpZiBzdGF0ZW1lbnQg
aS5lICAnPT0nJw0KSSdsbCB0YWtlIG91dCB0aGUgY29tbWVudC4NCg0KPiA+ID4gPiArICAgICAg
ICAgICBid19zdGF0LT5maWZvaW4gPSAwOw0KPiA+ID4gPiArfQ0KPiA+ID4NCj4gPiA+ID4gKy8q
DQo+ID4gPiA+ICsgKiBfX3JtaWRfcmVhZF9tYm0gY2hlY2tzIHdoZXRoZXIgaXQgaXMgTE9DQUwg
b3IgR0xPQkFMIE1CTSBldmVudA0KPiA+ID4gPiArYW5kIHJlYWRzDQo+ID4gPiA+ICsgKiBpdHMg
TVNSIGNvdW50ZXIuIENoZWNrIHdoZXRoZXIgb3ZlcmZsb3cgb2NjdXJyZWQgYW5kIGhhbmRsZXMg
aXQuDQo+ID4gPiA+ICtDYWxjdWxhdGVzDQo+ID4gPiA+ICsgKiBjdXJyZW5ldCAgQlcgYW5kIHVw
ZGF0ZXMgIHJ1bm5pbmcgYXZlcmFnZS4NCj4gPiA+DQo+ID4gPiBjdXJyZW5ldD8gQW5kIHBsZWFz
ZSBnZXQgcmlkIG9mIHRoZSBkb3VibGUgc3BhY2VzDQo+ID4gPg0KPiA+IFRoaXMgaXMgZml4ZWQg
bm93LiAgSGVyZSBpcyB0aGUgdXBkYXRlZCBjb21tZW50Og0KPiA+DQo+ID4gLyoNCj4gPiAqIHJt
aWRfcmVhZF9tYm0gY2hlY2tzIHdoZXRoZXIgaXQgaXMgTE9DQUwgb3IgVG90YWwgTUJNIGV2ZW50
IGFuZCByZWFkcw0KPiA+ICogaXRzIE1TUiBjb3VudGVyLiBDaGVjayB3aGV0aGVyIG92ZXJmbG93
IG9jY3VyZWQgYW5kIGhhbmRsZXMgaXQuIENhbGN1bGF0ZXMNCj4gPiAqIGN1cnJlbmV0ICBCVyBh
bmQgdXBkYXRlcyAgcnVubmluZyBhdmVyYWdlLg0KPiA+ICoNCj4gDQo+IF5eXiBZb3UndmUgc3Rp
bGwgbWlzc3BlbGxlZCBjdXJyZW50Lg0KDQpGaXhlZA0KDQo+ID4NCj4gPiAqIE92ZXJmbG93IEhh
bmRsaW5nOg0KPiA+ICogaWYgKE1TUiBjdXJyZW50IHZhbHVlIDwgTVNSIHByZXZpb3VzIHZhbHVl
KSBpdCBpcyBhbg0KPiA+ICogb3ZlcmZsb3cuIE1TUiB2YWx1ZXMgYXJlIGluY3JlYXNpbmcgd2hl
biBiYW5kd2lkdGggY29uc3VtcHRpb24gZm9yIHRoZQ0KPiB0aHJlYWQNCj4gPiAqIGlzIG5vbi16
ZXJvOyBXaGVuIE1TUiB2YWx1ZXMgcmVhY2hlcyBNQVhfQ09VTlRFUl9WQUxVRSBpdCBvdmVyZmxv
d3MuDQo+IEFmdGVyIG92ZXJmbG93LA0KPiA+ICogTVNSIGN1cnJlbnQgdmFsdWUgZ29lcyBiYWNr
IHRvIHplcm8gYW5kIHN0YXJ0cyBpbmNyZWFzaW5nIGFnYWluIGF0IHRoZSByYXRlDQo+IG9mDQo+
ID4gKiBiYW5kd2lkdGguDQo+ID4gKg0KPiANCg0KSG93IG92ZXJmbG93IGhhbmRsaW5nIGlzIGRv
d24gYmVsb3cuIEknbGwgY2hhbmdlIHRoaXMgYXMgcGVyIHRoZSBjb21tZW50cw0KDQo+IFlvdSBk
b24ndCBuZWVkIHRvIHByb3ZpZGUgYSBkZWZpbml0aW9uIG9mICJvdmVyZmxvdyIsIG1vc3QgcGVv
cGxlIHdpbGwgYmUNCj4gZmFtaWxpYXIgd2l0aCBpdC4gV2hhdCBpcyBtb3JlIGltcG9ydGFudCB0
byBkb2N1bWVudCBpcyBob3cgdGhlIG92ZXJmbG93IGlzDQo+IGhhbmRsZWQuLi4NCj4gPg0KPiA+
ICogT3ZlcmZsb3cgaGFuZGxpbmc6DQo+ID4gKiBEZXRlY3QgYW4gb3ZlcmZsb3cgOiAgY3VycmVu
dCByZWFkIHZhbHVlID4gbGFzdCByZWFkIHZhbHVlDQo+IA0KPiBJc24ndCB0aGlzIGludmVydGVk
PyBPdmVyZmxvdyBvY2N1cnJlZCBpZiBjdXJyZW50IDwgcHJldmlvdXMuDQo+IA0KPiA+DQo+ID4g
KiBPdmVyZmxvdyBjb3JyZWN0aW9uOiAgaWYgKG92ZXJmbG93KQ0KPiA+ICogICAgICAgICAgICAg
ICAgICAgICAgICAgIEN1cnJlbnQgdmFsdWUgPSAoTUFYX0NPVU5URVJfVkFMVUUgLSBwcmV2IHJl
YWQgdmFsdWUpICsNCj4gY3VycmVudCByZWFkIHZhbHVlDQo+ID4gKiAgICAgICAgICAgICAgICAg
ICAgICAgZWxzZQ0KPiA+ICogICAgICAgICAgICAgICAgICAgICAgICAgIEN1cnJlbnQgdmFsdWUg
PSBjdXJyZW50IHJlYWQgdmFsdWUNCj4gPiAqDQo+IA0KPiBQbGVhc2UgZG9uJ3Qgd3JpdGUgcHNl
dWRvY29kZSBpbiB0aGUgY29tbWVudHMuIFVzZSBFbmdsaXNoIHByb3NlIHRvIGRlc2NyaWJlDQo+
IHRoZSBpbXBvcnRhbnQgcGFydHMgb2YgdGhlIGNvZGUuDQo+IA0KT0sNCg0KPiA+DQo+ID4gKiBD
YWxjdWxhdGlvbiBvZiBDdXJyZW50IEJhbmR3aWR0aCB2YWx1ZToNCj4gPiAqIElmIE1TUiBpcyBy
ZWFkIHdpdGhpbiBsYXN0IDEwMG1zLCB0aGVuIHRoZW4gdGhlIHNtYXBsZSBpcyBpZ25vcmVkOw0K
PiA+ICogSWYgdGhlIE1TUiB3YXMgUmVhZCB3aXRoIGluIGxhc3QgMTAwbXMsIHdoeSAgaW5jdXIg
YW4gZXh0cmEgb3ZlcmhlYWQNCj4gPiAqIG9mIGRvaW5nIHRoZSBNU1IgcmVhZHMgYWdhaW4uIEFu
eXdheSB0aGVyZSdsbCBiZSBhIG5lZ2xpZ2libGUgY2hhbmdlIG9yIHplcm8NCj4gPiAqIGNoYW5n
ZSBpbiBNU1IgcmVhZGluZ3MgaW4gMTAwbXMuDQo+ID4gKg0KPiA+ICogQmFuZHdpZHRoIGlzIGNh
bGN1bGF0ZWQgYXM6DQo+ID4gKiBtZW1vcnkgYmFuZHdpZHRoID0gZGlmZmVyZW5jZSBvZiBsYXN0
IHR3byBtc3IgY291bnRlciB2YWx1ZXMvdGltZQ0KPiBkaWZmZXJlbmNlLg0KPiA+ICoNCj4gPiAq
IGN1bV9hdmcgPSBSdW5uaW5nIEF2ZXJhZ2UgYmFuZHdpZHRoIG9mIGxhc3QgJ24nIGJhbmR3aWR0
aCB2YWx1ZXMgZm9yDQo+ID4gKiB0aGUgc2FtcGxlcyB0aGF0IGFyZSBwcm9jZXNzZWQNCj4gPiAq
DQo+IA0KPiBXaGVyZSAnbicgaXMgJ21ibV93aW5kb3dfc2l6ZScgPyBJZiBzbywgcGxlYXNlIHVz
ZSAnbWJtX3dpbmRvd19zaXplJywgbm90ICduJy4NCg0KT0sNCg0KDQo+ID4NCj4gPiAqIFNsaWRp
bmcgd2luZG93IGlzIHVzZWQgdG8gc2F2ZSB0aGUgbGFzdCAnbicgc2FtcGxlcy4gV2hlcmUsDQo+
ID4gKiBuID0gc2xpZGluZ193aW5kb3dfc2l6ZSBhbmQgcmVzdWx0cyBpbiBzbGlkaW5nIHdpbmRv
dyBkdXJhdGlvbiBvZiAnbicgc2Vjcy4NCj4gDQo+IEhtbS4uLiB0aGlzIGNvbmZ1c2VzIG1lIGEg
bG90LiBJcyAnbicgYSBzaXplIG9yIGEgZHVyYXRpb24/IFRoZSB0d28gYXJlIG5vdCB0aGUNCj4g
c2FtZSB0aGluZy4NCj4gDQpBY3R1YWxseSAgdGhleSBoYXZlIHNhbWUgdmFsdWVzLiBBbnl3YXlz
IEknbGwgY2hhbmdlIHRoZSBjb21tZW50IHRvIHRhbGsgYWJvdXQgDQpkdXJhdGlvbi4gVGhhdCB3
YXkgaXQgd2lsbCBub3QgYmUgYSAgY29uZnVzaW9uLg0KDQo+ID4NCj4gPiAqIFRoZSBzbGlkaW5n
IHdpbmRvdyBzaXplIGJ5IGRlZmF1bHQgc2V0IHRvDQo+ID4gKiBNQk1fRklGT19TSVpFX01JTi4g
VXNlciBjYW4gY29uZmlndXJlIGl0IHRvIHRoZSB2YWx1ZXMgaW4gdGhlIHJhbmdlDQo+ID4gKiAo
TUJNX0ZJRk9fU0laRV9NSU4sTUJNX0ZJRk9fU0laRV9NQVgpLiBUaGUgcmFuZ2UgZm9yIHNsaWRp
bmcgd2luZG93DQo+ID4gKiBpcyBjaG9zZW4gYmFzZWQgb24gYSBnZW5lcmFsIGNyaXRlcmlhIGZv
ciBtb25pdG9yaW5nIGR1cmF0aW9uLiBFeGFtcGxlDQo+ID4gKiBmb3IgYSBzaG9ydCBsaXZlZCBh
cHBsaWNhdGlvbiwgMTBzZWMgbW9uaXRvcmluZyBwZXJpb2QgZ2l2ZXMNCj4gPiAqIGdvb2QgY2hh
cmFjdGVyaXphdGlvbiBvZiBpdHMgYmFuZHdpZHRoIGNvbnN1bXB0aW9uLiBGb3IgYW4gYXBwbGlj
YXRpb24NCj4gPiAqIHRoYXQgcnVucyBmb3IgbG9uZ2VyIGR1cmF0aW9uLCAzMDBzZWMgbW9uaXRv
cmluZyBwZXJpb2QgZ2l2ZXMgYmV0dGVyDQo+ID4gKiBjaGFyYWN0ZXJpemF0aW9uIG9mIGl0cyBi
YW5kd2lkdGggY29uc3VtcHRpb24uIFNpbmNlIHRoZSBydW5uaW5nIGF2ZXJhZ2UNCj4gPiAqIGNh
bGN1bGF0ZWQgZm9yIHRvdGFsIG1vbml0b3JpbmcgcGVyaW9kLCB1c2VyIGdldHMgdGhlIG1vc3Qg
YWNjdXJhY2F0ZQ0KPiA+ICogYXZlcmFnZSBiYW5kd2lkdGggZm9yIHRoZSBlYWNoIG1vbml0b3Jp
bmcgcGVyaW9kLg0KPiA+ICoNCj4gPiAqIFNjYWxpbmc6DQo+ID4gKiBjdW1fYXZnIGlzIHRoZSBy
YXcgYmFuZHdpZHRoIGlzIEJ5dGVzL3NlYy4NCj4gPiAqIGN1bV9hdmcgaXMgY29udmVydGVkIHRv
IE1CL3NlYyBieSBhcHBseWluZyAgTUJNX0NPTlZFUlNJT05fRkFDVE9SDQo+IGFuZA0KPiA+ICog
cm91bmRlZCB0byBuZWFyZXN0IGludGVnZXIuIFVzZXIgaW50ZXJmYWNlIGdldHMgdGhlIEJhbmR3
aWR0aCB2YWx1ZXMgaW4NCj4gTUIvc2VjLg0KPiA+ICoNCj4gPiAqLw0KPiA+ID4gPiArICoNCj4g
PiA+ID4gKyAqIE92ZXJmbG93IEhhbmRsaW5nOg0KPiA+ID4gPiArICogaWYgKE1TUiBjdXJyZW50
IHZhbHVlIDwgTVNSIHByZXZpb3VzIHZhbHVlKSBpdCBpcyBhbg0KPiA+ID4gPiArICogb3ZlcmZs
b3cuIGFuZCBvdmVyZmxvdyBpcyBoYW5kbGVkLg0KPiA+ID4NCj4gPiA+IFdvdy4gVGhhdCdzIGlu
Zm9ybWF0aXZlIGFzIGhlbGwhDQo+ID4gPg0KPiA+IFBsZWFzZSBsb29rIGF0IHRoZSBtb2RpZmll
ZCBjb21tZW50IGFib3ZlDQo+ID4gPiA+ICsgKg0KPiA+ID4gPiArICogQ2FsY3VsYXRpb24gb2Yg
Q3VycmVudCBCVyB2YWx1ZToNCj4gPiA+DQo+ID4gPiBCVyA9PSBCb2R5IFdlaWdodD8NCj4gPiA+
DQo+ID4NCj4gPiBJdCBpcyBmaXhlZCBub3cNCj4gPg0KPiA+ID4gPiArICogSWYgTVNSIGlzIHJl
YWQgd2l0aGluIGxhc3QgMTAwbXMsIHRoZW4gdGhlIHZhbHVlIGlzIGlnbm9yZWQ7DQo+ID4gPiA+
ICsgKiB0aGlzIHdpbGwgc3VwcHJlc3Mgc21hbGwgZGVsdGFzLiBXZSBkb24ndCBwcm9jZXNzIE1C
TSBzYW1wbGVzDQo+ID4gPiA+ICsgdGhhdCBhcmUNCj4gPiA+ID4gKyAqIHdpdGhpbiAxMDBtcy4N
Cj4gPiA+DQo+ID4gPiBXSFk/DQo+ID4gPg0KPiA+IEV4cGxhaW5lZCBpbiB0aGUgY29tbWVudC4g
SWYgbWJtX3JlYWQgaXMgY2FsbGVkIHdpdGhpbiBpbiAxMDBtcyBmb3INCj4gPiB0aGUgc2FtZSBy
bWlkLCB3ZSBkb27igJl0IGhhdmUgdG8gcHJvY2VzcyB0aGUgc2FtcGxlLg0KPiANCj4gVGhlIGtl
eSBwaWVjZSBvZiBpbmZvcm1hdGlvbiB5b3UncmUgbWlzc2luZyBoZXJlIGlzIHRoYXQgc2tpcHBp
bmcgdGhlc2Ugc21hbGwNCj4gZGVsdGFzIGlzIGFuIG9wdGltaXphdGlvbiwgYmVjYXVzZSB3ZSBh
dm9pZCBwZXJmb3JtaW5nIGNvc3RseSBvcGVyYXRpb25zIGZvcg0KPiB3aGF0IHdvdWxkIGxpa2Vs
eSBiZSBhIHZlcnkgbWlub3IgY2hhbmdlIGluIHRoZSBNQk0gZGF0YSwgcmlnaHQ/DQo+IA0KPiAN
Cg0KWWVzLCBZb3UgYXJlIGNvcnJlY3QuDQoNCj4gPiA+ID4gK3sNCj4gPiA+ID4gKyAgIHU2NCB2
YWwsIHRtcCwgZGlmZl90aW1lLCBjbWEsIGJ5dGVzLCBpbmRleDsNCj4gPiA+ID4gKyAgIGJvb2wg
b3ZlcmZsb3cgPSBmYWxzZSwgZmlyc3QgPSBmYWxzZTsNCj4gPiA+ID4gKyAgIGt0aW1lX3QgY3Vy
X3RpbWU7DQo+ID4gPiA+ICsgICB1MzIgdG1wMzIgPSBybWlkOw0KPiA+ID4gPiArICAgc3RydWN0
IHNhbXBsZSAqbWJtX2N1cnJlbnQ7DQo+ID4gPiA+ICsgICB1MzIgdnJtaWQgPSB0b3BvbG9neV9w
aHlzaWNhbF9wYWNrYWdlX2lkKHNtcF9wcm9jZXNzb3JfaWQoKSkgKg0KPiA+ID4gPiArICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcW1fbWF4X3JtaWQgKyBybWlk
Ow0KPiA+ID4gPiArDQo+ID4gPiA+ICsgICBybWlkID0gdnJtaWQ7DQo+ID4gPg0KPiA+ID4gRnJv
bSBteSBwcmV2aW91cyByZXZpZXc6DQo+ID4gPg0KPiA+ID4gICAiVGhpcyBpcyBjb21wbGV0ZWx5
IGJhY2t3YXJkcy4NCj4gPiA+DQo+ID4gPiAgICAgICAgdG1wMzIgPSBybWlkOw0KPiA+ID4gICAg
ICAgIHJtaWQgPSB2cm1pZDsNCj4gPiA+ICAgICAgICBkb19zdHVmZihybWlkKTsNCj4gPiA+ICAg
ICAgICBybWlkID0gdG1wMzI7DQo+ID4gPiAgICAgICAgZG9fb3RoZXJfc3R1ZmYocm1pZCk7DQo+
ID4gPg0KPiA+ID4gICAgV2h5IGNhbid0IHlvdSB1c2UgdnJtaWQgZm9yIGRvX3N0dWZmKCkgYW5k
IGxlYXZlIHJtaWQgYWxvbmU/IEp1c3QNCj4gPiA+ICAgIGJlY2F1c2UgaXQgd291bGQgbWFrZSB0
aGUgY29kZSBzaW1wbGVyIHRvIHJlYWQ/Ig0KPiA+ID4NCj4gPiA+IFN0aWxsIGFwcGxpZXMuDQo+
ID4gPg0KPiA+DQo+ID4gVGhpcyBpcyBub3cgY2hhbmdlZCB0bw0KPiA+IHU2NCB2YWwsIGN1cnJl
bnRtc3IsIGN1cnJlbnRidywgZGlmZl90aW1lLCBjbWEsIGJ5dGVzLCBpbmRleDsNCj4gPiAgICAg
ICAgIGJvb2wgb3ZlcmZsb3cgPSBmYWxzZSwgZmlyc3QgPSBmYWxzZTsNCj4gPiAgICAgICAgIGt0
aW1lX3QgY3VyX3RpbWU7DQo+ID4gICAgICAgICB1MzIgdG1wMzIgPSBybWlkLCBldmVudGlkOw0K
PiA+ICAgICAgICAgc3RydWN0IHNhbXBsZSAqbWJtX2N1cnJlbnQ7DQo+ID4gICAgICAgICB1MzIg
dnJtaWQgPSBybWlkXzJfaW5kZXgocm1pZCk7DQo+ID4NCj4gPiAgICAgICAgIHJtaWQgPSB2cm1p
ZDsNCj4gPiAgICAgICAgIGN1cl90aW1lID0ga3RpbWVfZ2V0KCk7DQo+ID4gICAgICAgICBpZiAo
cmVhZF9tYm1fbG9jYWwpIHsNCj4gPiAgICAgICAgICAgICAgICAgbWJtX2N1cnJlbnQgPSAmbWJt
X2xvY2FsW3ZybWlkXTsNCj4gPiAgICAgICAgICAgICAgICAgZXZlbnRpZCAgICAgPSAgUU9TX01C
TV9MT0NBTF9FVkVOVF9JRF9IVzsNCj4gPiAgICAgICAgICAgICAgICAgd3Jtc3IoTVNSX0lBMzJf
UU1fRVZUU0VMLCBRT1NfTUJNX0xPQ0FMX0VWRU5UX0lEX0hXLA0KPiA+IHJtaWQpOw0KPiANCj4g
WW91IGRvbid0IG5lZWQgdG8gcGVyZm9ybSB0aGlzIHdybXNyKCkgaGVyZSBiZWNhdXNlIGl0J3Mg
dGFrZW4gY2FyZSBvZiBpbiB0aGUNCj4gY29tbW9uIGNvZGUgYmVsb3cuDQo+IA0KDQpPSw0KDQo+
ID4gICAgICAgICB9IGVsc2Ugew0KPiA+ICAgICAgICAgICAgICAgICBtYm1fY3VycmVudCA9ICZt
Ym1fdG90YWxbdnJtaWRdOw0KPiA+ICAgICAgICAgICAgICAgICBldmVudGlkICAgICA9IFFPU19N
Qk1fVE9UQUxfRVZFTlRfSUQ7DQo+ID4gICAgICAgICB9DQo+ID4gICAgICAgICBybWlkID0gdG1w
MzI7DQo+IA0KPiBXaHkgZGlkIHlvdSBhc3NpZ24gcm1pZCB0byB2cm1pZCBpZiB5b3UgcmVhc3Np
Z24gaXQgYmVmb3JlIGl0IHdhcyB1c2VkPw0KPiANCj4gDQoNCkZvciBNU1Igd3JpdGVzIHdlIHVz
ZSBybWlkIHZhbHVlIGFuZCBmb3IgbWJtXyogYXJyYXJ5IHdlIHVzZSB2cm1pZCB3aGljaCBpcyBh
Y3R1YWwNCmluZGV4Lg0KIA0KPiA+ID4gPiArICAgLyogaWYgY3VycmVudCBtc3IgdmFsdWUgPCAg
cHJldmlvdXMgbXNyIHZhbHVlICwgIGl0IG1lYW5zIG92ZXJmbG93ICovDQo+ID4gPiA+ICsgICBp
ZiAodmFsIDwgYnl0ZXMpIHsNCj4gPiA+ID4gKyAgICAgICAgICAgdmFsID0gTUJNX0NOVFJfTUFY
IC0gYnl0ZXMgKyB2YWw7DQo+ID4gPiA+ICsgICAgICAgICAgIG92ZXJmbG93ID0gdHJ1ZTsNCj4g
PiA+ID4gKyAgIH0gZWxzZQ0KPiA+ID4gPiArICAgICAgICAgICB2YWwgPSB2YWwgLSBieXRlczsN
Cj4gPiA+ID4gKw0KPiA+ID4gPiArICAgdmFsID0gICh2YWwgKiBNQk1fVElNRV9ERUxUQV9NQVgp
IC8gZGlmZl90aW1lOw0KPiA+ID4gPiArDQo+ID4gPiA+ICsgICBpZiAoKGRpZmZfdGltZSA+IE1C
TV9USU1FX0RFTFRBX01BWCkgJiYgKCFjbWEpKQ0KPiA+ID4gPiArICAgICAgICAgICAvKiBGaXJz
dCBzYW1wbGUgKi8NCj4gPiA+ID4gKyAgICAgICAgICAgZmlyc3QgPSB0cnVlOw0KPiA+ID4gPiAr
DQo+ID4gPiA+ICsgICBybWlkID0gdnJtaWQ7DQo+ID4gPg0KPiA+ID4gQW5kIGFub3RoZXIgdGlt
ZToNCj4gPiA+DQo+ID4gPiAgICJNb3JlIG9iZnVzY2F0aW9uIg0KPiA+ID4NCj4gPg0KPiA+ICAg
ICAgICAvKg0KPiA+ICAgICAgICAgICogTUJNX1RJTUVfREVMVEFfTUFYIGlzIHBpY2tlZCBhcyBw
ZXIgTUJNIHNwZWNzLiBBcyBzcGVjaWZpZWQgaW4NCj4gSW50ZWwgUGxhdGZvcm0NCj4gPiAgICAg
ICAgICAqIFF1YWxpdHkgb2YgU2VydmljZSBNb25pdG9yaW5nIEltcGxlbWVudGVyJ3MgR3VpZGUg
VjEsIFNlY3Rpb24gMi43LjIuDQo+IHBhZ2UgMjEsDQo+ID4gICAgICAgICAgKiBvdmVyZmxvdyBj
YW4gb2NjdXIgbWF4aW11bSBvbmNlIGluIGEgc2Vjb25kLiBTbyBsYXRlc3Qgd2Ugd2FudCB0bw0K
PiByZWFkIHRoZSBNU1INCj4gPiAgICAgICAgICAqIGNvdW50ZXJzIGlzIDEwMDBtcy4gSWYgaXQg
aXMgbGVzcyB0aGFuIDEwMDBtcyB3ZSBjYW4gIGlnbm9yZSB0aGUgc2FtcGxlLg0KPiBUaGVuIHdl
DQo+ID4gICAgICAgICAgKiBkZWNpZGUgc2luY2Ugd2hlbiB3ZSBzaG91bGQgaWdub3JlLiBJZiB0
aGUgTVNSIHdhcyBSZWFkIHdpdGggaW4gbGFzdA0KPiAxMDBtcywgd2h5DQo+ID4gICAgICAgICAg
KiBwcm9jZXNzIHRoZSBNU1IgcmVhZHMgYWdhaW4uIEFueXdheSB0aGVyZSdsbCBiZSBzbWFsbCBj
aGFuZ2Ugb3IgemVybw0KPiBjaGFuZ2UuDQo+ID4gICAgICAgICAgKiBTbyBpZ25vcmluZyBNU1Ig
UmVhZHMgd2l0aGluIDEwMG1zIG9yIGxlc3MgaXMgZWZmaWNpZW50Lg0KPiBNQk1fVElNRV9ERUxU
QV9NSU4NCj4gPiAgICAgICAgICAqIGlzIHNwZWNpZmllZCBhcyAxMDBtcyBhcyBwZXIgdGhpcyBn
dWlkZWxpbmUuDQo+ID4gICAgICAgICAgKg0KPiA+ICAgICAgICAgICovDQo+IA0KPiBJIHN1c3Bl
Y3QgdGhlIGRvY3VtZW50IHlvdSdyZSByZWZlcnJpbmcgdG8gYWJvdmUgaXMgb25seSBhdmFpbGFi
bGUgdW5kZXIgTkRBLA0KPiB3aGljaCBtYWtlcyBpdCB1bnN1aXRhYmxlIGZvciBtZW50aW9uIGlu
IHRoZSBrZXJuZWwgc291cmNlIHNpbmNlIGEgbGFyZ2UgbnVtYmVyDQo+IG9mIHBlb3BsZSB3b24n
dCBoYXZlIGFjY2VzcyB0byBpdC4NCj4gDQo+IEp1c3QgZXhwbGFpbiB0aGF0IHRoZSB3YXkgdGhl
IGhhcmR3YXJlIGlzIGRlc2lnbmVkIHB1dHMgYW4gdXBwZXIgbGltaXQgb24gaG93DQo+IHF1aWNr
bHkgdGhlIGNvdW50ZXIgY2FuIG92ZXJmbG93LCB3aGljaCBpcyBvbmNlIHBlciBzZWNvbmQuDQo+
IA0KPg0KDQpPSy4gSSdsbCBjaGFuZ2UgdGhpcyB0byAiYXMgcGVyIGhhcmR3YXJlIGZ1bmN0aW9u
YWxpdHkiDQogDQo+ID4gPiA+ICtzdGF0aWMgdm9pZCBfX2ludGVsX2NxbV9ldmVudF90b3RhbF9i
d19jb3VudCh2b2lkICppbmZvKSB7DQo+ID4gPiA+ICsgICBzdHJ1Y3Qgcm1pZF9yZWFkICpyciA9
IGluZm87DQo+ID4gPiA+ICsgICB1NjQgdmFsOw0KPiA+ID4gPiArDQo+ID4gPiA+ICsgICB2YWwg
PSBfX3JtaWRfcmVhZF9tYm0ocnItPnJtaWQsIGZhbHNlKTsNCj4gPiA+ID4gKyAgIGlmICh2YWwg
JiAoUk1JRF9WQUxfRVJST1IgfCBSTUlEX1ZBTF9VTkFWQUlMKSkNCj4gPiA+ID4gKyAgICAgICAg
ICAgcmV0dXJuOw0KPiA+ID4gPiArICAgYXRvbWljNjRfYWRkKHZhbCwgJnJyLT52YWx1ZSk7IH0N
Cj4gPiA+ID4gKw0KPiA+ID4gPiArc3RhdGljIHZvaWQgX19pbnRlbF9jcW1fZXZlbnRfbG9jYWxf
YndfY291bnQodm9pZCAqaW5mbykgew0KPiA+ID4gPiArICAgc3RydWN0IHJtaWRfcmVhZCAqcnIg
PSBpbmZvOw0KPiA+ID4gPiArICAgdTY0IHZhbDsNCj4gPiA+ID4gKw0KPiA+ID4gPiArICAgdmFs
ID0gX19ybWlkX3JlYWRfbWJtKHJyLT5ybWlkLCB0cnVlKTsNCj4gPiA+ID4gKyAgIGlmICh2YWwg
JiAoUk1JRF9WQUxfRVJST1IgfCBSTUlEX1ZBTF9VTkFWQUlMKSkNCj4gPiA+ID4gKyAgICAgICAg
ICAgcmV0dXJuOw0KPiA+ID4gPiArICAgYXRvbWljNjRfYWRkKHZhbCwgJnJyLT52YWx1ZSk7IH0N
Cj4gPiA+DQo+ID4gPiBBbmQgb25jZSBtb3JlOg0KPiA+ID4NCj4gPiA+ICAgIllvdSdyZSByZWFs
bHkgYSBmYW4gb2YgY29weSBhbmQgcGFzdGUuIg0KPiA+ID4NCj4gPg0KPiA+IFRoZXNlIGZ1bmN0
aW9ucyBhcmUgaW52b2tlZCBpbmRpcmVjdGx5LiBUaGV5IHdlcmUgd3JpdHRlbiBrZWVwaW5nDQo+
IGludGVsX2NxbV9ldmVudF9jb3VudCBpbiAgbWluZC4NCj4gPiBJ4oCZbGwgY2hhbmdlIHRoZSBh
cmcgdG8gc3RydWN0ICAgbWJtX3JlYWR7DQo+ID4gICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJ1Y3Qgcm1pZF9yZWFkICpycjsNCj4gPiAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHUzMiBldmVu
dGlkOw0KPiA+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgIH07DQo+ID4gSW50ZWxfY3FtX2V2ZW50XypfYndfY291bnQo4oCmLikgbmVlZHMgZXZlbnRp
ZCB0byBjYWxsIGZvciBkZWNvZGluZw0KPiANCj4gTm8sIHBsZWFzZSBkbyBub3QgZHVwbGljYXRl
IHRoZSBybWlkX3JlYWQgc3RydWN0dXJlLCB0aGF0IGlzIG5vdCBhbg0KPiBpbXByb3ZlbWVudCwg
d2UgZG9uJ3QgbmVlZCB0d28gZGlmZmVyZW50IHN0cnVjdHMgZm9yIHJlYWRpbmcgdGhlIHJlYWQg
ZGF0YS4NCj4gDQo+IFBsZWFzZSBhZGQgdGhlIGV2ZW50IGZpZWxkIHRvIHRoZSBleGlzdGluZyBz
dHJ1Y3Qgcm1pZF9yZWFkLg0KPiANCj4gDQoNCk9LDQoNCg0KPiA+ID4gPiBAQCAtMTAyMyw2ICsx
NDM3LDE3IEBAIHN0YXRpYyB2b2lkIGludGVsX2NxbV9ldmVudF9zdG9wKHN0cnVjdA0KPiA+ID4g
cGVyZl9ldmVudCAqZXZlbnQsIGludCBtb2RlKQ0KPiA+ID4gPiAgICAgIH0gZWxzZSB7DQo+ID4g
PiA+ICAgICAgICAgICAgICBXQVJOX09OX09OQ0UoIXN0YXRlLT5ybWlkKTsNCj4gPiA+ID4gICAg
ICB9DQo+ID4gPiA+ICsNCj4gPiA+ID4gKyAgIGlmIChwbXUpIHsNCj4gPiA+ID4gKyAgICAgICAg
ICAgaWYgKHBtdS0+bl9hY3RpdmUgPiAgMCkgew0KPiA+ID4NCj4gPiA+IFdoYXQncyB0aGUgcHVy
cG9zZSBvZiB0aGlzIGNoZWNrPyBJbiB0aGUgcHJldmlvdXMgdmVyc2lvbiB0aGVyZSB3YXMNCj4g
PiA+IGEgV0FSTl9PTigpLCB3aGljaCBtYWRlIHNlbnNlLiBEaWQgaXQgdHJpZ2dlciBhbmQgeW91
IGRlY2lkZWQgdG8gIndvcmsiDQo+ID4gPiBhcm91bmQgaXQ/DQo+ID4gPg0KPiA+DQo+ID4gV2Ug
YWN0dWFsbHkgbWVhbnQgdG8gY2hlY2sgaWYgdGhlcmUgYXJlIGFjdGl2ZSBldmVudHMNCj4gDQo+
IEkgZG9uJ3QgZm9sbG93IHRoaXMgYW5zd2VyLiBBcmUgeW91IHNheWluZyB0aGF0IHRoZSBXQVJO
X09OKCkgZG9lc24ndCBtYWtlDQo+IHNlbnNlIGhlcmU/DQo+IA0KPiANCj4gDQpJIGNhbiBhZGQg
IFdBUk5fT04uIEJ1dCB0aGlzICB3aWxsIGFsd2F5cyBoaXQgaWYgdGhlcmUgYXJlIG5vIGV2ZW50
cy4gDQo+ID4NCj4gPiA+ID4gK0VWRU5UX0FUVFJfU1RSKGxsY190b3RhbF9idy51bml0LCBpbnRl
bF9jcW1fbGxjX3RvdGFsX2J3X3VuaXQsDQo+ID4gPiA+ICsiS0Ivc2VjIik7IEVWRU5UX0FUVFJf
U1RSKGxsY19sb2NhbF9idy51bml0LA0KPiA+ID4gPiAraW50ZWxfY3FtX2xsY19sb2NhbF9id191
bml0LCAiS0Ivc2VjIik7ICNlbmRpZg0KPiA+ID4NCj4gPiA+ID4gK3N0YXRpYyBzc2l6ZV90DQo+
ID4gPiA+ICtzbGlkaW5nX3dpbmRvd19zaXplX3N0b3JlKHN0cnVjdCBkZXZpY2UgKmRldiwNCj4g
PiA+ID4gKyAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICphdHRy
LA0KPiA+ID4gPiArICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2hhciAqYnVmLCBzaXplX3Qg
Y291bnQpIHsNCj4gPiA+ID4gKyAgIHVuc2lnbmVkIGludCBieXRlczsNCj4gPiA+ID4gKyAgIGlu
dCByZXQ7DQo+ID4gPiA+ICsNCj4gPiA+ID4gKyAgIHJldCA9IGtzdHJ0b3VpbnQoYnVmLCAwLCAm
Ynl0ZXMpOw0KPiA+ID4gPiArICAgaWYgKHJldCkNCj4gPiA+ID4gKyAgICAgICAgICAgcmV0dXJu
IHJldDsNCj4gPiA+ID4gKw0KPiA+ID4gPiArICAgbXV0ZXhfbG9jaygmY2FjaGVfbXV0ZXgpOw0K
PiA+ID4gPiArICAgaWYgKGJ5dGVzID4gMCAmJiBieXRlcyA8PSBNQk1fRklGT19TSVpFX01BWCkN
Cj4gPiA+ID4gKyAgICAgICAgICAgbWJtX3dpbmRvd19zaXplID0gYnl0ZXM7DQo+ID4gPg0KPiA+
ID4gU28sIGl0J3MgdmFsaWQgdG8gc2V0IHRoZSB3aW5kb3cgdG8gWCB3aGVyZSAwIDwgWCA8IE1C
TV9GSUZPX1NJWkVfTUlOLg0KPiA+ID4gV2hhdCdzIHRoZSBhY3R1YWwgcHVycG9zZSBvZiBNQk1f
RklGT19TSVpFX01JTj8NCj4gPiA+DQo+ID4gVGhpcyBpcyBjaGFuZ2VkIHRvDQo+ID4gaWYgKGJ5
dGVzID49IE1CTV9GSUZPX1NJWkVfTUlOICYmIGJ5dGVzIDw9IE1CTV9GSUZPX1NJWkVfTUFYKQ0K
PiA+ICAgICAgICAgICAgICAgICBtYm1fd2luZG93X3NpemUgPSBieXRlczsNCj4gDQo+IE5vdGUg
dGhhdCBpZiB0aGUgdXNlciBwYXNzZXMgYSB2YWx1ZSBvdXRzaWRlIG9mIHRoaXMgcmFuZ2UgeW91
IHNob3VsZCBiZSByZXR1cm5pbmcNCj4gLUVJTlZBTCB0byBpbmRpY2F0ZSB0aGF0Lg0KPiANCj4g
DQpPSw0KPiA+ID4gPiArICAgICAgICAgICBwbXUtPnRpbWVyX2ludGVydmFsID0gbXNfdG9fa3Rp
bWUoTUJNX1RJTUVfREVMVEFfTUFYKTsNCj4gPiA+ID4gKyAgICAgICAgICAgcGVyX2NwdShtYm1f
cG11LCBjcHUpID0gcG11Ow0KPiA+ID4gPiArICAgICAgICAgICBwZXJfY3B1KG1ibV9wbXVfdG9f
ZnJlZSwgY3B1KSA9IE5VTEw7DQo+ID4gPg0KPiA+ID4gV2hhdCdzIHRoZSBwb2ludCBvZiB0aGlz
PyBJZiB0aGVyZSBpcyBzdGlsbCBzb21ldGhpbmcgdG8gYmUgZnJlZSdkIGl0cyBsZWFrZWQuDQo+
ID4gPiBPdGhlcndpc2UgdGhhdCdzIHJlZHVuZGFudC4NCj4gPiBwZXJfY3B1KG1ibV9wbXVfdG9f
ZnJlZSwgY3B1KSA9IE5VTEw7IGlzIHJlbW92ZWQNCj4gPg0KPiA+ID4gPiArICAgICAgICAgICBt
Ym1faHJ0aW1lcl9pbml0KHBtdSk7DQo+ID4gPiA+ICsgICB9DQo+ID4gPiA+ICsgICByZXR1cm4g
MDsNCj4gPiA+DQo+ID4gPiBzLzAvTk9USUZZX09LLyBiZWNhdXNlIHlvdSByZXR1cm4gdGhhdCB2
YWx1ZSBkaXJlY3RseS4NCj4gPiA+DQo+ID4gWW91IG1lYW4gSSByZXR1cm4gdGhlIOKAmHJldHVy
biBjb2Rl4oCZDQo+IA0KPiA/DQo+IA0KPiBZb3Ugc2hvdWxkIGJlIHVzaW5nIE5PVElGWV9PSyBo
ZXJlIHNvIHRoYXQgeW91IGZvbGxvdyB0aGUgbm90aWZpZXIgQVBJDQo+IGNvbnZlbnRpb24uDQo+
IA0KT0sNCg0K
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1222215

FromMatt Fleming <matt.fleming@intel.com>
Date2015-09-10 16:00 +0200
Message-ID<q7aym-3dh-23@gated-at.bofh.it>
In reply to#1221000
On Tue, 2015-09-08 at 18:06 +0100, Juvva, Kanaka D wrote:
> 
> There are two aspects:
> 
>  1) Programming MSRs
>  2) EVENT_ATTR_STR(llc_local_bw, intel_cqm_llc_local_bw, "event=0x04");
> 
>  1 is used for programming MSRs
>  2 event attribute for perf
>   
> 
>  For MBM_LOCAL_EVENT HW ID is 0x3. We don't want to use 0x3 for EVENT ATTR. 
> 
> If we use 0x3 for event_attribute
> 
> We can't clearly distinguish whether is EVENT 01 & EVENT 02 or EVENT 03 alone.
>  For perf event attribute  it has to be 0x04. Because 0x01 and 0x02 are used for other two events

You cannot combine events like this, the perf events are not a bitmask
so having MBM_LOCAL_EVENT_ID as 0x3 is fine.

Just look at the Intel RAPL code, it does the same thing. 0x3 is a
perfectly valid perf event attr value and it does not mean "combine perf
event attr 0x1 and 0x2".

If you're concerned about QOS_EVENT_MASK, you can probably just delete
that and replace the code that uses it with a switch statement or
equivalent.

> > > Explained in the comment. If mbm_read is called within in 100ms for
> > > the same rmid, we don’t have to process the sample.
> > 
> > The key piece of information you're missing here is that skipping these small
> > deltas is an optimization, because we avoid performing costly operations for
> > what would likely be a very minor change in the MBM data, right?
> > 
> > 
> 
> Yes, You are correct.

OK, thanks. Please include that point in your comment.


> 
> > >         } else {
> > >                 mbm_current = &mbm_total[vrmid];
> > >                 eventid     = QOS_MBM_TOTAL_EVENT_ID;
> > >         }
> > >         rmid = tmp32;
> > 
> > Why did you assign rmid to vrmid if you reassign it before it was used?
> > 
> > 
> 
> For MSR writes we use rmid value and for mbm_* arrary we use vrmid which is actual
> index.

What I'm saying is that the assignment rmid = vrmid looks unnecessary in
this piece of code.

> > 
> > I suspect the document you're referring to above is only available under NDA,
> > which makes it unsuitable for mention in the kernel source since a large number
> > of people won't have access to it.
> > 
> > Just explain that the way the hardware is designed puts an upper limit on how
> > quickly the counter can overflow, which is once per second.
> > 
> >
> 
> OK. I'll change this to "as per hardware functionality"

I don't think that provides enough detail. Instead, how about "The
hardware architectures assure us that the counter will overflow at most
once a second", because that at least tells us where this assertion came
from.
  
> > > > > @@ -1023,6 +1437,17 @@ static void intel_cqm_event_stop(struct
> > > > perf_event *event, int mode)
> > > > >      } else {
> > > > >              WARN_ON_ONCE(!state->rmid);
> > > > >      }
> > > > > +
> > > > > +   if (pmu) {
> > > > > +           if (pmu->n_active >  0) {
> > > >
> > > > What's the purpose of this check? In the previous version there was
> > > > a WARN_ON(), which made sense. Did it trigger and you decided to "work"
> > > > around it?
> > > >
> > >
> > > We actually meant to check if there are active events
> > 
> > I don't follow this answer. Are you saying that the WARN_ON() doesn't make
> > sense here?
> > 
> > 
> > 
> I can add  WARN_ON. But this  will always hit if there are no events. 

OK, it sounds like the original WARN_ON() didn't make any sense. In
which case you don't need to re-add it.


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1222398

FromKanaka Juvva <kanaka.d.juvva@intel.com>
Date2015-09-10 23:20 +0200
Message-ID<q7hqa-529-11@gated-at.bofh.it>
In reply to#1222215
On Thu, 2015-09-10 at 14:58 +0100, Matt Fleming wrote:
> On Tue, 2015-09-08 at 18:06 +0100, Juvva, Kanaka D wrote:
> > 
> > There are two aspects:
> > 
> >  1) Programming MSRs
> >  2) EVENT_ATTR_STR(llc_local_bw, intel_cqm_llc_local_bw, "event=0x04");
> > 
> >  1 is used for programming MSRs
> >  2 event attribute for perf
> >   
> > 
> >  For MBM_LOCAL_EVENT HW ID is 0x3. We don't want to use 0x3 for EVENT ATTR. 
> > 
> > If we use 0x3 for event_attribute
> > 
> > We can't clearly distinguish whether is EVENT 01 & EVENT 02 or EVENT 03 alone.
> >  For perf event attribute  it has to be 0x04. Because 0x01 and 0x02 are used for other two events
> 
> You cannot combine events like this, the perf events are not a bitmask
> so having MBM_LOCAL_EVENT_ID as 0x3 is fine.
> 
> Just look at the Intel RAPL code, it does the same thing. 0x3 is a
> perfectly valid perf event attr value and it does not mean "combine perf
> event attr 0x1 and 0x2".
> 
> If you're concerned about QOS_EVENT_MASK, you can probably just delete
> that and replace the code that uses it with a switch statement or
> equivalent.
> 
OK. QOS_EVENT_MASK can't be applied. Code changes will be done as per
this.
> > > > Explained in the comment. If mbm_read is called within in 100ms for
> > > > the same rmid, we don’t have to process the sample.
> > > 
> > > The key piece of information you're missing here is that skipping these small
> > > deltas is an optimization, because we avoid performing costly operations for
> > > what would likely be a very minor change in the MBM data, right?
> > > 
> > > 
> > 
> > Yes, You are correct.
> 
> OK, thanks. Please include that point in your comment.
> 
> 

OK

> > 
> > > >         } else {
> > > >                 mbm_current = &mbm_total[vrmid];
> > > >                 eventid     = QOS_MBM_TOTAL_EVENT_ID;
> > > >         }
> > > >         rmid = tmp32;
> > > 
> > > Why did you assign rmid to vrmid if you reassign it before it was used?
> > > 
> > > 
> > 
> > For MSR writes we use rmid value and for mbm_* arrary we use vrmid which is actual
> > index.
> 
> What I'm saying is that the assignment rmid = vrmid looks unnecessary in
> this piece of code.
> 

From my previous review:

  "This is completely backwards.
 
        tmp32 = rmid;  
        rmid = vrmid;
        do_stuff(rmid);
        rmid = tmp32;
        do_other_stuff(rmid);

   Why can't you use vrmid for do_stuff() and leave rmid alone? Just
   because it would make the code simpler to read?"

I have included Thomas comment inline above.

and also I meant the following logic:

writemsr(..,rmid,...)
mbm_*[vrmid]  

So new patch will use this logic.

> > > 
> > > I suspect the document you're referring to above is only available under NDA,
> > > which makes it unsuitable for mention in the kernel source since a large number
> > > of people won't have access to it.
> > > 
> > > Just explain that the way the hardware is designed puts an upper limit on how
> > > quickly the counter can overflow, which is once per second.
> > > 
> > >
> > 
> > OK. I'll change this to "as per hardware functionality"
> 
> I don't think that provides enough detail. Instead, how about "The
> hardware architectures assure us that the counter will overflow at most
> once a second", because that at least tells us where this assertion came
> from.
>   
OK
> > > > > > @@ -1023,6 +1437,17 @@ static void intel_cqm_event_stop(struct
> > > > > perf_event *event, int mode)
> > > > > >      } else {
> > > > > >              WARN_ON_ONCE(!state->rmid);
> > > > > >      }
> > > > > > +
> > > > > > +   if (pmu) {
> > > > > > +           if (pmu->n_active >  0) {
> > > > >
> > > > > What's the purpose of this check? In the previous version there was
> > > > > a WARN_ON(), which made sense. Did it trigger and you decided to "work"
> > > > > around it?
> > > > >
> > > >
> > > > We actually meant to check if there are active events
> > > 
> > > I don't follow this answer. Are you saying that the WARN_ON() doesn't make
> > > sense here?
> > > 
> > > 
> > > 
> > I can add  WARN_ON. But this  will always hit if there are no events. 
> 
> OK, it sounds like the original WARN_ON() didn't make any sense. In
> which case you don't need to re-add it.
> 
> 
OK, WARN_ON I used for debugging.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1223106

FromMatt Fleming <matt@codeblueprint.co.uk>
Date2015-09-11 23:20 +0200
Message-ID<q7DTJ-57T-21@gated-at.bofh.it>
In reply to#1222398
On Thu, 10 Sep, at 02:18:49PM, Kanaka Juvva wrote:
> > > 
> > > > >         } else {
> > > > >                 mbm_current = &mbm_total[vrmid];
> > > > >                 eventid     = QOS_MBM_TOTAL_EVENT_ID;
> > > > >         }
> > > > >         rmid = tmp32;
> > > > 
> > > > Why did you assign rmid to vrmid if you reassign it before it was used?
> > > > 
> > > > 
> > > 
> > > For MSR writes we use rmid value and for mbm_* arrary we use vrmid which is actual
> > > index.
> > 
> > What I'm saying is that the assignment rmid = vrmid looks unnecessary in
> > this piece of code.
> > 
> 
> From my previous review:
> 
>   "This is completely backwards.
>  
>         tmp32 = rmid;  
>         rmid = vrmid;
>         do_stuff(rmid);
>         rmid = tmp32;
>         do_other_stuff(rmid);
> 
>    Why can't you use vrmid for do_stuff() and leave rmid alone? Just
>    because it would make the code simpler to read?"
> 
> I have included Thomas comment inline above.
> 
> and also I meant the following logic:
> 
> writemsr(..,rmid,...)
> mbm_*[vrmid]  
> 
> So new patch will use this logic.
 
OK, let's pull the code in and discuss this with some context,

	u64 val, currentmsr, currentbw, diff_time, cma, bytes, index;                                                                                                                      
        bool overflow = false, first = false;
        ktime_t cur_time;
        u32 tmp32 = rmid, eventid;
        struct sample *mbm_current;
        u32 vrmid = rmid_2_index(rmid);
 
        rmid = vrmid;			<--------- This looks wrong
        cur_time = ktime_get();
        if (read_mbm_local) {
                mbm_current = &mbm_local[vrmid];
                eventid     =  QOS_MBM_LOCAL_EVENT_ID_HW;
                wrmsr(MSR_IA32_QM_EVTSEL, QOS_MBM_LOCAL_EVENT_ID_HW, rmid);	<---- Unneccesary because..
        } else {
                mbm_current = &mbm_total[vrmid];
                eventid     = QOS_MBM_TOTAL_EVENT_ID;
        }
        rmid = tmp32;
        wrmsr(MSR_IA32_QM_EVTSEL, eventid, rmid);	<----- ... you write here
 
So you don't actually use 'rmid' within that if/else block. You can
probably get away with deleting 'tmp32' now that you've refactored
things.

-- 
Matt Fleming, Intel Open Source Technology Center
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1221057 — Re: [PATCH v3 1/2] perf, x86: add Intel Memory Bandwidth Monitoring (MBM) PMU

Fromkanaka.d.juvva@linux.intel.com
Date2015-09-08 22:00 +0200
SubjectRe: [PATCH v3 1/2] perf, x86: add Intel Memory Bandwidth Monitoring (MBM) PMU
Message-ID<q6xdE-5Kp-3@gated-at.bofh.it>
In reply to#1220719
Hi All,

   I have switched to Linux based email client (SquirrelMail) right now.
If required I'll resend the emails I just sent now. Sorry about the
repetition.
We have some of our team members planning for travel. I was in a rush.

Regards,
-Kanaka

> On Mon, 2015-09-07 at 20:22 +0100, Juvva, Kanaka D wrote:
>> Hi Thomas,
>>
>>    I'm sending updated patch(s). I have given details for each of
>> these items below.
>>
>
> Kanaka, this email is HTML formatted and so has been blocked by
> vger.kernel.org where the linux-kernel mailing list is hosted.
>
> Please configure outlook not to send html email, or use a different mail
> agent for working with upstream.
>
>> Regards,
>> -Kanaka
>>
>> > -----Original Message-----
>> > From: Thomas Gleixner [mailto:tglx@linutronix.de]
>> > Sent: Wednesday, August 19, 2015 1:50 PM
>> > To: Kanaka Juvva
>> > Cc: Juvva, Kanaka D; Williamson, Glenn P; Fleming, Matt; Auld, Will;
>> Andi Kleen;
>> > LKML; Luck, Tony; Peter Zijlstra; Tejun Heo; x86@kernel.org; Ingo
>> Molnar; H.
>> > Peter Anvin; Shivappa, Vikas
>> > Subject: Re: [PATCH v3 1/2] perf,x86: add Intel Memory Bandwidth
>> Monitoring
>> > (MBM) PMU
>> >
>> > On Fri, 7 Aug 2015, Kanaka Juvva wrote:
>> > > +#define MBM_CNTR_MAX               0xffffff
>> > > +#define MBM_SOCKET_MAX             8
>> > > +#define MBM_TIME_DELTA_MAX 1000
>> > > +#define MBM_TIME_DELTA_MIN 100
>> >
>> > What are these constants for and how are they determined? Pulled out
>> of thin
>> > air?
>> >
>>
>> /*
>> * MBM Counter is 24bits wide. MBM_CNTR_MAX defines max counter
>> * value
>> */
>> #define MBM_CNTR_MAX            0xffffff
>> /*
>> * Max #sockets supported
>> */
>> #define MBM_SOCKET_MAX          8
>
> This seems like a constant we could get by without. Do we really need to
> know this at compile time?
>
>> /*
>> * Expected time interval between consecutive MSR reads for a given rmid
>> */
>> #define MBM_TIME_DELTA_MAX      1000
>
> "max" and "expected" are not the same thing.
>
>
>> > >  #define QOS_L3_OCCUP_EVENT_ID      (1 << 0)
>> > > +#define QOS_MBM_TOTAL_EVENT_ID     (1 << 1)
>> > > +#define QOS_MBM_LOCAL_EVENT_ID_HW   0x3
>> > > +#define QOS_MBM_LOCAL_EVENT_ID     (1 << 2)
>> >
>> > So we have ID values which are built with (1 << X) and then this HW
>> variant in the
>> > middle with 0x3. Of course without any explanation what the heck this
>> stuff is.
>> >
>> > Last review:
>> >
>> >      "So this wants a descriptive ID name and a comment."
>> >
>> >
>>
>> /*
>> * MBM Event IDs as defined in SDM section 17.14.6
>> * Event IDs used to program MSRs for reading counters
>> */
>> #define QOS_MBM_TOTAL_EVENT_ID  (1 << 1)
>> #define QOS_MBM_LOCAL_EVENT_ID_HW        0x3
>> /*
>> * Perf needs event id to be 1 << x, hence we can't use 0x3 (HW EVENT ID)
>> * for MBM_LOCAL_EVENT we use next 1 << x for MBM_LOCAL_EVENT_ID
>> */
>> #define QOS_MBM_LOCAL_EVENT_ID  (1 << 2)
>
> No, perf events do not need to be of the form (1 << X), that was just a
> convention we used in the cqm code before we knew what values the MBM
> events would take - you can change these to be whatever format you want,
> but be sure to make it consistent.
>
> The constants are very much supposed to be programmed into the MSRs,
> take a look at __rmid_read().
>
> I would suggest (as I already did privately) that you change the format
> to be 0x0x for all of these event IDs.
>
>
>> > > @@ static bool intel_cqm_sched_in_event(u32 rmid)
>> > >      return false;
>> > >  }
>> > >
>> > > +
>> > > +static u32 bw_sum_calc(struct sample *bw_stat, int rmid) {
>> > > +   u32 val = 0, i, j, index;
>> > > +
>> > > +   if (++bw_stat->fifoout >=  mbm_window_size)
>> > > +           bw_stat->fifoout =  0;
>> > > +   index =  bw_stat->fifoout;
>> > > +   for (i = 0; i < mbm_window_size - 1; i++) {
>> > > +           if (index + i >= mbm_window_size)
>> > > +                   j = index + i - mbm_window_size;
>> > > +           else
>> > > +                   j = index + i;
>> > > +           val += bw_stat->mbmfifo[j];
>> > > +   }
>> >
>> > This math wants a explanatory comment.
>> >
>> /*
>> * Slide the window by 1 and calculate the sum of the last
>> * mbm_window_size-1  bandwidth  values.
>> * fifoout is the current position of the window.
>> * Increment the fifoout by 1 to slide the window by 1.
>> *
>> * Calcalute the bandwidth from ++fifiout  to ( ++fifoout +
>> mbm_window_size -1)
>> * e.g.fifoout =1;   Bandwidth1 Bandwidth2 ..... Bandwidthn are the
>> * sliding window values where n is size of the sliding window
>> *  bandwidth sum:  val  =  Bandwidth2 + Bandwidth3 + .. Bandwidthn
>> */
>
> Instead of these large comment blocks please comment smaller,
> logically-connected chunks of code, e.g.
>
> 	/* Slide the window by one */
> 	if (++bw_stat->fifoout >= mbm_window_size)
> 		bw_stat->fifoout = 0;
>
> 	/*
> 	 * Calculate the sum of last mbm_window_size-1 values.
> 	 */
> 	for (i = 0; i < mbm_window_size - 1; i++) {
> 		/* Handle wraparound at end of window */
> 		if (index + i >= mbm_window_size)
> 			j = index + i - mbm_window_size;
> 		else
> 			j = index + i;
>
> 		val += bw_stat->mbminfo[j];
> 	}
>
>>
>>
>> > > +   return val;
>> > > +}
>> > > +
>> > > +static u32 __mbm_fifo_sum_lastn_out(int rmid, bool is_localbw) {
>> > > +   if (is_localbw)
>> > > +           return bw_sum_calc(&mbm_local[rmid], rmid);
>> > > +   else
>> > > +           return bw_sum_calc(&mbm_total[rmid], rmid); }
>> > > +
>> > > +static void __mbm_fifo_in(struct sample *bw_stat, u32 val) {
>> > > +   bw_stat->mbmfifo[bw_stat->fifoin] = val;
>> > > +   if (++bw_stat->fifoin >= mbm_window_size)
>> >
>> > How does that become greater than mbm_windowsize?
>> >
>>
>> This is fixed by changing >= to ==
>> Added a comment:
>>
>> /*
>> * store current sample's bw value in sliding window at the
>> * index fifoin. Increment fifoin. Check if fifoin has reached
>> * max_window_size. If yes reset it to begining i.e. zero
>> * e.g.
>> * mbm_window_size = 10
>> * mbmfifo is a circular fifo   0 1 2 3 4 5 6 7 8 9 10
>> *                                          ^
>>   |
>> *                                               |
>>        |
>> *                                                | _ _ _ _ _ _ _ _ _ _|
>> *
>> * So when fifoin becomes 10, then it is reset to zero
>> *
>> */
>
> I'm not sure that this comment adds anything of value that isn't already
> understood by reading the code. I don't think you need a comment for
> this function, it seems pretty straight forward and Thomas' question was
> about the boundary limits of ->fifoin.
>
>> > > +           bw_stat->fifoin = 0;
>> > > +}
>> >
>> > > +/*
>> > > + * __rmid_read_mbm checks whether it is LOCAL or GLOBAL MBM event
>> and
>> > > +reads
>> > > + * its MSR counter. Check whether overflow occurred and handles it.
>> > > +Calculates
>> > > + * currenet  BW and updates  running average.
>> >
>> > currenet? And please get rid of the double spaces
>> >
>> This is fixed now.  Here is the updated comment:
>>
>> /*
>> * rmid_read_mbm checks whether it is LOCAL or Total MBM event and reads
>> * its MSR counter. Check whether overflow occured and handles it.
>> Calculates
>> * currenet  BW and updates  running average.
>> *
>
> ^^^ You've still misspelled current.
>>
>> * Overflow Handling:
>> * if (MSR current value < MSR previous value) it is an
>> * overflow. MSR values are increasing when bandwidth consumption for the
>> thread
>> * is non-zero; When MSR values reaches MAX_COUNTER_VALUE it overflows.
>> After overflow,
>> * MSR current value goes back to zero and starts increasing again at the
>> rate of
>> * bandwidth.
>> *
>
> You don't need to provide a definition of "overflow", most people will
> be familiar with it. What is more important to document is how the
> overflow is handled...
>>
>> * Overflow handling:
>> * Detect an overflow :  current read value > last read value
>
> Isn't this inverted? Overflow occurred if current < previous.
>
>>
>> * Overflow correction:  if (overflow)
>> *                          Current value = (MAX_COUNTER_VALUE - prev
>> read value) + current read value
>> *                       else
>> *                          Current value = current read value
>> *
>
> Please don't write pseudocode in the comments. Use English prose to
> describe the important parts of the code.
>
>>
>> * Calculation of Current Bandwidth value:
>> * If MSR is read within last 100ms, then then the smaple is ignored;
>> * If the MSR was Read with in last 100ms, why  incur an extra overhead
>> * of doing the MSR reads again. Anyway there'll be a negligible change
>> or zero
>> * change in MSR readings in 100ms.
>> *
>> * Bandwidth is calculated as:
>> * memory bandwidth = difference of last two msr counter values/time
>> difference.
>> *
>> * cum_avg = Running Average bandwidth of last 'n' bandwidth values for
>> * the samples that are processed
>> *
>
> Where 'n' is 'mbm_window_size' ? If so, please use 'mbm_window_size',
> not 'n'.
>>
>> * Sliding window is used to save the last 'n' samples. Where,
>> * n = sliding_window_size and results in sliding window duration of 'n'
>> secs.
>
> Hmm... this confuses me a lot. Is 'n' a size or a duration? The two are
> not the same thing.
>
>>
>> * The sliding window size by default set to
>> * MBM_FIFO_SIZE_MIN. User can configure it to the values in the range
>> * (MBM_FIFO_SIZE_MIN,MBM_FIFO_SIZE_MAX). The range for sliding window
>> * is chosen based on a general criteria for monitoring duration. Example
>> * for a short lived application, 10sec monitoring period gives
>> * good characterization of its bandwidth consumption. For an application
>> * that runs for longer duration, 300sec monitoring period gives better
>> * characterization of its bandwidth consumption. Since the running
>> average
>> * calculated for total monitoring period, user gets the most accuracate
>> * average bandwidth for the each monitoring period.
>> *
>> * Scaling:
>> * cum_avg is the raw bandwidth is Bytes/sec.
>> * cum_avg is converted to MB/sec by applying  MBM_CONVERSION_FACTOR and
>> * rounded to nearest integer. User interface gets the Bandwidth values
>> in MB/sec.
>> *
>> */
>> > > + *
>> > > + * Overflow Handling:
>> > > + * if (MSR current value < MSR previous value) it is an
>> > > + * overflow. and overflow is handled.
>> >
>> > Wow. That's informative as hell!
>> >
>> Please look at the modified comment above
>> > > + *
>> > > + * Calculation of Current BW value:
>> >
>> > BW == Body Weight?
>> >
>>
>> It is fixed now
>>
>> > > + * If MSR is read within last 100ms, then the value is ignored;
>> > > + * this will suppress small deltas. We don't process MBM samples
>> that
>> > > + are
>> > > + * within 100ms.
>> >
>> > WHY?
>> >
>> Explained in the comment. If mbm_read is called within in 100ms for the
>> same rmid, we don’t
>> have to process the sample.
>
> The key piece of information you're missing here is that skipping these
> small deltas is an optimization, because we avoid performing costly
> operations for what would likely be a very minor change in the MBM data,
> right?
>
>
>> > > +{
>> > > +   u64 val, tmp, diff_time, cma, bytes, index;
>> > > +   bool overflow = false, first = false;
>> > > +   ktime_t cur_time;
>> > > +   u32 tmp32 = rmid;
>> > > +   struct sample *mbm_current;
>> > > +   u32 vrmid = topology_physical_package_id(smp_processor_id()) *
>> > > +                                            cqm_max_rmid + rmid;
>> > > +
>> > > +   rmid = vrmid;
>> >
>> > From my previous review:
>> >
>> >   "This is completely backwards.
>> >
>> >        tmp32 = rmid;
>> >        rmid = vrmid;
>> >        do_stuff(rmid);
>> >        rmid = tmp32;
>> >        do_other_stuff(rmid);
>> >
>> >    Why can't you use vrmid for do_stuff() and leave rmid alone? Just
>> >    because it would make the code simpler to read?"
>> >
>> > Still applies.
>> >
>>
>> This is now changed to
>> u64 val, currentmsr, currentbw, diff_time, cma, bytes, index;
>>         bool overflow = false, first = false;
>>         ktime_t cur_time;
>>         u32 tmp32 = rmid, eventid;
>>         struct sample *mbm_current;
>>         u32 vrmid = rmid_2_index(rmid);
>>
>>         rmid = vrmid;
>>         cur_time = ktime_get();
>>         if (read_mbm_local) {
>>                 mbm_current = &mbm_local[vrmid];
>>                 eventid     =  QOS_MBM_LOCAL_EVENT_ID_HW;
>>                 wrmsr(MSR_IA32_QM_EVTSEL, QOS_MBM_LOCAL_EVENT_ID_HW,
>> rmid);
>
> You don't need to perform this wrmsr() here because it's taken care of
> in the common code below.
>
>>         } else {
>>                 mbm_current = &mbm_total[vrmid];
>>                 eventid     = QOS_MBM_TOTAL_EVENT_ID;
>>         }
>>         rmid = tmp32;
>
> Why did you assign rmid to vrmid if you reassign it before it was used?
>
>
>> > > +   /* if current msr value <  previous msr value ,  it means
>> overflow */
>> > > +   if (val < bytes) {
>> > > +           val = MBM_CNTR_MAX - bytes + val;
>> > > +           overflow = true;
>> > > +   } else
>> > > +           val = val - bytes;
>> > > +
>> > > +   val =  (val * MBM_TIME_DELTA_MAX) / diff_time;
>> > > +
>> > > +   if ((diff_time > MBM_TIME_DELTA_MAX) && (!cma))
>> > > +           /* First sample */
>> > > +           first = true;
>> > > +
>> > > +   rmid = vrmid;
>> >
>> > And another time:
>> >
>> >   "More obfuscation"
>> >
>>
>>        /*
>>          * MBM_TIME_DELTA_MAX is picked as per MBM specs. As specified
>> in Intel Platform
>>          * Quality of Service Monitoring Implementer's Guide V1, Section
>> 2.7.2. page 21,
>>          * overflow can occur maximum once in a second. So latest we
>> want to read the MSR
>>          * counters is 1000ms. If it is less than 1000ms we can  ignore
>> the sample. Then we
>>          * decide since when we should ignore. If the MSR was Read with
>> in last 100ms, why
>>          * process the MSR reads again. Anyway there'll be small change
>> or zero change.
>>          * So ignoring MSR Reads within 100ms or less is efficient.
>> MBM_TIME_DELTA_MIN
>>          * is specified as 100ms as per this guideline.
>>          *
>>          */
>
> I suspect the document you're referring to above is only available under
> NDA, which makes it unsuitable for mention in the kernel source since a
> large number of people won't have access to it.
>
> Just explain that the way the hardware is designed puts an upper limit
> on how quickly the counter can overflow, which is once per second.
>
>
>> > > +static void __intel_cqm_event_total_bw_count(void *info) {
>> > > +   struct rmid_read *rr = info;
>> > > +   u64 val;
>> > > +
>> > > +   val = __rmid_read_mbm(rr->rmid, false);
>> > > +   if (val & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL))
>> > > +           return;
>> > > +   atomic64_add(val, &rr->value);
>> > > +}
>> > > +
>> > > +static void __intel_cqm_event_local_bw_count(void *info) {
>> > > +   struct rmid_read *rr = info;
>> > > +   u64 val;
>> > > +
>> > > +   val = __rmid_read_mbm(rr->rmid, true);
>> > > +   if (val & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL))
>> > > +           return;
>> > > +   atomic64_add(val, &rr->value);
>> > > +}
>> >
>> > And once more:
>> >
>> >   "You're really a fan of copy and paste."
>> >
>>
>> These functions are invoked indirectly. They were written keeping
>> intel_cqm_event_count in  mind.
>> I’ll change the arg to struct   mbm_read{
>>                                                      struct rmid_read
>> *rr;
>>                                                      u32 eventid;
>>                                                    };
>> Intel_cqm_event_*_bw_count(….) needs eventid to call for decoding
>
> No, please do not duplicate the rmid_read structure, that is not an
> improvement, we don't need two different structs for reading the read
> data.
>
> Please add the event field to the existing struct rmid_read.
>
>
>> > > @@ -1023,6 +1437,17 @@ static void intel_cqm_event_stop(struct
>> > perf_event *event, int mode)
>> > >      } else {
>> > >              WARN_ON_ONCE(!state->rmid);
>> > >      }
>> > > +
>> > > +   if (pmu) {
>> > > +           if (pmu->n_active >  0) {
>> >
>> > What's the purpose of this check? In the previous version there was a
>> > WARN_ON(), which made sense. Did it trigger and you decided to "work"
>> > around it?
>> >
>>
>> We actually meant to check if there are active events
>
> I don't follow this answer. Are you saying that the WARN_ON() doesn't
> make sense here?
>
>
>
>>
>> > > +EVENT_ATTR_STR(llc_total_bw.unit, intel_cqm_llc_total_bw_unit,
>> > > +"KB/sec"); EVENT_ATTR_STR(llc_local_bw.unit,
>> > > +intel_cqm_llc_local_bw_unit, "KB/sec"); #endif
>> >
>> > > +static ssize_t
>> > > +sliding_window_size_store(struct device *dev,
>> > > +                     struct device_attribute *attr,
>> > > +                     const char *buf, size_t count)
>> > > +{
>> > > +   unsigned int bytes;
>> > > +   int ret;
>> > > +
>> > > +   ret = kstrtouint(buf, 0, &bytes);
>> > > +   if (ret)
>> > > +           return ret;
>> > > +
>> > > +   mutex_lock(&cache_mutex);
>> > > +   if (bytes > 0 && bytes <= MBM_FIFO_SIZE_MAX)
>> > > +           mbm_window_size = bytes;
>> >
>> > So, it's valid to set the window to X where 0 < X < MBM_FIFO_SIZE_MIN.
>> > What's the actual purpose of MBM_FIFO_SIZE_MIN?
>> >
>> This is changed to
>> if (bytes >= MBM_FIFO_SIZE_MIN && bytes <= MBM_FIFO_SIZE_MAX)
>>                 mbm_window_size = bytes;
>
> Note that if the user passes a value outside of this range you should be
> returning -EINVAL to indicate that.
>
>
>> > > +           pmu->timer_interval = ms_to_ktime(MBM_TIME_DELTA_MAX);
>> > > +           per_cpu(mbm_pmu, cpu) = pmu;
>> > > +           per_cpu(mbm_pmu_to_free, cpu) = NULL;
>> >
>> > What's the point of this? If there is still something to be free'd its
>> leaked.
>> > Otherwise that's redundant.
>> per_cpu(mbm_pmu_to_free, cpu) = NULL; is removed
>>
>> > > +           mbm_hrtimer_init(pmu);
>> > > +   }
>> > > +   return 0;
>> >
>> > s/0/NOTIFY_OK/ because you return that value directly.
>> >
>> You mean I return the ‘return code’
>
> ?
>
> You should be using NOTIFY_OK here so that you follow the notifier API
> convention.
>
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web