Skip to content

Commit 2a65660

Browse files
James Morsebp3tk0v
authored andcommitted
x86/resctrl: Expand the width of domid by replacing mon_data_bits
MPAM platforms retrieve the cache-id property from the ACPI PPTT table. The cache-id field is 32 bits wide. Under resctrl, the cache-id becomes the domain-id, and is packed into the mon_data_bits union bitfield. The width of cache-id in this field is 14 bits. Expanding the union would break 32bit x86 platforms as this union is stored as the kernfs kn->priv pointer. This saved allocating memory for the priv data storage. The firmware on MPAM platforms have used the PPTT cache-id field to expose the interconnect's id for the cache, which is sparse and uses more than 14 bits. Use of this id is to enable PCIe direct cache injection hints. Using this feature with VFIO means the value provided by the ACPI table should be exposed to user-space. To support cache-id values greater than 14 bits, convert the mon_data_bits union to a structure. These are shared between control and monitor groups, and are allocated on first use. The list of allocated struct mon_data is free'd when the filesystem is umount()ed. Co-developed-by: Tony Luck <tony.luck@intel.com> Signed-off-by: Tony Luck <tony.luck@intel.com> Signed-off-by: James Morse <james.morse@arm.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Reviewed-by: Reinette Chatre <reinette.chatre@intel.com> Reviewed-by: Fenghua Yu <fenghuay@nvidia.com> Tested-by: Fenghua Yu <fenghuay@nvidia.com> Tested-by: Babu Moger <babu.moger@amd.com> Tested-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com> Tested-by: Tony Luck <tony.luck@intel.com> Link: https://lore.kernel.org/20250515165855.31452-13-james.morse@arm.com
1 parent d4fb6b8 commit 2a65660

File tree

3 files changed

+106
-36
lines changed

3 files changed

+106
-36
lines changed

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

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -661,32 +661,38 @@ void mon_event_read(struct rmid_read *rr, struct rdt_resource *r,
661661
int rdtgroup_mondata_show(struct seq_file *m, void *arg)
662662
{
663663
struct kernfs_open_file *of = m->private;
664+
enum resctrl_res_level resid;
665+
enum resctrl_event_id evtid;
664666
struct rdt_domain_hdr *hdr;
665667
struct rmid_read rr = {0};
666668
struct rdt_mon_domain *d;
667-
u32 resid, evtid, domid;
668669
struct rdtgroup *rdtgrp;
669670
struct rdt_resource *r;
670-
union mon_data_bits md;
671-
int ret = 0;
671+
struct mon_data *md;
672+
int domid, ret = 0;
672673

673674
rdtgrp = rdtgroup_kn_lock_live(of->kn);
674675
if (!rdtgrp) {
675676
ret = -ENOENT;
676677
goto out;
677678
}
678679

679-
md.priv = of->kn->priv;
680-
resid = md.u.rid;
681-
domid = md.u.domid;
682-
evtid = md.u.evtid;
680+
md = of->kn->priv;
681+
if (WARN_ON_ONCE(!md)) {
682+
ret = -EIO;
683+
goto out;
684+
}
685+
686+
resid = md->rid;
687+
domid = md->domid;
688+
evtid = md->evtid;
683689
r = resctrl_arch_get_resource(resid);
684690

685-
if (md.u.sum) {
691+
if (md->sum) {
686692
/*
687693
* This file requires summing across all domains that share
688694
* the L3 cache id that was provided in the "domid" field of the
689-
* mon_data_bits union. Search all domains in the resource for
695+
* struct mon_data. Search all domains in the resource for
690696
* one that matches this cache id.
691697
*/
692698
list_for_each_entry(d, &r->mon_domains, hdr.list) {

arch/x86/kernel/cpu/resctrl/internal.h

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -89,27 +89,26 @@ struct mon_evt {
8989
};
9090

9191
/**
92-
* union mon_data_bits - Monitoring details for each event file.
93-
* @priv: Used to store monitoring event data in @u
94-
* as kernfs private data.
95-
* @u.rid: Resource id associated with the event file.
96-
* @u.evtid: Event id associated with the event file.
97-
* @u.sum: Set when event must be summed across multiple
98-
* domains.
99-
* @u.domid: When @u.sum is zero this is the domain to which
100-
* the event file belongs. When @sum is one this
101-
* is the id of the L3 cache that all domains to be
102-
* summed share.
103-
* @u: Name of the bit fields struct.
92+
* struct mon_data - Monitoring details for each event file.
93+
* @list: Member of the global @mon_data_kn_priv_list list.
94+
* @rid: Resource id associated with the event file.
95+
* @evtid: Event id associated with the event file.
96+
* @sum: Set when event must be summed across multiple
97+
* domains.
98+
* @domid: When @sum is zero this is the domain to which
99+
* the event file belongs. When @sum is one this
100+
* is the id of the L3 cache that all domains to be
101+
* summed share.
102+
*
103+
* Pointed to by the kernfs kn->priv field of monitoring event files.
104+
* Readers and writers must hold rdtgroup_mutex.
104105
*/
105-
union mon_data_bits {
106-
void *priv;
107-
struct {
108-
unsigned int rid : 10;
109-
enum resctrl_event_id evtid : 7;
110-
unsigned int sum : 1;
111-
unsigned int domid : 14;
112-
} u;
106+
struct mon_data {
107+
struct list_head list;
108+
enum resctrl_res_level rid;
109+
enum resctrl_event_id evtid;
110+
int domid;
111+
bool sum;
113112
};
114113

115114
/**

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

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ LIST_HEAD(rdt_all_groups);
4545
/* list of entries for the schemata file */
4646
LIST_HEAD(resctrl_schema_all);
4747

48+
/*
49+
* List of struct mon_data containing private data of event files for use by
50+
* rdtgroup_mondata_show(). Protected by rdtgroup_mutex.
51+
*/
52+
static LIST_HEAD(mon_data_kn_priv_list);
53+
4854
/* The filesystem can only be mounted once. */
4955
bool resctrl_mounted;
5056

@@ -3093,6 +3099,63 @@ static void rmdir_all_sub(void)
30933099
kernfs_remove(kn_mondata);
30943100
}
30953101

3102+
/**
3103+
* mon_get_kn_priv() - Get the mon_data priv data for this event.
3104+
*
3105+
* The same values are used across the mon_data directories of all control and
3106+
* monitor groups for the same event in the same domain. Keep a list of
3107+
* allocated structures and re-use an existing one with the same values for
3108+
* @rid, @domid, etc.
3109+
*
3110+
* @rid: The resource id for the event file being created.
3111+
* @domid: The domain id for the event file being created.
3112+
* @mevt: The type of event file being created.
3113+
* @do_sum: Whether SNC summing monitors are being created.
3114+
*/
3115+
static struct mon_data *mon_get_kn_priv(enum resctrl_res_level rid, int domid,
3116+
struct mon_evt *mevt,
3117+
bool do_sum)
3118+
{
3119+
struct mon_data *priv;
3120+
3121+
lockdep_assert_held(&rdtgroup_mutex);
3122+
3123+
list_for_each_entry(priv, &mon_data_kn_priv_list, list) {
3124+
if (priv->rid == rid && priv->domid == domid &&
3125+
priv->sum == do_sum && priv->evtid == mevt->evtid)
3126+
return priv;
3127+
}
3128+
3129+
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
3130+
if (!priv)
3131+
return NULL;
3132+
3133+
priv->rid = rid;
3134+
priv->domid = domid;
3135+
priv->sum = do_sum;
3136+
priv->evtid = mevt->evtid;
3137+
list_add_tail(&priv->list, &mon_data_kn_priv_list);
3138+
3139+
return priv;
3140+
}
3141+
3142+
/**
3143+
* mon_put_kn_priv() - Free all allocated mon_data structures.
3144+
*
3145+
* Called when resctrl file system is unmounted.
3146+
*/
3147+
static void mon_put_kn_priv(void)
3148+
{
3149+
struct mon_data *priv, *tmp;
3150+
3151+
lockdep_assert_held(&rdtgroup_mutex);
3152+
3153+
list_for_each_entry_safe(priv, tmp, &mon_data_kn_priv_list, list) {
3154+
list_del(&priv->list);
3155+
kfree(priv);
3156+
}
3157+
}
3158+
30963159
static void resctrl_fs_teardown(void)
30973160
{
30983161
lockdep_assert_held(&rdtgroup_mutex);
@@ -3102,6 +3165,7 @@ static void resctrl_fs_teardown(void)
31023165
return;
31033166

31043167
rmdir_all_sub();
3168+
mon_put_kn_priv();
31053169
rdt_pseudo_lock_release();
31063170
rdtgroup_default.mode = RDT_MODE_SHAREABLE;
31073171
closid_exit();
@@ -3208,19 +3272,20 @@ static int mon_add_all_files(struct kernfs_node *kn, struct rdt_mon_domain *d,
32083272
bool do_sum)
32093273
{
32103274
struct rmid_read rr = {0};
3211-
union mon_data_bits priv;
3275+
struct mon_data *priv;
32123276
struct mon_evt *mevt;
3213-
int ret;
3277+
int ret, domid;
32143278

32153279
if (WARN_ON(list_empty(&r->evt_list)))
32163280
return -EPERM;
32173281

3218-
priv.u.rid = r->rid;
3219-
priv.u.domid = do_sum ? d->ci->id : d->hdr.id;
3220-
priv.u.sum = do_sum;
32213282
list_for_each_entry(mevt, &r->evt_list, list) {
3222-
priv.u.evtid = mevt->evtid;
3223-
ret = mon_addfile(kn, mevt->name, priv.priv);
3283+
domid = do_sum ? d->ci->id : d->hdr.id;
3284+
priv = mon_get_kn_priv(r->rid, domid, mevt, do_sum);
3285+
if (WARN_ON_ONCE(!priv))
3286+
return -EINVAL;
3287+
3288+
ret = mon_addfile(kn, mevt->name, priv);
32243289
if (ret)
32253290
return ret;
32263291

0 commit comments

Comments
 (0)