aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/cpu/intel_rdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/cpu/intel_rdt.c')
-rw-r--r--arch/x86/kernel/cpu/intel_rdt.c375
1 files changed, 314 insertions, 61 deletions
diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c
index 5b366462f579..cd5fc61ba450 100644
--- a/arch/x86/kernel/cpu/intel_rdt.c
+++ b/arch/x86/kernel/cpu/intel_rdt.c
@@ -30,7 +30,8 @@
30#include <linux/cpuhotplug.h> 30#include <linux/cpuhotplug.h>
31 31
32#include <asm/intel-family.h> 32#include <asm/intel-family.h>
33#include <asm/intel_rdt.h> 33#include <asm/intel_rdt_sched.h>
34#include "intel_rdt.h"
34 35
35#define MAX_MBA_BW 100u 36#define MAX_MBA_BW 100u
36#define MBA_IS_LINEAR 0x4 37#define MBA_IS_LINEAR 0x4
@@ -38,7 +39,13 @@
38/* Mutex to protect rdtgroup access. */ 39/* Mutex to protect rdtgroup access. */
39DEFINE_MUTEX(rdtgroup_mutex); 40DEFINE_MUTEX(rdtgroup_mutex);
40 41
41DEFINE_PER_CPU_READ_MOSTLY(int, cpu_closid); 42/*
43 * The cached intel_pqr_state is strictly per CPU and can never be
44 * updated from a remote CPU. Functions which modify the state
45 * are called with interrupts disabled and no preemption, which
46 * is sufficient for the protection.
47 */
48DEFINE_PER_CPU(struct intel_pqr_state, pqr_state);
42 49
43/* 50/*
44 * Used to store the max resource name width and max resource data width 51 * Used to store the max resource name width and max resource data width
@@ -46,6 +53,12 @@ DEFINE_PER_CPU_READ_MOSTLY(int, cpu_closid);
46 */ 53 */
47int max_name_width, max_data_width; 54int max_name_width, max_data_width;
48 55
56/*
57 * Global boolean for rdt_alloc which is true if any
58 * resource allocation is enabled.
59 */
60bool rdt_alloc_capable;
61
49static void 62static void
50mba_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r); 63mba_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r);
51static void 64static void
@@ -54,7 +67,9 @@ cat_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r);
54#define domain_init(id) LIST_HEAD_INIT(rdt_resources_all[id].domains) 67#define domain_init(id) LIST_HEAD_INIT(rdt_resources_all[id].domains)
55 68
56struct rdt_resource rdt_resources_all[] = { 69struct rdt_resource rdt_resources_all[] = {
70 [RDT_RESOURCE_L3] =
57 { 71 {
72 .rid = RDT_RESOURCE_L3,
58 .name = "L3", 73 .name = "L3",
59 .domains = domain_init(RDT_RESOURCE_L3), 74 .domains = domain_init(RDT_RESOURCE_L3),
60 .msr_base = IA32_L3_CBM_BASE, 75 .msr_base = IA32_L3_CBM_BASE,
@@ -67,8 +82,11 @@ struct rdt_resource rdt_resources_all[] = {
67 }, 82 },
68 .parse_ctrlval = parse_cbm, 83 .parse_ctrlval = parse_cbm,
69 .format_str = "%d=%0*x", 84 .format_str = "%d=%0*x",
85 .fflags = RFTYPE_RES_CACHE,
70 }, 86 },
87 [RDT_RESOURCE_L3DATA] =
71 { 88 {
89 .rid = RDT_RESOURCE_L3DATA,
72 .name = "L3DATA", 90 .name = "L3DATA",
73 .domains = domain_init(RDT_RESOURCE_L3DATA), 91 .domains = domain_init(RDT_RESOURCE_L3DATA),
74 .msr_base = IA32_L3_CBM_BASE, 92 .msr_base = IA32_L3_CBM_BASE,
@@ -81,8 +99,11 @@ struct rdt_resource rdt_resources_all[] = {
81 }, 99 },
82 .parse_ctrlval = parse_cbm, 100 .parse_ctrlval = parse_cbm,
83 .format_str = "%d=%0*x", 101 .format_str = "%d=%0*x",
102 .fflags = RFTYPE_RES_CACHE,
84 }, 103 },
104 [RDT_RESOURCE_L3CODE] =
85 { 105 {
106 .rid = RDT_RESOURCE_L3CODE,
86 .name = "L3CODE", 107 .name = "L3CODE",
87 .domains = domain_init(RDT_RESOURCE_L3CODE), 108 .domains = domain_init(RDT_RESOURCE_L3CODE),
88 .msr_base = IA32_L3_CBM_BASE, 109 .msr_base = IA32_L3_CBM_BASE,
@@ -95,8 +116,11 @@ struct rdt_resource rdt_resources_all[] = {
95 }, 116 },
96 .parse_ctrlval = parse_cbm, 117 .parse_ctrlval = parse_cbm,
97 .format_str = "%d=%0*x", 118 .format_str = "%d=%0*x",
119 .fflags = RFTYPE_RES_CACHE,
98 }, 120 },
121 [RDT_RESOURCE_L2] =
99 { 122 {
123 .rid = RDT_RESOURCE_L2,
100 .name = "L2", 124 .name = "L2",
101 .domains = domain_init(RDT_RESOURCE_L2), 125 .domains = domain_init(RDT_RESOURCE_L2),
102 .msr_base = IA32_L2_CBM_BASE, 126 .msr_base = IA32_L2_CBM_BASE,
@@ -109,8 +133,11 @@ struct rdt_resource rdt_resources_all[] = {
109 }, 133 },
110 .parse_ctrlval = parse_cbm, 134 .parse_ctrlval = parse_cbm,
111 .format_str = "%d=%0*x", 135 .format_str = "%d=%0*x",
136 .fflags = RFTYPE_RES_CACHE,
112 }, 137 },
138 [RDT_RESOURCE_MBA] =
113 { 139 {
140 .rid = RDT_RESOURCE_MBA,
114 .name = "MB", 141 .name = "MB",
115 .domains = domain_init(RDT_RESOURCE_MBA), 142 .domains = domain_init(RDT_RESOURCE_MBA),
116 .msr_base = IA32_MBA_THRTL_BASE, 143 .msr_base = IA32_MBA_THRTL_BASE,
@@ -118,6 +145,7 @@ struct rdt_resource rdt_resources_all[] = {
118 .cache_level = 3, 145 .cache_level = 3,
119 .parse_ctrlval = parse_bw, 146 .parse_ctrlval = parse_bw,
120 .format_str = "%d=%*d", 147 .format_str = "%d=%*d",
148 .fflags = RFTYPE_RES_MB,
121 }, 149 },
122}; 150};
123 151
@@ -144,33 +172,28 @@ static unsigned int cbm_idx(struct rdt_resource *r, unsigned int closid)
144 * is always 20 on hsw server parts. The minimum cache bitmask length 172 * is always 20 on hsw server parts. The minimum cache bitmask length
145 * allowed for HSW server is always 2 bits. Hardcode all of them. 173 * allowed for HSW server is always 2 bits. Hardcode all of them.
146 */ 174 */
147static inline bool cache_alloc_hsw_probe(void) 175static inline void cache_alloc_hsw_probe(void)
148{ 176{
149 if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && 177 struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_L3];
150 boot_cpu_data.x86 == 6 && 178 u32 l, h, max_cbm = BIT_MASK(20) - 1;
151 boot_cpu_data.x86_model == INTEL_FAM6_HASWELL_X) {
152 struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_L3];
153 u32 l, h, max_cbm = BIT_MASK(20) - 1;
154
155 if (wrmsr_safe(IA32_L3_CBM_BASE, max_cbm, 0))
156 return false;
157 rdmsr(IA32_L3_CBM_BASE, l, h);
158 179
159 /* If all the bits were set in MSR, return success */ 180 if (wrmsr_safe(IA32_L3_CBM_BASE, max_cbm, 0))
160 if (l != max_cbm) 181 return;
161 return false; 182 rdmsr(IA32_L3_CBM_BASE, l, h);
162 183
163 r->num_closid = 4; 184 /* If all the bits were set in MSR, return success */
164 r->default_ctrl = max_cbm; 185 if (l != max_cbm)
165 r->cache.cbm_len = 20; 186 return;
166 r->cache.min_cbm_bits = 2;
167 r->capable = true;
168 r->enabled = true;
169 187
170 return true; 188 r->num_closid = 4;
171 } 189 r->default_ctrl = max_cbm;
190 r->cache.cbm_len = 20;
191 r->cache.shareable_bits = 0xc0000;
192 r->cache.min_cbm_bits = 2;
193 r->alloc_capable = true;
194 r->alloc_enabled = true;
172 195
173 return false; 196 rdt_alloc_capable = true;
174} 197}
175 198
176/* 199/*
@@ -213,15 +236,14 @@ static bool rdt_get_mem_config(struct rdt_resource *r)
213 return false; 236 return false;
214 } 237 }
215 r->data_width = 3; 238 r->data_width = 3;
216 rdt_get_mba_infofile(r);
217 239
218 r->capable = true; 240 r->alloc_capable = true;
219 r->enabled = true; 241 r->alloc_enabled = true;
220 242
221 return true; 243 return true;
222} 244}
223 245
224static void rdt_get_cache_config(int idx, struct rdt_resource *r) 246static void rdt_get_cache_alloc_cfg(int idx, struct rdt_resource *r)
225{ 247{
226 union cpuid_0x10_1_eax eax; 248 union cpuid_0x10_1_eax eax;
227 union cpuid_0x10_x_edx edx; 249 union cpuid_0x10_x_edx edx;
@@ -231,10 +253,10 @@ static void rdt_get_cache_config(int idx, struct rdt_resource *r)
231 r->num_closid = edx.split.cos_max + 1; 253 r->num_closid = edx.split.cos_max + 1;
232 r->cache.cbm_len = eax.split.cbm_len + 1; 254 r->cache.cbm_len = eax.split.cbm_len + 1;
233 r->default_ctrl = BIT_MASK(eax.split.cbm_len + 1) - 1; 255 r->default_ctrl = BIT_MASK(eax.split.cbm_len + 1) - 1;
256 r->cache.shareable_bits = ebx & r->default_ctrl;
234 r->data_width = (r->cache.cbm_len + 3) / 4; 257 r->data_width = (r->cache.cbm_len + 3) / 4;
235 rdt_get_cache_infofile(r); 258 r->alloc_capable = true;
236 r->capable = true; 259 r->alloc_enabled = true;
237 r->enabled = true;
238} 260}
239 261
240static void rdt_get_cdp_l3_config(int type) 262static void rdt_get_cdp_l3_config(int type)
@@ -246,12 +268,12 @@ static void rdt_get_cdp_l3_config(int type)
246 r->cache.cbm_len = r_l3->cache.cbm_len; 268 r->cache.cbm_len = r_l3->cache.cbm_len;
247 r->default_ctrl = r_l3->default_ctrl; 269 r->default_ctrl = r_l3->default_ctrl;
248 r->data_width = (r->cache.cbm_len + 3) / 4; 270 r->data_width = (r->cache.cbm_len + 3) / 4;
249 r->capable = true; 271 r->alloc_capable = true;
250 /* 272 /*
251 * By default, CDP is disabled. CDP can be enabled by mount parameter 273 * By default, CDP is disabled. CDP can be enabled by mount parameter
252 * "cdp" during resctrl file system mount time. 274 * "cdp" during resctrl file system mount time.
253 */ 275 */
254 r->enabled = false; 276 r->alloc_enabled = false;
255} 277}
256 278
257static int get_cache_id(int cpu, int level) 279static int get_cache_id(int cpu, int level)
@@ -300,6 +322,19 @@ cat_wrmsr(struct rdt_domain *d, struct msr_param *m, struct rdt_resource *r)
300 wrmsrl(r->msr_base + cbm_idx(r, i), d->ctrl_val[i]); 322 wrmsrl(r->msr_base + cbm_idx(r, i), d->ctrl_val[i]);
301} 323}
302 324
325struct rdt_domain *get_domain_from_cpu(int cpu, struct rdt_resource *r)
326{
327 struct rdt_domain *d;
328
329 list_for_each_entry(d, &r->domains, list) {
330 /* Find the domain that contains this CPU */
331 if (cpumask_test_cpu(cpu, &d->cpu_mask))
332 return d;
333 }
334
335 return NULL;
336}
337
303void rdt_ctrl_update(void *arg) 338void rdt_ctrl_update(void *arg)
304{ 339{
305 struct msr_param *m = arg; 340 struct msr_param *m = arg;
@@ -307,12 +342,10 @@ void rdt_ctrl_update(void *arg)
307 int cpu = smp_processor_id(); 342 int cpu = smp_processor_id();
308 struct rdt_domain *d; 343 struct rdt_domain *d;
309 344
310 list_for_each_entry(d, &r->domains, list) { 345 d = get_domain_from_cpu(cpu, r);
311 /* Find the domain that contains this CPU */ 346 if (d) {
312 if (cpumask_test_cpu(cpu, &d->cpu_mask)) { 347 r->msr_update(d, m, r);
313 r->msr_update(d, m, r); 348 return;
314 return;
315 }
316 } 349 }
317 pr_warn_once("cpu %d not found in any domain for resource %s\n", 350 pr_warn_once("cpu %d not found in any domain for resource %s\n",
318 cpu, r->name); 351 cpu, r->name);
@@ -326,8 +359,8 @@ void rdt_ctrl_update(void *arg)
326 * caller, return the first domain whose id is bigger than the input id. 359 * caller, return the first domain whose id is bigger than the input id.
327 * The domain list is sorted by id in ascending order. 360 * The domain list is sorted by id in ascending order.
328 */ 361 */
329static struct rdt_domain *rdt_find_domain(struct rdt_resource *r, int id, 362struct rdt_domain *rdt_find_domain(struct rdt_resource *r, int id,
330 struct list_head **pos) 363 struct list_head **pos)
331{ 364{
332 struct rdt_domain *d; 365 struct rdt_domain *d;
333 struct list_head *l; 366 struct list_head *l;
@@ -377,6 +410,44 @@ static int domain_setup_ctrlval(struct rdt_resource *r, struct rdt_domain *d)
377 return 0; 410 return 0;
378} 411}
379 412
413static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d)
414{
415 size_t tsize;
416
417 if (is_llc_occupancy_enabled()) {
418 d->rmid_busy_llc = kcalloc(BITS_TO_LONGS(r->num_rmid),
419 sizeof(unsigned long),
420 GFP_KERNEL);
421 if (!d->rmid_busy_llc)
422 return -ENOMEM;
423 INIT_DELAYED_WORK(&d->cqm_limbo, cqm_handle_limbo);
424 }
425 if (is_mbm_total_enabled()) {
426 tsize = sizeof(*d->mbm_total);
427 d->mbm_total = kcalloc(r->num_rmid, tsize, GFP_KERNEL);
428 if (!d->mbm_total) {
429 kfree(d->rmid_busy_llc);
430 return -ENOMEM;
431 }
432 }
433 if (is_mbm_local_enabled()) {
434 tsize = sizeof(*d->mbm_local);
435 d->mbm_local = kcalloc(r->num_rmid, tsize, GFP_KERNEL);
436 if (!d->mbm_local) {
437 kfree(d->rmid_busy_llc);
438 kfree(d->mbm_total);
439 return -ENOMEM;
440 }
441 }
442
443 if (is_mbm_enabled()) {
444 INIT_DELAYED_WORK(&d->mbm_over, mbm_handle_overflow);
445 mbm_setup_overflow_handler(d, MBM_OVERFLOW_INTERVAL);
446 }
447
448 return 0;
449}
450
380/* 451/*
381 * domain_add_cpu - Add a cpu to a resource's domain list. 452 * domain_add_cpu - Add a cpu to a resource's domain list.
382 * 453 *
@@ -412,14 +483,26 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r)
412 return; 483 return;
413 484
414 d->id = id; 485 d->id = id;
486 cpumask_set_cpu(cpu, &d->cpu_mask);
415 487
416 if (domain_setup_ctrlval(r, d)) { 488 if (r->alloc_capable && domain_setup_ctrlval(r, d)) {
489 kfree(d);
490 return;
491 }
492
493 if (r->mon_capable && domain_setup_mon_state(r, d)) {
417 kfree(d); 494 kfree(d);
418 return; 495 return;
419 } 496 }
420 497
421 cpumask_set_cpu(cpu, &d->cpu_mask);
422 list_add_tail(&d->list, add_pos); 498 list_add_tail(&d->list, add_pos);
499
500 /*
501 * If resctrl is mounted, add
502 * per domain monitor data directories.
503 */
504 if (static_branch_unlikely(&rdt_mon_enable_key))
505 mkdir_mondata_subdir_allrdtgrp(r, d);
423} 506}
424 507
425static void domain_remove_cpu(int cpu, struct rdt_resource *r) 508static void domain_remove_cpu(int cpu, struct rdt_resource *r)
@@ -435,19 +518,58 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r)
435 518
436 cpumask_clear_cpu(cpu, &d->cpu_mask); 519 cpumask_clear_cpu(cpu, &d->cpu_mask);
437 if (cpumask_empty(&d->cpu_mask)) { 520 if (cpumask_empty(&d->cpu_mask)) {
521 /*
522 * If resctrl is mounted, remove all the
523 * per domain monitor data directories.
524 */
525 if (static_branch_unlikely(&rdt_mon_enable_key))
526 rmdir_mondata_subdir_allrdtgrp(r, d->id);
438 kfree(d->ctrl_val); 527 kfree(d->ctrl_val);
528 kfree(d->rmid_busy_llc);
529 kfree(d->mbm_total);
530 kfree(d->mbm_local);
439 list_del(&d->list); 531 list_del(&d->list);
532 if (is_mbm_enabled())
533 cancel_delayed_work(&d->mbm_over);
534 if (is_llc_occupancy_enabled() && has_busy_rmid(r, d)) {
535 /*
536 * When a package is going down, forcefully
537 * decrement rmid->ebusy. There is no way to know
538 * that the L3 was flushed and hence may lead to
539 * incorrect counts in rare scenarios, but leaving
540 * the RMID as busy creates RMID leaks if the
541 * package never comes back.
542 */
543 __check_limbo(d, true);
544 cancel_delayed_work(&d->cqm_limbo);
545 }
546
440 kfree(d); 547 kfree(d);
548 return;
549 }
550
551 if (r == &rdt_resources_all[RDT_RESOURCE_L3]) {
552 if (is_mbm_enabled() && cpu == d->mbm_work_cpu) {
553 cancel_delayed_work(&d->mbm_over);
554 mbm_setup_overflow_handler(d, 0);
555 }
556 if (is_llc_occupancy_enabled() && cpu == d->cqm_work_cpu &&
557 has_busy_rmid(r, d)) {
558 cancel_delayed_work(&d->cqm_limbo);
559 cqm_setup_limbo_handler(d, 0);
560 }
441 } 561 }
442} 562}
443 563
444static void clear_closid(int cpu) 564static void clear_closid_rmid(int cpu)
445{ 565{
446 struct intel_pqr_state *state = this_cpu_ptr(&pqr_state); 566 struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
447 567
448 per_cpu(cpu_closid, cpu) = 0; 568 state->default_closid = 0;
449 state->closid = 0; 569 state->default_rmid = 0;
450 wrmsr(MSR_IA32_PQR_ASSOC, state->rmid, 0); 570 state->cur_closid = 0;
571 state->cur_rmid = 0;
572 wrmsr(IA32_PQR_ASSOC, 0, 0);
451} 573}
452 574
453static int intel_rdt_online_cpu(unsigned int cpu) 575static int intel_rdt_online_cpu(unsigned int cpu)
@@ -459,12 +581,23 @@ static int intel_rdt_online_cpu(unsigned int cpu)
459 domain_add_cpu(cpu, r); 581 domain_add_cpu(cpu, r);
460 /* The cpu is set in default rdtgroup after online. */ 582 /* The cpu is set in default rdtgroup after online. */
461 cpumask_set_cpu(cpu, &rdtgroup_default.cpu_mask); 583 cpumask_set_cpu(cpu, &rdtgroup_default.cpu_mask);
462 clear_closid(cpu); 584 clear_closid_rmid(cpu);
463 mutex_unlock(&rdtgroup_mutex); 585 mutex_unlock(&rdtgroup_mutex);
464 586
465 return 0; 587 return 0;
466} 588}
467 589
590static void clear_childcpus(struct rdtgroup *r, unsigned int cpu)
591{
592 struct rdtgroup *cr;
593
594 list_for_each_entry(cr, &r->mon.crdtgrp_list, mon.crdtgrp_list) {
595 if (cpumask_test_and_clear_cpu(cpu, &cr->cpu_mask)) {
596 break;
597 }
598 }
599}
600
468static int intel_rdt_offline_cpu(unsigned int cpu) 601static int intel_rdt_offline_cpu(unsigned int cpu)
469{ 602{
470 struct rdtgroup *rdtgrp; 603 struct rdtgroup *rdtgrp;
@@ -474,10 +607,12 @@ static int intel_rdt_offline_cpu(unsigned int cpu)
474 for_each_capable_rdt_resource(r) 607 for_each_capable_rdt_resource(r)
475 domain_remove_cpu(cpu, r); 608 domain_remove_cpu(cpu, r);
476 list_for_each_entry(rdtgrp, &rdt_all_groups, rdtgroup_list) { 609 list_for_each_entry(rdtgrp, &rdt_all_groups, rdtgroup_list) {
477 if (cpumask_test_and_clear_cpu(cpu, &rdtgrp->cpu_mask)) 610 if (cpumask_test_and_clear_cpu(cpu, &rdtgrp->cpu_mask)) {
611 clear_childcpus(rdtgrp, cpu);
478 break; 612 break;
613 }
479 } 614 }
480 clear_closid(cpu); 615 clear_closid_rmid(cpu);
481 mutex_unlock(&rdtgroup_mutex); 616 mutex_unlock(&rdtgroup_mutex);
482 617
483 return 0; 618 return 0;
@@ -492,7 +627,7 @@ static __init void rdt_init_padding(void)
492 struct rdt_resource *r; 627 struct rdt_resource *r;
493 int cl; 628 int cl;
494 629
495 for_each_capable_rdt_resource(r) { 630 for_each_alloc_capable_rdt_resource(r) {
496 cl = strlen(r->name); 631 cl = strlen(r->name);
497 if (cl > max_name_width) 632 if (cl > max_name_width)
498 max_name_width = cl; 633 max_name_width = cl;
@@ -502,38 +637,153 @@ static __init void rdt_init_padding(void)
502 } 637 }
503} 638}
504 639
505static __init bool get_rdt_resources(void) 640enum {
641 RDT_FLAG_CMT,
642 RDT_FLAG_MBM_TOTAL,
643 RDT_FLAG_MBM_LOCAL,
644 RDT_FLAG_L3_CAT,
645 RDT_FLAG_L3_CDP,
646 RDT_FLAG_L2_CAT,
647 RDT_FLAG_MBA,
648};
649
650#define RDT_OPT(idx, n, f) \
651[idx] = { \
652 .name = n, \
653 .flag = f \
654}
655
656struct rdt_options {
657 char *name;
658 int flag;
659 bool force_off, force_on;
660};
661
662static struct rdt_options rdt_options[] __initdata = {
663 RDT_OPT(RDT_FLAG_CMT, "cmt", X86_FEATURE_CQM_OCCUP_LLC),
664 RDT_OPT(RDT_FLAG_MBM_TOTAL, "mbmtotal", X86_FEATURE_CQM_MBM_TOTAL),
665 RDT_OPT(RDT_FLAG_MBM_LOCAL, "mbmlocal", X86_FEATURE_CQM_MBM_LOCAL),
666 RDT_OPT(RDT_FLAG_L3_CAT, "l3cat", X86_FEATURE_CAT_L3),
667 RDT_OPT(RDT_FLAG_L3_CDP, "l3cdp", X86_FEATURE_CDP_L3),
668 RDT_OPT(RDT_FLAG_L2_CAT, "l2cat", X86_FEATURE_CAT_L2),
669 RDT_OPT(RDT_FLAG_MBA, "mba", X86_FEATURE_MBA),
670};
671#define NUM_RDT_OPTIONS ARRAY_SIZE(rdt_options)
672
673static int __init set_rdt_options(char *str)
674{
675 struct rdt_options *o;
676 bool force_off;
677 char *tok;
678
679 if (*str == '=')
680 str++;
681 while ((tok = strsep(&str, ",")) != NULL) {
682 force_off = *tok == '!';
683 if (force_off)
684 tok++;
685 for (o = rdt_options; o < &rdt_options[NUM_RDT_OPTIONS]; o++) {
686 if (strcmp(tok, o->name) == 0) {
687 if (force_off)
688 o->force_off = true;
689 else
690 o->force_on = true;
691 break;
692 }
693 }
694 }
695 return 1;
696}
697__setup("rdt", set_rdt_options);
698
699static bool __init rdt_cpu_has(int flag)
700{
701 bool ret = boot_cpu_has(flag);
702 struct rdt_options *o;
703
704 if (!ret)
705 return ret;
706
707 for (o = rdt_options; o < &rdt_options[NUM_RDT_OPTIONS]; o++) {
708 if (flag == o->flag) {
709 if (o->force_off)
710 ret = false;
711 if (o->force_on)
712 ret = true;
713 break;
714 }
715 }
716 return ret;
717}
718
719static __init bool get_rdt_alloc_resources(void)
506{ 720{
507 bool ret = false; 721 bool ret = false;
508 722
509 if (cache_alloc_hsw_probe()) 723 if (rdt_alloc_capable)
510 return true; 724 return true;
511 725
512 if (!boot_cpu_has(X86_FEATURE_RDT_A)) 726 if (!boot_cpu_has(X86_FEATURE_RDT_A))
513 return false; 727 return false;
514 728
515 if (boot_cpu_has(X86_FEATURE_CAT_L3)) { 729 if (rdt_cpu_has(X86_FEATURE_CAT_L3)) {
516 rdt_get_cache_config(1, &rdt_resources_all[RDT_RESOURCE_L3]); 730 rdt_get_cache_alloc_cfg(1, &rdt_resources_all[RDT_RESOURCE_L3]);
517 if (boot_cpu_has(X86_FEATURE_CDP_L3)) { 731 if (rdt_cpu_has(X86_FEATURE_CDP_L3)) {
518 rdt_get_cdp_l3_config(RDT_RESOURCE_L3DATA); 732 rdt_get_cdp_l3_config(RDT_RESOURCE_L3DATA);
519 rdt_get_cdp_l3_config(RDT_RESOURCE_L3CODE); 733 rdt_get_cdp_l3_config(RDT_RESOURCE_L3CODE);
520 } 734 }
521 ret = true; 735 ret = true;
522 } 736 }
523 if (boot_cpu_has(X86_FEATURE_CAT_L2)) { 737 if (rdt_cpu_has(X86_FEATURE_CAT_L2)) {
524 /* CPUID 0x10.2 fields are same format at 0x10.1 */ 738 /* CPUID 0x10.2 fields are same format at 0x10.1 */
525 rdt_get_cache_config(2, &rdt_resources_all[RDT_RESOURCE_L2]); 739 rdt_get_cache_alloc_cfg(2, &rdt_resources_all[RDT_RESOURCE_L2]);
526 ret = true; 740 ret = true;
527 } 741 }
528 742
529 if (boot_cpu_has(X86_FEATURE_MBA)) { 743 if (rdt_cpu_has(X86_FEATURE_MBA)) {
530 if (rdt_get_mem_config(&rdt_resources_all[RDT_RESOURCE_MBA])) 744 if (rdt_get_mem_config(&rdt_resources_all[RDT_RESOURCE_MBA]))
531 ret = true; 745 ret = true;
532 } 746 }
533
534 return ret; 747 return ret;
535} 748}
536 749
750static __init bool get_rdt_mon_resources(void)
751{
752 if (rdt_cpu_has(X86_FEATURE_CQM_OCCUP_LLC))
753 rdt_mon_features |= (1 << QOS_L3_OCCUP_EVENT_ID);
754 if (rdt_cpu_has(X86_FEATURE_CQM_MBM_TOTAL))
755 rdt_mon_features |= (1 << QOS_L3_MBM_TOTAL_EVENT_ID);
756 if (rdt_cpu_has(X86_FEATURE_CQM_MBM_LOCAL))
757 rdt_mon_features |= (1 << QOS_L3_MBM_LOCAL_EVENT_ID);
758
759 if (!rdt_mon_features)
760 return false;
761
762 return !rdt_get_mon_l3_config(&rdt_resources_all[RDT_RESOURCE_L3]);
763}
764
765static __init void rdt_quirks(void)
766{
767 switch (boot_cpu_data.x86_model) {
768 case INTEL_FAM6_HASWELL_X:
769 if (!rdt_options[RDT_FLAG_L3_CAT].force_off)
770 cache_alloc_hsw_probe();
771 break;
772 case INTEL_FAM6_SKYLAKE_X:
773 if (boot_cpu_data.x86_mask <= 4)
774 set_rdt_options("!cmt,!mbmtotal,!mbmlocal,!l3cat");
775 }
776}
777
778static __init bool get_rdt_resources(void)
779{
780 rdt_quirks();
781 rdt_alloc_capable = get_rdt_alloc_resources();
782 rdt_mon_capable = get_rdt_mon_resources();
783
784 return (rdt_mon_capable || rdt_alloc_capable);
785}
786
537static int __init intel_rdt_late_init(void) 787static int __init intel_rdt_late_init(void)
538{ 788{
539 struct rdt_resource *r; 789 struct rdt_resource *r;
@@ -556,9 +806,12 @@ static int __init intel_rdt_late_init(void)
556 return ret; 806 return ret;
557 } 807 }
558 808
559 for_each_capable_rdt_resource(r) 809 for_each_alloc_capable_rdt_resource(r)
560 pr_info("Intel RDT %s allocation detected\n", r->name); 810 pr_info("Intel RDT %s allocation detected\n", r->name);
561 811
812 for_each_mon_capable_rdt_resource(r)
813 pr_info("Intel RDT %s monitoring detected\n", r->name);
814
562 return 0; 815 return 0;
563} 816}
564 817