diff options
-rw-r--r-- | arch/x86/kernel/cpu/resctrl/core.c | 65 |
1 files changed, 61 insertions, 4 deletions
diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c index c6b953fe7fdf..4c0b1265ffd4 100644 --- a/arch/x86/kernel/cpu/resctrl/core.c +++ b/arch/x86/kernel/cpu/resctrl/core.c @@ -509,6 +509,57 @@ void setup_default_ctrlval(struct rdt_resource *r, u32 *dc, u32 *dm) } } +static u32 *alloc_ctrlval_array(struct rdt_resource *r, struct rdt_domain *d, + bool mba_sc) +{ + /* these are for the underlying hardware, they may not match r/d */ + struct rdt_domain *underlying_domain; + struct rdt_hw_resource *hw_res; + struct rdt_hw_domain *hw_dom; + bool remapped; + + switch (r->rid) { + case RDT_RESOURCE_L3DATA: + case RDT_RESOURCE_L3CODE: + hw_res = &rdt_resources_all[RDT_RESOURCE_L3]; + remapped = true; + break; + case RDT_RESOURCE_L2DATA: + case RDT_RESOURCE_L2CODE: + hw_res = &rdt_resources_all[RDT_RESOURCE_L2]; + remapped = true; + break; + default: + hw_res = resctrl_to_arch_res(r); + remapped = false; + } + + /* + * If we changed the resource, we need to search for the underlying + * domain. Doing this for all resources would make it tricky to add the + * first resource, as domains aren't added to a resource list until + * after the ctrlval arrays have been allocated. + */ + if (remapped) + underlying_domain = rdt_find_domain(&hw_res->r_resctrl, d->id, + NULL); + else + underlying_domain = d; + hw_dom = resctrl_to_arch_dom(underlying_domain); + + if (mba_sc) { + if (hw_dom->mbps_val) + return hw_dom->mbps_val; + return kmalloc_array(hw_res->num_closid, + sizeof(*hw_dom->mbps_val), GFP_KERNEL); + } else { + if (hw_dom->ctrl_val) + return hw_dom->ctrl_val; + return kmalloc_array(hw_res->num_closid, + sizeof(*hw_dom->ctrl_val), GFP_KERNEL); + } +} + static int domain_setup_ctrlval(struct rdt_resource *r, struct rdt_domain *d) { struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r); @@ -516,11 +567,11 @@ static int domain_setup_ctrlval(struct rdt_resource *r, struct rdt_domain *d) struct msr_param m; u32 *dc, *dm; - dc = kmalloc_array(hw_res->num_closid, sizeof(*hw_dom->ctrl_val), GFP_KERNEL); + dc = alloc_ctrlval_array(r, d, false); if (!dc) return -ENOMEM; - dm = kmalloc_array(hw_res->num_closid, sizeof(*hw_dom->mbps_val), GFP_KERNEL); + dm = alloc_ctrlval_array(r, d, true); if (!dm) { kfree(dc); return -ENOMEM; @@ -679,8 +730,14 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r) if (d->plr) d->plr->d = NULL; - kfree(hw_dom->ctrl_val); - kfree(hw_dom->mbps_val); + /* temporary: these four don't have a unique ctrlval array */ + if (r->rid != RDT_RESOURCE_L3CODE && + r->rid != RDT_RESOURCE_L3DATA && + r->rid != RDT_RESOURCE_L2CODE && + r->rid != RDT_RESOURCE_L2DATA) { + kfree(hw_dom->ctrl_val); + kfree(hw_dom->mbps_val); + } bitmap_free(d->rmid_busy_llc); kfree(d->mbm_total); kfree(d->mbm_local); |