diff --git a/drivers/perf/resctrl_pmu.c b/drivers/perf/resctrl_pmu.c
index 99a2b90b5d83..ed77edc59d23 100644
--- a/drivers/perf/resctrl_pmu.c
+++ b/drivers/perf/resctrl_pmu.c
@@ -57,6 +57,7 @@ static struct rdt_resource *resctrl_event_get_resource(u16 event_num)
 	switch (event_id) {
 	case QOS_L3_OCCUP_EVENT_ID:
 	case QOS_L3_MBM_TOTAL_EVENT_ID:
+		return resctrl_arch_get_resource(RDT_RESOURCE_MBA);
 	case QOS_L3_MBM_LOCAL_EVENT_ID:
 		return resctrl_arch_get_resource(RDT_RESOURCE_L3);
 	}
diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c
index a1304fbfb26f..e1b7d27ed7ad 100644
--- a/drivers/platform/mpam/mpam_resctrl.c
+++ b/drivers/platform/mpam/mpam_resctrl.c
@@ -30,7 +30,7 @@ static struct mpam_resctrl_res mpam_resctrl_exports[RDT_NUM_RESOURCES];
 
 static bool exposed_alloc_capable;
 static bool exposed_mon_capable;
-static struct mpam_class *mbm_local_class;
+static struct mpam_class *mbm_local_class, *mbm_total_class;
 
 /*
  * MPAM emulates CDP by setting different PARTID in the I/D fields of MPAM1_EL1.
@@ -38,6 +38,11 @@ static struct mpam_class *mbm_local_class;
  */
 static bool cdp_enabled;
 
+bool resctrl_arch_is_mbm_total_enabled(void)
+{
+	return mbm_total_class;
+}
+
 /*
  * If resctrl_init() succeeded, resctrl_exit() can be used to remove support
  * for the filesystem in the event of an error.
@@ -300,6 +305,11 @@ int resctrl_arch_mon_ctx_alloc_no_wait(struct rdt_resource *r, int evtid)
 
 		return mpam_alloc_mbwu_mon(res->class);
 	case QOS_L3_MBM_TOTAL_EVENT_ID:
+		if (mpam_monitors_free_runing)
+			return USE_RMID_IDX;
+		res = container_of(r, struct mpam_resctrl_res, resctrl_res);
+
+		return mpam_alloc_mbwu_mon(res->class);
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -325,6 +335,13 @@ void resctrl_arch_mon_ctx_free(struct rdt_resource *r, int evtid, int ctx)
 		wake_up(&resctrl_mon_ctx_waiters);
 		return;
 	case QOS_L3_MBM_TOTAL_EVENT_ID:
+		if (mpam_monitors_free_runing)
+			return;
+		res = container_of(r, struct mpam_resctrl_res, resctrl_res);
+
+		mpam_free_mbwu_mon(res->class, ctx);
+		wake_up(&resctrl_mon_ctx_waiters);
+		return;
 	default:
 		return;
 	}
@@ -350,6 +367,9 @@ int resctrl_arch_rmid_read(struct rdt_resource	*r, struct rdt_domain *d,
 		type = mpam_feat_msmon_mbwu;
 		break;
 	case QOS_L3_MBM_TOTAL_EVENT_ID:
+		type = mpam_feat_msmon_mbwu;
+		break;
+	default:
 		return -EOPNOTSUPP;
 	}
 
@@ -726,6 +746,7 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res)
 		}
 	} else if (res->resctrl_res.rid == RDT_RESOURCE_MBA) {
 		struct mpam_props *cprops = &class->props;
+		bool has_mbwu = class_has_usable_mbwu(class);
 
 		/* TODO: kill these properties off as they are derivatives */
 		r->format_str = "%d=%0*u";
@@ -750,7 +771,17 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res)
 			r->alloc_capable = true;
 			exposed_alloc_capable = true;
 		}
-	}
+
+		if (has_mbwu) {
+			r->mon_capable = true;
+			exposed_mon_capable = true;
+		}
+
+		r->num_rmid = 1;
+
+		if (class_has_usable_mbwu(class))
+			mbm_total_class = class;
+		}
 
 	return 0;
 }
diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c
index 18b544c4ca79..843759131f88 100644
--- a/fs/resctrl/monitor.c
+++ b/fs/resctrl/monitor.c
@@ -448,7 +448,8 @@ static void update_mba_bw(struct rdtgroup *rgrp, struct rdt_domain *dom_mbm)
 	struct list_head *head;
 	struct rdtgroup *entry;
 
-	if (!resctrl_arch_is_mbm_local_enabled())
+	if (!resctrl_arch_is_mbm_local_enabled() ||
+		!resctrl_arch_is_mbm_total_enabled())
 		return;
 
 	r_mba = resctrl_arch_get_resource(RDT_RESOURCE_MBA);
@@ -721,29 +722,34 @@ static struct mon_evt mbm_local_event = {
  * because as per the SDM the total and local memory bandwidth
  * are enumerated as part of L3 monitoring.
  */
-static void l3_mon_evt_init(struct rdt_resource *r)
+static void resource_mon_evt_init(struct rdt_resource *r)
 {
 	INIT_LIST_HEAD(&r->evt_list);
 
-	if (resctrl_arch_is_llc_occupancy_enabled())
+	if (resctrl_arch_is_llc_occupancy_enabled() && !strcmp(r->name, "L3"))
 		list_add_tail(&llc_occupancy_event.list, &r->evt_list);
-	if (resctrl_arch_is_mbm_total_enabled())
+	if (resctrl_arch_is_mbm_total_enabled() && !strcmp(r->name, "MB"))
 		list_add_tail(&mbm_total_event.list, &r->evt_list);
-	if (resctrl_arch_is_mbm_local_enabled())
+	if (resctrl_arch_is_mbm_local_enabled() && !strcmp(r->name, "L3"))
 		list_add_tail(&mbm_local_event.list, &r->evt_list);
 }
 
 int resctrl_mon_resource_init(void)
 {
-	struct rdt_resource *r = resctrl_arch_get_resource(RDT_RESOURCE_L3);
+	enum resctrl_res_level i;
+	struct rdt_resource *r;
 	int ret;
 
-	ret = dom_data_init(r);
-	if (ret)
-		return ret;
+	for (i = 0; i < RDT_NUM_RESOURCES; i++) {
+		r = resctrl_arch_get_resource(i);
 
-	if (r->mon_capable)
-		l3_mon_evt_init(r);
+		ret = dom_data_init(r);
+		if (ret)
+			return ret;
+
+		if (r->mon_capable)
+			resource_mon_evt_init(r);
+	}
 
 	return 0;
 }
diff --git a/include/linux/arm_mpam.h b/include/linux/arm_mpam.h
index 1d82d9dfbc3f..2f3c354c13d0 100644
--- a/include/linux/arm_mpam.h
+++ b/include/linux/arm_mpam.h
@@ -47,6 +47,7 @@ static inline bool resctrl_arch_event_is_free_running(enum resctrl_event_id evt)
 	case QOS_L3_OCCUP_EVENT_ID:
 		return true;
 	case QOS_L3_MBM_TOTAL_EVENT_ID:
+		return mpam_monitors_free_runing;
 	case QOS_L3_MBM_LOCAL_EVENT_ID:
 		return mpam_monitors_free_runing;
 	}
@@ -65,11 +66,7 @@ bool resctrl_arch_alloc_capable(void);
 bool resctrl_arch_mon_capable(void);
 bool resctrl_arch_is_llc_occupancy_enabled(void);
 bool resctrl_arch_is_mbm_local_enabled(void);
-
-static inline bool resctrl_arch_is_mbm_total_enabled(void)
-{
-	return false;
-}
+bool resctrl_arch_is_mbm_total_enabled(void);
 
 /* reset cached configurations, then all devices */
 void resctrl_arch_reset_resources(void);
