From 04402116846f36adea9503d7cd5104a7ed27a1a6 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Sun, 12 Feb 2017 22:12:07 +0100 Subject: x86/cpu: Drop unneded members of struct cpuinfo_x86 Those member serve no purpose -- not even fill padding for alignment or such. So just get rid of them. Signed-off-by: Mathias Krause Acked-by: Borislav Petkov Cc: Jesper Nilsson Cc: Mikael Starvik Cc: Geert Uytterhoeven Cc: Andrew Morton Cc: "David S. Miller" Link: http://lkml.kernel.org/r/1486933932-585-2-git-send-email-minipli@googlemail.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/processor.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index f385eca5407a..893f80e30bfb 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -80,7 +80,7 @@ extern u16 __read_mostly tlb_lld_1g[NR_INFO]; /* * CPU type and hardware bug flags. Kept separately for each CPU. - * Members of this structure are referenced in head.S, so think twice + * Members of this structure are referenced in head_32.S, so think twice * before touching them. [mj] */ @@ -91,11 +91,6 @@ struct cpuinfo_x86 { __u8 x86_mask; #ifdef CONFIG_X86_32 char wp_works_ok; /* It doesn't on 386's */ - - /* Problems on some 486Dx4's and old 386's: */ - char rfu; - char pad0; - char pad1; #else /* Number of 4K pages in DTLB/ITLB combined(in pages): */ int x86_tlbsize; -- cgit v1.2.3 From 6415813bae75feba10b8ca3ed6634a72c2a4d313 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Sun, 12 Feb 2017 22:12:08 +0100 Subject: x86/cpu: Drop wp_works_ok member of struct cpuinfo_x86 Remove the wp_works_ok member of struct cpuinfo_x86. It's an optimization back from Linux v0.99 times where we had no fixup support yet and did the CR0.WP test via special code in the page fault handler. The < 0 test was an optimization to not do the special casing for each NULL ptr access violation but just for the first one doing the WP test. Today it serves no real purpose as the test no longer needs special code in the page fault handler and the only call side -- mem_init() -- calls it just once, anyway. However, Xen pre-initializes it to 1, to skip the test. Doing the test again for Xen should be no issue at all, as even the commit introducing skipping the test (commit d560bc61575e ("x86, xen: Suppress WP test on Xen")) mentioned it being ban aid only. And, in fact, testing the patch on Xen showed nothing breaks. The pre-fixup times are long gone and with the removal of the fallback handling code in commit a5c2a893dbd4 ("x86, 386 removal: Remove CONFIG_X86_WP_WORKS_OK") the kernel requires a working CR0.WP anyway. So just get rid of the "optimization" and do the test unconditionally. Signed-off-by: Mathias Krause Acked-by: Borislav Petkov Cc: Jesper Nilsson Cc: Jeremy Fitzhardinge Cc: Arnd Hannemann Cc: Mikael Starvik Cc: Geert Uytterhoeven Cc: Andrew Morton Cc: "David S. Miller" Link: http://lkml.kernel.org/r/1486933932-585-3-git-send-email-minipli@googlemail.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/processor.h | 4 +--- arch/x86/kernel/cpu/proc.c | 5 ++--- arch/x86/kernel/setup.c | 11 ++++------- arch/x86/mm/init_32.c | 9 +++++---- arch/x86/xen/enlighten.c | 1 - 5 files changed, 12 insertions(+), 18 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 893f80e30bfb..4aa93b560a2b 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -89,9 +89,7 @@ struct cpuinfo_x86 { __u8 x86_vendor; /* CPU vendor */ __u8 x86_model; __u8 x86_mask; -#ifdef CONFIG_X86_32 - char wp_works_ok; /* It doesn't on 386's */ -#else +#ifdef CONFIG_X86_64 /* Number of 4K pages in DTLB/ITLB combined(in pages): */ int x86_tlbsize; #endif diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index 18ca99f2798b..6df621ae62a7 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c @@ -31,14 +31,13 @@ static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) "fpu\t\t: %s\n" "fpu_exception\t: %s\n" "cpuid level\t: %d\n" - "wp\t\t: %s\n", + "wp\t\t: yes\n", static_cpu_has_bug(X86_BUG_FDIV) ? "yes" : "no", static_cpu_has_bug(X86_BUG_F00F) ? "yes" : "no", static_cpu_has_bug(X86_BUG_COMA) ? "yes" : "no", static_cpu_has(X86_FEATURE_FPU) ? "yes" : "no", static_cpu_has(X86_FEATURE_FPU) ? "yes" : "no", - c->cpuid_level, - c->wp_works_ok ? "yes" : "no"); + c->cpuid_level); } #else static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 4bf0c8926a1c..7cd7bbefd418 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -173,14 +173,11 @@ static struct resource bss_resource = { #ifdef CONFIG_X86_32 -/* cpu data as detected by the assembly code in head.S */ -struct cpuinfo_x86 new_cpu_data = { - .wp_works_ok = -1, -}; +/* cpu data as detected by the assembly code in head_32.S */ +struct cpuinfo_x86 new_cpu_data; + /* common cpu data for all cpus */ -struct cpuinfo_x86 boot_cpu_data __read_mostly = { - .wp_works_ok = -1, -}; +struct cpuinfo_x86 boot_cpu_data __read_mostly; EXPORT_SYMBOL(boot_cpu_data); unsigned int def_to_bigsmp; diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 2b4b53e6793f..4dddfaf6569a 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -716,15 +716,17 @@ void __init paging_init(void) */ static void __init test_wp_bit(void) { + int wp_works_ok; + printk(KERN_INFO "Checking if this processor honours the WP bit even in supervisor mode..."); /* Any page-aligned address will do, the test is non-destructive */ __set_fixmap(FIX_WP_TEST, __pa(&swapper_pg_dir), PAGE_KERNEL_RO); - boot_cpu_data.wp_works_ok = do_test_wp_bit(); + wp_works_ok = do_test_wp_bit(); clear_fixmap(FIX_WP_TEST); - if (!boot_cpu_data.wp_works_ok) { + if (!wp_works_ok) { printk(KERN_CONT "No.\n"); panic("Linux doesn't support CPUs with broken WP."); } else { @@ -811,8 +813,7 @@ void __init mem_init(void) BUG_ON(VMALLOC_START >= VMALLOC_END); BUG_ON((unsigned long)high_memory > VMALLOC_START); - if (boot_cpu_data.wp_works_ok < 0) - test_wp_bit(); + test_wp_bit(); } #ifdef CONFIG_MEMORY_HOTPLUG diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index ec1d5c46e58f..bc3dab5d47ca 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1595,7 +1595,6 @@ asmlinkage __visible void __init xen_start_kernel(void) /* set up basic CPUID stuff */ cpu_detect(&new_cpu_data); set_cpu_cap(&new_cpu_data, X86_FEATURE_FPU); - new_cpu_data.wp_works_ok = 1; new_cpu_data.x86_capability[CPUID_1_EDX] = cpuid_edx(1); #endif -- cgit v1.2.3 From c4026b7b95a4b852e404afa2cd7720866159d118 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Mon, 3 Apr 2017 14:44:16 -0700 Subject: x86/intel_rdt: Implement "update" mode when writing schemata file The schemata file can have multiple lines and it is cumbersome to update all lines. Remove code that requires that the user provides values for every resource (in the right order). If the user provides values for just a few resources, update them and leave the rest unchanged. Side benefit: we now check which values were updated and only send IPIs to cpus that actually have updates. Signed-off-by: Tony Luck Signed-off-by: Vikas Shivappa Tested-by: Sai Praneeth Prakhya Cc: ravi.v.shankar@intel.com Cc: fenghua.yu@intel.com Cc: peterz@infradead.org Cc: vikas.shivappa@intel.com Cc: h.peter.anvin@intel.com Link: http://lkml.kernel.org/r/1491255857-17213-3-git-send-email-vikas.shivappa@linux.intel.com Signed-off-by: Thomas Gleixner --- Documentation/x86/intel_rdt_ui.txt | 14 ++++++ arch/x86/include/asm/intel_rdt.h | 10 ++--- arch/x86/kernel/cpu/intel_rdt.c | 2 - arch/x86/kernel/cpu/intel_rdt_schemata.c | 76 ++++++++++++++------------------ 4 files changed, 51 insertions(+), 51 deletions(-) (limited to 'arch') diff --git a/Documentation/x86/intel_rdt_ui.txt b/Documentation/x86/intel_rdt_ui.txt index 51cf6fa5591f..3ea198460469 100644 --- a/Documentation/x86/intel_rdt_ui.txt +++ b/Documentation/x86/intel_rdt_ui.txt @@ -129,6 +129,20 @@ schemata format is always: L2:=;=;... +Reading/writing the schemata file +--------------------------------- +Reading the schemata file will show the state of all resources +on all domains. When writing you only need to specify those values +which you wish to change. E.g. + +# cat schemata +L3DATA:0=fffff;1=fffff;2=fffff;3=fffff +L3CODE:0=fffff;1=fffff;2=fffff;3=fffff +# echo "L3DATA:2=3c0;" > schemata +# cat schemata +L3DATA:0=fffff;1=fffff;2=3c0;3=fffff +L3CODE:0=fffff;1=fffff;2=fffff;3=fffff + Example 1 --------- On a two socket machine (one L3 cache per socket) with just four bits diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h index 0d64397cee58..d7705270c401 100644 --- a/arch/x86/include/asm/intel_rdt.h +++ b/arch/x86/include/asm/intel_rdt.h @@ -76,10 +76,7 @@ struct rftype { * @min_cbm_bits: Minimum number of consecutive bits to be set * in a cache bit mask * @domains: All domains for this resource - * @num_domains: Number of domains active * @msr_base: Base MSR address for CBMs - * @tmp_cbms: Scratch space when updating schemata - * @num_tmp_cbms: Number of CBMs in tmp_cbms * @cache_level: Which cache level defines scope of this domain * @cbm_idx_multi: Multiplier of CBM index * @cbm_idx_offset: Offset of CBM index. CBM index is computed by: @@ -94,10 +91,7 @@ struct rdt_resource { int min_cbm_bits; u32 max_cbm; struct list_head domains; - int num_domains; int msr_base; - u32 *tmp_cbms; - int num_tmp_cbms; int cache_level; int cbm_idx_multi; int cbm_idx_offset; @@ -109,12 +103,16 @@ struct rdt_resource { * @id: unique id for this instance * @cpu_mask: which cpus share this resource * @cbm: array of cache bit masks (indexed by CLOSID) + * @new_cbm: new cbm value to be loaded + * @have_new_cbm: did user provide new_cbm for this domain */ struct rdt_domain { struct list_head list; int id; struct cpumask cpu_mask; u32 *cbm; + u32 new_cbm; + bool have_new_cbm; }; /** diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index 5a533fefefa0..329b8876b984 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -309,7 +309,6 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r) cpumask_set_cpu(cpu, &d->cpu_mask); list_add_tail(&d->list, add_pos); - r->num_domains++; } static void domain_remove_cpu(int cpu, struct rdt_resource *r) @@ -325,7 +324,6 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r) cpumask_clear_cpu(cpu, &d->cpu_mask); if (cpumask_empty(&d->cpu_mask)) { - r->num_domains--; kfree(d->cbm); list_del(&d->list); kfree(d); diff --git a/arch/x86/kernel/cpu/intel_rdt_schemata.c b/arch/x86/kernel/cpu/intel_rdt_schemata.c index f369cb8db0d5..52e83eabd9b7 100644 --- a/arch/x86/kernel/cpu/intel_rdt_schemata.c +++ b/arch/x86/kernel/cpu/intel_rdt_schemata.c @@ -56,17 +56,21 @@ static bool cbm_validate(unsigned long var, struct rdt_resource *r) * Read one cache bit mask (hex). Check that it is valid for the current * resource type. */ -static int parse_cbm(char *buf, struct rdt_resource *r) +static int parse_cbm(char *buf, struct rdt_resource *r, struct rdt_domain *d) { unsigned long data; int ret; + if (d->have_new_cbm) + return -EINVAL; + ret = kstrtoul(buf, 16, &data); if (ret) return ret; if (!cbm_validate(data, r)) return -EINVAL; - r->tmp_cbms[r->num_tmp_cbms++] = data; + d->new_cbm = data; + d->have_new_cbm = true; return 0; } @@ -74,8 +78,8 @@ static int parse_cbm(char *buf, struct rdt_resource *r) /* * For each domain in this resource we expect to find a series of: * id=mask - * separated by ";". The "id" is in decimal, and must appear in the - * right order. + * separated by ";". The "id" is in decimal, and must match one of + * the "id"s for this resource. */ static int parse_line(char *line, struct rdt_resource *r) { @@ -83,21 +87,21 @@ static int parse_line(char *line, struct rdt_resource *r) struct rdt_domain *d; unsigned long dom_id; +next: + if (!line || line[0] == '\0') + return 0; + dom = strsep(&line, ";"); + id = strsep(&dom, "="); + if (!dom || kstrtoul(id, 10, &dom_id)) + return -EINVAL; list_for_each_entry(d, &r->domains, list) { - dom = strsep(&line, ";"); - if (!dom) - return -EINVAL; - id = strsep(&dom, "="); - if (kstrtoul(id, 10, &dom_id) || dom_id != d->id) - return -EINVAL; - if (parse_cbm(dom, r)) - return -EINVAL; + if (d->id == dom_id) { + if (parse_cbm(dom, r, d)) + return -EINVAL; + goto next; + } } - - /* Any garbage at the end of the line? */ - if (line && line[0]) - return -EINVAL; - return 0; + return -EINVAL; } static int update_domains(struct rdt_resource *r, int closid) @@ -105,7 +109,7 @@ static int update_domains(struct rdt_resource *r, int closid) struct msr_param msr_param; cpumask_var_t cpu_mask; struct rdt_domain *d; - int cpu, idx = 0; + int cpu; if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL)) return -ENOMEM; @@ -115,9 +119,13 @@ static int update_domains(struct rdt_resource *r, int closid) msr_param.res = r; list_for_each_entry(d, &r->domains, list) { - cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask); - d->cbm[msr_param.low] = r->tmp_cbms[idx++]; + if (d->have_new_cbm && d->new_cbm != d->cbm[closid]) { + cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask); + d->cbm[closid] = d->new_cbm; + } } + if (cpumask_empty(cpu_mask)) + goto done; cpu = get_cpu(); /* Update CBM on this cpu if it's in cpu_mask. */ if (cpumask_test_cpu(cpu, cpu_mask)) @@ -126,6 +134,7 @@ static int update_domains(struct rdt_resource *r, int closid) smp_call_function_many(cpu_mask, rdt_cbm_update, &msr_param, 1); put_cpu(); +done: free_cpumask_var(cpu_mask); return 0; @@ -135,10 +144,10 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, char *buf, size_t nbytes, loff_t off) { struct rdtgroup *rdtgrp; + struct rdt_domain *dom; struct rdt_resource *r; char *tok, *resname; int closid, ret = 0; - u32 *l3_cbms = NULL; /* Valid input requires a trailing newline */ if (nbytes == 0 || buf[nbytes - 1] != '\n') @@ -153,16 +162,9 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, closid = rdtgrp->closid; - /* get scratch space to save all the masks while we validate input */ - for_each_enabled_rdt_resource(r) { - r->tmp_cbms = kcalloc(r->num_domains, sizeof(*l3_cbms), - GFP_KERNEL); - if (!r->tmp_cbms) { - ret = -ENOMEM; - goto out; - } - r->num_tmp_cbms = 0; - } + for_each_enabled_rdt_resource(r) + list_for_each_entry(dom, &r->domains, list) + dom->have_new_cbm = false; while ((tok = strsep(&buf, "\n")) != NULL) { resname = strsep(&tok, ":"); @@ -185,14 +187,6 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, } } - /* Did the parser find all the masks we need? */ - for_each_enabled_rdt_resource(r) { - if (r->num_tmp_cbms != r->num_domains) { - ret = -EINVAL; - goto out; - } - } - for_each_enabled_rdt_resource(r) { ret = update_domains(r, closid); if (ret) @@ -201,10 +195,6 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, out: rdtgroup_kn_unlock(of->kn); - for_each_enabled_rdt_resource(r) { - kfree(r->tmp_cbms); - r->tmp_cbms = NULL; - } return ret ?: nbytes; } -- cgit v1.2.3 From de016df88f23a5ab0cec3a8e05f6066388725b9e Mon Sep 17 00:00:00 2001 From: Vikas Shivappa Date: Mon, 3 Apr 2017 14:44:17 -0700 Subject: x86/intel_rdt: Update schemata read to show data in tabular format The schemata file displays data from different resources on all domains. Its cumbersome to read since they are not tabular and data/names could be of different widths. Make the schemata file to display data in a tabular format thereby making it nice and simple to read. Signed-off-by: Vikas Shivappa Cc: ravi.v.shankar@intel.com Cc: tony.luck@intel.com Cc: fenghua.yu@intel.com Cc: peterz@infradead.org Cc: vikas.shivappa@intel.com Cc: h.peter.anvin@intel.com Link: http://lkml.kernel.org/r/1491255857-17213-4-git-send-email-vikas.shivappa@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/intel_rdt.h | 4 ++++ arch/x86/kernel/cpu/intel_rdt.c | 30 ++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/intel_rdt_schemata.c | 5 +++-- 3 files changed, 37 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h index d7705270c401..3f313991c0b3 100644 --- a/arch/x86/include/asm/intel_rdt.h +++ b/arch/x86/include/asm/intel_rdt.h @@ -40,6 +40,8 @@ struct rdtgroup { /* List of all resource groups */ extern struct list_head rdt_all_groups; +extern int max_name_width, max_data_width; + int __init rdtgroup_init(void); /** @@ -73,6 +75,7 @@ struct rftype { * @name: Name to use in "schemata" file * @num_closid: Number of CLOSIDs available * @max_cbm: Largest Cache Bit Mask allowed + * @data_width: Character width of data when displaying * @min_cbm_bits: Minimum number of consecutive bits to be set * in a cache bit mask * @domains: All domains for this resource @@ -90,6 +93,7 @@ struct rdt_resource { int cbm_len; int min_cbm_bits; u32 max_cbm; + int data_width; struct list_head domains; int msr_base; int cache_level; diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index 329b8876b984..70a3307fd592 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -39,6 +39,12 @@ DEFINE_PER_CPU_READ_MOSTLY(int, cpu_closid); #define domain_init(id) LIST_HEAD_INIT(rdt_resources_all[id].domains) +/* + * Used to store the max resource name width and max resource data width + * to display the schemata in a tabular format + */ +int max_name_width, max_data_width; + struct rdt_resource rdt_resources_all[] = { { .name = "L3", @@ -140,6 +146,7 @@ static void rdt_get_config(int idx, struct rdt_resource *r) r->num_closid = edx.split.cos_max + 1; r->cbm_len = eax.split.cbm_len + 1; r->max_cbm = BIT_MASK(eax.split.cbm_len + 1) - 1; + r->data_width = (r->cbm_len + 3) / 4; r->capable = true; r->enabled = true; } @@ -152,6 +159,7 @@ static void rdt_get_cdp_l3_config(int type) r->num_closid = r_l3->num_closid / 2; r->cbm_len = r_l3->cbm_len; r->max_cbm = r_l3->max_cbm; + r->data_width = (r->cbm_len + 3) / 4; r->capable = true; /* * By default, CDP is disabled. CDP can be enabled by mount parameter @@ -160,6 +168,26 @@ static void rdt_get_cdp_l3_config(int type) r->enabled = false; } +/** + * Choose a width for the resource name + * and resource data based on the resource that has + * widest name and cbm. + */ +static void rdt_init_padding(void) +{ + struct rdt_resource *r; + int cl; + + for_each_enabled_rdt_resource(r) { + cl = strlen(r->name); + if (cl > max_name_width) + max_name_width = cl; + + if (r->data_width > max_data_width) + max_data_width = r->data_width; + } +} + static inline bool get_rdt_resources(void) { bool ret = false; @@ -184,6 +212,8 @@ static inline bool get_rdt_resources(void) ret = true; } + rdt_init_padding(); + return ret; } diff --git a/arch/x86/kernel/cpu/intel_rdt_schemata.c b/arch/x86/kernel/cpu/intel_rdt_schemata.c index 52e83eabd9b7..8594db455aa1 100644 --- a/arch/x86/kernel/cpu/intel_rdt_schemata.c +++ b/arch/x86/kernel/cpu/intel_rdt_schemata.c @@ -203,11 +203,12 @@ static void show_doms(struct seq_file *s, struct rdt_resource *r, int closid) struct rdt_domain *dom; bool sep = false; - seq_printf(s, "%s:", r->name); + seq_printf(s, "%*s:", max_name_width, r->name); list_for_each_entry(dom, &r->domains, list) { if (sep) seq_puts(s, ";"); - seq_printf(s, "%d=%x", dom->id, dom->cbm[closid]); + seq_printf(s, "%d=%0*x", dom->id, max_data_width, + dom->cbm[closid]); sep = true; } seq_puts(s, "\n"); -- cgit v1.2.3 From 17f8ba1dca072ce66c25b9e74ea2500b029594a0 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 10 Apr 2017 11:50:11 +0200 Subject: x86/intel_rdt: Cleanup kernel-doc The kernel-doc is inconsistently formatted. Fix it up. Signed-off-by: Thomas Gleixner Cc: Fenghua Yu Cc: Tony Luck Cc: Vikas Shivappa --- arch/x86/include/asm/intel_rdt.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h index 3f313991c0b3..9030bcccb717 100644 --- a/arch/x86/include/asm/intel_rdt.h +++ b/arch/x86/include/asm/intel_rdt.h @@ -46,11 +46,11 @@ int __init rdtgroup_init(void); /** * struct rftype - describe each file in the resctrl file system - * @name: file name - * @mode: access mode - * @kf_ops: operations - * @seq_show: show content of the file - * @write: write to the file + * @name: File name + * @mode: Access mode + * @kf_ops: File operations + * @seq_show: Show content of the file + * @write: Write to the file */ struct rftype { char *name; @@ -75,7 +75,7 @@ struct rftype { * @name: Name to use in "schemata" file * @num_closid: Number of CLOSIDs available * @max_cbm: Largest Cache Bit Mask allowed - * @data_width: Character width of data when displaying + * @data_width: Character width of data when displaying * @min_cbm_bits: Minimum number of consecutive bits to be set * in a cache bit mask * @domains: All domains for this resource @@ -151,7 +151,7 @@ enum { #define for_each_capable_rdt_resource(r) \ for (r = rdt_resources_all; r < rdt_resources_all + RDT_NUM_RESOURCES;\ - r++) \ + r++) \ if (r->capable) #define for_each_enabled_rdt_resource(r) \ -- cgit v1.2.3 From 4ffa3c977b5da2907eb294dc6d0259a02f2284aa Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 10 Apr 2017 16:52:32 +0200 Subject: x86/intel_rdt: Add cpus_list rdtgroup file The resource control filesystem provides only a bitmask based cpus file for assigning CPUs to a resource group. That's cumbersome with large cpumasks and non-intuitive when modifying the file from the command line. Range based cpu lists are commonly used along with bitmask based cpu files in various subsystems throughout the kernel. Add 'cpus_list' file which is CPU range based. # cd /sys/fs/resctrl/ # echo 1-10 > krava/cpus_list # cat krava/cpus_list 1-10 # cat krava/cpus 0007fe # cat cpus fffff9 # cat cpus_list 0,3-23 [ tglx: Massaged changelog and replaced "bitmask lists" by "CPU ranges" ] Signed-off-by: Jiri Olsa Cc: Fenghua Yu Cc: Peter Zijlstra Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Shaohua Li Link: http://lkml.kernel.org/r/20170410145232.GF25354@krava Signed-off-by: Thomas Gleixner --- Documentation/x86/intel_rdt_ui.txt | 3 +++ arch/x86/include/asm/intel_rdt.h | 5 +++++ arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 29 +++++++++++++++++++++++++---- 3 files changed, 33 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/Documentation/x86/intel_rdt_ui.txt b/Documentation/x86/intel_rdt_ui.txt index 3ea198460469..a1ace91c4b86 100644 --- a/Documentation/x86/intel_rdt_ui.txt +++ b/Documentation/x86/intel_rdt_ui.txt @@ -59,6 +59,9 @@ There are three files associated with each group: given to the default (root) group. You cannot remove CPUs from the default group. +"cpus_list": One or more CPU ranges of logical CPUs assigned to this + group. Same rules apply like for the "cpus" file. + "schemata": A list of all the resources available to this group. Each resource has its own line and format - see below for details. diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h index 9030bcccb717..611c82306fdf 100644 --- a/arch/x86/include/asm/intel_rdt.h +++ b/arch/x86/include/asm/intel_rdt.h @@ -37,6 +37,9 @@ struct rdtgroup { /* rdtgroup.flags */ #define RDT_DELETED 1 +/* rftype.flags */ +#define RFTYPE_FLAGS_CPUS_LIST 1 + /* List of all resource groups */ extern struct list_head rdt_all_groups; @@ -49,6 +52,7 @@ int __init rdtgroup_init(void); * @name: File name * @mode: Access mode * @kf_ops: File operations + * @flags: File specific RFTYPE_FLAGS_* flags * @seq_show: Show content of the file * @write: Write to the file */ @@ -56,6 +60,7 @@ struct rftype { char *name; umode_t mode; struct kernfs_ops *kf_ops; + unsigned long flags; int (*seq_show)(struct kernfs_open_file *of, struct seq_file *sf, void *v); diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c index c05509d38b1f..8401cf5cc239 100644 --- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c @@ -174,6 +174,13 @@ static struct kernfs_ops rdtgroup_kf_single_ops = { .seq_show = rdtgroup_seqfile_show, }; +static bool is_cpu_list(struct kernfs_open_file *of) +{ + struct rftype *rft = of->kn->priv; + + return rft->flags & RFTYPE_FLAGS_CPUS_LIST; +} + static int rdtgroup_cpus_show(struct kernfs_open_file *of, struct seq_file *s, void *v) { @@ -182,10 +189,12 @@ static int rdtgroup_cpus_show(struct kernfs_open_file *of, rdtgrp = rdtgroup_kn_lock_live(of->kn); - if (rdtgrp) - seq_printf(s, "%*pb\n", cpumask_pr_args(&rdtgrp->cpu_mask)); - else + if (rdtgrp) { + seq_printf(s, is_cpu_list(of) ? "%*pbl\n" : "%*pb\n", + cpumask_pr_args(&rdtgrp->cpu_mask)); + } else { ret = -ENOENT; + } rdtgroup_kn_unlock(of->kn); return ret; @@ -252,7 +261,11 @@ static ssize_t rdtgroup_cpus_write(struct kernfs_open_file *of, goto unlock; } - ret = cpumask_parse(buf, newmask); + if (is_cpu_list(of)) + ret = cpulist_parse(buf, newmask); + else + ret = cpumask_parse(buf, newmask); + if (ret) goto unlock; @@ -472,6 +485,14 @@ static struct rftype rdtgroup_base_files[] = { .write = rdtgroup_cpus_write, .seq_show = rdtgroup_cpus_show, }, + { + .name = "cpus_list", + .mode = 0644, + .kf_ops = &rdtgroup_kf_single_ops, + .write = rdtgroup_cpus_write, + .seq_show = rdtgroup_cpus_show, + .flags = RFTYPE_FLAGS_CPUS_LIST, + }, { .name = "tasks", .mode = 0644, -- cgit v1.2.3 From 06b57e4550d400c2e7dcafbde6fdb1fcb6fcdcee Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 14 Apr 2017 14:06:26 +0200 Subject: x86/intel_rdt: Init padding only if a device exists If no device exists it's pointless to calculate the padding data for the schemata files. Signed-off-by: Thomas Gleixner Cc: ravi.v.shankar@intel.com Cc: tony.luck@intel.com Cc: fenghua.yu@intel.com Cc: vikas.shivappa@intel.com --- arch/x86/kernel/cpu/intel_rdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index 70a3307fd592..2802cad0371d 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -212,8 +212,6 @@ static inline bool get_rdt_resources(void) ret = true; } - rdt_init_padding(); - return ret; } @@ -410,6 +408,8 @@ static int __init intel_rdt_late_init(void) if (!get_rdt_resources()) return -ENODEV; + rdt_init_padding(); + state = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/rdt/cat:online:", intel_rdt_online_cpu, intel_rdt_offline_cpu); -- cgit v1.2.3 From 70a1ee92564d079b4c7a375b244a6c849b81f12f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 14 Apr 2017 14:07:47 +0200 Subject: x86/intel_rdt: Organize code properly Having init functions at random places in the middle of the code is unintuitive. Move them close to the init routine and mark them __init. Signed-off-by: Thomas Gleixner Cc: ravi.v.shankar@intel.com Cc: tony.luck@intel.com Cc: fenghua.yu@intel.com Cc: vikas.shivappa@intel.com --- arch/x86/kernel/cpu/intel_rdt.c | 92 ++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 47 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index 2802cad0371d..d2e5f92b5428 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -168,53 +168,6 @@ static void rdt_get_cdp_l3_config(int type) r->enabled = false; } -/** - * Choose a width for the resource name - * and resource data based on the resource that has - * widest name and cbm. - */ -static void rdt_init_padding(void) -{ - struct rdt_resource *r; - int cl; - - for_each_enabled_rdt_resource(r) { - cl = strlen(r->name); - if (cl > max_name_width) - max_name_width = cl; - - if (r->data_width > max_data_width) - max_data_width = r->data_width; - } -} - -static inline bool get_rdt_resources(void) -{ - bool ret = false; - - if (cache_alloc_hsw_probe()) - return true; - - if (!boot_cpu_has(X86_FEATURE_RDT_A)) - return false; - - if (boot_cpu_has(X86_FEATURE_CAT_L3)) { - rdt_get_config(1, &rdt_resources_all[RDT_RESOURCE_L3]); - if (boot_cpu_has(X86_FEATURE_CDP_L3)) { - rdt_get_cdp_l3_config(RDT_RESOURCE_L3DATA); - rdt_get_cdp_l3_config(RDT_RESOURCE_L3CODE); - } - ret = true; - } - if (boot_cpu_has(X86_FEATURE_CAT_L2)) { - /* CPUID 0x10.2 fields are same format at 0x10.1 */ - rdt_get_config(2, &rdt_resources_all[RDT_RESOURCE_L2]); - ret = true; - } - - return ret; -} - static int get_cache_id(int cpu, int level) { struct cpu_cacheinfo *ci = get_cpu_cacheinfo(cpu); @@ -400,6 +353,51 @@ static int intel_rdt_offline_cpu(unsigned int cpu) return 0; } +/* + * Choose a width for the resource name and resource data based on the + * resource that has widest name and cbm. + */ +static __init void rdt_init_padding(void) +{ + struct rdt_resource *r; + int cl; + + for_each_enabled_rdt_resource(r) { + cl = strlen(r->name); + if (cl > max_name_width) + max_name_width = cl; + + if (r->data_width > max_data_width) + max_data_width = r->data_width; + } +} + +static __init bool get_rdt_resources(void) +{ + bool ret = false; + + if (cache_alloc_hsw_probe()) + return true; + + if (!boot_cpu_has(X86_FEATURE_RDT_A)) + return false; + + if (boot_cpu_has(X86_FEATURE_CAT_L3)) { + rdt_get_config(1, &rdt_resources_all[RDT_RESOURCE_L3]); + if (boot_cpu_has(X86_FEATURE_CDP_L3)) { + rdt_get_cdp_l3_config(RDT_RESOURCE_L3DATA); + rdt_get_cdp_l3_config(RDT_RESOURCE_L3CODE); + } + ret = true; + } + if (boot_cpu_has(X86_FEATURE_CAT_L2)) { + /* CPUID 0x10.2 fields are same format at 0x10.1 */ + rdt_get_config(2, &rdt_resources_all[RDT_RESOURCE_L2]); + ret = true; + } + return ret; +} + static int __init intel_rdt_late_init(void) { struct rdt_resource *r; -- cgit v1.2.3 From 2545e9f51ea860736c4dc1e90a44ed75e9c91e3b Mon Sep 17 00:00:00 2001 From: Vikas Shivappa Date: Fri, 7 Apr 2017 17:33:51 -0700 Subject: x86/intel_rdt: Cleanup namespace to support multiple resource types Lot of data structures and functions are named after cache specific resources(named after cbm, cache etc). In many cases other non cache resources may need to share the same data structures/functions. Generalize such naming to prepare to add more resources like memory bandwidth. Signed-off-by: Vikas Shivappa Cc: ravi.v.shankar@intel.com Cc: tony.luck@intel.com Cc: fenghua.yu@intel.com Cc: vikas.shivappa@intel.com Link: http://lkml.kernel.org/r/1491611637-20417-3-git-send-email-vikas.shivappa@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/intel_rdt.h | 22 +++++++++++----------- arch/x86/kernel/cpu/intel_rdt.c | 28 ++++++++++++++-------------- arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 16 ++++++++-------- arch/x86/kernel/cpu/intel_rdt_schemata.c | 20 ++++++++++---------- 4 files changed, 43 insertions(+), 43 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h index 611c82306fdf..55e0459b9a03 100644 --- a/arch/x86/include/asm/intel_rdt.h +++ b/arch/x86/include/asm/intel_rdt.h @@ -79,7 +79,7 @@ struct rftype { * @capable: Is this feature available on this machine * @name: Name to use in "schemata" file * @num_closid: Number of CLOSIDs available - * @max_cbm: Largest Cache Bit Mask allowed + * @default_ctrl: Specifies default cache cbm or mem b/w percent. * @data_width: Character width of data when displaying * @min_cbm_bits: Minimum number of consecutive bits to be set * in a cache bit mask @@ -97,7 +97,7 @@ struct rdt_resource { int num_closid; int cbm_len; int min_cbm_bits; - u32 max_cbm; + u32 default_ctrl; int data_width; struct list_head domains; int msr_base; @@ -111,17 +111,17 @@ struct rdt_resource { * @list: all instances of this resource * @id: unique id for this instance * @cpu_mask: which cpus share this resource - * @cbm: array of cache bit masks (indexed by CLOSID) - * @new_cbm: new cbm value to be loaded - * @have_new_cbm: did user provide new_cbm for this domain + * @ctrl_val: array of cache or mem ctrl values (indexed by CLOSID) + * @new_ctrl: new ctrl value to be loaded + * @have_new_ctrl: did user provide new_ctrl for this domain */ struct rdt_domain { struct list_head list; int id; struct cpumask cpu_mask; - u32 *cbm; - u32 new_cbm; - bool have_new_cbm; + u32 *ctrl_val; + u32 new_ctrl; + bool have_new_ctrl; }; /** @@ -172,8 +172,8 @@ union cpuid_0x10_1_eax { unsigned int full; }; -/* CPUID.(EAX=10H, ECX=ResID=1).EDX */ -union cpuid_0x10_1_edx { +/* CPUID.(EAX=10H, ECX=ResID).EDX */ +union cpuid_0x10_x_edx { struct { unsigned int cos_max:16; } split; @@ -182,7 +182,7 @@ union cpuid_0x10_1_edx { DECLARE_PER_CPU_READ_MOSTLY(int, cpu_closid); -void rdt_cbm_update(void *arg); +void rdt_ctrl_update(void *arg); struct rdtgroup *rdtgroup_kn_lock_live(struct kernfs_node *kn); void rdtgroup_kn_unlock(struct kernfs_node *kn); ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index d2e5f92b5428..92d8431fdc38 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -125,7 +125,7 @@ static inline bool cache_alloc_hsw_probe(void) r->num_closid = 4; r->cbm_len = 20; - r->max_cbm = max_cbm; + r->default_ctrl = max_cbm; r->min_cbm_bits = 2; r->capable = true; r->enabled = true; @@ -136,16 +136,16 @@ static inline bool cache_alloc_hsw_probe(void) return false; } -static void rdt_get_config(int idx, struct rdt_resource *r) +static void rdt_get_cache_config(int idx, struct rdt_resource *r) { union cpuid_0x10_1_eax eax; - union cpuid_0x10_1_edx edx; + union cpuid_0x10_x_edx edx; u32 ebx, ecx; cpuid_count(0x00000010, idx, &eax.full, &ebx, &ecx, &edx.full); r->num_closid = edx.split.cos_max + 1; r->cbm_len = eax.split.cbm_len + 1; - r->max_cbm = BIT_MASK(eax.split.cbm_len + 1) - 1; + r->default_ctrl = BIT_MASK(eax.split.cbm_len + 1) - 1; r->data_width = (r->cbm_len + 3) / 4; r->capable = true; r->enabled = true; @@ -158,7 +158,7 @@ static void rdt_get_cdp_l3_config(int type) r->num_closid = r_l3->num_closid / 2; r->cbm_len = r_l3->cbm_len; - r->max_cbm = r_l3->max_cbm; + r->default_ctrl = r_l3->default_ctrl; r->data_width = (r->cbm_len + 3) / 4; r->capable = true; /* @@ -181,7 +181,7 @@ static int get_cache_id(int cpu, int level) return -1; } -void rdt_cbm_update(void *arg) +void rdt_ctrl_update(void *arg) { struct msr_param *m = (struct msr_param *)arg; struct rdt_resource *r = m->res; @@ -202,7 +202,7 @@ found: for (i = m->low; i < m->high; i++) { int idx = cbm_idx(r, i); - wrmsrl(r->msr_base + idx, d->cbm[i]); + wrmsrl(r->msr_base + idx, d->ctrl_val[i]); } } @@ -275,8 +275,8 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r) d->id = id; - d->cbm = kmalloc_array(r->num_closid, sizeof(*d->cbm), GFP_KERNEL); - if (!d->cbm) { + d->ctrl_val = kmalloc_array(r->num_closid, sizeof(*d->ctrl_val), GFP_KERNEL); + if (!d->ctrl_val) { kfree(d); return; } @@ -284,8 +284,8 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r) for (i = 0; i < r->num_closid; i++) { int idx = cbm_idx(r, i); - d->cbm[i] = r->max_cbm; - wrmsrl(r->msr_base + idx, d->cbm[i]); + d->ctrl_val[i] = r->default_ctrl; + wrmsrl(r->msr_base + idx, d->ctrl_val[i]); } cpumask_set_cpu(cpu, &d->cpu_mask); @@ -305,7 +305,7 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r) cpumask_clear_cpu(cpu, &d->cpu_mask); if (cpumask_empty(&d->cpu_mask)) { - kfree(d->cbm); + kfree(d->ctrl_val); list_del(&d->list); kfree(d); } @@ -383,7 +383,7 @@ static __init bool get_rdt_resources(void) return false; if (boot_cpu_has(X86_FEATURE_CAT_L3)) { - rdt_get_config(1, &rdt_resources_all[RDT_RESOURCE_L3]); + rdt_get_cache_config(1, &rdt_resources_all[RDT_RESOURCE_L3]); if (boot_cpu_has(X86_FEATURE_CDP_L3)) { rdt_get_cdp_l3_config(RDT_RESOURCE_L3DATA); rdt_get_cdp_l3_config(RDT_RESOURCE_L3CODE); @@ -392,7 +392,7 @@ static __init bool get_rdt_resources(void) } if (boot_cpu_has(X86_FEATURE_CAT_L2)) { /* CPUID 0x10.2 fields are same format at 0x10.1 */ - rdt_get_config(2, &rdt_resources_all[RDT_RESOURCE_L2]); + rdt_get_cache_config(2, &rdt_resources_all[RDT_RESOURCE_L2]); ret = true; } return ret; diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c index 6870ebfcdcb3..380ee9d8ee6f 100644 --- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c @@ -519,12 +519,12 @@ static int rdt_num_closids_show(struct kernfs_open_file *of, return 0; } -static int rdt_cbm_mask_show(struct kernfs_open_file *of, +static int rdt_default_ctrl_show(struct kernfs_open_file *of, struct seq_file *seq, void *v) { struct rdt_resource *r = of->kn->parent->priv; - seq_printf(seq, "%x\n", r->max_cbm); + seq_printf(seq, "%x\n", r->default_ctrl); return 0; } @@ -551,7 +551,7 @@ static struct rftype res_info_files[] = { .name = "cbm_mask", .mode = 0444, .kf_ops = &rdtgroup_kf_single_ops, - .seq_show = rdt_cbm_mask_show, + .seq_show = rdt_default_ctrl_show, }, { .name = "min_cbm_bits", @@ -801,7 +801,7 @@ out: return dentry; } -static int reset_all_cbms(struct rdt_resource *r) +static int reset_all_ctrls(struct rdt_resource *r) { struct msr_param msr_param; cpumask_var_t cpu_mask; @@ -824,14 +824,14 @@ static int reset_all_cbms(struct rdt_resource *r) cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask); for (i = 0; i < r->num_closid; i++) - d->cbm[i] = r->max_cbm; + d->ctrl_val[i] = r->default_ctrl; } cpu = get_cpu(); /* Update CBM on this cpu if it's in cpu_mask. */ if (cpumask_test_cpu(cpu, cpu_mask)) - rdt_cbm_update(&msr_param); + rdt_ctrl_update(&msr_param); /* Update CBM on all other cpus in cpu_mask. */ - smp_call_function_many(cpu_mask, rdt_cbm_update, &msr_param, 1); + smp_call_function_many(cpu_mask, rdt_ctrl_update, &msr_param, 1); put_cpu(); free_cpumask_var(cpu_mask); @@ -917,7 +917,7 @@ static void rdt_kill_sb(struct super_block *sb) /*Put everything back to default values. */ for_each_enabled_rdt_resource(r) - reset_all_cbms(r); + reset_all_ctrls(r); cdp_disable(); rmdir_all_sub(); static_branch_disable(&rdt_enable_key); diff --git a/arch/x86/kernel/cpu/intel_rdt_schemata.c b/arch/x86/kernel/cpu/intel_rdt_schemata.c index 8594db455aa1..7695179776ba 100644 --- a/arch/x86/kernel/cpu/intel_rdt_schemata.c +++ b/arch/x86/kernel/cpu/intel_rdt_schemata.c @@ -38,7 +38,7 @@ static bool cbm_validate(unsigned long var, struct rdt_resource *r) { unsigned long first_bit, zero_bit; - if (var == 0 || var > r->max_cbm) + if (var == 0 || var > r->default_ctrl) return false; first_bit = find_first_bit(&var, r->cbm_len); @@ -61,7 +61,7 @@ static int parse_cbm(char *buf, struct rdt_resource *r, struct rdt_domain *d) unsigned long data; int ret; - if (d->have_new_cbm) + if (d->have_new_ctrl) return -EINVAL; ret = kstrtoul(buf, 16, &data); @@ -69,8 +69,8 @@ static int parse_cbm(char *buf, struct rdt_resource *r, struct rdt_domain *d) return ret; if (!cbm_validate(data, r)) return -EINVAL; - d->new_cbm = data; - d->have_new_cbm = true; + d->new_ctrl = data; + d->have_new_ctrl = true; return 0; } @@ -119,9 +119,9 @@ static int update_domains(struct rdt_resource *r, int closid) msr_param.res = r; list_for_each_entry(d, &r->domains, list) { - if (d->have_new_cbm && d->new_cbm != d->cbm[closid]) { + if (d->have_new_ctrl && d->new_ctrl != d->ctrl_val[closid]) { cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask); - d->cbm[closid] = d->new_cbm; + d->ctrl_val[closid] = d->new_ctrl; } } if (cpumask_empty(cpu_mask)) @@ -129,9 +129,9 @@ static int update_domains(struct rdt_resource *r, int closid) cpu = get_cpu(); /* Update CBM on this cpu if it's in cpu_mask. */ if (cpumask_test_cpu(cpu, cpu_mask)) - rdt_cbm_update(&msr_param); + rdt_ctrl_update(&msr_param); /* Update CBM on other cpus. */ - smp_call_function_many(cpu_mask, rdt_cbm_update, &msr_param, 1); + smp_call_function_many(cpu_mask, rdt_ctrl_update, &msr_param, 1); put_cpu(); done: @@ -164,7 +164,7 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, for_each_enabled_rdt_resource(r) list_for_each_entry(dom, &r->domains, list) - dom->have_new_cbm = false; + dom->have_new_ctrl = false; while ((tok = strsep(&buf, "\n")) != NULL) { resname = strsep(&tok, ":"); @@ -208,7 +208,7 @@ static void show_doms(struct seq_file *s, struct rdt_resource *r, int closid) if (sep) seq_puts(s, ";"); seq_printf(s, "%d=%0*x", dom->id, max_data_width, - dom->cbm[closid]); + dom->ctrl_val[closid]); sep = true; } seq_puts(s, "\n"); -- cgit v1.2.3 From d3e11b4d6ffd363747ac6e6b5522baa9ca5a20c0 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 14 Apr 2017 13:00:36 +0200 Subject: x86/intel_rdt: Move CBM specific data into a struct Memory bandwidth allocation requires different information than cache allocation. To avoid a lump of data in struct rdt_resource, move all cache related information into a seperate structure and add that to struct rdt_resource. Sanitize the data types while at it. Signed-off-by: Thomas Gleixner Cc: ravi.v.shankar@intel.com Cc: tony.luck@intel.com Cc: fenghua.yu@intel.com Cc: vikas.shivappa@intel.com --- arch/x86/include/asm/intel_rdt.h | 49 ++++++++++-------- arch/x86/kernel/cpu/intel_rdt.c | 88 +++++++++++++++++--------------- arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 2 +- arch/x86/kernel/cpu/intel_rdt_schemata.c | 9 ++-- 4 files changed, 83 insertions(+), 65 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h index 55e0459b9a03..ae61b0fd55bc 100644 --- a/arch/x86/include/asm/intel_rdt.h +++ b/arch/x86/include/asm/intel_rdt.h @@ -73,37 +73,46 @@ struct rftype { char *buf, size_t nbytes, loff_t off); }; +/** + * struct rdt_cache - Cache allocation related data + * @cbm_len: Length of the cache bit mask + * @min_cbm_bits: Minimum number of consecutive bits to be set + * @cbm_idx_mult: Multiplier of CBM index + * @cbm_idx_offset: Offset of CBM index. CBM index is computed by: + * closid * cbm_idx_multi + cbm_idx_offset + * in a cache bit mask + */ +struct rdt_cache { + unsigned int cbm_len; + unsigned int min_cbm_bits; + unsigned int cbm_idx_mult; + unsigned int cbm_idx_offset; +}; + /** * struct rdt_resource - attributes of an RDT resource - * @enabled: Is this feature enabled on this machine - * @capable: Is this feature available on this machine - * @name: Name to use in "schemata" file - * @num_closid: Number of CLOSIDs available - * @default_ctrl: Specifies default cache cbm or mem b/w percent. - * @data_width: Character width of data when displaying - * @min_cbm_bits: Minimum number of consecutive bits to be set - * in a cache bit mask - * @domains: All domains for this resource - * @msr_base: Base MSR address for CBMs - * @cache_level: Which cache level defines scope of this domain - * @cbm_idx_multi: Multiplier of CBM index - * @cbm_idx_offset: Offset of CBM index. CBM index is computed by: - * closid * cbm_idx_multi + cbm_idx_offset + * @enabled: Is this feature enabled on this machine + * @capable: Is this feature available on this machine + * @name: Name to use in "schemata" file + * @num_closid: Number of CLOSIDs available + * @cache_level: Which cache level defines scope of this resource + * @default_ctrl: Specifies default cache cbm or memory B/W percent. + * @msr_base: Base MSR address for CBMs + * @data_width: Character width of data when displaying + * @domains: All domains for this resource + * @cache: Cache allocation related data */ struct rdt_resource { bool enabled; bool capable; char *name; int num_closid; - int cbm_len; - int min_cbm_bits; + int cache_level; u32 default_ctrl; + unsigned int msr_base; int data_width; struct list_head domains; - int msr_base; - int cache_level; - int cbm_idx_multi; - int cbm_idx_offset; + struct rdt_cache cache; }; /** diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index 92d8431fdc38..8d7e050567c2 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -37,56 +37,64 @@ DEFINE_MUTEX(rdtgroup_mutex); DEFINE_PER_CPU_READ_MOSTLY(int, cpu_closid); -#define domain_init(id) LIST_HEAD_INIT(rdt_resources_all[id].domains) - /* * Used to store the max resource name width and max resource data width * to display the schemata in a tabular format */ int max_name_width, max_data_width; +#define domain_init(id) LIST_HEAD_INIT(rdt_resources_all[id].domains) + struct rdt_resource rdt_resources_all[] = { { - .name = "L3", - .domains = domain_init(RDT_RESOURCE_L3), - .msr_base = IA32_L3_CBM_BASE, - .min_cbm_bits = 1, - .cache_level = 3, - .cbm_idx_multi = 1, - .cbm_idx_offset = 0 + .name = "L3", + .domains = domain_init(RDT_RESOURCE_L3), + .msr_base = IA32_L3_CBM_BASE, + .cache_level = 3, + .cache = { + .min_cbm_bits = 1, + .cbm_idx_mult = 1, + .cbm_idx_offset = 0, + }, }, { - .name = "L3DATA", - .domains = domain_init(RDT_RESOURCE_L3DATA), - .msr_base = IA32_L3_CBM_BASE, - .min_cbm_bits = 1, - .cache_level = 3, - .cbm_idx_multi = 2, - .cbm_idx_offset = 0 + .name = "L3DATA", + .domains = domain_init(RDT_RESOURCE_L3DATA), + .msr_base = IA32_L3_CBM_BASE, + .cache_level = 3, + .cache = { + .min_cbm_bits = 1, + .cbm_idx_mult = 2, + .cbm_idx_offset = 0, + }, }, { - .name = "L3CODE", - .domains = domain_init(RDT_RESOURCE_L3CODE), - .msr_base = IA32_L3_CBM_BASE, - .min_cbm_bits = 1, - .cache_level = 3, - .cbm_idx_multi = 2, - .cbm_idx_offset = 1 + .name = "L3CODE", + .domains = domain_init(RDT_RESOURCE_L3CODE), + .msr_base = IA32_L3_CBM_BASE, + .cache_level = 3, + .cache = { + .min_cbm_bits = 1, + .cbm_idx_mult = 2, + .cbm_idx_offset = 1, + }, }, { - .name = "L2", - .domains = domain_init(RDT_RESOURCE_L2), - .msr_base = IA32_L2_CBM_BASE, - .min_cbm_bits = 1, - .cache_level = 2, - .cbm_idx_multi = 1, - .cbm_idx_offset = 0 + .name = "L2", + .domains = domain_init(RDT_RESOURCE_L2), + .msr_base = IA32_L2_CBM_BASE, + .cache_level = 2, + .cache = { + .min_cbm_bits = 1, + .cbm_idx_mult = 1, + .cbm_idx_offset = 0, + }, }, }; -static int cbm_idx(struct rdt_resource *r, int closid) +static unsigned int cbm_idx(struct rdt_resource *r, unsigned int closid) { - return closid * r->cbm_idx_multi + r->cbm_idx_offset; + return closid * r->cache.cbm_idx_mult + r->cache.cbm_idx_offset; } /* @@ -124,9 +132,9 @@ static inline bool cache_alloc_hsw_probe(void) return false; r->num_closid = 4; - r->cbm_len = 20; r->default_ctrl = max_cbm; - r->min_cbm_bits = 2; + r->cache.cbm_len = 20; + r->cache.min_cbm_bits = 2; r->capable = true; r->enabled = true; @@ -144,9 +152,9 @@ static void rdt_get_cache_config(int idx, struct rdt_resource *r) cpuid_count(0x00000010, idx, &eax.full, &ebx, &ecx, &edx.full); r->num_closid = edx.split.cos_max + 1; - r->cbm_len = eax.split.cbm_len + 1; + r->cache.cbm_len = eax.split.cbm_len + 1; r->default_ctrl = BIT_MASK(eax.split.cbm_len + 1) - 1; - r->data_width = (r->cbm_len + 3) / 4; + r->data_width = (r->cache.cbm_len + 3) / 4; r->capable = true; r->enabled = true; } @@ -157,9 +165,9 @@ static void rdt_get_cdp_l3_config(int type) struct rdt_resource *r = &rdt_resources_all[type]; r->num_closid = r_l3->num_closid / 2; - r->cbm_len = r_l3->cbm_len; + r->cache.cbm_len = r_l3->cache.cbm_len; r->default_ctrl = r_l3->default_ctrl; - r->data_width = (r->cbm_len + 3) / 4; + r->data_width = (r->cache.cbm_len + 3) / 4; r->capable = true; /* * By default, CDP is disabled. CDP can be enabled by mount parameter @@ -200,7 +208,7 @@ void rdt_ctrl_update(void *arg) found: for (i = m->low; i < m->high; i++) { - int idx = cbm_idx(r, i); + unsigned int idx = cbm_idx(r, i); wrmsrl(r->msr_base + idx, d->ctrl_val[i]); } @@ -282,7 +290,7 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r) } for (i = 0; i < r->num_closid; i++) { - int idx = cbm_idx(r, i); + unsigned int idx = cbm_idx(r, i); d->ctrl_val[i] = r->default_ctrl; wrmsrl(r->msr_base + idx, d->ctrl_val[i]); diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c index 380ee9d8ee6f..3ec230baab91 100644 --- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c @@ -534,7 +534,7 @@ static int rdt_min_cbm_bits_show(struct kernfs_open_file *of, { struct rdt_resource *r = of->kn->parent->priv; - seq_printf(seq, "%d\n", r->min_cbm_bits); + seq_printf(seq, "%u\n", r->cache.min_cbm_bits); return 0; } diff --git a/arch/x86/kernel/cpu/intel_rdt_schemata.c b/arch/x86/kernel/cpu/intel_rdt_schemata.c index 7695179776ba..5097ac65d002 100644 --- a/arch/x86/kernel/cpu/intel_rdt_schemata.c +++ b/arch/x86/kernel/cpu/intel_rdt_schemata.c @@ -37,17 +37,18 @@ static bool cbm_validate(unsigned long var, struct rdt_resource *r) { unsigned long first_bit, zero_bit; + unsigned int cbm_len = r->cache.cbm_len; if (var == 0 || var > r->default_ctrl) return false; - first_bit = find_first_bit(&var, r->cbm_len); - zero_bit = find_next_zero_bit(&var, r->cbm_len, first_bit); + first_bit = find_first_bit(&var, cbm_len); + zero_bit = find_next_zero_bit(&var, cbm_len, first_bit); - if (find_next_bit(&var, r->cbm_len, zero_bit) < r->cbm_len) + if (find_next_bit(&var, cbm_len, zero_bit) < cbm_len) return false; - if ((zero_bit - first_bit) < r->min_cbm_bits) + if ((zero_bit - first_bit) < r->cache.min_cbm_bits) return false; return true; } -- cgit v1.2.3 From 0921c54769bac209b302027384e9dc081198c8f5 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 14 Apr 2017 14:14:31 +0200 Subject: x86/intel_rdt: Add resource specific msr update function Updating of Cache and Memory bandwidth QOS MSRs is different. Add a function pointer to struct rdt_resource and convert the cache part over. Based on Vikas all in one patch^Wmess. Signed-off-by: Thomas Gleixner Cc: ravi.v.shankar@intel.com Cc: tony.luck@intel.com Cc: fenghua.yu@intel.com Cc: vikas.shivappa@intel.com --- arch/x86/include/asm/intel_rdt.h | 63 +++++++++++++++++---------------- arch/x86/kernel/cpu/intel_rdt.c | 75 +++++++++++++++++++++++++++------------- 2 files changed, 84 insertions(+), 54 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h index ae61b0fd55bc..51e4a1ca9551 100644 --- a/arch/x86/include/asm/intel_rdt.h +++ b/arch/x86/include/asm/intel_rdt.h @@ -73,6 +73,36 @@ struct rftype { char *buf, size_t nbytes, loff_t off); }; +/** + * struct rdt_domain - group of cpus sharing an RDT resource + * @list: all instances of this resource + * @id: unique id for this instance + * @cpu_mask: which cpus share this resource + * @ctrl_val: array of cache or mem ctrl values (indexed by CLOSID) + * @new_ctrl: new ctrl value to be loaded + * @have_new_ctrl: did user provide new_ctrl for this domain + */ +struct rdt_domain { + struct list_head list; + int id; + struct cpumask cpu_mask; + u32 *ctrl_val; + u32 new_ctrl; + bool have_new_ctrl; +}; + +/** + * struct msr_param - set a range of MSRs from a domain + * @res: The resource to use + * @low: Beginning index from base MSR + * @high: End index + */ +struct msr_param { + struct rdt_resource *res; + int low; + int high; +}; + /** * struct rdt_cache - Cache allocation related data * @cbm_len: Length of the cache bit mask @@ -98,6 +128,7 @@ struct rdt_cache { * @cache_level: Which cache level defines scope of this resource * @default_ctrl: Specifies default cache cbm or memory B/W percent. * @msr_base: Base MSR address for CBMs + * @msr_update: Function pointer to update QOS MSRs * @data_width: Character width of data when displaying * @domains: All domains for this resource * @cache: Cache allocation related data @@ -110,41 +141,13 @@ struct rdt_resource { int cache_level; u32 default_ctrl; unsigned int msr_base; + void (*msr_update) (struct rdt_domain *d, struct msr_param *m, + struct rdt_resource *r); int data_width; struct list_head domains; struct rdt_cache cache; }; -/** - * struct rdt_domain - group of cpus sharing an RDT resource - * @list: all instances of this resource - * @id: unique id for this instance - * @cpu_mask: which cpus share this resource - * @ctrl_val: array of cache or mem ctrl values (indexed by CLOSID) - * @new_ctrl: new ctrl value to be loaded - * @have_new_ctrl: did user provide new_ctrl for this domain - */ -struct rdt_domain { - struct list_head list; - int id; - struct cpumask cpu_mask; - u32 *ctrl_val; - u32 new_ctrl; - bool have_new_ctrl; -}; - -/** - * struct msr_param - set a range of MSRs from a domain - * @res: The resource to use - * @low: Beginning index from base MSR - * @high: End index - */ -struct msr_param { - struct rdt_resource *res; - int low; - int high; -}; - extern struct mutex rdtgroup_mutex; extern struct rdt_resource rdt_resources_all[]; diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index 8d7e050567c2..8486abe40c3f 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -43,6 +43,9 @@ DEFINE_PER_CPU_READ_MOSTLY(int, cpu_closid); */ int max_name_width, max_data_width; +static void +cat_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r); + #define domain_init(id) LIST_HEAD_INIT(rdt_resources_all[id].domains) struct rdt_resource rdt_resources_all[] = { @@ -50,6 +53,7 @@ struct rdt_resource rdt_resources_all[] = { .name = "L3", .domains = domain_init(RDT_RESOURCE_L3), .msr_base = IA32_L3_CBM_BASE, + .msr_update = cat_wrmsr, .cache_level = 3, .cache = { .min_cbm_bits = 1, @@ -61,6 +65,7 @@ struct rdt_resource rdt_resources_all[] = { .name = "L3DATA", .domains = domain_init(RDT_RESOURCE_L3DATA), .msr_base = IA32_L3_CBM_BASE, + .msr_update = cat_wrmsr, .cache_level = 3, .cache = { .min_cbm_bits = 1, @@ -72,6 +77,7 @@ struct rdt_resource rdt_resources_all[] = { .name = "L3CODE", .domains = domain_init(RDT_RESOURCE_L3CODE), .msr_base = IA32_L3_CBM_BASE, + .msr_update = cat_wrmsr, .cache_level = 3, .cache = { .min_cbm_bits = 1, @@ -83,6 +89,7 @@ struct rdt_resource rdt_resources_all[] = { .name = "L2", .domains = domain_init(RDT_RESOURCE_L2), .msr_base = IA32_L2_CBM_BASE, + .msr_update = cat_wrmsr, .cache_level = 2, .cache = { .min_cbm_bits = 1, @@ -189,29 +196,31 @@ static int get_cache_id(int cpu, int level) return -1; } +static void +cat_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r) +{ + unsigned int i; + + for (i = m->low; i < m->high; i++) + wrmsrl(r->msr_base + cbm_idx(r, i), d->ctrl_val[i]); +} + void rdt_ctrl_update(void *arg) { - struct msr_param *m = (struct msr_param *)arg; + struct msr_param *m = arg; struct rdt_resource *r = m->res; - int i, cpu = smp_processor_id(); + int cpu = smp_processor_id(); struct rdt_domain *d; list_for_each_entry(d, &r->domains, list) { /* Find the domain that contains this CPU */ - if (cpumask_test_cpu(cpu, &d->cpu_mask)) - goto found; + if (cpumask_test_cpu(cpu, &d->cpu_mask)) { + r->msr_update(d, m, r); + return; + } } - pr_info_once("cpu %d not found in any domain for resource %s\n", + pr_warn_once("cpu %d not found in any domain for resource %s\n", cpu, r->name); - - return; - -found: - for (i = m->low; i < m->high; i++) { - unsigned int idx = cbm_idx(r, i); - - wrmsrl(r->msr_base + idx, d->ctrl_val[i]); - } } /* @@ -247,6 +256,32 @@ static struct rdt_domain *rdt_find_domain(struct rdt_resource *r, int id, return NULL; } +static int domain_setup_ctrlval(struct rdt_resource *r, struct rdt_domain *d) +{ + struct msr_param m; + u32 *dc; + int i; + + dc = kmalloc_array(r->num_closid, sizeof(*d->ctrl_val), GFP_KERNEL); + if (!dc) + return -ENOMEM; + + d->ctrl_val = dc; + + /* + * Initialize the Control MSRs to having no control. + * For Cache Allocation: Set all bits in cbm + * For Memory Allocation: Set b/w requested to 100 + */ + for (i = 0; i < r->num_closid; i++, dc++) + *dc = r->default_ctrl; + + m.low = 0; + m.high = r->num_closid; + r->msr_update(d, &m, r); + return 0; +} + /* * domain_add_cpu - Add a cpu to a resource's domain list. * @@ -262,7 +297,7 @@ static struct rdt_domain *rdt_find_domain(struct rdt_resource *r, int id, */ static void domain_add_cpu(int cpu, struct rdt_resource *r) { - int i, id = get_cache_id(cpu, r->cache_level); + int id = get_cache_id(cpu, r->cache_level); struct list_head *add_pos = NULL; struct rdt_domain *d; @@ -283,19 +318,11 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r) d->id = id; - d->ctrl_val = kmalloc_array(r->num_closid, sizeof(*d->ctrl_val), GFP_KERNEL); - if (!d->ctrl_val) { + if (domain_setup_ctrlval(r, d)) { kfree(d); return; } - for (i = 0; i < r->num_closid; i++) { - unsigned int idx = cbm_idx(r, i); - - d->ctrl_val[i] = r->default_ctrl; - wrmsrl(r->msr_base + idx, d->ctrl_val[i]); - } - cpumask_set_cpu(cpu, &d->cpu_mask); list_add_tail(&d->list, add_pos); } -- cgit v1.2.3 From ab66a33b032eb5b8186aeaf648127bce829c9efd Mon Sep 17 00:00:00 2001 From: Vikas Shivappa Date: Fri, 7 Apr 2017 17:33:52 -0700 Subject: x86/intel_rdt/mba: Memory bandwith allocation feature detect Detect MBA feature if CPUID.(EAX=10H, ECX=0):EBX.L2[bit 3] = 1. Add supporting data structures to detect feature details which is done in later patch using CPUID with EAX=10H, ECX= 3. Signed-off-by: Vikas Shivappa Cc: ravi.v.shankar@intel.com Cc: tony.luck@intel.com Cc: fenghua.yu@intel.com Cc: vikas.shivappa@intel.com Link: http://lkml.kernel.org/r/1491611637-20417-4-git-send-email-vikas.shivappa@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/cpufeatures.h | 2 ++ arch/x86/include/asm/intel_rdt.h | 8 ++++++++ arch/x86/kernel/cpu/intel_rdt.c | 4 ++++ arch/x86/kernel/cpu/scattered.c | 1 + 4 files changed, 15 insertions(+) (limited to 'arch') diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index b04bb6dfed7f..25d7f528bd96 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -201,6 +201,8 @@ #define X86_FEATURE_AVX512_4VNNIW (7*32+16) /* AVX-512 Neural Network Instructions */ #define X86_FEATURE_AVX512_4FMAPS (7*32+17) /* AVX-512 Multiply Accumulation Single precision */ +#define X86_FEATURE_MBA ( 7*32+18) /* Memory Bandwidth Allocation */ + /* Virtualization flags: Linux defined, word 8 */ #define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */ #define X86_FEATURE_VNMI ( 8*32+ 1) /* Intel Virtual NMI */ diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h index 51e4a1ca9551..6295594bd673 100644 --- a/arch/x86/include/asm/intel_rdt.h +++ b/arch/x86/include/asm/intel_rdt.h @@ -184,6 +184,14 @@ union cpuid_0x10_1_eax { unsigned int full; }; +/* CPUID.(EAX=10H, ECX=ResID=3).EAX */ +union cpuid_0x10_3_eax { + struct { + unsigned int max_delay:12; + } split; + unsigned int full; +}; + /* CPUID.(EAX=10H, ECX=ResID).EDX */ union cpuid_0x10_x_edx { struct { diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index 8486abe40c3f..82eafd643632 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -430,6 +430,10 @@ static __init bool get_rdt_resources(void) rdt_get_cache_config(2, &rdt_resources_all[RDT_RESOURCE_L2]); ret = true; } + + if (boot_cpu_has(X86_FEATURE_MBA)) + ret = true; + return ret; } diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c index d9794060fe22..23c23508c012 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c @@ -27,6 +27,7 @@ static const struct cpuid_bit cpuid_bits[] = { { X86_FEATURE_CAT_L3, CPUID_EBX, 1, 0x00000010, 0 }, { X86_FEATURE_CAT_L2, CPUID_EBX, 2, 0x00000010, 0 }, { X86_FEATURE_CDP_L3, CPUID_ECX, 2, 0x00000010, 1 }, + { X86_FEATURE_MBA, CPUID_EBX, 3, 0x00000010, 0 }, { X86_FEATURE_HW_PSTATE, CPUID_EDX, 7, 0x80000007, 0 }, { X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 }, { X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 }, -- cgit v1.2.3 From 05b93417ce5b924c6652de19fdcc27439ab37c90 Mon Sep 17 00:00:00 2001 From: Vikas Shivappa Date: Fri, 7 Apr 2017 17:33:53 -0700 Subject: x86/intel_rdt/mba: Add primary support for Memory Bandwidth Allocation (MBA) The MBA feature details like minimum bandwidth supported, bandwidth granularity etc are obtained via executing CPUID with EAX=10H ,ECX=3. Setup and initialize the MBA specific extensions to data structures like global list of RDT resources, RDT resource structure and RDT domain structure. [ tglx: Split out the seperate structure and the CBM related parts ] Signed-off-by: Vikas Shivappa Cc: ravi.v.shankar@intel.com Cc: tony.luck@intel.com Cc: fenghua.yu@intel.com Cc: vikas.shivappa@intel.com Link: http://lkml.kernel.org/r/1491611637-20417-5-git-send-email-vikas.shivappa@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/intel_rdt.h | 24 ++++++++++- arch/x86/kernel/cpu/intel_rdt.c | 89 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 110 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h index 6295594bd673..0620fc957e59 100644 --- a/arch/x86/include/asm/intel_rdt.h +++ b/arch/x86/include/asm/intel_rdt.h @@ -12,6 +12,7 @@ #define IA32_L3_QOS_CFG 0xc81 #define IA32_L3_CBM_BASE 0xc90 #define IA32_L2_CBM_BASE 0xd10 +#define IA32_MBA_THRTL_BASE 0xd50 #define L3_QOS_CDP_ENABLE 0x01ULL @@ -119,6 +120,23 @@ struct rdt_cache { unsigned int cbm_idx_offset; }; +/** + * struct rdt_membw - Memory bandwidth allocation related data + * @max_delay: Max throttle delay. Delay is the hardware + * representation for memory bandwidth. + * @min_bw: Minimum memory bandwidth percentage user can request + * @bw_gran: Granularity at which the memory bandwidth is allocated + * @delay_linear: True if memory B/W delay is in linear scale + * @mb_map: Mapping of memory B/W percentage to memory B/W delay + */ +struct rdt_membw { + u32 max_delay; + u32 min_bw; + u32 bw_gran; + u32 delay_linear; + u32 *mb_map; +}; + /** * struct rdt_resource - attributes of an RDT resource * @enabled: Is this feature enabled on this machine @@ -145,7 +163,10 @@ struct rdt_resource { struct rdt_resource *r); int data_width; struct list_head domains; - struct rdt_cache cache; + union { + struct rdt_cache cache; + struct rdt_membw membw; + }; }; extern struct mutex rdtgroup_mutex; @@ -161,6 +182,7 @@ enum { RDT_RESOURCE_L3DATA, RDT_RESOURCE_L3CODE, RDT_RESOURCE_L2, + RDT_RESOURCE_MBA, /* Must be the last */ RDT_NUM_RESOURCES, diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index 82eafd643632..ae1aec16a674 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -32,6 +32,9 @@ #include #include +#define MAX_MBA_BW 100u +#define MBA_IS_LINEAR 0x4 + /* Mutex to protect rdtgroup access. */ DEFINE_MUTEX(rdtgroup_mutex); @@ -43,6 +46,8 @@ DEFINE_PER_CPU_READ_MOSTLY(int, cpu_closid); */ int max_name_width, max_data_width; +static void +mba_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r); static void cat_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r); @@ -97,6 +102,13 @@ struct rdt_resource rdt_resources_all[] = { .cbm_idx_offset = 0, }, }, + { + .name = "MB", + .domains = domain_init(RDT_RESOURCE_MBA), + .msr_base = IA32_MBA_THRTL_BASE, + .msr_update = mba_wrmsr, + .cache_level = 3, + }, }; static unsigned int cbm_idx(struct rdt_resource *r, unsigned int closid) @@ -151,6 +163,53 @@ static inline bool cache_alloc_hsw_probe(void) return false; } +/* + * rdt_get_mb_table() - get a mapping of bandwidth(b/w) percentage values + * exposed to user interface and the h/w understandable delay values. + * + * The non-linear delay values have the granularity of power of two + * and also the h/w does not guarantee a curve for configured delay + * values vs. actual b/w enforced. + * Hence we need a mapping that is pre calibrated so the user can + * express the memory b/w as a percentage value. + */ +static inline bool rdt_get_mb_table(struct rdt_resource *r) +{ + /* + * There are no Intel SKUs as of now to support non-linear delay. + */ + pr_info("MBA b/w map not implemented for cpu:%d, model:%d", + boot_cpu_data.x86, boot_cpu_data.x86_model); + + return false; +} + +static bool rdt_get_mem_config(struct rdt_resource *r) +{ + union cpuid_0x10_3_eax eax; + union cpuid_0x10_x_edx edx; + u32 ebx, ecx; + + cpuid_count(0x00000010, 3, &eax.full, &ebx, &ecx, &edx.full); + r->num_closid = edx.split.cos_max + 1; + r->membw.max_delay = eax.split.max_delay + 1; + r->default_ctrl = MAX_MBA_BW; + if (ecx & MBA_IS_LINEAR) { + r->membw.delay_linear = true; + r->membw.min_bw = MAX_MBA_BW - r->membw.max_delay; + r->membw.bw_gran = MAX_MBA_BW - r->membw.max_delay; + } else { + if (!rdt_get_mb_table(r)) + return false; + } + r->data_width = 3; + + r->capable = true; + r->enabled = true; + + return true; +} + static void rdt_get_cache_config(int idx, struct rdt_resource *r) { union cpuid_0x10_1_eax eax; @@ -196,6 +255,30 @@ static int get_cache_id(int cpu, int level) return -1; } +/* + * Map the memory b/w percentage value to delay values + * that can be written to QOS_MSRs. + * There are currently no SKUs which support non linear delay values. + */ +static u32 delay_bw_map(unsigned long bw, struct rdt_resource *r) +{ + if (r->membw.delay_linear) + return MAX_MBA_BW - bw; + + pr_warn_once("Non Linear delay-bw map not supported but queried\n"); + return r->default_ctrl; +} + +static void +mba_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r) +{ + unsigned int i; + + /* Write the delay values for mba. */ + for (i = m->low; i < m->high; i++) + wrmsrl(r->msr_base + i, delay_bw_map(d->ctrl_val[i], r)); +} + static void cat_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r) { @@ -431,8 +514,10 @@ static __init bool get_rdt_resources(void) ret = true; } - if (boot_cpu_has(X86_FEATURE_MBA)) - ret = true; + if (boot_cpu_has(X86_FEATURE_MBA)) { + if (rdt_get_mem_config(&rdt_resources_all[RDT_RESOURCE_MBA])) + ret = true; + } return ret; } -- cgit v1.2.3 From 6a507a6ad8a6955a7d57255377edcef576823749 Mon Sep 17 00:00:00 2001 From: Vikas Shivappa Date: Fri, 7 Apr 2017 17:33:54 -0700 Subject: x86/intel_rdt: Make information files resource specific Cache allocation and memory bandwidth allocation require different information files in the resctrl/info directory, but the current implementation does not allow to have files per resource. Add the necessary fields to the resource struct and assign the files dynamically depending on the resource type. Signed-off-by: Vikas Shivappa Cc: ravi.v.shankar@intel.com Cc: tony.luck@intel.com Cc: fenghua.yu@intel.com Cc: vikas.shivappa@intel.com Link: http://lkml.kernel.org/r/1491611637-20417-6-git-send-email-vikas.shivappa@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/intel_rdt.h | 6 ++++++ arch/x86/kernel/cpu/intel_rdt.c | 1 + arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 18 ++++++++++++++---- 3 files changed, 21 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h index 0620fc957e59..b0f0a600c739 100644 --- a/arch/x86/include/asm/intel_rdt.h +++ b/arch/x86/include/asm/intel_rdt.h @@ -150,6 +150,8 @@ struct rdt_membw { * @data_width: Character width of data when displaying * @domains: All domains for this resource * @cache: Cache allocation related data + * @info_files: resctrl info files for the resource + * @nr_info_files: Number of info files */ struct rdt_resource { bool enabled; @@ -167,8 +169,12 @@ struct rdt_resource { struct rdt_cache cache; struct rdt_membw membw; }; + struct rftype *info_files; + int nr_info_files; }; +void rdt_get_cache_infofile(struct rdt_resource *r); + extern struct mutex rdtgroup_mutex; extern struct rdt_resource rdt_resources_all[]; diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index ae1aec16a674..b387e04885be 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -221,6 +221,7 @@ static void rdt_get_cache_config(int idx, struct rdt_resource *r) r->cache.cbm_len = eax.split.cbm_len + 1; r->default_ctrl = BIT_MASK(eax.split.cbm_len + 1) - 1; r->data_width = (r->cache.cbm_len + 3) / 4; + rdt_get_cache_infofile(r); r->capable = true; r->enabled = true; } diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c index 3ec230baab91..65d957b96567 100644 --- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c @@ -540,7 +540,7 @@ static int rdt_min_cbm_bits_show(struct kernfs_open_file *of, } /* rdtgroup information files for one cache resource. */ -static struct rftype res_info_files[] = { +static struct rftype res_cache_info_files[] = { { .name = "num_closids", .mode = 0444, @@ -561,11 +561,18 @@ static struct rftype res_info_files[] = { }, }; +void rdt_get_cache_infofile(struct rdt_resource *r) +{ + r->info_files = res_cache_info_files; + r->nr_info_files = ARRAY_SIZE(res_cache_info_files); +} + static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn) { struct kernfs_node *kn_subdir; + struct rftype *res_info_files; struct rdt_resource *r; - int ret; + int ret, len; /* create the directory */ kn_info = kernfs_create_dir(parent_kn, "info", parent_kn->mode, NULL); @@ -584,8 +591,11 @@ static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn) ret = rdtgroup_kn_set_ugid(kn_subdir); if (ret) goto out_destroy; - ret = rdtgroup_add_files(kn_subdir, res_info_files, - ARRAY_SIZE(res_info_files)); + + res_info_files = r->info_files; + len = r->nr_info_files; + + ret = rdtgroup_add_files(kn_subdir, res_info_files, len); if (ret) goto out_destroy; kernfs_activate(kn_subdir); -- cgit v1.2.3 From db69ef65636e6da135680d75d8646bd7e76136bc Mon Sep 17 00:00:00 2001 From: Vikas Shivappa Date: Fri, 7 Apr 2017 17:33:55 -0700 Subject: x86/intel_rdt/mba: Add info directory files for Memory Bandwidth Allocation The files in the info directory for MBA are as follows: num_closids The maximum number of CLOSids available for MBA min_bandwidth The minimum memory bandwidth percentage value bandwidth_gran The granularity of the bandwidth control in percent for the particular CPU SKU. Intermediate values entered are rounded off to the previous control step available. Available bandwidth control steps are minimum_bandwidth + N * bandwidth_gran. delay_linear When set, the OS writes a linear percentage based value to the control MSRs ranging from minimum_bandwidth to 100 percent. This value is informational and has no influence on the values written to the schemata files. The values written to the schemata are always bandwidth percentage that is requested. Signed-off-by: Vikas Shivappa Cc: ravi.v.shankar@intel.com Cc: tony.luck@intel.com Cc: fenghua.yu@intel.com Cc: vikas.shivappa@intel.com Link: http://lkml.kernel.org/r/1491611637-20417-7-git-send-email-vikas.shivappa@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/intel_rdt.h | 1 + arch/x86/kernel/cpu/intel_rdt.c | 1 + arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 62 ++++++++++++++++++++++++++++++-- 3 files changed, 62 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h index b0f0a600c739..167fe10f00b9 100644 --- a/arch/x86/include/asm/intel_rdt.h +++ b/arch/x86/include/asm/intel_rdt.h @@ -174,6 +174,7 @@ struct rdt_resource { }; void rdt_get_cache_infofile(struct rdt_resource *r); +void rdt_get_mba_infofile(struct rdt_resource *r); extern struct mutex rdtgroup_mutex; diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index b387e04885be..438efefd6862 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -203,6 +203,7 @@ static bool rdt_get_mem_config(struct rdt_resource *r) return false; } r->data_width = 3; + rdt_get_mba_infofile(r); r->capable = true; r->enabled = true; diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c index 65d957b96567..f5af0cc7eb0d 100644 --- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c @@ -515,7 +515,6 @@ static int rdt_num_closids_show(struct kernfs_open_file *of, struct rdt_resource *r = of->kn->parent->priv; seq_printf(seq, "%d\n", r->num_closid); - return 0; } @@ -525,7 +524,6 @@ static int rdt_default_ctrl_show(struct kernfs_open_file *of, struct rdt_resource *r = of->kn->parent->priv; seq_printf(seq, "%x\n", r->default_ctrl); - return 0; } @@ -535,7 +533,33 @@ static int rdt_min_cbm_bits_show(struct kernfs_open_file *of, struct rdt_resource *r = of->kn->parent->priv; seq_printf(seq, "%u\n", r->cache.min_cbm_bits); + return 0; +} + +static int rdt_min_bw_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) +{ + struct rdt_resource *r = of->kn->parent->priv; + seq_printf(seq, "%u\n", r->membw.min_bw); + return 0; +} + +static int rdt_bw_gran_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) +{ + struct rdt_resource *r = of->kn->parent->priv; + + seq_printf(seq, "%u\n", r->membw.bw_gran); + return 0; +} + +static int rdt_delay_linear_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) +{ + struct rdt_resource *r = of->kn->parent->priv; + + seq_printf(seq, "%u\n", r->membw.delay_linear); return 0; } @@ -561,6 +585,40 @@ static struct rftype res_cache_info_files[] = { }, }; +/* rdtgroup information files for memory bandwidth. */ +static struct rftype res_mba_info_files[] = { + { + .name = "num_closids", + .mode = 0444, + .kf_ops = &rdtgroup_kf_single_ops, + .seq_show = rdt_num_closids_show, + }, + { + .name = "min_bandwidth", + .mode = 0444, + .kf_ops = &rdtgroup_kf_single_ops, + .seq_show = rdt_min_bw_show, + }, + { + .name = "bandwidth_gran", + .mode = 0444, + .kf_ops = &rdtgroup_kf_single_ops, + .seq_show = rdt_bw_gran_show, + }, + { + .name = "delay_linear", + .mode = 0444, + .kf_ops = &rdtgroup_kf_single_ops, + .seq_show = rdt_delay_linear_show, + }, +}; + +void rdt_get_mba_infofile(struct rdt_resource *r) +{ + r->info_files = res_mba_info_files; + r->nr_info_files = ARRAY_SIZE(res_mba_info_files); +} + void rdt_get_cache_infofile(struct rdt_resource *r) { r->info_files = res_cache_info_files; -- cgit v1.2.3 From c6ea67de52c29a8b45e5fc7569fc4336bfd557b0 Mon Sep 17 00:00:00 2001 From: Vikas Shivappa Date: Fri, 7 Apr 2017 17:33:56 -0700 Subject: x86/intel_rdt: Make schemata file parsers resource specific The schemata files are the user space interface to update resource controls. The parser is hardwired to support only cache resources, which do not fit the requirements of memory resources. Add a function pointer for a parser to the struct rdt_resource and switch the cache parsing over. [ tglx: Massaged changelog ] Signed-off-by: Vikas Shivappa Cc: ravi.v.shankar@intel.com Cc: tony.luck@intel.com Cc: fenghua.yu@intel.com Cc: vikas.shivappa@intel.com Link: http://lkml.kernel.org/r/1491611637-20417-8-git-send-email-vikas.shivappa@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/intel_rdt.h | 6 ++++++ arch/x86/kernel/cpu/intel_rdt.c | 8 ++++++++ arch/x86/kernel/cpu/intel_rdt_schemata.c | 31 +++++++++++++++++-------------- 3 files changed, 31 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h index 167fe10f00b9..4a9005766d96 100644 --- a/arch/x86/include/asm/intel_rdt.h +++ b/arch/x86/include/asm/intel_rdt.h @@ -152,6 +152,8 @@ struct rdt_membw { * @cache: Cache allocation related data * @info_files: resctrl info files for the resource * @nr_info_files: Number of info files + * @format_str: Per resource format string to show domain value + * @parse_ctrlval: Per resource function pointer to parse control values */ struct rdt_resource { bool enabled; @@ -171,10 +173,14 @@ struct rdt_resource { }; struct rftype *info_files; int nr_info_files; + const char *format_str; + int (*parse_ctrlval) (char *buf, struct rdt_resource *r, + struct rdt_domain *d); }; void rdt_get_cache_infofile(struct rdt_resource *r); void rdt_get_mba_infofile(struct rdt_resource *r); +int parse_cbm(char *buf, struct rdt_resource *r, struct rdt_domain *d); extern struct mutex rdtgroup_mutex; diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index 438efefd6862..1e410ea6905e 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -65,6 +65,8 @@ struct rdt_resource rdt_resources_all[] = { .cbm_idx_mult = 1, .cbm_idx_offset = 0, }, + .parse_ctrlval = parse_cbm, + .format_str = "%d=%0*x", }, { .name = "L3DATA", @@ -77,6 +79,8 @@ struct rdt_resource rdt_resources_all[] = { .cbm_idx_mult = 2, .cbm_idx_offset = 0, }, + .parse_ctrlval = parse_cbm, + .format_str = "%d=%0*x", }, { .name = "L3CODE", @@ -89,6 +93,8 @@ struct rdt_resource rdt_resources_all[] = { .cbm_idx_mult = 2, .cbm_idx_offset = 1, }, + .parse_ctrlval = parse_cbm, + .format_str = "%d=%0*x", }, { .name = "L2", @@ -101,6 +107,8 @@ struct rdt_resource rdt_resources_all[] = { .cbm_idx_mult = 1, .cbm_idx_offset = 0, }, + .parse_ctrlval = parse_cbm, + .format_str = "%d=%0*x", }, { .name = "MB", diff --git a/arch/x86/kernel/cpu/intel_rdt_schemata.c b/arch/x86/kernel/cpu/intel_rdt_schemata.c index 5097ac65d002..c72c9cc17aac 100644 --- a/arch/x86/kernel/cpu/intel_rdt_schemata.c +++ b/arch/x86/kernel/cpu/intel_rdt_schemata.c @@ -34,22 +34,29 @@ * are allowed (e.g. FFFFH, 0FF0H, 003CH, etc.). * Additionally Haswell requires at least two bits set. */ -static bool cbm_validate(unsigned long var, struct rdt_resource *r) +static bool cbm_validate(char *buf, unsigned long *data, struct rdt_resource *r) { - unsigned long first_bit, zero_bit; + unsigned long first_bit, zero_bit, val; unsigned int cbm_len = r->cache.cbm_len; + int ret; + + ret = kstrtoul(buf, 16, &val); + if (ret) + return false; - if (var == 0 || var > r->default_ctrl) + if (val == 0 || val > r->default_ctrl) return false; - first_bit = find_first_bit(&var, cbm_len); - zero_bit = find_next_zero_bit(&var, cbm_len, first_bit); + first_bit = find_first_bit(&val, cbm_len); + zero_bit = find_next_zero_bit(&val, cbm_len, first_bit); - if (find_next_bit(&var, cbm_len, zero_bit) < cbm_len) + if (find_next_bit(&val, cbm_len, zero_bit) < cbm_len) return false; if ((zero_bit - first_bit) < r->cache.min_cbm_bits) return false; + + *data = val; return true; } @@ -57,18 +64,14 @@ static bool cbm_validate(unsigned long var, struct rdt_resource *r) * Read one cache bit mask (hex). Check that it is valid for the current * resource type. */ -static int parse_cbm(char *buf, struct rdt_resource *r, struct rdt_domain *d) +int parse_cbm(char *buf, struct rdt_resource *r, struct rdt_domain *d) { unsigned long data; - int ret; if (d->have_new_ctrl) return -EINVAL; - ret = kstrtoul(buf, 16, &data); - if (ret) - return ret; - if (!cbm_validate(data, r)) + if(!cbm_validate(buf, &data, r)) return -EINVAL; d->new_ctrl = data; d->have_new_ctrl = true; @@ -97,7 +100,7 @@ next: return -EINVAL; list_for_each_entry(d, &r->domains, list) { if (d->id == dom_id) { - if (parse_cbm(dom, r, d)) + if (r->parse_ctrlval(dom, r, d)) return -EINVAL; goto next; } @@ -208,7 +211,7 @@ static void show_doms(struct seq_file *s, struct rdt_resource *r, int closid) list_for_each_entry(dom, &r->domains, list) { if (sep) seq_puts(s, ";"); - seq_printf(s, "%d=%0*x", dom->id, max_data_width, + seq_printf(s, r->format_str, dom->id, max_data_width, dom->ctrl_val[closid]); sep = true; } -- cgit v1.2.3 From 64e8ed3d4a6dcd6139a869a3e760e625cb0d3022 Mon Sep 17 00:00:00 2001 From: Vikas Shivappa Date: Fri, 7 Apr 2017 17:33:57 -0700 Subject: x86/intel_rdt/mba: Add schemata file support for MBA Add support to update the MBA bandwidth values for the domains via the schemata file. - Verify that the bandwidth value is valid - Round to the next control step depending on the bandwidth granularity of the hardware - Convert the bandwidth to delay values and write the delay values to the corresponding domain PQOS_MSRs. [ tglx: Massaged changelog ] Signed-off-by: Vikas Shivappa Cc: ravi.v.shankar@intel.com Cc: tony.luck@intel.com Cc: fenghua.yu@intel.com Cc: vikas.shivappa@intel.com Link: http://lkml.kernel.org/r/1491611637-20417-9-git-send-email-vikas.shivappa@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/intel_rdt.h | 1 + arch/x86/kernel/cpu/intel_rdt.c | 2 ++ arch/x86/kernel/cpu/intel_rdt_schemata.c | 43 ++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) (limited to 'arch') diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h index 4a9005766d96..bd184e1fd207 100644 --- a/arch/x86/include/asm/intel_rdt.h +++ b/arch/x86/include/asm/intel_rdt.h @@ -181,6 +181,7 @@ struct rdt_resource { void rdt_get_cache_infofile(struct rdt_resource *r); void rdt_get_mba_infofile(struct rdt_resource *r); int parse_cbm(char *buf, struct rdt_resource *r, struct rdt_domain *d); +int parse_bw(char *buf, struct rdt_resource *r, struct rdt_domain *d); extern struct mutex rdtgroup_mutex; diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index 1e410ea6905e..731f70ae57d0 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -116,6 +116,8 @@ struct rdt_resource rdt_resources_all[] = { .msr_base = IA32_MBA_THRTL_BASE, .msr_update = mba_wrmsr, .cache_level = 3, + .parse_ctrlval = parse_bw, + .format_str = "%d=%*d", }, }; diff --git a/arch/x86/kernel/cpu/intel_rdt_schemata.c b/arch/x86/kernel/cpu/intel_rdt_schemata.c index c72c9cc17aac..9467a00c947b 100644 --- a/arch/x86/kernel/cpu/intel_rdt_schemata.c +++ b/arch/x86/kernel/cpu/intel_rdt_schemata.c @@ -28,6 +28,49 @@ #include #include +/* + * Check whether MBA bandwidth percentage value is correct. The value is + * checked against the minimum and max bandwidth values specified by the + * hardware. The allocated bandwidth percentage is rounded to the next + * control step available on the hardware. + */ +static bool bw_validate(char *buf, unsigned long *data, struct rdt_resource *r) +{ + unsigned long bw; + int ret; + + /* + * Only linear delay values is supported for current Intel SKUs. + */ + if (!r->membw.delay_linear) + return false; + + ret = kstrtoul(buf, 10, &bw); + if (ret) + return false; + + if (bw < r->membw.min_bw || bw > r->default_ctrl) + return false; + + *data = roundup(bw, (unsigned long)r->membw.bw_gran); + return true; +} + +int parse_bw(char *buf, struct rdt_resource *r, struct rdt_domain *d) +{ + unsigned long data; + + if (d->have_new_ctrl) + return -EINVAL; + + if (!bw_validate(buf, &data, r)) + return -EINVAL; + d->new_ctrl = data; + d->have_new_ctrl = true; + + return 0; +} + /* * Check whether a cache bit mask is valid. The SDM says: * Please note that all (and only) contiguous '1' combinations -- cgit v1.2.3 From c238f2343441e3995d2d4e993de42b072d005f4a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 16 Mar 2017 17:50:45 +0200 Subject: x86/cpu: Keep model defines sorted by model number For better maintenance keep it sorted by numeric model ID. Add new lines to seperate model groups. Signed-off-by: Andy Shevchenko Cc: Dave Hansen Link: http://lkml.kernel.org/r/20170316155045.50389-1-andriy.shevchenko@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/intel-family.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/intel-family.h b/arch/x86/include/asm/intel-family.h index 9814db42b790..75b748a1deb8 100644 --- a/arch/x86/include/asm/intel-family.h +++ b/arch/x86/include/asm/intel-family.h @@ -12,6 +12,7 @@ */ #define INTEL_FAM6_CORE_YONAH 0x0E + #define INTEL_FAM6_CORE2_MEROM 0x0F #define INTEL_FAM6_CORE2_MEROM_L 0x16 #define INTEL_FAM6_CORE2_PENRYN 0x17 @@ -21,6 +22,7 @@ #define INTEL_FAM6_NEHALEM_G 0x1F /* Auburndale / Havendale */ #define INTEL_FAM6_NEHALEM_EP 0x1A #define INTEL_FAM6_NEHALEM_EX 0x2E + #define INTEL_FAM6_WESTMERE 0x25 #define INTEL_FAM6_WESTMERE_EP 0x2C #define INTEL_FAM6_WESTMERE_EX 0x2F @@ -36,9 +38,9 @@ #define INTEL_FAM6_HASWELL_GT3E 0x46 #define INTEL_FAM6_BROADWELL_CORE 0x3D -#define INTEL_FAM6_BROADWELL_XEON_D 0x56 #define INTEL_FAM6_BROADWELL_GT3E 0x47 #define INTEL_FAM6_BROADWELL_X 0x4F +#define INTEL_FAM6_BROADWELL_XEON_D 0x56 #define INTEL_FAM6_SKYLAKE_MOBILE 0x4E #define INTEL_FAM6_SKYLAKE_DESKTOP 0x5E @@ -59,8 +61,8 @@ #define INTEL_FAM6_ATOM_MERRIFIELD 0x4A /* Tangier */ #define INTEL_FAM6_ATOM_MOOREFIELD 0x5A /* Anniedale */ #define INTEL_FAM6_ATOM_GOLDMONT 0x5C -#define INTEL_FAM6_ATOM_GEMINI_LAKE 0x7A #define INTEL_FAM6_ATOM_DENVERTON 0x5F /* Goldmont Microserver */ +#define INTEL_FAM6_ATOM_GEMINI_LAKE 0x7A /* Xeon Phi */ -- cgit v1.2.3 From a83827d04f081b1a73845553c7f60ab9cfd13767 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 17 Apr 2017 09:57:10 +0200 Subject: x86/intel_rdt: Get rid of anon union gcc-4.4.3 fails to statically initialize members of a anon union. See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=10676 The storage saving is not really worth it and aside of that it will catch usage of the cache member for bandwidth and vice versa easier. Fixes: 05b93417ce5b ("x86/intel_rdt/mba: Add primary support for Memory Bandwidth Allocation (MBA)") Reported-by: Fengguang Wu Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/intel_rdt.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h index bd184e1fd207..597dc4995678 100644 --- a/arch/x86/include/asm/intel_rdt.h +++ b/arch/x86/include/asm/intel_rdt.h @@ -167,10 +167,8 @@ struct rdt_resource { struct rdt_resource *r); int data_width; struct list_head domains; - union { - struct rdt_cache cache; - struct rdt_membw membw; - }; + struct rdt_cache cache; + struct rdt_membw membw; struct rftype *info_files; int nr_info_files; const char *format_str; -- cgit v1.2.3 From adcbdd70309dba5a12a9d8158deb6a62a6d5fc98 Mon Sep 17 00:00:00 2001 From: Vikas Shivappa Date: Wed, 19 Apr 2017 16:50:02 -0700 Subject: x86/intel_rdt: Fix padding when resource is enabled via mount Currently max width of 'resource name' and 'resource data' is being initialized based on 'enabled resources' during boot. But the mount can enable different capable resources at a later time which upsets the tabular format of schemata. Fix this to be based on 'all capable' resources. Signed-off-by: Vikas Shivappa Tested-by: Prakhya, Sai Praneeth Cc: fenghua.yu@intel.com Cc: tony.luck@intel.com Cc: ravi.v.shankar@intel.com Cc: vikas.shivappa@intel.com Link: http://lkml.kernel.org/r/1492645804-17465-2-git-send-email-vikas.shivappa@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/cpu/intel_rdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index 731f70ae57d0..5b366462f579 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -492,7 +492,7 @@ static __init void rdt_init_padding(void) struct rdt_resource *r; int cl; - for_each_enabled_rdt_resource(r) { + for_each_capable_rdt_resource(r) { cl = strlen(r->name); if (cl > max_name_width) max_name_width = cl; -- cgit v1.2.3 From 634b0e0491d6f6e882b922eb41c278d01a743bab Mon Sep 17 00:00:00 2001 From: Vikas Shivappa Date: Wed, 19 Apr 2017 16:50:03 -0700 Subject: x86/intel_rdt: Trim whitespace while parsing schemata input Schemata is displayed in tabular format which introduces some whitespace to show data in a tabular format. Writing back the same data fails as the parser does not handle the whitespace. Trim the leading and trailing whitespace before parsing. Reported-by: Prakhya, Sai Praneeth Signed-off-by: Vikas Shivappa Tested-by: Prakhya, Sai Praneeth Cc: fenghua.yu@intel.com Cc: tony.luck@intel.com Cc: ravi.v.shankar@intel.com Cc: vikas.shivappa@intel.com Link: http://lkml.kernel.org/r/1492645804-17465-3-git-send-email-vikas.shivappa@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/cpu/intel_rdt_schemata.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/intel_rdt_schemata.c b/arch/x86/kernel/cpu/intel_rdt_schemata.c index 9467a00c947b..e64b2cf1c428 100644 --- a/arch/x86/kernel/cpu/intel_rdt_schemata.c +++ b/arch/x86/kernel/cpu/intel_rdt_schemata.c @@ -141,6 +141,7 @@ next: id = strsep(&dom, "="); if (!dom || kstrtoul(id, 10, &dom_id)) return -EINVAL; + dom = strim(dom); list_for_each_entry(d, &r->domains, list) { if (d->id == dom_id) { if (r->parse_ctrlval(dom, r, d)) @@ -214,7 +215,7 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, dom->have_new_ctrl = false; while ((tok = strsep(&buf, "\n")) != NULL) { - resname = strsep(&tok, ":"); + resname = strim(strsep(&tok, ":")); if (!tok) { ret = -EINVAL; goto out; -- cgit v1.2.3 From 4797b7dfdfcf457075c36743d71e2b0feeaaa20f Mon Sep 17 00:00:00 2001 From: Vikas Shivappa Date: Wed, 19 Apr 2017 16:50:04 -0700 Subject: x86/intel_rdt: Return error for incorrect resource names in schemata When schemata parses the resource names it does not return an error if it detects incorrect resource names and fails quietly. This happens because for_each_enabled_rdt_resource(r) leaves "r" pointing beyond the end of the rdt_resources_all[] array, and the check for !r->name results in an out of bounds access. Split the resource parsing part into a helper function to avoid the issue. [ tglx: Made it readable by splitting the parser loop out into a function ] Reported-by: Prakhya, Sai Praneeth Signed-off-by: Vikas Shivappa Tested-by: Prakhya, Sai Praneeth Cc: fenghua.yu@intel.com Cc: tony.luck@intel.com Cc: ravi.v.shankar@intel.com Cc: vikas.shivappa@intel.com Link: http://lkml.kernel.org/r/1492645804-17465-4-git-send-email-vikas.shivappa@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/cpu/intel_rdt_schemata.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/intel_rdt_schemata.c b/arch/x86/kernel/cpu/intel_rdt_schemata.c index e64b2cf1c428..406d7a6532f9 100644 --- a/arch/x86/kernel/cpu/intel_rdt_schemata.c +++ b/arch/x86/kernel/cpu/intel_rdt_schemata.c @@ -188,6 +188,17 @@ done: return 0; } +static int rdtgroup_parse_resource(char *resname, char *tok, int closid) +{ + struct rdt_resource *r; + + for_each_enabled_rdt_resource(r) { + if (!strcmp(resname, r->name) && closid < r->num_closid) + return parse_line(tok, r); + } + return -EINVAL; +} + ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, char *buf, size_t nbytes, loff_t off) { @@ -210,9 +221,10 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, closid = rdtgrp->closid; - for_each_enabled_rdt_resource(r) + for_each_enabled_rdt_resource(r) { list_for_each_entry(dom, &r->domains, list) dom->have_new_ctrl = false; + } while ((tok = strsep(&buf, "\n")) != NULL) { resname = strim(strsep(&tok, ":")); @@ -220,19 +232,9 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, ret = -EINVAL; goto out; } - for_each_enabled_rdt_resource(r) { - if (!strcmp(resname, r->name) && - closid < r->num_closid) { - ret = parse_line(tok, r); - if (ret) - goto out; - break; - } - } - if (!r->name) { - ret = -EINVAL; + ret = rdtgroup_parse_resource(resname, tok, closid); + if (ret) goto out; - } } for_each_enabled_rdt_resource(r) { -- cgit v1.2.3