diff --git a/arch/arm64/include/asm/resctrl.h b/arch/arm64/include/asm/resctrl.h index 2119204fa090e761f59de6f46cbd7021d7da8e53..58cff955fbdab07f2e75aab67ce88fd308761d77 100644 --- a/arch/arm64/include/asm/resctrl.h +++ b/arch/arm64/include/asm/resctrl.h @@ -75,6 +75,10 @@ struct rdtgroup { struct mongroup mon; }; +int schemata_list_init(void); + +void schemata_list_destroy(void); + static inline int alloc_mon_id(void) { diff --git a/arch/arm64/kernel/mpam/mpam_ctrlmon.c b/arch/arm64/kernel/mpam/mpam_ctrlmon.c index 39c5020cdfa6f6ff4449ae74f4773bd145d6eb75..d5cbb5f16d92e64f3fddf8f575296e8305e15c4f 100644 --- a/arch/arm64/kernel/mpam/mpam_ctrlmon.c +++ b/arch/arm64/kernel/mpam/mpam_ctrlmon.c @@ -40,6 +40,84 @@ #include #include "mpam_internal.h" +/* schemata content list */ +LIST_HEAD(resctrl_all_schema); + +/* Init schemata content */ +static int add_schema(enum resctrl_conf_type t, struct resctrl_resource *r) +{ + char *suffix = ""; + struct resctrl_schema *s; + + s = kzalloc(sizeof(*s), GFP_KERNEL); + if (!s) + return -ENOMEM; + + s->res = r; + s->conf_type = t; + + switch (t) { + case CDP_CODE: + suffix = "CODE"; + break; + case CDP_DATA: + suffix = "DATA"; + break; + case CDP_BOTH: + suffix = ""; + break; + default: + return -EINVAL; + } + + WARN_ON_ONCE(strlen(r->name) + strlen(suffix) + 1 > RESCTRL_NAME_LEN); + snprintf(s->name, sizeof(s->name), "%s%s", r->name, suffix); + + INIT_LIST_HEAD(&s->list); + list_add_tail(&s->list, &resctrl_all_schema); + + return 0; +} + +int schemata_list_init(void) +{ + int ret; + struct mpam_resctrl_res *res; + struct resctrl_resource *r; + + for_each_supported_resctrl_exports(res) { + r = &res->resctrl_res; + if (!r || !r->alloc_capable) + continue; + + if (r->cdp_enable) { + ret = add_schema(CDP_CODE, r); + ret |= add_schema(CDP_DATA, r); + } else { + ret = add_schema(CDP_BOTH, r); + } + if (ret) + break; + } + + return ret; +} + +/* + * During resctrl_kill_sb(), the mba_sc state is reset before + * schemata_list_destroy() is called: unconditionally try to free the + * array. + */ +void schemata_list_destroy(void) +{ + struct resctrl_schema *s, *tmp; + + list_for_each_entry_safe(s, tmp, &resctrl_all_schema, list) { + list_del(&s->list); + kfree(s); + } +} + /* * Check whether a cache bit mask is valid. The SDM says: * Please note that all (and only) contiguous '1' combinations diff --git a/fs/resctrlfs.c b/fs/resctrlfs.c index 7bd1f519d4b1859cba173adcb7ef2626c6d599a2..9fbabed56015c3471e9a6295bf20779fa33bb742 100644 --- a/fs/resctrlfs.c +++ b/fs/resctrlfs.c @@ -335,7 +335,13 @@ static struct dentry *resctrl_mount(struct file_system_type *fs_type, dentry = ERR_PTR(ret); goto out_options; } - +#ifdef CONFIG_ARM64 + ret = schemata_list_init(); + if (ret) { + dentry = ERR_PTR(ret); + goto out_options; + } +#endif resctrl_id_init(); ret = resctrl_group_create_info_dir(resctrl_group_default.kn); @@ -505,6 +511,9 @@ static void resctrl_kill_sb(struct super_block *sb) mutex_lock(&resctrl_group_mutex); resctrl_resource_reset(); +#ifdef CONFIG_ARM64 + schemata_list_destroy(); +#endif rmdir_all_sub(); static_branch_disable_cpuslocked(&resctrl_alloc_enable_key);