diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index f12bb91b8c667fcd51a2acf9756761a70d9c093c..4c17a7060dfdb7d161f3dc83ac9e9a5d123c40a5 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -420,6 +420,8 @@ static int domain_setup_ctrlval(struct rdt_resource *r, struct rdt_domain *d) static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d) { + size_t tsize; + if (is_llc_occupancy_enabled()) { d->rmid_busy_llc = kcalloc(BITS_TO_LONGS(r->num_rmid), sizeof(unsigned long), @@ -427,6 +429,23 @@ static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d) if (!d->rmid_busy_llc) return -ENOMEM; } + if (is_mbm_total_enabled()) { + tsize = sizeof(*d->mbm_total); + d->mbm_total = kcalloc(r->num_rmid, tsize, GFP_KERNEL); + if (!d->mbm_total) { + kfree(d->rmid_busy_llc); + return -ENOMEM; + } + } + if (is_mbm_local_enabled()) { + tsize = sizeof(*d->mbm_local); + d->mbm_local = kcalloc(r->num_rmid, tsize, GFP_KERNEL); + if (!d->mbm_local) { + kfree(d->rmid_busy_llc); + kfree(d->mbm_total); + return -ENOMEM; + } + } return 0; } @@ -466,6 +485,7 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r) return; d->id = id; + cpumask_set_cpu(cpu, &d->cpu_mask); if (r->alloc_capable && domain_setup_ctrlval(r, d)) { kfree(d); @@ -477,7 +497,6 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r) return; } - cpumask_set_cpu(cpu, &d->cpu_mask); list_add_tail(&d->list, add_pos); /* @@ -509,6 +528,8 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r) rmdir_mondata_subdir_allrdtgrp(r, d->id); kfree(d->ctrl_val); kfree(d->rmid_busy_llc); + kfree(d->mbm_total); + kfree(d->mbm_local); list_del(&d->list); kfree(d); } diff --git a/arch/x86/kernel/cpu/intel_rdt.h b/arch/x86/kernel/cpu/intel_rdt.h index 2660d15d17123258ba724d0128a36034e6f2a428..2137d5e5580322171c91078db08f07dec22763d2 100644 --- a/arch/x86/kernel/cpu/intel_rdt.h +++ b/arch/x86/kernel/cpu/intel_rdt.h @@ -19,6 +19,9 @@ #define QOS_L3_OCCUP_EVENT_ID 0x01 #define QOS_L3_MBM_TOTAL_EVENT_ID 0x02 #define QOS_L3_MBM_LOCAL_EVENT_ID 0x03 + +#define MBM_CNTR_WIDTH 24 + #define RMID_VAL_ERROR BIT_ULL(63) #define RMID_VAL_UNAVAIL BIT_ULL(62) @@ -50,6 +53,7 @@ union mon_data_bits { struct rmid_read { struct rdtgroup *rgrp; + struct rdt_domain *d; int evtid; u64 val; }; @@ -159,6 +163,16 @@ struct rftype { char *buf, size_t nbytes, loff_t off); }; +/** + * struct mbm_state - status for each MBM counter in each domain + * @chunks: Total data moved (multiply by rdt_group.mon_scale to get bytes) + * @prev_msr Value of IA32_QM_CTR for this RMID last time we read it + */ +struct mbm_state { + u64 chunks; + u64 prev_msr; +}; + /** * struct rdt_domain - group of cpus sharing an RDT resource * @list: all instances of this resource @@ -166,6 +180,8 @@ struct rftype { * @cpu_mask: which cpus share this resource * @rmid_busy_llc: * bitmap of which limbo RMIDs are above threshold + * @mbm_total: saved state for MBM total bandwidth + * @mbm_local: saved state for MBM local bandwidth * @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 @@ -175,6 +191,8 @@ struct rdt_domain { int id; struct cpumask cpu_mask; unsigned long *rmid_busy_llc; + struct mbm_state *mbm_total; + struct mbm_state *mbm_local; u32 *ctrl_val; u32 new_ctrl; bool have_new_ctrl; @@ -230,6 +248,21 @@ static inline bool is_llc_occupancy_enabled(void) return (rdt_mon_features & (1 << QOS_L3_OCCUP_EVENT_ID)); } +static inline bool is_mbm_total_enabled(void) +{ + return (rdt_mon_features & (1 << QOS_L3_MBM_TOTAL_EVENT_ID)); +} + +static inline bool is_mbm_local_enabled(void) +{ + return (rdt_mon_features & (1 << QOS_L3_MBM_LOCAL_EVENT_ID)); +} + +static inline bool is_mbm_enabled(void) +{ + return (is_mbm_total_enabled() || is_mbm_local_enabled()); +} + /** * struct rdt_resource - attributes of an RDT resource * @rid: The index of the resource diff --git a/arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c b/arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c index f44e77dc568b31e87a5ae51476ac5353d1bbc862..cf8e2c776440d7a75076f42ed893722f21a1174f 100644 --- a/arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c +++ b/arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c @@ -294,6 +294,7 @@ void mon_event_read(struct rmid_read *rr, struct rdt_domain *d, */ rr->rgrp = rdtgrp; rr->evtid = evtid; + rr->d = d; rr->val = 0; smp_call_function_any(&d->cpu_mask, mon_event_count, rr, 1); diff --git a/arch/x86/kernel/cpu/intel_rdt_monitor.c b/arch/x86/kernel/cpu/intel_rdt_monitor.c index 6ae5cf58e50aae962fa37a3ff2df90fa204f4ffd..ef0358b591022c990a7eba464cc379e69fcb06f1 100644 --- a/arch/x86/kernel/cpu/intel_rdt_monitor.c +++ b/arch/x86/kernel/cpu/intel_rdt_monitor.c @@ -296,7 +296,8 @@ void free_rmid(u32 rmid) static int __mon_event_count(u32 rmid, struct rmid_read *rr) { - u64 tval; + u64 chunks, shift, tval; + struct mbm_state *m; tval = __rmid_read(rmid, rr->evtid); if (tval & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL)) { @@ -307,6 +308,12 @@ static int __mon_event_count(u32 rmid, struct rmid_read *rr) case QOS_L3_OCCUP_EVENT_ID: rr->val += tval; return 0; + case QOS_L3_MBM_TOTAL_EVENT_ID: + m = &rr->d->mbm_total[rmid]; + break; + case QOS_L3_MBM_LOCAL_EVENT_ID: + m = &rr->d->mbm_local[rmid]; + break; default: /* * Code would never reach here because @@ -314,6 +321,14 @@ static int __mon_event_count(u32 rmid, struct rmid_read *rr) */ return -EINVAL; } + shift = 64 - MBM_CNTR_WIDTH; + chunks = (tval << shift) - (m->prev_msr << shift); + chunks >>= shift; + m->chunks += chunks; + m->prev_msr = tval; + + rr->val += m->chunks; + return 0; } /* @@ -377,6 +392,16 @@ static struct mon_evt llc_occupancy_event = { .evtid = QOS_L3_OCCUP_EVENT_ID, }; +static struct mon_evt mbm_total_event = { + .name = "mbm_total_bytes", + .evtid = QOS_L3_MBM_TOTAL_EVENT_ID, +}; + +static struct mon_evt mbm_local_event = { + .name = "mbm_local_bytes", + .evtid = QOS_L3_MBM_LOCAL_EVENT_ID, +}; + /* * Initialize the event list for the resource. * @@ -390,6 +415,10 @@ static void l3_mon_evt_init(struct rdt_resource *r) if (is_llc_occupancy_enabled()) list_add_tail(&llc_occupancy_event.list, &r->evt_list); + if (is_mbm_total_enabled()) + list_add_tail(&mbm_total_event.list, &r->evt_list); + if (is_mbm_local_enabled()) + list_add_tail(&mbm_local_event.list, &r->evt_list); } int rdt_get_mon_l3_config(struct rdt_resource *r)