Hi James,

On 10/30/2020 9:10 AM, James Morse wrote:
resctrl is the defacto Linux ABI for SoC resource partitioning features.
To support it on another architecture, it needs to be abstracted from
Intel RDT, and moved it to /fs/.

Current support for AMD PQoS should also be considered.

s/and moved it to/and moved to/?


Start by splitting struct rdt_resource, (the name is kept to keep the noise
down), and add some type-trickery to keep the foreach helpers working.

Move everything that that is particular to resctrl into a new header

s/that that/that/

file, keeping the x86 hardware accessors where they are. resctrl code
paths touching a 'hw' struct indicates where an abstraction is needed.

Splitting rdt_domain up in a similar way happens in the next patch.
No change in behaviour, this patch just moves types around.

Please remove the "this patch" term.


Signed-off-by: James Morse <james.mo...@arm.com>
---
  arch/x86/kernel/cpu/resctrl/core.c        | 258 ++++++++++++----------
  arch/x86/kernel/cpu/resctrl/ctrlmondata.c |  14 +-
  arch/x86/kernel/cpu/resctrl/internal.h    | 138 +++---------
  arch/x86/kernel/cpu/resctrl/monitor.c     |  32 +--
  arch/x86/kernel/cpu/resctrl/pseudo_lock.c |   4 +-
  arch/x86/kernel/cpu/resctrl/rdtgroup.c    |  69 +++---
  include/linux/resctrl.h                   | 117 ++++++++++
  7 files changed, 362 insertions(+), 270 deletions(-)

diff --git a/arch/x86/kernel/cpu/resctrl/core.c 
b/arch/x86/kernel/cpu/resctrl/core.c
index e5f4ee8f4c3b..470661f2eb68 100644
--- a/arch/x86/kernel/cpu/resctrl/core.c
+++ b/arch/x86/kernel/cpu/resctrl/core.c

...

@@ -912,9 +938,14 @@ static __init bool get_rdt_resources(void)
static __init void rdt_init_res_defs_intel(void)
  {
+       struct rdt_hw_resource *hw_res;
        struct rdt_resource *r;
+       int i;
+
+       for (i = 0; i < RDT_NUM_RESOURCES; i++) {
+               hw_res = &rdt_resources_all[i];
+               r = &rdt_resources_all[i].resctrl;
- for_each_rdt_resource(r) {
                if (r->rid == RDT_RESOURCE_L3 ||
                    r->rid == RDT_RESOURCE_L3DATA ||
                    r->rid == RDT_RESOURCE_L3CODE ||

Could using for_each_rdt_resource() remain with the additional assignment of hw_res? Similar to the later usage of for_each_alloc_enabled_rdt_resource()?

@@ -924,17 +955,22 @@ static __init void rdt_init_res_defs_intel(void)
                        r->cache.arch_has_sparse_bitmaps = false;
                        r->cache.arch_has_empty_bitmaps = false;
                } else if (r->rid == RDT_RESOURCE_MBA) {
-                       r->msr_base = MSR_IA32_MBA_THRTL_BASE;
-                       r->msr_update = mba_wrmsr_intel;
+                       hw_res->msr_base = MSR_IA32_MBA_THRTL_BASE;
+                       hw_res->msr_update = mba_wrmsr_intel;
                }
        }
  }
static __init void rdt_init_res_defs_amd(void)
  {
+       struct rdt_hw_resource *hw_res;
        struct rdt_resource *r;
+       int i;
+
+       for (i = 0; i < RDT_NUM_RESOURCES; i++) {
+               hw_res = &rdt_resources_all[i];
+               r = &rdt_resources_all[i].resctrl;
- for_each_rdt_resource(r) {
                if (r->rid == RDT_RESOURCE_L3 ||
                    r->rid == RDT_RESOURCE_L3DATA ||
                    r->rid == RDT_RESOURCE_L3CODE ||

Same here (keep using for_each_rdt_resource()?).

@@ -944,8 +980,8 @@ static __init void rdt_init_res_defs_amd(void)
                        r->cache.arch_has_sparse_bitmaps = true;
                        r->cache.arch_has_empty_bitmaps = true;
                } else if (r->rid == RDT_RESOURCE_MBA) {
-                       r->msr_base = MSR_IA32_MBA_BW_BASE;
-                       r->msr_update = mba_wrmsr_amd;
+                       hw_res->msr_base = MSR_IA32_MBA_BW_BASE;
+                       hw_res->msr_update = mba_wrmsr_amd;
                }
        }
  }
diff --git a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c 
b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
index c877642e8a14..ab6e584c9d2d 100644
--- a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
+++ b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
@@ -284,10 +284,12 @@ int update_domains(struct rdt_resource *r, int closid)
  static int rdtgroup_parse_resource(char *resname, char *tok,
                                   struct rdtgroup *rdtgrp)
  {
+       struct rdt_hw_resource *hw_res;
        struct rdt_resource *r;
for_each_alloc_enabled_rdt_resource(r) {
-               if (!strcmp(resname, r->name) && rdtgrp->closid < r->num_closid)
+               hw_res = resctrl_to_arch_res(r);
+               if (!strcmp(resname, r->name) && rdtgrp->closid < 
hw_res->num_closid)
                        return parse_line(tok, r, rdtgrp);
        }

This is the usage of for_each_alloc_enabled_rdt_resource() I refer to earlier.

        rdt_last_cmd_printf("Unknown or unsupported resource name '%s'\n", 
resname);

...

diff --git a/arch/x86/kernel/cpu/resctrl/internal.h 
b/arch/x86/kernel/cpu/resctrl/internal.h
index 80fa997fae60..bcae86138cad 100644
--- a/arch/x86/kernel/cpu/resctrl/internal.h
+++ b/arch/x86/kernel/cpu/resctrl/internal.h

...

@@ -438,56 +381,29 @@ struct rdt_parse_data {
  };
/**
- * struct rdt_resource - attributes of an RDT resource
- * @rid:               The index of the resource
- * @alloc_enabled:     Is allocation enabled on this machine
- * @mon_enabled:       Is monitoring enabled for this feature
- * @alloc_capable:     Is allocation available on this machine
- * @mon_capable:       Is monitor feature available on this machine
- * @name:              Name to use in "schemata" file
- * @num_closid:                Number of CLOSIDs available
- * @cache_level:       Which cache level defines scope of this resource
- * @default_ctrl:      Specifies default cache cbm or memory B/W percent.
+ * struct rdt_hw_resource - hw attributes of an RDT resource

Perhaps rather "hw attributes of a resctrl resource" to help with the transition away from being specific to Intel RDT.

+ * @num_closid:                Number of CLOSIDs available.
   * @msr_base:         Base MSR address for CBMs
   * @msr_update:               Function pointer to update QOS MSRs
- * @data_width:                Character width of data when displaying
- * @domains:           All domains for this resource
- * @cache:             Cache allocation related data
- * @format_str:                Per resource format string to show domain value
- * @parse_ctrlval:     Per resource function pointer to parse control values
- * @evt_list:          List of monitoring events
- * @num_rmid:          Number of RMIDs available
   * @mon_scale:                cqm counter * mon_scale = occupancy in bytes
- * @fflags:            flags to choose base and info files
   */
-struct rdt_resource {
-       int                     rid;
-       bool                    alloc_enabled;
-       bool                    mon_enabled;
-       bool                    alloc_capable;
-       bool                    mon_capable;
-       char                    *name;
+struct rdt_hw_resource {
+       struct rdt_resource     resctrl;
+

Please use tabs and spaces similar to the existing format.

        int                     num_closid;
-       int                     cache_level;
-       u32                     default_ctrl;
+

Please remove these empty lines.

        unsigned int            msr_base;
        void (*msr_update)      (struct rdt_domain *d, struct msr_param *m,
                                 struct rdt_resource *r);
-       int                     data_width;
-       struct list_head        domains;
-       struct rdt_cache        cache;
-       struct rdt_membw        membw;
-       const char              *format_str;
-       int (*parse_ctrlval)(struct rdt_parse_data *data,
-                            struct rdt_resource *r,
-                            struct rdt_domain *d);
-       struct list_head        evt_list;
-       int                     num_rmid;
        unsigned int            mon_scale;
        unsigned int            mbm_width;
-       unsigned long           fflags;
  };
+static inline struct rdt_hw_resource *resctrl_to_arch_res(struct rdt_resource *r)
+{
+       return container_of(r, struct rdt_hw_resource, resctrl);
+}
+
  int parse_cbm(struct rdt_parse_data *data, struct rdt_resource *r,
              struct rdt_domain *d);
  int parse_bw(struct rdt_parse_data *data, struct rdt_resource *r,

...



diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
index 9b05af9b3e28..b2c2b7386d28 100644
--- a/include/linux/resctrl.h
+++ b/include/linux/resctrl.h
@@ -2,6 +2,8 @@
  #ifndef _RESCTRL_H
  #define _RESCTRL_H
+#include <linux/kernel.h>
+#include <linux/list.h>
  #include <linux/pid.h>
#ifdef CONFIG_PROC_CPU_RESCTRL
@@ -13,4 +15,119 @@ int proc_resctrl_show(struct seq_file *m,
#endif +struct rdt_domain;
+
+/**
+ * struct resctrl_cache - Cache allocation related data
+ * @cbm_len:           Length of the cache bit mask
+ * @min_cbm_bits:      Minimum number of consecutive bits to be set
+ * @cbm_idx_mult:      Multiplier of CBM index
+ * @cbm_idx_offset:    Offset of CBM index. CBM index is computed by:
+ *                     closid * cbm_idx_multi + cbm_idx_offset
+ *                     in a cache bit mask
+ * @shareable_bits:    Bitmask of shareable resource with other
+ *                     executing entities
+ * @arch_has_sparse_bitmaps:   True if a bitmap like f00f is valid.
+ * @arch_has_empty_bitmaps:    True if the '0' bitmap is valid.
+ */
+struct resctrl_cache {
+       u32             cbm_len;
+       u32             min_cbm_bits;
+       unsigned int    cbm_idx_mult;   // TODO remove this
+       unsigned int    cbm_idx_offset; // TODO remove this
+       u32             shareable_bits;
+       bool            arch_has_sparse_bitmaps;
+       bool            arch_has_empty_bitmaps;
+};
+
+/**
+ * enum membw_throttle_mode - System's memory bandwidth throttling mode
+ * @THREAD_THROTTLE_UNDEFINED: Not relevant to the system
+ * @THREAD_THROTTLE_MAX:       Memory bandwidth is throttled at the core
+ *                             always using smallest bandwidth percentage
+ *                             assigned to threads, aka "max throttling"
+ * @THREAD_THROTTLE_PER_THREAD:        Memory bandwidth is throttled at the 
thread
+ */
+enum membw_throttle_mode {
+       THREAD_THROTTLE_UNDEFINED = 0,
+       THREAD_THROTTLE_MAX,
+       THREAD_THROTTLE_PER_THREAD,
+};
+
+/**
+ * struct resctrl_membw - Memory bandwidth allocation related data
+ * @min_bw:            Minimum memory bandwidth percentage user can request
+ * @bw_gran:           Granularity at which the memory bandwidth is allocated
+ * @delay_linear:      True if memory B/W delay is in linear scale
+ * @arch_needs_linear: True if we can't configure non-linear resources
+ * @throttle_mode:     Bandwidth throttling mode when threads request
+ *                     different memory bandwidths
+ * @mba_sc:            True if MBA software controller(mba_sc) is enabled
+ * @mb_map:            Mapping of memory B/W percentage to memory B/W delay
+ */
+struct resctrl_membw {
+       u32                             min_bw;
+       u32                             bw_gran;
+       u32                             delay_linear;
+       bool                            arch_needs_linear;
+       enum membw_throttle_mode        throttle_mode;
+       bool                            mba_sc;
+       u32                             *mb_map;
+};
+
+struct rdt_parse_data;
+
+/**

Missing a kernel-doc description here.

+ * @rid:               The index of the resource
+ * @alloc_enabled:     Is allocation enabled on this machine
+ * @mon_enabled:       Is monitoring enabled for this feature
+ * @alloc_capable:     Is allocation available on this machine
+ * @mon_capable:       Is monitor feature available on this machine
+ *
+ * @num_rmid:          Number of RMIDs available.
+ *
+ * @cache_level:       Which cache level defines scope of this resource
+ *
+ * @cache:             If the component has cache controls, their properties.
+ * @membw:             If the component has bandwidth controls, their 
properties.
+ *
+ * @domains:           All domains for this resource
+ *
+ * @name:              Name to use in "schemata" file.
+ * @data_width:                Character width of data when displaying.
+ * @default_ctrl:      Specifies default cache cbm or memory B/W percent.
+ * @format_str:                Per resource format string to show domain value
+ * @parse_ctrlval:     Per resource function pointer to parse control values
+ *
+ * @evt_list:          List of monitoring events
+ * @fflags:            flags to choose base and info files

Please remove the empty lines in the above. It hints at some grouping that is unclear.

+ */
+struct rdt_resource {
+       int                     rid;
+       bool                    alloc_enabled;
+       bool                    mon_enabled;
+       bool                    alloc_capable;
+       bool                    mon_capable;
+
+       int                     num_rmid;
+
+       int                     cache_level;
+
+       struct resctrl_cache    cache;
+       struct resctrl_membw    membw;
+
+       struct list_head        domains;
+

Please remove empty lines.

+       char                    *name;
+       int                     data_width;
+       u32                     default_ctrl;
+       const char              *format_str;
+       int                     (*parse_ctrlval)(struct rdt_parse_data *data,
+                                                struct rdt_resource *r,
+                                                struct rdt_domain *d);
+       struct list_head        evt_list;
+       unsigned long           fflags;
+
+};
+
  #endif /* _RESCTRL_H */


Reinette

Reply via email to