]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
arm_mpam: resctrl: Add resctrl_arch_rmid_read()
authorJames Morse <james.morse@arm.com>
Fri, 13 Mar 2026 14:46:07 +0000 (14:46 +0000)
committerJames Morse <james.morse@arm.com>
Fri, 27 Mar 2026 15:31:50 +0000 (15:31 +0000)
resctrl uses resctrl_arch_rmid_read() to read counters. CDP emulation means
the counter may need reading in three different ways.

The helpers behind the resctrl_arch_ functions will be re-used for the ABMC
equivalent functions.

Add the rounding helper for checking monitor values while we're here.

Tested-by: Gavin Shan <gshan@redhat.com>
Tested-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com>
Tested-by: Peter Newman <peternewman@google.com>
Tested-by: Zeng Heng <zengheng4@huawei.com>
Tested-by: Jesse Chick <jessechick@os.amperecomputing.com>
Reviewed-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Gavin Shan <gshan@redhat.com>
Co-developed-by: Ben Horgan <ben.horgan@arm.com>
Signed-off-by: Ben Horgan <ben.horgan@arm.com>
Signed-off-by: James Morse <james.morse@arm.com>
drivers/resctrl/mpam_resctrl.c
include/linux/arm_mpam.h

index 9682ffb1518467c239831291c309d7936b682d82..9a15ddd340f7355b4fc8265568058c0c0e7323e6 100644 (file)
@@ -356,6 +356,88 @@ void resctrl_arch_mon_ctx_free(struct rdt_resource *r,
        resctrl_arch_mon_ctx_free_no_wait(evtid, mon_idx);
 }
 
+static int __read_mon(struct mpam_resctrl_mon *mon, struct mpam_component *mon_comp,
+                     enum mpam_device_features mon_type,
+                     int mon_idx,
+                     enum resctrl_conf_type cdp_type, u32 closid, u32 rmid, u64 *val)
+{
+       struct mon_cfg cfg;
+
+       if (!mpam_is_enabled())
+               return -EINVAL;
+
+       /* Shift closid to account for CDP */
+       closid = resctrl_get_config_index(closid, cdp_type);
+
+       if (irqs_disabled()) {
+               /* Check if we can access this domain without an IPI */
+               return -EIO;
+       }
+
+       cfg = (struct mon_cfg) {
+               .mon = mon_idx,
+               .match_pmg = true,
+               .partid = closid,
+               .pmg = rmid,
+       };
+
+       return mpam_msmon_read(mon_comp, &cfg, mon_type, val);
+}
+
+static int read_mon_cdp_safe(struct mpam_resctrl_mon *mon, struct mpam_component *mon_comp,
+                            enum mpam_device_features mon_type,
+                            int mon_idx, u32 closid, u32 rmid, u64 *val)
+{
+       if (cdp_enabled) {
+               u64 code_val = 0, data_val = 0;
+               int err;
+
+               err = __read_mon(mon, mon_comp, mon_type, mon_idx,
+                                CDP_CODE, closid, rmid, &code_val);
+               if (err)
+                       return err;
+
+               err = __read_mon(mon, mon_comp, mon_type, mon_idx,
+                                CDP_DATA, closid, rmid, &data_val);
+               if (err)
+                       return err;
+
+               *val += code_val + data_val;
+               return 0;
+       }
+
+       return __read_mon(mon, mon_comp, mon_type, mon_idx,
+                         CDP_NONE, closid, rmid, val);
+}
+
+/* MBWU when not in ABMC mode (not supported), and CSU counters. */
+int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_domain_hdr *hdr,
+                          u32 closid, u32 rmid, enum resctrl_event_id eventid,
+                          void *arch_priv, u64 *val, void *arch_mon_ctx)
+{
+       struct mpam_resctrl_dom *l3_dom;
+       struct mpam_component *mon_comp;
+       u32 mon_idx = *(u32 *)arch_mon_ctx;
+       enum mpam_device_features mon_type;
+       struct mpam_resctrl_mon *mon = &mpam_resctrl_counters[eventid];
+
+       resctrl_arch_rmid_read_context_check();
+
+       if (eventid >= QOS_NUM_EVENTS || !mon->class)
+               return -EINVAL;
+
+       l3_dom = container_of(hdr, struct mpam_resctrl_dom, resctrl_mon_dom.hdr);
+       mon_comp = l3_dom->mon_comp[eventid];
+
+       if (eventid != QOS_L3_OCCUP_EVENT_ID)
+               return -EINVAL;
+
+       mon_type = mpam_feat_msmon_csu;
+
+       return read_mon_cdp_safe(mon, mon_comp, mon_type, mon_idx,
+                                closid, rmid, val);
+}
+
 static bool cache_has_usable_cpor(struct mpam_class *class)
 {
        struct mpam_props *cprops = &class->props;
index e1461e32af75602df7d9e4d04b590c07c45c9ec2..86d5e326d2bd3738a47aa18747435387b6ddb614 100644 (file)
@@ -67,6 +67,11 @@ struct rdt_resource;
 void *resctrl_arch_mon_ctx_alloc(struct rdt_resource *r, enum resctrl_event_id evtid);
 void resctrl_arch_mon_ctx_free(struct rdt_resource *r, enum resctrl_event_id evtid, void *ctx);
 
+static inline unsigned int resctrl_arch_round_mon_val(unsigned int val)
+{
+       return val;
+}
+
 /**
  * mpam_register_requestor() - Register a requestor with the MPAM driver
  * @partid_max:                The maximum PARTID value the requestor can generate.