summaryrefslogtreecommitdiff
path: root/fs/resctrl/ctrlmondata.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/resctrl/ctrlmondata.c')
-rw-r--r--fs/resctrl/ctrlmondata.c113
1 files changed, 99 insertions, 14 deletions
diff --git a/fs/resctrl/ctrlmondata.c b/fs/resctrl/ctrlmondata.c
index b2d178d3556e..cc4237c57cbe 100644
--- a/fs/resctrl/ctrlmondata.c
+++ b/fs/resctrl/ctrlmondata.c
@@ -17,6 +17,7 @@
#include <linux/cpu.h>
#include <linux/kernfs.h>
+#include <linux/math.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/tick.h>
@@ -551,8 +552,8 @@ struct rdt_domain_hdr *resctrl_find_domain(struct list_head *h, int id,
}
void mon_event_read(struct rmid_read *rr, struct rdt_resource *r,
- struct rdt_mon_domain *d, struct rdtgroup *rdtgrp,
- cpumask_t *cpumask, int evtid, int first)
+ struct rdt_domain_hdr *hdr, struct rdtgroup *rdtgrp,
+ cpumask_t *cpumask, struct mon_evt *evt, int first)
{
int cpu;
@@ -563,21 +564,26 @@ void mon_event_read(struct rmid_read *rr, struct rdt_resource *r,
* Setup the parameters to pass to mon_event_count() to read the data.
*/
rr->rgrp = rdtgrp;
- rr->evtid = evtid;
+ rr->evt = evt;
rr->r = r;
- rr->d = d;
+ rr->hdr = hdr;
rr->first = first;
if (resctrl_arch_mbm_cntr_assign_enabled(r) &&
- resctrl_is_mbm_event(evtid)) {
+ resctrl_is_mbm_event(evt->evtid)) {
rr->is_mbm_cntr = true;
} else {
- rr->arch_mon_ctx = resctrl_arch_mon_ctx_alloc(r, evtid);
+ rr->arch_mon_ctx = resctrl_arch_mon_ctx_alloc(r, evt->evtid);
if (IS_ERR(rr->arch_mon_ctx)) {
rr->err = -EINVAL;
return;
}
}
+ if (evt->any_cpu) {
+ mon_event_count(rr);
+ goto out_ctx_free;
+ }
+
cpu = cpumask_any_housekeeping(cpumask, RESCTRL_PICK_ANY_CPU);
/*
@@ -591,22 +597,93 @@ void mon_event_read(struct rmid_read *rr, struct rdt_resource *r,
else
smp_call_on_cpu(cpu, smp_mon_event_count, rr, false);
+out_ctx_free:
if (rr->arch_mon_ctx)
- resctrl_arch_mon_ctx_free(r, evtid, rr->arch_mon_ctx);
+ resctrl_arch_mon_ctx_free(r, evt->evtid, rr->arch_mon_ctx);
+}
+
+/*
+ * Decimal place precision to use for each number of fixed-point
+ * binary bits computed from ceil(binary_bits * log10(2)) except
+ * binary_bits == 0 which will print "value.0"
+ */
+static const unsigned int decplaces[MAX_BINARY_BITS + 1] = {
+ [0] = 1,
+ [1] = 1,
+ [2] = 1,
+ [3] = 1,
+ [4] = 2,
+ [5] = 2,
+ [6] = 2,
+ [7] = 3,
+ [8] = 3,
+ [9] = 3,
+ [10] = 4,
+ [11] = 4,
+ [12] = 4,
+ [13] = 4,
+ [14] = 5,
+ [15] = 5,
+ [16] = 5,
+ [17] = 6,
+ [18] = 6,
+ [19] = 6,
+ [20] = 7,
+ [21] = 7,
+ [22] = 7,
+ [23] = 7,
+ [24] = 8,
+ [25] = 8,
+ [26] = 8,
+ [27] = 9
+};
+
+static void print_event_value(struct seq_file *m, unsigned int binary_bits, u64 val)
+{
+ unsigned long long frac = 0;
+
+ if (binary_bits) {
+ /* Mask off the integer part of the fixed-point value. */
+ frac = val & GENMASK_ULL(binary_bits - 1, 0);
+
+ /*
+ * Multiply by 10^{desired decimal places}. The integer part of
+ * the fixed point value is now almost what is needed.
+ */
+ frac *= int_pow(10ull, decplaces[binary_bits]);
+
+ /*
+ * Round to nearest by adding a value that would be a "1" in the
+ * binary_bits + 1 place. Integer part of fixed point value is
+ * now the needed value.
+ */
+ frac += 1ull << (binary_bits - 1);
+
+ /*
+ * Extract the integer part of the value. This is the decimal
+ * representation of the original fixed-point fractional value.
+ */
+ frac >>= binary_bits;
+ }
+
+ /*
+ * "frac" is now in the range [0 .. 10^decplaces). I.e. string
+ * representation will fit into chosen number of decimal places.
+ */
+ seq_printf(m, "%llu.%0*llu\n", val >> binary_bits, decplaces[binary_bits], frac);
}
int rdtgroup_mondata_show(struct seq_file *m, void *arg)
{
struct kernfs_open_file *of = m->private;
enum resctrl_res_level resid;
- enum resctrl_event_id evtid;
struct rdt_domain_hdr *hdr;
struct rmid_read rr = {0};
- struct rdt_mon_domain *d;
struct rdtgroup *rdtgrp;
int domid, cpu, ret = 0;
struct rdt_resource *r;
struct cacheinfo *ci;
+ struct mon_evt *evt;
struct mon_data *md;
rdtgrp = rdtgroup_kn_lock_live(of->kn);
@@ -623,10 +700,17 @@ int rdtgroup_mondata_show(struct seq_file *m, void *arg)
resid = md->rid;
domid = md->domid;
- evtid = md->evtid;
+ evt = md->evt;
r = resctrl_arch_get_resource(resid);
if (md->sum) {
+ struct rdt_l3_mon_domain *d;
+
+ if (WARN_ON_ONCE(resid != RDT_RESOURCE_L3)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
/*
* This file requires summing across all domains that share
* the L3 cache id that was provided in the "domid" field of the
@@ -641,7 +725,7 @@ int rdtgroup_mondata_show(struct seq_file *m, void *arg)
continue;
rr.ci = ci;
mon_event_read(&rr, r, NULL, rdtgrp,
- &ci->shared_cpu_map, evtid, false);
+ &ci->shared_cpu_map, evt, false);
goto checkresult;
}
}
@@ -653,12 +737,11 @@ int rdtgroup_mondata_show(struct seq_file *m, void *arg)
* the resource to find the domain with "domid".
*/
hdr = resctrl_find_domain(&r->mon_domains, domid, NULL);
- if (!hdr || WARN_ON_ONCE(hdr->type != RESCTRL_MON_DOMAIN)) {
+ if (!hdr) {
ret = -ENOENT;
goto out;
}
- d = container_of(hdr, struct rdt_mon_domain, hdr);
- mon_event_read(&rr, r, d, rdtgrp, &d->hdr.cpu_mask, evtid, false);
+ mon_event_read(&rr, r, hdr, rdtgrp, &hdr->cpu_mask, evt, false);
}
checkresult:
@@ -673,6 +756,8 @@ checkresult:
seq_puts(m, "Unavailable\n");
else if (rr.err == -ENOENT)
seq_puts(m, "Unassigned\n");
+ else if (evt->is_floating_point)
+ print_event_value(m, evt->binary_bits, rr.val);
else
seq_printf(m, "%llu\n", rr.val);