Skip to content

Commit e37c9a3

Browse files
aeglbp3tk0v
authored andcommitted
x86,fs/resctrl: Support binary fixed point event counters
resctrl assumes that all monitor events can be displayed as unsigned decimal integers. Hardware architecture counters may provide some telemetry events with greater precision where the event is not a simple count, but is a measurement of some sort (e.g. Joules for energy consumed). Add a new argument to resctrl_enable_mon_event() for architecture code to inform the file system that the value for a counter is a fixed-point value with a specific number of binary places. Only allow architecture to use floating point format on events that the file system has marked with mon_evt::is_floating_point which reflects the contract with user space on how the event values are displayed. Display fixed point values with values rounded to ceil(binary_bits * log10(2)) decimal places. Special case for zero binary bits to print "{value}.0". Signed-off-by: Tony Luck <tony.luck@intel.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Reviewed-by: Reinette Chatre <reinette.chatre@intel.com> Link: https://lore.kernel.org/20251217172121.12030-1-tony.luck@intel.com
1 parent ab0308a commit e37c9a3

5 files changed

Lines changed: 95 additions & 6 deletions

File tree

arch/x86/kernel/cpu/resctrl/core.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -902,15 +902,15 @@ static __init bool get_rdt_mon_resources(void)
902902
bool ret = false;
903903

904904
if (rdt_cpu_has(X86_FEATURE_CQM_OCCUP_LLC)) {
905-
resctrl_enable_mon_event(QOS_L3_OCCUP_EVENT_ID, false);
905+
resctrl_enable_mon_event(QOS_L3_OCCUP_EVENT_ID, false, 0);
906906
ret = true;
907907
}
908908
if (rdt_cpu_has(X86_FEATURE_CQM_MBM_TOTAL)) {
909-
resctrl_enable_mon_event(QOS_L3_MBM_TOTAL_EVENT_ID, false);
909+
resctrl_enable_mon_event(QOS_L3_MBM_TOTAL_EVENT_ID, false, 0);
910910
ret = true;
911911
}
912912
if (rdt_cpu_has(X86_FEATURE_CQM_MBM_LOCAL)) {
913-
resctrl_enable_mon_event(QOS_L3_MBM_LOCAL_EVENT_ID, false);
913+
resctrl_enable_mon_event(QOS_L3_MBM_LOCAL_EVENT_ID, false, 0);
914914
ret = true;
915915
}
916916
if (rdt_cpu_has(X86_FEATURE_ABMC))

fs/resctrl/ctrlmondata.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include <linux/cpu.h>
1919
#include <linux/kernfs.h>
20+
#include <linux/math.h>
2021
#include <linux/seq_file.h>
2122
#include <linux/slab.h>
2223
#include <linux/tick.h>
@@ -601,6 +602,77 @@ void mon_event_read(struct rmid_read *rr, struct rdt_resource *r,
601602
resctrl_arch_mon_ctx_free(r, evt->evtid, rr->arch_mon_ctx);
602603
}
603604

605+
/*
606+
* Decimal place precision to use for each number of fixed-point
607+
* binary bits computed from ceil(binary_bits * log10(2)) except
608+
* binary_bits == 0 which will print "value.0"
609+
*/
610+
static const unsigned int decplaces[MAX_BINARY_BITS + 1] = {
611+
[0] = 1,
612+
[1] = 1,
613+
[2] = 1,
614+
[3] = 1,
615+
[4] = 2,
616+
[5] = 2,
617+
[6] = 2,
618+
[7] = 3,
619+
[8] = 3,
620+
[9] = 3,
621+
[10] = 4,
622+
[11] = 4,
623+
[12] = 4,
624+
[13] = 4,
625+
[14] = 5,
626+
[15] = 5,
627+
[16] = 5,
628+
[17] = 6,
629+
[18] = 6,
630+
[19] = 6,
631+
[20] = 7,
632+
[21] = 7,
633+
[22] = 7,
634+
[23] = 7,
635+
[24] = 8,
636+
[25] = 8,
637+
[26] = 8,
638+
[27] = 9
639+
};
640+
641+
static void print_event_value(struct seq_file *m, unsigned int binary_bits, u64 val)
642+
{
643+
unsigned long long frac = 0;
644+
645+
if (binary_bits) {
646+
/* Mask off the integer part of the fixed-point value. */
647+
frac = val & GENMASK_ULL(binary_bits - 1, 0);
648+
649+
/*
650+
* Multiply by 10^{desired decimal places}. The integer part of
651+
* the fixed point value is now almost what is needed.
652+
*/
653+
frac *= int_pow(10ull, decplaces[binary_bits]);
654+
655+
/*
656+
* Round to nearest by adding a value that would be a "1" in the
657+
* binary_bits + 1 place. Integer part of fixed point value is
658+
* now the needed value.
659+
*/
660+
frac += 1ull << (binary_bits - 1);
661+
662+
/*
663+
* Extract the integer part of the value. This is the decimal
664+
* representation of the original fixed-point fractional value.
665+
*/
666+
frac >>= binary_bits;
667+
}
668+
669+
/*
670+
* "frac" is now in the range [0 .. 10^decplaces). I.e. string
671+
* representation will fit into chosen number of decimal places.
672+
*/
673+
seq_printf(m, "%llu.%0*llu\n", val >> binary_bits, decplaces[binary_bits], frac);
674+
}
675+
604676
int rdtgroup_mondata_show(struct seq_file *m, void *arg)
605677
{
606678
struct kernfs_open_file *of = m->private;
@@ -678,6 +750,8 @@ int rdtgroup_mondata_show(struct seq_file *m, void *arg)
678750
seq_puts(m, "Unavailable\n");
679751
else if (rr.err == -ENOENT)
680752
seq_puts(m, "Unassigned\n");
753+
else if (evt->is_floating_point)
754+
print_event_value(m, evt->binary_bits, rr.val);
681755
else
682756
seq_printf(m, "%llu\n", rr.val);
683757

fs/resctrl/internal.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ static inline struct rdt_fs_context *rdt_fc2context(struct fs_context *fc)
6262
* Only valid if @evtid is an MBM event.
6363
* @configurable: true if the event is configurable
6464
* @any_cpu: true if the event can be read from any CPU
65+
* @is_floating_point: event values are displayed in floating point format
66+
* @binary_bits: number of fixed-point binary bits from architecture,
67+
* only valid if @is_floating_point is true
6568
* @enabled: true if the event is enabled
6669
*/
6770
struct mon_evt {
@@ -71,6 +74,8 @@ struct mon_evt {
7174
u32 evt_cfg;
7275
bool configurable;
7376
bool any_cpu;
77+
bool is_floating_point;
78+
unsigned int binary_bits;
7479
bool enabled;
7580
};
7681

@@ -79,6 +84,9 @@ extern struct mon_evt mon_event_all[QOS_NUM_EVENTS];
7984
#define for_each_mon_event(mevt) for (mevt = &mon_event_all[QOS_FIRST_EVENT]; \
8085
mevt < &mon_event_all[QOS_NUM_EVENTS]; mevt++)
8186

87+
/* Limit for mon_evt::binary_bits */
88+
#define MAX_BINARY_BITS 27
89+
8290
/**
8391
* struct mon_data - Monitoring details for each event file.
8492
* @list: Member of the global @mon_data_kn_priv_list list.

fs/resctrl/monitor.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -988,16 +988,22 @@ struct mon_evt mon_event_all[QOS_NUM_EVENTS] = {
988988
},
989989
};
990990

991-
void resctrl_enable_mon_event(enum resctrl_event_id eventid, bool any_cpu)
991+
void resctrl_enable_mon_event(enum resctrl_event_id eventid, bool any_cpu, unsigned int binary_bits)
992992
{
993-
if (WARN_ON_ONCE(eventid < QOS_FIRST_EVENT || eventid >= QOS_NUM_EVENTS))
993+
if (WARN_ON_ONCE(eventid < QOS_FIRST_EVENT || eventid >= QOS_NUM_EVENTS ||
994+
binary_bits > MAX_BINARY_BITS))
994995
return;
995996
if (mon_event_all[eventid].enabled) {
996997
pr_warn("Duplicate enable for event %d\n", eventid);
997998
return;
998999
}
1000+
if (binary_bits && !mon_event_all[eventid].is_floating_point) {
1001+
pr_warn("Event %d may not be floating point\n", eventid);
1002+
return;
1003+
}
9991004

10001005
mon_event_all[eventid].any_cpu = any_cpu;
1006+
mon_event_all[eventid].binary_bits = binary_bits;
10011007
mon_event_all[eventid].enabled = true;
10021008
}
10031009

include/linux/resctrl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,8 @@ u32 resctrl_arch_get_num_closid(struct rdt_resource *r);
412412
u32 resctrl_arch_system_num_rmid_idx(void);
413413
int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid);
414414

415-
void resctrl_enable_mon_event(enum resctrl_event_id eventid, bool any_cpu);
415+
void resctrl_enable_mon_event(enum resctrl_event_id eventid, bool any_cpu,
416+
unsigned int binary_bits);
416417

417418
bool resctrl_is_mon_event_enabled(enum resctrl_event_id eventid);
418419

0 commit comments

Comments
 (0)