Re: [PATCH] cacheinfo: Introduce cache id
From: Borislav Petkov
Date: Fri Jul 01 2016 - 06:22:29 EST
On Wed, Jun 29, 2016 at 06:56:10PM -0700, Fenghua Yu wrote:
> From: Fenghua Yu <fenghua.yu@xxxxxxxxx>
>
> Each cache node is described by cacheinfo and is a unique node across
What is a cache node?
> the platform. But there is no id for a cache node. We introduce cache ID
> to identify a cache node.
>
> Intel Cache Allocation Technology (CAT) allows some control on the
> allocation policy within each cache that it controls. We need a unique
> cache ID for each cache level to allow the user to specify which
> controls are applied to which cache.
>
> The cache id is first enabled on x86. It can be enabled on other platforms
> as well. The cache id is not necessary contiguous.
>
> Add an "id" entry to /sys/devices/system/cpu/cpu*/cache/index*/
>
> Signed-off-by: Fenghua Yu <fenghua.yu@xxxxxxxxx>
> ---
> arch/x86/kernel/cpu/intel_cacheinfo.c | 21 +++++++++++++++++++++
> drivers/base/cacheinfo.c | 5 +++++
> include/linux/cacheinfo.h | 3 +++
> 3 files changed, 29 insertions(+)
>
> diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
> index de6626c..aefc1e5 100644
> --- a/arch/x86/kernel/cpu/intel_cacheinfo.c
> +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
> @@ -153,6 +153,7 @@ struct _cpuid4_info_regs {
> union _cpuid4_leaf_eax eax;
> union _cpuid4_leaf_ebx ebx;
> union _cpuid4_leaf_ecx ecx;
> + unsigned int id;
> unsigned long size;
> struct amd_northbridge *nb;
> };
> @@ -894,6 +895,9 @@ static void __cache_cpumap_setup(unsigned int cpu, int index,
> static void ci_leaf_init(struct cacheinfo *this_leaf,
> struct _cpuid4_info_regs *base)
> {
> + this_leaf->id = base->id;
> + /* Set CACHE_ID bit in attributes to enable cache id in x86. */
No need for that comment.
> + this_leaf->attributes = CACHE_ID;
> this_leaf->level = base->eax.split.level;
> this_leaf->type = cache_type_map[base->eax.split.type];
> this_leaf->coherency_line_size =
> @@ -920,6 +924,22 @@ static int __init_cache_level(unsigned int cpu)
> return 0;
> }
>
> +/*
> + * The max shared threads number comes from CPUID.4:EAX[25-14] with input
> + * ECX as cache index. Then right shift apicid by the number's order to get
> + * cache id for this cache node.
> + */
> +static void get_cache_id(int cpu, struct _cpuid4_info_regs *id4_regs)
> +{
> + struct cpuinfo_x86 *c = &cpu_data(cpu);
> + unsigned long num_threads_sharing;
> + int index_msb;
> +
> + num_threads_sharing = 1 + id4_regs->eax.split.num_threads_sharing;
> + index_msb = get_count_order(num_threads_sharing);
> + id4_regs->id = c->apicid >> index_msb;
> +}
> +
> static int __populate_cache_leaves(unsigned int cpu)
> {
> unsigned int idx, ret;
> @@ -931,6 +951,7 @@ static int __populate_cache_leaves(unsigned int cpu)
> ret = cpuid4_cache_lookup_regs(idx, &id4_regs);
> if (ret)
> return ret;
> + get_cache_id(cpu, &id4_regs);
> ci_leaf_init(this_leaf++, &id4_regs);
> __cache_cpumap_setup(cpu, idx, &id4_regs);
> }
> diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
> index e9fd32e..2a21c15 100644
> --- a/drivers/base/cacheinfo.c
> +++ b/drivers/base/cacheinfo.c
> @@ -233,6 +233,7 @@ static ssize_t file_name##_show(struct device *dev, \
> return sprintf(buf, "%u\n", this_leaf->object); \
> }
>
> +show_one(id, id);
> show_one(level, level);
> show_one(coherency_line_size, coherency_line_size);
> show_one(number_of_sets, number_of_sets);
> @@ -314,6 +315,7 @@ static ssize_t write_policy_show(struct device *dev,
> return n;
> }
>
> +static DEVICE_ATTR_RO(id);
> static DEVICE_ATTR_RO(level);
> static DEVICE_ATTR_RO(type);
> static DEVICE_ATTR_RO(coherency_line_size);
> @@ -327,6 +329,7 @@ static DEVICE_ATTR_RO(shared_cpu_list);
> static DEVICE_ATTR_RO(physical_line_partition);
>
> static struct attribute *cache_default_attrs[] = {
> + &dev_attr_id.attr,
> &dev_attr_type.attr,
> &dev_attr_level.attr,
> &dev_attr_shared_cpu_map.attr,
> @@ -350,6 +353,8 @@ cache_default_attrs_is_visible(struct kobject *kobj,
> const struct cpumask *mask = &this_leaf->shared_cpu_map;
> umode_t mode = attr->mode;
>
> + if ((attr == &dev_attr_id.attr) && this_leaf->attributes & CACHE_ID)
> + return mode;
> if ((attr == &dev_attr_type.attr) && this_leaf->type)
> return mode;
> if ((attr == &dev_attr_level.attr) && this_leaf->level)
> diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h
> index 2189935..16e5573 100644
> --- a/include/linux/cacheinfo.h
> +++ b/include/linux/cacheinfo.h
> @@ -18,6 +18,7 @@ enum cache_type {
>
> /**
> * struct cacheinfo - represent a cache leaf node
> + * @id: id of this cache node. This is unique id across the platform.
So you need to explain what a "cache node" is. Especially since this is
generic code and other arches might not necessarily have a notion of a
"cache node" - whatever that is.
And since this patch adds the generic functionality and then enables it
on x86, it should be split into two patches.
--
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix ImendÃrffer, Jane Smithard, Graham Norton, HRB 21284 (AG NÃrnberg)
--