提交 b4617397 编写于 作者: X Xie XiuQi

arm64/mpam: support mondata fields

hulk inclusion
category: feature
bugzilla: 5510
CVE: NA
Signed-off-by: NXie XiuQi <xiexiuqi@huawei.com>
Reviewed-by: NHanjun Guo <guohanjun@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 89691ba7
......@@ -140,6 +140,7 @@ struct mongroup {
* @kn: kernfs node
* @resctrl_group_list: linked list for all rdtgroups
* @closid: closid for this rdtgroup
* #endif
* @cpu_mask: CPUs assigned to this rdtgroup
* @flags: status bits
* @waitcount: how many cpus expect to find this
......
......@@ -55,4 +55,12 @@ int resctrl_group_schemata_show(struct kernfs_open_file *of,
r < resctrl_resources_all + MPAM_NUM_RESOURCES; \
r++) \
int mkdir_mondata_all(struct kernfs_node *parent_kn,
struct resctrl_group *prgrp,
struct kernfs_node **dest_kn);
int
mongroup_create_dir(struct kernfs_node *parent_kn, struct resctrl_group *prgrp,
char *name, struct kernfs_node **dest_kn);
#endif /* _ASM_ARM64_RESCTRL_H */
......@@ -28,6 +28,8 @@
#include <linux/slab.h>
#include <linux/resctrlfs.h>
#include <asm/mpam.h>
#include <asm/mpam_resource.h>
#include <asm/resctrl.h>
/*
......@@ -248,3 +250,278 @@ int resctrl_group_schemata_show(struct kernfs_open_file *of,
resctrl_group_kn_unlock(of->kn);
return ret;
}
/*
* [FIXME]
* use pmg as monitor id
* just use match_pardid only.
*/
static u64 mbwu_read(struct rdt_domain *d, struct rdtgroup *g)
{
u32 pmg = g->mon.rmid;
mpam_writel(pmg, d->base + MSMON_CFG_MON_SEL);
return mpam_readl(d->base + MSMON_MBWU);
}
static u64 csu_read(struct rdt_domain *d, struct rdtgroup *g)
{
u32 pmg = g->mon.rmid;
mpam_writel(pmg, d->base + MSMON_CFG_MON_SEL);
return mpam_readl(d->base + MSMON_CSU);
}
int resctrl_group_mondata_show(struct seq_file *m, void *arg)
{
struct kernfs_open_file *of = m->private;
struct rdtgroup *rdtgrp;
struct rdt_domain *d;
int ret = 0;
rdtgrp = resctrl_group_kn_lock_live(of->kn);
d = of->kn->priv;
/* for debug */
seq_printf(m, "group: partid: %d, pmg: %d",
rdtgrp->closid, rdtgrp->mon.rmid);
/* show monitor data */
resctrl_group_kn_unlock(of->kn);
return ret;
}
static struct kernfs_ops kf_mondata_ops = {
.atomic_write_len = PAGE_SIZE,
.seq_show = resctrl_group_mondata_show,
};
/* set uid and gid of resctrl_group dirs and files to that of the creator */
static int resctrl_group_kn_set_ugid(struct kernfs_node *kn)
{
struct iattr iattr = { .ia_valid = ATTR_UID | ATTR_GID,
.ia_uid = current_fsuid(),
.ia_gid = current_fsgid(), };
if (uid_eq(iattr.ia_uid, GLOBAL_ROOT_UID) &&
gid_eq(iattr.ia_gid, GLOBAL_ROOT_GID))
return 0;
return kernfs_setattr(kn, &iattr);
}
#if 0 /* used at remove cpu*/
/*
* Remove all subdirectories of mon_data of ctrl_mon groups
* and monitor groups with given domain id.
*/
void rmdir_mondata_subdir_allrdtgrp(struct resctrl_resource *r, unsigned int dom_id)
{
struct resctrl_group *prgrp, *crgrp;
char name[32];
if (!r->mon_enabled)
return;
list_for_each_entry(prgrp, &resctrl_all_groups, resctrl_group_list) {
sprintf(name, "mon_%s_%02d", r->name, dom_id);
kernfs_remove_by_name(prgrp->mon.mon_data_kn, name);
list_for_each_entry(crgrp, &prgrp->mon.crdtgrp_list, mon.crdtgrp_list)
kernfs_remove_by_name(crgrp->mon.mon_data_kn, name);
}
}
#endif
static int mkdir_mondata_subdir(struct kernfs_node *parent_kn,
struct rdt_domain *d,
struct resctrl_resource *r, struct resctrl_group *prgrp)
{
#if 1
struct kernfs_node *kn;
char name[32];
int ret;
sprintf(name, "mon_%s_%02d", r->name, d->id);
kn = __kernfs_create_file(parent_kn, name, 0444,
GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, 0,
&kf_mondata_ops, d, NULL, NULL);
if (IS_ERR(kn))
return PTR_ERR(kn);
ret = resctrl_group_kn_set_ugid(kn);
if (ret) {
kernfs_remove(kn);
return ret;
}
return ret;
#if 0
/* create the directory */
kn = kernfs_create_dir(parent_kn, name, parent_kn->mode, prgrp);
if (IS_ERR(kn))
return PTR_ERR(kn);
/*
* This extra ref will be put in kernfs_remove() and guarantees
* that kn is always accessible.
*/
kernfs_get(kn);
ret = resctrl_group_kn_set_ugid(kn);
if (ret)
goto out_destroy;
#endif
#if 0
ret = mon_addfile(kn, mevt->name, d);
if (ret)
goto out_destroy;
kernfs_activate(kn);
return 0;
out_destroy:
kernfs_remove(kn);
return ret;
#endif
#else
return 0;
#endif
}
/*
* Add all subdirectories of mon_data for "ctrl_mon" groups
* and "monitor" groups with given domain id.
*/
void mkdir_mondata_subdir_allrdtgrp(struct resctrl_resource *r,
struct rdt_domain *d)
{
struct kernfs_node *parent_kn;
struct resctrl_group *prgrp, *crgrp;
struct list_head *head;
if (!r->mon_enabled)
return;
list_for_each_entry(prgrp, &resctrl_all_groups, resctrl_group_list) {
parent_kn = prgrp->mon.mon_data_kn;
mkdir_mondata_subdir(parent_kn, d, r, prgrp);
head = &prgrp->mon.crdtgrp_list;
list_for_each_entry(crgrp, head, mon.crdtgrp_list) {
parent_kn = crgrp->mon.mon_data_kn;
mkdir_mondata_subdir(parent_kn, d, r, crgrp);
}
}
}
static int mkdir_mondata_subdir_alldom(struct kernfs_node *parent_kn,
struct resctrl_resource *r,
struct resctrl_group *prgrp)
{
struct rdt_domain *dom;
int ret;
list_for_each_entry(dom, &r->domains, list) {
ret = mkdir_mondata_subdir(parent_kn, dom, r, prgrp);
if (ret)
return ret;
}
return 0;
}
int
mongroup_create_dir(struct kernfs_node *parent_kn, struct resctrl_group *prgrp,
char *name, struct kernfs_node **dest_kn)
{
struct kernfs_node *kn;
int ret;
/* create the directory */
kn = kernfs_create_dir(parent_kn, name, parent_kn->mode, prgrp);
if (IS_ERR(kn))
return PTR_ERR(kn);
if (dest_kn)
*dest_kn = kn;
/*
* This extra ref will be put in kernfs_remove() and guarantees
* that @rdtgrp->kn is always accessible.
*/
kernfs_get(kn);
ret = resctrl_group_kn_set_ugid(kn);
if (ret)
goto out_destroy;
kernfs_activate(kn);
return 0;
out_destroy:
kernfs_remove(kn);
return ret;
}
/*
* This creates a directory mon_data which contains the monitored data.
*
* mon_data has one directory for each domain whic are named
* in the format mon_<domain_name>_<domain_id>. For ex: A mon_data
* with L3 domain looks as below:
* ./mon_data:
* mon_L3_00
* mon_L3_01
* mon_L3_02
* ...
*
* Each domain directory has one file per event:
* ./mon_L3_00/:
* llc_occupancy
*
*/
int mkdir_mondata_all(struct kernfs_node *parent_kn,
struct resctrl_group *prgrp,
struct kernfs_node **dest_kn)
{
struct resctrl_resource *r;
struct kernfs_node *kn;
int ret;
/*
* Create the mon_data directory first.
*/
ret = mongroup_create_dir(parent_kn, NULL, "mon_data", &kn);
if (ret)
return ret;
if (dest_kn)
*dest_kn = kn;
/*
* Create the subdirectories for each domain. Note that all events
* in a domain like L3 are grouped into a resource whose domain is L3
*/
for_each_resctrl_resource(r) {
if (r->mon_enabled) {
ret = mkdir_mondata_subdir_alldom(kn, r, prgrp);
if (ret)
goto out_destroy;
}
}
kernfs_activate(kn);
return 0;
out_destroy:
kernfs_remove(kn);
return ret;
}
......@@ -71,6 +71,7 @@ static int resctrl_group_add_file(struct kernfs_node *parent_kn, struct rftype *
int ret;
kn = __kernfs_create_file(parent_kn, rft->name, rft->mode,
GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
0, rft->kf_ops, rft, NULL, NULL);
if (IS_ERR(kn))
return PTR_ERR(kn);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册