lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <alpine.DEB.2.10.1701171050520.16222@vshiva-Udesk>
Date:   Tue, 17 Jan 2017 11:11:38 -0800 (PST)
From:   Shivappa Vikas <vikas.shivappa@...el.com>
To:     Thomas Gleixner <tglx@...utronix.de>
cc:     Vikas Shivappa <vikas.shivappa@...ux.intel.com>,
        vikas.shivappa@...el.com, davidcc@...gle.com, eranian@...gle.com,
        linux-kernel@...r.kernel.org, x86@...nel.org, hpa@...or.com,
        mingo@...nel.org, peterz@...radead.org, ravi.v.shankar@...el.com,
        tony.luck@...el.com, fenghua.yu@...el.com, andi.kleen@...el.com,
        h.peter.anvin@...el.com
Subject: Re: [PATCH 04/12] x86/cqm: Add Per pkg rmid support\



On Mon, 16 Jan 2017, Thomas Gleixner wrote:

> On Fri, 6 Jan 2017, Vikas Shivappa wrote:
>
>> Subject : [PATCH 04/12] x86/cqm: Add Per pkg rmid support
>
> Can you please be a bit more careful about the subject lines. 'Per' wants
> to be 'per' and pkg really can be written as package. There is no point in
> cryptic abbreviations for no value. Finaly RMID wants to be all uppercase
> as you use it in the text below.

Will fix and write more readable names.

>
>> Patch introduces a new cqm_pkgs_data to keep track of the per package
>
> Again. We know that this is a patch.....
>
>> free list, limbo list and other locking structures.
>
> So free list and limbo list are locking structures, interesting.
>
>> The corresponding rmid structures in the perf_event is
>
> s/structures/structure/

Will fix

>
>> changed to hold an array of u32 RMIDs instead of a single u32.
>>
>> The RMIDs are not assigned at the time of event creation and are
>> assigned in lazy mode at the first sched_in time for a task, thereby
>> rmid is never allocated if a task is not scheduled on a package. This
>> helps better usage of RMIDs and its scales with the increasing
>> sockets/packages.
>>
>> Locking:
>> event list - perf init and terminate hold mutex. spin lock is held to
>> gaurd from the mbm hrtimer.
>> per pkg free and limbo list - global spin lock. Used by
>> get_rmid,put_rmid, perf start, terminate
>
> Locking documentation wants to be in the code not in some random changelog.

Will add this to the code where i do the locking.

>
>> Tests: RMIDs available increase by x times where x is number of sockets
>> and the usage is dynamic so we save more.
>
> What means: 'Tests:'? Is there a test in this patch? If yes, I seem to be
> missing it.

Patch does not include a test case. Will add a description of the actual tests. 
Will that work ?

In this case , the test was done as below:

On a dual socket bdw system
For testing , force the max_rmid to x (prefreably less #)
Run x threads which a affinitized to each socket.
-This gives valid data with the per package patch.

>
>> Patch is based on David Carrillo-Cisneros <davidcc@...gle.com> patches
>> in cqm2 series.
>
> We document such attributions with a tag:
>
> Originally-From: David Carrillo-Cisneros <davidcc@...gle.com>
>
> That way tools can pick it up.

Ok , will fix this on all patches rather than the confusing 'based on' in the 
change log on all the patches.

>
>>  static cpumask_t cqm_cpumask;
>>
>> +struct pkg_data **cqm_pkgs_data;
>
> Why is this global? There is no user outside of cqm.c AFAICT.

will fix

>
>> -/*
>> - * We use a simple array of pointers so that we can lookup a struct
>> - * cqm_rmid_entry in O(1). This alleviates the callers of __get_rmid()
>> - * and __put_rmid() from having to worry about dealing with struct
>> - * cqm_rmid_entry - they just deal with rmids, i.e. integers.
>> - *
>> - * Once this array is initialized it is read-only. No locks are required
>> - * to access it.
>> - *
>> - * All entries for all RMIDs can be looked up in the this array at all
>> - * times.
>
> So this comment was actually valuable. Sure, it does not match the new
> implementation, but the basic principle is still the same. The comment
> wants to be updated and not just removed.
>
>>   *
>>   * We expect to be called with cache_mutex held.
>
> You rename cache_mutex to cache lock, but updating the comments is
> optional, right?
>
>> -static u32 __get_rmid(void)
>> +static u32 __get_rmid(int domain)
>
>  unsigned int domain please. The domain cannot be negative.
>
>>  {
>> +	struct list_head *cqm_flist;
>>  	struct cqm_rmid_entry *entry;
>
> Please keep the variables as a reverse fir tree:
>
>>  	struct cqm_rmid_entry *entry;
>> +	struct list_head *cqm_flist;
>
>>
>> -	lockdep_assert_held(&cache_mutex);
>> +	lockdep_assert_held(&cache_lock);
>
>> -static void __put_rmid(u32 rmid)
>> +static void __put_rmid(u32 rmid, int domain)
>>  {
>>  	struct cqm_rmid_entry *entry;
>>
>> -	lockdep_assert_held(&cache_mutex);
>> +	lockdep_assert_held(&cache_lock);
>>
>> -	WARN_ON(!__rmid_valid(rmid));
>> -	entry = __rmid_entry(rmid);
>> +	WARN_ON(!rmid);
>
> What's wrong with __rmid_valid() ?
>
>> +	entry = __rmid_entry(rmid, domain);
>>
>> +	kfree(cqm_pkgs_data);
>>  }
>>
>> +
>
> Random white space noise.
>

Will fix with respect to all comments above

>>  static bool is_cqm_event(int e)
>> @@ -420,10 +349,11 @@ static void __intel_mbm_event_init(void *info)
>>  {
>>  	struct rmid_read *rr = info;
>>
>> -	update_sample(rr->rmid, rr->evt_type, 1);
>> +	if (__rmid_valid(rr->rmid[pkg_id]))
>
> Where the heck is pkg_id coming from?
>
> Ahh:
>
> #define pkg_id  topology_physical_package_id(smp_processor_id())
>
> That's crap. It's existing crap, but nevertheless crap.
>
> First of all it's irritating as 'pkg_id' looks like a variable and in this
> case it would be at least file global, which makes no sense at all.
>
> Secondly, we really want to move this to the logical package id as that is
> actually guaranteing that the package id is smaller than
> topology_max_packages(). The physical package id has no such guarantee.
>
> And then please keep this local so its simple to read and parse:

Ok , this pkg_id was from the mbm patch. Will change this and fix, probably 
have a seperate patch to first change this one as its already used in 
upstream.

>
>    	 unsigned int pkgid = topology_logical_package_id(smp_processor_id());
>
>> +		update_sample(rr->rmid[pkg_id], rr->evt_type, 1);
>>  }
>
>> @@ -444,7 +374,7 @@ static int intel_cqm_setup_event(struct perf_event *event,
>>  				  struct perf_event **group)
>>  {
>>  	struct perf_event *iter;
>> -	u32 rmid;
>> +	u32 *rmid, sizet;
>
> What's wrong with size? It's not confusable with size_t, right?
>
>> +void alloc_needed_pkg_rmid(u32 *cqm_rmid)
>
> Again: Why is this global?
>
> And what's the meaning of needed in the function name? If the RMID wouldn't
> be needed then the function would not be called, right?

THis is related to the other problem you commented a lot that I put 
structures/functions and used them later in a seperate patch (hence compiler 
warnings .. and a whole bunch of such issues ). This i used later -

i will better organize the patches to fix all these.

>
>> +{
>> +	unsigned long flags;
>> +	u32 rmid;
>> +
>> +	if (WARN_ON(!cqm_rmid))
>> +		return;
>> +
>> +	if (cqm_rmid[pkg_id])
>> +		return;
>> +
>> +	raw_spin_lock_irqsave(&cache_lock, flags);
>> +
>> +	rmid = __get_rmid(pkg_id);
>> +	if (__rmid_valid(rmid))
>> +		cqm_rmid[pkg_id] = rmid;
>> +
>> +	raw_spin_unlock_irqrestore(&cache_lock, flags);
>> +}
>> +
>>  static void intel_cqm_event_start(struct perf_event *event, int mode)
>>  {
>>  	struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
>> -	u32 rmid = event->hw.cqm_rmid;
>> +	u32 rmid;
>>
>>  	if (!(event->hw.cqm_state & PERF_HES_STOPPED))
>>  		return;
>>
>>  	event->hw.cqm_state &= ~PERF_HES_STOPPED;
>>
>> +	alloc_needed_pkg_rmid(event->hw.cqm_rmid);
>> +
>> +	rmid = event->hw.cqm_rmid[pkg_id];
>
> The allocation can fail. What's in event->hw.cqm_rmid[pkg_id] then? Zero or
> what? And why is any of those values fine?
>
> Can you please add comments so reviewers and readers do not have to figure
> out every substantial detail themself?

If the allocation fails , it will have zero which is the default. And zero is 
the default RMID for all threads. A later patch indicates this as an error to 
the user if the RMID wasnt available. Will comment this.

>
>>  	state->rmid = rmid;
>>  	wrmsr(MSR_IA32_PQR_ASSOC, rmid, state->closid);
>
>> +static inline void
>> +	cqm_event_free_rmid(struct perf_event *event)
>
> Yet another coding style variant from your unlimited supply of coding
> horrors.
>
>> +{
>> +	u32 *rmid = event->hw.cqm_rmid;
>> +	int d;
>> +
>> +	for (d = 0; d < cqm_socket_max; d++) {
>> +		if (__rmid_valid(rmid[d]))
>> +			__put_rmid(rmid[d], d);
>> +	}
>> +	kfree(event->hw.cqm_rmid);
>> +	list_del(&event->hw.cqm_groups_entry);
>> +}
>>  static void intel_cqm_event_destroy(struct perf_event *event)
>>  {
>>  	struct perf_event *group_other = NULL;
>> @@ -737,16 +693,11 @@ static void intel_cqm_event_destroy(struct perf_event *event)
>>  		 * If there was a group_other, make that leader, otherwise
>>  		 * destroy the group and return the RMID.
>>  		 */
>> -		if (group_other) {
>> +		if (group_other)
>>  			list_replace(&event->hw.cqm_groups_entry,
>>  				     &group_other->hw.cqm_groups_entry);
>
> Please keep the brackets. See:
>
> http://lkml.kernel.org/r/alpine.DEB.2.20.1609101416420.32361@nanos
>
>> -		} else {
>> -			u32 rmid = event->hw.cqm_rmid;
>> -
>> -			if (__rmid_valid(rmid))
>> -				__put_rmid(rmid);
>> -			list_del(&event->hw.cqm_groups_entry);
>> -		}
>> +		else
>> +			cqm_event_free_rmid(event);
>>  	}
>>
>>  	raw_spin_unlock_irqrestore(&cache_lock, flags);
>
>> +static int pkg_data_init_cpu(int cpu)
>
> cpus are unsigned int
>
>> +{
>> +	struct cqm_rmid_entry *ccqm_rmid_ptrs = NULL, *entry = NULL;
>
> What are the pointer intializations for?
>
>> +	int curr_pkgid = topology_physical_package_id(cpu);
>
> Please use logical packages.

Will fix this and all coding style errors pointed.

>
>> +	struct pkg_data *pkg_data = NULL;
>> +	int i = 0, nr_rmids, ret = 0;
>
> Crap. 'i' is used in the for() loop below and therefor initialized exactly
> there and not at some random other place. ret is a completely pointless
> variable and the initialization is even more pointless. There is exactly
> one code path using it (fail) and you can just return -ENOMEM from there.
>
>> +	if (cqm_pkgs_data[curr_pkgid])
>> +		return 0;
>> +
>> +	pkg_data = kzalloc_node(sizeof(struct pkg_data),
>> +				GFP_KERNEL, cpu_to_node(cpu));
>> +	if (!pkg_data)
>> +		return -ENOMEM;
>> +
>> +	INIT_LIST_HEAD(&pkg_data->cqm_rmid_free_lru);
>> +	INIT_LIST_HEAD(&pkg_data->cqm_rmid_limbo_lru);
>> +
>> +	mutex_init(&pkg_data->pkg_data_mutex);
>> +	raw_spin_lock_init(&pkg_data->pkg_data_lock);
>> +
>> +	pkg_data->rmid_work_cpu = cpu;
>> +
>> +	nr_rmids = cqm_max_rmid + 1;
>> +	ccqm_rmid_ptrs = kzalloc(sizeof(struct cqm_rmid_entry) *
>> +			   nr_rmids, GFP_KERNEL);
>> +	if (!ccqm_rmid_ptrs) {
>> +		ret = -ENOMEM;
>> +		goto fail;
>> +	}
>> +
>> +	for (; i <= cqm_max_rmid; i++) {
>> +		entry = &ccqm_rmid_ptrs[i];
>> +		INIT_LIST_HEAD(&entry->list);
>> +		entry->rmid = i;
>> +
>> +		list_add_tail(&entry->list, &pkg_data->cqm_rmid_free_lru);
>> +	}
>> +
>> +	pkg_data->cqm_rmid_ptrs = ccqm_rmid_ptrs;
>> +	cqm_pkgs_data[curr_pkgid] = pkg_data;
>> +
>> +	/*
>> +	 * RMID 0 is special and is always allocated. It's used for all
>> +	 * tasks that are not monitored.
>> +	 */
>> +	entry = __rmid_entry(0, curr_pkgid);
>> +	list_del(&entry->list);
>> +
>> +	return 0;
>> +fail:
>> +	kfree(ccqm_rmid_ptrs);
>> +	ccqm_rmid_ptrs = NULL;
>
> And clearing the local variable has which value?
>
>> +	kfree(pkg_data);
>> +	pkg_data = NULL;
>> +	cqm_pkgs_data[curr_pkgid] = NULL;
>
> It never got set, so why do you need to clear it? Just because you do not
> trust the compiler?
>
>> +	return ret;
>> +}
>> +
>> +static int cqm_init_pkgs_data(void)
>> +{
>> +	int i, cpu, ret = 0;
>
> Again, pointless 0 initialization.
>
>> +	cqm_pkgs_data = kzalloc(
>> +		sizeof(struct pkg_data *) * cqm_socket_max,
>> +		GFP_KERNEL);
>
> Using a simple local variable to calculate size first would spare this new
> variant of coding style horror.
>
>> +	if (!cqm_pkgs_data)
>> +		return -ENOMEM;
>> +
>> +	for (i = 0; i < cqm_socket_max; i++)
>> +		cqm_pkgs_data[i] = NULL;
>
> Surely kzalloc() is not reliable enough, so make sure that the pointers are
> really NULL. Brilliant stuff.

Will fix all the initialization and repeated zeroing indicated.

>
>> +
>> +	for_each_online_cpu(cpu) {
>> +		ret = pkg_data_init_cpu(cpu);
>> +		if (ret)
>> +			goto fail;
>> +	}
>
> And that's protected against CPU hotplug in which way?
>
> Aside of that. What allocates the package data for packages which come
> online _AFTER_ this function is called? Nothing AFAICT.
>
> What you really need is a CPU hotplug callback for the prepare stage, which
> is doing the setup of this race free and also handling packages which come
> online after this.

Will fix the init and protecting this in cpu hotplug (get_online_cpus()).

>
>> diff --git a/arch/x86/events/intel/cqm.h b/arch/x86/events/intel/cqm.h
>> new file mode 100644
>> index 0000000..4415497
>> --- /dev/null
>> +++ b/arch/x86/events/intel/cqm.h
>> @@ -0,0 +1,37 @@
>> +#ifndef _ASM_X86_CQM_H
>> +#define _ASM_X86_CQM_H
>> +
>> +#ifdef CONFIG_INTEL_RDT_M
>> +
>> +#include <linux/perf_event.h>
>> +
>> +/**
>> + * struct pkg_data - cqm per package(socket) meta data
>> + * @cqm_rmid_free_lru    A least recently used list of free RMIDs
>> + *     These RMIDs are guaranteed to have an occupancy less than the
>> + * threshold occupancy
>
> You certainly did not even try to run kernel doc on this.
>
>    @var:  Explanation
>
> is the proper format. Can you spot the difference?
>
> Also the multi line comments are horribly formatted:
>
>   @var:       	    This is a multiline commend which is necessary because
>   		    it needs a lot of text......
>
>> + * @cqm_rmid_entry - The entry in the limbo and free lists.
>
> And this is incorrect as well. You are not even trying to make stuff
> consistently wrong.
>
>> + * @delayed_work - Work to reuse the RMIDs that have been freed.
>> + * @rmid_work_cpu - The cpu on the package on which work is scheduled.
>
> Also the formatting wants to be tabular:
>
> * @var:		Text
> * @long_var:		Text
> * @really_long_var:	Text

Will fix the comment formats.

Thanks,
Vikas



>
> Sigh,
>
> 	tglx
>

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ